agentafk
Guides

Subagents & Delegation

How to delegate work to subagents: the agent tool, background mode, /bgsub, the compose DAG, and when to delegate vs. stay inline.

Agent AFK can fork child sessions — subagents — that run isolated tasks in parallel or sequence. This guide covers the mechanics: the agent tool, background mode, the compose DAG, and the decision rules for when to delegate vs. stay inline.

How subagents work

Subagents are child sessions that run independently. Each inherits permissions from the parent and runs the same tool surface. What it does not inherit is context — every subagent starts with zero prior conversation.

Subagents are non-interactive

A forked subagent has no operator surface of its own — it returns findings to its parent, which owns the human relationship. So subagents run non-interactive by default:

  • The ask_question tool is stripped from a subagent's toolset entirely — it cannot block on the operator. It must proceed on a stated assumption or return a Blocked / Asking result to the parent.
  • A path-approval prompt (file access outside the granted roots) is auto-denied rather than surfaced — pre-authorize the path in the parent or run in bypass mode.
  • MCP elicitations are auto-declined.

The parent session decides what to do with a subagent's Blocked/Asking result — including re-dispatching with wider grants or asking you directly.

Always include in a subagent brief:

  • Objective
  • Relevant file paths and constraints
  • Expected deliverable (format, length)
  • What not to do and when to stop

A subagent brief with missing context produces unreliable output. Synthesize what the subagent needs; don't assume it can infer from the parent conversation.

The agent tool

The primary dispatch mechanism is the built-in agent tool (also called Task in the tool list). Pass a prompt describing the work:

agent({
  prompt: "Read the retry logic in src/http/client.ts and explain the backoff strategy in ≤150 words. Cite file:line for each claim.",
  model: "haiku",          // optional — right-size the model
  max_turns: 5             // optional — bound the budget
})

The tool forks a child session, runs it to completion, and returns the compressed result to the parent. The parent's context window receives the final message only — not the child's internal reasoning or tool call log.

Model selection

You can dispatch subagents on cheaper models when the task doesn't need full capability:

ModelBest for
haikuFast lookups, simple summarisation, file reads
sonnetGeneral investigation, multi-file analysis
opusComplex reasoning, long-horizon planning

Foreground vs. background

By default agent is foreground: the parent waits for the child to finish before continuing.

Pass mode: "background" to fire-and-forget. The tool returns a jobId immediately. The parent can keep working and join the result later:

// Dispatch background job
agent({ prompt: "...", mode: "background" })
// → returns { jobId: "abc123" }

// Later, in the REPL:
/bgsub:join abc123

Use background mode for long investigations where the result isn't needed in the current turn — for example, running a security audit while the main session continues implementing a feature.

/bgsub — background job management

In the REPL, background subagent jobs are surfaced through the /bgsub namespace:

/bgsub:join <jobId>    # wait for and return the result

The status bar at the bottom of the REPL shows running background task counts.

Source: src/cli/background-status-bar.ts, src/cli/commands/interactive/background.js.

afk bg — CLI background job inspection

From the terminal, inspect persisted background job logs with the afk bg command:

afk bg list              # list all jobs (most recent first, --max <n> to limit)
afk bg tail <jobId>      # stream live events (--from-start to replay first)
afk bg replay <jobId>    # replay all events, then exit

Jobs are persisted to ~/.afk/state/bg/ even after the parent REPL exits. Use afk bg to check status, review logs, or re-stream a job's output from disk. Complements /bgsub:join when you need access outside an active REPL session.

The compose tool — DAG orchestration

For structured multi-agent workflows, the compose tool dispatches up to 20 subagent nodes with explicit dependency edges. Independent nodes run in parallel; dependent nodes wait.

compose({
  nodes: [
    { id: "security", prompt: "Audit src/api for authz and injection bugs. List each finding with file:line." },
    { id: "coverage", prompt: "Find untested branches in src/api. List each with file:line." },
    { id: "report",   prompt: "Combine the security and coverage findings into one prioritised punch-list." }
  ],
  edges: [
    { from: "security", to: "report" },
    { from: "coverage", to: "report" }
  ]
})

Dependencies are declared as edges ({ from, to } — "from must finish before to starts"), not as a field on the node. Here security and coverage have no incoming edges, so they run in parallel; report waits for both. If any node fails and fail-fast is enabled (the default), downstream nodes are cancelled rather than running with incomplete inputs.

Limits and failure behavior:

  • Maximum 20 nodes per compose call
  • Cycles are rejected at dispatch time
  • Fail-fast cancels all downstream nodes on first failure — the parent sees which nodes ran and which were skipped

Source: src/agent/tools/compose-executor.ts, src/agent/dag.ts.

How cancellation works

When you cancel a session, all running subagents stop immediately. The rules:

  • Parent abort cascades down — aborting the parent cancels all running children.
  • Child abort notifies up but does not auto-abort the parent — a failed subagent surfaces an error to the parent; the parent decides whether to continue.
  • Abort beats hook decisions — if an abort signal fires while a hook is deciding, abort wins.

This means you can cancel a daemon session or a REPL turn and all its child work stops immediately. A single broken subagent in a compose DAG does not bring down the orchestrator unless it's in a dependency chain.

When to delegate vs. stay inline

Delegate when the work would:

  • Read or grep more than 3 files inline
  • Verify a claim independently from the chain that produced it
  • Investigate a failing test or unexplained behavior
  • Run two or more independent investigations that could happen in parallel
  • Consume more main-session context than the subagent's compressed answer would

Stay inline when:

  • The task is a single-file edit or localized fix visible in fewer than 2 reads
  • The answer is conversational or requires no file access
  • The user explicitly asked for a direct tool call
  • Dispatch overhead exceeds the work itself

Source: AGENTS.md (Delegation section).

Right-sizing the budget

Subagents should have explicit budgets. Before dispatching:

  • Set max_turns on focused investigations (max_turns: 5 for a quick lookup)
  • Choose the cheapest sufficient model (haiku for reads, sonnet for multi-file analysis)
  • For wide fan-outs, dispatch in bounded waves rather than all at once — a burst of parallel children can hit provider rate limits and cascade into timeouts

Subagent output

Subagents return their final assistant message verbatim. Structure the brief to ask for compressed output:

"...Return: answer (1–2 sentences), evidence with file:line citations, confidence (high/medium/low), and any unresolved questions."

For typed output, the SubagentManager accepts optional Zod schemas — the subagent's output is validated before it reaches the parent. Malformed output surfaces as an error rather than silently passing through.

Verifying subagent output

High-stakes subagent findings should not be trusted blindly. Use the /shadow-verify skill to dispatch parallel adversarial verifiers that re-derive 2–3 key claims from scratch using tool calls. Any disagreement is flagged before you act on the result.

See the Verification guide for the full workflow.

On this page