MoonshotAI / MoonshotAI/kimi-code

Subagent thinking effort stuck at "high" for third-party models: support_efforts ignored and global/inherited effort always wins

Open
#3,190 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

bug
Dominant language
TypeScript
Stars
7.5k
Forks
1.2k
Avg merge
11h 53m
Merged PRs (30d)
350

Description

What version of Kimi Code is running?

Reported on 0.38.x; mechanism verified against main @ 9a71582.

Which open platform/subscription were you using?

Third-party model (custom OpenAI-compatible provider configured via config file).

What issue are you seeing?

Original user report (Chinese):

kimi code调用子代理的思考强度有严重bug。我配置了第三方模型,无论我修改config文件里的描述还是web端的设置,或者我直接在提示词里直接说明使用max思考强度都没用。调用子代理都只会使用high思考强度(可能和主代理思考强度有关)最离谱的是,我把config文件中子代理模型中的思考强度删掉了low和high,只保留了max,调用子代理时依然会使用high思考强度

Summary: with a third-party model configured, subagents always send thinking effort high, and none of the user's countermeasures work:

  • editing the model's thinking fields in the config file;
  • changing the thinking setting in the web UI;
  • asking for "max" thinking explicitly in the prompt;
  • even removing low/high from the subagent model's support_efforts so only max remains — subagents still send high.
What steps can reproduce the bug?
  1. Configure a third-party (non-Kimi protocol) model and a [secondary_model] pool for subagents.
  2. Set that model's support_efforts to ["max"] only.
  3. Spawn a subagent (Agent tool) bound to that model.
  4. Inspect the outgoing request: reasoning_effort is "high".
What did you expect to happen?
  • A subagent model that declares support_efforts: ["max"] should resolve to max (or at least to a declared effort), regardless of protocol.
  • Global/inherited effort should not silently override a subagent model's declared constraints; subagent binding should clamp to the target model's declared efforts.
  • The maxhigh startup migration should not rewrite a value the user deliberately set via the UI.
Root cause analysis (main @ 9a71582)

How a subagent's thinking effort is resolved (v2 engine):

  1. Subagent inheriting the caller's model (primary, or no [secondary_model.models] pool) inherits the caller agent's current thinking levelresolveSubagentBinding returns own.thinkingLevel, and fork binds thinking ?? sourceData.thinkingLevel (agent-core-v2/src/session/subagent/configSection.ts, agent-core-v2/src/session/agentLifecycle/agentLifecycleService.ts).
  2. Subagent bound to a pool/force model gets thinking = undefined; at bind time it resolves via resolveThinkingEffortForModel(undefined, global [thinking] config, model, strict) — the global thinking.effort wins over the model's own default_effort / support_efforts (agent-core-v2/src/agent/profile/profileService.ts, agent-core-v2/src/kosong/model/thinking.ts).
  3. Prompt-level requests cannot help: the subagent spawn path has no thinking parameter at all — only a model choice.

Why high survives every countermeasure:

  • Non-Kimi protocols never validate support_efforts. strictThinkingValidation is only enabled for the kimi provider (kosong/provider/providers/kimi/kimi.contrib.ts:96). For OpenAI/Anthropic-compatible third-party providers the resolved effort is passed through verbatim as reasoning_effort (kosong/provider/bases/openai/openai-legacy.ts:616), so editing support_efforts changes nothing. (This half is addressed by PR #3144.)
  • The web UI writes thinking effort to the global config (POST /config), so both main-agent and subagent resolution pick it up.
  • Startup migration migrateThinkingEffortMaxToHigh rewrites a persisted thinking.effort = "max" to "high" once (agent-core-v2/src/app/config/migrations.ts), because max is session-only now — a user who set max via the web UI is silently moved to high on the next start.
  • When a model declares support_efforts containing high but no default_effort, registration defaults default_effort to high (kosong/model/modelAuth.ts; v1: agent-core/src/config/model.ts).
Additional context

PR #3144 implements "declared support_efforts ⇒ fall back to a declared effort" independent of protocol, which fixes the verbatim-passthrough half once merged. The precedence question (global/inherited high winning over a subagent model's declaration), the web-UI-writes-global behavior, and the migration behavior are not covered by it.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with resolveSubagentBinding in agent-core-v2/src/session/subagent/configSection.ts and the fork logic in agent-core-v2/src/session/agentLifecycle/agentLifecycleService.ts. Then trace resolveThinkingEffortForModel in agent-core-v2/src/agent/profile/profileService.ts and kosong/model/thinking.ts, along with the migration in agent-core-v2/src/app/config/migrations.ts. Done means subagent effort respects the target model's declared support_efforts, while inherited and global values no longer override valid model constraints or silently rewrite the user's setting.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
backend, devtools
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.