Skip to content

Commit 67873a6

Browse files
committed
Refactor spawn agents to not just pass all params through. Passes all context params and then is explicit about subagent params
1 parent ed1d539 commit 67873a6

File tree

4 files changed

+100
-4
lines changed

4 files changed

+100
-4
lines changed

packages/agent-runtime/src/run-agent-step.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -506,6 +506,7 @@ export async function loopAgentSteps(
506506
| 'system'
507507
| 'template'
508508
| 'toolCallParams'
509+
| 'tools'
509510
> &
510511
ParamsExcluding<typeof getAgentTemplate, 'agentId'> &
511512
ParamsExcluding<

packages/agent-runtime/src/tools/handlers/tool/spawn-agent-inline.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
logAgentSpawn,
55
executeSubagent,
66
createAgentState,
7+
extractSubagentContextParams,
78
} from './spawn-agent-utils'
89

910
import type { CodebuffToolHandlerFunction } from '../handler-function-type'
@@ -75,9 +76,13 @@ export const handleSpawnAgentInline = (async (
7576
await previousToolCallFinished
7677

7778
const { agentTemplate, agentType } = await validateAndGetAgentTemplate({
78-
...params,
7979
agentTypeStr,
8080
parentAgentTemplate,
81+
localAgentTemplates: params.localAgentTemplates,
82+
logger,
83+
fetchAgentFromDatabase: params.fetchAgentFromDatabase,
84+
databaseAgentCache: params.databaseAgentCache,
85+
apiKey: params.apiKey,
8186
})
8287

8388
validateAgentInput(agentTemplate, agentType, prompt, spawnParams)
@@ -105,18 +110,24 @@ export const handleSpawnAgentInline = (async (
105110
}
106111

107112
logAgentSpawn({
108-
...params,
109113
agentTemplate: inlineTemplate,
110114
agentType,
111115
agentId: childAgentState.agentId,
112116
parentId: childAgentState.parentId,
113117
prompt,
114118
spawnParams,
115119
inline: true,
120+
logger,
116121
})
117122

123+
// Extract common context params to avoid bugs from spreading all params
124+
const contextParams = extractSubagentContextParams(params)
125+
118126
const result = await executeSubagent({
119-
...params,
127+
...contextParams,
128+
129+
// Spawn-specific params
130+
ancestorRunIds: parentAgentState.ancestorRunIds,
120131
userInputId: `${userInputId}-inline-${agentType}${childAgentState.agentId}`,
121132
prompt: prompt || '',
122133
spawnParams,

packages/agent-runtime/src/tools/handlers/tool/spawn-agent-utils.ts

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,10 @@ import { getAgentTemplate } from '../../../templates/agent-registry'
77
import { filterUnfinishedToolCalls, withSystemTags } from '../../../util/messages'
88

99
import type { AgentTemplate } from '@codebuff/common/types/agent-template'
10+
import type {
11+
AgentRuntimeDeps,
12+
AgentRuntimeScopedDeps,
13+
} from '@codebuff/common/types/contracts/agent-runtime'
1014
import type { Logger } from '@codebuff/common/types/contracts/logger'
1115
import type {
1216
ParamsExcluding,
@@ -19,8 +23,80 @@ import type {
1923
AgentTemplateType,
2024
Subgoal,
2125
} from '@codebuff/common/types/session-state'
26+
import type { ProjectFileContext } from '@codebuff/common/util/file'
2227
import { Message } from '@codebuff/common/types/messages/codebuff-message'
2328

29+
/**
30+
* Common context params needed for spawning subagents.
31+
* These are the params that don't change between different spawn calls
32+
* and are passed through from the parent agent runtime.
33+
*/
34+
export type SubagentContextParams = AgentRuntimeDeps &
35+
AgentRuntimeScopedDeps & {
36+
clientSessionId: string
37+
fileContext: ProjectFileContext
38+
localAgentTemplates: Record<string, AgentTemplate>
39+
repoId: string | undefined
40+
repoUrl: string | undefined
41+
signal: AbortSignal
42+
userId: string | undefined
43+
}
44+
45+
/**
46+
* Extracts the common context params needed for spawning subagents.
47+
* This avoids bugs from spreading all params with `...params` which can
48+
* accidentally pass through params that should be overridden.
49+
*/
50+
export function extractSubagentContextParams(
51+
params: SubagentContextParams,
52+
): SubagentContextParams {
53+
return {
54+
// AgentRuntimeDeps - Environment
55+
clientEnv: params.clientEnv,
56+
ciEnv: params.ciEnv,
57+
// AgentRuntimeDeps - Database
58+
getUserInfoFromApiKey: params.getUserInfoFromApiKey,
59+
fetchAgentFromDatabase: params.fetchAgentFromDatabase,
60+
startAgentRun: params.startAgentRun,
61+
finishAgentRun: params.finishAgentRun,
62+
addAgentStep: params.addAgentStep,
63+
// AgentRuntimeDeps - Billing
64+
consumeCreditsWithFallback: params.consumeCreditsWithFallback,
65+
// AgentRuntimeDeps - LLM
66+
promptAiSdkStream: params.promptAiSdkStream,
67+
promptAiSdk: params.promptAiSdk,
68+
promptAiSdkStructured: params.promptAiSdkStructured,
69+
// AgentRuntimeDeps - Mutable State
70+
databaseAgentCache: params.databaseAgentCache,
71+
liveUserInputRecord: params.liveUserInputRecord,
72+
sessionConnections: params.sessionConnections,
73+
// AgentRuntimeDeps - Analytics
74+
trackEvent: params.trackEvent,
75+
// AgentRuntimeDeps - Other
76+
logger: params.logger,
77+
fetch: params.fetch,
78+
79+
// AgentRuntimeScopedDeps - Client (WebSocket)
80+
handleStepsLogChunk: params.handleStepsLogChunk,
81+
requestToolCall: params.requestToolCall,
82+
requestMcpToolData: params.requestMcpToolData,
83+
requestFiles: params.requestFiles,
84+
requestOptionalFile: params.requestOptionalFile,
85+
sendAction: params.sendAction,
86+
sendSubagentChunk: params.sendSubagentChunk,
87+
apiKey: params.apiKey,
88+
89+
// Core context params
90+
clientSessionId: params.clientSessionId,
91+
fileContext: params.fileContext,
92+
localAgentTemplates: params.localAgentTemplates,
93+
repoId: params.repoId,
94+
repoUrl: params.repoUrl,
95+
signal: params.signal,
96+
userId: params.userId,
97+
}
98+
}
99+
24100
/**
25101
* Checks if a parent agent is allowed to spawn a child agent
26102
*/

packages/agent-runtime/src/tools/handlers/tool/spawn-agents.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
createAgentState,
77
logAgentSpawn,
88
executeSubagent,
9+
extractSubagentContextParams,
910
} from './spawn-agent-utils'
1011

1112
import type { CodebuffToolHandlerFunction } from '../handler-function-type'
@@ -111,8 +112,14 @@ export const handleSpawnAgents = (async (
111112
logger,
112113
})
113114

115+
// Extract common context params to avoid bugs from spreading all params
116+
const contextParams = extractSubagentContextParams(params)
117+
114118
const result = await executeSubagent({
115-
...params,
119+
...contextParams,
120+
121+
// Spawn-specific params
122+
ancestorRunIds: parentAgentState.ancestorRunIds,
116123
userInputId: `${userInputId}-${agentType}${subAgentState.agentId}`,
117124
prompt: prompt || '',
118125
spawnParams,
@@ -122,6 +129,7 @@ export const handleSpawnAgents = (async (
122129
fingerprintId,
123130
isOnlyChild: agents.length === 1,
124131
excludeToolFromMessageHistory: false,
132+
fromHandleSteps: false,
125133
parentSystemPrompt,
126134
parentTools: agentTemplate.inheritParentSystemPrompt
127135
? parentTools

0 commit comments

Comments
 (0)