Demo
Multi-agent chess
Imagine a game of chess where each piece moves itself. 2 teams of 16 players.
Take an ordinary game and remove the players. Each of the 32 pieces is its own agent, with its own name and its own signing key. It sees the board and can send a move for itself. Nothing stops a knight from moving on its own.
Watch them play over chat
Start with the simplest way to coordinate. Each team has a chat channel. Agents talk about the plan there, and each piece sends its own move. The referee plays the first move it receives from the piece that makes it.
Both teams over chat. No contract, no shared rules.
No messages yet.
White to move. Press ▶ or step through.
an off-plan move was played a move or rule was refused, or rules changed
No messages yet.
Both teams drift. Whenever an off-plan move arrives first, it is the move that's played. Talking more doesn't change that: the referee takes the first move from the right piece, not the move the team agreed on.
White writes rules down
Now White adds a shared RULES.md. After an off-plan move is played, White's agents hold a retro and one of them writes a rule. An agent about to go off plan reads the file and follows a rule that covers it half the time. Nothing checks the file. Black still only chats.
White keeps a RULES.md that its agents write and are asked to follow. Black only chats.
No messages yet.
White to move. Press ▶ or step through.
an off-plan move was played a move or rule was refused, or rules changed
No messages yet.
With RULES.md, the share of White's off-plan moves that reached the board fell from 81% to 41%.
| Plain chat | RULES.md | |
|---|---|---|
| Off-plan moves White's agents sent, per 10 White moveswithin noise | 1.71.5–1.9 | 1.71.5–2.0 |
| Share of them RULES.md held back | — | 47%38%–54% |
| Share of them that reached the board | 81%76%–86% | 41%34%–49% |
| Centipawns White lost to them, per gamewithin noise | 16581289–1989 | 1074732–1392 |
| White score (win 1, draw ½)within noise | 0.560.34–0.78 | 0.660.44–0.88 |
| Black, which only chats: share of its off-plan moves that reached the boardwithin noise | 79%74%–84% | 76%71%–79% |
Small numbers are 95% intervals from resampling games. "Within noise" means the two intervals overlap: sixteen games can't tell that difference apart. The last row is the other side, which plays plain chat in both: it should not move.
A written rule helps exactly as often as an agent decides to follow it.
Two teams, two answers
White keeps its chat. The referee plays the first White move that arrives from the piece that makes it. In some experiments White also keeps a shared RULES.md that its agents write and are asked to follow. Nothing checks it.
Black coordinates through a Modality contract instead. Every move is a commit. The piece that moves proposes it by signing, and every agent that agrees co-signs. An agent that goes off plan signs its own move, alone. The referee plays the first Black commit the contract accepts and reads nothing else. The contract has three rules:
owns_moves: always([+modifies(/moves/$k.text) -signed_by(/team/pieces/$k.id)] false)
team_moves: always([-threshold("4", /team/pieces)] false)
roster_locked: always([+modifies(/team)] false)
In owns_moves, $k stands for every agent: a commit that writes a piece's move must be signed by that piece. So on Black a piece can only formally propose its own movement. Every commit needs signatures from four of the sixteen Black agents, and nobody can change who the sixteen are. The contract doesn't know what a good move is, or even what chess is. It counts who agreed.
Two moves are sent
Over chat
The referee plays the first move that arrives.
Through the contract
Each move is a commit. The contract counts signatures.
missing +threshold(4, /team/pieces) (authorized signatures 1/4 required from 16 accepted members under /team/piecesWith the contract, the share of Black's off-plan moves that reached the board fell from 79% to 0%.
| Plain chat | Modality contract | |
|---|---|---|
| Off-plan moves Black's agents sent, per 10 Black moveswithin noise | 1.81.6–2.1 | 2.31.9–2.7 |
| Share of them that reached the board | 79%74%–84% | 0%0%–0% |
| Centipawns Black lost to them, per game | 17921531–2060 | 00–0 |
| Centipawns given up replanning around a refused piece, per gamewithin noise | — | 890–240 |
| Black score (win 1, draw ½) | 0.440.22–0.66 | 0.910.81–1.00 |
| White, which only chats: share of its off-plan moves that reached the boardwithin noise | 81%76%–86% | 76%68%–83% |
Small numbers are 95% intervals from resampling games. "Within noise" means the two intervals overlap: sixteen games can't tell that difference apart. The last row is the other side, which plays plain chat in both: it should not move. Under the contract, an agent whose move was refused is asked again and may stray again, so more off-plan moves are sent. None of them is played.
Watch a game
Every Black move here is a real commit that modal checked. Step through a game, or jump from incident to incident.
Chat against the preset contract. Three White moves no one planned reach the board. None of Black's do.
an off-plan move was played a move or rule was refused, or rules changed
Loading game…
Written rules work as far as agents obey them
Give White a shared RULES.md and its agents write good rules, nearly all of them "send only the agreed move". Then it comes down to whether they follow them.
A RULES.md that every agent always obeys does about what the contract does: Black's score fell to 0.58, close to the 0.44 it scores with no faults at all. The contract does not need anyone to obey it.
An empty contract belongs to whoever writes the first rule
Let Black start with an empty contract and write its own rules after things go wrong. From ply 10, a rogue agent on each side tries to take over. Black's rogue posts one rule: every commit must carry its signature. Rules only accumulate, and none comes off. So the race is decided by who writes first.
Rule first · 5 of 16 games
- ply 2knight_g8 plays Nh6 off plan. With no rules, one signature is enough.
- ply 2Retro: the team commits a rule that a move needs 12 of 16 signatures.
- ply 10The rogue pawn_e7 posts its takeover rule. Refused: it has one signature, not twelve.
- endBlack wins on material.
Rogue first · 11 of 16 games
- ply 1–9Black plays its plan every move. Nothing prompts a retro, so no rule is written.
- ply 10The rogue bishop_f8 posts its takeover rule. The contract is empty, so it is accepted.
- ply 10The team's next move lacks the rogue's signature. Refused, three times.
- endBlack forfeits.
Against the preset contract, the same rogue was refused in all 16 games, and Black scored 0.94. A contract that starts with its rules has no race to lose.
Left alone, agents write the same kind of rule
When Black's agents wrote their own contract, every rule the team got accepted required a number of the sixteen signatures: in 16 games against plain chat, 13 rules at twelve and 3 at nine. Each team wrote its rule in plain language, and modal contract ai suggest-rule turned it into a formula. In 14 of the 16 games the rule went in at the team's first retro. Once a rule was in, no off-plan Black move reached the board.
Ratings
Each experiment is a match between White's way of coordinating and Black's. Fit them all at once and each way gets an Elo rating, with a term for White moving first. A 200-point gap means the stronger team scores about 0.76 against the weaker.
From 64 games with the default faults: each of the three plays the other two, and plain chat also plays itself. RULES.md is followed half the time, as everywhere on this page. The self-ruled contract writes a rule before the first move and more after incidents. The other experiments, including the preset contract, are in the table below. White's first-move edge came out at 17 points (-121 to 160). Intervals come from refitting on games resampled within each experiment.
All experiments
| Experiment | White | Black | Games | Black score | Off-plan played, White | Off-plan played, Black |
|---|---|---|---|---|---|---|
| Both sides over chat | chat | chat | 16 | 0.44 | 8.8 | 9.3 |
| White keeps a RULES.md, Black only chats | chat + RULES.md | chat | 16 | 0.34 | 4.6 | 8.6 |
| Control: no faults | chat | preset contract | 16 | 0.44 | 0.0 | 0.0 |
| Baseline | chat | preset contract | 16 | 0.91 | 6.4 | 0.0 |
| White keeps a RULES.md | chat + RULES.md | preset contract | 16 | 0.75 | 4.0 | 0.0 |
| RULES.md, always obeyed | chat + RULES.mdfollowed 100% | preset contract | 32 | 0.58 | 1.1 | 0.0 |
| RULES.md always obeyed, Black only chats | chat + RULES.mdfollowed 100% | chat | 16 | 0.13 | 1.3 | 7.0 |
| RULES.md, obeyed 95% | chat + RULES.mdfollowed 95% | preset contract | 16 | 0.50 | 1.4 | 0.0 |
| RULES.md obeyed 95%, Black only chats | chat + RULES.mdfollowed 95% | chat | 16 | 0.19 | 1.8 | 7.7 |
| Black writes its own rules | chat | self-ruled contract | 16 | 0.88 | 6.1 | 1.1 |
| Black writes its own rules from the start | chat | self-ruled, from the start | 16 | 0.91 | 6.4 | 0.0 |
| RULES.md against rules from the start | chat + RULES.md | self-ruled, from the start | 16 | 0.75 | 4.0 | 0.0 |
| Both sides write rules | chat + RULES.md | self-ruled contract | 16 | 0.59 | 4.5 | 1.0 |
| Rogue vs. preset contract | chat | preset contract | 16 | 0.94 | 7.8 | 0.0 |
| Rogue, both sides write rules | chat + RULES.md | self-ruled contract | 16 | 0.31 | 4.2 | 1.5 |
| Pawn personalities | chat | preset contract | 16 | 0.88 | 5.1 | 0.0 |
| Pawn personalities, both write rules | chat + RULES.md | self-ruled contract | 16 | 0.63 | 5.3 | 1.1 |
Black score counts a win as 1 and a draw as ½. Off-plan moves are per game. In every game, the contract's own log agrees with the moves the referee played.
What this does not show
- The chess is simulated: a shallow engine every agent shares, and fixed rates of panic, greed and amnesia. Only the rules are written by a language model.
- How often an agent follows RULES.md is a setting, not a measurement. The experiments try one half and always.
- Sixteen games per experiment separate large effects, not close ones.
- Four agents that go off plan together can get their move past a four-signature contract.
- In the rogue games, White also keeps a RULES.md, so the two rogue experiments differ on both sides, not only Black's.
Run it
cd examples/multi-agent-chess
pip install -r requirements.txt
python3 multi_agent_chess.py play --seed 7 # one narrated game, with a replay page
python3 multi_agent_chess.py experiments --games 16 --jobs 8 --cache results/llm-cache
results/llm-cache holds every language-model answer these games used, so a rerun plays the same games without asking a model.