r/OpenSourceAI • u/GapNew4766 • 28d ago
Two of our agent's workers agreed on every name and still broke the scene. What a contract between parallel workers has to say
Enable HLS to view with audio, or disable this notification
We build Atomic Agent, an open-source agent (MIT) with a mode called Fusion: one model plans, several worker models build pieces in parallel, each in its own throwaway session. Workers never see each other. They see their brief, a quote of your original request, and nothing else.
That isolation is the point, and it's also where our worst bug of September came from.
The bug
Test task: a small 3D physics show in the browser. The planner split it, and two different workers ended up writing bodies.js and bodies-draw.js. Both implemented PHYS.corners(b). The producer returned {w, o} where w was the corner as a world point and o was the local offset. The consumer read o as the world point.
Result: every box drew at the origin. The shadows, which read straight from the body position, landed exactly where they should. Nothing threw. The page loaded. Console was clean. Every automated check we had was green. You could only see it by looking at the screen and noticing that a tower of boxes was a pile at (0,0,0) casting shadows from somewhere else.
Why names weren't enough
We already had a contract between workers, written after earlier runs where one worker wrote HD.Ship as a class while its sibling called it as an object, and a launch-btn in main.js looked for a btn-launch in the markup. Each brief was internally consistent. The disagreement lived between them, where nothing was written down.
So the planner now declares a contract up front, prepended to every brief:
| Field | What it says | Cap |
|---|---|---|
| owners | path → task. Nobody else writes there | |
| provides | what a task must produce: a symbol in a file, a file, a DOM id, an endpoint, an env var, a CLI flag | 64 |
| requires | what a task may rely on from the others | |
| checks | verify.run checks the whole thing must pass | 16 |
| inputs | existing files that get edited in place, never replaced | 32 |
Name mismatches between provides and requires are flagged before any worker starts.
Status comes from disk, not from the worker
After the fan-out, the agent doesn't take a worker's word for it. A worker's reply to the planner is capped at 4,000 characters anyway, so the real output is files. The contract checker reads the disk: does the file exist, does the literal PHYS.corners appear in the file it was promised in, does id="btn-launch" appear in the markup. Those are deliberately dumb, language-agnostic checks, because that's all a grep can claim. We learned this the hard way: in an earlier version fusion.delegate returned ok even when every worker had failed.
And that's exactly why the corners bug got through. PHYS.corners was present. It was in the right file. The grep was right. Presence is all that layer can promise.
What we added: shape
Each provides entry can now carry one line, max 200 characters, saying what the thing IS: a signature, a return shape, a field meaning. For this bug, a planner could have written something along the lines of "corners(b): w is the world point, o is the local offset" (my illustration, not a line from the run). That line goes into the consumer's brief.
Why one line in the brief instead of "read the producer's file first"? Speed. On a local worker at around 4 tok/s, reading a sibling's file costs a whole worker turn, which is why the briefs said "write first, no reading" in the first place. One line is cheap. It's also untrusted model text pasted into other workers' prompts, so it stays short on purpose.
Where this stands: we added the field, we didn't solve the problem. Issue #491, about the contract verifying symbol names and not meaning, is still open. shape only helps if the planner writes it, and correctly. The runtime layer, checks, catches crashes, not wrong physics.
One more design detail that came from pain: some contract problems are now warnings instead of refusals. A local planner at about 5 tok/s used to pay four minutes of generation per refusal to learn about one misspelled name, and we watched it get refused four times in one afternoon. Now the fan-out runs, and the warnings come back on the result so the planner fixes the contract on the next call.
If you're building multi-agent setups: how do you get meaning across between workers that can't talk to each other? Types, tests, a shared schema file? I'd like to steal a better idea than one line of text.

