# How to Build Custom Subagents (Coder, Explore, Plan) in Kimi Code

> Learn to build custom subagents like coder, explore, and plan in Kimi Code. Follow simple steps to create YAML profiles, register them, and spawn agents for powerful automation.

- Repository: [Moonshot AI/kimi-code](https://github.com/MoonshotAI/kimi-code)
- Tags: how-to-guide
- Published: 2026-07-26

---

**Building custom subagents in Kimi Code requires creating a YAML profile in `packages/agent-core/src/profile/default/`, registering it in [`default.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/default.ts), and spawning it via the `Agent` tool or `AgentSwarm` for parallel execution.**

Kimi Code, the open-source agentic framework from MoonshotAI, enables parent agents to delegate tasks to specialized subagents through a declarative profile system. Whether you need a read-only explorer, a file-editing coder, or a planning reviewer, custom subagents extend core capabilities while maintaining strict isolation and observability. This guide walks through the exact implementation steps found in the `MoonshotAI/kimi-code` repository.

## Step 1: Declare a Subagent Profile

Every subagent starts as a YAML profile stored in `packages/agent-core/src/profile/default/`. Each profile extends the base `agent` configuration and defines the subagent's identity, capabilities, and strict tool constraints.

A profile contains five critical fields:

- **extends**: Inherits from the base agent template (typically `agent`)
- **name**: The unique identifier used as the `subagent_type` parameter
- **promptVars.roleAdditional**: System instructions that constrain behavior (e.g., read-only enforcement)
- **whenToUse**: Human-readable description for UI context
- **tools**: An explicit allowlist of callable tools that enforces security boundaries

Here is the built-in **explore** profile that demonstrates read-only constraints:

```yaml

# packages/agent-core/src/profile/default/explore.yaml

extends: agent
name: explore
promptVars:
  roleAdditional: |
    You are now running as a subagent. You are a read-only agent. 
    Do not modify files; only search and read code.
whenToUse: |
  Fast agent specialized for exploring codebases. 
  Use "quick", "medium", or "thorough" to control search depth.
tools:
  - Bash
  - Read
  - ReadMediaFile
  - Glob
  - Grep
  - WebSearch
  - FetchURL

```

The **coder** profile (which permits editing) and **plan** profile (review-only) follow identical structures but include tools like `Write` or `Replace` where appropriate. You can find these at [`packages/agent-core/src/profile/default/coder.yaml`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core/src/profile/default/coder.yaml) and [`packages/agent-core/src/profile/default/plan.yaml`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core/src/profile/default/plan.yaml).

## Step 2: Register the Profile in DEFAULT_AGENT_PROFILES

After creating the YAML file, expose it to the runtime through the central registry in [`packages/agent-core/src/profile/default.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core/src/profile/default.ts). This file exports the `DEFAULT_AGENT_PROFILES` map that resolves `subagent_type` strings to configuration objects.

The TypeScript file imports each YAML as a raw string and parses it into the registry:

```typescript
// packages/agent-core/src/profile/default.ts
import exploreYaml from './default/explore.yaml?raw';
import coderYaml from './default/coder.yaml?raw';
import planYaml from './default/plan.yaml?raw';

export const DEFAULT_AGENT_PROFILES = {
  agent: parseYaml(agentYaml),
  coder: parseYaml(coderYaml),
  explore: parseYaml(exploreYaml),
  plan: parseYaml(planYaml),
};

```

The build pipeline automatically generates these imports, or you can manually add entries for custom profiles. Once registered, the engine can resolve any string passed to `subagent_type` against this map.

## Step 3: Spawn Subagents from a Parent Agent

With the profile registered, parent agents instantiate subagents using the **Agent** tool implemented in [`packages/agent-core/src/tools/builtin/collaboration/agent.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core/src/tools/builtin/collaboration/agent.ts). This tool accepts a `subagent_type` argument that must match a key in `DEFAULT_AGENT_PROFILES`.

The tool delegates to `SessionSubagentHost` to create isolated agent instances:

```typescript
// packages/agent-core/src/tools/builtin/collaboration/agent.ts
const profileName = args.subagent_type?.length ? args.subagent_type : 'coder';

const handle = await this.subagentHost.spawn({
  subagent_type: profileName,
  prompt: args.prompt,
  // Optional: timeout, resume flags, etc.
});

```

**Example: Launching an explore subagent from a parent coder agent**

```typescript
import { Agent } from '@moonshot-ai/kimi-code-sdk';

const result = await Agent({
  subagent_type: 'explore',
  prompt: `
    thoroughness: medium
    Search the repository for any function named "handleRequest"
    and list the files where it appears.
  `,
});

console.log('Explore subagent finished:', result.output);

```

### Parallel Execution with AgentSwarm

For batch operations across multiple inputs, use **AgentSwarm** from [`packages/agent-core/src/tools/builtin/collaboration/agent-swarm.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core/src/tools/builtin/collaboration/agent-swarm.ts). This fans out multiple subagents in parallel across an `items` array:

```typescript
import { AgentSwarm } from '@moonshot-ai/kimi-code-sdk';

const swarmResult = await AgentSwarm({
  subagent_type: 'explore',
  items: ['src/**/*.ts', 'tests/**/*.ts'],
  prompt_template: `
    thoroughness: quick
    Read {{item}} and extract all exported class names.
  `,
});

console.log('Swarm results:', swarmResult.output);

```

The parent agent receives consolidated results once all subagents complete, with lifecycle events (`subagent.spawned`, `subagent.completed`) recorded in the transcript for full observability.

## Subagent Architecture and Lifecycle

Understanding the execution model helps debug custom subagents. The orchestration happens in [`packages/agent-core/src/session/subagent-host.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core/src/session/subagent-host.ts) through **SessionSubagentHost**, which manages four critical responsibilities:

1. **Profile resolution**: Validates `subagent_type` against `DEFAULT_AGENT_PROFILES`
2. **Instance isolation**: Creates a new `Agent` instance with separate task and turn queues while sharing the parent's model context
3. **Lifecycle tracking**: Emits events (`subagent.spawned`, `subagent.started`, `subagent.completed`, `subagent.failed`) to the transcript
4. **Result bubbling**: Marks subagent turns with `PromptOrigin` = `{ kind: 'system_trigger', name: 'subagent' }` and appends summaries to the parent's context

This architecture ensures that even if a subagent fails or times out, the parent agent receives structured feedback without state corruption.

## Complete Custom Subagent Example

Here is a complete implementation pattern for a documentation generation subagent:

**Step A: Create the profile** ([`packages/agent-core/src/profile/default/docgen.yaml`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core/src/profile/default/docgen.yaml)):

```yaml
extends: agent
name: docgen
promptVars:
  roleAdditional: |
    You are a documentation specialist. Generate JSDoc comments 
    for functions but do not modify implementation logic.
whenToUse: |
  Use when you need to generate API documentation for TypeScript files.
tools:
  - Read
  - Write
  - Glob

```

**Step B: Register in default.ts** (add to imports and `DEFAULT_AGENT_PROFILES`):

```typescript
import docgenYaml from './default/docgen.yaml?raw';

export const DEFAULT_AGENT_PROFILES = {
  // ... existing profiles
  docgen: parseYaml(docgenYaml),
};

```

**Step C: Spawn from parent**:

```typescript
const docs = await Agent({
  subagent_type: 'docgen',
  prompt: 'Generate JSDoc for all functions in src/utils/',
});

```

## Summary

- Create YAML profiles in `packages/agent-core/src/profile/default/` to define subagent capabilities, system prompts, and strict tool constraints.
- Register new profiles in [`packages/agent-core/src/profile/default.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core/src/profile/default.ts) by adding them to the `DEFAULT_AGENT_PROFILES` export map.
- Spawn individual subagents using the `Agent` tool for sequential delegation, or use `AgentSwarm` for parallel processing across multiple inputs.
- Subagent isolation is enforced by `SessionSubagentHost` in [`packages/agent-core/src/session/subagent-host.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core/src/session/subagent-host.ts), which manages separate task queues and lifecycle events while bubbling results back to the parent transcript.

## Frequently Asked Questions

### What is the difference between the coder, explore, and plan subagent types?

The **coder** profile includes editing tools like `Write` and `Replace` for file modification, **explore** restricts operations to read-only search and discovery via `Read`, `Glob`, and `Grep`, while **plan** enables architectural review and planning without mutations. Each profile configures distinct tool sets in their respective YAML files under `packages/agent-core/src/profile/default/`.

### How do I restrict a subagent to read-only operations?

Limit the `tools` array in the profile YAML to non-mutating tools like `Read`, `Glob`, `Grep`, and `FetchURL`. Additionally, set `promptVars.roleAdditional` to explicitly instruct the LLM that it cannot modify files, and document these constraints in the `whenToUse` field for UI clarity.

### Can I run multiple subagents simultaneously?

Yes. Use the **AgentSwarm** tool from [`packages/agent-core/src/tools/builtin/collaboration/agent-swarm.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core/src/tools/builtin/collaboration/agent-swarm.ts) to fan out multiple subagents across a collection of items. The parent agent receives consolidated results once all parallel subagents complete, with each subagent operating in isolation.

### Where are subagent profiles stored in the Kimi Code repository?

Built-in profiles reside in `packages/agent-core/src/profile/default/` as YAML files (e.g., [`coder.yaml`](https://github.com/MoonshotAI/kimi-code/blob/main/coder.yaml), [`explore.yaml`](https://github.com/MoonshotAI/kimi-code/blob/main/explore.yaml), [`plan.yaml`](https://github.com/MoonshotAI/kimi-code/blob/main/plan.yaml)). The registration logic lives in [`packages/agent-core/src/profile/default.ts`](https://github.com/MoonshotAI/kimi-code/blob/main/packages/agent-core/src/profile/default.ts), which generates the `DEFAULT_AGENT_PROFILES` map used by the `Agent` tool to resolve `subagent_type` strings.