Build · · 4 min read
Building a voice app with a team of agents
Chelar is a pantry app you talk to. You say “I took 5 rolls from the cellar and put them in the bathroom” and the stock moves from the cellar to the bathroom, for everyone in the family. It is built almost entirely by coding agents. Not one agent in a long chat, but a small team with fixed roles, each with its own rules.
The roles
- Architect. Read-only. For tickets that need it, it writes a short mechanism note before any code: how each write and retry works, what must stay true when events arrive twice or out of order, and which failures the tests have to show.
- Implementer. Works test-first, on its own branch, in its own copy of the repository. Its report maps every acceptance criterion to the test or flow that proves it, and lists what it is unsure about.
- Reviewer. Read-only. Checks the code against the project’s standards and against the ticket, and compares screenshots from CI with the design board.
- Security reviewer. Read-only, in parallel with the reviewer. Only access rules, authentication and privacy.
Neither reviewer is ever the session that wrote the code. A fix round starts a fresh implementer, and every finding gets a failing test before it gets a fix.
One ticket, start to finish
- A ticket with acceptance criteria, cut from a larger spec, with its dependencies linked.
- Checks before starting. For example: any screen the ticket touches must already exist on the design board.
- An optional design pass, then the implementer, then a pull request.
- Both reviewers in parallel. The implementer’s open doubts go to both of them to judge.
- Fix rounds until nothing above “low” is left, then CI must be green and the branch up to date before it merges.
At most two tickets run at once, and only when they share no tables, components or screens.
What three weeks looked like
From the first commit on 3 October to 23 October:
- 64 tickets went through the review loop, in 142 review rounds.
- Only 13 of them (20%) merged on the first review. The rest went back at least once; most needed two rounds, the worst five.
- Reviewers flagged 49 high or critical findings and 25 regressions before anything reached the main branch.
- About 100 merged pull requests and roughly 35,000 lines of TypeScript and SQL.
The 80% is the number I care about. An agent that writes code is fast and confident. A second agent that did not write it, with a narrow brief and the ticket in hand, is what makes the speed usable.
Tests carry the weight
About 120 test files: unit and component tests, plus database tests that check who may read which rows. On top of that, 17 end-to-end flows run on Android emulators in CI, split into two parallel chains, each with its own emulator and its own local backend. Speech recognition is replaced by a stub in those runs: it “hears” one fixed Romanian sentence, so the flow is tested without depending on a microphone.
Every merge to main applies database migrations, deploys the server functions and builds a signed Android package.
What went wrong
Early on, several screens were built from a written description or a rough mock instead of a finished design. The agents did what they were told, and the screens did not match the rest of the app.
The fix was a rule, not a better prompt: no UI ticket starts until its design board exists, both in the design canvas and as a frozen copy in the repository. Reviewers compare CI screenshots with that board, and an unexplained difference counts as a finding.
Recurring mistakes go into a pitfalls file, one line each. Implementers read it before writing code; reviewers treat it as a standard. One line from it: an undo message that scrolls off screen applies an action nobody saw, so anything with a countdown stays on screen or pauses.
What carries over to client work
The same shape works outside a household app. Before an agent writes code, decide what it may touch, what “done” means in tests, and who reviews it. Then let a different agent, and finally a person, check the work.
Next in this setup: scoring speech prompts against recorded voice clips before they ship. That is still a ticket, not a result.