Skip to content
moaz
Case study 02 · 2026

crosstalk

Agents from rival vendors (Claude Code, Codex, Cursor) build one codebase as a team. A review finding is a claim to verify, not a command.

The problem

I started crosstalk after a review session where the agents were good at producing confident conclusions and bad at establishing whether those conclusions were true. A finding from one worker could be treated like an instruction by another. The motivating session made the cost visible: roughly as many defects came from the orchestrating agent as from either worker. Evidence was routinely unfalsifiable. An errors: [] result only proved that the renderer did not throw; it did not prove that the claim was right.

I wanted a review finding to behave like a claim with a state, evidence, and a way to dispute it. The practical setting is several agents from rival vendors working in one codebase. They need shared evidence, isolated workspaces, and a record that remains inspectable after a merge changes the code.

Architecture

Claude CodeCursor / CodexMCP serverclaim/dispute coreGitHubmirrordaemon (HTTP+SSE)append-only JSONL log
Agents reach the shared claim/dispute core through the MCP server; the daemon accelerates reads over the same append-only log.

The repository is split into nine modules. The core owns the claim and dispute state machine. A daemon provides an HTTP and SSE accelerator over an append-only JSONL log, but the log is the protocol rather than the daemon. Contracts define schemas for falsify, contest, and uphold operations. The MCP server is the way Claude Code, Cursor, and Codex agents participate.

The harness module describes vendor-specific harnesses and brief templates, while node-pty mirrors interactive seats. The workspace module gives each seat a git worktree. The mirror module connects the process to GitHub with one pull request per task and one edited comment per claim. A loopback UI hub, CLI, and the JSONL log complete the local workflow.

Try it

A real recorded session: help, init in a fresh repo, and doctor. Nothing is faked.

crosstalk · init and doctor

Recorded terminal session

Decisions

Make falsifiability a required field

I made a falsifier part of the API contract instead of leaving it in the prompt. Prompt rules are forgotten around turn 40; schemas are not. The rejected approach also has a failure mode of its own: agents can end up defending broken code, which is sycophancy inverted rather than a useful review.

Rejected
Let workers push back on findings in conversation.

Keep JSONL as the protocol

The daemon is useful for HTTP and SSE acceleration, but an append-only JSONL log is easier to inspect, replay, and keep independent of one process. This keeps the protocol present when the accelerator is not running.

Rejected
Make the daemon the source of truth.

Expire evidence at the commit boundary

Every result carries the commit it ran against. If a merge or later change orphans that result, crosstalk reopens the claim. That makes stale evidence visible instead of quietly letting an old pass or failure stand for new code.

Rejected
Keep a result valid after the branch has moved.

Security / reliability

Falsifiability is a schema field, not a stronger instruction to the model. A claim has to say what would disprove it, and the state machine records whether it was disputed or upheld. Evidence is tied to a commit SHA, so the system can distinguish “this was true on that tree” from “this is still true now.” When the normal rounds end, the escalation ladder is a discriminating test, then an uninvolved peer, then the leader. The last rung waits rather than pretending certainty.

Numbers

318
commits
source: facts.md
115
TypeScript files
source: facts.md
26,259
lines in src
source: facts.md
1,236
test cases
source: facts.md
11
test files
source: facts.md
6
harnesses
source: facts.md

What went wrong

What went wrong

A working protocol with uncomfortable gaps

The motivating session is part of the warning label. The orchestrating agent introduced roughly as many defects as either worker, and the empty error list was not meaningful evidence. The implementation is working, and not yet used in anger.

There are known gaps. taskAcceptance.method is leader-only. The tier-3 file inbox is not built. init overwrites CLAUDE.md and AGENTS.md, and pressing Ctrl-C on up can orphan seats. init does not check the first commit (#23). The doctor's MCP probe is only access(F_OK|W_OK), so it checks access rather than whether the server actually answers.

What I'd change

I would make the first real multi-agent run a design input, not a victory lap. The protocol has the right places to put evidence, but the gaps are in the edges around it: initialization, seat cleanup, acceptance routing, and meaningful health checks. I would close those before adding more vendor-specific behavior.

The public repository is linked above as “crosstalk on GitHub.” The npm name is crosstalk-ai, but it is not yet published. The Vault benchmark applies this in practice: /work/vault.