Skip to main content

Subagents

Subagents are specialized roles that the main session can temporarily delegate to. The Qoder CN Agent SDK supports two kinds of subagents:
  • Built-in subagents: provided by qodercli, such as general-purpose search, code exploration, and planning.
  • Custom subagents: defined by SDK consumers via options.agents, suitable for specialized roles such as business review, test execution, and security analysis.
This article focuses on how to use built-in subagents in the SDK, and how to customize subagents as needed. You can read it in order, or jump to a section for a specific configuration option. See the Agents Reference for the complete type definitions. Unless otherwise noted, "Agent" in this article refers to a subagent that can be delegated to by the main session; options.agent is a special usage that runs a subagent definition as the main session's role.

Built-in Subagents

When using a built-in subagent, you don't need to write a subagent definition yourself. You only need to know its name and reference it in the SDK. Common built-in subagents currently in qodercli:
NamePurpose
general-purposeA general-purpose subagent, suitable for searching code, researching complex problems, and executing multi-step tasks
ExploreA read-only code exploration subagent, suitable for quickly locating files, searching for keywords, and understanding code structure
PlanA read-only planning subagent, suitable for designing implementation plans, identifying key files, and analyzing architectural trade-offs
The list of built-in subagents changes with the qodercli version and current configuration. In the interactive CLI you can type /agents to view the subagents currently discovered; on the command line you can also run:
qodercli agents list
After an SDK session is initialized, you can use q.supportedAgents() to read the subagents actually available in the current session:
import { query } from '@qoder-ai/qoder-agent-sdk';

const q = query({ prompt: 'List available agents.' });
const agents = await q.supportedAgents();
The list returned by q.supportedAgents() includes subagents registered by the SDK via options.agents, as well as the built-in, user, project, and plugin subagents that the current CLI has discovered and that are applicable to SDK scenarios. general-purpose, Explore, and Plan can appear in SDK sessions by default; the interactive-CLI helper subagents qoder-guide and statusline-setup are not supported in SDK sessions and do not appear in q.supportedAgents(). See AgentInfo for the returned structure.

Using Built-in Subagents

Running as the Main Session Role

If you want the entire session to run as a certain built-in subagent's role, you can pass the built-in subagent name directly to options.agent without redefining it in options.agents.
import { query } from '@qoder-ai/qoder-agent-sdk';

const q = query({
  prompt: 'Summarize this project architecture and identify the most important modules.',
  options: {
    agent: 'general-purpose',
  },
});
options.agent can reference a subagent registered by the SDK, or a built-in / user / project / plugin subagent that the current CLI has discovered and that is applicable to SDK scenarios.

Delegating as a Subagent

Subagent delegation is done through the built-in Agent tool. The main session's available tool set must include Agent so that the model has an entry point to initiate delegation; a common practice in the SDK is to pre-authorize this tool-call path, then call it out by name in the prompt.
const q = query({
  prompt: 'Use the Explore agent to find where authentication is implemented.',
  options: {
    // Pre-authorize Agent tool calls. If options.tools restricts the tool set, include 'Agent' there too.
    allowedTools: ['Agent'],
  },
});
allowedTools: ['Agent'] means allowing / pre-authorizing this kind of tool call; if you also use options.tools to narrow the main session's available tool allowlist, you must include Agent in tools as well. Do not put Agent in disallowedTools. The subagent name must match the current discovery result, including case. For example, the current built-in names include Explore, Plan, and general-purpose. When unsure, call q.supportedAgents() first.

Custom Subagents

When built-in subagents don't fit your business or project constraints well enough, you can customize subagents via options.agents. For example:
  • A read-only code review subagent: can only read files and search, and cannot modify code.
  • A test execution subagent: can run test commands and analyze failure causes.
  • A security review subagent: focuses only on risks such as authentication, authorization, injection, and sensitive information leakage.
  • A business support subagent: can only call specified MCP tools, such as order lookup, ticket retrieval, and internal knowledge base search.
Customizing a subagent usually involves three steps:
  1. In options.agents, define the subagent's name, purpose description, and system prompt.
  2. Use tools or disallowedTools to constrain which tools it can use.
  3. Let the main session delegate to it through the Agent tool, or use options.agent to have it drive the main session directly.
The Agent tool must be included: a custom subagent needs the main session to initiate delegation through the built-in Agent tool, so allowedTools must include the Agent tool.

Customizing Subagents with options.agents

A minimal example: register a read-only code review subagent.
import { query } from '@qoder-ai/qoder-agent-sdk';

const q = query({
  prompt: 'Use the code-reviewer agent to review the authentication module.',
  options: {
    // Pre-authorize Agent tool calls. If options.tools restricts the tool set, include 'Agent' there too.
    allowedTools: ['Agent'],
    agents: {
      'code-reviewer': {
        description:
          'Reviews code for correctness, security issues, and maintainability problems.',
        prompt: `You are a code review specialist.
Review the requested code and report concrete findings.
Sort findings by severity and include file paths when possible.`,
        tools: ['Read', 'Grep', 'Glob'],
      },
    },
  },
});

for await (const message of q) {
  // Consume streamed messages according to your application needs.
}
There are three key points in this example: options.agents registers the custom subagents available for this session.
  • Subagent delegation happens through the Agent tool; here you must use allowedTools: ['Agent'] to pre-authorize this call path.
  • The subagent's own tools allow only reading and searching, so it cannot modify files or execute commands.
options.agents Parameters options.agents is a mapping from subagent names to subagent definitions. See AgentDefinition for the complete type.
FieldTypeRequiredHow to FillDescription
descriptionstringYesA one-sentence explanation of when to use this subagentRouting description for the model; affects whether it gets called
promptstringYesThe subagent's role, boundaries, and output requirementsThe subagent's system prompt
toolsstring[]Noe.g. ['Read', 'Grep', 'Glob']Tool allowlist; once configured, only the listed tools can be used
disallowedToolsstring[]Noe.g. ['Bash', 'Write']Tool blocklist; suitable for excluding just a few tools
modelstringNoe.g. 'inherit', 'auto', 'performance'The subagent's model configuration
maxTurnsnumberNoe.g. 8Limits the maximum number of turns the subagent runs
effortEffortLevelNoe.g. 'low', 'medium', 'high', 'max'Controls the reasoning effort level
permissionModePermissionModeNoe.g. 'default', 'acceptEdits', 'plan'Controls the permission mode for the subagent's internal tool calls
skillsstring[]Noe.g. ['review']Skills preloaded into the subagent's context
mcpServersAgentMcpServerSpec[]NoMCP server name or configurationRestricts or adds MCP servers for the subagent
initialPromptstringNoAutomatic first-turn inputOnly takes effect when this subagent becomes the main session role via options.agent

Configuring the Subagent Role

description and prompt are the two most important fields for a custom subagent.
description description describes "when this subagent should be used." The model decides whether to delegate based on it.
description:
  'Runs project tests, analyzes failing output, and suggests fixes.'
A good description should specifically state the task boundaries. Don't write generic descriptions like A helpful agent or Helper.
prompt prompt defines the subagent's role, boundaries, and output style. TypeScript users will get a type-check error if they don't pass prompt; JavaScript users should always pass this field as well.
prompt: `You are a code review specialist.
Only review the requested code; do not edit files.
Return findings sorted by severity, with file paths and suggested fixes.`
If prompt is written only vaguely, like "you are a helpful assistant," the model may still call this subagent, but its behavior will be close to that of an ordinary assistant: it won't know what to check first, what not to do, or how to return results. We recommend that prompt state at least three things:
What to StateExample
What task it's responsible forReview code for security and maintainability issues.
What it shouldn't doDo not edit files. Do not run commands.
How to return resultsReturn findings sorted by severity with file paths.

Configuring the Subagent's Model and Reasoning

Write description and prompt clearly first, then consider model, effort, and maxTurns. The former determine whether the subagent gets called correctly and whether it knows its boundaries once called; the latter are mainly used to tune effectiveness, speed, and cost after the role is already clear.
ConfigurationWhat It ControlsWhen to Adjust First
modelSelects the model tier the subagent usesThis subagent takes on a fixed type of task long-term and needs stable control over capability and Credit cost
effortControls how much reasoning budget to spend within the same modelThe same subagent occasionally encounters more complex tasks that require more careful reasoning
maxTurnsLimits the maximum number of turnsThe task may explore too deeply, run too long, or you want to set a hard cap on cost
You can decide in this order:
  1. By default, configure nothing, or set model: 'inherit' to have the subagent follow the main session's model.
  2. If this subagent handles high-frequency, simple tasks that can tolerate rough answers, use model: 'efficient' or model: 'lite' to reduce cost.
  3. If this subagent takes on high-risk tasks such as architecture design, complex refactoring, or cross-module review, use model: 'performance' or model: 'ultimate' to raise the capability ceiling.
  4. If the model tier stays the same but you want it to think a bit more on the current task, raise effort.
  5. If you're worried about runaway exploration, use maxTurns to set a cap on the number of execution turns.
Common combinations:
ScenarioRecommended ConfigurationDescription
Quick Q&A, format conversion, simple lookupmodel: 'efficient', effort: 'low', maxTurns: 3Cheap and fast, suitable for low-risk tasks
Read-only code exploration, mapping module relationshipsmodel: 'auto' or 'inherit', effort: 'medium'Let routing or the main session model decide the capability tier
Code review, security review, migration plansmodel: 'performance', effort: 'high'Better suited for tasks that require careful trade-offs and problem discovery
Complex system design, high-difficulty problem analysismodel: 'ultimate', effort: 'high' or 'max'Higher cost; recommended only for critical, complex tasks
Batch assistant subtasksmodel: 'efficient', effort: 'low', smaller maxTurnsSuitable for controlling total cost when multiple subagents collaborate
Example: configure different strategies for different subagents.
agents: {
  explorer: {
    description: 'Quickly searches code and summarizes relevant files.',
    prompt: 'Find relevant files and return a concise summary. Do not edit.',
    tools: ['Read', 'Grep', 'Glob'],
    model: 'efficient',
    effort: 'low',
    maxTurns: 5,
  },
  architect: {
    description: 'Designs complex implementation plans across modules.',
    prompt: 'Analyze tradeoffs carefully and return an implementation plan with risks.',
    tools: ['Read', 'Grep', 'Glob'],
    model: 'performance',
    effort: 'high',
    maxTurns: 10,
  },
}
For the complete set of allowed values for each field, see Agents Reference - model, Agents Reference - maxTurns, and Agents Reference - effort.

Controlling Subagent Tools

Custom subagents use the same tool names as the main session. Built-in tool names include Read, Grep, Glob, and Bash; custom MCP tool names use the full format mcp__{serverName}__{toolName}. This part configures which tools the subagent can see and call.

The Agent Tool on the Main Session Side

options.agents only registers subagents; it does not automatically call them on the model's behalf. For the model to delegate a task, Agent must exist in the main session's tool set. The default tool set usually registers it; if you use options.tools to restrict the main session's available tools, remember to include Agent; if you set disallowedTools: ['Agent'], delegation will be disabled.

Tool Allowlist: tools

tools is the subagent's tool allowlist. Once configured, this subagent can only use the listed tools.
tools: ['Read', 'Grep', 'Glob']
Common tool combinations:
ScenarioRecommended ToolsDescription
Read-only analysisRead, Grep, GlobCan view code but cannot modify it or execute commands
Running testsBash, Read, GrepCan execute test commands and analyze output
Writing codeRead, Edit, Write, Grep, GlobCan read and write files, but cannot run commands directly
Calling business toolsmcp__server__toolOnly allows calling the specified custom tools

Tool Blocklist: disallowedTools

disallowedTools is suitable for the "allow most tools, exclude only a few" scenario.
disallowedTools: ['Bash', 'Write']
Generally, do not set both tools and disallowedTools, unless you know the final tool set exactly.

Relationship with the Main Session's Tool Configuration

A subagent's tools / disallowedTools apply only to itself, and do not inherit the main session's tool allowlist or blocklist restrictions. Even if the main session only pre-authorizes the Agent delegation path, the subagent can still use its own configured tools such as Read and Grep.
query({
  prompt: 'Use the analyst agent to inspect the repository.',
  options: {
    // Pre-authorize the main session to call the Agent tool.
    allowedTools: ['Agent'],
    agents: {
      analyst: {
        description: 'Reads and summarizes code structure.',
        prompt: 'Inspect relevant files and return a concise summary. Do not edit files.',
        tools: ['Read', 'Grep', 'Glob'],
      },
    },
  },
});

Controlling Subagent Permissions

The tool set determines "which tools a subagent can call," while permission configuration determines "how those tool calls are approved or blocked." You can configure permissionMode individually on a subagent to control the permission behavior of its internal tool execution.

Permission Mode: permissionMode

agents: {
  planner: {
    description: 'Plans implementation work without making changes.',
    prompt: 'Read relevant files and return an implementation plan. Do not edit files.',
    tools: ['Read', 'Grep', 'Glob'],
    permissionMode: 'plan',
  },
}
For the complete set of allowed values and semantics of permissionMode, see Agents Reference - permissionMode. If the host needs to approve tool calls one by one, you can use the session-level canUseTool callback;

Loading Skills for a Subagent

skills is used to preload specialized skills into a particular subagent. It's suitable for binding a specific workflow, team convention, or tool usage to a single subagent, rather than stuffing it into every call's prompt.
agents: {
  reviewer: {
    description: 'Reviews pull requests using the team review workflow.',
    prompt: 'Review the requested changes and return actionable findings.',
    tools: ['Read', 'Grep', 'Glob'],
    skills: ['review'],
  },
}
Usage recommendations:
ScenarioHow to Configure
The subagent always works according to a specific specialized processWrite the corresponding skill into that subagent's skills
Only the main session needs a certain skillUse the session-level options.skills; don't put it in the subagent
A skill provided by a pluginUse the plugin-qualified name, e.g. sdk-test-plugin:sdk-echo
A subagent's skills only affects that subagent's context, and is not equivalent to the main session's options.skills. For session-level skill behavior, see Skills.

Configuring the Subagent's mcpServers

mcpServers is used to restrict or add MCP servers for a subagent. It's suitable for exposing business tools only to the subagent that needs them, such as order lookup, ticket retrieval, and internal knowledge base search. You can reference an MCP server already configured in the session:
const q = query({
  prompt: 'Use the support agent to check the latest order status.',
  options: {
    mcpServers: {
      orders: {
        type: 'stdio',
        command: 'node',
        args: ['servers/orders.js'],
      },
    },
    allowedTools: ['Agent'],
    agents: {
      support: {
        description: 'Answers customer support questions using order tools.',
        prompt: 'Use order tools when needed and return a concise answer.',
        mcpServers: ['orders'],
        tools: ['mcp__orders__get_order'],
      },
    },
  },
});
You can also configure a dedicated MCP server for a particular subagent:
agents: {
  knowledge: {
    description: 'Searches the internal knowledge base.',
    prompt: 'Search the knowledge base and cite the relevant entries.',
    mcpServers: [
      {
        kb: {
          type: 'stdio',
          command: 'node',
          args: ['servers/kb.js'],
        },
      },
    ],
    tools: ['mcp__kb__search'],
  },
}
Usage recommendations:
ScenarioHow to Configure
Multiple subagents share the same MCP serverConfigure the server at the session level in options.mcpServers, then reference the name in the subagent's mcpServers
Only a certain subagent needs business toolsPut the server in that subagent's mcpServers, and use tools to restrict which tools can be called
You only want to call a specific MCP toolAlso configure tools: ['mcp__server__tool'] to avoid exposing all of the server's tools
For the MCP server configuration structure, see MCP and Agents Reference - mcpServers.

Invoking Subagents

There are three common ways to invoke a subagent.

Automatic Invocation

The model automatically decides whether to invoke a subagent based on the task and each subagent's description. Writing a clear description improves matching accuracy.
agents: {
  tester: {
    description: 'Runs tests and analyzes test failures.',
    prompt: 'Run relevant tests and explain any failures clearly.',
    tools: ['Bash', 'Read', 'Grep'],
  },
}

Explicit Invocation by Name

If you want the model to use a certain subagent, you can call it out by name in the prompt.
const q = query({
  prompt: 'Use the tester agent to run the unit tests and summarize failures.',
  options: {
    // Pre-authorize Agent tool calls. If options.tools restricts the tool set, include 'Agent' there too.
    allowedTools: ['Agent'],
    agents: {
      tester: {
        description: 'Runs tests and analyzes failures.',
        prompt: 'Run the requested tests and explain failures clearly.',
        tools: ['Bash', 'Read', 'Grep'],
      },
    },
  },
});

Running as the Main Session Role

options.agent lets the main session run directly as a certain subagent.
const q = query({
  prompt: 'Plan the refactor for the payment module.',
  options: {
    agents: {
      planner: {
        description: 'Plans implementation work before code changes.',
        prompt: 'Break the task into clear steps, risks, and validation checks.',
        tools: ['Read', 'Grep', 'Glob'],
        model: 'inherit',
      },
    },
    agent: 'planner',
  },
});
options.agent can reference a custom subagent in options.agents, or a built-in / user / project / plugin subagent that the current CLI has discovered.

Subagent Context and Results

A subagent runs in an isolated context. It receives its own system prompt and the delegation prompt, but does not directly inherit the parent session's full history.
What the Subagent Can SeeWhat the Subagent Cannot See
Its own promptThe parent session's full conversation history
The task prompt passed in by the main session via the Agent toolThe parent session's intermediate tool results
Its own available tool definitionsThe parent session's private reasoning process that wasn't passed to it
Skills preloaded per configurationOther agents' intermediate contexts
The main channel for the parent session to pass information to a subagent is the task prompt passed in when calling the Agent tool. Therefore, if a subagent needs specific file paths, error messages, or business context, the main session should pass them explicitly when delegating. After a subagent completes, the parent session receives its final return, not the full context of every one of its internal tool calls. This is also the main value of using subagents to isolate context.

Combined Examples

Multi-role Collaboration

Register multiple subagents with different roles, and let the main session decide whether and when to invoke them based on task needs.
const q = query({
  prompt: 'Add input validation to the user registration endpoint.',
  options: {
    // Pre-authorize Agent tool calls. If options.tools restricts the tool set, include 'Agent' there too.
    allowedTools: ['Agent'],
    agents: {
      researcher: {
        description: 'Reads existing code to understand patterns and constraints.',
        prompt: 'Research relevant files and report implementation constraints. Do not edit.',
        tools: ['Read', 'Grep', 'Glob'],
        maxTurns: 8,
      },
      implementer: {
        description: 'Implements code changes following existing project conventions.',
        prompt: 'Implement the requested change with minimal, idiomatic edits.',
        tools: ['Read', 'Edit', 'Write', 'Grep', 'Glob'],
        maxTurns: 12,
      },
      tester: {
        description: 'Runs tests and explains failures.',
        prompt: 'Run relevant tests, summarize results, and identify failing cases.',
        tools: ['Bash', 'Read', 'Grep'],
        maxTurns: 6,
      },
    },
  },
});

Automatically Executing the First-turn Task After Startup

initialPrompt takes effect only when the subagent becomes the main session role via options.agent:
const q = query({
  prompt: '',
  options: {
    agents: {
      auditor: {
        description: 'Audits code for security risks.',
        prompt: 'Scan code for security risks and produce a concise report.',
        initialPrompt: 'Start with the authentication and session management code.',
        tools: ['Read', 'Grep', 'Glob'],
        effort: 'high',
      },
    },
    agent: 'auditor',
  },
});
If auditor is invoked by the main session as a subagent through the Agent tool, initialPrompt is ignored.

Common Pitfalls

  • When using a built-in subagent directly, don't redefine a subagent with the same name in options.agents, unless you explicitly want to override it.
  • Invoking a subagent depends on the main session's Agent tool. allowedTools: ['Agent'] is pre-authorization; if you use options.tools to restrict the main session's available tools, include Agent as well.
  • The subagent name must match the case of the current discovery result, e.g. Explore and Plan start with an uppercase letter. description is responsible for telling the model when to invoke; prompt is responsible for telling the subagent what to do once invoked.
  • A subagent cannot spawn its own subagents. Don't put Agent in a subagent's tools. initialPrompt only takes effect for the main session role specified by options.agent, and is ignored when delegated to as a subagent.
  • A subagent's dedicated MCP server can be configured via mcpServers; for MCP connection methods, see MCP.

Further Reading

  • Agents Reference: complete reference for AgentDefinition, AgentInfo, options.agent, and options.agents.
  • Tools: built-in tools, custom tools, and tool permissions.
  • Permission Control: permissionMode, allowedTools, canUseTool.
  • Skills: session-level and subagent-level skill configuration.