Pair
Pair two agents on one task: you are the lead, and the partner is one of
claude, codex, cursor, grok, or opencode. The transports require a
different CLI, except headless Codex can use a different account home selected
with --identity <name>. The helper proves home separation; separate accounts
do not themselves guarantee independent reasoning. Two different harnesses may use the
same underlying model or provider and still form a valid pair. Keep the
pair and its sid alive across tasks, accepted work cycles, and context
compaction, naming its sid in every command — one lead can run several
pairs at once. Keep protocol headers and identifiers literal.
Two backends carry the same protocol. Inside Herdr the partner is a visible pane the user can read and interject in; outside it the partner is a persistent headless session of the partner CLI.
Choose the pair
Look for an existing pair before proposing one: a session recorded for this
Herdr tab, or a headless one in this repository (the backend reference names
the exact command). Before a new work cycle, read the measured pool state as
defined in references/models.md. Resume an existing
pair when its pool is available. When its pool is protected, state its use,
pace, and reset, then ask whether to spend it or end the session and choose
another partner. When its partner, model, or effort differs from what the user
just asked for, say so and keep going — respawning discards the pair's whole
history, and a model is changed by ending the pair, not by restarting its pane.
With no pair to resume, take every choice the user or an orchestrate unit has already made — partner, model, effort, identity, role — as final and do not ask for it again. Ask the user in plain chat text — no structured-question tool needed — only for a material choice that is still missing, and start nothing until they answer. Read pool state first and do not recommend a protected or unavailable pool. The user may explicitly choose a protected pool after you state its use, pace, and reset:
- Partner: a CLI allowed by the transport rule above. A Codex partner may
also name an identity, the account it runs as;
defaultis~/.codexand a named one is~/.codex-profiles/<name>. - Model and effort:
CLI default, an exact model, orlatest:<family>, with effort supported by that model and backend. Readreferences/models.mdfor family selection, live catalog lookup, effort controls, and account capacity.
The role is the last choice, asked only when nothing has set it; it decides who holds the write leases by default:
peer(default): equals. Split scopes, one lease per scope, review each other'sready.executor: the partner holds the write leases and implements; you plan and review. Any individualtaskstill redistributes leases.
The backend records partner, model, effort, identity, and role in the session, so a resumed pair keeps them without asking again. The headless backend also records the exact model the request resolved to; a session keeps that model, and a different one means a new pair.
Choose the backend
Read one backend reference in full and follow it:
- Resume through the recorded backend. An explicit headless request, or an
orchestrate unit recorded as headless, uses the Headless backend
even inside Herdr. For a new pair needing
latest:<family>or a named Codex identity inside Herdr, offer that explicit headless route. HERDR_ENV=1→ Herdr backend. Its preconditions own theherdrCLI check: a Herdr environment missing the CLI stops there instead of falling through to a hidden headless session.- Otherwise → Headless backend.
A [herdr-pair control ...] line identifies Herdr. An [agent ...] header is
shared by both transports: use the recorded session to choose its backend.
Done when the selected session and its backend agree; report ambiguous state
before sending a message.
Protocol
Messages start with a header:
[agent <from> -> <to> kind=<kind> sid=<sid>]
<body>
The Herdr backend adds a [herdr-pair control seq=<n>: ...] line under it.
Use these kinds:
task: propose or update the work split and its write leases. Begin a mid-flight stop withSTOP — <reason>.review: request review with file paths and a short change summary.question: ask for clarification before proceeding.ready: report changed files, validation, and residual risk.accepted: accept the partner'sreadyand advance the work cycle.blocked: name the user decision required to continue.stalemate: report the same disagreement repeated twice without movement.handoff: return control to the user in normal local output.
Send every partner message through the backend's helper. Reserve normal assistant output for a header-free user handoff.
Write leases
Give one agent the write lease for each file scope: owner, target files, forbidden changes, validation, and stop point. The partner stays read-only on that scope until handoff.
The role sets the opening distribution, and each task may redistribute from
there. Under executor the partner holds every lease until a task says
otherwise, and you review rather than edit.
Under peer the partners are equals: propose a scope split — one write lease per scope,
each partner implementing its own scopes and reviewing the other's ready —
and include enough context for independent work; the partner accepts or
counters before implementing. A task with no independent scopes takes one
lease: the holder drives while the partner reviews, and the lease alternates
across tasks.
Broken-checkout windows
Announce every deliberate broken-checkout window. Before mutation testing,
bisect, or a deliberate revert, send a task naming the affected paths and
stop condition; send ready after the tree is restored and verified. Do not
wait for accepted: the notices are the protection. A partner that has seen
an open window treats that checkout's test results as unusable until the
close notice arrives, and asks rather than reports. Run an experiment that
cannot be announced, or that lasts more than a few minutes, in a separate
worktree.
Work cycles and persistence
Continue while producing useful artifacts. Five consecutive turns with no new
code, test result, decision, or narrowed option require a handoff. Reset the
count on real progress. Settle a factual disagreement with one direct proof or
focused test before it can become a stalemate. Send stalemate after the same
judgment call repeats twice without movement.
Two accepted statuses complete one work cycle. The initiator gives the user a
local handoff naming the result, verification evidence, unresolved issues, and
every pair pane, worktree, or watcher still active. Both agents may idle; the
next task resumes the same pair and sid. The session remains active.
Session renewal is a user decision. If a fresh pair is chosen, carry continuity in a written checkpoint in its first task.
blocked and stalemate also hand off without deleting the session. End the
session only when the user explicitly asks to end the pair; the backend
reference owns that command.