refactor(sdk-py): wrap relaycast-sdk in hosted communicate transport

Merged
WI
4mo ago
+479-321

Summary

Refactors the Python SDK's hosted communicate transport (agent_relay.communicate.transport.RelayTransport) to wrap the published relaycast-sdk (PyPI relaycast-sdk, module relay_sdk) instead of hand-rolling aiohttp HTTP/WS. relay_sdk now owns the wire protocol (envelope unwrap, 5xx retry, auth errors, the WebSocket lifecycle).

Mapping

Operationrelay_sdk call
register_agentAsyncRelay(...).agents.register(name, type="agent") (reads .id/.token)
unregisterrelay._client.delete("/v1/agents/{name}") escape hatch (no agents.delete() exists)
post to channelAsyncAgentClient.send(channel, text)
replyAsyncAgentClient.reply(id, text)
dmAsyncAgentClient.dm(to, text)
check_inboxraw agent.client.get("/v1/inbox") (typed InboxResponse drops messages)
list_agentsAsyncRelay(...).agents.list()
WebSocketrelay_sdk.WsClient with on(event, handler)

What mapped cleanly vs needed workarounds

Clean: register, list, post, reply, dm, error translation (RelayError → RelayAuthError/RelayConnectionError), 5xx retry, 401 handling, base-URL pass-through.

Workarounds:

  • unregister — relay_sdk has no agents.delete(); used the http-client escape hatch. The cleanup path also swallows the empty-body decode error relay_sdk raises on 204 No Content.
  • check_inbox — AgentClient.inbox() returns the typed InboxResponse (unread metadata only) and discards the deliverable messages array; read the raw /v1/inbox payload through the agent http client (still envelope-unwrapped/retried/auth-checked) to preserve behavior.
  • WebSocket pong — WsClient has no pong-on-server-ping primitive; kept a minimal local workaround (on("ping", ...) → _send_json({"type":"pong"})).
  • WebSocket open gating — WsClient.connect() blocks for the socket lifetime, so it runs in a background task; connect() waits on the "open" event so the socket is live on return.

Constraints honored

  • Default base URL https://api.relaycast.dev preserved and passed explicitly into the relay_sdk clients.
  • RelayConfig / public types and AgentRelayClient broker behavior untouched.
  • RelayTransport public method signatures and agent_id/token attributes kept stable.
  • relaycast-sdk added to the communicate (and dev) extras; aiohttp retained for the A2A modules.

Tests

relaycast-sdk was installed and inspected to verify the surface. The in-process mock relay server was updated to return SDK-contract-compliant payloads, and the retry/reconnect transport tests were adapted to relay_sdk's behavior (retry = initial + 3; reconnect owned by WsClient).

python -m pytest tests/communicate → 211 passed, 2 skipped.

🤖 Generated with Claude Code