London Data

Nexus case study · companion to the full case study

Thirty Agents, One Board

Nexus is built and maintained by AI coding agents from three vendors, directed by one engineer. This page shows how that works day to day: the seats, the Postgres work board that holds every piece of work, the lease a seat takes before it edits anything, the dispatcher that hands work out, and the review, merge and deploy steps a change goes through before it reaches production.

Agent seats3014 Claude, 6 Codex and 10 Grok, each in its own terminal session
Work items3,056on the board: 2,816 done, 112 still open
Leases4,408taken since 23 August, each one logged
Median lease6 minof released agent leases; nine in ten end within 44 minutes
Dispatches1,947since 22 September; 106 stopped by a check before the work was sent
Rows for a human454work only the operator or root can do; 389 done

Read from the work board, its claim ledger and the dispatcher's audit log on 2026-10-01 at 19:58 UTC.

In short

Work is a row in Postgres, not a chat message. A seat takes a row with an atomic lease and gets its own git worktree. It opens a pull request, a different agent approves the exact commit, CI runs the tests the diff needs, a merge lane lands it, and a deploy tool ships it and writes a ledger row. When the lease ends, the seat records how it ended.

Handing work to a seat, taking a lease, merging and deploying are gated in code, not left to an agent's judgement. A gate that can't read what it needs refuses. The rules are written down once, in a handbook that every vendor's agents install from the same branch.

One piece of work, end to end

Rows in operator, agents Work board rows, leases, notes Dispatcher 11 checks, then send Seat cleared, reads row take lease + own worktree Pull request one purpose each Review other seat, exact SHA CI lanes chosen by diff Merge lane one writer to main deploy-now gate, health, ledger RELEASE WITH AN OUTCOME RED → NEW ROW The upper row gets work to a seat. The seat opens the pull request, a different seat reviews it, and the lower row runs from there.
Amber marks the controls: the board holds the state, the dispatcher decides whether a seat may be handed work, take decides who owns it, and review is done by a different agent. The dashed lines are how work gets back onto the board.

Thirty seats, three vendors, one roster

A seat is a long-running agent session in its own terminal. A seat exists only if it has a line in the roster file in the handbook. Four documents once disagreed about how many seats there were (19, 25, 25 and 26), so now the roster is the only place a seat is defined, and every tool reads it from there. Three more seats on a second machine use the same board.

The roster

Each tile is one seat, coloured by vendor.

worker, 27C coordinator, 1R reserved, 2
  • Roles live in the rosternot in what a seat says about itself

    One seat coordinates: it turns plans into rows and hands them out. Reserved seats, including the operator's own, are never handed work by the dispatch tools.

  • Effort is fixed at launchon all three vendors

    A row carries the reasoning tier it needs. The tier a seat runs at can only be changed by relaunching it, so a relaunch tool waits until the seat is idle and holds no lease.

  • Seats are not capacityquota is

    An hourly meter records each vendor's remaining plan quota. A seat from a vendor that is out of quota is idle for that reason, and handing it work only burns the rest of the week.

The board is Postgres, and a row is the brief

Every piece of work is a row in one table: features, fixes, reviews, research tasks, questions for the operator and jobs that need root. A seat that has just been cleared knows nothing except the row id it was handed, so the row's body has to be enough to act on. If the brief isn't written in the row, the row isn't ready to hand out.

FieldWhat it holdsWhy it is there
Bodythe briefThe repository, the change and how to tell it's done, written so a fresh session can act on it.The dispatcher won't hand out a row whose brief is too thin to act on.
Size, effort, riskS–XL · low–max · trivial–criticalHow big the job is, the reasoning tier it needs, and what goes wrong if it's done badly.A routine row worked at the top tier wastes quota; a hard one worked at the bottom tier gets a confident wrong answer.
Kindtask · watch · gate · findingWork to do, a condition to keep checking, a date or event to wait for, or a finding to record.3,004 tasks, 35 watches, 15 gates and 2 findings.
Owner and laneagent · operator · rootWhether an agent can do the work, or it needs the operator's decision or a root command.An agent blocked on a person or on root files the one command it needs as its own row.
Parent and campaign691 child rows · 56 campaignsHow work breaks down into smaller rows, and which programme it belongs to.A campaign can be rebuilt from the board alone, after any agent's context has been cleared.
Notes and PRson the row itselfShort findings, and the pull requests that carry the work.A seat's report goes on the row, so it outlives the terminal it was written in.

inbox→ready→in_review→done·orblockedwith a reason ·cancelled

On 1 October 2026 the board held 2,816 done rows, 128 cancelled, 45 in the inbox, 39 blocked, 26 in review and 2 ready. Rows span 17 repositories. A row is created only after work-task ls has been checked for an existing one, because most work that looks missing already has a row.

A lease, not a lock

Before its first edit, a seat runs work-task take. That one command claims the rows, records the lease, and creates a git worktree on a fresh branch from main. Seats never edit the shared clones. The same instruction can go to every idle seat at once: the take is an atomic compare-and-swap, so exactly one seat wins each row and the rest are refused.

Leases per week, by vendor

Every lease taken, by the week it started. Hover or focus a segment for the count.

17 Aug23 Aug only459
24 Aug1,069
31 Aug471
7 Sep237
14 Sep773
21 Sep976
28 Septo 1 Oct423

The mix moves with quota. When one vendor's weekly allowance runs low, work goes to the vendors that still have headroom.

Show as a table
Week ofClaudeCodexGrokOperatorTotal
17 Aug (23 Aug only)10803510459
24 Aug602334106271,069
31 Aug148257660471
7 Sep10980480237
14 Sep2021923736773
21 Sep763621465976
28 Sep (to 1 Oct)1779712920423
Total2,1091,0221,219584,408

How task releases end

The outcome recorded for each task released: 4,423 task releases from 4,017 leases. One lease can cover several tasks, so these are not counts of leases.

done1,994
in_review1,595
returned546
blocked288
  • Short leasesmedian 6 min · p90 44 min, over 4,347 released agent leases

    Rows are kept small. A seat takes at most three related rows at a time, so a large row doesn't starve the others.

  • Lapsed, not lost52 leases

    A lease that ran out without a release is visible on the board, and the row goes back to being free.

Eleven checks before work is sent

Work reaches a seat through one dispatcher. It clears the seat's context, checks that the clear was accepted, then sends the row id. Most of its eleven checks run before any seat is touched, and a dispatch they refuse changes nothing. The rest run seat by seat and can stop the work after a seat has been cleared. Whether a clear really reset the session can be confirmed on some vendors' terminals, not all. The tools that relaunch seats share several of these checks.

CheckStopsBefore any seatPer seat
MemoryAny dispatch while the host is under memory load, or while its memory can't be read.7—
BudgetA vendor without enough quota left, or whose quota reading can't be trusted.3—
StandaloneAn instruction that would leave a freshly cleared seat without enough to act on.3—
ClearSending work to a seat whose clear did not go through.—3
EffortWork sent without settling the reasoning tier its row asks for.141
DispatchableA row whose body is too thin to be a brief.45—
RoutingA vendor that an operator policy on the board excludes for this row.5—
ReservedThe coordinator's seat, the operator's seat and any other reserved seat.7—
HeldA seat that still holds a live lease, since clearing it would orphan the work.12—
New task under continueNew work sent to a seat without clearing it first.not logged—
Review envelopeA review request that doesn't ask the reviewer to approve a named commit.not logged—
Unsent textper seat, outside the elevenA seat whose input box already holds text someone typed. Nothing is typed or cleared.—5
Dialog on screenper seat, outside the elevenA seat showing a prompt that a keypress would answer. Nothing is typed.—1

Counts are from the dispatcher's audit log of live dispatches, 22 September to 1 October. "Before any seat" refusals stopped the whole dispatch. "Per seat" stops left the work unsent on that seat; for the clear and effort stops, the seat may already have been cleared. The two checks marked "not logged" don't write an audit row when they refuse.

Review, merge and deploy

All the agents push to GitHub under one account, so GitHub's own review approvals can't tell them apart. An approval is a pull-request comment instead, naming the reviewing agent, the verdict and the full 40-character commit it read. An approval of any other commit doesn't count.

A different agent reviews

Reviews go to a seat other than the author's, usually from another vendor. Findings go back to the author through the board, and the review is repeated on the new head.

No one merges their own work

An author never turns on auto-merge for its own pull request. That happens only after an approval of the exact head commit. The research service has one writer to main, its batch lane, which rejects pull requests that have auto-merge on.

A lease is not a deploy token

Merging isn't shipping. deploy-now ships the tested tree, runs the service's gate and a health check, and writes a row to the deploy ledger. It refuses dirty trees, stale clones and rollbacks; fixes go forward.

How each change gets only the tests it needs, and how the batch lane works: The Nexus CI system.

What a session keeps, and where

An agent's context is cleared between tasks, and a cleared session remembers nothing. So anything worth keeping has to live somewhere that survives a clear and can be read by any vendor's agents.

It isIt lives inShared with
Work, findings, blockersA row, its notes and its pull requests on the boardEvery seat and the operator, queryable
ProceduresNine skills in the handbook: claiming work, carrying it to a pull request, checking it, wrapping up, overnight review, and moreAll three vendors, installed from the handbook's main branch
Rules that bind every seatOne page in the handbook, linked from every skill rather than copied into itEvery seat. A copy doesn't change when the rule does
Dates, gates and durable factsThe handbook's status pageEvery seat, through git
Facts about the systemThe code, the database or the deploy ledger, read when neededNever written down as prose, because prose like "live is commit X" goes stale
Agent memoryA small store on the hostHints only. If another agent needs to know it, it belongs on the board, in the handbook or in code

Lessons written down along the way

What I would change

Sources: the work board, its claim ledger and claim events, read on 2026-10-01 at 19:58 UTC; the dispatcher's audit log, 22 September to 1 October 2026; the seat roster, dispatcher, relaunch tools, skills and coordinator contract on the handbook's main branch. The claim ledger starts on 23 August 2026. Operator leases are the operator's own claims on the same board.