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
8 changes: 8 additions & 0 deletions packages/agent-core/src/config/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,12 @@ export const BackgroundConfigSchema = z.object({

export type BackgroundConfig = z.infer<typeof BackgroundConfigSchema>;

export const SubagentConfigSchema = z.object({
model: z.string().optional(),
});

export type SubagentConfig = z.infer<typeof SubagentConfigSchema>;

export const ExperimentalConfigSchema = z.record(z.string(), z.boolean());

export type ExperimentalConfig = z.infer<typeof ExperimentalConfigSchema>;
Expand Down Expand Up @@ -204,6 +210,7 @@ export const KimiConfigSchema = z.object({
loopControl: LoopControlSchema.optional(),
background: BackgroundConfigSchema.optional(),
experimental: ExperimentalConfigSchema.optional(),
subagents: SubagentConfigSchema.optional(),
telemetry: z.boolean().optional(),
raw: z.record(z.string(), z.unknown()).optional(),
});
Expand Down Expand Up @@ -243,6 +250,7 @@ export const KimiConfigPatchSchema = z
loopControl: LoopControlPatchSchema.optional(),
background: BackgroundConfigPatchSchema.optional(),
experimental: ExperimentalConfigPatchSchema.optional(),
subagents: SubagentConfigSchema.optional(),
telemetry: z.boolean().optional(),
})
.strict();
Expand Down
22 changes: 17 additions & 5 deletions packages/agent-core/src/session/subagent-host.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ export class SessionSubagentHost {
const completion = this.runWithActiveChild(agentId, options, async (runOptions) => {
this.emitSubagentSpawned(parent, agentId, profileName, runOptions);
try {
child.config.update({ modelAlias: parent.config.modelAlias });
child.config.update({ modelAlias: this.resolveSubagentModel(parent) });
return await this.runPromptTurn(parent, agentId, child, profileName, runOptions);
} catch (error) {
this.emitSubagentFailed(parent, agentId, runOptions, error);
Expand All @@ -159,7 +159,7 @@ export class SessionSubagentHost {
const completion = this.runWithActiveChild(agentId, options, async (runOptions) => {
try {
runOptions.signal.throwIfAborted();
child.config.update({ modelAlias: parent.config.modelAlias });
child.config.update({ modelAlias: this.resolveSubagentModel(parent) });
this.emitSubagentStarted(parent, agentId);
const turnId = child.turn.retry('agent-host');
if (turnId === null) {
Expand Down Expand Up @@ -220,7 +220,7 @@ export class SessionSubagentHost {
);

child.config.update({
modelAlias: parent.config.modelAlias,
modelAlias: this.resolveSubagentModel(parent),
thinkingLevel: parent.config.thinkingLevel,
systemPrompt: parent.config.systemPrompt,
});
Expand Down Expand Up @@ -350,15 +350,27 @@ export class SessionSubagentHost {
return { result, usage };
}

private resolveSubagentModel(parent: Agent): string {
// Env var override has highest priority
const envModel = process.env.KIMI_SUBAGENT_MODEL;
if (envModel) return envModel;

// Config override from [subagents] section
const subagentModel = this.session.options.config?.subagents?.model;

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 Honor [subagents] when loading TOML

When users set [subagents] model = "..." in config.toml, this lookup never sees it: transformTomlData only preserves explicitly handled plain-object sections and has no subagents branch, so the table is dropped during config load; the write path also lacks a subagents section. As a result, the advertised config option silently falls back to the parent model unless KIMI_SUBAGENT_MODEL is set.

Useful? React with 👍 / 👎.

if (subagentModel) return subagentModel;

// Default: inherit parent model
return parent.config.modelAlias;
}

private async configureChild(
parent: Agent,
child: Agent,
profile: ResolvedAgentProfile,
): Promise<void> {
// A subagent always inherits the parent agent's model.
child.config.update({
cwd: parent.config.cwd,
modelAlias: parent.config.modelAlias,
modelAlias: this.resolveSubagentModel(parent),
thinkingLevel: parent.config.thinkingLevel,
});

Expand Down