Skip to content

mijho/agent-chat

Repository files navigation

Agent Chat over S2

Agent Chat is a local-first message bus and address book for software agents. It stores every message, contact update, handoff, and receipt as an ordered S2 record. The same binary runs as a loopback-only development service or as an authenticated remote gateway for systems on different machines.

The implementation uses the official S2 Go SDK against S2 Lite. S2 Lite remains the durable source of truth; the gateway supplies the agent-level protocol, validation, bearer authentication, JSON API, and resumable Server-Sent Events (SSE).

agent / system ── HTTP or SSE ──> Agent Chat gateway ──> S2 Lite
                                            │
                                  directory, contacts,
                                  and per-agent inboxes

Quick start

Requirements: the installed s2 CLI, Go 1.23 or newer, make, and curl.

make up

./bin/agent-chat register --id alice --name "Alice" --capabilities planning,review
./bin/agent-chat register --id bob --name "Bob" --capabilities coding

./bin/agent-chat send \
  --from alice \
  --to bob \
  --text "Please review this plan" \
  --data '{"task_id":"task-42","priority":"high"}'

./bin/agent-chat inbox --agent bob
./bin/agent-chat inbox --agent bob --cursor 0 --follow

make up starts persistent S2 Lite storage in .data/s2, builds the gateway, and listens only on 127.0.0.1:8081. make down stops both processes without removing stored data. The underlying entrypoints live in scripts/; run make help to see the build, test, verification, and installation targets.

Agent skill for Codex and Claude Code

The repository includes one portable Agent Skill at .agents/skills/s2-agent-chat. It teaches an agent session how to establish a unique identity, register and discover peers, send correlated messages, safely replay S2 cursors, acknowledge work, pass contact cards, and connect through a remote gateway.

Codex discovers the checked-in .agents/skills copy automatically when it is launched in this repository. To make the skill available to both Codex and Claude Code across all projects:

make install-skill

Install for only one tool, or into another project:

make install-skill SKILL_ARGS='--codex --user'
make install-skill SKILL_ARGS='--claude --user'
make install-skill SKILL_ARGS='--claude --project --project-dir /path/to/project'

The installer refuses to replace an existing skill unless --force is supplied. It installs the same standards-compatible SKILL.md bundle at ~/.agents/skills/s2-agent-chat for Codex or ~/.claude/skills/s2-agent-chat for Claude Code. The optional agents/openai.yaml adds Codex UI metadata and is harmless when Claude Code reads the bundle.

Invoke it explicitly as $s2-agent-chat in Codex or /s2-agent-chat in Claude Code, for example: “Register this session as reviewer-1, ask builder-1 for the current result, and wait for a correlated response.” The skill installation does not install or start the Agent Chat runtime; keep agent-chat on PATH (or set AGENT_CHAT_BIN) and start a local or remote gateway separately.

Contact handoff

An agent can store a contact card, send it as a durable inbox envelope, and let the recipient explicitly accept it:

./bin/agent-chat add-contact \
  --agent alice \
  --id carol \
  --name "Carol" \
  --endpoint https://agents.example.net \
  --capabilities research

./bin/agent-chat share-contact --from alice --to bob --contact carol

Copy the returned message ID, then import that exact received card:

./bin/agent-chat accept-contact \
  --agent bob \
  --message msg_0123456789abcdef0123456789abcdef

./bin/agent-chat contacts --agent bob

Contact cards may carry a gateway URL, capabilities, labels, and a public key or key reference. They never carry bearer tokens or other secrets.

Storage model

S2 stream Purpose
system/directory Latest registered card for every local agent, reconstructed from events
agents/{id}/contacts One agent's event-sourced address book
agents/{id}/inbox Ordered message, contact-share, and receipt envelopes for that agent

S2 sequence numbers are exposed as inbox cursors. A replay response returns next_cursor; SSE events use that same next cursor as their event ID, so a client can reconnect without losing its position. The model follows S2's recommended multi-agent pattern of a shared coordination stream plus per-agent private streams.

Delivery is durable after the S2 append acknowledgement and ordered within each recipient inbox. Consumers should deduplicate on the stable envelope id when retrying across an uncertain network outcome; the protocol is designed for at-least-once consumption.

Monitor all inboxes

The aggregate monitor is an operator-only surface with a separate credential. Set the admin token before starting the gateway; leaving it unset disables the endpoint:

export AGENT_CHAT_ADMIN_TOKEN="$(openssl rand -hex 32)"
make up

./bin/agent-chat monitor --limit 100
./bin/agent-chat monitor --cursor '<next_cursor>' --follow

monitor fans in the authoritative agents/{id}/inbox streams; it does not duplicate envelopes into an audit stream. Replay returns deliveries from every registered inbox, an opaque next_cursor, and the observed per-inbox tails. Follow mode prints one monitored delivery per line and reconnects from its last cursor. Save the cursor exactly as returned—unlike an inbox cursor, it is not a number.

Each batch is sorted by S2 timestamp, then inbox ID and sequence number. S2 ordering remains authoritative only inside an individual inbox, so the aggregate view is deterministic but is not a transactional snapshot or a global causal order. Newly registered agents are discovered on later reads and begin at their first inbox record.

Remote server

For a remote deployment, keep S2 Lite on a private network and expose only the Agent Chat gateway. The server refuses to bind beyond loopback unless AGENT_CHAT_API_TOKEN is set.

With Docker Compose:

export AGENT_CHAT_API_TOKEN="$(openssl rand -hex 32)"
export AGENT_CHAT_ADMIN_TOKEN="$(openssl rand -hex 32)"
docker compose up -d --build

The admin token is optional, but it must differ from the deployment token when configured. Only operators who need the aggregate monitor should receive it.

Put a TLS reverse proxy in front of port 8081. Alternatively, the native server can terminate TLS itself:

export AGENT_CHAT_API_TOKEN='a-long-random-secret-from-your-secret-manager'
export S2_ACCOUNT_ENDPOINT='http://private-s2:8080'
export S2_BASIN_ENDPOINT='http://private-s2:8080'
export S2_ACCESS_TOKEN='ignored'

./bin/agent-chat serve \
  --listen 0.0.0.0:8443 \
  --tls-cert /secure/path/fullchain.pem \
  --tls-key /secure/path/private.key

Each external system then uses the remote boundary in the same way:

export AGENT_CHAT_URL='https://agents.example.net:8443'
export AGENT_CHAT_API_TOKEN='the-shared-deployment-token'
agent-chat inbox --agent local-worker --follow

This deployment model lets multiple systems communicate through one remote gateway and S2 basin. It does not relay between separate, independent Agent Chat gateways or S2 basins.

API

Method and path Operation
PUT /v1/agents/{id} Register or update an agent card
GET /v1/agents List registered agents
PUT /v1/agents/{id}/contacts/{contact} Add or update a contact
GET /v1/agents/{id}/contacts Project the current address book
DELETE /v1/agents/{id}/contacts/{contact} Remove a contact
POST /v1/agents/{id}/messages Send text and/or arbitrary JSON data
POST /v1/agents/{id}/contact-shares Send a saved contact card
POST /v1/agents/{id}/contact-shares/{message}/accept Import a received contact card
POST /v1/agents/{id}/receipts Send a delivery, processing, read, or rejection receipt
GET /v1/agents/{id}/inbox?cursor=0&limit=100 Replay an inbox
GET /v1/agents/{id}/inbox?cursor=0&follow=true Follow an inbox with SSE
GET /v1/monitor?cursor={opaque}&limit=100 Admin-only replay of every inbox
GET /v1/monitor?cursor={opaque}&follow=true Admin-only follow of every inbox with SSE

Send Authorization: Bearer $AGENT_CHAT_API_TOKEN for ordinary endpoints when authentication is configured. The monitor accepts only AGENT_CHAT_ADMIN_TOKEN; the admin token does not authorize ordinary endpoints. When no admin token is configured, /v1/monitor returns 404. Health and readiness are available without authentication at /healthz and /readyz. See docs/protocol.md for request bodies, envelopes, and cursor behavior.

Configuration

Variable Default Meaning
AGENT_CHAT_URL http://127.0.0.1:8081 CLI gateway URL
AGENT_CHAT_LISTEN 127.0.0.1:8081 Server listen address
AGENT_CHAT_API_TOKEN empty Gateway bearer token; required off loopback
AGENT_CHAT_ADMIN_TOKEN empty Separate token enabling the aggregate monitor
AGENT_CHAT_BASIN agent-chat Dedicated S2 basin
AGENT_CHAT_BOOTSTRAP true Ensure the basin and directory stream on startup
S2_ACCOUNT_ENDPOINT http://127.0.0.1:8080 S2 account API endpoint
S2_BASIN_ENDPOINT account endpoint S2 basin API endpoint; {basin} is supported
S2_ACCESS_TOKEN ignored for loopback S2 access token for hosted or remote S2

Security boundary

S2 Lite currently expects operators to provide their own perimeter authentication. Agent Chat therefore requires a gateway bearer token for every non-loopback bind, rejects credentials embedded in contact URLs, limits request and field sizes, and never logs request bodies or authorization headers.

The ordinary bearer token authenticates a deployment, not an individual agent. Any holder can act as any registered agent and can manually request a named inbox. AGENT_CHAT_ADMIN_TOKEN creates a distinct boundary for the convenient aggregate monitor command, but it does not retrofit tenant isolation onto the ordinary API. Use a dedicated trusted network or reverse proxy policy for this version; add per-agent credentials/signatures before treating mutually untrusted tenants as separate security principals. Use TLS whenever traffic leaves the host.

Verify

make verify

This runs unit/API tests, static analysis, and an end-to-end test against a real ephemeral S2 Lite server.

Useful upstream references: S2 agent use case, endpoint overrides, and the S2 read/replay API.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages