Skip to content

Deep agent

A deep agent performs hierarchical task decomposition — it asks the LLM whether the input can be solved directly, and if not, breaks it into subtasks and recurses. Leaf subtasks (or anything at max_depth) are solved through a ReAct sub-loop, then the agent synthesises the subtask results into a final answer. Pick this for open-ended tasks where the depth of decomposition isn't known up front — research-heavy questions, "do the whole thing" requests, multi-part analyses.

Type identifier

YAML form:

agents:
  - id: deep-researcher
    type: deep
    model: { ... }
    deep_max_depth: 3
    tools: [ ... ]

What it does

runDeep in pkg/agent/adk/run_orchestration.go is a thin entry point — deepDecompose(ctx, task, depth=0, maxDepth) does the work:

  1. At depth >= maxDepth — short-circuit and solve directly with runReAct(ctx, task). No more decomposition attempts.
  2. Below max depth — issue a Model.Generate call with this decision prompt:
Analyze this task and decide: can it be solved directly, or
should it be broken into subtasks?
If it can be solved directly, respond with: {"direct": true}
If it needs decomposition, respond with:
  {"direct": false, "subtasks": ["subtask1", "subtask2", ...]}
Task: <input>
  1. Parse the JSON. If the response is {"direct": true}, the JSON is malformed, or subtasks is empty → solve directly via runReAct.
  2. Otherwise recurse: for each subtask call deepDecompose(ctx, subtask, depth+1, maxDepth). Collect results into a markdown digest:
## Subtask 1: <text>
<result>

## Subtask 2: <text>
<result>
  1. After all subtasks complete, synthesise a final answer by calling runReAct with:
Original task: <input>
Subtask results: <digest>
Synthesize a final comprehensive answer.

The ReAct sub-loop may itself call tools to refine / verify the synthesis.

Every recursion level emits a decompose debug event with the depth and task preview so a tracer can render the full tree.

Configuration

Deep accepts every ReAct field (see react) plus:

Field Type Default Description
deep_max_depth int 3 Maximum recursion depth. At depth >= this value, the agent solves with runReAct directly instead of decomposing further. Zero is coerced to 3 by New.
max_iterations int 10 Per-ReAct cap for every leaf and synthesis call — applies inside each runReAct invocation, not across the recursion.

All other ReAct-shaped fields (tools, memory, guardrails, budget, approval_*, tool_retry, governance) apply to the inner ReAct sub-loops and synthesis calls.

Behavior notes

  • The decomposition phase is a single Model.Generate call — fast, but if it returns malformed JSON the agent just solves directly. There is no re-prompt or fallback parser.
  • Token consumption can blow up exponentially: at max_depth=3 with three subtasks per level you'll see up to 1 + 3 + 9 + 9 ≈ 22 ReAct sub-loops, each up to max_iterations LLM calls plus their tool calls. Always set a budget: for production.
  • The final synthesis is itself a ReAct loop, so tool calls happen there too — useful for verification ("re-fetch the most recent number before finalising").
  • The decomposition prompt is prepended to the agent's system prompt verbatim. Customise the system prompt to bias what "subtask" means in your domain.
  • Sub-agents (sub_agents:) are NOT used by deep. Everything is the same agent recursing on itself.
  • Streaming is not supported — RunStream falls back to non-streaming and replays the final text as word chunks.

Example

A deep research agent producing a structured report:

agents:
  - id: deep-researcher
    type: deep
    deep_max_depth: 2
    max_iterations: 8
    model:
      provider: anthropic
      model: claude-sonnet-4-7
    system_prompt: |
      You are a research analyst. Break complex questions into the
      smallest meaningful sub-questions, gather sources, then write
      a citation-rich synthesis.
    tools:
      - { name: web-fetch, type: function, function: web.fetch }
      - { name: read-file, type: function, function: fs.read }
    budget:
      max_tool_calls: 60
      max_input_tokens: 800000

Source

  • pkg/agent/adk/run_orchestration.go — runDeep and deepDecompose (the recursion).
  • pkg/agent/adk/agent.go — Run dispatch on TypeDeep, DeepMaxDepth field on AgentConfig, default-3 coercion in New.
  • pkg/workflow/definition.go — AgentDefinition.DeepMaxDepth.

See also

  • plan-execute — flat plan-then-execute (one level of decomposition).
  • react — the leaf executor that solves each subtask.
  • loop — single-LLM iterative refinement.