@librechat/agents 3.8.5 → 3.8.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/dist/cjs/agents/AgentContext.cjs +1 -1
  2. package/dist/cjs/common/constants.cjs +2 -0
  3. package/dist/cjs/common/constants.cjs.map +1 -1
  4. package/dist/cjs/graphs/Graph.cjs +18 -9
  5. package/dist/cjs/graphs/Graph.cjs.map +1 -1
  6. package/dist/cjs/hitl/approvalReview.cjs +1 -1
  7. package/dist/cjs/hooks/types.cjs.map +1 -1
  8. package/dist/cjs/main.cjs +7 -6
  9. package/dist/cjs/messages/index.cjs +1 -1
  10. package/dist/cjs/messages/prune.cjs +1 -1
  11. package/dist/cjs/run.cjs +7 -3
  12. package/dist/cjs/run.cjs.map +1 -1
  13. package/dist/cjs/stream.cjs +13 -3
  14. package/dist/cjs/stream.cjs.map +1 -1
  15. package/dist/cjs/summarization/node.cjs +3 -1
  16. package/dist/cjs/summarization/node.cjs.map +1 -1
  17. package/dist/cjs/tools/ToolNode.cjs +127 -26
  18. package/dist/cjs/tools/ToolNode.cjs.map +1 -1
  19. package/dist/cjs/tools/local/LocalProgrammaticToolCalling.cjs +1 -0
  20. package/dist/cjs/tools/local/LocalProgrammaticToolCalling.cjs.map +1 -1
  21. package/dist/cjs/tools/subagent/SubagentExecutionRegistry.cjs +0 -1
  22. package/dist/cjs/tools/subagent/SubagentExecutionRegistry.cjs.map +1 -1
  23. package/dist/cjs/tools/subagent/SubagentExecutor.cjs +120 -26
  24. package/dist/cjs/tools/subagent/SubagentExecutor.cjs.map +1 -1
  25. package/dist/cjs/tools/toolBatchReplay.cjs +1 -1
  26. package/dist/cjs/utils/index.cjs +1 -1
  27. package/dist/esm/agents/AgentContext.mjs +1 -1
  28. package/dist/esm/common/constants.mjs +2 -1
  29. package/dist/esm/common/constants.mjs.map +1 -1
  30. package/dist/esm/graphs/Graph.mjs +17 -8
  31. package/dist/esm/graphs/Graph.mjs.map +1 -1
  32. package/dist/esm/hitl/approvalReview.mjs +1 -1
  33. package/dist/esm/hooks/types.mjs.map +1 -1
  34. package/dist/esm/main.mjs +6 -6
  35. package/dist/esm/messages/index.mjs +1 -1
  36. package/dist/esm/messages/prune.mjs +1 -1
  37. package/dist/esm/run.mjs +7 -3
  38. package/dist/esm/run.mjs.map +1 -1
  39. package/dist/esm/stream.mjs +13 -3
  40. package/dist/esm/stream.mjs.map +1 -1
  41. package/dist/esm/summarization/node.mjs +3 -1
  42. package/dist/esm/summarization/node.mjs.map +1 -1
  43. package/dist/esm/tools/ToolNode.mjs +127 -26
  44. package/dist/esm/tools/ToolNode.mjs.map +1 -1
  45. package/dist/esm/tools/local/LocalProgrammaticToolCalling.mjs +1 -0
  46. package/dist/esm/tools/local/LocalProgrammaticToolCalling.mjs.map +1 -1
  47. package/dist/esm/tools/subagent/SubagentExecutionRegistry.mjs +0 -1
  48. package/dist/esm/tools/subagent/SubagentExecutionRegistry.mjs.map +1 -1
  49. package/dist/esm/tools/subagent/SubagentExecutor.mjs +120 -26
  50. package/dist/esm/tools/subagent/SubagentExecutor.mjs.map +1 -1
  51. package/dist/esm/tools/toolBatchReplay.mjs +1 -1
  52. package/dist/esm/utils/index.mjs +1 -1
  53. package/dist/types/common/constants.d.ts +2 -0
  54. package/dist/types/graphs/Graph.d.ts +3 -2
  55. package/dist/types/hooks/types.d.ts +3 -0
  56. package/dist/types/run.d.ts +1 -0
  57. package/dist/types/summarization/node.d.ts +1 -0
  58. package/dist/types/tools/ToolNode.d.ts +4 -2
  59. package/dist/types/tools/subagent/SubagentExecutor.d.ts +7 -4
  60. package/dist/types/types/graph.d.ts +28 -0
  61. package/dist/types/types/run.d.ts +2 -0
  62. package/dist/types/types/tools.d.ts +11 -1
  63. package/package.json +1 -1
  64. package/src/common/constants.ts +3 -0
  65. package/src/graphs/Graph.ts +32 -18
  66. package/src/hooks/types.ts +3 -0
  67. package/src/run.ts +30 -15
  68. package/src/stream.ts +27 -5
  69. package/src/summarization/node.ts +3 -0
  70. package/src/tools/ToolNode.ts +521 -152
  71. package/src/tools/local/LocalProgrammaticToolCalling.ts +1 -0
  72. package/src/tools/subagent/SubagentExecutionRegistry.ts +0 -1
  73. package/src/tools/subagent/SubagentExecutor.ts +214 -55
  74. package/src/types/graph.ts +37 -0
  75. package/src/types/run.ts +2 -0
  76. package/src/types/tools.ts +11 -1
  77. package/src/utils/llmConfig.ts +0 -1
@@ -299,7 +299,8 @@ export declare class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode>
299
299
  /** See {@link t.StandardGraphInput.subagentTasks}. */
300
300
  subagentTasks: t.SubagentTaskConfig | undefined;
301
301
  /** See {@link t.StandardGraphInput.subagentExecutionContext}. */
302
- private readonly subagentExecutionContext?;
302
+ readonly subagentExecutionContext?: t.SubagentExecutionContext;
303
+ private readonly subagentContext?;
303
304
  /** See {@link t.StandardGraphInput.preemption}. */
304
305
  preemption?: t.StreamPreemption;
305
306
  /**
@@ -436,7 +437,7 @@ export declare class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode>
436
437
  * from a discard.
437
438
  */
438
439
  private preemptRestartPending;
439
- constructor({ runId, signal, agents, langfuse, tokenCounter, indexTokenCountMap, calibrationRatio, fadingTier, fadingTiers, subagentUsageSink, subagentTasks, subagentScope, subagentExecutionContext, preemption, streamLimits, toolExecution, }: t.StandardGraphInput, dependencies?: GraphFactoryDependencies);
440
+ constructor({ runId, signal, agents, langfuse, tokenCounter, indexTokenCountMap, calibrationRatio, fadingTier, fadingTiers, subagentUsageSink, subagentTasks, subagentScope, subagentExecutionContext, subagentContext, preemption, streamLimits, toolExecution, }: t.StandardGraphInput, dependencies?: GraphFactoryDependencies);
440
441
  /**
441
442
  * A compaction applies its remove-all inside the agent subgraph, so the
442
443
  * subgraph's result carries only the retained tail, and an outer reducer
@@ -1,4 +1,5 @@
1
1
  import type { BaseMessage } from '@langchain/core/messages';
2
+ import type { SubagentExecutionContext } from '@/types/graph';
2
3
  import type { InjectedMessage } from '@/types/tools';
3
4
  /**
4
5
  * Closed set of hook lifecycle events supported by the hooks system.
@@ -33,6 +34,8 @@ export type StopDecision = 'continue' | 'block';
33
34
  * hook to a specific agent regardless of subagent scope.
34
35
  */
35
36
  export interface BaseHookInput {
37
+ /** SDK-owned child lineage, including distinct identities for concurrent self-spawns. */
38
+ executionContext?: SubagentExecutionContext;
36
39
  runId: string;
37
40
  threadId?: string;
38
41
  agentId?: string;
@@ -22,6 +22,7 @@ export declare class Run<_T extends t.BaseGraphState> {
22
22
  private maxStopContinuations;
23
23
  private streamLimits?;
24
24
  private subagentTasks?;
25
+ private subagentContext?;
25
26
  private indexTokenCountMap?;
26
27
  calibrationRatio: number;
27
28
  fadingTier?: t.FadingTier;
@@ -14,6 +14,7 @@ interface CreateSummarizeNodeParams {
14
14
  config?: RunnableConfig;
15
15
  runId?: string;
16
16
  isMultiAgent: boolean;
17
+ getSubagentExecutionContext?: () => t.SubagentExecutionContext | undefined;
17
18
  hookRegistry?: HookRegistry;
18
19
  getToolsForBinding?: (provider: t.ProviderName, clientOptions: t.ClientOptions | undefined) => t.GraphTools | undefined;
19
20
  dispatchRunStep: (runStep: t.RunStep, config?: RunnableConfig) => Promise<void>;
@@ -161,6 +161,7 @@ export declare class ToolNode<T = any> extends RunnableCallable<T, T> {
161
161
  * even where `agentId` (the subagent-scope marker) is undefined.
162
162
  */
163
163
  private executingAgentId?;
164
+ private readonly executionContext?;
164
165
  private executingAgentName?;
165
166
  private rootAgentId?;
166
167
  private rootAgentName?;
@@ -225,7 +226,7 @@ export declare class ToolNode<T = any> extends RunnableCallable<T, T> {
225
226
  * other's in-flight state.
226
227
  */
227
228
  private anonBatchCounter;
228
- constructor({ tools, toolMap, name, tags, trace, runLangfuse, agentLangfuse, errorHandler, toolCallStepIds, handleToolErrors, loadRuntimeTools, toolRegistry, toolDefinitions, getDiscoveredToolNames, sessions, codeSessionKey, eventDrivenMode, eagerEventToolExecution, eagerEventToolExecutions, eagerEventToolUsageCount, eagerEventToolSuppressions, agentId, executingAgentId, executingAgentName, rootAgentId, rootAgentName, directToolNames, interruptingToolNames, codeSessionToolNames, maxContextTokens, maxToolResultChars, hookRegistry, humanInTheLoop, toolOutputReferences, toolOutputRegistry, toolExecution, fileCheckpointer, getBreakerSignal, getRunScope, preparedSubagents, restoreRunStepResumeState, createRunStepResumeState, }: t.ToolNodeConstructorParams);
229
+ constructor({ tools, toolMap, name, tags, trace, runLangfuse, agentLangfuse, errorHandler, toolCallStepIds, handleToolErrors, loadRuntimeTools, toolRegistry, toolDefinitions, getDiscoveredToolNames, sessions, codeSessionKey, eventDrivenMode, eagerEventToolExecution, eagerEventToolExecutions, eagerEventToolUsageCount, eagerEventToolSuppressions, agentId, executingAgentId, executionContext, executingAgentName, rootAgentId, rootAgentName, directToolNames, interruptingToolNames, codeSessionToolNames, maxContextTokens, maxToolResultChars, hookRegistry, humanInTheLoop, toolOutputReferences, toolOutputRegistry, toolExecution, fileCheckpointer, getBreakerSignal, getRunScope, preparedSubagents, restoreRunStepResumeState, createRunStepResumeState, }: t.ToolNodeConstructorParams);
229
230
  invoke(input: any, options?: Partial<RunnableConfig>): Promise<any>;
230
231
  private withToolScope;
231
232
  /**
@@ -411,6 +412,7 @@ export declare class ToolNode<T = any> extends RunnableCallable<T, T> {
411
412
  * paths derive the runtime session hint identically. */
412
413
  private resolveRuntimeSessionHint;
413
414
  private storeCodeSessionFromResults;
415
+ private retainCodeSessionInputsFromRequests;
414
416
  /**
415
417
  * Post-processes standard runTool outputs: dispatches ON_RUN_STEP_COMPLETED
416
418
  * and stores code session context. Mirrors the completion handling in
@@ -531,7 +533,7 @@ export declare class ToolNode<T = any> extends RunnableCallable<T, T> {
531
533
  * invocations cannot race on shared mutable state.
532
534
  */
533
535
  private executeViaEvent;
534
- protected run(input: any, config: RunnableConfig, referenceReplay?: {
536
+ protected run(input: T, config: RunnableConfig, referenceReplay?: {
535
537
  state?: ToolOutputReferenceState;
536
538
  }): Promise<T>;
537
539
  private isSendInput;
@@ -1,7 +1,7 @@
1
1
  import { BaseMessage } from '@langchain/core/messages';
2
2
  import type { RunnableConfig } from '@langchain/core/runnables';
3
3
  import type { ToolCall } from '@langchain/core/messages/tool';
4
- import type { MultiAgentGraphState, HumanInTheLoopConfig, StandardGraphInput, ExecutableSubagentConfigEntry, SubagentExecutionContext, SubagentTaskConfig, SubagentTaskRuntime, SubagentUsageSink, TokenCounter } from '@/types';
4
+ import type { MultiAgentGraphState, HumanInTheLoopConfig, StandardGraphInput, ExecutableSubagentConfigEntry, SubagentExecutionContext, SubagentContextAdapter, SubagentContextResult, SubagentTaskConfig, SubagentTaskRuntime, SubagentUsageSink, TokenCounter } from '@/types';
5
5
  import type { SubagentResumeManifest, SettledSubagentToolOutput } from './SubagentReplay';
6
6
  import type { GraphFactory } from '@/graphs/graphFactory';
7
7
  import type { StandardGraph } from '@/graphs/Graph';
@@ -71,11 +71,11 @@ export type SubagentExecuteParams = {
71
71
  /** Host-restored child transcript for a fresh continuation run. @internal */
72
72
  initialMessages?: BaseMessage[];
73
73
  };
74
- export type SubagentExecuteResult = {
75
- content: string;
76
- messages: BaseMessage[];
74
+ export type SubagentExecuteResult = SubagentContextResult & {
77
75
  /** Tagged internal failure; foreground callers retain the legacy content. */
78
76
  error?: string;
77
+ /** Completed child work whose host projection must be retried without re-execution. */
78
+ retryableDelivery?: true;
79
79
  };
80
80
  /**
81
81
  * Factory that constructs a child graph for subagent execution. Injected
@@ -160,6 +160,7 @@ export type SubagentExecutorOptions = {
160
160
  usageSink?: SubagentUsageSink;
161
161
  /** Host-owned process-local task namespace for detached execution. */
162
162
  taskConfig?: SubagentTaskConfig;
163
+ subagentContext?: SubagentContextAdapter;
163
164
  };
164
165
  export declare class SubagentExecutor {
165
166
  private readonly configs;
@@ -187,6 +188,7 @@ export declare class SubagentExecutor {
187
188
  private readonly createDetachedChildGraphFactory?;
188
189
  private readonly usageSink?;
189
190
  private readonly taskConfig?;
191
+ private readonly subagentContext?;
190
192
  private readonly executions;
191
193
  private replayCheckpointWorkflow?;
192
194
  private readonly resolveParentHandlerRegistry?;
@@ -266,6 +268,7 @@ export declare class SubagentExecutor {
266
268
  private persistChildCheckpointMarker;
267
269
  execute(params: SubagentExecuteParams): Promise<SubagentExecuteResult>;
268
270
  private executeOnce;
271
+ private completeHostContext;
269
272
  /**
270
273
  * Emits a single {@link GraphEvents.ON_SUBAGENT_UPDATE} envelope through the
271
274
  * parent's handler registry. Silent no-op when no parent registry is set.
@@ -278,6 +278,8 @@ export type StandardGraphInput = {
278
278
  * do not inherit it, keeping background nesting disabled for the MVP.
279
279
  */
280
280
  subagentTasks?: SubagentTaskConfig;
281
+ /** Host-owned context and result projection for each isolated child execution. */
282
+ subagentContext?: SubagentContextAdapter;
281
283
  /**
282
284
  * True when this graph IS a subagent child run (set by `SubagentExecutor`
283
285
  * when it constructs the child graph). Drives the hook-input `agentId`
@@ -499,6 +501,32 @@ export interface SubagentExecutionContext {
499
501
  readonly depth: number;
500
502
  readonly ancestry: readonly SubagentAncestryEntry[];
501
503
  }
504
+ /** Trusted identity supplied before a child can access host-owned resources. */
505
+ export interface SubagentContextInput {
506
+ executionContext: SubagentExecutionContext;
507
+ parentThreadId?: string;
508
+ memberAgentIds: readonly string[];
509
+ signal: AbortSignal;
510
+ resumed: boolean;
511
+ }
512
+ export interface PreparedSubagentContext {
513
+ /** Added to the initial child input; checkpoint recovery does not add them again. */
514
+ messages?: BaseMessage[];
515
+ /** Host configuration; SDK execution and checkpoint identities remain authoritative. */
516
+ configurable?: RunnableConfig['configurable'];
517
+ /** Each entry replaces that member's inherited code partition and initial sessions. */
518
+ agentSessions?: Readonly<Record<string, Pick<AgentInputs, 'codeSessionKey' | 'initialSessions'>>>;
519
+ }
520
+ export interface SubagentContextResult {
521
+ content: string;
522
+ messages: BaseMessage[];
523
+ }
524
+ export interface SubagentContextAdapter {
525
+ /** Reauthorizes reconstructed executions; durable work must be idempotent by child run ID. */
526
+ prepare(input: SubagentContextInput): Promise<PreparedSubagentContext>;
527
+ /** Projects durable references into the result returned to the parent. */
528
+ complete?(input: SubagentContextInput, result: SubagentContextResult): Promise<Pick<SubagentContextResult, 'content'>>;
529
+ }
502
530
  /**
503
531
  * Wrapper event emitted when a subagent's child graph dispatches activity.
504
532
  * Lets hosts show subagent progress in a UI surface separate from the parent
@@ -272,6 +272,8 @@ export type RunConfig = {
272
272
  * Omit to preserve foreground-only subagent behavior.
273
273
  */
274
274
  subagentTasks?: SubagentTaskConfig;
275
+ /** Authorizes and supplies host-owned context to isolated child runs. */
276
+ subagentContext?: g.SubagentContextAdapter;
275
277
  /**
276
278
  * Pre-constructed hook registry for this run. Hooks fire at lifecycle
277
279
  * points in `processStream` (RunStart, UserPromptSubmit, Stop,
@@ -3,10 +3,10 @@ import type { StructuredToolInterface } from '@langchain/core/tools';
3
3
  import type { ToolCall } from '@langchain/core/messages/tool';
4
4
  import type { MessageContentComplex, RunStepResumeState, ToolErrorData } from './stream';
5
5
  import type { ToolOutputReferenceRegistry } from '@/tools/toolOutputReferences';
6
+ import type { LangfuseConfig, SubagentExecutionContext } from './graph';
6
7
  import type { PreparedSubagents } from '@/tools/preparedSubagents';
7
8
  import type { RunBreakerScope } from '@/llm/streamLimits';
8
9
  import type { HumanInTheLoopConfig } from './hitl';
9
- import type { LangfuseConfig } from './graph';
10
10
  import type { HookRegistry } from '@/hooks';
11
11
  /** Replacement type for `import type { ToolCall } from '@langchain/core/messages/tool'` in order to have stringified args typed */
12
12
  export type CustomToolCall = {
@@ -63,6 +63,7 @@ export type EagerEventToolExecution = {
63
63
  toolName: string;
64
64
  args: Record<string, unknown>;
65
65
  request: ToolCallRequest;
66
+ codeSessionBaselineByName?: ReadonlyMap<string, string>;
66
67
  promise: Promise<EagerEventToolExecutionOutcome>;
67
68
  /**
68
69
  * True when the streaming eager path already emitted the user-visible
@@ -139,6 +140,8 @@ export type ToolNodeOptions = {
139
140
  /** ID of the agent that owns this tool node, surfaced to hooks as `executingAgentId`
140
141
  * so a batch can be attributed to a specific agent even where `agentId` is undefined. */
141
142
  executingAgentId?: string;
143
+ /** SDK-owned identity of the child execution, independent of reusable agent IDs. */
144
+ executionContext?: SubagentExecutionContext;
142
145
  /** Name of the agent that owns this tool node, used for active Langfuse attribution. */
143
146
  executingAgentName?: string;
144
147
  /** Root graph-agent identity retained alongside the currently executing tool owner. */
@@ -529,6 +532,10 @@ export type ToolCallRequest = {
529
532
  session_id: string;
530
533
  files?: CodeEnvFile[];
531
534
  };
535
+ /** Request-time execution session used to detect host session refreshes. */
536
+ codeSessionBaselineId?: string;
537
+ /** Preserve request-provisioned code inputs after an eager identity mismatch. */
538
+ retainCodeSessionInputs?: true;
532
539
  /**
533
540
  * Stable runtime session hint for stateful sandbox sessions. Orthogonal to
534
541
  * `codeSessionContext` (which threads the transient exec-session for file
@@ -550,6 +557,8 @@ export type CallerCapabilityProjectionSnapshot = {
550
557
  };
551
558
  /** Batch request containing ALL tool calls for a graph step */
552
559
  export type ToolExecuteBatchRequest = {
560
+ /** SDK-owned child lineage. Unset for tools in the root graph. */
561
+ executionContext?: SubagentExecutionContext;
553
562
  /** All tool calls from the AIMessage */
554
563
  toolCalls: ToolCallRequest[];
555
564
  /** User ID for context */
@@ -1134,6 +1143,7 @@ export type ProgrammaticHookContext = {
1134
1143
  runId: string;
1135
1144
  threadId?: string;
1136
1145
  agentId?: string;
1146
+ executionContext?: SubagentExecutionContext;
1137
1147
  executingAgentId?: string;
1138
1148
  };
1139
1149
  /** Search mode: code_interpreter uses external sandbox, local uses safe substring matching */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@librechat/agents",
3
- "version": "3.8.5",
3
+ "version": "3.8.6",
4
4
  "reova": {
5
5
  "enabled": true,
6
6
  "endpoint": "https://telemetry.reo.dev/data"
@@ -1,3 +1,6 @@
1
+ /** Host context preparation and trusted subagent execution identity are supported. */
2
+ export const SUBAGENT_CONTEXT_VERSION = 1;
3
+
1
4
  /**
2
5
  * Anthropic direct API tool schema overhead multiplier.
3
6
  * Empirically calibrated against real MCP tool sets (29 tools).
@@ -133,10 +133,18 @@ import {
133
133
  annotateMessagesForLLM,
134
134
  ToolOutputReferenceRegistry,
135
135
  } from '@/tools/toolOutputReferences';
136
+ import {
137
+ prepareProviderRequest,
138
+ usesNativeOpenAIResponses,
139
+ } from '@/llm/prepareProviderRequest';
136
140
  import {
137
141
  resolveLangfuseRuntimeScope,
138
142
  withLangfuseRuntimeScope,
139
143
  } from '@/langfuseRuntimeScope';
144
+ import {
145
+ ManualSummarizationSkippedError,
146
+ shouldTriggerSummarization,
147
+ } from '@/summarization';
140
148
  import {
141
149
  getToolContentCharLength,
142
150
  serializeToolContentBounded,
@@ -150,6 +158,11 @@ import {
150
158
  PreparedSubagents,
151
159
  PreparedSubagentError,
152
160
  } from '@/tools/preparedSubagents';
161
+ import {
162
+ createRemoveAllMessage,
163
+ messagesStateReducer,
164
+ } from '@/messages/reducer';
165
+ import { createToolHistoryPreparation } from '@/messages/toolHistoryProjection';
153
166
  import { ToolNode as CustomToolNode, toolsCondition } from '@/tools/ToolNode';
154
167
  import { shouldTraceToolNodeForLangfuse } from '@/langfuseToolOutputTracing';
155
168
  import { createLocalCodingToolBundle } from '@/tools/local/LocalCodingTools';
@@ -157,29 +170,16 @@ import { SUBAGENT_REPLAY_CONTROLLER } from '@/tools/subagent/SubagentReplay';
157
170
  import { applyGraphRuntimeConfig } from '@/graphs/applyGraphRuntimeConfig';
158
171
  import { isFadingTier, isInformativeFadingTier } from '@/messages/fading';
159
172
  import { createContextPressureMeter } from '@/llm/contextPressureMeter';
160
- import { createToolHistoryPreparation } from '@/messages/toolHistoryProjection';
161
173
  import { safeDispatchCustomEvent, emitAgentLog } from '@/utils/events';
162
- import {
163
- prepareProviderRequest,
164
- usesNativeOpenAIResponses,
165
- } from '@/llm/prepareProviderRequest';
166
174
  import { createCloudflareCodingToolBundle } from '@/tools/cloudflare';
167
175
  import { calculateMaxToolCallInputChars } from '@/utils/truncation';
168
176
  import { prepareToolsForPromptCache } from '@/llm/promptCacheTools';
169
177
  import { providerRequiresStrictAlternation } from '@/llm/providers';
170
178
  import { buildSubagentToolParams } from '@/tools/SubagentTool';
171
179
  import { initializeLangfuseTracing } from '@/instrumentation';
172
- import {
173
- ManualSummarizationSkippedError,
174
- shouldTriggerSummarization,
175
- } from '@/summarization';
176
180
  import { isRunStepResumeState } from '@/tools/runStepResume';
177
181
  import { resolveLocalToolsForBinding } from '@/tools/local';
178
182
  import { createSummarizeNode } from '@/summarization/node';
179
- import {
180
- createRemoveAllMessage,
181
- messagesStateReducer,
182
- } from '@/messages/reducer';
183
183
  import { getTruncationStopReason } from '@/llm/truncation';
184
184
  import { createSchemaOnlyTools } from '@/tools/schema';
185
185
  import { AgentContext } from '@/agents/AgentContext';
@@ -1356,7 +1356,8 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
1356
1356
  /** See {@link t.StandardGraphInput.subagentTasks}. */
1357
1357
  subagentTasks: t.SubagentTaskConfig | undefined;
1358
1358
  /** See {@link t.StandardGraphInput.subagentExecutionContext}. */
1359
- private readonly subagentExecutionContext?: t.SubagentExecutionContext;
1359
+ readonly subagentExecutionContext?: t.SubagentExecutionContext;
1360
+ private readonly subagentContext?: t.SubagentContextAdapter;
1360
1361
  /** See {@link t.StandardGraphInput.preemption}. */
1361
1362
  preemption?: t.StreamPreemption;
1362
1363
  /**
@@ -1534,6 +1535,7 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
1534
1535
  subagentTasks,
1535
1536
  subagentScope,
1536
1537
  subagentExecutionContext,
1538
+ subagentContext,
1537
1539
  preemption,
1538
1540
  streamLimits,
1539
1541
  toolExecution,
@@ -1560,6 +1562,7 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
1560
1562
  this.subagentTasks = subagentTasks;
1561
1563
  this.subagentScope = subagentScope === true;
1562
1564
  this.subagentExecutionContext = subagentExecutionContext;
1565
+ this.subagentContext = subagentContext;
1563
1566
  this.preemption = preemption;
1564
1567
  this.streamLimits = resolveStreamLimits(streamLimits);
1565
1568
  this.toolExecution = toolExecution;
@@ -2881,6 +2884,7 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
2881
2884
  // run_id); `executingAgentId` always identifies the owning agent.
2882
2885
  agentId: this.subagentScope ? agentContext?.agentId : undefined,
2883
2886
  executingAgentId: agentContext?.agentId,
2887
+ executionContext: this.subagentExecutionContext,
2884
2888
  executingAgentName: agentContext?.name,
2885
2889
  rootAgentId: this.defaultAgentId,
2886
2890
  rootAgentName: this.agentContexts.get(this.defaultAgentId)?.name,
@@ -2965,6 +2969,7 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
2965
2969
  // hooks can attribute the batch even at the top level.
2966
2970
  agentId: this.subagentScope ? agentContext?.agentId : undefined,
2967
2971
  executingAgentId: agentContext?.agentId,
2972
+ executionContext: this.subagentExecutionContext,
2968
2973
  executingAgentName: agentContext?.name,
2969
2974
  rootAgentId: this.defaultAgentId,
2970
2975
  rootAgentName: this.agentContexts.get(this.defaultAgentId)?.name,
@@ -4627,7 +4632,9 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
4627
4632
  fallbackProvider,
4628
4633
  fallbackClientOptions
4629
4634
  );
4630
- let projection: ReturnType<typeof measureProviderPayload> | undefined;
4635
+ let projection:
4636
+ | ReturnType<typeof measureProviderPayload>
4637
+ | undefined;
4631
4638
  const request = prepareProviderRequest({
4632
4639
  model: fallbackModel,
4633
4640
  messages: cached,
@@ -4644,7 +4651,9 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
4644
4651
  },
4645
4652
  });
4646
4653
  if (projection == null) {
4647
- throw new Error('Fallback preparation did not measure its payload');
4654
+ throw new Error(
4655
+ 'Fallback preparation did not measure its payload'
4656
+ );
4648
4657
  }
4649
4658
  return { request, projection };
4650
4659
  };
@@ -4664,8 +4673,7 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
4664
4673
  if (!projection.fits) {
4665
4674
  const compacted = compactSyntheticProviderContext(
4666
4675
  servingFallbackMessages,
4667
- (candidate) =>
4668
- prepareFallback(candidate).projection
4676
+ (candidate) => prepareFallback(candidate).projection
4669
4677
  );
4670
4678
  if (compacted !== servingFallbackMessages) {
4671
4679
  preparedFallbackRequest = prepareFallback(compacted);
@@ -5025,6 +5033,7 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
5025
5033
  runId,
5026
5034
  threadId: configurable?.thread_id as string | undefined,
5027
5035
  agentId: this.subagentScope ? agentId : undefined,
5036
+ executionContext: this.subagentExecutionContext,
5028
5037
  executingAgentId: agentId,
5029
5038
  sealCount: this.preemptSealCount,
5030
5039
  },
@@ -5247,6 +5256,7 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
5247
5256
  tokenCounter: agentContext.tokenCounter,
5248
5257
  usageSink: this.subagentUsageSink,
5249
5258
  taskConfig: this.subagentTasks,
5259
+ subagentContext: this.subagentContext,
5250
5260
  streamLimits: this.streamLimits,
5251
5261
  humanInTheLoop: this.humanInTheLoop,
5252
5262
  checkpointer: this.compileOptions?.checkpointer,
@@ -5343,6 +5353,9 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
5343
5353
  });
5344
5354
  }
5345
5355
  const result = await executor.execute(executeParams);
5356
+ if (result.retryableDelivery === true) {
5357
+ throw new Error(result.content);
5358
+ }
5346
5359
  return result.content;
5347
5360
  },
5348
5361
  buildSubagentToolParams(executableConfigs, {
@@ -5527,6 +5540,7 @@ export class StandardGraph extends Graph<t.BaseGraphState, t.GraphNode> {
5527
5540
  },
5528
5541
  runId: this.runId,
5529
5542
  isMultiAgent: this.isMultiAgentGraph(),
5543
+ getSubagentExecutionContext: () => this.subagentExecutionContext,
5530
5544
  hookRegistry: this.hookRegistry,
5531
5545
  getToolsForBinding: (
5532
5546
  provider: t.ProviderName,
@@ -1,5 +1,6 @@
1
1
  // src/hooks/types.ts
2
2
  import type { BaseMessage } from '@langchain/core/messages';
3
+ import type { SubagentExecutionContext } from '@/types/graph';
3
4
  import type { InjectedMessage } from '@/types/tools';
4
5
 
5
6
  /**
@@ -57,6 +58,8 @@ export type StopDecision = 'continue' | 'block';
57
58
  * hook to a specific agent regardless of subagent scope.
58
59
  */
59
60
  export interface BaseHookInput {
61
+ /** SDK-owned child lineage, including distinct identities for concurrent self-spawns. */
62
+ executionContext?: SubagentExecutionContext;
60
63
  runId: string;
61
64
  threadId?: string;
62
65
  agentId?: string;
package/src/run.ts CHANGED
@@ -37,11 +37,6 @@ import {
37
37
  DEFAULT_MAX_STOP_CONTINUATIONS,
38
38
  DEFAULT_RECURSION_LIMIT,
39
39
  } from '@/common';
40
- import {
41
- requireValidSubagentResumeManifest,
42
- SUBAGENT_RESUME_ATTEMPT_CONFIG_KEY,
43
- SUBAGENT_RESUME_MANIFEST_CONFIG_KEY,
44
- } from '@/tools/subagent/SubagentReplay';
45
40
  import {
46
41
  ACTIVITY_PHASE_LABEL_PROMPT,
47
42
  ACTIVITY_LABEL_PROMPT,
@@ -57,12 +52,23 @@ import {
57
52
  isLangfuseCallbackHandler,
58
53
  withLangfuseAttributes,
59
54
  } from '@/langfuse';
55
+ import {
56
+ requireValidSubagentResumeManifest,
57
+ SUBAGENT_RESUME_ATTEMPT_CONFIG_KEY,
58
+ SUBAGENT_RESUME_MANIFEST_CONFIG_KEY,
59
+ } from '@/tools/subagent/SubagentReplay';
60
60
  import {
61
61
  REASONING_LABEL_PROMPT,
62
62
  buildReasoningLabelTraceSeed,
63
63
  buildReasoningLabelPrompt,
64
64
  normalizeReasoningLabel,
65
65
  } from '@/prompts/reasoningLabel';
66
+ import {
67
+ TOOL_BATCH_REPLAY_KEY,
68
+ restoreToolReplayConfig,
69
+ stripToolBatchReplayState,
70
+ getPublicToolInterruptPayload,
71
+ } from '@/tools/toolBatchReplay';
66
72
  import {
67
73
  hasToolOutputTracingConfig,
68
74
  resolveLangfuseConfig,
@@ -72,12 +78,6 @@ import {
72
78
  cloneToolApprovalInterruptPayload,
73
79
  TOOL_APPROVAL_REVIEW_CONFIG_KEY,
74
80
  } from '@/hitl/approvalReview';
75
- import {
76
- TOOL_BATCH_REPLAY_KEY,
77
- restoreToolReplayConfig,
78
- stripToolBatchReplayState,
79
- getPublicToolInterruptPayload,
80
- } from '@/tools/toolBatchReplay';
81
81
  import {
82
82
  resolveLangfuseDestinationKey,
83
83
  resolveLangfuseTraceAnchorParent,
@@ -474,6 +474,7 @@ export class Run<_T extends t.BaseGraphState> {
474
474
  private maxStopContinuations: number;
475
475
  private streamLimits?: t.StreamLimits;
476
476
  private subagentTasks?: t.SubagentTaskConfig;
477
+ private subagentContext?: t.SubagentContextAdapter;
477
478
  private indexTokenCountMap?: Record<string, number>;
478
479
  calibrationRatio: number = 1;
479
480
  fadingTier?: t.FadingTier;
@@ -556,6 +557,7 @@ export class Run<_T extends t.BaseGraphState> {
556
557
  this.toolExecution = config.toolExecution;
557
558
  this.subagentUsageSink = config.subagentUsageSink;
558
559
  this.subagentTasks = config.subagentTasks;
560
+ this.subagentContext = config.subagentContext;
559
561
  this.preemption = config.preemption;
560
562
  this.maxStopContinuations = resolveMaxStopContinuations(
561
563
  config.maxStopContinuations
@@ -654,6 +656,7 @@ export class Run<_T extends t.BaseGraphState> {
654
656
  fadingTiers: this.fadingTiers,
655
657
  subagentUsageSink: this.subagentUsageSink,
656
658
  subagentTasks: this.subagentTasks,
659
+ subagentContext: this.subagentContext,
657
660
  preemption: this.preemption,
658
661
  streamLimits: this.streamLimits,
659
662
  toolExecution: this.toolExecution,
@@ -696,6 +699,7 @@ export class Run<_T extends t.BaseGraphState> {
696
699
  fadingTiers: this.fadingTiers,
697
700
  subagentUsageSink: this.subagentUsageSink,
698
701
  subagentTasks: this.subagentTasks,
702
+ subagentContext: this.subagentContext,
699
703
  preemption: this.preemption,
700
704
  streamLimits: this.streamLimits,
701
705
  toolExecution: this.toolExecution,
@@ -1283,7 +1287,11 @@ export class Run<_T extends t.BaseGraphState> {
1283
1287
  );
1284
1288
  const publicPayload = stripRunStepResumeState(this._interrupt?.payload);
1285
1289
  if (config.configurable != null) {
1286
- restoreToolReplayConfig(config.configurable, this._interrupt?.interruptId, publicPayload);
1290
+ restoreToolReplayConfig(
1291
+ config.configurable,
1292
+ this._interrupt?.interruptId,
1293
+ publicPayload
1294
+ );
1287
1295
  }
1288
1296
  if (graph.getStopContinuationExecutionId() === '') {
1289
1297
  graph.startStopContinuationExecution(nanoid());
@@ -2015,8 +2023,11 @@ export class Run<_T extends t.BaseGraphState> {
2015
2023
  await this.restoreInterruptFromCheckpoint(callerConfig, resumeUpdate);
2016
2024
  const interrupt = this._interrupt;
2017
2025
  const replayPayload = stripRunStepResumeState(interrupt?.payload);
2018
- const resumeManifest = requireValidSubagentResumeManifest(replayPayload) ??
2019
- requireValidSubagentResumeManifest(stripToolBatchReplayState(replayPayload));
2026
+ const resumeManifest =
2027
+ requireValidSubagentResumeManifest(replayPayload) ??
2028
+ requireValidSubagentResumeManifest(
2029
+ stripToolBatchReplayState(replayPayload)
2030
+ );
2020
2031
  const resumeConfigurable = { ...callerConfig.configurable };
2021
2032
  delete resumeConfigurable[TOOL_APPROVAL_REVIEW_CONFIG_KEY];
2022
2033
  delete resumeConfigurable[TOOL_BATCH_REPLAY_KEY];
@@ -2027,7 +2038,11 @@ export class Run<_T extends t.BaseGraphState> {
2027
2038
  resumeConfigurable[SUBAGENT_RESUME_MANIFEST_CONFIG_KEY] = resumeManifest;
2028
2039
  }
2029
2040
  const publicPayload = stripRunStepResumeState(interrupt?.payload);
2030
- restoreToolReplayConfig(resumeConfigurable, interrupt?.interruptId, publicPayload);
2041
+ restoreToolReplayConfig(
2042
+ resumeConfigurable,
2043
+ interrupt?.interruptId,
2044
+ publicPayload
2045
+ );
2031
2046
  const manifestConfig = {
2032
2047
  ...callerConfig,
2033
2048
  configurable: resumeConfigurable,
package/src/stream.ts CHANGED
@@ -805,6 +805,21 @@ function startEagerToolExecutions(args: {
805
805
  return;
806
806
  }
807
807
 
808
+ const codeSessionBaselineById = new Map(
809
+ entries.map((entry) => [
810
+ entry.id,
811
+ new Map(
812
+ (entry.request.codeSessionContext?.files ?? []).map((file) => [
813
+ file.name,
814
+ `${file.storage_session_id}\0${file.id}`,
815
+ ])
816
+ ),
817
+ ])
818
+ );
819
+ for (const entry of entries) {
820
+ entry.request.codeSessionBaselineId =
821
+ entry.request.codeSessionContext?.session_id;
822
+ }
808
823
  const records: t.EagerEventToolExecution[] = [];
809
824
  const promise: Promise<t.EagerEventToolExecutionOutcome> = new Promise<
810
825
  t.ToolExecuteResult[]
@@ -818,6 +833,7 @@ function startEagerToolExecutions(args: {
818
833
  }
819
834
  };
820
835
  const batchRequest: t.ToolExecuteBatchRequest = {
836
+ executionContext: graph.subagentExecutionContext,
821
837
  toolCalls: entries.map((entry) => entry.request),
822
838
  userId: graph.config?.configurable?.user_id as string | undefined,
823
839
  agentId: agentContext?.agentId,
@@ -826,10 +842,14 @@ function startEagerToolExecutions(args: {
826
842
  | Partial<Pick<AgentContext, 'getCallerCapabilityProjectionSnapshot'>>
827
843
  | undefined
828
844
  )?.getCallerCapabilityProjectionSnapshot?.(),
829
- configurable: graph.config?.configurable as
830
- | Record<string, unknown>
831
- | undefined,
832
- metadata,
845
+ configurable: {
846
+ ...graph.config?.configurable,
847
+ executionContext: graph.subagentExecutionContext,
848
+ },
849
+ metadata: {
850
+ ...metadata,
851
+ executionContext: graph.subagentExecutionContext,
852
+ },
833
853
  signal: composeAbortSignals(
834
854
  graph.config?.signal,
835
855
  graph.breakerAbort.signal
@@ -873,6 +893,7 @@ function startEagerToolExecutions(args: {
873
893
  toolName: entry.toolName,
874
894
  args: entry.coercedArgs,
875
895
  request: entry.request,
896
+ codeSessionBaselineByName: codeSessionBaselineById.get(entry.id),
876
897
  promise,
877
898
  };
878
899
  records.push(record);
@@ -1653,7 +1674,8 @@ export class ChatModelStreamHandler implements t.EventHandler {
1653
1674
  if (
1654
1675
  eventBreaker != null &&
1655
1676
  eventBreaker.signal.aborted &&
1656
- (eventBreaker.signal.reason instanceof StreamLimitExceededError || eventBreaker.signal.reason instanceof PreparedSubagentError)
1677
+ (eventBreaker.signal.reason instanceof StreamLimitExceededError ||
1678
+ eventBreaker.signal.reason instanceof PreparedSubagentError)
1657
1679
  ) {
1658
1680
  throw eventBreaker.signal.reason;
1659
1681
  }
@@ -924,6 +924,7 @@ async function dispatchCompletionEvents(params: {
924
924
  runId: sessionId,
925
925
  threadId,
926
926
  agentId,
927
+ executionContext: graph.getSubagentExecutionContext?.(),
927
928
  summary: summaryText,
928
929
  messagesAfterCount,
929
930
  },
@@ -948,6 +949,7 @@ interface CreateSummarizeNodeParams {
948
949
  config?: RunnableConfig;
949
950
  runId?: string;
950
951
  isMultiAgent: boolean;
952
+ getSubagentExecutionContext?: () => t.SubagentExecutionContext | undefined;
951
953
  hookRegistry?: HookRegistry;
952
954
  getToolsForBinding?: (
953
955
  provider: t.ProviderName,
@@ -1331,6 +1333,7 @@ export function createSummarizeNode({
1331
1333
  runId: sessionId,
1332
1334
  threadId,
1333
1335
  agentId: request.agentId,
1336
+ executionContext: graph.getSubagentExecutionContext?.(),
1334
1337
  messagesBeforeCount: messagesToRefine.length,
1335
1338
  trigger:
1336
1339
  request.reason === 'manual'