Browse the documentation

Nexus: autopilot, parallel work and durable runs

Autopilot with checkpoints, supervised parallel work, plan export from a swarm, and the durable runtime (create, start, launch, collect, verify, accept) with its Codex adapter and limits.

On this page
  1. Autopilot
  2. Parallel work
  3. The durable runtime
  4. The plan file
  5. The host-owned flow: create, start, record, verify, accept
  6. Interruption, cancellation and retry
  7. The optional process backend and the Codex adapter
  8. Limits and what it does not do

Nexus is the orchestrator of Core. It has four roles: Scrum Master (sprints, stories, retrospectives), Quick Flow (a small change with minimum ceremony), Autopilot Controller (the pipeline from idea to delivery, with checkpoints) and Parallel Supervisor (several agents at once, without collisions). Underneath, a durable runtime, bmad-plus nexus, keeps task graphs and attempts on disk so that work survives a closed session and nothing counts as done until independent checks say so. This page is for anyone who wants to automate more than one agent’s work, and wants to know exactly how far the automation goes.

Nexus and parallel work How Nexus finds independent tasks, gives each its own write scope, records real results and runs independent checks before accepting.
Transcript

Nexus coordinates the work of the other roles. It looks for independent tasks, the ones that touch no shared file. Each task gets its own write scope, and scopes may not overlap. Parallel agents come from your host tool. Without them, the tasks run in sequence. Nexus can also launch a planned local command or a Codex CLI process, under a foreground supervisor. It records the real result, then runs independent checks before anything is accepted. There is no background scheduler, and host permissions still apply. In autopilot, the same pipeline runs from idea to delivery, with the checkpoints you configure.

Described transcript

Autopilot

Say autopilot in the chat of your AI tool, then describe the project. These are chat instructions, not terminal commands. Nexus inspects the request and the project before choosing stages: a small change goes straight to implementation and review, while a missing contract or a consequential uncertainty justifies deeper planning. For a project that needs the full pipeline there are three phases.

The autopilot pipeline
PhaseStepsCheckpoint
1. DiscoveryStep 0: the intake of every pack the request involves. Then Atlas (Analyst): brainstorming and domain research; Atlas (PM): product brief and PRD; Sentinel (UX): UX design spec.discovery: you review the PRD and the UX spec.
2. BuildForge (Architect): architecture; Nexus (Scrum Master): epics, stories, sprint plan; then for each story, parallelizable if independent: implement, test, draft the acceptance steps a person can observe. A failing check keeps its evidence and is repaired within the task’s attempt limit.architecture: you review the architecture. story: a notice per completed story.
3. ShipFull code review, UX review, documentation, finalized acceptance recipe delivered to a person, results read and every failure classified, retrospective.delivery: you review the final deliverable, with the run quoted.

Each checkpoint follows the setting in _bmad/config.yaml: require_approval stops and waits, notify_only reports and continues, auto continues and logs. With execution_mode: autopilot the story checkpoint becomes notify_only by default. An external notification (a message to your phone, say) needs a configured channel and your authorization: a bare installation has no background sender, so a reminder is not sent on its own.

Human acceptance fits in as well. With uat.mode: advisory (the default, also when the block is absent) the page is built and offered at every delivery and never blocks; gate makes the delivery checkpoint wait for bmad-plus uat gate to pass; off produces no recipe and the delivery report says so. A pack can also declare a pipeline in the registry (ordered steps, each with a gate); autopilot then runs that pipeline for the pack’s work, after its intake. No pack declares one in 0.23.0, so this is a capability of the framework, not shipped content.

State, resume and failures

  • Authoritative state lives under .bmad-plus/nexus/runs/. The optional .bmad-plus/orchestrator-state.yaml is a navigation summary only; it cannot prove that something is accepted or that a process stopped.
  • There is no autopilot --resume executable. To resume, inspect the intended durable run and the host’s real state, and reconcile an interrupted attempt before retrying.
  • Test failure: the failed checks are kept, the repair happens within the task’s maxAttempts, then the changed artifacts are verified again. A completion claim cannot pass a failing check.
  • Agent error: partial work and its attempt identity are preserved, and the report says what stays uncertain. Dependent tasks wait for acceptance.
  • Conflict in parallel work: stop assigning overlapping work, inspect the owners, reconcile their attempts and keep your changes before any retry.

Parallel work

Say parallel in the chat, or let autopilot call it when parallel_execution is true and independent tasks are detected. The Parallel Supervisor decides what can run at the same time; the host decides whether it can. Real parallelism depends on your tool: if it cannot run sub-agents, the tasks run one after the other.

What can and cannot run in parallel
ParallelizableSequential only
Stories with no shared fileStories that modify the same files
Independent research (market and technical)A task whose input is another task’s output
Tests while documentation is writtenArchitecture decisions before implementation
Changes to separate modules or packagesCode review after implementation
The six supervision actions
ActionWhenWhat happens
LaunchIndependent tasks detectedStart parallel agent sessions.
MonitorContinuouslyTrack progress in the Nexus run.
PauseConflict detectedStop the conflicting agent.
RestartAfter the conflict is resolvedReconcile the existing attempt and its effects, then retry within the recorded limit with a new host identity.
ReallocateAn agent finishes earlyAssign the next queued task.
EscalateAttempt limit reached or reconciliation blockedReport the unresolved condition and the evidence; continue independent authorized work.

The durable runtime

bmad-plus nexus persists a task graph and its attempts under .bmad-plus/nexus/runs/. Every normal change takes an exclusive project lock and writes a checksummed state file through a flushed temporary file and an atomic rename. Inspection is read-only. Three outcomes are kept apart, and this separation is the point of the runtime.

Execution, verification, acceptance
OutcomeWho establishes itWhat it means
ExecutionAn identified host reports completed, failed, blocked or ambiguous; or an original foreground supervisor collects its child process’s real result.An observation. It is not independent verification.
VerificationNexus itself runs the plan’s check commands with literal argument arrays and no shell, records exit codes and bounded output, and compares artifact and write-scope snapshots before and after.The result passes the independent checks, with receipts.
AcceptanceA separate, serialized operation rechecks current artifacts, resource hashes and dependency evidence.The current workspace is accepted. No Git commit, merge, copy or deployment is done.

Evidence stays honest over time. An accepted task counts as current only while its artifacts, protected resources and every transitive dependency still match what was verified: changing an upstream file invalidates the dependents’ evidence, and an old "accepted" record does not assert that later-edited files still pass. A deadline is an observation, not proof that work never happened or that a process ended.

The plan file

A plan is a JSON file; structured input always goes through files so that shell quoting cannot reinterpret a command array. This minimal plan has one task whose result must satisfy a check that already exists (checks/check-result.cjs) and whose source lies outside the worker’s write scope.

nexus-plan.json
{
  "id": "example",
  "maxParallel": 1,
  "config": { "language": "English" },
  "tasks": [
    {
      "id": "result",
      "objective": "Produce the requested result in work/result.txt.",
      "acceptance": ["The result satisfies the independent check."],
      "dependsOn": [],
      "scope": ["work"],
      "artifacts": ["work/result.txt"],
      "resources": ["checks/check-result.cjs", ".agents/skills/agent-orchestrator/SKILL.md"],
      "checks": [
        {
          "id": "result-content",
          "command": "node",
          "args": ["checks/check-result.cjs"],
          "cwd": ".",
          "timeoutMs": 30000
        }
      ],
      "maxAttempts": 2,
      "deadlineMs": 3600000,
      "idempotent": true,
      "authorizations": ["Edit work/ and run the listed local check."]
    }
  ]
}

Task fields
FieldMeaning
id, objective, acceptanceIdentifier, what to produce, and the conditions that must hold.
dependsOnTasks that must have current accepted evidence before this one starts.
scopeFiles or folders the task may write. Scopes of all tasks are exclusive and must be pairwise disjoint, even between tasks that run in sequence.
artifactsFiles that make up the result; their hashes are recorded.
resourcesEvery instruction and support file supplied to the host, hashed by Nexus. They must lie outside every task’s write scope. Nexus cannot attest to what is not declared.
checksUp to 30 per task: command (node or an absolute executable path, whose bytes are bound into the plan), args, cwd, timeoutMs (10 to 300000). File arguments must be declared resources.
maxAttempts, deadlineMs, idempotentAttempt limit (at most 10), deadline, and whether a retry is safe without a specific observation.
authorizationsText describing the existing authorization. A worker cannot modify it or answer an approval prompt.
executionOptional contract for a process-backed task (see below). Without it the task is host-owned.

Paths in a plan are portable, project-relative and use /. Absolute paths, traversal, alternate streams, reserved Windows names, symlinks or junctions, and writes to .git or Nexus’s own state tree are rejected. Checks run with a restricted environment: only PATH, SYSTEMROOT, WINDIR, TEMP, TMP and TMPDIR can be copied (plus a few non-secret identity and path variables on Windows), locale is C, timezone is UTC, and NODE_OPTIONS, PYTHONPATH, loader hooks and credentials are absent. This restricts the environment; it is not an operating-system sandbox.

The host-owned flow: create, start, record, verify, accept

The default backend is the host: your assistant does the work with its own facilities and reports back. Below, a real run of a fanout exported from a swarm (three page units; only the first is walked through). Create the three swarm files and host.json in a project to reproduce it. The "worker" is a stand-in that writes the answer file by hand, so the example shows the bookkeeping, not any model’s work.

swarm/page-fanout.json (the swarm definition)
{
  "schemaVersion": 1,
  "id": "site-pages",
  "kind": "fanout",
  "title": "One sub-agent per page of the site",
  "units": { "source": "input" },
  "brief": { "template": "briefs/page.md", "context": [] },
  "answer": {
    "required": ["id", "done", "words"],
    "fields": {
      "done": { "type": "boolean" },
      "words": { "type": "integer", "min": 0 },
      "note": { "type": "string", "max": 200 }
    }
  },
  "tally": { "rate": "done", "numbers": ["words"] },
  "disclosure": "Each page was written by a separate sub-agent from the same brief; read them together before publishing."
}

swarm/units.json (the three units)
{
  "schemaVersion": 1,
  "units": [
    { "id": "about", "scope": "site/about", "title": "About us", "tone": "warm" },
    { "id": "pricing", "scope": ["site/pricing", "site/data/prices.json"], "title": "Pricing", "tone": "plain" },
    { "id": "contact", "scope": "site/contact", "title": "Contact", "tone": "short" }
  ]
}

swarm/briefs/page.md (the brief template)
# Page {{unit.id}}

Write the page "{{card.title}}" under `{{card.scope}}`, {{card.tone}} in tone. Touch nothing
outside that folder.

When the page is written, write a JSON object to `{{answer.path}}` with `id` ("{{unit.id}}"),
`done`, `words` (the word count) and an optional `note`.

{{disclosure}}

host.json (the identity of the worker and of its session)
{ "backend": { "kind": "host", "id": "demo-worker", "sessionId": "demo-session-1" } }

A host-owned task from creation to acceptance
npx bmad-plus swarm init --definition swarm/page-fanout.json --units swarm/units.json
site-pages-20261019-vwk0: fanout of 3 units, budget 26, approval not-needed.
Units listed, no seed.
Next: bmad-plus swarm briefs site-pages-20261019-vwk0
npx bmad-plus swarm plan site-pages-20261019-vwk0 --out .bmad-plus/swarm/reports/site-pages-20261019-vwk0/plan.json
/work/demo/app/.bmad-plus/swarm/reports/site-pages-20261019-vwk0/plan.json: 3 tasks, 10 in parallel.
Next: bmad-plus nexus create --plan /work/demo/app/.bmad-plus/swarm/reports/site-pages-20261019-vwk0/plan.json
npx bmad-plus nexus create --plan .bmad-plus/swarm/reports/site-pages-20261019-vwk0/plan.json
Nexus run site-pages-20261019-vwk0 — durable task coordination
about: not started; verification=pending; acceptance=pending
pricing: not started; verification=pending; acceptance=pending
contact: not started; verification=pending; acceptance=pending
Use inspect --json for recorded evidence and reconciliation observations.
npx bmad-plus nexus start site-pages-20261019-vwk0 about --input host.json
about: running; verification=pending; acceptance=pending
  Attempt: a4ec0495-660b-487c-8c83-e82ada22a857; host: demo-worker/demo-session-1
echo '{"id":"about","done":true,"words":120}' > .bmad-plus/swarm/runs/site-pages-20261019-vwk0/answers/about.json
The stand-in worker writes its answer file by hand. Then write rec.json (shown below this terminal) with the attempt id printed by start.
npx bmad-plus nexus record site-pages-20261019-vwk0 about --input rec.json
about: completed; verification=pending; acceptance=pending
  Attempt: a4ec0495-660b-487c-8c83-e82ada22a857; host: demo-worker/demo-session-1
npx bmad-plus nexus verify site-pages-20261019-vwk0 about
about: completed; verification=passed; acceptance=pending
npx bmad-plus nexus accept site-pages-20261019-vwk0 about
about: completed; verification=passed; acceptance=accepted
npx bmad-plus nexus inspect site-pages-20261019-vwk0
about: completed; verification=passed; acceptance=accepted
  Accept only after rechecking current artifacts and resources.
pricing: not started; verification=pending; acceptance=pending
  Start when dependencies have current accepted evidence.
Each nexus command also prints the header line, the pricing and contact lines and the closing hint; only the lines that change are kept here.

Output captured from a real run. Source: bmad-plus 0.23.0, 2026-10-19

rec.json (what the host reports; the attempt id is copied from start)
{
  "attemptId": "a4ec0495-660b-487c-8c83-e82ada22a857",
  "backend": { "kind": "host", "id": "demo-worker", "sessionId": "demo-session-1" },
  "outcome": "completed",
  "exitCode": 0,
  "summary": "The demo host reports the about page is written."
}

record needs the exact attempt id and the same backend and session. Other outcomes are failed, blocked (the request stays visible and keeps its capacity) and ambiguous (ordinary acknowledgements are then refused; reconcile explicitly). verify exits 1 when the verification did not pass, and accept refuses a task without an eligible passed verification. A worker’s exit code or a sentence saying "done" never replaces a check receipt.

Interruption, cancellation and retry

Commands for the difficult cases
CommandInput fileWhat it does
nexus cancel RUN TASK{ "reason": "..." } (host); exact attemptId, backend and reason (process)Records a request. A host attempt signals no PID or terminal; the host stops only its own operation. Capacity stays held until reconciliation.
nexus reconcile RUN TASKThe attempt, outcome (completed, failed or cancelled), ownerStopped: true, retrySafe, summaryCloses an uncertain attempt with an operator observation. It is an observation, never independent evidence that the owner stopped.
nexus retry RUN TASKA new host identityStarts a new attempt after reconciliation. It consumes maxAttempts; a new session does not reset the limit. Non-idempotent tasks also need retrySafe: true.
nexus recover-lockThe exact lock hash from inspect, ownerStopped: true, a non-empty noteRemoves an interrupted writer lock after you inspected its owner. A live local writer blocks removal. Never automatic.

The optional process backend and the Codex adapter

A task can carry an execution object instead of being host-owned. This is an operator-supplied definition, never a command inferred from task prose. nexus launch RUN TASK then stays in the foreground until the owned operation finishes; a terminal, a coding host or a CI runner keeps it alive. The task record is saved before the process is spawned, binding a fresh attempt id to a fresh supervisor session, the exact definition and the hashes of its protected inputs. The supervisor keeps bounded stdout and stderr, the real exit or signal, and a checksummed receipt. launch leaves collection pending even after a clean exit: nexus collect RUN TASK --input attempt.json (the exact attemptId and the whole backend object) closes it, and refuses a foreign, repeated or late receipt. Exit status 0 on launch means only that the process receipt says completed; it does not mean acceptance.

A task with the generic command adapter (execution object)
{
  "execution": {
    "adapter": "command",
    "command": "node",
    "args": ["workers/task.cjs"],
    "cwd": ".",
    "input": "inputs/task.json",
    "resources": ["workers/task.cjs"],
    "blockedExitCodes": [75],
    "outputLimitBytes": 262144
  }
}

The installed Codex CLI adapter
{
  "execution": {
    "adapter": "codex-exec",
    "command": "/absolute/path/to/codex",
    "input": "inputs/task.md",
    "instructions": [".agents/skills/agent-architect-dev/SKILL.md"],
    "sandbox": "workspace-write"
  }
}

  • The executable is resolved to a regular file and its SHA-256 is pinned in the plan. Arguments are literal arrays, passed with no shell, no environment override and no credential snapshot.
  • Text inputs are at most 256 KiB each and the whole packet at most 1 MiB. Instructions are prepended to stdin with their relative paths.
  • Generic zero exit is completion; a nonzero code listed in blockedExitCodes is blocked. That list is a convention of your wrapper, never an approval policy.
  • The Codex adapter builds -a never exec --json --color never --sandbox MODE --skip-git-repo-check --ignore-user-config -; model is optional and adds only --model MODEL. sandbox is read-only (default) or workspace-write; no other flag, no approval bypass and no shell string is accepted. Only HOME, USERPROFILE, HOMEDRIVE, HOMEPATH and CODEX_HOME may be inherited beyond the minimal environment, and receipts list variable names, not values.
  • Codex completion needs a zero exit, a thread.started identity and a turn.completed event without a terminal error. Only explicit approval_required error codes map to blocked; other provider errors stay failed.
  • Cancellation is bound to the returned identity. Only the original supervisor may signal the direct child it created; nothing kills a saved PID or adopts an old terminal. A deadline, excess output or a lost supervisor produces an ambiguous result and keeps the capacity until reconciliation.
  • Honest evidence: the flag contract was checked against Codex CLI 0.153.4. One authorized call on 2026-09-11 produced a real thread and terminal event, but the host rejected the requested file edit as read-only, Nexus collected the receipt, the independent verifier failed and acceptance was refused. That shows the wiring and the failure containment on that host; successful Codex file writing was not established there.

Limits and what it does not do

Supported bounds
BoundValue
Tasks per run200
Active attempts per run32
Attempts per task10
Checks per task30
Time allowed per check10 to 300000 ms
Captured output per check64 KiB (truncation is marked)
Files per scope snapshot; size of a snapshotted file10000; 16 MiB
JSON input filesAt most 1 MiB, regular files
  • No daemon, no scheduler, no unattended loop. Every launch is explicit and holds a capacity slot; capacity is not a money budget.
  • No operating-system sandbox. Workers share the project and the OS user with Nexus and can ignore declared scopes; checksums detect accidental change, they are not signatures. Protect the plan and the verifier, and use an isolated project or a host policy when it matters.
  • No Git commit, merge or deployment. Acceptance means "the current workspace passed the independent checks", nothing more.
  • No model quality claim. A receipt is not evidence that a model got better at anything.
  • A verification timeout signals only the direct child and records an ambiguous result, because descendants or outside effects are not proven absent. Check programs must be bounded foreground commands.

Let Nexus run a small project with checkpoints

Use at the start of a project, with execution_mode left on manual or set to hybrid so that you keep the approvals.

In your AI assistant
autopilot. The project: a small API that lets freelancers send quotes and turn them into invoices. Start with the intake of any pack involved. Stop at the PRD checkpoint and at the architecture checkpoint and wait for my approval. Keep every story small, verify each one against its acceptance criteria before the next, and tell me what stays uncertain at the end.

What you should get Discovery runs first (brief, PRD, UX spec) and stops at the discovery checkpoint with something you can read. After your approval Forge writes the architecture and Nexus stops again. Stories are then implemented and tested one at a time; with the default checkpoints each completed story also waits for your approval (story) unless you set it to notify_only, and the final delivery stops for your review (delivery). A failing check is repaired within the attempt limit rather than waved through. The final report states what was verified and what is still open.

Split approved work into independent tasks

Use after the stories exist. The host must support sub-agents for real parallelism; otherwise the tasks run in sequence.

In your AI assistant
parallel. Take the approved stories and split them into tasks that do not touch the same files. For each task give an exclusive write scope, the files it may read, and a check that I can run. Record the plan with bmad-plus nexus create, run only the independent tasks together, and show me nexus inspect after each wave. Do not accept a task before nexus verify has passed.

What you should get A nexus-plan.json with disjoint scopes and independent checks, a Nexus run listed by nexus inspect (each task not started; verification=pending; acceptance=pending), and then one status line per task as work proceeds. A task whose check fails shows verification=failed and cannot be accepted; a conflict pauses the colliding task instead of overwriting it.

See also