fix(subagent): inherit parent provider in spawned subagents

Pass parent's resolvedProvider through the tool chain (tools.ts →
sessions-spawn.ts → hub.createSubagent) so subagents use the same
LLM provider as the parent. Previously subagents fell back to the
hardcoded default provider, causing API key errors.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Jiang Bohan 2026-02-11 17:09:49 +08:00
parent 2e6d419c27
commit 121b644df4
2 changed files with 11 additions and 2 deletions

View file

@ -26,6 +26,8 @@ export interface CreateToolsOptions {
isSubagent?: boolean | undefined;
/** Session ID of the agent (passed to sessions_spawn tool) */
sessionId?: string | undefined;
/** Resolved provider ID of the parent agent (passed to sessions_spawn for subagent inheritance) */
provider?: string | undefined;
/** Callback invoked when exec tool needs approval before running a command */
onExecApprovalNeeded?: ExecApprovalCallback | undefined;
}
@ -131,6 +133,7 @@ export function createAllTools(options: CreateToolsOptions | string): AgentTool<
const sessionsSpawnTool = createSessionsSpawnTool({
isSubagent: isSubagent ?? false,
...(sessionId !== undefined ? { sessionId } : {}),
...(opts.provider !== undefined ? { provider: opts.provider } : {}),
});
tools.push(sessionsSpawnTool as AgentTool<any>);
@ -165,6 +168,7 @@ export function resolveTools(options: ResolveToolsOptions): AgentTool<any>[] {
profileDir: options.profileDir,
isSubagent: options.isSubagent,
sessionId: options.sessionId,
provider: options.provider,
onExecApprovalNeeded: options.onExecApprovalNeeded,
});

View file

@ -57,6 +57,8 @@ export interface CreateSessionsSpawnToolOptions {
isSubagent?: boolean;
/** Session ID of the current (requester) agent */
sessionId?: string;
/** Resolved provider ID of the parent agent (inherited by subagents) */
provider?: string;
}
export function createSessionsSpawnTool(
@ -67,7 +69,9 @@ export function createSessionsSpawnTool(
label: "Spawn Subagent",
description:
"Spawn a background subagent to handle a specific task. The subagent runs in an isolated session with its own tool set. " +
"When it completes, its findings are announced back to you automatically. " +
"When it completes, its findings are delivered directly into your context automatically — you do NOT need to poll or check. " +
"IMPORTANT: After spawning subagents, continue with any other immediate tasks you have, or simply finish your turn and wait. " +
"Do NOT call sessions_list to check on subagents you just spawned — results take time and will arrive on their own. " +
"Use this for parallelizable work, long-running analysis, or tasks that benefit from isolation.",
parameters: SessionsSpawnSchema,
execute: async (_toolCallId, args) => {
@ -107,6 +111,7 @@ export function createSessionsSpawnTool(
const childAgent = hub.createSubagent(childSessionId, {
systemPrompt,
model,
provider: options.provider,
});
// Register the run for lifecycle tracking.
@ -127,7 +132,7 @@ export function createSessionsSpawnTool(
content: [
{
type: "text",
text: `Subagent spawned successfully.\n\nRun ID: ${runId}\nSession: ${childSessionId}\nTask: ${label || task.slice(0, 80)}\n\nThe subagent is now working in the background. You will receive its findings when it completes.`,
text: `Subagent spawned successfully.\n\nRun ID: ${runId}\nSession: ${childSessionId}\nTask: ${label || task.slice(0, 80)}\n\nThe subagent is now working in the background. Its findings will be delivered directly into your context when it completes — do NOT poll or call sessions_list for it. Continue with other tasks or finish your turn.`,
},
],
details: {