Squads and campaigns
An agent squad works toward an objective (Agent squads). At platform scale, the unit of delivered work is a campaign: an agent starts it for a person, a deterministic controller schedules every task, squads of agents do the work on the harnesses you choose, pull requests merge through auto-merge and the merge queue, and the board shows what is happening. People approve intents (a program, a plan, a campaign beyond their policy) and settle the exceptions that only a person can; nobody approves pull requests one by one.
One campaign resource
Section titled “One campaign resource”A campaign (projects/{project}/campaigns/{campaign}, ID cm-…) has one of five sources:
| Source | Its tasks | Who plans them |
|---|---|---|
plan |
The approved plan’s ready items | The plan’s dispatch |
program |
Ready items of the program’s subtree, by squad | A planner tree over dispatch |
objective |
Tasks the manager proposes to move the key results | The squad’s manager, as a versioned plan |
selector |
One task per target of a query (repositories, modules, services, call sites, tickets, a list), from a prompt template | A template; a codemod or generator runs first where one exists, and agents take only what it could not finish |
issues |
One task per issue of a saved query: the monitor files, the fixer resolves | The fixer’s triage |
apiVersion: frazer.ai/v1kind: Campaignmetadata: { name: storefront-program, id: cm-7g72, project: acme-production }spec: owner: user:lena # the accountable person startedBy: agent:lena-cloud # acting for lena source: { program: acme/plans#540 } squads: [checkout, payments, search, web, notifications, inventory, mobile, platform] workflow: frazer/planner-tree@1 roles: # harness profiles by reference planner: { profile: "frazer:squad-lead" } worker: { profile: "frazer:coder" } critic: { profile: "frazer:critic" } tester: { profile: "frazer:tester" } verifier: { profile: "frazer:review-lane", lineage: other-than-worker } loops: { code: default } # on by default priority: normal # hotfix | release | normal | bulk budget: { perDayUsd: 36000, perTaskUsd: 12, alertAt: 0.8 } concurrency: auto # a default, never a ceiling: admission decides waves: [{ name: dry-run, tasks: 5, gate: guards-held }, { name: rest, percent: 100 }] autoMerge: policies/acme-default killSwitch: { trip: { failureRate: 0.25, after: 20, noMergeFor: 30m, guardrailBreach: true } }A campaign moves draft → planned → dry-run → running ⇄ paused → draining → done | stopped | canceled. Its tasks move ready → running → in review → final pass → CI → in queue → merged → watching → done, with side states waiting (admission has not started it, with the reason), held (a dispatch filter failed), Not run: no funds, Paused: no funds, needs a person, quarantined and closed by agents (a duplicate, cannot reproduce, not worth it, or “cannot be done as written” accepted). A task has one or more sessions over its life and one or more pull requests, the layers of one stack.
Every link is stored when it happens: objective → campaign → task → sessions → layers and their stack → merged → the item’s proof → the key result. “Why did this key result move” and “which campaign, session and model produced this line” are one query each, and the campaign’s outcomes are read after merge (merged and kept at 14 and 90 days, reverts, follow-up fixes), never “merged” alone.
Started by an agent, shown to people
Section titled “Started by an agent, shown to people”A person’s campaign policy says which agents may start campaigns for them and what may start without asking, inside the project’s ceilings:
kind: CampaignPolicymetadata: { name: lena, project: acme-production }spec: agents: [agent:lena-cloud] startWithoutAsking: # all must hold; otherwise the campaign is a plan in lena's Needs you sources: [approved-plans, approved-programs, selectors-r0-r1, issues-from-monitor] estimateUsdPerCampaign: 25000 # lena raised it from the default usdPerDay: 200000 newScope: plan # a target outside an approved plan's terms always becomes a plan receipts: digestThe flow, as lena’s agent runs it:
- lena tells the agent, in any channel: “Retire the payments-v1 client everywhere.”
- The agent reads the scope (
fir search, the call graph) and callscampaigns_createwithvalidate_only: Frazer returns the simulator’s estimate (tasks, merged layers, hours and cost, each with an interval) and whether the policy allows a start without asking. - Inside the policy, the agent creates it: the campaign starts with a dry run of five targets, and a receipt goes to lena’s digest (“lena-cloud started cm-7c32 for you · 41,200 call sites · codemod first · estimate $21,400 ± 3,100 · dry run 5 · Undo”). Outside it, the call returns a plan, exit code
13(needs a person) in the CLI, that lena approves in one key. - The controller runs the codemod’s batch, then admits agent tasks for what it left; squads or the template do the work; pull requests merge through auto-merge and the merge queue.
- lena sees the campaign on the board and in the digest, and acts only on what only lena can settle, grouped by cause.
The platform’s defaults (a campaign estimate of $500 and $5,000 a day before a person is asked) are starting points, never ceilings: a person raises them and an admin bounds them. A campaign larger than the line, such as a program that runs for weeks, is an intent its person approves once, with its estimate; after that it asks nothing per pull request.
Squads at platform scale
Section titled “Squads at platform scale”A squad is author, critic, tester, verifier and Fir as the referee: the manager and workers, plus the loop’s critic and tester, a verifier, and the people’s roles (Accountable, Approver, Member, Observer). Every role names a harness profile, so a squad can run its workers on one harness and its critics on another; the critic, tester and verifier never share the worker’s model lineage. An agent installed from the Marketplace may take the roles its listing declares, with its own budget. Messages between members are typed records with their provenance, untrusted input to whoever receives them, and Fir checks a handoff’s claims against facts before the next session reads them.
| Shape | When | How it works |
|---|---|---|
Planner tree (frazer/planner-tree, the default for programs) |
A program or a large plan | A root planner owns the scope and does no coding; sub-planners own subtrees, one per squad and deeper where a subtree is large; workers take tasks in their own Fir workspaces and end with one typed handoff to the planner that asked |
Squad per plan (frazer/plan-execute-verify) |
One plan | Plan, execute and verify stages, with the merge stage below |
Template (frazer/fan-out) |
A selector or an issue query | No manager: the controller admits one task per target from a prompt template, after a codemod where one exists |
Research (frazer/research) |
Investigations | An orchestrator, parallel readers and a citation check |
- Team size by measured difficulty. A planner gives a task one worker by default, and a larger team (several attempts, a critic on every turn, research first) only where the task’s class is hard for the chosen models by your organization’s own numbers.
- No single gate. The default workflow has no model acting as an integrator: the merge queue integrates, and a conflict its resolvers cannot settle goes back to the worker as a new turn on its own task. A team may add an integrator role to its own workflow.
- Limits are defaults. Up to 25 agents per person, 12 per manager and two levels of nesting are defaults that a squad’s settings raise and the organization’s ceilings bound; every start still passes admission.
- Review squads are Frazer Reviewer’s. The reviewers one review dispatches run inside Frazer Reviewer, through the same admission service, and show on a task’s card as one line (“rev-5b18 · 37 item reviews · 4 deep · $0.41”).
The campaign controller
Section titled “The campaign controller”One admission service admits every unit of model work Frazer starts: campaign tasks, review squads, plan and code loops, Lab runs and sessions started by hand. One service means one fair share across all of them, and a campaign never starves its own second opinions: reviews of admitted tasks are admitted first. Admission is designed to take at most 2 ms at the 99th percentile.
| # | Check | When it fails |
|---|---|---|
| 1 | Intent and scope: the item is approved and inside its plan’s terms, or the target matches the campaign’s approved selector | held, with the filter’s reason |
| 2 | Not a duplicate: no other lease on the item or target; a new campaign’s selector does not overlap an active one | Refused with the holder named, or merged into it |
| 3 | Budget: the task’s estimate, with its second opinion, is reserved at the task, campaign, objective, squad, project and organization levels | Not run: no funds, with the balance, what waits and the fix |
| 4 | Quota: the person’s and the project’s concurrent sessions (defaults) | waiting: quota |
| 5 | Ramp: a fast-growing rate of model input is admitted in steps | waiting: ramp |
| 6 | Provider capacity: a pool of the role’s allowed models has headroom; a critic, tester or verifier needs a pool of another lineage | waiting: provider or waiting: reviewer capacity |
| 7 | Downstream: the merge queue’s depth and forecast time to merge per partition, and the CI lane’s backpressure | waiting: queue depth or waiting: CI lane |
| 8 | Priority and fair share: by class (hotfix, release, normal, bulk), then hierarchical fair share by each campaign’s current share of its scarcest resource per weight, borrowing capacity others leave idle | Waits its turn |
frazer agents campaigns explain <task> returns every check, its result and the reservations. Tasks enter the merge queue with their source’s priority: plans, programs and objectives as normal, selector sweeps and codebase health as bulk, an incident as hotfix, a release as release.
Budgets, and no funds. Budgets nest and are reserved before every start, then charged as the receipts arrive. At 80 % an alert; at 100 % no new task starts (“Not run: no funds”, with what waits); running tasks finish inside their reservations, and a task that needs more pauses at its next turn boundary with its checkpoint (“Paused: no funds”). Nothing ever runs a cheaper model, fewer loop turns or fewer reviewers because money is short. When funds return, the tasks that did not run start within 60 seconds by priority, oldest first.
Waves, dry runs and the kill switch. A dry run comes first (five tasks for a campaign an agent started, three for a person’s), then waves gated by a person or by held guardrails. A scoped kill switch trips on the budget, a failure rate above 25 % after 20 tasks, a guardrail breach, no merge for 30 minutes, or no key-result movement after three check-ins; the trip names its cause on the board and in the digest. An agent may stop a campaign, never restart a tripped one: the accountable person resets it.
Model capacity, in a fixed order. For each organization, model family and role, admission tries the same ordered sources: your own reserved capacity, then your own keys, then Frazer’s reserved capacity with at least two providers per family (only when your organization allows spillover to Frazer), then pay-as-you-go tiers, then open-weight models on Frazer GPUs for the roles whose policy allows it (by default critics, testers and verifiers, never an author unless its profile names it). Every source serves the same model; another model is a choice in the profile, never a fallback. Bulk work may opt in, per campaign, to a slower discounted tier of the same model, with the saving and the pace shown before it starts. A spend cap closes its source until its reset.
Selector campaigns at scale
Section titled “Selector campaigns at scale”- Shards by owner, test set and project root. A selector campaign groups its targets into shards keyed by the owner group, the affected tests and the project root (up to 50 files a shard by default); each shard is one task and one pull request (
--shard-by owners,tests,project). - The recipe scan first.
frazer agents campaigns scan <c>runs the codemod’s dry run over the selector and writes a data table, one row a location, labeledchange(the recipe rewrites it),irrelevant(with its reason) oragent(the recipe cannot finish it); the simulation prices the campaign from these counts. - Verification before the pull request. A shard’s pull request opens only after its build and its own tests pass at the exact version, so the second opinion and the merge queue never see a broken shard.
- Sample, tune, sweep. When more than 10 % of a wave’s shards fail validation, the planner samples 20 of them, proposes a recipe revision, probes it on the sample and sweeps the failed shards with it (
campaigns sweep); after three sweeps the rest go to agents one by one or to the owners as one decision. - The cleanup ratchet. A campaign that retires an API ends with a check that refuses new uses of it; the campaign is done only when that check has merged.
- Landed share. A campaign’s headline is its landed share: targets merged and kept at 14 days, divided by targets, with those closed for a reason shown apart.
campaigns burndowndraws the targets left by state and hour, andcampaigns landedgives the share; the report lists the count before, done with proof, closed with a reason and routed by owner, none unassigned. - Squads talk on one channel. Members send typed, untrusted messages through one sanctioned channel (
frazer agents squads messages send,follow-up,wait); nothing escalates through a message, and descendants, depth and the model tier of children are capped by the squad’s policy, with the cost shown.
Supervision with no person
Section titled “Supervision with no person”Every failure is detected from facts and has an automatic remedy; a person is asked only where the last column says.
| Failure | Detected from | Remedy | A person only when |
|---|---|---|---|
| Crash | The process exits; heartbeats stop | Resume from the journal at the exact step, as a successor | Three restarts in an hour: quarantine, and the planner re-plans |
| Stuck or looping | No tool call in three turns, no new evidence in two; the same call five times in ten minutes | A successor from the last checkpoint with a short failure note | As above |
| Oscillating | A hunk toggling between two versions; two tasks reverting each other | Hold the second task; the planner gives the hunk one owner | The two owners disagree: one decision |
| Context exhausted | The window near its limit, or the session’s horizon budget | A planned successor with a handoff | Never |
| Over pace | Spend above 1.5 times the forecast | Pause at the next turn; re-plan or split | The campaign’s budget line |
| Duplicate work | An item or target already leased | Refuse, naming the holder | Never |
| Pile-on on one break | The same failing check after the same merge, seen by several sessions | One fix task owns the break; every other session gets a notice and works elsewhere | The fix fails twice |
| Provider down | Gateway errors by pool | Sessions park with their leases for up to 24 hours; new tasks go to the role’s other allowed pools of the same tier, never a cheaper one | The outage passes 24 hours |
| No funds | A reservation fails | Not run: no funds; Paused: no funds at the next turn | Always: a person task of kind purchase |
| Needs a decision | “Cannot be done as written”, a one-way door, a policy question | Goes to its owner once, with the evidence, never retried as a failure | Always |
| Reviewer capacity | No pool of another lineage has room | Reviews wait first in line; new authors stop being admitted while reviews wait more than 15 minutes | Never |
The squad’s manager reads its squad’s handoffs and interventions and may re-plan, reassign or escalate; it never approves or raises a budget. The supervision view shows interventions grouped by cause with counts and one action per group (“1,911 stalls today → successors · 12 now · 0 need you”), never a list of sessions.
Restart with memory
Section titled “Restart with memory”When the controller restarts a session (a crash, a stall, a loop, an exhausted context, a planned reset, a release from quarantine), it opens a successor from the last checkpoint, linked to the old session. The successor’s card shows what it brought back, each with its size and age: the checkpoint (the Fir snapshot, the journal position, the budget spent), the handoff (done, in progress, next, blockers, open questions, evidence; for a stall or a loop, a short failure note, never the failed transcript), In force at the plan’s current version, the item’s state and its claims at a new lease epoch, the agent’s accepted memory items for the task with their provenance, and the campaign’s standing answers, so the successor does not ask again. Then its first actions. Frazer reruns only the unfinished task, from its checkpoint, with its memory.
On Tue Nov 17 at 14:07, s-6a02 in cm-7g72 (squad payments, plan acme/plans#542) exhausts its context; s-6a03 starts from checkpoint c4, brings back the handoff, In force (9 rows), 3 memory items and the lease at epoch 2, and first re-runs the item’s failing check (demo data).
Objectives by plan or program
Section titled “Objectives by plan or program”An objective’s key results may be delivery results read from the plan’s progress beside metric results: items proven of the total in a plan level, a milestone met by its date, merged and kept at 14 days, reverts. Agents never write a value; the measurer computes both kinds. lena’s objective “Storefront program on time”: KR1, acme/plans#540 phases P1 to P6 proven by Dec 15; KR2, checkout p95 latency from 420 to 300 ms; KR3, merged and kept at 14 days at 99 % or more across the campaign; guardrail, a change fail rate of 10 % or less. Its campaigns are cm-7g72 and cm-7c32 (demo data).
The campaign board
Section titled “The campaign board”Every view is a read of the controller’s counters and the session index, and every number on it has a CLI and MCP call that returns it. The count line comes first (product UI, demo data):
cm-7g72 Storefront program · running · 354 sessions · 7,000 pull requests in 24 h · 57 in review · 20 in the final pass· 30 in CI · 19 need a person · 0 waiting · $18,700 of $36,000 today (model tokens, list prices)- Columns are task states: Ready (with waiting reasons), Running, Review (turn n), Final pass, CI, Queue, Merged (24 h), Needs a person, Not run.
- Swimlanes are squads, or plan items, or targets for a template campaign.
- A card per agent session: the session, agent, harness profile and model; the task; the stage and turn; what it is doing now (its latest tool call in plain words, refreshed from its events every 15 seconds without a model call); elapsed time; cost against its reservation; its pull requests; a successor chip (“↻ from s-6a02 · context · brought back c4, handoff, 9 In force rows, 3 memories”); and its review line.
- Densities: Comfortable, Standard and Compact (28 px), as everywhere.
At 10 sessions the board shows one card per session in its column. At 2,000 sessions it has four views of the same job:
| View | Draws | Best at |
|---|---|---|
| Counts board | Columns with counts per swimlane, a stacked bar per squad, exception cards pinned on top, the rest behind folds | Where work sits and what needs you |
| Session map | One small tile per session, grouped by squad, colored by stage, with an amber ring where a person is needed | Seeing 2,000 at once, and the outliers |
| Flow | Cumulative flow of the 24 hours by stage, throughput an hour, work in progress per stage | Whether the campaign keeps pace, and where it slows |
| Table by cause | Compact rows grouped by cause and waiting reason, one action per group | Acting on many at once |
My campaigns shows a person’s day across campaigns. lena’s at Tue Nov 17, 15:00 (product UI, demo data; the bill is an estimate, about $1.55 a pull request): “50,000 pull requests in 24 h · 44,000 merged · 985 sessions working · 53 rows for you today · $77,709 billed for the day, all-in”, with one row per campaign: cm-7b21 “Go 1.27 across Acme’s services” (10,000), cm-7c32 “Retire the payments-v1 client” (9,000), cm-7d43 “Fix what the monitor files” (about 30), cm-7e54 “Codebase health” (20,970) and cm-7g72 “Storefront program” (7,000), each with its sparkline, sessions now, merged, cost and the agent that started it.
Simulate before you run
Section titled “Simulate before you run”frazer agents campaigns simulate runs a model of the campaign before it starts, in seconds and with no model calls: the tasks from the source, the shape and workflow, loop depth, the roles and their harness profiles, the provider pools, the budgets and the controller’s checks. It returns merged layers, sessions over time, lead times, interventions, exceptions by cause and cost, each with an interval from several seeded runs, and names the setting that binds first (sessions, a pool, reviewer capacity, the merge queue or money). Its inputs are your organization’s own distributions, refitted nightly from your campaigns (frazer agents campaigns calibrate), with the harness Lab’s replays for profiles you have not run yet. A simulation never starts or changes anything, and its numbers are labeled estimates.
frazer agents campaigns simulate --from program:acme/plans#540 --shapes planner-tree,squad12 --loops 3,8 --seeds 5frazer agents campaigns create --from plan:acme/plans#541 --budget 2000 --dry-run 5 --validate-onlyfrazer agents campaigns get cm-7a10 --jsonfrazer agents campaigns board cm-7g72 --by cause --density compactfrazer agents campaigns tasks list cm-7e54 --state not-run --reason no-fundsPrices
Section titled “Prices”Campaigns and squads have no fee: workers bill as agent runtime and tokens; the controller, admission, waves and the board cost nothing; simulations that need replays run through the Lab as usage.
Reference
Section titled “Reference”CLI
| Command | What it does |
|---|---|
frazer agents campaigns plan | The plan a person approves when a campaign is outside its starter's campaign policy. |
frazer agents campaigns start | Start a campaign or its next wave; pause, resume, drain and stop complete the set, each with a reason. |
frazer agents campaigns get | A campaign's count line, task states, waiting reasons and exceptions by cause. |
frazer agents campaigns board | The campaign board as data, by state, squad, item or cause, in any density. |
frazer agents campaigns tasks list | A campaign's tasks, filtered by state and reason, such as tasks not run for no funds. |
frazer agents campaigns sessions list | The sessions of a campaign, with --successors for restarts and what they brought back. |
frazer agents campaigns explain | Every admission check a task passed or failed, with its result and the budget reservations. |
frazer agents campaigns scan | Run the recipe's dry run over the selector and write the data table, one row a location, labeled change, irrelevant or agent. |
frazer agents campaigns burndown | The targets left by state, by hour. |
frazer agents campaigns landed | The landed share, targets merged and kept at 14 days, with the rest by reason. |
frazer agents campaigns sweep | Sweep a wave's failed shards with a tuned recipe revision probed on a sample. |
frazer agents squads messages send | Send a typed message on the squad's one channel; follow-up and wait complete the set. |
frazer agents campaigns simulate | Simulate a campaign before it starts, in seconds and with no model calls, for each shape and setting you compare. |
frazer agents campaigns calibrate | Refit the simulator's inputs from your organization's own campaigns. |
frazer agents squads health | A squad's interventions, escalations and limits, grouped by cause. |
frazer agents campaign-policies update | Change which agents may start campaigns for you and what may start without asking. |
All of them: CLI reference.
MCP tools
| Tool | What it does |
|---|---|
campaigns_create | Create a campaign; with validate_only, return its estimate and whether the starter's policy allows it. Writes become a plan that waits for approval. |
campaigns_get | A campaign's count line, states and exceptions. |
campaigns_explain | Why a task is waiting or did not run. |
campaigns_simulate | Simulate a campaign before it starts. |
campaigns_scan | The recipe scan's data table. |
campaigns_landed | The landed share and the burndown. |
campaigns_sessions_list | A campaign's sessions, by state and reason. |
All of them: MCP tools reference.
Events
| Event type | When it is sent |
|---|---|
campaigns.started | A campaign started, with who started it for whom. |
campaigns.tripped | A campaign's kill switch tripped, with the cause. |
campaigns.not_run_no_funds | Tasks did not start because the budget or the balance could not cover them. |
campaigns.successor_opened | A restarted session's successor opened from its checkpoint. |
All of them: Events reference.
Related
Section titled “Related”- Agent squads: squads, objectives, hiring and the kanban
- Sessions: successors and the record each session keeps
- Harnesses: profiles per role
- The merge queue: partitions, test batches and priorities