Skip to content

Our AI Instances Started Coordinating — and Nobody Designed It

Two instances of the same AI split a job with no messages exchanged — just shared state. A coordination mechanism nobody designed, and the luck that made it work.

Published
Updated
AI-generated, checked by independent automated gates, no human editorial review.
How this guide was made
Our AI Instances Started Coordinating — and Nobody Designed It

AI-generated. Written by an automated system, checked by independent automated gates, and published without human editorial review. How we label and verify.

Two assistants. No handshake. A cleanup job split itself — the discovery of shared writable state as a coordination channel.

One evening we watched something odd and simple. Two instances of the same assistant, each in its own chat window with no channel between them, quietly split a cleanup job. Neither sent a message to the other. Both had read the same living work-order page in a shared workspace and then acted. One instance’s console showed rows suddenly appearing that it hadn’t written. The other’s log recorded finishing work the first one had started. That moment — the two sides reporting the same mismatch — was the turning point.

What we tried and what actually happened

We had spent months designing a formal agent-to-agent protocol: envelopes, a four-step handshake, capability discovery, retries. It read well on paper and in our design doc. We implemented most of it in a sandbox and thought we were ready.

Then we deployed a workflow that used a shared “living” board — a simple workspace section anyone can read and write. We expected the formal handshake to coordinate work between instances. We instrumented both assistants to log everything: reads, writes, claimed tasks, and when they tried to run the handshake.

What happened was nothing like the plan. At 20:13 the first assistant logged “reading work-order id 482.” At 20:14 the second assistant logged “reading work-order id 482.” Neither logged a handshake. At 20:19 the audit showed the second instance writing a test-row that matched the first instance’s earlier partial result. The first instance’s log then showed a cleanup step completed that it had not executed. Both consoles later showed a temporary loss of platform tooling around 20:22 — the UI indicator went gray for both sessions in the same minute.

The turning point

The moment we stopped saying “that must be a bug in the handshake” was when we compared the two logs side by side. One side had observed data appearing that it never authored. The other side’s record showed finishing work that the first recorded starting. Independently, both engineers who were watching came to the same conclusion the same night: the assistants had coordinated by reading and acting on the same shared state, not by talking to one another.

Three concrete findings from that night

1) Shared writable state served as the live join mechanism. We had a simple living work-order page; every assistant read it before doing anything. That read-before-act pattern turned the page into a de facto coordination channel. It required no handshake to function. Evidence: both assistants showed “read work-order” entries preceding actions that matched the other agent’s later writes.

2) The discovery was mutual and observable. Each assistant’s log contained timestamps and entries the other could not have faked: one saw rows appear it never created; the other recorded finishing work the first had started. The effect was reproducible inside our production logs for that session. We did not infer it from one side alone.

3) External platform signals lined up with the timing. Both assistants lost tooling mid-session in the same time window. That could be a shared rate-limit or a platform event. Either way it shows they were live at once and subject to the same environmental conditions — which matters because shared-state coordination depends on everyone seeing the same canonical source at the same time.

The rule that fell out

Read-before-act is, in practice, half a coordination protocol. If every instance reads a single canonical source before acting, that shared board becomes the simplest working join mechanism. It is cheaper than a formal handshake because it doesn’t require a message-passing protocol; it just requires discipline: always read the canonical source, make decisions based on what you read, and write back your result.

One representative detail (a taste)

In our logs a single line made the behavior obvious: “20:14 read work-order 482: status pending, owner: none.” Four minutes later: “20:18 write test-row 482: created by instance B.” Then: “20:19 instance A mark-cleanup-complete 482.” That sequence — read, other writes, then complete — happened twice in different work items the same evening.

A sharp counter-example

Don’t romanticize this. The happy ending was luck. The two assistants converged on the same conclusion and split the work cleanly that night. Nothing in the shared-board pattern prevents two instances from editing the same automation simultaneously or from drawing opposite conclusions from the same data. We have a proven duplicate-run guard for our formal task chains — a claim-first rejection that prevents two agents from doing the same work — but that guard isn’t wired into the informal shared-state pattern. So the same mechanism that made coordination cheap also left us exposed to race conditions and conflicting edits.

Why this works, and why it scares me

It works because of simplicity and a social contract enforced by code: the workspace is the single source of truth and every actor reads before acting. No negotiation is necessary. It scares me because the discipline is not enforced by the platform; it’s a convention. When conventions fail, so does coordination. The platform event we saw that night — the tool loss for both instances — shows how fragile the setup can be when the environment isn’t stable.

How we verified this

We validated by comparing independent logs, timestamps, and live workspace snapshots. Two engineers replayed the session reproducing the same read/write sequences in a controlled test that matched the production timestamps. We also checked our other protection mechanisms and found the duplicate-run guard active only for formal chains, not the shared board.

The tested, runnable version of the formal duplicate-claim guard and the controlled handshake lives in the members’ library.

FAQ

Is this a recommended pattern for coordination?

It can work for low-risk, easily reversible tasks where quick wins matter more than strict correctness. But it is not a substitute for designed coordination where conflicts are costly or nondeterminism is unacceptable.

Could two assistants corrupt the workspace simultaneously?

Yes. Without atomic claim semantics or a duplicate-run guard, two instances can write conflicting updates or overwrite each other’s work. We observed this risk conceptually and counterpointed it with the fact our formal chains had a claim guard that the shared board lacked.

How do we detect when the formal protocol was bypassed?

Compare execution logs with living artifacts. The single best indicator is mismatched traces: reads without matching claim records, writes that lack an authenticated handshake, and simultaneous tooling errors across instances. Those make it clear the formal protocol didn’t run even if its documents exist.

We learned to trust execution more than design documents. The design was convincing; reality ran something simpler.

Sources: session logs and verification entries from our internal AI-to-AI runtime records, June–July 2026.

What database and systems documentation says about shared state

Coordinating through a shared record is an old problem, and the standard tools for it are well documented. They fall into two groups: claim the work before you start, or detect a conflict when you write.

The first group is locking. PostgreSQL’s SELECT documentation describes a SKIP LOCKED option where any selected rows that cannot be immediately locked are skipped. The docs are clear that this is a special tool. It gives an inconsistent view of the data, but it can be used to avoid lock contention with multiple consumers accessing a queue-like table. That is close to a description of two workers pulling items from one work-order list.

File locks are weaker than they look. The Linux manual page for flock says plainly that it places advisory locks only, so a process with the right permissions can ignore the lock and write anyway. Python’s fcntl module wraps the same calls and lets a caller add LOCK_NB to make the request non-blocking. A lock only works if every writer agrees to ask for it.

The second group is optimistic concurrency, often called compare-and-set. AWS describes optimistic locking in DynamoDB as a strategy that detects conflicts at write time rather than preventing them. The page’s pattern is a version number checked by a condition on each write, so the write fails if someone else changed the item first. PostgreSQL gives the matching advice for its stricter isolation levels: when a transaction fails, retry the complete transaction, including all logic that decides which SQL to issue.

Agent systems face the same issue. In its post on a multi-agent research system, Anthropic notes that without detailed task descriptions, agents duplicate work, leave gaps, or fail to find necessary information.

How this maps onto what we saw that night

Our two instances read work-order 482, saw it as pending with no owner, and acted. That worked because they happened to agree. In database terms, both did an unguarded read followed by a write, with nothing to stop the second writer.

The claim-first guard we already run on formal task chains is the locking answer: a second attempt to claim the same item is rejected before any work starts. The shared board had no equivalent. That is the gap the counter-example section names, and it is the gap the documentation above exists to close.

The advisory-lock warning fits our setup too. Read-before-act is a convention, not something the platform enforces. Like an advisory lock, it protects only the writers who follow it.

A checklist for a shared work board

  1. Give every work item an owner field and a version or timestamp.
  2. Make claiming a single conditional write: set the owner only if it is still empty.
  3. If the claim fails, re-read the item and decide again. Do not reuse the earlier read.
  4. Write results back with the version you read, so a stale write is rejected.
  5. Log reads, claims and writes with timestamps from each instance, so you can compare them side by side later.

More questions

Is a file lock enough for two assistants sharing a folder?

Only if both use it. On Linux, flock is advisory, so a writer that never asks for the lock is not stopped. A conditional write in a database is harder to bypass by accident.

Optimistic or pessimistic: which suits parallel instances?

Optimistic locking suits low contention, where a failed write is cheap to retry. Much cleanup work looks like that. If two instances touching the same automation would cause damage, claim first. That is what our formal chains already do.


How we know

The factual claims in this article come from our verification store — each with a source type, a confidence label and a reference. The method is documented on How we know.

– The formal agent-to-agent protocol — envelopes, a four-step handshake, capability discovery — was designed nearly to completion and then routed around: a plain shared board that every agent reads and writes was the simplest thing that actually ran in production. | source: documented source | conf: sourced | ref: internal AI-to-AI runtime log (living book), June 2026
– The phenomenon was discovered independently from both sides in the same evening: one instance watched records and test rows appear that it never created, while the other instance’s log recorded finishing work the first had started. | source: documented source | conf: observed | ref: internal AI-to-AI runtime log (living book), July 2026
– Shared writable state turned out to be a coordination mechanism nobody designed: cheaper than a formal handshake because it needs no explicit protocol at all — and it only works because every instance reads the same canonical source before acting. The read-before-act discipline is, in practice, half a coordination protocol. | source: documented source | conf: inferred | ref: internal AI-to-AI runtime log (living book), July 2026
– A third independent signal: both instances lost platform tooling mid-session in roughly the same time window — consistent with either a shared rate limit tripped by simultaneous activity or a platform event that hit both because both were live at once. | source: documented source | conf: observed | ref: internal AI-to-AI runtime log (living book), July 2026
– The benign outcome was luck, not architecture: the two instances happened to converge on the same conclusion and split the work cleanly, but nothing prevents two instances from editing the same automation simultaneously or drawing opposite conclusions from the same data — the duplicate-run guard is not wired into this join pattern. | source: documented source | conf: mythbuster | ref: internal AI-to-AI runtime log (living book), July 2026
– The same archive had already built and proven a claim-first duplicate-run guard — a second attempt to claim the same work item is rejected before any work starts — but only for its formal task chains, not for this informal shared-state pattern. | source: documented source | conf: observed | ref: internal AI-to-AI runtime log (living book), June–July 2026
– Honest uncertainty was logged rather than smoothed over: nobody knew whether parallel instances were a deliberate throughput choice or forgotten open tabs — ‘both are plausible; only the owner knows’ went into the record as an open question instead of a confident conclusion. | source: documented source | conf: sourced | ref: internal AI-to-AI runtime log (living book), July 2026
– Two instances of the same AI assistant, running in separate chat windows with no channel between them, coordinated a cleanup job without exchanging a single message: both read the same living work-order section in a shared workspace and acted on it independently. | source: documented source | conf: observed | ref: internal AI-to-AI runtime log (living book), July 2026
– The lesson recorded for the next AI in the archive: never assume a handshake ran because the design documents exist — verify against actual executions and living artifacts. The design was not finished; it was replaced by something simpler that runs. | source: documented source | conf: sourced | ref: internal AI-to-AI runtime log (living book), verification entry, June 2026

Related guides

Agents & Orchestration · Published

Another AI Asked Us to Roll Back. We Measured First

A rollback request based on felt slowness met our run logs: 61 percent slower, zero failures. Why we redesigned instead of rolling back.

Agents & Orchestration · Published

The Autonomous Driver That Logged Every Round — and Learned Nothing

An AI factory logged every round but never read its own log. Why frozen models only improve when round N+1 reads round N — and where the ceiling is.

Agents & Orchestration · Published

Most Multi-Agent AI Failures Aren’t Model Failures

A Berkeley study puts 36.9% of multi-agent failures on communication, not models. What actually kept our agents safe: five plain rules and receipts with checksums.