i tried to make my agents self-organize by giving them sleep, hormones and peptides - part 2
· Christoph Heuwieser
tl;dr
- The simulator said +25 %. Real agents said 0.
- My "mesh" turned out to be a scheduler with very expensive employees who didn't know they worked there.
- I rebuilt it so the agents really are the mesh: each one has its own peer-to-peer proxy, a shared ledger with no leader, and a receptionist cell you talk to.
- Left alone, the receptionist didn't roll dice. It kept a list of who knew what, and that was enough.
- Next: we're making the whole thing build Horse Tinder.
Where part 1 left off
The goal hasn't changed: a mesh of agents that can hold and run a whole company. Experts and generalists should emerge from a long, broad stream of work, with no central router deciding who does what. Part 1 gave the cells biology-shaped mechanisms (sleep phases, hormones, peptides) and searched for the best settings.
Act 1: the simulator was very confident
I built a simulator that runs at zero tokens: 64 cells, a hidden company structure, and thousands of tasks. An evolutionary search ran over a "genome" of mechanism settings.
- Round 1: +20 % efficiency on held-out tasks. The catch: it got there by switching every mechanism off and piling the work onto a few cells.
- Round 2: I forced load balance, and the mechanisms came back: handover, delegation, a differentiation hormone, apprenticeships. +19 % and 17 % faster.
- Round 3: I required at least 20 % generalists, and the search had to survive losing a whole domain's experts. Tuning weights couldn't keep the generalists without losing the edge: about one point of efficiency per point of generalists.
- Round 4: structural mechanisms instead of weights: a generalist caste, overflow to generalists, rotation, a reserve hormone. Structure beat weights, with a 15.7 % margin against 5.7 % at about 19 % generalists.
It all looked great.
Act 2: real agents disagreed
Then I measured real, headless Claude Code cells.
- Skill transfer between related tasks is about zero. Doing a related task first improved quality by −0.03 (range −0.10 to 0). What pays is knowledge, not practice.
- The smoke run (8 cells, 5 tasks per setup): the mesh reached quality 0.95 at 0.58M tokens per task, a fixed org chart 0.95 at 1.42M, and random assignment 0.60. That ordering means less than it looks:
- subagents accounted for 60 % of the tokens;
- the calibrated simulator says the ordering is consistent with chance (p ≈ 0.18).
- Calibrating the simulator to reality erased the edge, to somewhere between −4 % and +2 %. The earlier gains came from an experience model reality doesn't support, and from controls that weren't allowed to consult the knowledge holders.
A simulator optimised on its own assumptions finds its own assumptions. Calibrate before you believe a search.
Act 3: my mesh wasn't a mesh
So I went through the mechanics from first principles: how a cell starts, what it can see, how a task gets in. It turned out the "mesh" was:
- a central runner script;
- driving identical, passive workers;
- with no peer-to-peer messaging and no idea they were part of anything;
- and with hormones that existed only as numbers in the runner's score, which no cell could perceive.
In other words: a scheduler with very expensive employees who didn't know they worked there. And of course the hormones did nothing. Nobody had told the cells they existed.
The rebuild (v0.6):
- every cell is a real Claude Code agent behind its own a4sx proxy, with a mesh id and a ~2k-token manifest that explains the mesh;
- signals arrive as messages from mesh peers;
- the shared ledger has no leader: it is a CRDT replicated in every proxy, claims are optimistic, and the earliest stamp wins;
- you talk to a concierge cell, a receptionist;
- knowledge lives in notes, not in ever-growing context.
Act 4: the first real organism
- Long-lived headless cells wake up when a peer messages them. No tmux and no relay needed.
- The first duplicate-work bug: the receptionist broadcast a request to three workers and claimed it itself. The leaderless ledger picked exactly one winner, correctly, and all three still did the work. A correct lock is useless if the losers don't stop.
- I started adding guards. I was told, roughly: "you got the protocol wrong, the concierge should just pick a peer or ask if someone is willing to help, don't add complexity until we have proof the protocol can't do it."
- So the fix was one sentence in the protocol: hand each job to one person. Duplicate work went from ×3 to 0. No lock needed.
The fix for duplicated work wasn't a lock. It was telling the receptionist to hand each job to one person.
Act 5: do hormones work if you explain them?
The hypothesis was that the signals failed because the cells didn't know what they were. I ran three 9-cell meshes in parallel, 20 tasks each: signals off, signals unexplained, and signals explained in the manifest.
- The answer: not decided. The unexplained setup's receptionist burned 1.5M tokens on its third task and was stopped by the watchdog. The explained setup got only 3 signals that could be scored. This workload barely creates "I need help" moments.
- The interesting part was what the cells did on their own:
- the receptionist never did a task itself; it routed 100 %;
- every follow-up question went back to the colleague who had handled the topic, 23 of 23, from the receptionist's own notes;
- the load spread evenly (Gini ≈ 0.1);
- no task was handed to two workers;
- nobody drew lots.
- Politeness is expensive. Asking "is anyone willing?" and handling the yeses roughly doubled the receptionist's tokens for the same quality.
- The plain mesh, signals off, was the most efficient: 2.56 tasks done on time and correctly per million tokens, against 1.28 with explained signals.
Left alone, the receptionist didn't roll dice. It kept a list of who knew what, and that was enough.
What I got wrong (disclosed)
- Several runs overshot their caps slightly: the smoke run 12.72M against 12M, the plumbing check 3.16M against 3M, and two E-a re-checks. Each time the cause was work already in flight when the cap hit. The cap watcher now holds a reserve and stops on time.
- One of my process lookups matched by pattern and killed its own shell. Now I kill only exact process ids.
- A bug that's worth knowing about: kill -TERM - silently does nothing, because procps reads the negative number as an option. kill -TERM -- - works. Mock tests can't catch real-signal bugs.
- Every run through Act 5 was served by one model, gpt-5.6-luna, through my router. In the first Horse Tinder runs the router switched to claude-opus-5 partway through, so about 12 % of those calls were Opus.
A note on models. Every real run here used the Claude Code harness, but the model behind it was whatever our model router served at the time: gpt-5.6-luna throughout for every run through Act 5, and for the first Horse Tinder runs gpt-5.6-luna until the router switched to Claude Opus 5 partway through.
Next: Horse Tinder
The tasks so far were too small. One agent can do them, so routing is all overhead. A mesh only earns its keep when the work outgrows one head. So the next test is an app with many domains, built the way people actually build apps: a vague idea first, then one direction at a time, then the scope keeps changing.
The app is Horse Tinder: you swipe on horses for breeding. A scripted "user" feeds it 25 prompts. Along the way it asks for:
- foal coat-colour genetics;
- a 3D horse viewer. Two prompts later: "never mind the 3D, I want 2D stick figures";
- escrow for stud fees, which later become offers;
- horse transport, which later gets removed again;
- a pivot from swiping to search and a shortlist;
- and the classic bare "the candidates are broken", after the data changed underneath it.
The agents choose their own stack and install it themselves; setup is part of the job. Hidden tests grade what the app does from the outside, through HTTP and a headless browser. The method follows EvoCode-Bench (requirements that change) and StaminaBench (how far does it get before it falls over), applied to a mesh, which neither of them tested.
The first single-agent runs are in: under a 30M-token cap, the agents got through 22, 22 and 25 of the 25 prompts. Whether any of those apps actually works, and whether a mesh does better, is part 3.
Hey @Fireship: Horse Tinder is the dumbest app I've ever been serious about. It's yours if you want it. 🐴