SDKs and ready-to-run agent plugins for the Synadia Agent Protocol for NATS.
The Synadia Agent Protocol for NATS lets any AI agent — Claude Code, OpenClaw, PI, Hermes, or your own — register itself as a NATS micro service named agents, and be discovered, prompted, and streamed from by any caller speaking the same wire format. This repo is the home of the official caller and host SDKs (TypeScript and Python — see SDKs below), plus pre-built channel plugins that put popular AI harnesses on NATS without writing code.
| You want to… | Go to | Install |
|---|---|---|
| Put an existing AI agent on NATS (Claude Code, OpenClaw, PI, Hermes, DSPy ReAct) | agents/ — pick the agent |
per-agent README |
| Build a caller that discovers and prompts agents | client-sdk/typescript/ · client-sdk/python/ |
npm i @synadia-ai/agents · pip install synadia-ai-agents |
| Host a brand-new agent built from scratch | agent-sdk/typescript/ · agent-sdk/python/ |
npm i @synadia-ai/agent-service · pip install synadia-ai-agent-service |
Pre-built channel plugins that put existing AI harnesses on NATS. Each registers as an agents micro service and serves the protocol's prompt, status, and hb endpoints out of the box.
| Agent | Token | Package |
|---|---|---|
| Claude Code | cc |
claude-channel-nats |
| OpenClaw | oc |
@synadia-ai/nats-channel |
| PI Agent | pi |
@synadia-ai/nats-pi-channel |
| Hermes | hermes |
upstream fork — see agents/hermes/ (work in progress) |
| DeerFlow | df |
synadia-ai-nats-deerflow-channel — external Python wrapper for a running DeerFlow Gateway |
| open-agent | open-agent |
@synadia-ai/open-agent (private) — inbound bridge for vercel-labs/open-agents; LocalSandbox + companion examples/open-agent-vercel/ |
| DSPy ReAct | dspy |
standalone example (not published) — built from scratch with ax-llm ReAct |
Subjects follow a verb-first pattern: agents.{verb}.{token}.{owner}.{session} where verb is prompt, hb, or status.
Two halves per language. The caller SDK (client-sdk/) discovers and prompts agents; the host SDK (agent-sdk/) lets you register and serve one. Caller-only consumers install just the caller package; agent-host authors install both halves of their language's pair.
| Side | Folder | TypeScript | Python |
|---|---|---|---|
| Caller | client-sdk/ |
@synadia-ai/agents |
synadia-ai-agents |
| Host | agent-sdk/ |
@synadia-ai/agent-service |
synadia-ai-agent-service |
Both languages stay in lockstep on the wire format, validated by a cross-SDK interop test (tests/test_interop_e2e.py) that runs the TS reference agent against the Python client.
caller (SDK) ──▶ NATS ──▶ agent host
▲ │
└─── streamed chunks ───────┘
A request is plain UTF-8 text or a JSON envelope {"prompt": "...", "attachments": [{"filename": "...", "content": "<base64>"}]}. The agent streams typed JSON chunks on the reply subject — {"type":"response","data":"..."} for content, {"type":"status","data":"ack"} as the mandatory §6.4 leading chunk (and optionally again as periodic keep-alive), {"type":"query","data":{...}} for mid-stream questions — and ends with an empty-body, no-headers terminator. Errors use the Nats-Service-Error-Code header (400 client, 500 server).
Discovery is standard NATS micro:
nats req '$SRV.INFO.agents' '' --replies=0 --timeout=2s
nats sub 'agents.hb.*.*.*'To prompt an agent directly from the CLI (no SDK), pass three flags — --replies=0 --reply-timeout=30s --timeout=60s. The full CLI cookbook (prompts, attachments, status, control-plane, gotchas) lives at docs/using-nats-cli.md.
Full spec: https://github.com/synadia-ai/synadia-agent-sdk-docs.
Both snippets use TypeScript and bring their own NatsConnection — use @nats-io/transport-node for TCP or wsconnect from @nats-io/nats-core for WebSocket.
Uses the caller SDK (client-sdk/typescript/ → @synadia-ai/agents).
import { connect } from "@nats-io/transport-node";
import { Agents } from "@synadia-ai/agents";
const nc = await connect({ servers: "nats://localhost:4222" });
const agents = new Agents({ nc });
const [agent] = await agents.discover();
for await (const msg of await agent!.prompt("hello")) {
if (msg.type === "response") process.stdout.write(msg.text);
}
await agents.close();
await nc.close();Uses the host SDK (agent-sdk/typescript/ → @synadia-ai/agent-service). Agent-host authors install both packages — caller types and helpers stay imported from @synadia-ai/agents.
import { connect } from "@nats-io/transport-node";
import { AgentService } from "@synadia-ai/agent-service";
const nc = await connect({ servers: "nats://localhost:4222" });
const service = new AgentService({
nc,
agent: "echo", // metadata.agent — canonical harness identifier
owner: "demo", // metadata.owner — operator / account namespace
name: "main", // 5th subject token — instance name
description: "Echo agent demo",
});
service.onPrompt(async (envelope, response) => {
await response.send(`echo: ${envelope.prompt}`);
});
await service.start();
console.log(`listening on ${service.subject.prompt}`);
// on shutdown:
await service.stop();
await nc.close();Try it now: agent-sdk/typescript/examples/01-echo.ts is this code packaged as a runnable script — bun agent-sdk/typescript/examples/01-echo.ts (with $NATS_CONTEXT, $NATS_URL, or localhost fallback).
For full install, error handling, and longer examples see the per-package READMEs: caller — client-sdk/typescript/ · client-sdk/python/; host — agent-sdk/typescript/ · agent-sdk/python/.
End-to-end apps built on the SDKs — controllers that spawn ephemeral agents, a browser test client, a from-scratch DSPy ReAct agent. See examples/ and its README.
Both SDKs ship a spec-compliant reference agent that implements the full §12 agent checklist (service registration, prompt endpoint, status endpoint, heartbeats, terminator semantics). When reasoning about wire shape, testing a third SDK, or validating AI/LLM-generated tooling, read these first — they are the authoritative on-the-wire counterpart to the spec.
| SDK | Reference agent | Demo scripts |
|---|---|---|
| TypeScript | ReferenceAgent — importable as @synadia-ai/agent-service/testing. Runnable: _run-reference-agent.ts. |
client-sdk/typescript/examples/ — 01-discover.ts … 05-liveness.ts. |
| Python | _reference_agent.py — runnable echo agent with conversation memory. |
client-sdk/python/examples/ — 01-discover.py … 05-liveness.py, plus 06-chat.py (interactive REPL). |
Repository layout
synadia-agents/
├── README.md ← you are here
├── README-DEV.md ← local-development build / install recipes
├── client-sdk/ ← caller-side language SDKs (discover · prompt · stream)
│ ├── typescript/ ← @synadia-ai/agents
│ └── python/ ← synadia-ai-agents
├── agent-sdk/ ← host-side language SDKs (host an agent)
│ ├── typescript/ ← @synadia-ai/agent-service
│ └── python/ ← synadia-ai-agent-service
├── agents/ ← plugins that put existing AI harnesses on NATS
│ ├── claude-code/
│ ├── openclaw/
│ ├── pi/
│ ├── hermes/
│ ├── deerflow/
│ └── open-agent/ ← inbound bridge for vercel-labs/open-agents
└── examples/ ← apps built with the SDKs (callers and agents)
├── agent-web-ui/ ← Vue 3 + Bun browser client
├── claude-code-headless/ ← spawn/stop many Claude Code sessions
├── pi-headless/ ← spawn/stop many PI sessions
├── dspy/ ← standalone agent built from scratch (ax-llm ReAct)
└── open-agent-vercel/ ← runs the open-agent bridge against @vercel/sandbox
Each subtree has its own README.md and the index READMEs (client-sdk/README.md, agent-sdk/README.md, agents/README.md, examples/README.md) describe what lives at each level. See README-DEV.md for local-dev build and install recipes.
Apache-2.0 across this monorepo — see each package's LICENSE file.