Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/coder-subagent-tool-alignment.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@moonshot-ai/kimi-code": minor
---

Expand the coder subagent tool set to include background tasks, todo lists, plan mode, skill invocation, and nested agents, mirroring the main agent's capabilities; a subagent run also waits for its background tasks to settle before reporting completion. Applies automatically to coder subagents launched through the Agent tool.
4 changes: 3 additions & 1 deletion docs/en/customization/agents.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ Kimi Code CLI includes three built-in sub-agents, ready to use out of the box, e
- **`explore`**: Dedicated to codebase exploration; performs read-only operations only and does not modify any files. Ideal for quickly searching, reading, and summarizing a repository without touching files.
- **`plan`**: Dedicated to implementation planning and architecture design; even shell commands are not available, keeping the focus on "figuring out how to do something" rather than "actually doing it."

A `coder` sub-agent shares most of the main Agent's tool set: it can run shell commands in the background, maintain todo lists, enter Plan mode, invoke Agent Skills, and dispatch its own nested sub-agents when a task decomposes naturally. If it finishes its turn while background tasks are still running, its run only reports completion after those tasks settle, so the parent receives the result after the underlying work has actually finished.

## How to Invoke

Sub-agents are scheduled automatically by the main Agent — based on task complexity, context consumption, and sub-task independence, they are dispatched at the right moment without the user having to specify one.
Expand All @@ -29,7 +31,7 @@ This isolation provides two benefits:
- **The main Agent's context stays lean** and is not filled with large volumes of exploratory logs during long sessions.
- **Multiple sub-agents can run in parallel** without interfering with each other.

Note that each sub-agent independently consumes model tokens. For simple tasks, there is no need to dispatch a sub-agent — the main Agent handles them more economically. Sub-agents also cannot themselves schedule further nested sub-agents.
Note that each sub-agent independently consumes model tokens. For simple tasks, there is no need to dispatch a sub-agent — the main Agent handles them more economically.

## Permission Inheritance

Expand Down
4 changes: 3 additions & 1 deletion docs/zh/customization/agents.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ Kimi Code CLI 内置三种子 Agent,开箱即用,分别面向不同任务形
- **`explore`**:代码库探索专用,只做只读操作,不修改任何文件。适合在不改动文件的前提下快速搜索、阅读和总结仓库。
- **`plan`**:实现规划与架构设计专用,连 Shell 命令都不提供,专注于"想清楚怎么做"而不是"动手做"。

`coder` 子 Agent 与主 Agent 共享大部分工具集:可以在后台执行 Shell 命令、维护待办列表、进入 Plan 模式、调用 Agent Skills,也可以在任务自然拆解时继续派发自己的嵌套子 Agent。如果它结束自己的轮次时仍有后台任务在运行,那么只有在这些后台任务全部落定后,这次运行才会回报完成——主 Agent 拿到结果时,背后的工作也已经真正完成。

## 调用方式

子 Agent 由主 Agent 自动调度——根据任务复杂度、上下文消耗和子任务的独立性,在适当时机派发,无需用户手动指定。
Expand All @@ -29,7 +31,7 @@ Kimi Code CLI 内置三种子 Agent,开箱即用,分别面向不同任务形
- **主 Agent 上下文保持精炼**,长会话中不会被大量探索性日志撑满。
- **多个子 Agent 可以并行运行**,互不干扰。

需要注意的是,每个子 Agent 都会独立消耗模型 token。简单任务没有必要派发子 Agent,主 Agent 直接处理更经济。子 Agent 也不支持继续嵌套调度。
需要注意的是,每个子 Agent 都会独立消耗模型 token。简单任务没有必要派发子 Agent,主 Agent 直接处理更经济。

## 权限继承

Expand Down
9 changes: 9 additions & 0 deletions packages/agent-core/src/agent/tool/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,15 @@ export class ToolManager {
// builtin/user tool names. The split keeps every caller on one string[].
this.enabledTools = new Set(names.filter((name) => !isMcpToolName(name)));
this.mcpAccessPatterns = names.filter((name) => isMcpToolName(name));
// Builtin construction reads the enabled set (Bash/Agent bake
// `allowBackground` from the Task* trio), and the constructor may already
// have built the map while the enabled set was still empty. The lazy
// re-init in `get tools()` only fires on an empty map, so rebuild here —
// otherwise a profile applied after construction (every subagent) keeps
// the construction-time capabilities.
if (this.agent.config.hasProvider) {
this.initializeBuiltinTools();
}
}

copyLoopToolsFrom(source: ToolManager): void {
Expand Down
20 changes: 16 additions & 4 deletions packages/agent-core/src/profile/default/coder.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,25 @@ promptVars:
whenToUse: |
Use this agent for non-trivial software engineering work that may require reading files, editing code, running commands, and returning a compact but technically complete summary to the parent agent.
tools:
- Agent
- AgentSwarm
- Bash
- Read
- ReadMediaFile
- CronCreate
- CronDelete
- CronList
- Edit
- EnterPlanMode
- ExitPlanMode
- Glob
- Grep
- Write
- Edit
- Read
- ReadMediaFile
- Skill
- TaskList
- TaskOutput
- TaskStop
- TodoList
- WebSearch
- FetchURL
- Write
- mcp__*
44 changes: 44 additions & 0 deletions packages/agent-core/src/session/subagent-host.ts
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,7 @@ export class SessionSubagentHost {
options: RunSubagentOptions,
): Promise<SubagentCompletion> {
await runChildTurnToCompletion(child, options.signal);
await this.drainChildBackgroundTasks(child, options.signal);

// A subagent that returns an overly terse summary leaves the parent
// agent under-informed. Give it a bounded number of chances to expand
Expand Down Expand Up @@ -416,6 +417,49 @@ export class SessionSubagentHost {
child.tools.inheritUserTools(parent.tools);
}

/**
* Hold the run open until the child agent's background tasks (background
* Bash, nested background agents) settle — the print-mode (`kimi -p`)
* drain semantics applied to subagent completion. Drained tasks get their
* terminal notifications suppressed: without that, a task outliving the
* child's final turn steers a fresh turn on the finished subagent
* (`steer` degrades to `launch`), which runs unobserved and whose output
* never reaches the parent. Bounded by the run's signal — the Agent
* tool's per-run timeout / user-cancel envelope covers the drain too.
*/
private async drainChildBackgroundTasks(child: Agent, signal: AbortSignal): Promise<void> {
for (;;) {
signal.throwIfAborted();
await this.suppressChildTaskNotifications(child);
await child.background.waitForActiveTasks(() => true, { signal });
// Suppress again after the wait: notification delivery re-checks
// suppression after its async output snapshot, so this pass still
// blocks notifications for tasks that settled during the wait.
await this.suppressChildTaskNotifications(child);
// A terminal effect that slipped past the suppression race may have
// steered a follow-up turn onto the child; let it finish (it can fan
// out new tasks) before declaring the child drained.
if (child.turn.hasActiveTurn) {
await runChildTurnToCompletion(child, signal);
continue;
}
if (child.background.list(true).length === 0) return;
}
}

/**
* Suppress terminal notifications for every child background task —
* including already-settled ones whose notification may still be in
* flight. `list(false)` is required: the active-only list drops a task
* the moment it terminates, which is exactly when an unsuppressed
* notification can still steer an orphan turn onto the finished child.
*/
private async suppressChildTaskNotifications(child: Agent): Promise<void> {
for (const task of child.background.list(false)) {
await child.background.suppressTerminalNotification(task.taskId);
}
}

private async triggerSubagentStart(
parent: Agent,
profileName: string,
Expand Down
Loading
Loading