Subagents
You asked the agent to debug a flaky test. Forty messages later, it’s read seventeen files, tried four hypotheses, run the test six times with different env vars, and finally pinned it down. Now you want to actually fix the test and ship the feature you originally came in to build - and your context window is full of debug noise. Stack traces. Trial fixes. Failed reproductions. The agent is now somewhat less coherent than it was an hour ago, because half its context is rabbit-hole.
The cost wasn’t the debugging. It was that the debugging happened in the same window as the rest of your work. Everything the agent learned to find the bug is now polluting the context it needs to write the fix.
A subagent is an isolated worker the main agent spawns to do a discrete task - it runs its own loop, in a fresh context window that doesn’t touch yours, and when it finishes the parent receives only a summary.
Hand the debug task to one: it spawns fresh, burns through whatever context it needs, and returns “the bug is in auth/session.ts:142, the session token is being mutated by the middleware before the test asserts on it.” One sentence back. Forty messages of investigation: gone. Whatever the subagent read, tried, backtracked through, or threw away never lands in your conversation - your main context stays clean for the actual fix.
Real-world examples of what teams use subagents for:
- Codebase exploration - “find every place we call the auth API and how each one handles errors.” Dozens of file reads collapse into a one-paragraph map.
- Code review - give a subagent the diff plus a checklist (security, perf, naming) and let it return findings. The 200-line diff and 50 lines of analysis don’t enter your conversation.
- Verification / audit - “go check that every endpoint in the new router has a corresponding test.” Returns a list of gaps, not a tour of the test suite.
- Parallel work - spawn three subagents at once: one writes the migration, one writes the seed data, one drafts the rollback. Merge results.
- Specialised personas - a “security reviewer” subagent with a tighter tool surface (read-only, no shell) and a system prompt focused on threat modelling.
- Research and synthesis - “read the last six release notes and summarise the breaking changes we need to handle.” Returns the summary, not the raw notes.
The test: if a task would generate a lot of intermediate noise but you only care about the final answer, it’s a subagent task.
What “isolated context” actually looks like
Section titled “What “isolated context” actually looks like”The subagent’s defining property is that it runs in its own context window - separate from yours. Picture two windows:
The parent receives the one-sentence summary and nothing else. Whatever the subagent learned to find the answer is gone the moment it returns; whatever you needed to act on the answer is still there, uncluttered.
The trade-off is also right there in the picture. The subagent starts with no shared history. It doesn’t know what you discussed earlier, what you’ve already ruled out, what you care about. You have to brief it in the task description - the more precisely, the better. Subagents shine for self-contained work; they’re a poor fit for tasks that need ongoing back-and-forth with you, because every “wait, also…” is a fresh subagent with no memory of the last one.
See it at scale
Section titled “See it at scale”One delegation keeps a window clean; fan-out is where subagents change what’s possible. The same audit - “find dead code across api/, ui/, and tests/” - run both ways. Token counts are illustrative; toggle and watch your window.
A worked example
Section titled “A worked example”You’re mid-flow on a feature when CI flags a flaky test. Without a subagent:
you: why is auth/session.test.ts flaky on CI?agent: [reads session.test.ts]agent: [reads session.ts]agent: [runs the test locally - passes]agent: [reads the test runner config]agent: [reads the middleware]agent: [tries a hypothesis: timezone? - runs again, still passes]agent: [reads the CI workflow file]agent: [tries another hypothesis: ordering? - runs in --random]... 30 messages later ...agent: found it - middleware mutates the session token.you: great, now back to the feature.agent: [main context now full of debugging trail; coherence dropping]With a subagent:
you: spawn a subagent: investigate why auth/session.test.ts is flaky on CI, return the root cause in one paragraph.agent: [spawns subagent - fresh context] ... 30 messages happen elsewhere ...subagent: Root cause: middleware in src/auth/middleware.ts:64 mutates session.token before the test asserts on it. Reproduces locally only under --random-order.agent: [receives the paragraph, parent window otherwise untouched]you: great, now back to the feature.agent: [main context still clean; full coherence on the feature]Same work happens. Same answer returns. The difference is what your conversation looks like afterward.
Why this and not…
Section titled “Why this and not…”| You want to… | Reach for | Not |
|---|---|---|
| Isolate a side-quest’s context so it doesn’t bloat the main thread | Subagent | Skill |
| Encode reusable instructions the model picks up on its own | Skill | Subagent |
| Run two or more pieces of work in parallel | Subagent (one per piece) | Single agent serially |
| Enforce a deterministic rule on every tool call | Hook | Subagent |
| Restrict a worker to a narrow tool surface (read-only, etc.) | Subagent with tool restrictions | Permissions alone |
| Have peer agents coordinate and message each other | Agent teams (Claude Code, experimental) | Subagent |
A subagent returns once. It doesn’t continue the conversation. If you need a back-and-forth peer, you want an agent team (Claude Code) or the Agents SDK (Codex), not a subagent.
How it works in each tool
Section titled “How it works in each tool”Subagents are spawned via the Agent tool. Custom subagents live at:
.claude/agents/<name>.md- project~/.claude/agents/<name>.md- user- Plugin-bundled
- Managed-policy
Frontmatter:
---name: code-reviewerdescription: Reviews a diff for bugs, performance, and security issues.tools: [Read, Grep, Glob] # restrict the subagent's tool surfaceskills: [security-checklist] # preload these skills into its context---Precedence (most-wins): managed > CLI flag > project > user > plugin.
What the subagent inherits: the system prompt (shared for cache efficiency), CLAUDE.md content, git status, plus whatever the parent passes in the prompt. It does not inherit the parent’s conversation history.
Agent teams (experimental) are different - independent peer Claude Code sessions that message each other and share a task list. Use a subagent when only the result matters; use an agent team when teammates need to discuss and coordinate.
Codex ships three built-in subagents:
default- general-purpose fallbackworker- execution-focused (implementation/fixes)explorer- read-heavy codebase exploration
Custom subagents are standalone TOML files at ~/.codex/agents/<name>.toml (user) or .codex/agents/<name>.toml (project). One agent per file; the name field is authoritative.
TOML schema - required: name, description, developer_instructions. Optional: nickname_candidates, model, model_reasoning_effort, sandbox_mode, mcp_servers, skills.config. Unset optionals inherit from the parent.
name = "reviewer"description = "Reviews a diff for bugs, performance, and security issues."developer_instructions = "..."model = "gpt-5.4"Invocation: natural-language dispatch from the parent (e.g. “Have the reviewer agent look at the diff…”). Codex only spawns when explicitly asked. The /agent CLI command inspects active threads - it does not spawn them.
Tool restriction: Codex’s documented TOML schema has no explicit tools / allowed_tools allowlist field. The subagent’s tool surface is shaped indirectly via mcp_servers and sandbox_mode. (Related open issue: #15250.)
The OpenAI Agents SDK is the heavier orchestration layer - for complex multi-agent workflows beyond what the CLI exposes directly.
OpenCode is the most opinionated here. It ships three built-in subagents:
general- full-access workerexplore- read-only worker for codebase scansscout- read-only docs/dependencies worker
Invoke a subagent by @mention in your prompt - e.g. @explore find every place we call the auth API.
Custom subagents: opencode agent create, or hand-write a markdown file in ~/.config/opencode/agents/ or .opencode/agents/. Frontmatter mode: subagent (vs primary for build/plan-style top-level agents).
Frontmatter schema: description, mode (subagent | primary | all), model (per-agent override, e.g. anthropic/claude-sonnet-4-6), temperature, top_p, permission (preferred - object with edit / bash / webfetch / skill keys taking allow / deny / ask; supports glob patterns for bash), tools (deprecated; per-tool booleans), steps (max agentic iterations), color, hidden (suppress from @-mention autocomplete).
---description: Read-only auditor for security findingsmode: subagentmodel: anthropic/claude-sonnet-4-6permission: edit: deny bash: { "git *": allow, "*": ask } skill: { "security-*": allow }---Skills aren’t statically baked into a subagent’s prompt; they load on demand via a native skill tool, gated by per-agent permission.skill rules. Set tools: { skill: false } to disable skills for an agent entirely.
Cursor has a first-class Subagents primitive (introduced in Cursor 2.4). Each subagent is a markdown file with YAML frontmatter, discovered from:
- Project:
.cursor/agents/,.claude/agents/, or.codex/agents/ - User:
~/.cursor/agents/,~/.claude/agents/, or~/.codex/agents/
Project-level files take precedence on name collision. Frontmatter fields include name, description, model, readonly, and is_background. Subagents run in their own context window (isolation) and can be launched in parallel.
Invocation is threefold: automatic delegation by the parent agent, explicit /name syntax (e.g. /verifier check the auth flow), or natural-language mention. Subagents work in the editor, the CLI, and Cloud Agents.
Cloud Agents (formerly Background Agents) are a separate primitive: full agents running in isolated cloud VMs rather than locally. Environment is configured via .cursor/environment.json (agent-led setup, a saved snapshot, or a Dockerfile). They clone the repo to a fresh branch, run, push results, and are reachable from Cursor Desktop, the web dashboard, Slack (@cursor), GitHub PR/issue comments, Linear, or the Cloud Agents REST API.
The parallel-agent fan-out in Cursor 2.0 (up to eight agents from a single prompt, isolated in git worktrees) is a third flavour - local, not cloud, one-shot rather than delegated.
Copilot Chat in VS Code ships a native Subagents primitive (current as of 2026-07): the main agent calls a runSubagent tool to spawn a worker in its own context window, optionally in parallel with others, and gets a summary back - the same shape as Claude Code’s Agent tool, different plumbing.
Any custom agent doubles as a subagent. A custom agent (.agent.md, discovered at .github/agents/, or the Claude-compatible .claude/agents/) is dual-purpose: pick it from the chat agents dropdown to switch personas, or let another agent delegate to it via runSubagent - same file, two invocation paths. Relevant frontmatter:
---name: security-reviewertools: ['agent'] # lets THIS agent delegate to othersagents: ['security-reviewer', 'perf-checker'] # who it may delegate to ('*' = all, [] = none)model: ['Claude Opus 4.5', 'GPT-5.2'] # tried in orderuser-invocable: true # show in the chat pickerdisable-model-invocation: false # allow other agents to invoke this one as a subagent---Invocation is agent-initiated, not typed by you - the coordinating agent decides isolation helps and calls runSubagent on its own; natural-language hints (“investigate X in isolation,” “run these in parallel”) are enough to nudge it. This is a different invocation model from Claude Code’s Agent tool, which a user can also trigger by name.
Parallel and nested execution: subagents can run side by side - e.g. security/perf/accessibility reviewer agents over one diff, or the same task across two models for comparison. Nesting is off by default; a subagent can’t spawn its own subagents until chat.subagents.allowInvocationsFromSubagents is enabled, at which point nesting goes up to depth 5.
Copilot Extensions (@extension-name in Chat) are a separate thing: full external agents running on the extension provider’s servers, not isolated sub-contexts of your local session. Examples: @docker, @sentry. Distributed via GitHub Marketplace.
Copilot Coding Agent (cloud, GitHub Actions-backed) is also separate from the in-session primitive above - an async hand-off that returns a PR, not a subagent inside your current session. Reach for it when the isolation needs to outlive the session, not just a subroutine within it.
No built-in subagents. Pi doesn’t ship a subagent primitive or a dispatch tool for spawning scoped workers the way Claude Code or Codex do.
Ways to approximate it:
tmux-spawned Pi instances. Since Pi is just a CLI process, running additionalpisessions in separate tmux panes (or windows) and coordinating between them by hand is a low-effort way to get parallel, isolated contexts.- Extension or package. The repo’s
examples/extensions/includes a subagent example showing the pattern for having one Pi process programmatically spawn another via the ExtensionAPI, capture its output, and fold it back into the parent’s context. - Community packages exist for this, but treat them as third-party rather than official - install one deliberately (see Plugins) rather than assuming subagent orchestration is a stock capability.
The underlying idea - pi spawning pi - is the same shape as Claude Code’s Task tool, just assembled from primitives instead of shipped as a first-class feature.
Comparison
Section titled “Comparison”| Aspect | Claude Code | Codex | OpenCode | Cursor | Copilot | Pi |
|---|---|---|---|---|---|---|
| Built-in subagents | Explore, Plan, general-purpose | default, worker, explorer | general, explore, scout | None by default | None named - native runSubagent/agent tool spawns isolated subagents | None |
| Custom subagent path | .claude/agents/*.md | .codex/agents/*.toml | .opencode/agents/*.md | .cursor/agents/*.md (also reads .claude/agents/, .codex/agents/) | .github/agents/*.agent.md (also reads .claude/agents/) - any custom agent doubles as a subagent | No native primitive - via extension/package, or spawn a second pi process (e.g. in tmux) |
| Invocation | Via Agent tool from parent | Natural-language dispatch from parent | @<name> mention | Auto-delegation, /name, or natural-language mention | Agent-initiated via runSubagent; not typically user-invoked by name | Whatever the extension/package defines; or manual (separate pi session) |
| Tool restriction | Frontmatter tools: field | No explicit allowlist field; shape via mcp_servers / sandbox_mode | permission (preferred) or deprecated tools | Frontmatter readonly flag | Frontmatter tools: (own surface) and agents: (allowed delegates) | - |
| Skill preload | Frontmatter skills: field | TOML skills.config field | Via permission.skill rules | - | - | - |
| Inherits parent history | No | No | No | No | No | N/A (no built-in concept) |
| Peer-to-peer coordination | Agent teams (experimental) | Via Agents SDK | - | - | Custom-agent handoffs | - |
Name collisions
Section titled “Name collisions”- “Agent” in OpenCode - usually means a primary agent (
build,plan) you switch into with Tab. “Subagent” is reserved for a worker the primary spawns. - “Agent” in Claude Code - colloquially means a subagent, unless someone says “agent team.”
- “Custom agent” in Copilot - one
.agent.mdfile, dual-purpose: a persona you pick from the chat dropdown, or a subagent another agent delegates to viarunSubagent. Two invocation paths, not two separate primitives. - Subagent vs Agent team (Claude Code) - a subagent returns a summary; an agent team is a set of independent peer sessions that communicate directly and share a task list.
- Don’t confuse the Codex CLI’s child agents with the OpenAI Agents SDK, which is a separate framework for production multi-agent orchestration.
- Cursor Cloud Agents (formerly Background Agents) and Copilot Coding Agent both run in isolated remote sandboxes and return a PR - they’re closer to “async hand-off” than “in-session subagent.” Treat them as a separate primitive when comparing.
Next time a task is about to fill your window with work you’ll never look at again, ask what you actually need back. If the answer is a paragraph rather than the trail that produced it, delegate it - and write the brief, because a subagent starts with none of what you already know. That discarded window is the isolated cost profile in practice: paid for once, never carried.