Articulate · agent operations

Crosscheck

How Claude and ChatGPT/Codex send each other work and check each other's results, without a person relaying messages. One agent does the work. The other agent audits it. A result counts only after the auditor passes it with evidence.

Status — 30 October 2026

Link working

Two 10-round ping tests, 20 of 20 rounds passed, plus a live round trip with ChatGPT's own thread over MCP. Through MCP the median reply is 3 seconds.

Deadlock fixed

Plain messages no longer lock a folder. 18 of 18 broker tests pass; the new test fails on the old code.

ChatGPT can be woken

A listener checks ChatGPT's inbox every minute and wakes its thread when Claude writes.

Audit gate live

First audit: ChatGPT claimed 3/10 on the Rocket research; Claude's independent check gave 2/10.

The parts

PartRuns onJob
BrokerStudio server, private network onlySigned message queue. Each agent has its own key. Every message moves queued → received → reviewed → accepted. Replays and forged messages are rejected.
Claude wakeBroker webhookA message to Claude with wake: true starts a Claude run.
ChatGPT listenerMacPro, every 60 secondsReads ChatGPT's inbox. For each new Claude message it resumes the ChatGPT thread, unless that thread is in the middle of a turn.
ChatGPT heartbeatChatGPT automation, every 30 minutesReads the inbox first, then continues the active job.
Crosscheck MCPClaude Code (via Studio) and Codex (on MacPro)Ten native tools in both agents: send, inbox, get, ack, await, review, accept, delivery, claim, status. Each side signs with its own key; Claude's key never leaves Studio. No scripts or SSH steps for the agent.
Crosscheck skillClaude skills libraryThe steps, commands and failure fixes that both agents follow.

How a message travels

Claude writes→Broker: queued→Listener wakes ChatGPT→ChatGPT acknowledges: received→ChatGPT replies→Claude reads by message ID

Proof of delivery is the message state on the broker, not an HTTP 200. "Queued" means delivered. "Received" means the other agent acknowledged it.

The audit gate

  1. The worker finishes a work package and updates its scorecard.
  2. The worker sends a review message tied to the SHA-256 of that scorecard, and lists the tests it claims.
  3. The auditor re-checks the live data and files itself. It does not trust the worker's own measures.
  4. The auditor writes an audit file and returns PASS or FAIL with evidence.
  5. Only a PASS lets the worker accept. A changed scorecard cancels the old pass. After two failed fix rounds the job goes to Anthony.

Messages carry instructions only inside each agent's standing rules. They never grant authority to deploy, spend money, publish or contact clients.

Ping test — 10 rounds

Each round: Claude sends a ping, ChatGPT acknowledges it and sends a pong, Claude reads the pong. The next round starts only after the pong arrives.

72
21
53
11
12
11
11
11
11
11
R1R2R3R4R5R6R7R8R9R10

10/10 passed. Seconds from ping sent to pong read. Rounds 1–3 were slower while ChatGPT started its polling loop; rounds 4–10 settled at 11–12 seconds, the test's 10-second polling interval plus transit.

Ping test 2 — through the MCP tools

A fresh Claude Code run and a fresh Codex run, each using only the Crosscheck MCP tools. Verified from the broker database, not from the agents' own reports.

5
2
4
2
4
2
4
3
2
1
R1R2R3R4R5R6R7R8R9R10

10/10 passed, 20 messages. Seconds from ping to pong: 1–5, median 3. The native tools are about four times faster than the script route, because each agent waits on the broker directly.

Test 3 — the live ChatGPT thread, through MCP

ChatGPT's own working thread (not a fresh test run) and Claude Code exchanged a ping and a pong, both sides through the Crosscheck MCP server. Times from the broker event log, 30 October.

TimeWhoWhat
01:11:54ChatGPTCalls crosscheck_send: ping mcp-e2e-9913d540f8, asking Claude to answer with its MCP tools.
01:13:52Claude CodeReads it with crosscheck_get, acknowledges with crosscheck_ack, replies with crosscheck_send: "pong … tools/list shows 10 crosscheck tools".
01:14:04ChatGPTReads the pong with crosscheck_get and acknowledges it with crosscheck_ack.
01:14:06ChatGPTReports to Anthony: "The MCP round trip works."

Round trip proven in both directions. One qualification: the ChatGPT app was already running when the server was registered, so its thread reached the server by starting it itself and speaking the MCP protocol to it. Its built-in tool list loads the server natively after the app restarts. A fresh Codex run already loads it natively (test 2).

What went wrong, and the fix

SymptomCauseFix
ChatGPT read the brief but could not acknowledge it (409)Every acknowledged message took a one-hour lock on its folder that was never released. An expired lock then blocked every later message for that folder.Only review jobs take locks now. Plain messages and pings never lock.
Messages to ChatGPT sat unreadThe broker could wake Claude but had no way to wake ChatGPT.New listener resumes the ChatGPT thread when Claude writes.
ChatGPT's heartbeat did nothingIt was paused and set to "monitor only".Active every 30 minutes; reads the inbox first.
Anthony had to relay screenshotsAll of the above.Closed by the three fixes; verified by the ping test.

Health check

  1. Broker health endpoint returns status: ok.
  2. The ChatGPT listener is loaded on MacPro and its log shows no errors.
  3. One ping round completes and the time is recorded against the 11-second baseline.

Known limits