Case study

Multi-agent dispatcher - atomic tasks from brief to PR

Eighty staff across four offices, twenty-plus active client engagements at any moment, hundreds of small decisions a week. The cost shows up in two places - engineer attention is fragmented all day, and the small-but-constant rate of dropped balls erodes client trust. We built a multi-agent dispatcher: a Planner that breaks each brief into atomic tasks, a Scout that picks the next dispatchable one, an Orchestrator that routes each task to the right model class, and an Executor that opens the PR. The engineer reviews. The bet is on the 90% the engineer does not start from scratch on, not on the dream of zero-edit autopilot.

Tasks dispatched / week

180-240

across active clients

Brief-to-PR · routine

~12 min

atomic-task workflow

Per engineer, weekly

~10h

reclaimed

Last updated:

01. The problem

Per-engineer context-switch tax

Outsourcing firms run at the intersection of "many concurrent clients" and "short cycle times." For their engineers, every working day is a parade of context switches: which client's repo, whose conventions, whose locked decisions, which tickets still open from last Tuesday. The cost shows up in two places - engineer attention is fragmented all day, and the small-but-constant rate of dropped balls (a follow-up missed, a ticket lost, a question that never got answered) erodes client trust.

The firm had tried Jira workflows, dedicated PMs, and weekly cross-client standups. The PMs reduced dropped balls but added a layer of latency to every decision. The engineers wanted to go directly from "task brief" to "PR open" without writing tickets that described what they were about to do.

This is the same multi-agent pattern we ship for everything else. The reason the firm gets disproportionate value from it is that the per-engineer context-switch tax is highest in their shape of work.

The Brief

A dispatcher the engineer drives, that knows the same conventions the engineer knows, that ships the routine work and surfaces the interesting decisions. A multi-agent system, scoped strictly, where every action lands in a pull request a human reviews.

02. The stack we built

Four agents around a state file

The architecture is four agents around a state file the engineer can read at a glance.

  • Planner

    Reads brief task notes from a per-client task directory. Breaks each brief into atomic tasks - one objective each, 5-30 minutes of work, a verifiable acceptance-criteria list per task. Output is a versioned set of task files with strict YAML frontmatter: id, dependencies, target project, model class, timeout, max iterations, allowed-tool list. The graph is wide rather than deep - non-dependent tasks fan out in parallel.

  • Scout

    Reads the task state file, picks the next task whose dependencies are all `completed`. Runs on a small local model - single-digit-billion parameters - so the heavy compute is reserved for actual work, not queue logic.

  • Orchestrator

    Routes each picked task to the right runtime by complexity. See routing rules below.

  • Executor

    A headless agent loop running ONE task at a time. Reads the task file, reads the project-context file, executes the implementation steps in scope, runs every acceptance-criteria check, opens a PR with a written description, pings the responsible engineer in Slack. Strict scope discipline - never edits files outside the task's file list, never refactors "while it was here," never pushes to main, never deploys. Every acceptance criterion gets a PASS or FAIL line in the result before status flips to `completed`.

Orchestrator routing

Routes each picked task to the right runtime by complexity:

  1. Stateless file edits

    Typo, config, search/replace, docs, CSS - go to a local open-weights model running on hardware we own and operate. No shell, no Bash. Free at the margin.

  2. Tasks that need shell access

    Install, build, test, multi-file edits with verification - go to a frontier reasoning model on subscription. Bash allowed, scope-limited to the task's `allowedTools` list.

  3. Architecture-shaped work

    Five-plus files, schema changes, security boundaries - gets the larger reasoning model with a higher iteration budget.

The split is not about price. Every runtime here is fixed-cost for the firm. The split is about capability - the local runtime is faster and never bills, but it does not run shell commands.

Supporting layers

Per-client context layer

Each client engagement carries a `project-contexts/<client>.md` describing the architecture, conventions, gotchas, and locked decisions specific to that client. The Executor reads this file on every task - not just at the start of a session. Cross-client contamination is enforced at the routing layer; the Planner planning Client A never reads Client B's state.

State file

A single JSON file is the source of truth: per-task status (`pending` / `running` / `completed` / `failed` / `skipped`), timestamps, file artefacts produced, and the structured PASS/FAIL on every acceptance criterion. The engineer reads it at a glance; the Scout reads it to pick the next task; replays read it to debug a task months later.

Approval gates

The Executor opens a PR. A human reviews. A human merges. The system never auto-merges, never deploys, never messages a client. Each task is bounded by `timeout` (kill switch) and `maxTurns` (loop cap); an Executor that hits its iteration cap fails the task cleanly rather than retrying for hours.

Observability

Per-client throughput, PR-merge rate, queue depth, time-to-PR distribution, rejection-rate trend. Dashboards segment by project and runtime - the firm sees which client engagements lean heavily on the frontier track and which run almost entirely on the local one.

03. Implementation

Four phases - pilot, context, routing, hardening

  1. Shipped
    01Phase 1 · Single-client pilot (first month)

    Stood up Planner + Scout + Orchestrator + Executor against a single client engagement the firm had already scoped. Validated that the Executor produced PRs the engineer was happy to merge after light edits. Strict scope discipline took two iterations to land - early Executors helpfully refactored adjacent files. A diff-size limit per task plus a tighter prompt fixed it.

  2. Shipped
    02Phase 2 · Per-client context (months 2-3)

    Added the project-context layer. PR-merge-rate jumped immediately once the Executor knew each client's conventions, stack, and locked decisions. Same pattern as long-term agent memory - context the agent reads on every call, not relies on having "learned".

  3. Shipped
    03Phase 3 · Multi-client routing (months 3-4)

    Planner picks up a heterogeneous task queue across all active engagements and produces a concrete week-plan ranked by priority. Cross-client memory was sharded after the Planner, in one debugging session, recommended an architecture from one client to another.

  4. Shipped
    04Phase 4 · Operational hardening (ongoing)

    Strict schema validator at the Planner's output boundary, diff-size limits on the Executor, per-client cost tagging, and an approval-policy preset per client (some accept feature-branch pushes; others require PR-only). Added a `dryRun` task type that outputs the plan without modifying files - useful for high-stakes tasks where the engineer wants to read the plan before the Executor moves.

Friction we hit

  • Scope drift. Early Executor would clean up an adjacent file "while it was here". A diff-size limit + a strict prompt instruction (Execute ONLY what the task says, nothing more, nothing less) pulled it back into scope.
  • Cross-client contamination. A Planner once referenced one client's locked architecture in another client's plan. Sharded the state per project; each Planner now reads exactly one client's directory.
  • Planner output drift. JSON-shape quality drifted week over week. A schema validator at the boundary now rejects bad outputs and re-runs with a stronger prompt.
  • Acceptance-criteria mismatch. Executor early on would mark a task complete with a soft "looks good" rather than a verifiable check. Hardened to require PASS/FAIL per criterion before status flips to `completed`.
  • Per-client cost tagging. Initially one big bill across all engagements; couldn't attribute to client work cleanly. Per-project tagging in the Orchestrator made monthly client invoicing trivial.
04. The numbers

180-240 tasks dispatched per week, ~12 min routine brief-to-PR

Tasks dispatched / week
180-240
Tasks shipping without human edit
~40%
Tasks needing edits before merge
~50%
Tasks rejected outright
~10%
Avg brief-to-PR - routine
~12 minutes
Avg brief-to-PR - complex
~45 minutes
Engineering-time reclaimed / engineer / week
~10 hours
Active per-client contexts maintained
20+

The honest middle row - 40% ship clean, 50% need edits, 10% are wrong - is the realistic outcome of agent-based code editing in 2026. The bet is on the 90% the engineer does not start from scratch on, not on a fantasy of zero-edit autopilot.

AI that already runs

Want this dispatcher pattern for your team?

Multi-agent dispatch is one of the highest-leverage automations we ship. A 30-minute diagnostic covers your engineering shape, your bottlenecks, and whether the pattern fits.

Live · powered by Gemma-4 · running on our hardware in Sofia