Files
agents/sdk/python/tests/test_async_execution.py
zeekayandHanzo Dev e0e84f7808 The Python SDK's tests run, it calls /v1, and it can keep memory in Base
- A rebrand wrote "Hanzo Agents" into identifiers, so the conftest did not
  parse and no test ran.
- The client built {url}/api/v1; the control plane serves /v1. Notes append
  /ui to the base instead of rewriting its first /v1.
- BaseMemory stands where MemoryClient stands; pass it to Agent as `store`. It
  binds to the running execution, so scope ids resolve as the control plane
  resolves them, and a read without a scope walks workflow, session, actor and
  global.
- The web3 extension declares eth-account as an extra, and stops exporting two
  modules that import packages this SDK does not have.
- A heartbeat test waits for the state it asserts instead of sleeping.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-11 04:10:34 -07:00

90 lines
2.5 KiB
Python

import asyncio
import httpx
import pytest
from hanzo_agents.agent import Agent
from hanzo_agents.client import HanzoAgentsClient
@pytest.mark.asyncio
async def test_reasoner_async_mode_sends_status(monkeypatch):
agent = Agent(
node_id="test-agent", hanzo_agents_server="http://control", auto_register=False
)
@agent.reasoner()
async def echo(value: int) -> dict:
await asyncio.sleep(0)
return {"value": value}
recorded = []
class DummyResponse:
def __init__(self, status_code: int = 200):
self.status_code = status_code
def json(self):
return {}
async def fake_request(self, method, url, **kwargs):
recorded.append({"method": method, "url": url, "json": kwargs.get("json")})
return DummyResponse(200)
monkeypatch.setattr(HanzoAgentsClient, "_async_request", fake_request)
async with httpx.AsyncClient(
transport=httpx.ASGITransport(app=agent), base_url="http://agent"
) as client:
response = await client.post(
"/reasoners/echo",
json={"value": 7},
headers={"X-Execution-ID": "exec-123"},
)
assert response.status_code == 202
await asyncio.sleep(0.1)
status_calls = [entry for entry in recorded if "/executions/" in entry["url"]]
assert status_calls, "expected async status callback"
payload = status_calls[-1]["json"]
assert payload["status"] == "succeeded"
assert payload["result"]["value"] == 7
@pytest.mark.asyncio
async def test_post_execution_status_retries(monkeypatch):
agent = Agent(
node_id="test-agent", hanzo_agents_server="http://control", auto_register=False
)
attempts = {"count": 0}
class DummyResponse:
def __init__(self, status_code: int):
self.status_code = status_code
async def fake_request(self, method, url, **kwargs):
attempts["count"] += 1
if attempts["count"] < 3:
raise RuntimeError("transient error")
return DummyResponse(200)
monkeypatch.setattr(HanzoAgentsClient, "_async_request", fake_request)
sleeps = []
async def fake_sleep(delay):
sleeps.append(delay)
monkeypatch.setattr(asyncio, "sleep", fake_sleep)
await agent._post_execution_status(
"http://control/v1/executions/exec-1/status",
{"status": "running"},
"exec-1",
max_retries=5,
)
assert attempts["count"] == 3
assert sleeps == [1, 2]