Sample agent
Claude
claude_code:impl-1 Builds the change last "I'm here" line: none yet Guided story · 9 short scenes · guess, then see
Agent Rally Point is a shared log that coding agents write to and read from inside one repository. In 9 short scenes, you guess what happens when two agents claim files, hand off work, and correct a mistake. Then you see what Rally actually does, and where its knowledge ends.
The agents, their conversation, the file paths, and the counts are invented. Every command and rule they follow is real Rally behavior, read from Rally source at commit bc97e13 (2026-09-12). Handoff delivery, claims, the log in your repo, and worktrees were re-checked on 2026-09-24; those citations are marked re-checked and name file paths. Scene 9 uses real log and Build Loop data captured 2026-09-12T07:46Z. Token and time savings are unmeasured. Playing this story runs no agents.
Who is here, open claims, open handoffs. Finished claims drop off.
Every line is added to a file under .rally/log and never rewritten. A correction is a new line.
Only the agent a handoff names can close it. An answer means it arrived, not that the work is done.
Build Loop, not Rally, knows whether its run is live, crashed, or finished.
01 · Joining Step 2 · enter
Claude and Codex get related tasks in one repository. Neither can see the other's plan, and a quiet terminal looks the same as an idle one.
Your guess Codex wants to know whether anyone else is working here. Where does it look?
Answer: It reads the room: the shared log Rally keeps in the repo. It reads the room. Each agent writes a line saying it is here, and any agent can read those lines without asking anyone.
Sample agent
claude_code:impl-1 Builds the change last "I'm here" line: none yet Agents here claude_code:impl-1, codex:verify-1
Sample files
src/api.tsopensrc/client.tsopentests/api.test.tsopenno line added in this scene
Sample agent
codex:verify-1 Checks the change last "I'm here" line: none yet claude_code:impl-1 is here. I'm starting on the API response shape.
rally enter --tool claude_code:impl-1 added to the log Is anyone else in this repo right now?
rally room --tool codex:verify-1 --json read: the agent asked One agent here: claude_code:impl-1, by its own report. No claims yet.
room projection answer to the asker codex:verify-1 is here. I'll read before I write.
rally enter --tool codex:verify-1 added to the log After the story
The story used two agents in one checkout. Real work often uses more. In a workflow, your host runs the agents, and Rally launches a session only when you ask it to with rally run. Either way, Rally gives every agent the same record of who is doing what. First, a whole workflow with four subagents at once; then the four pieces that make it work.
A whole workflow
A Rally workflow splits one job into tasks that run in parallel. Your host (Claude Code, Codex, and so on) or rally run starts the subagents; Rally never does. What Rally adds is the shared record every subagent writes to and the lead checks.
Your guess Four subagents work at once and finish at different times. When does the lead close the job?
The lead reads the room and confirms that every task posted its result with evidence. A released claim or a "done" message is not proof, and Rally never closes work on its own.
owns src/api/**claim, work in own worktree, post resultowns src/ui/**claim, work in own worktree, post resultowns db/**claim, work in own worktree, post resultowns tests/**claim, work in own worktree, post resultrally run starts a new Claude, Codex, OpenCode, or Gemini session that Rally manages. The session gets its own name, can receive handoffs, and can be stopped.
rally run codex --task "Review the parser and report findings."rally run claude --name reviewer A workstream lists each task's goal, the files it owns, what it depends on, and how to check it. Rally's linter rejects a plan in which two tasks that write files own overlapping paths.
In Rally workflows, the host (Claude Code, Codex, and so on) runs its own agents. Rally records claims, checks write boundaries, routes handoffs, and shows which tasks are ready for an agent. In a workflow, your host picks, schedules and retries the work; rally run launches a session only when you ask. No manager agent sits on top: each agent checks the room itself.
By default, rally run gives each managed session its own linked git worktree: its own branch and its own copy of the files, so agents cannot overwrite each other's uncommitted work. All worktrees share one room through git's common directory, so claims, handoffs, and history stay visible to every agent, and agents still claim files before editing. Before merging, rally worktree plan --json lists every worktree and branch, how far each is ahead of or behind the base, and which have uncommitted changes. It only reads and advises; it does not prove a merge will be conflict-free.
rally worktree plan --json The shared project boundary. Linked worktrees resolve the same room through the git common directory, so one .rally store serves the main checkout and every worktree. RALLY.md:326-327; crates/rally-cli/src/run_worktree.rs:7-9
Sample agents. The rules are Observed.Several agents run with cwd at the repo root on whatever branch is checked out. A commit by one lands on the branch the others are on.
Collision risk is visible: two writers, one branch. Claim checks and the shared-branch-hazard risk fact are the early signals, and both cover records, not writes.
rally run --shared or --no-worktree (deliberate opt-out) Observed This session's own enter into the canonical checkout raised shared-branch-hazard risk facts.
crates/rally-cli/src/run_worktree.rs:3-6,27-28; RALLY.md:326-330rally run provisions .rally/worktrees/<session-id> on branch rally/<session-id> off the run base. Each agent edits its own branch; all of them read and write one room and one ledger.
Isolation is the default. If the worktree cannot be created, provisioning fails closed and the agent is not launched into the shared checkout.
rally run claude --backend auto --json (default) Observed Build Loop used the same pattern for this run: worktree bl/run-319525 off the Lab commit, one shared .rally store.
crates/rally-cli/src/run_worktree.rs:4-34,81-131; RALLY.md:326-327rally run claude --dry-run --json shows the exact session_id, target, tool, and backend command before anything spawns.
rally run claude --backend auto --json Nothing is launched yet. Claude, Codex, OpenCode, Gemini as first-class launch targets; any other agent joins through whoami, enter, ack, next with a stable tool id.
auto, tmux, cmux, ptyd, ptyd-strict. auto picks the rally-owned ptyd path only when that daemon socket is live, otherwise tmux.
RALLY.md:47-63,144-158; docs/HANDOFFS-AND-LAUNCHING-AGENTS.md:19-36The target is a live session Rally manages (listed by rally sessions --json).
The target is not listed by rally sessions --json.
Nothing sent yet.
Optional, per repo, demand activated, fail open. Owns the disposable facts.db cache and serializes reads and writes over .rally/rallyd.sock so concurrent CLIs stop contending. Records, serves, and derives only. Never decides, schedules, launches, or executes work.
CLI, then the Unix socket, then facts.db. One writer.
The JSONL ledger under .rally/log stays canonical; facts.db is rebuilt from it. A kernel file lock guards the handover so there is never more than one writer.
Observed rally daemon status in this repo returned live false with a stale pid file. Every command in this run still worked, which is the documented fail-open behavior.
RALLY.md:320-330,420-452Run backends that host the agent's terminal. auto selects ptyd only when its socket is live.
RALLY.md:152-153Subscribes to directives written in the ledger and delivers them to Easy Terminal or ptyd hosted sessions. Terminal delivery, not store coordination.
docs/HANDOFFS-AND-LAUNCHING-AGENTS.md:30,111Why it changes the outcome
Each line says what becomes visible before what, and under what condition. Neither the direction nor the size of any outcome has been measured.
Overlap is refused at append time, so a second agent learns of a conflicting scope before it starts editing rather than at merge.
Only if agents run the check and honor advisory findings. Direction and size are both unmeasured.
Direction and magnitude UnknownA wrong decision is corrected by appending one withdrawal that any later reader can see, instead of by reconstructing the conversation.
Only if agents run the check and honor advisory findings. Direction and size are both unmeasured.
Direction and magnitude UnknownResponsibility transfers only on a fact the receiver authored, so delivered and accepted stay distinguishable.
Only if agents run the check and honor advisory findings. Direction and size are both unmeasured.
Direction and magnitude UnknownScope is visible before the write rather than after, so the reconcile step has a chance to not exist.
Only if agents run the check and honor advisory findings. Direction and size are both unmeasured.
Direction and magnitude UnknownClaim scopes are narrow and host-neutral, so two vendors' agents can hold different paths in one checkout.
Only if agents run the check and honor advisory findings. Direction and size are both unmeasured.
Direction and magnitude UnknownA verifier's evidence is a separate artifact fact from its receipt, so acceptance is not mistaken for verification.
Only if agents run the check and honor advisory findings. Direction and size are both unmeasured.
Direction and magnitude UnknownThe counterfactual, with its knobs showing
Identical repo, identical two tasks, identical agents. The only removed element is the pre-write coordination read: no claim, no before-write check, no room read.
Modeledp_overlapp_honorC_reconcileT_check, T_write2, T_merge| Row | Formula | Without a check | With Rally | Label |
|---|---|---|---|---|
| Collision timingThe ordering follows from documented rules; the duration is Unknown. It collapses to zero for any agent that skips the check or ignores a non-strict finding. | delta_detect = T_merge - T_check | After both edits | Before the second write | Derived |
| ReworkTotal. A product of three unmeasured terms is unmeasured. The formula is shown so the reader knows what would have to be measured. | E[rework_avoided] = p_overlap x p_honor x C_reconcile | Unknown | Unknown: three unmeasured inputs | Unknown |
| ReceiptA third state, work complete, is distinguishable by neither. A receiver can author a receipt and do nothing. | count of distinguishable delivery states | 1 state: sent | 2 states: sent; acknowledged by the named receiver | Derived |
| RecoveryRecovered as asserted, not as verified. A large room is budget-trimmed and says so in totals. | F_recoverable = facts appended for this engagement | 0 for a new agent asking programmatically | Every appended fact, within the room budget | Derived |
| Tokens and end-to-end timeNo matched measurement exists. The available benchmark is explicitly not a billed-token or end-to-end latency comparison. | none offered | Unknown | Unknown | Unknown |
What would close the unknowns. Pair comparable runs by task class, model tier, changed-file count, and starting repo state. Report sample size, missing usage data, conflicts, reverts, handoff-to-receipt time, and review outcomes.
Evidence before claims
About 81% smaller output and about 47% lower median CLI read time
Six alternating reads in one crowded room (median 261,210 bytes / 0.224 s full, 49,903 bytes / 0.119 s compact). Not a billed-token or end-to-end model latency comparison.
docs/OPTIMIZATION-EVIDENCE.md:3020 of 20 synthetic handoff tasks
Does not test interactive model TUIs or production task generality.
docs/OPTIMIZATION-EVIDENCE.md:328 of 8 after commit 9129d81
Source still states that no universal exactly-once or never-fails guarantee is made.
docs/OPTIMIZATION-EVIDENCE.md:33,75No matched comparison exists across coordinated and uncoordinated runs.
Historical sessions differ in task, model, and coordination maturity, so the current data cannot support a causal savings claim.
Read together
Pairs as they appear in the scenes. Citations point into Rally source at commit bc97e13, or were re-checked on 2026-09-24 where marked re-checked.
| Scene | Rally promises | Rally does not |
|---|---|---|
| 01 · Joining | Nothing in the log is ever rewritten. The log file is the record; Rally's database is a cache it rebuilds from the log. Whether the very last line survives a crash is up to the filesystem, not Rally.NORTH_STAR.md:29-31; docs/RALLY_ARCHITECTURE.md:70-75; re-checked: RALLY.md:328-333 (log canonical and committed), RALLY.md:335-343 (rally init ignores caches only; log/ stays committable); README.md:398 (Rally's own release repo ignores live logs and commits only manifest.json) | The name on each line is whatever the agent typed. It is not signed, so a line proves something was written, not who wrote it.RALLY.md:264-266; docs/security/TRUST-MODEL.md:86,113-117 |
| 02 · Reading | Rally records and advises. It never assigns, schedules, or retries work, and it starts an agent session only when you ask with rally run. rally next returns a suggestion, not an order.NORTH_STAR.md:23-26; docs/TURN-LOOP.md:3,25,69; README.md:272 | Rally sends nothing to Codex for an ordinary post, and a post nobody reads changes nothing. A handoff addressed to one agent can be queued for that agent's session with rally inject when Rally manages it, as scene 8 shows. Even then, only the receiver's own reply proves it arrived.docs/COMMAND-SEMANTICS.md:28-29; docs/AUTO-COORDINATION-HOOKS.md:268; re-checked: README.md:15, README.md:211 (rally inject) |
| 03 · Claim | One owner per path, recorded in the log. A single-file claim lasts 30 minutes; broader claims last 120.NORTH_STAR.md:31; crates/rally-cli/src/store.rs:5391-5411; crates/rally-cli/src/decay.rs:39-47,90-113; crates/rally-cli/src/lib.rs:2493-2545; docs/PROTOCOL-NORTH-STAR.md:345-353 (scope kinds) | A claim is not a file permission, and Rally is not a sandbox. Nothing on disk changed.docs/TURN-LOOP.md:67; docs/security/TRUST-MODEL.md:22-23; re-checked: README.md:14 |
| 04 · Refusal | Overlapping claims are refused when they are written: an error, nothing added to the log, a failing exit code.crates/rally-cli/src/store.rs:5391-5411; re-checked: README.md:14 (Rally refuses overlapping exclusive claims) | Rally refused the coordination record, not the file write. Nothing stops an agent editing src/api.ts anyway: Rally does not guard files against writes or make simultaneous edits safe. The before-write check warns by default; --strict makes it fail.re-checked: README.md:14, README.md:251; earlier: docs/TURN-LOOP.md:66-69; crates/rally-cli/src/check.rs:53-91; RALLY.md:37-40 |
| 05 · Reroute | One command set and one set of rules across Claude, Codex, Gemini, and Cursor.NORTH_STAR.md:35; RALLY.md:65-76 | Rally does not judge whether Codex picked useful work. Its own docs say it cannot tell a useful task from a harmful one.docs/PROTOCOL-NORTH-STAR.md:30-32; dynamic-workflows/PROTOCOL.md:120-134 |
| 06 · Stale claim | The log keeps the old claim forever. What the room shows now drops a claim only when a release, a resolve, a session close, or a cleanup closes it.crates/rally-cli/src/claim_authority.rs:71-84; RALLY.md:315-331 | Two Rally commands can answer differently for the same file at the same moment: claim refused, before-write allowed with a warning. An owner quiet for 15 minutes only earns a warning; taking over its work needs 2 hours of silence.crates/rally-cli/src/store.rs:1732,1740; crates/rally-cli/src/check.rs:120-146; session observation 2026-09-12 |
| 07 · Correction | The log is never rewritten. The withdrawal itself stays visible, and room totals count withdrawals instead of hiding them.RALLY.md:242-270,348-419 | Rally does not decide which version is right and does not chase anyone. An agent that read the old note and never reads again keeps acting on it.docs/PROTOCOL-NORTH-STAR.md:30-32; docs/COMMAND-SEMANTICS.md:28-29 |
| 08 · Handoff | Only the named receiver can close a handoff; neither the sender nor Rally's cleanup can. A handoff with a reply deadline shows up as overdue the next time the sender runs rally next, with one no-response risk recorded. The receiver's own view of what waits for it is rally inbox.crates/rally-cli/src/store.rs:7413-7470,7452-7459,1147-1149; crates/rally-cli/src/lib.rs:12352-12363; re-checked: README.md:211 (rally inject); docs/COMMAND-SEMANTICS.md:110 (rally inbox); docs/ACK-DEADLINE-ESCALATION.md:35-39,43 (reply deadline) | A receipt proves receipt, not completion, and the receiver's name on it is self-asserted and unsigned. A queued or delivered inject is not proof the model read it. Nothing happens at the deadline by itself: the overdue check runs only when the sender runs rally next. A receiver Rally does not manage cannot be reached by rally inject; it sees the handoff when it next reads rally inbox or rally next.crates/rally-cli/src/store.rs:7431-7433; RALLY.md:264-266; re-checked: README.md:15, README.md:211; skills/agent-rally-point/SKILL.md:164-178; docs/ACK-DEADLINE-ESCALATION.md:35-39,43 (reply deadline) |
| 09 · The limit | Rally records the coordination facts but does not run the task. Rally coordinates across agents; each agent's own checks drive the work inside its lane.README.md:272; RALLY.md:130-138; dynamic-workflows/COORDINATION.md:118-138 | Rally does not know another tool's run state beyond what that tool reports about itself. The status tool admits its own limits too: heartbeat unknown, process liveness unknown.docs/OPTIMIZATION-EVIDENCE.md:1-5,69-70; run_status.py output 2026-09-12T07:46Z |
Model tests assert the page's own scenario model, not Rally. Session observations are real command output captured 2026-09-12. Sources are at bc97e13 unless marked re-checked (2026-09-24, against the public repository).
| Interaction | Command | Source (bc97e13 unless marked re-checked) | Model test or session observation |
|---|---|---|---|
| Agent announces presence | rally enter --tool <tool>; rally say presence | crates/rally-cli/src/store.rs:527,601,631; docs/AGENT-STATE-MODEL.md:36 | model test: presence is a write |
| Agent reads the room | rally room --json; rally whoami; rally next | docs/COMMAND-SEMANTICS.md:28-32; docs/TURN-LOOP.md:25 | model test: no push events |
| Host hook reads on the agent's behalf | SessionStart and PreToolUse hooks | docs/AUTO-COORDINATION-HOOKS.md:268; docs/security/TRUST-MODEL.md:172-177; rally hooks status (enabled by default) | session observation: rally hooks status enabled by default, 2026-09-12 |
| Claim a scope with a lease | rally say claim --path <p> | NORTH_STAR.md:31; crates/rally-cli/src/decay.rs:39-47,90-113 | session observation: claim fact_8bd9_18d48373a53099e8 carried lease_expires_at |
| Overlapping claim refused at append | rally say claim (overlap) | crates/rally-cli/src/store.rs:5391-5411 | session observation: verbatim 2026-09-12: claim conflict ... overlaps the scope you requested |
| Advisory before-write finding | rally check before-write --path <p> [--strict] | crates/rally-cli/src/check.rs:53-91,120-146; RALLY.md:37-40 | session observation: 2026-09-12: allow:true with stale-owner-claim |
| Expired lease is not closure | rally doctor --reap-stale --apply | crates/rally-cli/src/claim_authority.rs:71-84; crates/rally-cli/src/reaper.rs:406-439 | session observation: 2026-09-12: three reap passes closed the expired claims |
| Retract without rewriting | rally retract <fact-id> --reason <why> | RALLY.md:242-270 | model test: withdrawal keeps the original |
| Handoff stays open until the target answers | rally say handoff --target <tool>; rally say receipt|resolve|artifact --ref <id> | crates/rally-cli/src/store.rs:7413-7470; crates/rally-cli/src/lib.rs:12352-12363 | session observation: receipt fact_fc26_18d483db677dce00 authored by the target |
| Handoff queued for a managed session | rally say handoff --target <tool>; rally inject <session> --handoff <event-id> | re-checked: README.md:211; crates/rally-cli/src/backends.rs:1226 | model test: scene 8 push comes from the room into the managed receiver |
| Reply deadline and overdue list | rally say handoff --ack-within 10m; sender's rally next | re-checked: docs/ACK-DEADLINE-ESCALATION.md:35-39,43 | model test: scene 8 records one no-response risk before the receipt |
| Receiver's view of open handoffs | rally inbox --tool <tool> | re-checked: docs/COMMAND-SEMANTICS.md:110 | model test: scene 8 receiver reads rally inbox |
| Plan work so no two write tasks own the same paths | workstream descriptor; workstream-lint | re-checked: README.md:305-306; dynamic-workflows/PROTOCOL.md:95 | model test: ending cites the lint rule |
| Review worktrees before merging | rally worktree plan --json | re-checked: RALLY.md:314-323 (rally worktree plan) | model test: ending says the plan is read-only and advisory |
| Receipt is not completion | rally say receipt | crates/rally-cli/src/store.rs:7431-7433 | model test: receipt and artifact are separate events |
| Build Loop run lifecycle | python3 scripts/run_status.py <run-id> | build-loop scripts/run_status.py; README.md:272 (Rally does not execute the task) | session observation: 2026-09-12T07:46Z: status abandoned, crash_signal stop_hook |
| Choose shared checkout or linked worktrees | rally run (default worktree) or rally run --shared / --no-worktree | crates/rally-cli/src/run_worktree.rs:4-34,81-131; RALLY.md:326-330 | model test: systems view layouts and fail-closed provisioning |
| Launch a managed lane | rally run claude|codex|opencode|gemini --backend auto --json; --dry-run first | RALLY.md:47-63,144-158; docs/HANDOFFS-AND-LAUNCHING-AGENTS.md:19-36 | model test: launch objects are separate and cited |
| Send a handoff again into a managed session | rally inject <session> --handoff <event-id> | re-checked: README.md:211; skills/agent-rally-point/SKILL.md:175 | model test: acceptance still needs target-authored evidence |
| Reach an unmanaged process | rally say handoff --target <tool> (records only); rally inbox; rally watch | re-checked: skills/agent-rally-point/SKILL.md:169-171; earlier: RALLY.md:95-99,160-162; docs/HANDOFFS-AND-LAUNCHING-AGENTS.md:86-110 | session observation: 2026-09-12: handoff 07:55:00Z, receipt 07:58:50Z by this unmanaged session |
| Daemon cutaway | rally daemon status|start|stop|serve | RALLY.md:320-330,420-452; RALLY.md:152-153; docs/HANDOFFS-AND-LAUNCHING-AGENTS.md:30,111 | session observation: 2026-09-12: daemon live false, commands still worked (fail open) |