Sentō is the first agent framework with first-class agent-to-agent (A2A) messaging built in. Two agents pair once, exchange a shared secret, and from then on can send each other signed messages over HTTP.
No central server. No pub/sub broker. No hosted directory. Just two Linux processes with HTTP endpoints and a shared HMAC secret.
Why have this at all
Real use cases:
- Mira (marketing) needs data from Kai (personal): Mira messages Kai, "what were the tasks Gabriel mentioned this week?" Kai replies with relevant memory.
- Blair (household) alerts Porter (mail processing): Blair sees a school message about a new form; Porter handles scanning and filing it.
- Load-shedding: one agent passes a sub-task to another specialized agent.
Without A2A, every coordination requires you as the bridge. With it, agents can cooperate directly.
How pairing works
# On agent A
sento pair
→ agent prints a code: SENTO-4F2K
→ agent says "have the other agent's owner run `sento pair SENTO-4F2K`"
# On agent B
sento pair SENTO-4F2K
→ A's owner sees in chat: "Agent B wants to pair. Approve? (yes/no)"
→ A's owner types: yes
→ both agents exchange HMAC secrets
→ pairing stored in ~/.sento-config.json on both sides
Now A and B can message each other via HTTP.
The transport
Each agent's Guardian runs an HTTP listener on an auto-selected port (9876, 9877, 9878…). Messages are POST requests with:
X-Sento-Signature: HMAC-SHA256 of the body using the shared secretX-Sento-Timestamp: RFC3339 timestamp, refused if older than 5 minutes- Rate limited: 10 requests / minute per pair, then 429
Delivered messages are piped into the target agent's tmux session as if they were incoming chat messages tagged ← agent <name>.
The security model
- Mutual consent: pairing requires the owner of the receiving agent to approve in chat. The agent cannot auto-accept.
- HMAC signatures: forged messages without the shared secret are rejected.
- Timestamp window: replay attacks fail after 5 minutes.
- Rate limits: a misbehaving or compromised agent can't flood another.
- Listen-only for pairings you approved: unknown senders get dropped at the HTTP layer before Claude Code ever sees them.
Listing and unpairing
sento agents # list paired agents + their ports + last-contacted time
sento agents remove kai # revoke a pairing; rotates our end of the secret
What messages can they send?
Anything text. Common patterns:
- Questions / answers ("what's the latest HN top story?")
- Structured task handoffs ("please scan this invoice:
- Status pings ("are you around?")
The target agent receives the text as a normal inbound message and responds the way it would respond to a human owner, except the reply goes back through the A2A channel instead of Discord/Telegram/Slack.
Where to read the code
src/templates/guardian.js— HTTP server implementationsrc/commands/pair.js— pairing flowsrc/commands/agents.js— listing + removal