# Understanding the Qwen Code SubAgent Architecture: How to Create Custom Sub-Agents

> Explore the Qwen Code SubAgent architecture to delegate tasks to isolated sub-agents. Learn how to create custom sub-agents using Markdown or APIs for specialized functions.

- Repository: [Qwen/qwen-code](https://github.com/qwenlm/qwen-code)
- Tags: architecture
- Published: 2026-02-19

---

**The Qwen Code SubAgent architecture enables a primary AI agent to delegate specialized tasks to isolated sub-agents defined via Markdown files or programmatic APIs, each with distinct system prompts, tool permissions, and model configurations.**

Qwen Code implements a sophisticated delegation system that treats specialized agents as first-class citizens. The SubAgent architecture allows the primary AI to offload domain-specific work to isolated agents with custom capabilities, configured through YAML-fronted Markdown files or TypeScript APIs. This design separates static agent definitions from dynamic execution scopes, enabling users to extend Qwen Code's functionality without modifying core engine code.

## What Is the SubAgent Architecture?

The SubAgent architecture is a delegation framework where a primary AI agent distributes work to specialized, isolated agents. Each sub-agent operates as an independent entity with its own **system prompt**, **tool allowances**, and **model configuration**, ensuring clean separation of concerns and configurable isolation.

According to the Qwen Code source code, the architecture distinguishes between **definition** (static configuration) and **execution** (dynamic runtime scope). Definitions are stored as Markdown files with YAML front-matter or managed programmatically through the `SubagentManager` class. The system supports five storage levels—`builtin`, `project`, `user`, `extension`, and `session`—with precedence resolving from session (highest) down to builtin (lowest). The `SubagentLevel` type definition in [`packages/sdk-typescript/src/types/types.ts`](https://github.com/QwenLM/qwen-code/blob/main/packages/sdk-typescript/src/types/types.ts) (lines 10-16) formalizes these persistence layers.

## Core Components of the SubAgent System

### SubagentConfig and Storage Levels

Every sub-agent conforms to the `SubagentConfig` interface defined in [`packages/sdk-typescript/src/types/types.ts`](https://github.com/QwenLM/qwen-code/blob/main/packages/sdk-typescript/src/types/types.ts) (lines 30-48). This interface specifies:

- **name**: Unique identifier for the agent
- **description**: Human-readable purpose statement
- **tools**: Array of permitted tool identifiers (e.g., `read_file`, `edit`)
- **modelConfig**: LLM parameters including model name and temperature
- **runConfig**: Execution constraints like `max_time_minutes` and `max_turns`
- **systemPrompt**: Behavioral instructions templated at runtime

Storage levels determine where configurations persist. **Builtin** agents reside in `BuiltinAgentRegistry` ([`packages/core/src/subagents/builtin-agents.ts`](https://github.com/QwenLM/qwen-code/blob/main/packages/core/src/subagents/builtin-agents.ts)) and are immutable. **Project** and **user** level agents serialize to `.qwen/agents/` directories, while **session** agents exist only in memory for the current runtime.

### SubagentManager

The `SubagentManager` class in [`packages/core/src/subagents/subagent-manager.ts`](https://github.com/QwenLM/qwen-code/blob/main/packages/core/src/subagents/subagent-manager.ts) orchestrates the sub-agent lifecycle. It handles discovery, validation, caching, and CRUD operations.

Key methods include:

- **`loadSubagent(name)`**: Resolves configurations respecting level precedence (session > project > user > builtin)
- **`createSubagentScope`**: Converts stored configurations into runtime objects at lines 86-95, producing `PromptConfig`, `ModelConfig`, `RunConfig`, and `ToolConfig` instances
- **`convertToRuntimeConfig`**: Transforms static definitions into execution-ready parameters

The manager maintains an in-memory `subagentsCache` to avoid redundant disk I/O during lookups.

### SubAgentScope and Execution

The `SubAgentScope` class in [`packages/core/src/subagents/subagent.ts`](https://github.com/QwenLM/qwen-code/blob/main/packages/core/src/subagents/subagent.ts) implements the actual execution engine. When invoked via `runNonInteractive`, the scope:

1. Builds a chat context templating `${…}` placeholders with current `ContextState`
2. Streams model responses through the chat interface
3. Dispatches tool calls via `CoreToolScheduler`
4. Aggregates tool results into subsequent context rounds
5. Returns `finalText` alongside a termination mode (`GOAL`, `TIMEOUT`, or `ERROR`)

Execution emits lifecycle events through `SubAgentEventEmitter`, including `START`, `ROUND_START`, `TOOL_CALL`, `TOOL_RESULT`, and `FINISH`, enabling real-time UI feedback and telemetry collection.

### Task Tool Invocation

Primary agents invoke sub-agents through the **Task** tool implemented in [`packages/core/src/tools/task.ts`](https://github.com/QwenLM/qwen-code/blob/main/packages/core/src/tools/task.ts). The tool accepts a `subagent_type` parameter specifying the target agent name. Internally, `TaskTool` delegates to `SubagentManager` to load the configuration, instantiate a `SubAgentScope`, and execute the non-interactive run loop.

## How to Create Custom Sub-Agents

### Method 1: Markdown Definition Files

The simplest approach creates a Markdown file with YAML front-matter. Save the following to `~/.qwen/agents/code-reviewer.md` (user-level) or [`PROJECT_ROOT/.qwen/agents/code-reviewer.md`](https://github.com/QwenLM/qwen-code/blob/main/PROJECT_ROOT/.qwen/agents/code-reviewer.md) (project-level):

```markdown
---
name: code-reviewer
description: |
  Use this agent to review a recently-added function and suggest improvements.
tools:
  - read_file
  - write_file
  - edit
modelConfig:
  model: qwen3-coder-plus
  temp: 0.2
runConfig:
  max_time_minutes: 5
  max_turns: 10
color: auto
---

You are a code-review specialist. The user will provide a snippet of TypeScript code.
Your task is to:
1. Analyse the code for correctness, style and performance.
2. Suggest concrete improvements and, if possible, emit the updated source file using the **edit** tool.
Only respond with the revised code block and a short rationale.

```

The fields map directly to the `SubagentConfig` interface. The `SubagentManager` automatically discovers these files on startup via the discovery mechanism that populates `subagentsCache`.

### Method 2: Programmatic Creation with SubagentManager

For dynamic agent creation, instantiate `SubagentManager` and call `createSubagent`:

```typescript
import { Config } from 'qwen-code/packages/core/src/config/config.js';
import { SubagentManager } from 'qwen-code/packages/core/src/subagents/subagent-manager.js';
import type { SubagentConfig } from 'qwen-code/packages/core/src/subagents/types.js';

async function addCustomAgent(globalConfig: Config) {
  const manager = new SubagentManager(globalConfig);

  const myAgent: SubagentConfig = {
    name: 'code-reviewer',
    description: 'Reviews a newly added TypeScript function and suggests improvements.',
    tools: ['read_file', 'write_file', 'edit'],
    systemPrompt: `
You are a code-review specialist. The user will provide a snippet of TypeScript code.
Your task is to:
1. Analyse the code for correctness, style and performance.
2. Suggest concrete improvements and, if possible, emit the updated source file using the **edit** tool.
Only respond with the revised code block and a short rationale.
`.trim(),
    level: 'project',
    modelConfig: { model: 'qwen3-coder-plus', temp: 0.2 },
    runConfig: { max_time_minutes: 5, max_turns: 10 },
    color: 'auto',
  };

  await manager.createSubagent(myAgent, { level: 'project', overwrite: true });
}

```

The manager validates the configuration using `SubagentValidator` and persists the definition using `serializeSubagent`, which handles YAML front-matter generation via the utility in [`packages/core/src/utils/yaml-parser.ts`](https://github.com/QwenLM/qwen-code/blob/main/packages/core/src/utils/yaml-parser.ts).

### Method 3: LLM-Generated Agents

Qwen Code provides the `subagentGenerator` utility in [`packages/core/src/utils/subagentGenerator.ts`](https://github.com/QwenLM/qwen-code/blob/main/packages/core/src/utils/subagentGenerator.ts) to generate configurations from natural language descriptions:

```typescript
import { subagentGenerator } from 'qwen-code/packages/core/src/utils/subagentGenerator.js';
import { Config } from 'qwen-code/packages/core/src/config/config.js';

const userText = 'I need an agent that can automatically document my public functions.';
const generated = await subagentGenerator(userText, config, AbortSignal.timeout(30000));

console.log(generated);
/* => {
   name: 'auto-docs',
   description: 'Creates Markdown documentation for all exported functions in a module.',
   systemPrompt: 'You are a documentation generator …'
} */

```

Pass the returned object to `SubagentManager.createSubagent` to persist the generated configuration.

## Invoking Custom Sub-Agents from Primary Sessions

Once defined, invoke custom sub-agents through the Task tool:

```typescript
import { TaskTool } from 'qwen-code/packages/core/src/tools/task.js';
import { Config } from 'qwen-code/packages/core/src/config/config.js';

const task = new TaskTool(config, config.getSubagentManager());

await task.run({
  subagent_type: 'code-reviewer',
  description: 'Review the newly added `add` function in src/utils/math.ts',
  prompt: 'Please read the file and suggest improvements.',
});

```

The `TaskTool` loads the `code-reviewer` definition via `SubagentManager`, creates a `SubAgentScope`, and executes `runNonInteractive`. The method streams the model response, handles permitted tool calls, and returns the final text output along with execution statistics.

## Summary

- **SubAgent architecture** separates static definitions (Markdown/YAML or programmatic configs) from dynamic execution scopes, enabling specialized agent delegation without core code modifications.
- **Five storage levels** (`session`, `project`, `user`, `extension`, `builtin`) provide flexible persistence with session-level configurations overriding project-level defaults.
- **SubagentManager** in [`packages/core/src/subagents/subagent-manager.ts`](https://github.com/QwenLM/qwen-code/blob/main/packages/core/src/subagents/subagent-manager.ts) handles CRUD operations, caching, and runtime configuration conversion via `createSubagentScope`.
- **SubAgentScope** in [`packages/core/src/subagents/subagent.ts`](https://github.com/QwenLM/qwen-code/blob/main/packages/core/src/subagents/subagent.ts) executes agents non-interactively, emitting lifecycle events and returning termination states (`GOAL`, `TIMEOUT`, `ERROR`).
- **Task tool** serves as the invocation interface, accepting `subagent_type` parameters to route work to specific agents.
- **Creation methods** include Markdown files in `.qwen/agents/`, programmatic `SubagentManager.createSubagent()` calls, or LLM-assisted generation via `subagentGenerator`.

## Frequently Asked Questions

### What is the difference between builtin and project-level sub-agents?

**Builtin agents** are hard-coded in `BuiltinAgentRegistry` ([`packages/core/src/subagents/builtin-agents.ts`](https://github.com/QwenLM/qwen-code/blob/main/packages/core/src/subagents/builtin-agents.ts)) and provide default capabilities like general-purpose assistance. They are immutable and always available. **Project-level agents** are stored as Markdown files in `PROJECT_ROOT/.qwen/agents/` and are specific to the current workspace, allowing teams to version-control custom agents alongside their codebase.

### How does the SubAgent system handle tool permissions?

Tool permissions are explicitly declared in the `tools` array within the `SubagentConfig` interface. When `SubAgentScope` executes via `runNonInteractive`, it restricts the agent to only those tools listed in its configuration. The `CoreToolScheduler` dispatches calls exclusively for permitted tools, ensuring isolation between different sub-agents' capabilities.

### What happens when a sub-agent exceeds its execution limits?

The `runConfig` parameters `max_time_minutes` and `max_turns` define hard boundaries. When exceeded, `SubAgentScope` terminates execution and returns the termination mode `TIMEOUT` alongside any accumulated `finalText`. Similarly, unhandled exceptions during tool execution result in the `ERROR` termination mode, allowing the primary agent to handle failures gracefully.

### Can sub-agent definitions be modified during an active session?

Yes. While `SubagentManager` maintains an in-memory `subagentsCache` for performance, you can update configurations by overwriting the Markdown files in `.qwen/agents/` or calling `manager.createSubagent()` with `overwrite: true`. The cache respects the storage level precedence, so session-level changes take immediate effect, while file-based changes are reloaded on the next `loadSubagent` call if the cache entry has expired or been invalidated.