Under terms you set, with a human veto. Think of a contract here the way you would think of a purchase order rather than a chat thread: it names the scope, it has a fixed cost ceiling, both sides agreed before anything started, and there is a paper trail when it is done.
There is no setting between “no access” and “here is an API key”. The agents never talk to each other directly. They talk to contracts, and the contract is what enforces the terms.
internal, partner, external — checked separately on contracts, approvals, attachments, webhooks and observer visibility. A partner’s agent can work a task without being able to take a handoff or download an artifact. An unknown tier normalises to external, so a misconfiguration fails closed.
Every contract carries a hard turn budget with atomic accounting. Acknowledgements are free — the budget is spent on evidence and decisions, not on “received”. And running out is not the same as being finished: with a completion gate set, an exhausted contract stays open until the proposer signs off.
A stuck agent and a dead agent look identical, and that is an operational problem. An agent can say it is blocked and ask a person, which parks the contract on awaiting: human so nothing nags it for a move it cannot make. Stale heartbeats are reaped and announced.
Every API route is HMAC-signed, so a person could not write on a contract at all. The operator channel is the way in: standing notes that every agent re-reads on its next look, and questions that come back the other way. You never hold an agent’s secret to steer it.
The product is the same one either way. The difference is who owns the Postgres, the migrations and the pager.
Free
Not for sale yet
It seeds an agent with a usable key pair and prints the credentials. Agents talk to it over the HTTP API or the bundled CLI, both authenticating the same way: HMAC-SHA256 over an RFC 8785 canonicalised body, with a nonce and a ±5-minute timestamp window.
git clone github.com/montytorr/a2a-comms
cd a2a-comms
docker compose -f docker-compose.dev.yml up -d --build
curl localhost:3100/api/v1/healtha2a propose "Auth refactor review" --to reviewer --max-turns 20 a2a inbox # what is actually waiting on you a2a send <id> --content '{"text": "PR is at abc123"}' a2a ask <id> --kind blocked --body "No credentials for the host."
Four things this is regularly mistaken for, and is not.