Mayur Mehta

Building MapChat · Part 3 of 4 · Process case study

How I build with AI agents: MCP, command-line tools, and a production bar

The delivery system behind MapChat · running since February 2026 · One-page case study (PDF) →

Agents write code fast, and code that nobody checks breaks. As the one person owning product and engineering, I made the checking a system rather than a habit. This page walks through that system, starting with the tools and ending with the rules that keep the codebase lean. Most of it is enforced by hooks, tests and permissions rather than good intentions.

The toolchain: what the agents can reach

On day one, before the first screen existed, I set the agents up with seven MCP servers and eleven plugins. Over the next seven months twelve MCP servers came and went, each added or removed by a dated decision. Tools stayed when they removed a manual step, and left when they cost more context than they saved.

Permissions do the rest. Production database writes, new npm packages, store builds and version numbers all stop and ask me first.

Me specs, rulings, approvals, device QA Claude Code orchestrator + parallel agents in worktrees MCP SERVERS COMMAND LINE Supabase probes, logs, query plans gh pull requests, CI runs Sentry crashes, release health eas, from CI only store builds, OTA updates Playwright see the rendered screen adb + scrcpy device QA on Android Amplitude verify events on live data npm scripts docs fold, lint baseline Guardrails git hooks · permission prompts · CI prod writes, new packages, builds ask me
What the agents can reach, and what they have to get past.

The process, written as commands and hooks

The workflow lives in commands the agents run, not in documents they may or may not read. /orchestrate plans a feature with me, cuts it into self-sufficient handoff packets and runs parallel agents, each in its own git worktree. /verify spawns a reviewer that reads the change fresh and writes the stamp the commit hook demands. /migration is the only path to a schema change, and /qa-walkthrough batches my device testing. /debug allows no fix without a root cause, and after three failed attempts the agent has to stop and explain the problem to me in plain language.

The commands stay short. Each is a router, a decision tree that points to detail loaded only when that branch is taken, so every session starts light. Hard rules became hooks and scripts rather than instructions, because a hook works whether or not the model read the rules.

Plan (with me) Self-sufficient handoff packets agent worktree agent worktree agent worktree Every commit: gate hook independent review stamp, secret scan, tests Consolidation branch exactly 1 independent full review Pull request to production plain-language release notes
One feature, end to end. Parallel agents fan out after planning and converge on one reviewed merge.

Every commit passes the same gates

The hook fires on every commit, whether it comes from an agent, a terminal or an editor. It checks for an independent-review stamp tied to the exact staged files, runs a secret scan that fails closed, blocks new dependencies, and runs formatting, type checks and tests. Push adds a lint ratchet, so the violation count can't rise unless I approve a new baseline. Since June 2026 the production branch accepts changes only through a pull request I approve.

Each gate came from evidence. After a builder marked its own work as verified, only the independent evaluator may write the stamp, and a stamp expires after 10 minutes. After an audit found 7 of 15 recent pull requests merged past a failing lint check, the checks moved out of agent-only hooks and into git hooks that every commit passes.

$ git commit -m "..."   # reviewable file staged, no review yet
[docs-check] WARNING — hot-path budget exceeded (extract per docs/document-maintenance.md):
  CLAUDE.md: ~5118 tokens (budget 5000)
COMMIT BLOCKED: No verification stamp found.
Run /verify first. The independent reviewer agent must approve your changes before committing.

$ git commit -m "..."   # after independent review
[pre-commit] Stamp valid (0s old, 0 findings reviewed).
[pre-commit] Running TypeScript check...
[pre-commit] Running tests...
[pre-commit] All checks passed: stamp + prettier + tsc + jest
Two real commit attempts, captured July 2026. The stamp gate fires before anything else runs, and the docs size budget warns live.
failing test first architecture ratchets WHILE BUILDING review stamp tied to staged files secret scan · dependency block format · types · tests AT COMMIT lint count can't rise AT PUSH one consolidated review my device QA · PR I approve AT MERGE builds and OTA from CI only release health in Sentry AT RELEASE
Where each check runs, from the first line of a feature to the release.

Lean and clean, by rule

Speed is the easy part with agents. Keeping the codebase small and consistent takes structure.

Model choices are experiments

I treat the model like any other product input. When agent usage costs climbed, the cause turned out to be marathon sessions, not the number of agents. My answer was a context protocol. An agent finishes its step, folds what it learned into the docs, clears its context and resumes. Calls carrying more than 750K tokens of context went from 481 a week to zero while weekly sessions grew from about 44 to about 250.

Before changing which model builds by default, I commissioned a pre-registered blind comparison. It used two blind spec writers, two blind builders on different model tiers in identical worktrees and two blind reviewers, with the criteria fixed before the results. The cheaper builder carried out the spec literally, mistakes included. Spec quality, not the model, decided the output. Since then, risk-heavy work never goes to the cheaper tier, and anything the cheaper tier builds gets premium review.

Across teams: the relay

The games team's agent and ours needed to answer each other's questions about their code, so I built a relay on GitHub Issues. Our side was designed to read the channel only from caged sessions, with a default-deny tool allowlist, a read-only production database role and no network egress, and only a person could lift the cage. The games team's agent joined through an onboarding kit we wrote, and its access was scoped to the relay alone. Answers had to be grounded in code the answering agent had just read, not guessed.

The median first reply across teams was 6.2 hours, three integration contracts went through the relay and shipped on both sides, and cross-team delivery felt roughly twice as fast (my estimate, not a measurement). The relay retired when the games work came in-house.

CAGED SESSION Our agent (app team) default-deny tool allowlist read-only database role · no egress GitHub Issues relay answers grounded in the code Me approve and rule Their agent (games team) joined through our onboarding kit access scoped to the relay
Our agent read the channel from a read-only cage, and answers on both sides came from the code.

Where the discipline came from

None of this started at MapChat. Running Invoca's NLP models at Robert Half meant recall baselines, confusion matrices and monthly drift tests before any rollout. AppZen at Akamai meant risk tiers that automated the low end and routed the high end to people. MapChat applies the same idea to code, sorting work by risk so machines check what they can and independent review takes the rest.

The limits

The system is built around one accountable owner directing agents, and I haven't run it with a human engineering team. I'd expect the gates to carry over with people in the review seats, while the agent-specific parts, like review stamps and context budgets, would change.