Skip to main content

Python client SDK for the NATS Agent Protocol — discover and prompt spec-compliant agents over NATS

Project description

synadia-ai-agents

Python client SDK for the NATS Agent Protocol. Discover protocol-compliant agents over NATS and prompt them with streamed typed responses.

Hosting an agent (Hermes / claude-code / openclaw / pi)? That side of the protocol now ships separately as synadia-ai-agent-service (import synadia_ai.agent_service). It depends on this package for the shared wire primitives — install both when authoring an agent harness.

Cross-SDK parity with the TypeScript SDK is tracked in tests/test_interop_e2e.py. Both SDKs declare protocol_version = "0.3" in service metadata, so the test spawns the TS reference agent via bun and rounds-trips a prompt through it. The test pytest.skips cleanly when bun or the sibling ../typescript/ checkout is missing — running the suite without TS interop is fine for day-to-day work.

Calling agents?Quickstart - call an agent. Hosting an agent? → see synadia-ai-agent-service.

Installation

From this checkout (no published wheel yet):

uv pip install -e .

Once released on PyPI:

pip install synadia-ai-agents

You also need a reachable nats-server. Pick whichever fits:

brew install nats-server                          # macOS
# Linux / anywhere with Docker:
docker run --rm -p 4222:4222 nats:2.12-alpine
# Then:
nats-server -a 127.0.0.1 -p 4222

See the nats.io install docs for more options. Synadia Cloud or any hosted NATS works too - see Connecting to NATS in production below.

Quickstart - call an agent

The SDK doesn't open NATS connections — you build a nats.aio.client.Client and hand it to Agents. That mirrors what Svcm(nc), jetstream(nc), Kvm(nc) do, and lets one connection serve JetStream, KV, services, and agents at once.

import asyncio
import nats
from synadia_ai.agents import Agents, ResponseChunk, StatusChunk

async def main() -> None:
    nc = await nats.connect(servers="nats://127.0.0.1:4222")
    agents = Agents(nc=nc)
    try:
        found = await agents.discover()           # list[Agent], stall by default
        for a in found:
            print(f"{a.agent}/{a.owner}/{a.name} @ {a.prompt_subject}")

        # Each Agent is directly callable — no bind step.
        async for msg in found[0].prompt("hello"):
            if isinstance(msg, ResponseChunk):
                print(msg.text, end="")
            elif isinstance(msg, StatusChunk) and msg.status == "done":
                print()
    finally:
        await agents.close()                      # SDK state only
        await nc.close()                          # caller owns this

asyncio.run(main())

API matrix

Symbol Lives in Purpose
Agents agents.py Caller-side entry point. Construct with nc=; owns the heartbeat wildcard sub.
Agent agent.py Live handle from Agents.discover(). .prompt() is the one method that does I/O.
AgentInfo discovery.py Pure-data record (parsed $SRV.INFO per §4.3). What build_agent_info() returns.
Liveness heartbeat.py Frozen snapshot from Agents.liveness(instance_id).
load_context_options context.py Resolve a nats CLI context into kwargs for nats.connect(...).
AgentService synadia-ai-agent-service Server-side; ships in a separate distribution. Import from synadia_ai.agent_service.

Mid-stream queries

Agent handlers can pause their response stream to ask the caller a question (permission prompt, clarification, menu selection):

async for msg in agent.prompt("do the thing"):
    if isinstance(msg, Query):
        await msg.reply("yes")
    else:
        print(msg)     # ResponseChunk / StatusChunk

Server-side, the handler asks via stream.ask(...) — see synadia-ai-agent-service for the host-side API.

Try the examples

Six runnable client-side demos live under examples/. They talk to the reference agent which now ships with synadia-ai-agent-service at agent-sdk/python/examples/_reference_agent.py. The ritual to see the SDKs work end-to-end:

# terminal 1 — start the reference agent (from the agent-sdk dist)
uv run --directory ../../agent-sdk/python python examples/_reference_agent.py \
  --url nats://127.0.0.1:4222

# terminal 2 — discover and prompt (from this dist)
uv run python examples/01-discover.py --url nats://127.0.0.1:4222
uv run python examples/02-prompt-text.py --url nats://127.0.0.1:4222 "hello"

See examples/README.md for the full tour.

Connecting to NATS in production

For Synadia Cloud or any self-hosted NATS that needs credentials, JWTs, or a non-default URL, use a nats CLI context and load its kwargs into nats.connect:

import nats
from synadia_ai.agents import Agents, load_context_options

nc = await nats.connect(**load_context_options("prod"))
agents = Agents(nc=nc)

load_context_options(...) reads ~/.config/nats/context/<name>.json — URL, creds file, token, user/password, inbox prefix are all honored. See CLAUDE.md for the full field-by-field table (including which NATS-context fields are not yet supported and fail fast rather than silently).

Hosting an agent

The agent-host surface (AgentService, PromptStream, PromptHandler, the heartbeat publisher) ships separately as synadia-ai-agent-service — install that package alongside this one when authoring an agent harness, and import the host classes from synadia_ai.agent_service. The shared wire types (Envelope, Attachment, error classes, HeartbeatPayload, AgentSubject, the discovery constants) stay in this package and continue to import from synadia_ai.agents.

Probe a running agent with the nats CLI (subjects are verb-first per protocol v0.3):

nats micro list                                          # see "agents"
nats req  agents.prompt.demo.alice.worker-1 "hello"      # prompt it
nats req  agents.status.demo.alice.worker-1 ""           # heartbeat-shaped status reply
nats sub  "agents.hb.demo.alice.worker-1"                # watch heartbeats

Documentation

Development

uv sync                              # install
uv run ruff check . && uv run ruff format --check . && uv run mypy src tests examples && uv run pytest

Integration tests spawn a real nats-server per session and record wire evidence under tests/_evidence/<test-nodeid>/. Cross-SDK interop tests (tests/test_interop_e2e.py) additionally spawn the TypeScript reference agent via bun; they skip cleanly if bun or the sibling ../typescript/ checkout isn't present.

License

Apache-2.0. See LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

synadia_ai_agents-0.6.0.tar.gz (138.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

synadia_ai_agents-0.6.0-py3-none-any.whl (52.1 kB view details)

Uploaded Python 3

File details

Details for the file synadia_ai_agents-0.6.0.tar.gz.

File metadata

  • Download URL: synadia_ai_agents-0.6.0.tar.gz
  • Upload date:
  • Size: 138.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for synadia_ai_agents-0.6.0.tar.gz
Algorithm Hash digest
SHA256 fa83e40162c1300c755f48edec3aac153dedb777fb23f8ded4313e7e6b1eb0fb
MD5 327749a77eeb3501aecb223c03b1acae
BLAKE2b-256 8f4bb6c3faf5f11c1251de927cbecfd7f53a26cfe42f046dd76d4f5bcb6c3141

See more details on using hashes here.

Provenance

The following attestation bundles were made for synadia_ai_agents-0.6.0.tar.gz:

Publisher: release-python.yml on synadia-ai/synadia-agents

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file synadia_ai_agents-0.6.0-py3-none-any.whl.

File metadata

File hashes

Hashes for synadia_ai_agents-0.6.0-py3-none-any.whl
Algorithm Hash digest
SHA256 3ab8a7f180af97926e4934240f95fbed67b7ae63b8eefccf2b6b860111d971a2
MD5 7b2b5eac0ef8f7c63aabe5f3a86adfac
BLAKE2b-256 b2ea81c29e3564f01e942b094c8fb63d8347cf1278e1b11641b203973ae97f0c

See more details on using hashes here.

Provenance

The following attestation bundles were made for synadia_ai_agents-0.6.0-py3-none-any.whl:

Publisher: release-python.yml on synadia-ai/synadia-agents

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page