Sub-agents in Deep Agents: handing off focused work
The highest-leverage move a deep agent makes is delegation — spinning up a focused sub-agent for a slice of work so the main agent's context stays clean. Here's how sub-agents work and when to use them.
The Deep Agents post listed sub-agents as one of the four things that make an agent 'deep'. It's worth its own post, because delegation is the move that does the most work: it's how a deep agent takes on a task too big for one context window and keeps its head. This is the same idea as the supervisor pattern from the multi-agent post — here it's a first-class feature you configure in one place.
Why delegate: context isolation
The reason to hand off isn't parallelism — it's keeping context clean. A research sub-task might make dozens of tool calls and read pages of material. If all of that lands in the main agent's context window, it bloats fast and the main agent loses the plot (the failure modes from the agent-loops and memory posts). A sub-agent does that verbose work in its own isolated context, and the main agent receives only the final result — not the dozens of tool calls that produced it. Delegation is context engineering by another name.
Defining a sub-agent
You pass a list of sub-agents to create_deep_agent via the subagents parameter. Each one is a small dict: a name, a description, and a system_prompt, plus optionally its own tools, model, and skills. The description is the important field — it's what the main agent reads to decide when to delegate, so write it like a job posting: say exactly what this sub-agent is for.
from deepagents import create_deep_agent
research_subagent = {
'name': 'researcher',
'description': 'Researches a topic in depth. Delegate anything needing many searches.',
'system_prompt': 'You are a thorough researcher. Search, read, and report findings.',
'tools': [internet_search], # optional: only what this sub-agent needs
'model': 'openai:gpt-4o', # optional: override the main model
}
agent = create_deep_agent(
model='openai:gpt-4o',
instructions='You are a lead. Delegate research to the researcher sub-agent.',
subagents=[research_subagent],
)How the hand-off happens
The main agent delegates through a built-in task() tool: it calls task with the sub-agent's name and a description of the work to do. The call is synchronous — the main agent waits for the sub-agent to finish and gets its result back, then continues. So from the main agent's point of view, delegating a whole chunk of work looks like calling one high-level tool, which is exactly why it keeps the main thread readable.
Each sub-agent can be specialised
- Its own system_prompt — focused instructions for its job; it doesn't inherit the main agent's prompt.
- Its own tools — give it only what the sub-task needs, which is least privilege applied to agents (see the tool-calling post).
- Its own model — a cheap, fast model for a simple sub-task, or a stronger one for hard reasoning, without changing the main agent.
- Its own skills — SKILL.md capabilities scoped to that sub-agent (see the Agent Skills post).
When to use sub-agents — and when not
Reach for a sub-agent when a slice of work is verbose, specialised, or context-heavy enough that you don't want it polluting the main thread: deep research, a self-contained coding change, a review pass. Don't split work that's cheap and inline — every sub-agent is another agent to reason about, and as the multi-agent post argues, usually you don't need one. The test is simple: does isolating this work keep the main agent clearer and its context leaner? If yes, delegate; if not, just do it in the main loop.
A sub-agent isn't about doing two things at once — it's about doing one messy thing somewhere else, so the agent in charge only ever sees the clean result.