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 secret
  • X-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 implementation
  • src/commands/pair.js — pairing flow
  • src/commands/agents.js — listing + removal