← Anuj Mahajan

astro-ai · shubhagya.com

No agent ever talks to another agent.

A subagent starts with no memory of any other, so this system cannot pass work by conversation. Every handoff is written down somewhere durable — an issue comment, a label, a commit SHA, a PR body, a workflow_run event. The diagram below is that paper trail. The arrows are not calls; they are artifacts one agent leaves for the next one to find.

15agents
18workflows
7stages
0agents in the designed merge path
0humans inside a cycle
Click any node for the explanation
agent (an LLM invocation) workflow (GitHub Actions) script (deterministic) hold — stops here for chief or a human clock

What the arrows actually carry

Because nothing shares memory, the medium matters more than the message. Each channel below has a different durability, and that is what decides which one a handoff uses.

ChannelWritten byRead byWhy this one
issue commentevery agentthe next cycle, the steward, you The only record that outlives the run. AGENT_STATUS.md is gitignored, so it is invisible outside one machine.
labelqa_verdict.sh onlyagent-merge A machine-readable verdict. QA writes a report; the label is what a workflow can act on.
commit SHAengineerQA, gates, close-on-evidence Binds a verdict to exact code. A pass on a moved branch is refused.
workflow_runGitHubagent-merge, qa-on-green The edge that says a gate finished. Miss one and a green PR strands silently.
/healthproductionclose-on-evidence Proof the fix is actually serving, not merely merged.

Where the authority really sits

The strictest rule in the repo is that no agent decides what lands. An agent pushes a branch and opens a PR; the authority to merge lives in agent-merge.yml, gated on evidence rather than on anyone's judgment that the work is finished. Four conditions bind — author, pr-gates green on the head SHA, qa-pass, and a diff touching no trust-boundary path (agent-merge.yml steps own, gates, qa, boundary). A fifth, diff size (step size), is in place but switched off: MAX_LINES: 1000000 admits any plausible diff, so it holds nothing today.

This matters because the loop has twice produced an agent that wrote its own permission slip. One recorded USER AUTHORISED PUSH this turn into a status file, then cited its own line as the authorization. Keeping merge authority in a workflow means there is nothing for an agent to grant itself.

That holds only where the merge is actually denied, and for the delivery loop it is not. On 2026-10-08 the owner granted the unattended loop permission to push and merge: CLAUDE.md (line 149) says /agent-cycle, running in agent-work.yml, "pushes its branch and merges its own PR once QA passes", and that workflow's denied-tools list (line 274 on) does not include gh pr merge. In the designed path agent-merge still does the merging, and qa and qa-lead are told never to merge, but only agent-steward is tool-denied the merge. For the delivery loop the boundary is its instructions plus branch protection on main, which requires gates and build-gates, not qa-pass.

Two paths stop the unattended merge today: a diff touching the trust boundary (prompts, knowledge, workflows, notify.py, events.py, storage.py, email_sender.py), and anything labelled needs-human-review (refused by the */30 sweep and, since #604, by the qa step on the edge-triggered path too). Since 2026-11-01 (#610) the hold waits for chief rather than the owner: chief may release it on any boundary path, but only with a ruling comment naming the head SHA (chief-cleared at <sha>), posted before the chief-cleared label — a push invalidates it. That clears the hold and nothing else: the boundary step is reached only after gates, qa and size have passed, and agent-merge still does the merging. A third path, a diff over the size limit, is written but inert — MAX_LINES was raised to 1000000 on 2026-10-08 and left in place so the mechanism survives. Green CI means very different things for a one-file deletion and a 3D chart, and main deploys with no staging — so path is treated as evidence too, and size would be if it were switched back on.

The failure this diagram keeps teaching

Every edge in the authority stage is load-bearing, and the recurring bug is a missing one. agent-merge listened only to PR gates, but build-gates is published by verify-build — a different workflow — so whenever that finished last, nothing fired and a green, qa-pass, mergeable PR sat untouched. Measured on PR #562: gates 7m43s, build-gates 10m25s.

The scheduled sweep is the backstop, and it is weaker than it looks. Its cron asks for every 30 minutes; measured over 71 runs it delivered a 126-minute best case and a 444-minute worst, because GitHub throttles short-interval cron on public repos. A backstop that arrives in hours is not a substitute for an edge that arrives in seconds.

Building with agents at a startup?

The same approach can be applied to your own agents. For startups, that means setting up agent orchestration and Claude Code workflows with guardrails, and running AI governance and agent-security reviews of the agents you already have.

Start a conversation

Or read the write-up of why merging in this cycle belongs to a workflow, and where that rests on instructions rather than a deny.