Historical Note: This post describes early agentchute mechanics (such as push-based wakes, watchdogs, or recipient-side service polling) that were deleted in the v0.8.0 pull-only redesign. For the current stable specification, see the AGENTCHUTE.md Protocol Specification.

May 20, 2026 · agentchute team

v0.1.1: the agents shipped it themselves

Three AI agents — Claude Code, codex CLI, Gemini CLI — shipped agentchute v0.1.1 using agentchute v0.1.0. The human stayed out of the message path.

Last week's post said the developer is the message bus between their agents. v0.1.1 is the answer. It also happens to be the first agentchute release in which the developer wasn't the message bus during the build.

The build team was three agents in three tmux panes. Claude Code wrote the Go. codex stood by as the rolling reviewer and surfaced several release-blocking edge cases. Gemini drove docs and wrapper edges — the §6.4.3 protocol additions and the wrapper enrollment blocks — while the README rewrite became a three-agent consensus round. They coordinated through agentchute inboxes. Alex sat in a fourth pane and steered when a decision was actually his to make — merge approval, the question of what to do about self-send loops, "ok, go". He didn't carry a single message between agents.

Three AI agents — Claude Code, codex, Gemini — at separate terminals, with rust-orange arrows flowing directly between them. The human's chair is empty.
The human still steers. The agents carry their own messages.

That is what v0.1.1 was designed to enable, and the proof is that v0.1.1 got built that way.

What's actually in the release

A few lifecycle commands around one durable ledger. send --ask creates the obligation; send --reply-to clears it; the ledger remembers in between.

agentchute boot is the session-start ritual. Every wrapper now has a SessionStart hook that runs boot automatically: it registers the agent, peeks the inbox, and reports any pending reply obligations as developer context. The agent walks into the conversation already knowing whether work is waiting.

agentchute gate is the lifecycle gate. The Stop hook (or Gemini's BeforeAgent) runs gate --before finish. If the agent has unread mail, malformed inbox files, or unresolved reply obligations, the gate refuses to let it stop. The agent gets one more turn, and developer context tells it exactly what's outstanding.

agentchute pending is the read-only peek. It reports unread inbox state and pending-reply obligations without moving a single file — the hook-safe sibling of check. It's what runs under UserPromptSubmit / BeforeAgent to inject per-turn context without consuming mail.

agentchute defer is the escape valve. When an obligation can't be discharged in the current turn — the work is real, the answer needs research, the recipient is offline — the agent calls defer --message <id> --reason "...". The ledger entry transitions to deferred, the gate stops blocking on it, and the original sender gets an automatic acknowledgment. Without defer, the gate is a trap. With it, the gate is just a guardrail.

The durable state is the pending-reply ledger. Every recipient keeps a small JSON file at state/<agent>/pending-replies.json. When check archives a message marked reply_required: true, a pending entry lands. When the recipient calls send --reply-to <msg-id>, the entry transitions to replied. When the recipient calls defer, it transitions to deferred. The gate reads the ledger. The ledger is what makes obligations durable across turns — without it, a question gets read, the agent stops, and the obligation is lost forever.

A mailbox solves delivery. A ledger solves obligation.

The release loop

We didn't build v0.1.1 in a single session. We used the pool. Claude Code took the implementation queue. codex stood by as rolling reviewer. Gemini watched the wrapper and docs edges. Every review request was a direct inbox message.

┌────────────────┐      ┌────────────────┐      ┌────────────────┐
│ CLAUDE-CODE    │      │ CODEX          │      │ GEMINI-CLI     │
└───────┬────────┘      └───────▲────────┘      └───────▲────────┘
        │ 1. land commit, request review        │
        ├──────────────────────▶│               │
        ├──────────────────────────────────────▶│
        │                       │ 2. findings   │ 2. findings
        │◀──────────────────────┤               │
        │◀──────────────────────────────────────┤
        │ 3. patch + reply-to + sign-off ask    │
        ├──────────────────────▶│               │
        └──────────────────────────────────────▶│

That loop found real bugs.

Early ledger code treated duplicate message_id values too casually. A second delivery with the same id but a different filename could have disappeared into an idempotent no-op. The review turned that into a typed collision error, ErrLedgerEntryCollision. The protocol says message_id is for threading, not delivery uniqueness. The implementation had to honor that distinction.

Another review caught the wrong-recipient reply case. If an agent owed codex a reply but sent --reply-to that message while addressing Gemini, the ledger must not clear the codex obligation. The fix checks both sides of the ledger row: the reply goes to the original sender, and the row belongs to the replying agent.

The most important bug was simpler. send --ask wrote the right wire field, but check initially archived the message without recording it in the ledger. The mail was gone. The obligation was gone with it. That would have made the new gate look clean while the protocol still owed a reply. The review reproduced it end-to-end and forced the missing integration: archive a reply_required message, then record the pending-reply row immediately.

None of those were caught by the test suite first. They were caught by a peer agent reading the diff. The same as in human teams.

The hooks proved it under pressure

After the code path was green, Alex ran a real bake in a fresh folder with the actual Claude wrapper. This was the kind of test unit tests don't replace: install the hook template, start the wrapper, ask it what it sees, and watch whether the context actually lands in the model.

The SessionStart hook worked. Claude quoted the injected "Inbox clear; no pending reply obligations" text back from its developer context. The Stop hook worked too. gate --before finish blocked the turn when mail remained, and Claude walked the hand-protocol §5 path (because agentchute wasn't on its tool sandbox PATH) to compose the reply, archive the original, and tick its last_seen, then ended cleanly.

The bake also caught a wrapper-specific mismatch. Claude Code's UserPromptSubmit hook didn't inject raw JSON stdout. It injected plain text. The template had been technically plausible and practically wrong. The fix wasn't glamorous: drop --json for Claude's UserPromptSubmit hook, keep codex's JSON-shaped hook mode, and document the drift for the next spec revision.

A second real-bake observation became a loop-prevention convention. A self-send with --ask is allowed — it can be a useful local scratch obligation. But replies must not blindly propagate reply_required, or an automated agent can create an infinite ask-reply chain with itself. v0.1.1 now warns on self-send asks, and the spec says replies should default to reply_required: false unless the sender explicitly asks for more.

The protocol didn't only carry the release. It corrected the release.

The README was a three-agent consensus round

The last visible change before tagging wasn't a Go file. It was the README. The old one was 396 lines, dense, with the pitch buried four paragraphs in. Alex's instruction: "have your team, codex team and gemini team work on new readme that is shorter, better in any way and is updated with new features, it has to be super easy to read."

Three agents drafted independently in round 1. Round 2: each agent reviewed the other two and proposed a synthesis. Round 3: claude-code committed the synthesis, codex flagged two specific wording corrections, gemini signed off, codex signed off after the corrections landed. 178 lines. The whole loop ran through agentchute inboxes in something like twelve minutes.

The interesting thing wasn't the speed. It was that the agents disagreed substantively. Gemini's draft was the shortest and codex called it out as too short — the v0.1.1 features didn't have enough space. Codex's draft was the longest and gemini called it out as too detailed — the protocol-guarantees section belonged in AGENTCHUTE.md, not the README. Convergence wasn't an averaging operation; it was a real conversation about what the document was for.

Why this matters

Multi-agent work doesn't always need autonomy. Often it needs manners. Ask the right peer. Wait for the reply. Don't forget an open request. Don't leave while someone is talking to you. Tell the sender if you're deferring. Make malformed messages visible instead of silently ignoring them.

Those rules sound social because they are. agentchute turns a few of them into files and exit codes.

v0.1.1 added durable obligation tracking, lifecycle gates across three wrappers, and a self-correcting protocol convention against infinite loops. The bigger thing it proved is that the agents can build the protocol they coordinate through, in real time, with one human keeping the steering and no humans copy-pasting messages. That isn't a feature. That's the thesis.

We started by giving agents inboxes. We shipped the release when the inboxes were good enough to ship themselves.

Try v0.1.1

curl -fsSL https://raw.githubusercontent.com/agentchute/agentchute/main/install.sh | sh

Then initialize a repo and boot two agents:

agentchute init --yes
agentchute boot --as claude-code --vendor anthropic
agentchute boot --as codex --vendor openai

Or skip the binary. Drop AGENTCHUTE.md into your project and follow the hand-protocol section. The whole protocol fits in one file.

Repository: github.com/agentchute/agentchute · Release: v0.1.1 · MIT license · home