-
Notifications
You must be signed in to change notification settings - Fork 0
Two agents
Handing work from one session to the next is a baton: one sentence, one pointer, one direction. This page is about the other shape — two agents working towards one goal over time, with roles.
It is one button: Two agents, in the desk's toolbar, on any desk with two terminals open in it.
Two agents on the same machine already share a filesystem. What you can arbitrate with is a
file both of them can read, so that is what this is. The button writes two files into the
desk's folder — PLAN.argus.md, what they are trying to do, and BRIDGE.argus.md,
what they say to each other — and sends each agent a prompt that points at them.
Nothing is installed inside the agent. Nothing is asked of it that it cannot already do — read a file, write a file, end on a sentence. That is why the same two patterns work with Claude Code, Codex, Gemini, Aider or a script that reads its own instructions, and why there is no integration to break when one of them changes.
The rules live in the prompts because there is nowhere else to put them: you cannot enforce anything on an agent you do not control, you can only give it an instruction simple enough that it cannot be misread.
Both work towards one goal. The plan file carries:
## Goal one paragraph, agreed
## Files every file that will be touched, each with one owner
## Doing what each of you is on right now
## Done finished, with what changed
## Blocked what you need from the other, and why
Two rules do the work. Ownership is by file, not by task — two agents can agree on who does what and still both edit the same module. And if you need something that is not yours, write it down and stop, which turns a collision into a line in a file instead of a lost afternoon.
One prompt goes to both, through the chain — chained on for the send and off immediately, because leaving it on is the one way this could quietly ruin an afternoon. The two agents differ only in which name the plan gives work to, so there is nothing to word differently.
They talk through the bridge as well, the same file the reviewing pattern uses, with the
same markers and the same rules. Between peers the statuses mean what you would expect: DONE
for a finished piece, ASK for something you need from the other one — and then you get on
with something else rather than waiting — BLOCKED, and OK when you think the whole goal is
met, which the other answers with its own OK or with what is still missing. Nobody owns the
turn: they work at once, and the file is where they say what they have finished and what they
need. Turns are signed with each agent's own tmux session name rather than WORKER and
REVIEWER.
One writes and never marks its own work correct. The other reads the diff — the diff, not the description of it — and never edits the work.
They talk through a file. BRIDGE.argus.md, beside the plan, append-only. This is the
question the pattern has to answer and it is worth being blunt about why: the two agents
cannot see each other's terminals. A review printed into the reviewer's pane is a review
nobody reads.
@TURN who=WORKER at=2026-08-18T09:14:02Z status=DONE
Added the cache and a test for the empty case. 48 tests pass.
@END at=2026-08-18T09:15:30Z
@TURN who=REVIEWER at=2026-08-18T09:21:40Z status=REDO round=2
src/pipeline.py:88 — the cache key ignores the scheme version, so a stale entry
survives an update. The test passes because it never updates the scheme.
@END at=2026-08-18T09:26:02Z
Timestamp, actor, status, text — all four inside the opening marker, named rather than
positional, so a field left out is visible instead of shifting the others along. Extra fields
are allowed and ignored: round=2, tests=16/0, whatever a pair finds worth carrying. The
last turn says whose move it is, so there is no state anywhere else — not in Argus, not in
either agent's head.
It began as a markdown heading, ## <timestamp> WORKER: DONE, and the first real run showed
why that is not enough: the agent wrote ## WORKER: DONE, without the timestamp. A heading is
prose a parser reads over its shoulder, so every part of it looks optional; a sentinel is a
line you either wrote or did not. The shape is FASTQ's, and so is the reason for it.
| status | written by | means |
|---|---|---|
DONE |
worker | a pass is finished — the reviewer's turn |
REDO |
reviewer | not right yet, and why — the worker's turn |
OK |
reviewer | it is right. Both stop. |
ASK |
either | a question for the other one, which answers before doing anything else |
BLOCKED |
either | stuck, or a person is needed. Both stop. |
STOP |
argus | out of rounds or out of time. Both stop. |
ASK is worth its own line. Neither of them can see the other's screen, so a review that was
misread becomes a REDO for something that is not broken, and an afternoon spent solving
different problems. A question costs one round; a wrong guess costs the afternoon.
Three rules make it work, and all three are written into the top of the file itself, so an agent that reads it cold needs nothing else:
-
A turn is finished only when it says so. The
@ENDline is the difference between "they have said their piece" and "they are halfway through typing it". Act only on a finished turn; otherwise wait and read again. - Append, never rewrite. One command per turn — heading, text and end line together — so nothing is lost when both write at once.
-
There is a deadline, in the first turn. Two agents who cannot agree will not start
agreeing at three in the morning. Past it, whoever notices adds a
BLOCKEDturn and stops.
Both agents start at the same time and poll the file every sixty seconds. Nothing here needs a browser: close the tab and they carry on.
It writes the plan and the bridge, sends each agent its prompt, and then it is a reader — one more thing looking at the same file:
- the pair note shows the last status, or
worker is writing…while a turn is unfinished; - it rings when the reviewer says
OK, and when either saysBLOCKED; - it adds
ARGUS: STOPwhen the rounds you allowed are used up, or the deadline passes; - clicking the note shows the last few turns, and offers to open the bridge, open the plan, or tell them to stop — which is itself a turn in the file, because that is the only instruction the two of them are listening for.
It does not pass the work along any more, and does not read what the review says. The turn-taking belongs to the agents; a program that started interpreting the content would be a third opinion nobody asked for.
An earlier version of this had Argus watching both terminals for VERDICT: and HANDOVER:
lines and sending the next prompt itself. It worked, and it needed the tab open, guessed the
state of the conversation from what was on screen, and left nothing behind to read. The file
is better in all three ways.
Worth knowing, because none of this is new and one of them may suit you better:
- claude-codex-handoff — the same idea in JSONL, two directional streams, per-session cursors, atomic claims. More machinery, less readable by a person.
- llm-handoff — markdown files for state, backlog and handoffs, with validators as the authority.
- FIPA-ACL and Google's A2A — where the field set comes from: who, when, what, and what state that leaves the task in.
The bridge is the small readable end of that family: one file, both directions, markdown.
Nothing takes a lock, and nothing needs to. Every writer appends, and the kernel will not let two appends land on top of each other: whoever gets there first is first, the other follows, and the timestamps say which was which. Nobody's turn can overwrite anybody's.
What is not safe is writing a turn in pieces. The other one's turn can land in the middle of
yours, and then the tail of yours belongs to nothing — the parser drops it rather than
attributing it to the wrong agent, which is the least bad outcome and still a loss. Hence the
rule the header states and the command it gives: one append per turn, both markers and the
text together. If what you have to say is long, build it in a scratch file and cat it in
between the markers in that one append.
The other race is creating the file. In the reviewing pattern the worker creates it and the
reviewer waits; between peers either may find it missing, so they are told to create it with
the shell's noclobber (set -C, then a plain >) and, if that fails because it now exists,
to read what the other one wrote instead of overwriting it.
They arrive in your prompt library in two groups — Two agents · together and Two agents · one reviews — and they are ordinary templates. Open them, read exactly what your agents are being told, change the wording, keep your own version.
One prompt per pattern, plus a nudge: Start (send to both) for peers, and You build / You review for the reviewing pair. There is no "answer the review", no "your turn" and no "converge" — all three were ways of saying out loud something the file now says, back when a person had to notice whose move it was. The nudge is for the one case left: one of them has stopped reading the file and you want to point at it.
Four numbers reach the prompts as placeholders, so none of them is written into a sentence:
{every} how often they read the bridge, {limit} how long the whole run may take, {tries}
how many reads before giving up on something that is not coming, and {bridge} and {plan}
themselves. The durations carry their unit — "every 60 seconds", "30 minutes" — because
"every 60" is an instruction with a hole in it.
One thing to keep if you rewrite them: never put a runnable command at the start of a line. Argus types a prompt into a terminal, and if that terminal is a shell rather than an agent, the shell runs it. The stock prompts point at the command in the bridge's own header instead of repeating it, and they do so because a shell dutifully ran the example and invented two turns.
The set it ships with cannot be deleted, so the button always has something to send. Editing one clears its stock mark, and that is also how an unedited copy gets brought up to date when a wording improves: only untouched ones are refreshed, so your words are never overwritten.
If you rewrite the reviewing prompt, keep the verdict line — it is the one sentence the loop reads.
- The referee that matters is not the other model. An LLM judging an LLM is a weak judge. Ground the round in something that cannot be talked round: your test suite, the diff, a script that either exits zero or does not.
- Watch the first few rounds. The loop is worth switching on once the wording has proved itself, not before — a wrong prompt repeated six times is a faster way to be wrong.
- Read the bridge, not the terminals. The terminals show two agents thinking out loud; the bridge is what they actually committed to each other, and it is a tenth as long.
- Two agents editing one repository is still two agents editing one repository. The plan is an agreement, not a lock.