feat: replace the secondary-model experiment with the [subagent] model pool - #2700
Draft
7Sageer wants to merge 7 commits into
Draft
feat: replace the secondary-model experiment with the [subagent] model pool#27007Sageer wants to merge 7 commits into
7Sageer wants to merge 7 commits into
Conversation
Add a declarative subagent model pool to agent-core-v2: [subagent.models] maps [models] entry ids to selection hints rendered in the Agent/AgentSwarm tool descriptions, and [subagent].default_model picks the spawn model when the caller passes none. The tools' model parameter becomes a free-form alias string (stripped when no pool is configured), description rendering is caller-aware (primary (alias) [main model]), and a session-start validation service fails fast with CONFIG_INVALID on a missing/invalid default_model or an unresolvable pool alias. Remove the secondary-model experiment from the v2 engine, node-sdk, kap-server, and the TUI (the /secondary_model command), and drop the agent-profile modelPreference / model_preference frontmatter field on v2. The legacy v1 engine keeps the experiment unchanged; v2 ignores leftover [secondary_model] config silently.
…icker mapping Deep-review follow-ups to the [subagent.models] pool: - validate the pool before session materialization (after config.ready) and before the fork file copy, so a broken pool no longer leaves orphaned session dirs or leaked MCP overlay connections; the Session-scope validation service stays as a backstop - reject the reserved "primary" pool alias at startup, and again defensively in resolveSubagentBinding so a pool broken by a runtime config edit fails loudly at spawn instead of binding the wrong model - keep the [default] marker when the caller's own model is the pool default (primary (alias) [main model] [default]) - recompile the cached tool-args validator when a tool advertises a new schema object (mid-session pool edits no longer hit a stale validator) - map config.invalid to VALIDATION_FAILED in kap-server's session routes, the debug transport mapper, and the catch-all error handler - hide the v1-synthesized __secondary__ entry from the /model and /provider pickers again - fold per-export doc blocks into file headers per package comment conventions; add pre-flight/reserved-key/validator/mapping tests and document that create/resume/fork all fail on a broken pool
- v2 engine: a pool-less [subagent] default_model forms an implicit single-entry pool — validated at session create/resume/fork like an explicit pool, and advertised through the Agent/AgentSwarm model parameter. - Tool descriptions: the caller's own alias is a normal pool entry marked [main model]; the primary line stays distinct because only it inherits the caller's thinking level. - TUI: /secondary_model returns, persisting [subagent] default_model (merging into an existing pool with an empty description); the picker hides the no-op Thinking footer and rejects the reserved primary alias. - kap-server: /api/v1/config accepts and echoes subagent; the snake-to-camel patch conversion preserves user-defined map keys under providers/models/experimental/raw without leaking preserve mode into a colliding alias's own fields. - v1 config schema learns subagent.defaultModel/models so the shared config.toml round-trips; the v1 engine still ignores them at runtime. - Docs (en/zh) and changesets updated.
🦋 Changeset detectedLatest commit: c620153 The changes in this PR will be included in the next version bump. This PR includes changesets to release 4 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Related Issue
No tracking issue — the problem is explained below.
Problem
The experimental secondary model (
[secondary_model]+KIMI_SECONDARY_MODEL/KIMI_SECONDARY_EFFORTenv vars + the agent-filemodel_preferencefield) gives subagents a single fallback model and is wired through SDK session-apply APIs (Session.applyPersistedSecondaryModel, a synthesized__secondary__model entry). The main agent cannot choose a subagent model per spawn, and the recipe does not fit the v2 engine's config-section architecture.What changed
v2 engine — declarative subagent model pool
[subagent.models]maps configured[models]aliases to the selection hints shown to the main agent;[subagent] default_modelnames the fallback used when a spawn passes no model. A lonedefault_model(no models table) forms an implicit single-entry pool — the minimal "secondary model" configuration.Agent/AgentSwarmtools gain amodelparameter (advertised only when a pool exists): any pool alias, or the reserved symbolicprimary, which binds the caller's own model and thinking level — pool-alias bindings resolve thinking naturally instead.CONFIG_INVALID) at session create / resume / fork on a missing or out-of-pooldefault_model, an unresolvable alias, or a reservedprimarykey. Tool descriptions mark[default]/[main model]; the caller's alias stays a normal pool entry because onlyprimaryinherits the caller's thinking level.Session.applyPersistedSecondaryModel,SECONDARY_DERIVED_MODEL_ALIAS), kap-server, and the agent-filemodel_preferencefield on v2.TUI
/secondary_modelre-added: opens a model picker and persists[subagent] default_model, merging into an existing pool with an empty description. The picker hides the no-op Thinking footer; the reservedprimaryalias is rejected with a rename hint. New spawns pick the value up without a session restart.kap-server
/api/v1/configaccepts and echoessubagent; the snake→camel patch conversion now preserves user-defined map keys underproviders/models/experimental/raw(an alias likefast_modelpreviously becamefastModel), without leaking preserve mode into a colliding alias's own fields.Default (v1) engine
[secondary_model], its env vars, andmodel_preferencekeep working there; the v1 config schema learnssubagent.defaultModel/modelsonly so a sharedconfig.tomlround-trips — v1 ignores them at runtime.Docs & changesets: en/zh config-files, tools, and slash-commands pages updated; two changesets (
minorfor@moonshot-ai/kimi-codeand@moonshot-ai/kimi-code-sdk).Behavior examples
Configuration — minimal form (every subagent binds
kimi-hsby default) vs a full pool:What the main agent sees — the
Agent/AgentSwarmtool description gains amodelparameter and renders the pool (here the caller itself runsk3):The two
k3lines differ only in thinking inheritance: a pool-alias binding carries no explicit thinking level (the subagent resolves it from global config / the model's default effort), whileprimaryinherits the caller's model and current thinking level./secondary_model— interactive-only path to the minimal form:[subagent] default_model.[subagent.models]table exists and the picked alias is not in it, the alias is added with an empty description (the engine requires the default to be a pool key); without a table onlydefault_modelis written.primaryis rejected with a rename hint instead of writing a pool the engine would refuse.[subagent] default_modeland keeps resolving subagent models through[secondary_model].Checklist
gen-changesetsskill, or this PR needs no changeset.gen-docsskill, or this PR needs no doc update.