Skip to content

feat(agent-core): per-workspace subagent model bindings#1928

Open
Yorha9e wants to merge 6 commits into
MoonshotAI:mainfrom
Yorha9e:feat/subagent-model-binding
Open

feat(agent-core): per-workspace subagent model bindings#1928
Yorha9e wants to merge 6 commits into
MoonshotAI:mainfrom
Yorha9e:feat/subagent-model-binding

Conversation

@Yorha9e

@Yorha9e Yorha9e commented Jul 19, 2026

Copy link
Copy Markdown

Related Issue

Resolve #1927

Problem

See linked issue.

What changed

Bindings belong to the user, not the model. Model selection for delegated work is treated as user configuration, applied mechanically — the calling agent never sees or overrides it. This deliberately avoids LLM-facing model directories/parameters: in testing, agents would self-fill a model argument in ways that silently overrode user intent.

  • Bindings persist in <projectRoot>/.kimi-code/local.toml under [subagent.<type>], following the existing workspace.additional_dir pattern
  • First unbound spawn of a type asks the user once interactively and persists the answer (an explicit "keep inheriting" choice is recorded too); non-interactive environments simply inherit
  • New /subagent-model command (list / set <type> / clear <type>) via a new session RPC chain (agent-core → node-sdk → TUI)
  • Precedence: workspace binding > profile binding (new modelAlias/thinkingEffort on profile subagents entries) > parent inheritance
  • Sticky resume/retry: a subagent always keeps its configured model/effort (restored via config.update wire records); no mid-conversation switches. Unresolvable stored aliases fail fast with a configuration error instead of silently realigning to the parent — a deliberate behavior change from today's realign-on-resume
  • Stale workspace bindings are repaired, not obeyed: the bound alias is validated against the user's models config at spawn. Interactive sessions re-ask the binding question with the missing-model reason and persist the new choice; non-interactive sessions inherit the parent model with an explicit warning in the tool result — never a silent route to a wrong or pricier model
  • Effective model/effort exposed in the subagent.spawned event, AgentBackgroundTaskInfo, approval label, and tool result text
  • Gated by the subagent-model-selection experiment (off by default, KIMI_CODE_EXPERIMENTAL_SUBAGENT_MODEL_SELECTION=1), so default behavior is unchanged

Validation

  • New coverage: binding store round-trips, first-use ask flow (model/effort/inherit/dismiss), AgentTool binding application & gating & approval label, sticky resume, spawn override + event payload, profile bindings, SDK RPC round-trip, /subagent-model flows — all passing
  • Full agent-core suite: no regressions vs base (remaining failures are pre-existing Windows environment issues: missing /bin/bash, symlink/UNC semantics)
  • tsc --noEmit clean (agent-core, protocol, node-sdk, apps/kimi-code); oxlint 0 errors in touched files
  • Live TUI smoke: first-use ask → persisted binding → mechanical re-application → sticky resume → /subagent-model list/clear, all verified

Checklist

  • I have read the CONTRIBUTING document.
  • I have linked a related issue, or explained the problem above.
  • I have added tests that prove my feature works.
  • Ran gen-changesets skill, or this PR needs no changeset.
  • Ran gen-docs skill, or this PR needs no doc update.

@changeset-bot

changeset-bot Bot commented Jul 19, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: a90501a

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@moonshot-ai/kimi-code Minor

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

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ccf0f39e9d

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

const { child, profileName } = await this.ensureIdleSubagent(agentId, parent);
// Sticky semantics: a resumed child always keeps its configured
// model/effort; mid-conversation model switches are not supported.
const modelAlias = this.resolveChildModel(parent, child.config.modelAlias);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Gate sticky resume behind the experiment

When the experiment is off, this still changes the default resume path: the only flag check is in AgentTool's binding lookup, but Agent(resume=...) now resolves the child's persisted alias instead of the current parent alias. A user who changes or removes the main model and then resumes an old subagent will keep the stale child model or get CONFIG_INVALID, whereas the pre-change code realigned to the parent; gate sticky resume/retry with subagent-model-selection or keep the old realignment for unbound children.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch — the sticky resume was applying unconditionally, which contradicted the "default behavior unchanged" claim. Fixed: resume()/retry() now check parent.experimentalFlags.enabled('subagent-model-selection'). With the flag on, a resumed child keeps its configured model/effort (sticky, no mid-conversation switches; unresolvable stored aliases fail fast with CONFIG_INVALID). With the flag off, resume realigns the child to the parent's current model exactly as before, byte-for-byte the old behavior — effort is untouched on resume in both modes. Added test coverage for both the flag-off realign path and the flag-on sticky/error paths.

const operation = resumeAgentId !== undefined && resumeAgentId.length > 0 ? 'resume' : 'spawn';
// Workspace model binding (experiment-gated): applied mechanically at
// spawn; the first unbound spawn may ask the user once interactively.
const binding = await this.resolveSpawnBinding(requestedProfileName ?? 'coder', operation, true);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Apply workspace bindings to AgentSwarm launches

With workspace binding enabled, this is the only path that reads or asks for .kimi-code/local.toml bindings. AgentSwarm launches item-based subagents through AgentSwarmToolSessionSubagentHost.runQueued()spawn() without going through this code or passing modelAlias/thinkingEffort, so /subagent-model set coder is ignored for swarm-spawned coder agents even though the feature is described as applying to every new subagent of that type. Move binding resolution into the shared spawn path or wire it through AgentSwarm too.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct — AgentSwarm launches go through runQueued() and never see the bindings. For this PR we've deliberately scoped bindings to Agent-tool spawns only and narrowed the docs accordingly (bindings are applied to subagents spawned via the Agent tool; AgentSwarm support is future work). Rationale: swarm model routing deserves its own design (per-item vs per-batch bindings, ramp behavior), and we'd rather not ship a half-considered version of it here. If maintainers prefer, a clean follow-up is to move binding resolution into the shared SessionSubagentHost.spawn path so swarm benefits mechanically with no swarm-specific code — happy to do that in a separate PR.

Comment on lines +183 to +184
if (target.modelAlias === undefined && subagent.modelAlias !== undefined) {
target.modelAlias = subagent.modelAlias;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Store profile overrides on the subagent edge

Profile bindings are properties of an owner's subagents entry, but this mutates the shared resolved target profile. If two owner profiles bind the same subagent type differently, whichever owner is processed first permanently sets target.modelAlias, so later owners silently run that subagent on the wrong model. Keep the override on the owner-to-subagent link instead of the global target profile.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reply: profile overrides are stored on the shared resolved target

Thanks for the careful read — the mechanism is described accurately. Sharing our analysis of why we kept it, and what the actual blast radius is.

What the mechanism is

A model binding declared in an owner's subagents: entry is conceptually a property of the owner → subagent edge ("when this owner delegates to coder, use model M"). applySubagentOverrides instead writes it onto the shared resolved target profile (coder.modelAlias = ...), because every subagent type resolves to a single global ResolvedAgentProfile object.

When it would break

The failure mode requires two owner profiles binding the same subagent type differently:

# agent.yaml
subagents:
  coder:
    modelAlias: cheap-model

# researcher.yaml
subagents:
  coder:
    modelAlias: strong-model

Both entries point at the same coder object; the first owner processed wins, and the second owner's binding is silently skipped. Codex's point is exactly right about this.

Why we assess it as low-risk in practice

  1. Unreachable with shipped configuration. The bundled profiles have exactly one owner (agent.yaml) declaring subagent entries. No second owner exists, so the conflict cannot occur out of the box.
  2. The pattern is pre-existing, not introduced here. The description field has used the identical shared-target mechanism since applySubagentDescriptions. This PR extends an established pattern rather than inventing a new one — if the shared-target hazard ever becomes real, it needs solving for description and modelAlias/thinkingEffort together.
  3. Bounded impact. The worst case is a subagent running on an unintended model — a configuration surprise, not data loss or a correctness failure, and it is corrected by editing one binding.
  4. Discovery cost is low by design of this PR. The effective model is now visible in the tool result (model: line), the subagent.spawned event payload, and AgentBackgroundTaskInfo. A wrong-model outcome is observable immediately rather than silent.

What we did about it

  • Added a code comment on applySubagentOverrides documenting the shared-target limitation and the direction of the proper fix (moving overrides onto the owner→subagent edge).
  • We explicitly chose not to do the edge-storage refactor in this PR: it would change the shape of ResolvedAgentProfile.subagents and every consumer for a scenario that is currently unreachable.

If maintainers disagree

Two clean fallbacks, and we're happy to take either:

  • Edge storage: keep { profile, modelAlias, thinkingEffort } per owner→subagent link and resolve per-owner at spawn time.
  • Drop profile bindings from this PR: the workspace local.toml bindings are the core feature and cover the user need; profile-level bindings were included for completeness and can be split into a follow-up.

Yorha9e pushed a commit to Yorha9e/kimi-code that referenced this pull request Jul 19, 2026
…xperiment

Address review feedback on MoonshotAI#1928:

- resume/retry only keep the child's configured model when
  subagent-model-selection is enabled; with the experiment off, resume
  realigns to the parent's current model exactly as before
- spawn-time profile modelAlias/thinkingEffort bindings are likewise
  ignored unless the experiment is enabled
- docs: workspace bindings apply to Agent tool spawns only; AgentSwarm
  does not read bindings yet (swarm-wide routing is future work)
- note the shared-target limitation of profile override resolution
@Yorha9e
Yorha9e force-pushed the feat/subagent-model-binding branch from d5dca1f to 9bd3cb2 Compare July 19, 2026 18:07
@wraghadismail-creator

Copy link
Copy Markdown

Thanks — the experiment-gating part looks fixed, but I think two original review points are still unresolved.

  • AgentSwarm still doesn’t apply workspace bindings. Updating the docs helps, but it doesn’t fix the behavior. I think binding resolution should live in the shared spawn path so Agent tool spawns and AgentSwarm launches behave the same way.

  • The shared-target override issue also looks unchanged. The new comment documents the limitation, but owner-specific model/thinking-effort overrides still seem like they should stay scoped to the owner->subagent edge rather than mutating shared resolved target state.

  • Could we follow up on those remaining pieces here, or at least track them in a separate issues?

@wraghadismail-creator

Copy link
Copy Markdown

Thanks for the work here — the overall direction looks good, but I think there’s still a remaining freshness gap around session.list_changed.

From the PR notes, this path can stall for >45s on macOS under multi-instance fs load because it still depends on fs event delivery. I agree that GET /sessions with ownership is the authoritative path, but I think the current watch-based hint mechanism still needs a reconciliation fallback so clients don’t sit on stale session/ownership state for too long.

Suggested fix:

  • keep fs/watch events as the fast hint
  • add a periodic readdir/stat reconciliation loop in SessionListWatchService
  • rebuild the authoritative session/ownership view from

@Yorha9e

Yorha9e commented Jul 20, 2026

Copy link
Copy Markdown
Author

Thanks — the experiment-gating part looks fixed, but I think two original review points are still unresolved.
AgentSwarm still doesn’t apply workspace bindings. Updating the docs helps, but it doesn’t fix the behavior. I think binding resolution should live in the shared spawn path so Agent tool spawns and AgentSwarm launches behave the same way.
The shared-target override issue also looks unchanged. The new comment documents the limitation, but owner-specific model/thinking-effort overrides still seem like they should stay scoped to the owner->subagent edge rather than mutating shared resolved target state.
Could we follow up on those remaining pieces here, or at least track them in a separate issues?

Thanks for pushing on this — you're right that narrowing the docs doesn't change behavior, and I appreciate the concrete suggestion.
On AgentSwarm specifically, we've spent some time mapping the current swarm machinery (SubagentBatch scheduling, a single uniform subagent_type per batch, one prompt_template, and a star topology where members can't see each other). The current swarm is honestly still fairly minimal here: applying workspace bindings as-is would only bind one model for the entire batch, which isn't actually useful. What swarm really needs is per-member model routing — a swarmIndex → model mapping so different members of one batch can run different models — and that deserves its own design rather than bolting a type-level binding onto a uniform batch.
We're actively exploring what a better swarm should look like, including MoA-style orchestration and intra-swarm communication, so I'd rather not rush a half-fitting change into this PR. Once that exploration lands, I'll file a proper issue/proposal for swarm-level model routing and link it back here.
On the profile edge point: agreed the override belongs on the owner→subagent edge in principle — I'll track that refactor in the same follow-up so it doesn't get lost.
Thanks again for the careful review — this is exactly the push the design needed.

@Yorha9e

Yorha9e commented Jul 20, 2026

Copy link
Copy Markdown
Author

Thanks for the work here — the overall direction looks good, but I think there’s still a remaining freshness gap around session.list_changed.

From the PR notes, this path can stall for >45s on macOS under multi-instance fs load because it still depends on fs event delivery. I agree that GET /sessions with ownership is the authoritative path, but I think the current watch-based hint mechanism still needs a reconciliation fallback so clients don’t sit on stale session/ownership state for too long.

Suggested fix:

  • keep fs/watch events as the fast hint
  • add a periodic readdir/stat reconciliation loop in SessionListWatchService
  • rebuild the authoritative session/ownership view from

This looks unrelated to this PR's scope (per-workspace subagent model bindings) — the session-list freshness/watch mechanism isn't touched here and deserves its own issue or PR. Flagging so it doesn't get lost

Yorha9e pushed a commit to Yorha9e/kimi-code that referenced this pull request Jul 20, 2026
…xperiment

Address review feedback on MoonshotAI#1928:

- resume/retry only keep the child's configured model when
  subagent-model-selection is enabled; with the experiment off, resume
  realigns to the parent's current model exactly as before
- spawn-time profile modelAlias/thinkingEffort bindings are likewise
  ignored unless the experiment is enabled
- docs: workspace bindings apply to Agent tool spawns only; AgentSwarm
  does not read bindings yet (swarm-wide routing is future work)
- note the shared-target limitation of profile override resolution
@Yorha9e
Yorha9e force-pushed the feat/subagent-model-binding branch from 9bd3cb2 to f8293ac Compare July 20, 2026 10:27
@wraghadismail-creator

Copy link
Copy Markdown

Thanks — the experiment-gating part looks fixed, but I think two original review points are still unresolved.
AgentSwarm still doesn’t apply workspace bindings. Updating the docs helps, but it doesn’t fix the behavior. I think binding resolution should live in the shared spawn path so Agent tool spawns and AgentSwarm launches behave the same way.
The shared-target override issue also looks unchanged. The new comment documents the limitation, but owner-specific model/thinking-effort overrides still seem like they should stay scoped to the owner->subagent edge rather than mutating shared resolved target state.
Could we follow up on those remaining pieces here, or at least track them in a separate issues?
Thanks for pushing on this — you're right that narrowing the docs doesn't change behavior, and I appreciate the concrete suggestion.
On AgentSwarm specifically, we've spent some time mapping the current swarm machinery (SubagentBatch scheduling, a single uniform subagent_type per batch, one prompt_template, and a star topology where members can't see each other). The current swarm is honestly still fairly minimal here: applying workspace bindings as-is would only bind one model for the entire batch, which isn't actually useful. What swarm really needs is per-member model routing — a swarmIndex → model mapping so different members of one batch can run different models — and that deserves its own design rather than bolting a type-level binding onto a uniform batch.
We're actively exploring what a better swarm should look like, including MoA-style orchestration and intra-swarm communication, so I'd rather not rush a half-fitting change into this PR. Once that exploration lands, I'll file a proper issue/proposal for swarm-level model routing and link it back here.
On the profile edge point: agreed the override belongs on the owner→subagent edge in principle — I'll track that refactor in the same follow-up so it doesn't get lost.
Thanks again for the careful review — this is exactly the push the design needed.

Hey, hear me out — I actually get your constraint here, and I agree that if the current AgentSwarm shape doesn’t really fit type-level workspace bindings, then it probably doesn’t make sense to force that behavior into this PR just for consistency.

So instead of pushing against that, I tried to think about the remaining gaps in a way that works with the direction you described. I came up with three possible ways this could go, and I’m hoping one of them might fit what you want better.

I think the underlying issue here is that the current binding model is trying to answer two different questions with one mechanism:

  1. what model should a normal subagent spawn use?
  2. what model should a swarm member use if AgentSwarm eventually wants per-member routing?

Those are related, but they’re not really the same problem. That’s why I think the remaining gap is less about “apply bindings everywhere” and more about making launch resolution flexible enough to support both cases without locking AgentSwarm into the wrong semantics too early.

Option 1: shared launch-config resolver + swarm-aware routing

This feels like the cleanest long-term fix to me.

The idea would be to move model/thinking resolution into one shared launch-config resolver that all subagent launches use, but make that resolver capable of accepting swarm-specific routing context.

That way:

  • normal Agent tool spawns still resolve from the current precedence model
    • workspace binding
    • profile binding
    • inherited parent model/effort
  • owner-specific overrides stay scoped to the owner->subagent edge instead of mutating shared resolved target state
  • AgentSwarm launches go through the same shared path, but with extra member-level context like:
    • member index
    • member role
    • shard / prompt variant
    • whatever future routing metadata you end up needing

The reason I like this is that it keeps one shared mechanism for launch resolution, but doesn’t pretend regular subagent spawns and swarm-member launches are the same thing.

For example, a normal coder spawn might just resolve to one workspace-bound model. But a swarm might eventually want something more like:

  • member 0 -> planning model
  • member 1 -> coding model
  • member 2 -> lighter synthesis model

That does not fit a single type-level binding for the whole batch, but it does fit a shared resolver that can accept member-specific context.

Option 2: fix the correctness bug now, defer full swarm routing cleanly

If the full swarm-aware routing design is too much for this PR, I still think there’s a meaningful smaller step here.

That would be:

  • fix the shared-target override issue now by moving owner-specific model/thinking overrides onto the owner->subagent edge
  • apply those overrides only when producing runtime launch config
  • stop mutating the shared resolved target profile
  • move regular spawn binding resolution into a shared launch-config entry point
  • let AgentSwarm use that same entry point too, but explicitly without per-member routing yet

What I like about this option is that it fixes the correctness issue that exists today without forcing a half-fitting AgentSwarm change.

It wouldn’t solve the full swarm problem yet, but it would still:

  • fix cross-owner override leakage
  • remove duplicated launch-resolution behavior
  • create a clean place for future swarm routing to plug into later

Option 3: introduce an explicit swarm-routing abstraction

Another option might be to create a small abstraction boundary specifically for swarm routing instead of trying to stretch the current binding model to cover it.

For example:

  • normal subagent spawns resolve directly through the shared launch-config path
  • AgentSwarm doesn’t try to resolve bindings inline member-by-member
  • instead, it asks something like a SwarmRoutingPolicy for routing input

That policy could stay minimal for now:

  • today: uniform routing only
  • or: inherit only
  • later: per-member routing
  • later: role-based or shard-based routing

The reason I think this might work well is that it gives you a clean extension point for the richer swarm behavior you said you’re already exploring, without hardcoding today’s minimal batch semantics too deeply into the long-term design.

For example, today it could just say:

  • all swarm members inherit parent model

Later it could evolve into:

  • swarmIndex 0 -> planning model
  • swarmIndex 1..N -> coding model
  • final aggregator -> synthesis model

That gives you room to grow without pretending the current type-level binding model already solves the swarm problem.

The one part that still feels important either way

Independent of the AgentSwarm question, the shared-target override issue still looks like a real correctness bug today.

So even if full swarm routing is intentionally deferred, I do think it would still be worth fixing the owner->subagent override scoping now:

  • keep owner-specific overrides on the owner->subagent edge
  • apply them only when producing runtime config for a specific launch
  • do not mutate shared resolved target state

That part feels independently fixable and worth addressing even if the full swarm story comes later.

Tests I’d expect either way

Whichever direction you go, I’d want to see regression coverage proving that:

  • two owners can bind the same subagent type differently without cross-owner leakage
  • normal Agent spawns still respect the expected binding precedence
  • swarm launches don’t silently inherit misleading semantics
  • future routing context can be added without re-breaking the shared launch path

Overall

So I don’t think the remaining issue is really “please apply the current binding model to AgentSwarm as-is.”

It feels more like:

  • fix the correctness bug around owner->subagent overrides
  • centralize runtime launch-config resolution
  • leave room for proper swarm-aware routing instead of forcing today’s type-level binding model onto a batch abstraction that you already know is too limited

If you want the cleanest long-term outcome, I’d lean toward Option 1.
If you want a safer incremental step, Option 2 still seems like a meaningful improvement.
And if you want to preserve flexibility while the swarm design is still evolving, Option 3 could be a good bridge.

@Yorha9e

Yorha9e commented Jul 21, 2026

Copy link
Copy Markdown
Author

Thanks for laying out the three options — and for framing it as two separate questions; that's the right split.

On the shared-target override: confirmed, and the code already confesses it. applySubagentOverrides (profile/resolve.ts) mutates the shared resolved target profile, and its own comment admits "if multiple owners ever bind the same subagent type differently, the first owner processed wins." Latent today (single bundled owner), but wrong as a mechanism. I'll fix it in this PR by moving overrides onto the owner→subagent edge: linkResolvedSubagents will build an edge-scoped view ({...target, modelAlias: sub.modelAlias ?? target.modelAlias, ...}) instead of mutating shared state, plus regression tests for two owners binding the same type differently — exactly the coverage you listed.

On Option 1 — I have to admit this gave me a genuine double-take. You independently described, almost feature for feature, something we've already built on a stacked branch (feat/subagent-binding-slots): shared launch resolution that accepts member-level routing context, while keeping model selection out of the LLM's hands. When I read "member 0 -> planning model, member 1 -> coding model" in your message it was honestly uncanny — that is precisely the shape of what we've been calling named binding slots. Thank you for thinking this through so deeply; two people converging on the same design from opposite directions is the strongest signal I've seen that it's the right one.

On the stacked branch it works like this:

  • Users pre-configure slots in .kimi-code/local.toml under [subagent-slot.<name>] — each slot is a model/effort pair chosen by the user
  • The Agent tool gains a binding_slot parameter: the caller names a slot, never a model — model routing stays user configuration, preserving this PR's "no LLM-facing model directory" stance
  • Precedence: slot > workspace type binding > profile binding > parent inheritance; slots reuse the same ask-once creation flow and the stale-binding repair path
  • For swarm this yields per-member routing with no new semantics: member 0 → binding_slot: planner, members 1..N → worker, final → synthesizer

Why it's not in this PR: we're holding it while finishing a port of the hermes MoA (mixture-of-agents) orchestration flow onto kimi-code — orchestrator → collectors → debaters → aggregators is the primary consumer of instance-level routing, and we'd rather land the routing design once, informed by that real usage, than ship the parameter now and revise it when the swarm design settles. It'll come as a follow-up PR after this one merges; happy to link the branch earlier if you'd like a look.

Separately: the session.list_changed comment reads like it belongs to a different PR (this one doesn't touch session listing or the watch service) — could you confirm?

yorha9e added 6 commits July 21, 2026 22:08
Add an experimental subagent-model-selection feature (off by default,
KIMI_CODE_EXPERIMENTAL_SUBAGENT_MODEL_SELECTION=1) that binds configured
model aliases and thinking efforts to subagent types per workspace:

- Bindings live in <projectRoot>/.kimi-code/local.toml [subagent.<type>]
  and are applied mechanically at spawn (workspace binding > profile
  binding > parent inheritance); the calling agent never sees or
  overrides them, removing LLM discretion from model routing
- First unbound spawn of a type asks the user once interactively and
  persists the answer, including an explicit keep-inheriting choice
- /subagent-model command (list/set/clear) manages bindings via a new
  session RPC chain (agent-core -> node-sdk -> TUI)
- Resume/retry are sticky: a subagent always keeps the model/effort it
  was configured with (persisted via config.update wire records); no
  mid-conversation model switches. Unresolvable stored aliases fail fast
  with a configuration error instead of silently realigning
- Agent profiles can bind modelAlias/thinkingEffort per subagent type
- Effective model/effort are exposed in the subagent.spawned event,
  AgentBackgroundTaskInfo, approval label, and tool result text
…xperiment

Address review feedback on MoonshotAI#1928:

- resume/retry only keep the child's configured model when
  subagent-model-selection is enabled; with the experiment off, resume
  realigns to the parent's current model exactly as before
- spawn-time profile modelAlias/thinkingEffort bindings are likewise
  ignored unless the experiment is enabled
- docs: workspace bindings apply to Agent tool spawns only; AgentSwarm
  does not read bindings yet (swarm-wide routing is future work)
- note the shared-target limitation of profile override resolution
…del aliases

When a stored subagent binding references a model alias missing from the
user's models config, interactive spawns re-ask with the missing-model
reason and persist the repaired binding; non-interactive spawns inherit
the main agent model with an explicit warning in the tool result.
applySubagentOverrides mutated the shared resolved target profile, so
once two owners bound the same subagent type differently the first
processed owner would win for all of them. linkResolvedSubagents now
builds an edge-scoped view of the target ({...target, overrides})
instead of mutating shared state. Single-owner behavior is unchanged;
adds regression coverage for two owners binding the same type.
… dismissed

In non-interactive sessions the question channel exists but is never
answered (e.g. kimi -p), so the missing-model re-ask always dismisses —
previously that path inherited the parent model silently. A dismissed
re-ask now emits the same explicit warning as the no-ask path.
@Yorha9e
Yorha9e force-pushed the feat/subagent-model-binding branch from 78c6093 to a90501a Compare July 21, 2026 14:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

per-workspace model bindings for subagent types/子agent指定模型与思考强度功能

2 participants