Skip to content

feat: add /swarm-model command for subagent model override#589

Open
KJ-AIML wants to merge 3 commits into
MoonshotAI:mainfrom
KJ-AIML:feat/swarm-subagent-model
Open

feat: add /swarm-model command for subagent model override#589
KJ-AIML wants to merge 3 commits into
MoonshotAI:mainfrom
KJ-AIML:feat/swarm-subagent-model

Conversation

@KJ-AIML

@KJ-AIML KJ-AIML commented Jun 9, 2026

Copy link
Copy Markdown

Related Issue

No existing issue — this was requested directly as a user need.

Problem

When using swarm mode, all subagents inherit the main agent's model. Users running expensive models (e.g., deepseek-v4-pro) as their main model pay that cost for every parallel subagent too, even for simple sub-tasks that could run on a cheaper model (e.g., deepseek-v4-flash). There is no way to configure a separate model for subagents.

What changed

Added a /swarm-model slash command and a sub_agent_model config key that lets users set a different model for all swarm subagents.

Backend (packages/agent-core)

  • Added subAgentModel: string | null to the config schema and TOML serialization.
  • Updated 4 locations in subagent-host.ts (configureChild, resume, retry, startBtw) to read parent.kimiConfig?.subAgentModel instead of the hardcoded parent.config.modelAlias. Falls back to the parent model when not set.

TUI (apps/kimi-code)

  • Registered /swarm-model command with model picker support (reuses existing TabbedModelSelectorComponent).
  • /swarm-model → opens picker; /swarm-model <alias> → pre-selects alias; /swarm-model off → clears override.
  • Populated subAgentModel in AppState on login, logout, and config reload.

Docs

  • Added /swarm-model to slash commands reference (en + zh).
  • Added sub_agent_model to config files reference (en + zh).

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 (config round-trip: 25/25, swarm-model command: 20/20).
  • 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 Jun 9, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 5a3e3c2

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

This PR includes changesets to release 4 packages
Name Type
@moonshot-ai/agent-core Minor
@moonshot-ai/kimi-code Minor
@moonshot-ai/acp-adapter Patch
@moonshot-ai/migration-legacy Patch

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: 7f4ddc0d07

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

}

try {
await host.harness.setConfig({ subAgentModel: alias });

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 Update the active session when changing swarm model

When /swarm-model is used after a session is already active, this only persists the new value to config.toml and updates TUI state; existing Session/Agent instances keep the config object they were constructed with, and the new subagent path reads parent.kimiConfig?.subAgentModel when spawning. As a result, the command can report Swarm subagents will use <alias> while swarms in the current session still use the old/inherited model until a reload or new session. Please also update the live session/agent runtime state, or make the subagent host read the refreshed config.

Useful? React with 👍 / 👎.

@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: 67d4ef82e5

ℹ️ About Codex in GitHub

Your team has set up Codex to 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 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

// Push the updated config to the live session so active agents pick it up
const session = host.session;
if (session !== undefined) {
await session.reloadSession();

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 Block clearing swarm model while streaming

When /swarm-model off is entered while a turn is still running, this path is allowed by the command registry (availability: 'always') and unlike setSwarmModel it does not check streamingPhase before calling session.reloadSession(). The core reload path rejects active sessions with TURN_AGENT_BUSY, and because clearSwarmModel is launched with void clearSwarmModel(host) that rejection is not caught by the slash-command dispatcher after the config has already been written. Please apply the same idle guard/catch here so clearing the override during streaming reports a normal error instead of leaving the UI/runtime out of sync or surfacing an unhandled rejection.

Useful? React with 👍 / 👎.

}

export function handleSwarmModelCommand(host: SlashCommandHost, args: string): void {
const alias = args.trim().toLowerCase();

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 Preserve model alias casing in /swarm-model

Model aliases are case-sensitive config keys (models is a string-keyed record, and /model checks availableModels[alias] without lowercasing), but this command lowercases the user's argument before lookup and persistence. With a valid custom alias such as ClaudeSonnet, /swarm-model ClaudeSonnet looks for availableModels['claudesonnet'] and reports it as unknown, making direct selection impossible for mixed-case aliases. Keep the original trimmed alias for lookup and only compare a lowercased copy for the off subcommand.

Useful? React with 👍 / 👎.

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.

1 participant