# Agent Swarms

Several agents in one repository collide, duplicate work and overstate what they did; these features coordinate them and check their claims, for teams running many agents at once.

> **Beta, early access.** A workspace without access gets `403 FEATURE_EARLY_ACCESS` and a link to request it.

When several agents work in one repository at once, they pick the same migration number, edit the same files, break each other's call sites and report work they didn't do. These features coordinate the swarm and check what agents claim.

For the controls that apply to a single agent (guard, pause, memory, provenance), see [Agent Controls](/docs/agent-controls). Every command is in the [CLI Reference](/docs/cli), every endpoint in the [API Reference](/docs/api-reference), and every MCP tool is in the [MCP server](/docs/mcp). Most swarm tools appear only when their flag is on; the Approvals, agents, lessons review, contracts and test database management tools are always listed, and the API refuses them while the flag is off.

| Feature | Flag | Commands | MCP tools |
|---------|------|----------|-----------|
| [Claims](#claims) | `swarm_claims` | `bumpkit claim`, `claims`, `renew`, `unclaim` | `claim`, `renew_claim`, `release_claim`, `list_claims`, `next_migration` |
| [Conflict prediction](#conflict-prediction) | `conflict_prediction` | `bumpkit intent` | `declare_intent` |
| [Merge planning](#merge-planning) | `merge_planning` | `bumpkit merge-plan` | `merge_plan`, `merge_notifications` |
| [Verified agent reports](#verified-agent-reports) | `verified_reports` | `bumpkit agent-report`, `bumpkit coverage upload` | `report_work` |
| [Internal contract alerts](#internal-contract-alerts) | `contract_alerts` | `bumpkit contracts` | `contract_alerts` |
| [Flaky test registry](#flaky-test-registry) | `flaky_tests` | `bumpkit test` | `test_triage` |
| [Per-agent test databases](#per-agent-test-databases) | `test_isolation` | `bumpkit testdb` | `test_database_lease`, `test_database_release` |
| [Swarm lessons](#swarm-lessons) | `swarm_lessons` | `bumpkit lessons`, `bumpkit recall` | `lessons`, `propose_lesson` |
| [Has this been tried?](#has-this-been-tried) | `tried_before` | `bumpkit tried` | `has_this_been_tried` |
| [Approval inbox](#approval-inbox) | `approval_inbox` | `bumpkit inbox` | `inbox_list`, `inbox_approve`, `inbox_deny`, `inbox_batch` (gate and paused-command items are refused: a person decides those) |
| [Agent budgets and scopes](#agent-budgets-and-scopes) | `agent_budgets` | `bumpkit agents usage`, `spend`, `violations` | `agents_usage`, `agents_spend`, `agents_violations` |
| [Agent track records](#agent-track-records) | `agent_track_records` | `bumpkit agents records` | `agents_records` |
| [Fix tasks](#fix-tasks) | `close_the_loop` | `bumpkit loop` | `fix_tasks` |

## Identify each agent

Swarm commands record which agent and run did something. Pass `--agent` and `--session` on each command, or set them in each agent's environment:

| Variable | Read by |
|----------|---------|
| `BUMPKIT_SESSION` | `bumpkit claim`, `renew`, `unclaim`, `intent` |
| `BUMPKIT_AGENT_ID` | `bumpkit claim`, `claims --mine`, `renew`, `unclaim`, `intent`, `agent-report`, `contracts sync`, `testdb lease`, `lessons propose`, `agents spend`, `gate`, and the `guard` and `pause` hooks |

`BUMPKIT_AGENT_ID` is the canonical name. `BUMPKIT_AGENT` is accepted as an alias.

Without a session, the CLI uses this host and shell. The MCP server uses its own session ID, so pass the same `session` when you renew or release a claim from MCP.

## Claims

> **Beta, early access.** A workspace without access gets `403 FEATURE_EARLY_ACCESS` and a link to request it. Flag: `swarm_claims`.

A claim is a lease on a resource. An agent claims a migration number, file, symbol, route, feature flag key or env var before it uses it, renews the claim while it works, and releases it when done.

```bash
bumpkit claim migration
bumpkit claim path services/orders/helpers_test.go --ttl 2h --note "new test helpers"
bumpkit claim symbol coord.newRepo
bumpkit claims --kind migration
bumpkit renew CLAIM_ID --ttl 1h
bumpkit unclaim CLAIM_ID
```

| Kind | Resource |
|------|----------|
| `migration` | A migration number. With no number, Bumpkit hands out the next free one |
| `path` | A file path |
| `symbol` | A symbol, as `pkg.Func` |
| `route` | A route, like `GET /v1/x` |
| `flag` | A feature flag key |
| `env` | An env var name |
| `other` | Any name |

| Flag (`bumpkit claim`) | Default | Meaning |
|------|---------|---------|
| `--ttl` | `30m`, or `24h` for `claim migration` without a number | How long the lease lasts before it must be renewed |
| `--dir` | `db/migrations` | The migrations directory, for `claim migration` |
| `--note` | none | Why you need it, shown to other agents |
| `--agent` | `$BUMPKIT_AGENT_ID`, or `cli` | Who holds the lease |
| `--session` | `$BUMPKIT_SESSION`, or this host and shell | Which run of the agent |
| `--repository` | The origin remote | `owner/name` |

`bumpkit claim migration` counts the numbers in your local migrations directory and in other agents' claims, then holds the next free one for you. With the GitHub App installed on the repository for your workspace, it also counts the numbers on main and in open branches and pull requests; without the App, those are skipped.

If someone else holds the resource, the API answers `409` with code `CLAIM_HELD`, the `holder`, and a free `alternative` when there is one. `bumpkit claims --mine` lists only your claims.

Only the agent and session that hold a claim can renew or release it. To release another agent's claim, use a key created by a workspace owner or admin; the claim records `released by <email>`. Any other key gets `403 FORBIDDEN`, and the refusal is written to the audit log as `claim.release.denied` (or `claim.renew.denied`).

| Endpoint | What it does |
|----------|--------------|
| `POST /v1/claims` | Claim a resource |
| `GET /v1/claims` | List active claims |
| `POST /v1/claims/migration` | Claim the next free migration number |
| `POST /v1/claims/{id}/renew` | Extend a claim |
| `POST /v1/claims/{id}/release` | Release a claim |

The MCP `claim` and `next_migration` tools take `ttl_seconds` (default 1800 for `claim`, 86400 for `next_migration`; at most 86400).

## Conflict prediction

> **Beta, early access.** A workspace without access gets `403 FEATURE_EARLY_ACCESS` and a link to request it. Flag: `conflict_prediction`.

Before an agent starts or pushes work, it declares the paths and symbols it will touch, or its branch. Bumpkit compares them with open pull requests, active claims and other agents' intents, and reports overlapping hunks, the same new files, changed signatures of what it calls, and same-named symbols in the same package, with evidence.

```bash
bumpkit intent --paths services/orders/reserve.go --symbols orders.Reserve
bumpkit intent --branch feature/checkout-v2
bumpkit intent
```

| Flag | Default | Meaning |
|------|---------|---------|
| `--paths` | none | Files or directories you will change |
| `--symbols` | none | Symbols you will change, as `pkg.Func` |
| `--calls` | none | Symbols your change calls |
| `--adds` | none | Symbols you will add |
| `--branch` | none | Your branch, compared once it is pushed |
| `--base` | `origin/HEAD` | With no `--paths`, `--symbols` or `--calls`, the CLI reads your branch's changes since this ref |
| `--ttl` | `2h` | How long other agents see this intent |

`bumpkit intent` exits 1 when it predicts a conflict. The MCP tool is `declare_intent`; the endpoints are `POST /v1/intents` and `GET /v1/intents`.

## Merge planning

> **Beta, early access.** A workspace without access gets `403 FEATURE_EARLY_ACCESS` and a link to request it. Flag: `merge_planning`. Needs the GitHub App.

`bumpkit merge-plan` orders the repository's open pull requests so the ones with the fewest overlaps merge first and stacked pull requests follow their base, with the reason for each position.

```bash
bumpkit merge-plan
bumpkit merge-plan --recheck
```

With `--recheck`, each waiting pull request is merged with main using `git merge-tree` and checked for signatures main changed that it uses. Bumpkit also re-checks waiting pull requests whenever main moves, and reports the result on the pull request, to your outbound webhook as the `pull_request.recheck` event, and to agents polling `merge_notifications`.

| Endpoint | What it does |
|----------|--------------|
| `POST /v1/merge-plan` | Build the merge plan, optionally re-checking now |
| `GET /v1/merge-plan/notifications` | Re-check results, filtered by `agent`, `branch` and `since` |

## Verified agent reports

> **Beta, early access.** A workspace without access gets `403 FEATURE_EARLY_ACCESS` and a link to request it. Flag: `verified_reports`.

An agent's summary says tests pass; the report checks it. `bumpkit agent-report` sends an agent's claims about a commit. Bumpkit checks each one against GitHub checks for that exact SHA, coverage uploaded by CI, and the real diff, and answers `verified`, `contradicted` or `unverifiable` per claim.

```bash
bumpkit agent-report --tests-pass --diff-coverage 100 --lint-clean --no-migrations
bumpkit agent-report --sha 4b7a1d2... --file services/orders/reserve.go --coverage 87.5
```

| Flag | Claim |
|------|-------|
| `--tests-pass` | The tests pass (`--tests-pass=false` claims they fail) |
| `--coverage` | Total coverage percent |
| `--diff-coverage` | Coverage percent of changed lines |
| `--lint-clean` | Lint is clean |
| `--file` | A file the commit changes (repeatable; claims the exact set) |
| `--files-count` | The number of files changed |
| `--migration` | A migration the commit adds (repeatable) |
| `--no-migrations` | The commit adds no migrations |

| Flag | Default | Meaning |
|------|---------|---------|
| `--sha` | `HEAD` | The full commit SHA the claims are about |
| `--base` | The pull request's base, else the parent | Where the change starts |
| `--pr` | The pull request GitHub Actions is running for | Pull request to comment on |
| `--agent` | `$BUMPKIT_AGENT_ID` | The agent making the claims |
| `--branch` | The current branch | Branch |
| `--repository` | The origin remote | Repository |

The report's verdict is `contradicted` if any claim is, else `unverifiable` if any claim is, else `verified`. The command exits 1 when any claim is contradicted, so an orchestrator can trust the exit code instead of the agent's summary. `unverifiable` usually means CI hasn't produced the evidence yet: push and let CI run first.

### Upload coverage from CI

Coverage claims are checked against a Go coverage profile CI uploads:

```yaml
permissions:
  id-token: write
steps:
  - run: go test -coverprofile=cover.out ./...
  - run: bumpkit coverage upload --profile cover.out
```

Inside GitHub Actions with `id-token: write`, the upload carries the job's OIDC token, so Bumpkit knows the profile came from CI for that repository and SHA, not from an agent. Bumpkit computes total coverage, and diff coverage against each report's diff.

| Flag | Default | Meaning |
|------|---------|---------|
| `--profile` | `cover.out` | The Go coverage profile |
| `--sha` | `HEAD` | The commit the profile measured |
| `--diff-percent` | none | Diff coverage as measured by CI, trusted only with an OIDC token |
| `--no-oidc` | `false` | Upload with the API key only |
| `--repository` | The origin remote | Repository |

| Endpoint | What it does |
|----------|--------------|
| `POST /v1/reports` | Submit a report: `repository`, `sha`, `base`, `branch`, `pull_request`, `agent`, `claims` |
| `GET /v1/reports` | List reports |
| `GET /v1/reports/{id}` | One report with each claim's `status`, `evidence` and `source` |
| `POST /v1/coverage` | Upload a coverage profile |

The MCP tool `report_work` takes the same claims and posts the result on the pull request when you pass `pull_request`.

## Internal contract alerts

> **Beta, early access.** A workspace without access gets `403 FEATURE_EARLY_ACCESS` and a link to request it. Flag: `contract_alerts`.

When a push changes the signature of a Go function, method or type, open branches that call the old signature are alerted with the old and new signature and their call sites, by pull request comment, webhook and MCP.

Run `bumpkit contracts sync` on every push, in CI or by an agent. It records the signatures this branch changed or removed, and the ones its changed lines call. Alerts for this branch are printed.

```bash
bumpkit contracts sync
bumpkit contracts alerts
bumpkit contracts ack ALERT_ID
bumpkit contracts close --branch feature/old
```

| Command | What it does |
|---------|--------------|
| `sync [--base REF] [--branch] [--owner] [--pr]` | Record this push's signature changes and calls. `--owner` defaults to `BUMPKIT_AGENT_ID`, else this API key |
| `alerts [--branch] [--all]` | List alerts for a branch; `--all` includes acknowledged ones |
| `ack ALERT_ID` | Acknowledge an alert once the call sites are updated |
| `close [--branch]` | Stop tracking a merged or abandoned branch |

The MCP tool `contract_alerts` takes `branch`, `all` and `repository`. Call it before you push and again before you merge. Endpoints: `POST /v1/contracts/sync`, `GET /v1/contracts/alerts`, `POST /v1/contracts/alerts/{id}/ack`, `DELETE /v1/contracts/branches`.

## Flaky test registry

> **Beta, early access.** A workspace without access gets `403 FEATURE_EARLY_ACCESS` and a link to request it. Flag: `flaky_tests`.

Bumpkit tracks test results per CI run and commit. A test that passes and fails on the same commit is marked flaky. When tests fail, triage says whether each failure is known flaky or likely real, with history.

```bash
go test -json ./... > results.json
bumpkit test upload --file results.json
bumpkit test triage --file results.json
bumpkit test triage --test services/orders.TestReserve
bumpkit test flaky
```

| Command | Flags |
|---------|-------|
| `upload` | `--file` (JUnit XML or `go test -json`), `--format` (`junit` or `go-test-json`, detected by default), `--run-key` (default `GITHUB_RUN_ID`), `--attempt` (default `GITHUB_RUN_ATTEMPT`), `--sha`, `--branch`, `--repository` |
| `triage` | `--file` or `--test` (repeatable), `--format`, `--sha`, `--repository` |
| `flaky` | `--limit` (default 100, max 500), `--repository` |

Each failing test gets the verdict `known_flaky` or `likely_real`. `bumpkit test triage` exits 1 when any failure is likely real, and 0 when every one is known flaky. Re-run known flaky tests instead of changing code for them.

The MCP tool `test_triage` takes `tests`, `sha` and `repository`. Endpoints: `POST /v1/tests/runs`, `POST /v1/tests/triage`, `GET /v1/tests/flaky`.

## Per-agent test databases

> **Beta, early access.** A workspace without access gets `403 FEATURE_EARLY_ACCESS` and a link to request it. Flag: `test_isolation`.

Each agent run gets its own Postgres database, so agents never share test data.

```bash
export DATABASE_URL=$(bumpkit testdb lease --agent "$BUMPKIT_AGENT_ID")
go test ./...
bumpkit testdb release NAME
```

The CLI and MCP server create the database themselves from these variables in the agent's environment. Bumpkit records each lease and enforces the quota.

| Variable | Meaning |
|----------|---------|
| `TEST_DB_ADMIN_URL` | Connection URL of the test Postgres server |
| `TEST_DB_TEMPLATE` | The template database each lease is created from |
| `TEST_DB_ALLOWED_HOSTS` | Comma-separated hosts allowed as the test server. Bumpkit refuses any other host |
| `TEST_DB_MAX_LEASES` | Local cap on active leases (default 20) |

Bumpkit only ever creates or drops databases named `bk_lease_*`. A workspace holds at most 20 active leases.

| Command | What it does |
|---------|--------------|
| `lease [--ttl 1h] [--agent]` | Create a database and print its URL. `--ttl` is between 1m and 24h |
| `list` | List the workspace's leased databases |
| `release NAME` | Drop a leased database now |
| `sweep` | Drop every expired leased database on the test server |

MCP tools: `test_database_lease` (`agent`, `ttl_minutes`, default 60) and `test_database_release` (`name`). Endpoints: see [Test database leases](/docs/api-agents#test-database-leases).

## Swarm lessons

> **Beta, early access.** A workspace without access gets `403 FEATURE_EARLY_ACCESS` and a link to request it. Flag: `swarm_lessons`.

A lesson is a repository-wide rule every agent follows. Any agent can propose one; only a person can approve it. Each lesson has a kind, the paths and areas it applies to, and a version.

| Kind | Use it for |
|------|------------|
| `practice` | How work is done here (the default) |
| `pitfall` | A mistake agents keep making |
| `decision` | A choice the team made |
| `dropped` | Something the team chose not to build |

```bash
bumpkit lessons propose "Every migration runs inside a transaction; never edit a migration that already shipped." --kind pitfall --path db/migrations --area migrations
bumpkit lessons list --status pending
bumpkit recall --path db/migrations
```

A person reviews the proposals:

```text
bumpkit lessons approve LESSON_ID
bumpkit lessons reject LESSON_ID
bumpkit lessons retire LESSON_ID --reason "We moved to online schema changes."
```

| Command | Flags |
|---------|-------|
| `propose TEXT` | `--kind` (default `practice`), `--path` and `--area` (repeatable), `--supersedes LESSON_ID` |
| `list` | `--path`, `--area`, `--status` (`approved` by default, or `pending`, `retired`, `superseded`, `rejected`, `all`) |
| `approve LESSON_ID`, `reject LESSON_ID` | none |
| `retire LESSON_ID` | `--reason` (required, 10 to 500 characters, kept with the lesson) |

How lessons work:

- **Agents get them at session start.** `bumpkit recall` and the session start hooks print approved lessons first, and the `lessons` MCP tool returns them. Pending, rejected and retired lessons never reach agents. Recall carries at most 20 lessons and about 4,000 characters of lesson text.
- **People approve.** A key can't approve a lesson proposed with a key of the same person, or with a key that was since deleted, and a key that isn't tied to a person can't approve anything (`403 FORBIDDEN`). The dashboard inbox and a teammate's key can.
- **Versions.** `--supersedes` proposes a new version in the same lineage. Approving it supersedes the old one. Retiring a lesson needs a reason.
- **Duplicates.** Proposing the same text again returns the existing lesson.
- **Who proposed it.** The proposer's name comes from `BUMPKIT_AGENT_ID`, then `BUMPKIT_AGENT`.

MCP tools: `lessons` (`path`, `area`, `repository`) and `propose_lesson` (`body`, `kind`, `paths`, `areas`, `supersedes`, `repository`).

| Endpoint | What it does |
|----------|--------------|
| `POST /v1/lessons` | Propose a lesson: `repository`, `body`, `kind`, `paths`, `areas`, `proposed_by`, `supersedes`. Returns `201` |
| `GET /v1/lessons` | List lessons, filtered by `repository`, `path`, `area` and `status` |
| `POST /v1/lessons/{id}/approve`, `/reject` | Approve or reject a proposal (a person's key) |
| `POST /v1/lessons/{id}/retire` | Retire a lesson: `reason` (a person's key) |

`GET /v1/memories` also returns `lessons` when the flag is on. An unknown `supersedes` ID answers `404 LESSON_NOT_FOUND`; approving, rejecting or retiring an unknown ID answers `404 NOT_FOUND`.

## Has this been tried?

> **Beta, early access.** A workspace without access gets `403 FEATURE_EARLY_ACCESS` and a link to request it. Flag: `tried_before`.

Before building something, an agent or a person describes it, names the paths and symbols it touches, or both. Bumpkit searches the repository's release history for what happened last time.

```bash
bumpkit tried "realtime websocket notifications" --path services/notify --symbol Stream
```

| Evidence kind | What it found |
|---------------|---------------|
| `revert` | A matching commit that was reverted |
| `removed_feature` | Files that were added and later deleted |
| `removed_api` | A removed API or breaking change |
| `decision` | A `decision` or `dropped` [lesson](#swarm-lessons) |
| `gate_block` | A past gate block |
| `release` | A related release |

Each result links to its release page and, for GitHub repositories, the commit. With the [findings only and ephemeral retention modes](/docs/data-handling), commit subjects aren't stored, and with ephemeral, commit authors aren't either. Reverts are still found by commit hash.

The MCP tool is `has_this_been_tried` (`query`, `paths`, `symbols`, `repository`). The endpoint is `POST /v1/tried` with `repository`, `query`, `paths` and `symbols`; it returns `query`, `tried`, `summary` and `evidence`.

## Approval inbox

> **Beta, early access.** A workspace without access gets `403 FEATURE_EARLY_ACCESS` and a link to request it. Flag: `approval_inbox`.

One inbox for everything that waits for a person: gate decisions that need approval or failed, [paused agent commands](/docs/agent-controls#pause-risky-commands), [pending memories](/docs/agent-controls#memory-approval) and [lesson](#swarm-lessons) proposals. Each item has a risk score: low, medium or high. In the dashboard it is the Inbox, with filters for releases, agent commands and context. Releases whose pull request is merged or closed, or that have a newer commit, drop off the list. In Slack, [`/bumpkit inbox`](/docs/approvals#slack-commands) shows the same list, only to you.

```bash
bumpkit inbox list
bumpkit inbox list --filter releases
```

Decide one item, or approve several low-risk ones at once:

```text
bumpkit inbox approve lesson:ID
bumpkit inbox deny memory:ID
bumpkit inbox batch lesson:ID lesson:ID memory:ID --confirm "approve 3 low-risk items"
```

The kinds are `gate`, `command`, `release_batch`, `release_publish`, `memory` and `lesson`. `bumpkit inbox approve release_batch:ID` runs the browser vote of `bumpkit release approve`, and with no item it lists what's waiting with the exact command for each.

- **Batch approval** accepts only low-risk items, at most 50 per call, and the `--confirm` text must be exactly `approve N low-risk items` (`item` for one). The server checks this too. Medium- and high-risk items are refused with "is medium risk; decide it on its own".
- **Gate items and paused commands** need a person signed in to the dashboard, on the **Approvals** page. An API key is refused with `403 HUMAN_APPROVAL_REQUIRED` and the link, including from the CLI and MCP. A paused command also needs a write role. Gate items need a note of at least 10 characters; approving one is recorded as an override of the gate for that commit, so it needs the override role. Gate decisions can't be denied from the inbox. A gate run on a local diff with no commit SHA doesn't appear; CI and API gate runs at a full SHA do.
- **Audit.** Every decision is audited with who made it, for example `lesson.approve`, `memory.approve` and `inbox.batch_approve`.

The inbox API takes a person's key: `GET /v1/inbox`, `POST /v1/inbox/decide` with `kind`, `id`, `approve` and `note`, and `POST /v1/inbox/batch` with `items` (each `kind` and `id`) and `confirm`. `gate` and `command` items answer `403 HUMAN_APPROVAL_REQUIRED` for a key.

## Agent budgets and scopes

> **Beta, early access.** A workspace without access gets `403 FEATURE_EARLY_ACCESS` and a link to request it. Flag: `agent_budgets`.

The `agents:` section of `bumpkit.yml` gives each agent, or each glob of agent IDs, a budget and a scope:

```yaml
agents:
  claude-*:
    max_open_prs: 2
    max_changed_lines: 40
    paths_allow: [services/notify/**]
    paths_deny: [services/billing/**]
    areas_deny: [billing]
    spend_limit: 10
    on_violation: block
```

`spend_limit` is in US dollars per calendar month (UTC). `on_violation` is `block` (the default) or `approve`. See the [bumpkit.yml Reference](/docs/bumpkit-yml) for every key.

- **In the gate.** The gate checks every agent on the change: the ID from `BUMPKIT_AGENT_ID` or `BUMPKIT_AGENT` (which `bumpkit gate` sends), commit trailers and bot authors, and the agents on the check. Each limit the change breaks becomes a reason named `agents.<pattern>.paths`, `.areas_deny`, `.max_changed_lines`, `.max_open_prs` or `.spend_limit`, which fails the gate (`block`) or asks for approval (`approve`).
- **While the agent works.** `bumpkit pause --hook claude` denies file writes outside the agent's paths, with the reason. See [Pause risky commands](/docs/agent-controls#pause-risky-commands).
- **Open pull requests** are counted from gate runs and closed by GitHub's pull request `closed` webhook.
- **Every violation** is recorded and audited, and shows in `bumpkit agents violations` and the `agents_violations` MCP tool.

```bash
bumpkit agents spend --agent claude-1 --usd 7.50 --note "model tokens for the refund task"
bumpkit agents usage
bumpkit agents violations --limit 50
```

| Endpoint | What it does |
|----------|--------------|
| `POST /v1/agents/spend` | Record spend: `agent`, `repository`, `amount_usd`, `note`. Returns `204` |
| `GET /v1/agents/usage` | Open pull requests, open changed lines and this month's spend per agent |
| `GET /v1/agents/violations?limit=N` | Recent violations |

## Agent track records

> **Beta, early access.** A workspace without access gets `403 FEATURE_EARLY_ACCESS` and a link to request it. Flag: `agent_track_records`.

Each agent's outcomes over a window, overall and by work type (`tests`, `migrations`, `auth`, `api`, `ui`): releases, clean, reverted, fixed up within 7 days, blocked by the gate, and failed required checks, plus a score, the share that was clean. Checks of the same commits count as one release, so running the gate again doesn't change a record, and the change being gated isn't counted in its own record.

```bash
bumpkit agents records --days 90
```

`--days` defaults to 90. The same data is on the Reports tab of Insights and at `GET /v1/agents/track-records?days=N`.

Use a track record in the gate:

```yaml
gate:
  require_approval:
    - agent_track_record_below: 0.8
      min_releases: 1
      work_types: [migrations]
```

`min_releases` (default 3) ignores agents with fewer releases, and `work_types` applies the rule only when the change touches those work types. The reason states the numbers, for example:

```text
claude's migrations record is 0% clean over 1 release in 90 days (1 reverted, 0 fixed up, 0 blocked by the gate, 0 failed required checks); the policy asks a person to approve below 80%.
```

## Fix tasks

> **Beta, early access.** A workspace without access gets `403 FEATURE_EARLY_ACCESS` and a link to request it. Flag: `close_the_loop`. Needs the GitHub App.

When a change leaves callers on an old contract, such as a renamed function or a removed parameter, the release gate opens a fix task. Fix tasks cover Go functions and methods today; `bumpkit gate` builds the analysis from your checkout. It lists every caller by `file:line`, the symbol change and the expected edit. Mechanical changes get a pull request with the edit into the author's branch. Everything else is routed to the agent that wrote the change and to the pull request.

From the agent's side:

- **The Stop hook blocks.** While fix tasks are open on the branch, `bumpkit guard --hook ...` sends the agent back with each task, its places and pull requests, even when the gate passes.
- **The `fix_tasks` MCP tool** (`repository`, `branch`, `all`) lists the open tasks on the current branch.
- **Agents can't mark a task done.** Bumpkit marks it verified only when a later gate run proves every listed place clean, and reopens it if it comes back.

```bash
bumpkit loop --mine
```

`gate.fix_tasks` in `bumpkit.yml` decides what open tasks do to the gate: `block` (the default when Close the loop is on), `approve` or `off`. Bumpkit also opens rollback and back-port pull requests; see [Rollback & Time Machine](/docs/rollback) and [Hotfixes & Break Glass](/docs/hotfixes).

## Run several agents in one repository

A workflow for three agents working on the same repository at once:

1. **Give each agent an identity.** In each agent's environment, set `BUMPKIT_AGENT_ID=claude-1` and `BUMPKIT_SESSION`, or pass `--agent` and `--session` on each command. Add the [MCP server](/docs/mcp) and install the [agent hooks](/docs/agent-hooks), so each session starts with recalled memories and risky commands pause.
2. **Check before building.** Each agent runs `bumpkit tried "..."` to see whether the idea was reverted or dropped before, and `bumpkit intent --paths ... --symbols ...`, and stops to re-plan when it exits 1.
3. **Claim shared resources.** `bumpkit claim migration` for a migration number, `bumpkit claim path ...` for new files, `bumpkit renew` during long work.
4. **Test in isolation.** `export DATABASE_URL=$(bumpkit testdb lease)` before running tests, `bumpkit testdb release NAME` after.
5. **Push and report.** CI runs `bumpkit test upload`, `bumpkit coverage upload` and `bumpkit contracts sync`. The agent runs `bumpkit agent-report` with its claims and fixes anything contradicted; on test failures it runs `bumpkit test triage`.
6. **Merge in order.** Run `bumpkit merge-plan`, and have agents poll `merge_notifications` to rebase when main moves. Agents fix any open [fix tasks](#fix-tasks) before they finish.
7. **Review in one place.** People work through gate approvals, paused commands, memories and lesson proposals in the [approval inbox](#approval-inbox), and approve the lessons every agent should learn.
8. **Clean up.** `bumpkit unclaim` releases any leftover claims.
