Skip to content
Open
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
45 changes: 44 additions & 1 deletion .agents/skills/agent-core-dev/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,12 +78,21 @@ User config.toml (persisted user preferences)
Operational env overlay (e.g. KIMI_MODEL_*, KIMI_CODE_EXPERIMENTAL_*)
Memory per-run intent (CLI flags); never persisted; highest
Derived overlays synthesize runtime-only values from the fully resolved inputs
```

`set(domain, patch, target?)` writes the `User` layer (persisted) by default;
pass `ConfigTarget.Memory` for a per-run override that is never written to disk.
`inspect(domain)` reports the value at each layer.

Effective overlays declare a phase. Environment overlays run before Memory so
the per-run layer remains the highest user/operator input. Derived overlays run
after Memory and may synthesize runtime-only sibling values from the fully
resolved inputs. `[secondary_model]` and `[subagent_models]` use the derived
phase so patched recipes supplied through `ConfigTarget.Memory` materialize the
same model entries as persisted recipes.

## Layout

- `src/config/config.ts` — `IConfigRegistry` / `IConfigService` tokens, `ConfigSection`, `ConfigEffectiveOverlay`, event types.
Expand Down Expand Up @@ -232,7 +241,7 @@ This means registration order is never a correctness concern — you do not need
- `rawSnake` — snake_case clone of the file; the write base, never carries the env overlay.
- `raw` — camelCase, env-free; the read/set/replace base.
- `validated` — validated `raw`, env-free; the base every live env re-application starts from, so a degraded or removed env value falls back to the file instead of a stale overlay.
- `effective` — `validated` plus the env overlay, recomputed on load/set; `get()`/`getAll()` re-apply the overlay on a fresh `validated` copy per read rather than caching it.
- `effective` — `validated` plus section env bindings and environment overlays, then Memory input, then derived overlays; recomputed on load/set. `get()`/`getAll()` rebuild the same sequence from a fresh `validated` copy per read rather than caching live env values.

### `KIMI_MODEL_*` env overlay

Expand Down Expand Up @@ -270,3 +279,37 @@ The authoritative, always-current list of registered sections — rendered in th
- Reading config / calling `configure(...)` / switching model at runtime must not rewrite `config.toml`; runtime state lives in memory and the session wireRecord, not the file.
- Never persist env overlays (`__kimi_env__` / `__kimi_env_model__` / shell API key / experimental env); overlays live only in `effective` / `Memory`.
- Registering from an Agent-scope service is fine — the late-registration mechanism keeps validation correct; do not add an eager bootstrap.

## `[subagent_models]` — named model slots

When model slots are configured under `[subagent_models]`, the Agent and AgentSwarm
tool schemas dynamically expose the slot names as the `model` parameter enum.
Each slot references a `[models]` alias and can layer patch fields that are
synthesised into a derived model entry (e.g. `__sm__fast`).

```toml
[subagent_models.fast]
model = "fast-model"
description = "Fast, budget-friendly model. Best for routine / low-risk tasks."
recommended_for = ["routine", "data_processing"]

[subagent_models.quality]
model = "quality-model"
description = "Highest reasoning quality. Best for architecture, complex logic."
recommended_for = ["architecture", "complex_code"]
default = true

[subagent_models.large_context]
model = "large-context-model"
description = "Long-context model for codebase-wide refactors."
max_context_size = 262144
default_effort = "medium"
```

Key rules:
- Slot names must match `^[a-zA-Z][a-zA-Z0-9_]*$`, must not be `"primary"` or start with `__`.
- At most one slot may have `default = true`; otherwise the first slot is the default.
- Patch fields (anything other than `model` / `description` / `recommended_for` / `default` — i.e. any ModelOverride field such as `max_output_size`, `max_context_size`, `default_effort`, `capabilities`, etc.) synthesise a derived `[models.__sm__<slot>]` entry. User-defined `[models.__sm__*]` entries collide with derived ones and are rejected.
- Memory-layer slot recipes use the same derived synthesis as persisted recipes; Memory remains above config/env input and is never written to disk.
- An explicit tool-call slot overrides the agent type's `model_preference`; the caller can still opt into `"primary"`.
- The derived model IDs are stripped from `/api/v1/models` (kap-server).
5 changes: 5 additions & 0 deletions .changeset/subagent-model-list.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@moonshot-ai/kimi-code": patch
---

Add experimental named subagent model slots so the main agent can choose subagent models by task. Configure them under `[subagent_models.<name>]`; effective under `kimi web` and experimental `kimi -p`.
41 changes: 38 additions & 3 deletions docs/en/configuration/config-files.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ Fields in the config file fall into two categories: **top-level scalars** that d
| `telemetry` | `boolean` | `true` | Whether anonymous telemetry is enabled; disabled only when explicitly set to `false` |
| `providers` | `table` | `{}` | API provider table → [`providers`](#providers) |
| `models` | `table` | — | Model alias table → [`models`](#models) |
| `subagent_models` | `table` | — | Named model slots for subagents → [`subagent_models`](#subagent_models) |
| `thinking` | `table` | — | Default parameters for Thinking mode → [`thinking`](#thinking) |
| `loop_control` | `table` | — | Agent loop control parameters → [`loop_control`](#loop_control) |
| `background` | `table` | — | Background task runtime parameters → [`background`](#background) |
Expand All @@ -115,7 +116,7 @@ Fields in the config file fall into two categories: **top-level scalars** that d
| `permission` | `table` | — | Initial permission rules → [`permission`](#permission) |
| `hooks` | `array<table>` | — | Lifecycle hooks; see [Hooks](../customization/hooks.md) |

The following sections cover each of the nested tables in turn: `providers`, `models`, `thinking`, `loop_control`, `background`, `tools`, `image`, `services`, and `permission`.
The following sections cover each of the nested tables in turn: `providers`, `models`, `subagent_models`, `thinking`, `loop_control`, `background`, `tools`, `image`, `services`, and `permission`.

## `providers`

Expand Down Expand Up @@ -188,12 +189,46 @@ display_name = "Kimi for Coding (custom)"

You can also switch models temporarily without touching the config file — by setting `KIMI_MODEL_*` environment variables, the CLI synthesizes a temporary provider in memory that does not persist after restart. See [Define a model from environment variables](./env-vars.md#define-a-model-from-environment-variables-kimi_model).

## `secondary_model`
## `subagent_models`

The secondary model is a second model pointer next to the primary `default_model` — typically a cheaper model that features can bind to when they do not need the main model. Its consumer today is subagent spawning: when set, newly spawned subagents (`Agent` / `AgentSwarm`) bind to it by default instead of inheriting the main agent's model, and the main agent is told it can pick per spawn between `"secondary"` (this model) and `"primary"` (the main model). When unset, subagents inherit the main agent's model.
Named subagent model slots let the main agent choose a model for each delegated task from descriptions you provide. Each `[subagent_models."<name>"]` entry points to a configured `[models]` alias. When the experiment is enabled, `Agent` and `AgentSwarm` show the main agent every slot's name, model, description, and recommended uses, together with `primary` for the main model.

This feature is experimental and disabled by default. Under `kimi web`, enable it with `KIMI_CODE_EXPERIMENTAL_SECONDARY_MODEL=1`. Under `kimi -p`, `KIMI_CODE_EXPERIMENTAL_FLAG=1` is already required to select the v2 engine and also enables this feature. The interactive TUI ignores the configuration.

| Field | Type | Default | Description |
| --- | --- | --- | --- |
| `model` | `string` | — | Required model id from your configured `[models]` |
| `description` | `string` | — | Required guidance the main agent reads when choosing a slot; describe the model's cost, speed, quality, or other relevant trade-offs |
| `recommended_for` | `string[]` | `[]` | Optional task categories shown alongside the description |
| `default` | `boolean` | `false` | Makes this slot the default when neither the tool call nor the selected agent profile chooses one. At most one slot may set it; without one, the first configured slot is the default |
| Other fields | — | — | Accepts every field of [`[models."<alias>".overrides]`](#models) (`max_context_size`, `max_output_size`, `support_efforts`, …) as a patch applied only to subagents using this slot |

```toml
[subagent_models.fast]
model = "fast-model"
description = "Low-cost, low-latency model for routine searches and formatting."
recommended_for = ["search", "formatting"]
default = true
default_effort = "low"

[subagent_models.quality]
model = "quality-model"
description = "Highest reasoning quality for architecture and complex code."
recommended_for = ["architecture", "complex_code"]
```

An explicit `model` passed to `Agent` or `AgentSwarm` takes priority over the selected agent profile's `model_preference`; the profile preference takes priority over the configured default slot. Pass `primary` to use the caller's main model. A resumed subagent always keeps its existing model.

Every field besides `model`, `description`, `recommended_for`, and `default` forms a model patch. A patched slot receives a private derived model entry in memory, while an unpatched slot binds its `model` directly. Derived entries are never written to `config.toml` or shown in model pickers. A slot that would collide with a user-owned derived entry such as `[models.__sm__fast]` is rejected and produces a startup warning instead of overwriting or selecting that model. Invalid slots are omitted from the model choices shown to the main agent, so ordinary conversation remains available, while attempts to spawn with the invalid configuration fail closed.

Slot names must start with a letter and contain only letters, numbers, and underscores. `primary` and names starting with `__` are reserved.

## `secondary_model`

The secondary model is the legacy single-slot form of [named subagent models](#subagent_models). It is used only when `[subagent_models]` is empty: newly spawned subagents bind to it by default, and the main agent can choose between `secondary` and `primary`. When neither section is configured, subagents inherit the main agent's model.

It uses the same experimental flag and surface support described above.

| Field | Type | Default | Description |
| --- | --- | --- | --- |
| `model` | `string` | — | A model id from your configured `[models]` (any provider, not limited to Kimi models) |
Expand Down
4 changes: 2 additions & 2 deletions docs/en/customization/agents.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ You are a strict code reviewer. Read the diff, then report findings grouped by s
| `description` | yes | What the agent does. Shown to the main Agent when it picks a sub-agent, so write it to guide delegation decisions |
| `whenToUse` | no | Extra hint describing when the agent should be used |
| `override` | no | Whether this file may replace a same-name built-in Agent. Defaults to `false`; `--agent-file` is already explicit and does not require this field |
| `model_preference` | no | Symbolic default used when `Agent` or `AgentSwarm` spawns this profile: `primary` selects the caller's main model, while `secondary` selects `[secondary_model] model`. An explicit tool-call `model` wins; without either setting, the configured secondary model remains the default. If no secondary model is configured, the subagent inherits the caller's model |
| `model_preference` | no | Named `[subagent_models]` slot used when `Agent` or `AgentSwarm` spawns this profile. `primary` selects the caller's main model; `secondary` selects the legacy `[secondary_model]` slot when named slots are absent. An explicit tool-call `model` takes priority |
| `tools` | no | Allowlist of tool names such as `Read` or `Bash`; MCP tools are matched with globs such as `mcp__github__*`. Accepts a YAML list or a comma-separated string (`tools: Read, Grep`). Omit to allow all tools; a lone `*` also allows all tools; an empty list (`tools: []`) disables all tools |
| `disallowedTools` | no | Denylist with the same syntax and matching rules, applied after `tools` |
| `subagents` | no | Allowlist of sub-agent names this agent may delegate to, with the same syntax as `tools` (YAML list or comma-separated string). Omit to allow every type; a lone `*` also allows all types |
Expand All @@ -109,7 +109,7 @@ The body is the agent's system prompt, and it is rendered as a template each tim

Unknown fields are ignored, so newer files stay readable by older versions. Fields from other agent tools (such as Claude Code's `model` or OpenCode's `mode`) are ignored the same way, the comma-separated `tools` form keeps Claude Code-style agent files loadable, and a missing `name` falls back to the file name so OpenCode-style files load too — a minimal file with `description` and a body works across tools.

`model_preference` applies only to newly spawned subagents when the secondary-model experiment is enabled. Under `kimi web`, set `KIMI_CODE_EXPERIMENTAL_SECONDARY_MODEL=1`; under experimental `kimi -p`, the required `KIMI_CODE_EXPERIMENTAL_FLAG=1` also enables it. The TUI currently ignores this field. It never names a concrete model alias, and resumed subagents keep their existing model. The selected preference is shown to the main agent alongside the profile description so it can still pass an explicit `model` when a task needs a different choice.
`model_preference` applies only to newly spawned subagents when the subagent-model experiment is enabled. Under `kimi web`, set `KIMI_CODE_EXPERIMENTAL_SECONDARY_MODEL=1`; under experimental `kimi -p`, the required `KIMI_CODE_EXPERIMENTAL_FLAG=1` also enables it. The TUI currently ignores this field. Use a slot name from [`[subagent_models]`](../configuration/config-files.md#subagent_models), not a concrete model alias. An explicit tool-call `model` overrides the preference; resumed subagents keep their existing model. The selected preference is shown to the main agent alongside the profile description so it can still choose a different slot when a task calls for it.

A file with invalid content discovered in a directory is skipped with a warning and does not affect other files. A file passed explicitly via `--agent-file` must be valid — otherwise the CLI reports the error and exits.

Expand Down
Loading