From 121b644df49518a7485c378293acee12a5c3b6cb Mon Sep 17 00:00:00 2001 From: Jiang Bohan Date: Wed, 11 Feb 2026 17:09:49 +0800 Subject: [PATCH] fix(subagent): inherit parent provider in spawned subagents MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- packages/core/src/agent/tools.ts | 4 ++++ packages/core/src/agent/tools/sessions-spawn.ts | 9 +++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/packages/core/src/agent/tools.ts b/packages/core/src/agent/tools.ts index f3908d73..5c203412 100644 --- a/packages/core/src/agent/tools.ts +++ b/packages/core/src/agent/tools.ts @@ -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); @@ -165,6 +168,7 @@ export function resolveTools(options: ResolveToolsOptions): AgentTool[] { profileDir: options.profileDir, isSubagent: options.isSubagent, sessionId: options.sessionId, + provider: options.provider, onExecApprovalNeeded: options.onExecApprovalNeeded, }); diff --git a/packages/core/src/agent/tools/sessions-spawn.ts b/packages/core/src/agent/tools/sessions-spawn.ts index 35c0017b..7c26de07 100644 --- a/packages/core/src/agent/tools/sessions-spawn.ts +++ b/packages/core/src/agent/tools/sessions-spawn.ts @@ -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: {