Inspiration

Every engineering team has the same messy chore: a backlog of subtasks that depend on each other. The expensive mistake is not writing the code. It is picking the wrong thing to build next.

A paper by Geng and Neubig on asynchronous software engineering agents measures exactly that. Two runs on the same repository, the same model, differing only in which files got assigned, scored 8.7% and 34.3%. The delegation decision dominates the outcome.

So we built the delegation decision as an agent, gave it real work, and put everything it does on a dashboard — including the parts where it would be easy to lie.


What it does

The factory takes a written build plan and turns it into parallel, test-gated work.

A manager agent on Google ADK, running gemini-3.7-flash, reads the dependency graph and decides what goes out. Each engineer works in its own git worktree on its own branch, runs the tests for the area it touched, and commits. The manager merges to one trial branch, one at a time, and retests after each merge.

In a measured run it built five subtasks in about a minute. It left the sixth alone: subtask 7.3 states a dependency on four subtasks from another phase that are not part of this run, and the dashboard says so rather than building something that cannot work yet.

The workload is real. Plinkie is a price-comparison system we operate on Google Cloud, and the backlog the factory builds is its Phase 7, written weeks before the factory existed.


How we built it

The manager is an agent; the machinery is not. LlmAgent with six FunctionTools: read the graph, read what the human pointed at, delegate, poll, merge, finish. Merging, the guardrail check, the retest and the bookkeeping are ordinary code. A model decides what goes out; it never decides whether a merge may land.

The guardrail runs on the diff, not in the prompt. Some paths must not be touched by an engineer — the build plan itself is the sharpest case, because it holds every checkbox and a running total. Before every merge the manager runs git diff --name-only and checks each path against a list in werkwijze/config.json. One match ends the run. It is never asked of the model, because an agent that can argue its way past its own guardrail does not have one.

The log separates reported from measured. What an agent says about itself is rich, early and untrustworthy: one that has lost track will report progress that is not there. What git says is thin, late and impossible to fake. Every line on the dashboard carries its source, and two of the warnings fire exactly where the two disagree.

The dashboard is a separate process. Node, no dependencies, server-sent events. It shows the build plan with the reason beside every blocked subtask, each engineer's measured git state, the warnings, and the log. A recorded run of it is deployed on Cloud Run.


Challenges we ran into

Isolation is not concurrency, and only the timestamps said so. The engineers had their own branches and their own worktrees. Everything looked right. Then a log comparison showed engineer one finishing at 15:22:02 and engineer two starting at 15:22:03 — they had been running one after the other the whole time. The engineer loop was synchronous, and nothing in the design, the dashboard or the tests had an opinion about it. Engineers now run in their own threads; merging stays sequential, which is the paper's design and not an omission.

The build plan carries the tasks but not the order. The manager was supposed to derive the dependency graph from the plan. In 1,300 lines with 115 open subtasks, exactly one states its dependency in a form a machine can read. The order lives in the head of whoever wrote it. So the edges are stated by hand, per run, and the builder refuses a run where a subtask has no entry: an empty list means "checked, independent", a missing entry means "nobody looked".

The guardrail held and the run did not stop. With the scripted manager, one forbidden path ended the run. With the ADK manager driving, the same violation was refused three times in a row while the agent kept retrying — the gate was right, the consequence was missing from that code path.


Accomplishments we are proud of

The three failures above were all found by the log, not by the tests. That is the design working: the whole point of separating what an agent claims from what git records is to make exactly this kind of mistake visible.

A guardrail that also reports when it finds nothing. It used to log only on a clean check, which meant it was invisible precisely when it mattered. It now writes a line before every merge, so the dashboard can show that it ran four times in a run where nothing went wrong.

A demo you can reproduce without a Google Cloud account. make werkwijze-proef runs the whole loop with scripted engineers: real worktrees, real commits, real tests, no model and no cost.


What we learned

Where a rule lives decides whether it is a rule. In a prompt it is a request. On the diff it is a gate.

Silence is not success. An agent that stops reporting looks exactly like an agent that is working. Every warning we built comes from asking what silence could mean.

Documents drift from code faster than you expect. Preparing this submission surfaced three places where our own design documents promised more than the build delivered — a queueing behaviour that was never built, eight warnings of which four exist, and a language gate that lived only in the documentation. All three are corrected in the repository, with the correction dated.


What's next

The engineer role is an interface with a second implementation already written: JulesEngineer, which talks to Google's Jules API and would run each engineer in its own Google Cloud VM. It has never been executed — no API key configured, no session ever created — and nothing in this submission rests on it. Running it is the next step, and it is the one that turns "written" into "demonstrated".

Beyond that: moving the manager itself to a scheduled cloud agent. The role is already defined as a prompt plus a state contract rather than as a session, so the move is a wake-up, a bucket and a service rather than a rewrite.## Inspiration

Built With

Share this project:

Updates

Submission history