Subagents
Atomic bundles@bastani/subagents, an extension for bounded specialist delegation with separate context while the parent remains in control. Use a single agent or parallel fan-out when isolation or a specialist pass materially helps with locating code, analyzing behavior, researching references, reproducing actual failures, or simplifying code. Keep interactive, exploratory, conceptual, and conversation-led work inline when direct user steering is more useful.
You do not need to install anything separately when you use @bastani/atomic.
Start with natural language
Ask Atomic to coordinate subagents in plain language:Subagent execution is non-interactive
Supported subagent launches start immediately without opening a preview/editor prompt or waiting for terminal input. This applies to single, parallel, forked, fanout, and prompt-template execution. Ask any necessary questions in the parent conversation before delegating. Prompt-template delegation comes from the separately installedpi-prompt-template-model extension, whose requestDelegatedRun emits prompt-template:subagent:request. If that caller must survive an extension reload, import registerPromptTemplateBridgeRequestSettlement from @bastani/subagents, register it before the emit, and unregister it from the normal response, cancellation, or abort path. The hook rejects the caller only when the old bridge drops a stale response emit; normal completion still arrives through prompt-template:subagent:response. Atomic cannot register this opt-in for an out-of-tree emitter.
Subagents now run and return their results directly. Atomic does not infer acceptance gates from prompt wording, inject acceptance-report instructions into child prompts, parse or strip acceptance-report blocks, or reject completed child runs because changed-file, test, or review evidence is missing. Put any evidence or validation requirements directly in the task text you give the parent or child agent.
Foreground supervisor coordination
When a foreground child callscontact_supervisor with need_decision or interview_request, or uses intercom.ask against its resolved launching parent, Atomic claims the request before broker send or reply-waiter admission. The current child ends and the parent subagent call returns the original question verbatim, the child agent identity, ordered attachments with duplicates preserved, and a dynamically generated [TASK_CONTEXT] handoff.
The handoff explicitly tells the parent to start a fresh child with a normal launch such as subagent({ agent: "worker", task: "[TASK_CONTEXT] ... Continue with this supervisor answer: ..." }). The new child receives a new run identity. Completed, interrupted, and parent-question children are terminal for continuation; a prior run ID cannot revive one.
For a parallel foreground run, one claimed parent ask interrupts the active siblings and closes the worker gate. Tasks still queued behind the concurrency limit never launch or request supervisor authorization. No sibling set or worktree/session execution state is retained for later continuation. Follow-up work is launched explicitly as fresh SINGLE or PARALLEL work with the necessary context.
intercom.send, contact_supervisor progress updates, and intercom.ask calls resolved to a sibling or other peer keep their existing Intercom delivery path. Non-parent blocking asks keep the single race-safe reply-waiter slot and exact threaded replies.
When the Intercom bridge is active, the parent may connect long enough to issue the initial child capability; the child’s own connection remains tool-driven. A claimed parent decision or interview ends before child send or waiter admission. Non-interactive children still run normal extension lifecycle and remain in-process AgentSession instances while live.
Migration from acceptance gates
If you have older subagent calls or custom agents that used the removed gate fields:- Remove
acceptanceproperties fromsubagent()calls, task entries, and parallel task items. Atomic no longer reads these fields. - Remove
completionGuard: falsefrom agent frontmatter and custom agent definitions. The no-mutation completion guard no longer exists, so the override has no effect and management rewrites strip it. - Move validation, command, evidence, review, or residual-risk requirements into the natural-language task text passed to the parent or child agent.
Bundled agents
Atomic currently bundles these agents from@bastani/subagents:
All bundled agents except
debugger default to openai-codex/gpt-6-astra:low; debugger uses openai-codex/gpt-6-astra:xhigh. Their fallback chains start with GitHub Copilot Astra, OpenAI Astra, Anthropic Fable 5.1, then GitHub Copilot Fable 5.1. Ordinary agents use Astra/Fable 5.1 at low, with Sol and GPT-5.5 fallbacks at medium, including the locator roles. Debugger keeps Astra and Sol at xhigh and Anthropic fallbacks at high. Later candidates retain provider-specific reasoning levels and identifiers; OpenRouter mirrors follow the direct-provider candidates. Each agent definition contains its complete ordered chain.
The bundled definitions keep their routing and model frontmatter but use compact, outcome-first bodies: role and goal, success criteria, constraints and tool routes, output contract, and stop rules where applicable. Report-producing agents ground progress claims in tool results and return concise evidence rather than narrating internal reasoning. Read-oriented agents inspect and report. debugger, code-simplifier, and worker can edit files, so give them an explicit scope and validation target. The debugger should finish an in-scope diagnosis by applying and validating the fix, not stop at a proposed patch.
Review compositions
Atomic does not bundle a single generic review agent. Instead, compose specialists with distinct angles and let the parent session synthesize their findings before applying any fix. Common review angles:
Example request:
subagent tool. Treat them as parent-side recipes, not bundled slash commands.
Foreground work and control
Foreground subagents stream progress in the conversation and return their results before the call completes. Natural-language examples:interrupt to stop a live child. Interrupted children are terminal for continuation; launch a fresh child with an explicit context handoff for follow-up work.
If the parent turn is cancelled while a foreground in-process child is still running, the child stops through the existing abort/interrupted state. That outcome is terminal and non-retryable: it does not count as a failure, never looks completed, and preserves any fallback metadata already recorded before abort. Parent receipts, Intercom summaries, and progress present the child as cancelled; persisted metadata records interrupted with abort cause rather than a new public status. Atomic recovers bounded, clearly labelled partial findings in this order:
- A modified run-scoped
progress.md - The last assistant message that contains actual text
- A cancellation notice with session, progress, and output artifact references
progress.md; recovery attributes that file to the first progress-enabled child so siblings are not each given a copy of the same findings. A mixed parallel set that contains both a user interrupt and a parent cancellation presents the cancellation summary rather than interrupt-specific follow-up guidance.
Status and interrupt use the live Rust registry and status watch; list and get remain read-only management actions. No retained foreground-run map, resume generation, session rehydration, or bare-run-ID continuation exists. Terminal delivery remains an in-memory bounded envelope with artifacts and run history persisted once.
Inside workflow stages, completion delivery observes the stage generation boundary. A completion admitted before the boundary closes is queued through the stage AgentSession and processed before the stage publishes its terminal snapshot. Closing the boundary cancels still-running stage-owned children, and findings or completion notifications that arrive afterward are suppressed rather than routed to the parent/main chat. Explicit post-mortem stage chat remains available separately for deliberate follow-up.
Cancellation does not retract an Intercom send already submitted to the broker. That operation keeps its transport receipt or retry identity, while the closed stage suppresses late incoming messages from its own children. A transport acknowledgement does not mean a late finding was shown in the parent chat.
Live progress and completed results show each step’s resolved model ID and effective reasoning level, including after a model fallback; parallel steps keep their metadata separate. Fast inference is part of the model ID, so an agent pinned to a fast variant renders it directly — codebase-analyzer (openai-codex/gpt-5.6-sol-fast · thinking medium) — with no separate fast badge. Select fast inference in an agent definition’s model and fallback model fields, for example openai-codex/gpt-5.6-sol-fast:medium; normal and fast IDs stay distinct fallback candidates and distinct records. See Providers for which providers publish fast variants and what each one sends upstream.
Orchestrator model and group policy
Atomic applies the same delegation policy to any parent chat or workflow stage that orchestrates subagents. A named agent uses the model and fallback sequence declared by its agent definition, so the orchestrator normally omits the subagent tool’s explicitmodel argument. An override needs either the user’s exact model request or a documented task-specific reason recorded before launch; model diversity alone is not enough.
If an agent declares no model or fallback policy, the orchestrator consults the role guidance in Model selection and the measured per-evaluation scores in Evals, then calls workflow({ action: "models" }) when that tool is available. It may pin only a returned fullId and may add a thinking suffix only when the model entry lists that level. When the catalog tool is unavailable, the catalog is empty, or no recommended model is present, the child stays unpinned and the orchestrator reports the limit instead of inventing a model or inspecting credentials.
Each workflow invocation automatically receives one stable, non-"default" Intercom group as typed admission policy. Its stages and delegated children carry that group across single, parallel, and follow-up work unless a call explicitly overrides group. Outside workflows, children inherit the launching session’s resolved group. This isolates workflow runs from unrelated runs and the main chat while contact_supervisor retains its authorized cross-group route.
Context and execution modes
Subagents can run with fresh or forked context:context: "fresh"starts a separate in-process child session with only the task and selected agent context.context: "fork"creates a real branched child session from the parent session leaf. It fails fast if the parent session cannot be forked; it does not silently downgrade to fresh context.
worktree: true can give each child an isolated git worktree so concurrent edits do not clobber each other.
Fresh child sessions use normal Atomic package discovery when an agent omits extensions, so bundled lightweight MCP and web-access wrappers are available just as they are in the parent. An explicit extensions field, including an empty list, switches optional extensions to allowlist mode and excludes unlisted optional builtins; mandatory bundled Intercom remains loaded. The child does not inherit the parent’s normal optional discovery set.
Top-level parallel calls support up to 50 subagents after expanding each task’s optional count. The extension’s parallel.maxTasks setting defaults to 50 and can enforce a lower task limit; parallel.concurrency independently controls how many of those children run at once, while the Rust turn limiter admits at most four running turns per parent.
When one assistant response emits several sibling execution-mode subagent tool calls, Atomic collects that synchronous burst before starting a child and runs it as one indexed parallel set. Each original tool call still receives one result containing only the children it requested, and its live result, progress, control, and artifact updates are projected to that same route without sibling data. The TUI redraws the shared run as one aggregate parallel widget rather than retaining one widget per original call. A single call keeps its original SINGLE or PARALLEL mode, calls awaited in sequence remain separate runs, and management actions bypass collection. An execution call that arrives after a child has started still receives the existing in-progress rejection. Prefer one explicit { tasks: [...] } call when planning parallel work; burst collection handles sibling calls emitted by a model.
For a collected burst, each call contributes its top-level agent task first and then its tasks entries in array order. Atomic preserves duplicates, expands count in place, and applies the configured task cap after flattening and expansion; the hard maximum remains 50. Each call-level cwd selects that call’s agent-discovery scope and child base directory. A task-level cwd stays relative to that call base and changes only that child’s execution directory, not agent discovery. This per-origin discovery rule applies only to collected sibling calls; an ordinary explicit { tasks: [...] } call keeps one discovery scope from its top-level cwd. Per-call and per-task group values also stay with their originating children. Shared run options must match across every sibling call: concurrency, worktree, context, share, control, sessionDir, maxOutput, artifacts, includeProgress, and agentScope. A mismatch rejects the whole burst before any child launches and names the incompatible field.
For a collected worktree: true burst, every call-level cwd must resolve to the same path. That common path becomes the shared worktree root; differing origins reject the burst before launch, and any task-level cwd must still resolve to that root. Each projected caller result keeps shared worktree diff text and terminal control guidance while its child results and standard child-output sections remain route-local.
Subagent tasks, parallel items, and the top-level call accept a group field that sets the spawned child’s Intercom home group, so same-group subagents can intercom each other while staying isolated from other groups. A named string joins that group; true auto-generates one shared UUID group per parallel set. Precedence is explicit subagent group > inherited current-session group > config > "default". Workflow stages carry their runtime-owned invocation group, so children launched without group automatically join the workflow group; callers do not need to copy or generate an ID. In other sessions, omission inherits that launching session’s resolved group. The child group is applied only when the child has Intercom access (the peer intercom tool or subagent-only contact_supervisor tool); a child without Intercom receives no group. contact_supervisor still reaches the supervisor across group boundaries because Atomic requests a broker capability during typed admission and binds the child’s registration to the issuing supervisor. Foreground paths use exact child scopes. The lightweight Intercom wrapper lazy-loads the authorization provider; provider failures abort launch, while hosts without a provider omit supervisor metadata instead of exposing a broken channel.
Detached children remain owned by the workflow stage that launched them. When that stage completes, Atomic cancels every still-running owned child (single or parallel) with the existing parent-cancellation outcome (status: "interrupted", cause: "abort") and suppresses late findings and completion notifications instead of routing them to the parent/main chat. A detached child that finishes while its stage is still live notifies normally, and completing one stage does not affect children owned by other stages or sessions.
When a subagent call or parallel task uses a cwd, Atomic validates that working directory before starting the child runtime. Missing or non-directory paths are reported as cwd problems instead of lower-level runtime errors.
Single-agent calls also accept reads: string[] | false. Atomic prepends those files as read context for foreground execution through the same in-process session path. Relative entries resolve against the effective child cwd (including a relative top-level cwd resolved from the parent); absolute entries are unchanged. Invalid values fail before the child session starts.
Single-agent calls accept progress: boolean in foreground mode. progress: true creates a run-scoped progress.md under isolated subagent artifact storage and instructs the child to maintain it without writing progress.md into the child cwd; progress: false disables an agent’s defaultProgress. When progress is omitted, the agent’s default is inherited, except that inherited progress is suppressed for read-only tasks (progress: true still explicitly opts in). Foreground runs remove this run-owned progress storage after the child exits when artifacts: false, including children temporarily detached for intercom coordination. This is separate from includeProgress: true, which only includes detailed runtime progress telemetry in the final tool result and does not create or maintain a file.
Delegation and child boundaries
Child-safety boundaries are enforced by typed admission policy and the bundled subagent extension:- In-process child sessions load bundled extensions through normal discovery. The
subagenttool may therefore be registered when the child’s active tool selection permits it, including the default no-allowlist case; an explicit allowlist may omit it. Tool presence does not grant fanout. The bundled subagents skill remains parent-only and is stripped from child prompts, including fanout-authorized children. - Child context is filtered to remove parent orchestration artifacts, old control/status messages, and prior parent
subagenttool calls/results. - Children are instructed that they are not the parent orchestrator and must complete their assigned task directly rather than delegating.
- Delegation is exactly one level deep and is not configurable. A session admitted as a subagent child is refused every launch and
interrupt; onlylist,get, andstatusstay available. A management-restricted child is also refusedcreate,update, anddelete. - The rule is enforced twice: the subagent executor refuses a child before any run starts, and the Rust admission door refuses a child deeper than the single permitted level. Admitted depth is typed admission state, never inherited from process environment state.
Custom agents
Custom agents are Markdown files with YAML frontmatter and a system prompt body. Keep the body outcome-first and locally complete: state the role or goal, observable success criteria, constraints and context-dependent tool routes, required output shape, and stop conditions. Reserve absolute wording for true invariants, request evidence and conclusions rather than private reasoning, and avoid repeated self-check instructions. Common locations are:
A small custom read-only inspection agent:
Fallback models
Agents can define orderedfallbackModels for retryable provider or model failures such as rate limits, quota/usage-limit exhaustion (for example a provider reporting The usage limit has been reached, or usage_limit_reached/insufficient_quota codes), auth problems, unavailable models, network timeouts, or 5xx errors. Atomic tries the requested primary model first, then configured fallbacks, and finally appends the current user-selected model as the last fallback candidate when available. The main chat and workflow stages share one failure classifier, so auth, model-availability, request-incompatibility, and transport signals are handled consistently. Cancellations, safety refusals, and task/tool failures are never retried on another model.
A candidate that cannot serve the current request — for example an HTTP 400/413/422 bad/unprocessable/payload-too-large request, an unsupported tool or parameter, a context-length/context-window overflow, or a too large / invalid_request error — is treated as request/context incompatible and the fallback sequence advances to the next candidate rather than stopping. This means that if none of the configured candidates are applicable to the request, Atomic falls back to the currently selected user model instead of failing outright.
Model fallback decisions use structured provider and attempt causes. There is no per-attempt idle watchdog, no child wall-clock kill cap, and no timeout-regex classification: a quiet provider response is allowed to finish, and only an explicit termination or provider failure supplies a retryable cause. Numeric process exit codes are not used as an outcome discriminator.
When registry availability shows that a known candidate provider has no configured auth, Atomic records a skipped model attempt before starting the in-process turn. Unknown/custom providers are still attempted, and the current user-selected model appended as the final fallback is never filtered out by this pre-admission check.
Fallbacks do not retry ordinary task failures, validation failures, tool failures, cancellations, or workflow-code errors. Because a fallback may send the same prompt and context to a different provider, choose models that match your cost, privacy, and data-handling requirements.
Each candidate can also carry its own reasoning effort — see Reasoning levels.
Reasoning levels
Set the reasoning (thinking) effort for each model candidate with amodel_name:thinking_effort suffix on model and on every fallbackModels entry. Valid efforts are off, minimal, low, medium, high, xhigh, and max — the same shorthand used by atomic --model sonnet:high. xhigh and max are used only when the selected model’s capability map supports them.
thinking field. The separate thinking: frontmatter field is deprecated. It still works as a default for any candidate that has no suffix, and a suffix always wins, but new agents should encode the effort directly on model and fallbackModels:
fallbackThinkingLevels exists only as an optional compatibility helper: it is aligned by index to fallbackModels and supplies a fallback candidate’s effort only when that fallback entry has no suffix. Prefer suffixed model strings instead. Attempt metadata reports the resolved model and the effective reasoning effort used for each attempt.