deepagents 1.13.2 → 1.13.4-rc.0

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.
@@ -1,8 +1,8 @@
1
- import { AIMessage, HumanMessage, SystemMessage, ToolMessage, anthropicPromptCachingMiddleware, bedrockPromptCachingMiddleware, context, countTokensApproximately, createAgent, createMiddleware, humanInTheLoopMiddleware, todoListMiddleware, tool } from "langchain";
1
+ import { AIMessage, HumanMessage, SystemMessage, ToolMessage, anthropicPromptCachingMiddleware, bedrockPromptCachingMiddleware, context, countTokensApproximately, createAgent, createMiddleware, humanInTheLoopMiddleware, omitPayload, todoListMiddleware, tool } from "langchain";
2
2
  import { Command, REMOVE_ALL_MESSAGES, ReducedValue, StateSchema, getConfig, getCurrentTaskInput, getStore, isCommand } from "@langchain/langgraph";
3
3
  import { z } from "zod/v4";
4
4
  import micromatch from "micromatch";
5
- import { AIMessage as AIMessage$1, HumanMessage as HumanMessage$1, RemoveMessage, ToolMessage as ToolMessage$1, getBufferString } from "@langchain/core/messages";
5
+ import { AIMessage as AIMessage$1, HumanMessage as HumanMessage$1, RemoveMessage, SystemMessage as SystemMessage$1, ToolMessage as ToolMessage$1, getBufferString } from "@langchain/core/messages";
6
6
  import * as z$2 from "zod";
7
7
  import { z as z$1 } from "zod";
8
8
  import { ContextOverflowError } from "@langchain/core/errors";
@@ -2574,6 +2574,7 @@ function createFilesystemMiddleware(options = {}) {
2574
2574
  }
2575
2575
  return createMiddleware({
2576
2576
  name: "FilesystemMiddleware",
2577
+ tracePolicy: { processInputs: omitPayload },
2577
2578
  stateSchema: FilesystemStateSchema,
2578
2579
  tools: allTools,
2579
2580
  async beforeAgent(state) {
@@ -3313,6 +3314,7 @@ function createSummarizationMiddleware(options) {
3313
3314
  }
3314
3315
  return createMiddleware({
3315
3316
  name: "SummarizationMiddleware",
3317
+ tracePolicy: { processInputs: omitPayload },
3316
3318
  stateSchema: SummarizationStateSchema,
3317
3319
  async wrapModelCall(request, handler) {
3318
3320
  const effectiveMessages = getEffectiveMessages(request.messages ?? [], request.state);
@@ -3358,6 +3360,83 @@ function createSummarizationMiddleware(options) {
3358
3360
  });
3359
3361
  }
3360
3362
  //#endregion
3363
+ //#region src/middleware/utils.ts
3364
+ /**
3365
+ * Utility functions for middleware.
3366
+ *
3367
+ * This module provides shared helpers used across middleware implementations.
3368
+ */
3369
+ /**
3370
+ * Merge custom middleware into an assembled stack by `.name`.
3371
+ *
3372
+ * Matching custom middleware replaces the existing entry in place. New
3373
+ * middleware is appended after the base stack in caller-provided order.
3374
+ */
3375
+ function mergeMiddleware$1(base, custom) {
3376
+ const merged = new Map(base.map((middleware) => [middleware.name, middleware]));
3377
+ for (const middleware of custom) merged.set(middleware.name, middleware);
3378
+ return [...merged.values()];
3379
+ }
3380
+ function middlewareNames(middleware) {
3381
+ return new Set(middleware.map((entry) => entry.name));
3382
+ }
3383
+ function matchingMiddleware(middleware, names) {
3384
+ return middleware.filter((entry) => names.has(entry.name));
3385
+ }
3386
+ /**
3387
+ * Merge custom middleware into default and tail middleware segments.
3388
+ *
3389
+ * Same-name custom entries replace matching defaults in either segment. Novel
3390
+ * custom entries are inserted between the default and tail segments unless
3391
+ * `appendNew` is false.
3392
+ */
3393
+ function mergeMiddlewareStack(defaultMiddleware, customMiddleware, tailMiddleware = [], options = {}) {
3394
+ const defaultMiddlewareNames = middlewareNames(defaultMiddleware);
3395
+ const tailMiddlewareNames = middlewareNames(tailMiddleware);
3396
+ const knownMiddlewareNames = /* @__PURE__ */ new Set([...defaultMiddlewareNames, ...tailMiddlewareNames]);
3397
+ const novelMiddleware = options.appendNew === false ? [] : customMiddleware.filter((entry) => !knownMiddlewareNames.has(entry.name));
3398
+ return [
3399
+ ...mergeMiddleware$1(defaultMiddleware, matchingMiddleware(customMiddleware, defaultMiddlewareNames)),
3400
+ ...novelMiddleware,
3401
+ ...mergeMiddleware$1(tailMiddleware, matchingMiddleware(customMiddleware, tailMiddlewareNames))
3402
+ ];
3403
+ }
3404
+ /**
3405
+ * Append text to a system message.
3406
+ *
3407
+ * Creates a new SystemMessage with the text appended to the existing content.
3408
+ * If the original message has content, the new text is separated by two newlines.
3409
+ *
3410
+ * @param systemMessage - Existing system message or null/undefined.
3411
+ * @param text - Text to add to the system message.
3412
+ * @returns New SystemMessage with the text appended.
3413
+ *
3414
+ * @example
3415
+ * ```typescript
3416
+ * const original = new SystemMessage({ content: "You are a helpful assistant." });
3417
+ * const updated = appendToSystemMessage(original, "Always be concise.");
3418
+ * // Result: SystemMessage with content "You are a helpful assistant.\n\nAlways be concise."
3419
+ * ```
3420
+ */
3421
+ function appendToSystemMessage(systemMessage, text) {
3422
+ if (!systemMessage) return new SystemMessage$1({ content: text });
3423
+ const existingContent = systemMessage.content;
3424
+ if (typeof existingContent === "string") {
3425
+ const newContent = existingContent ? `${existingContent}\n\n${text}` : text;
3426
+ return new SystemMessage$1({ content: newContent });
3427
+ }
3428
+ if (Array.isArray(existingContent)) {
3429
+ const newContent = [...existingContent];
3430
+ const textToAdd = newContent.length > 0 ? `\n\n${text}` : text;
3431
+ newContent.push({
3432
+ type: "text",
3433
+ text: textToAdd
3434
+ });
3435
+ return new SystemMessage$1({ content: newContent });
3436
+ }
3437
+ return new SystemMessage$1({ content: text });
3438
+ }
3439
+ //#endregion
3361
3440
  //#region src/middleware/subagents.ts
3362
3441
  /**
3363
3442
  * Config key used by task-tool callers to request dynamic response format.
@@ -3371,6 +3450,8 @@ const SUBAGENT_RESPONSE_FORMAT_CONFIG_KEY = "__deepagents_subagent_response_form
3371
3450
  * Provides a minimal base prompt that can be extended by specific subagent configurations.
3372
3451
  */
3373
3452
  const DEFAULT_SUBAGENT_PROMPT = "In order to complete the objective that the user asks of you, you have access to a number of standard tools.";
3453
+ const FORKED_CONTEXT_KEY = "_deepagentsForkedContext";
3454
+ const FORK_RECURSION_REFUSAL = "You are a subagent and cannot delegate to another subagent. Complete this task yourself instead of calling this tool again.";
3374
3455
  /**
3375
3456
  * State keys excluded when passing state to subagents and when returning
3376
3457
  * updates from subagents. Summarization keys are excluded because their
@@ -3383,6 +3464,18 @@ const EXCLUDED_STATE_KEYS = [
3383
3464
  "skillsMetadata",
3384
3465
  "memoryContents",
3385
3466
  "_summarizationEvent",
3467
+ "_summarizationSessionId",
3468
+ FORKED_CONTEXT_KEY
3469
+ ];
3470
+ /**
3471
+ * State keys excluded when inheriting state into a declarative fork.
3472
+ * Narrower than `EXCLUDED_STATE_KEYS`: a fork's mirrored middleware needs
3473
+ * the parent's private channels (skills metadata, memory contents, etc.)
3474
+ * to rebuild an equivalent prompt.
3475
+ */
3476
+ const FORK_EXCLUDED_STATE_KEYS = [
3477
+ "structuredResponse",
3478
+ "_summarizationEvent",
3386
3479
  "_summarizationSessionId"
3387
3480
  ];
3388
3481
  /**
@@ -3392,25 +3485,37 @@ const EXCLUDED_STATE_KEYS = [
3392
3485
  const DEFAULT_GENERAL_PURPOSE_DESCRIPTION = "General-purpose agent for researching complex questions, searching for files and content, and executing multi-step tasks. When you are searching for a keyword or file and are not confident that you will find the right match in the first few tries use this agent to perform the search for you. This agent has access to all tools as the main agent.";
3393
3486
  function getTaskToolDescription(subagentDescriptions) {
3394
3487
  return context`
3395
- Launch an ephemeral subagent to handle a complex, multi-step task in an isolated context window.
3488
+ Launch an ephemeral subagent to handle a complex, multi-step task.
3396
3489
 
3397
3490
  Available agent types and the tools they have access to:
3398
3491
  ${subagentDescriptions.join("\n")}
3399
3492
 
3400
3493
  Specify subagent_type to select the agent. Usage notes:
3401
3494
  - Launch multiple agents concurrently when their tasks are independent, using a single message with multiple tool calls.
3402
- - Each invocation is stateless: the agent sees only the prompt you give it and returns a single final report. Put full detail in the prompt and state exactly what it should return.
3495
+ - Each invocation is stateless by default: the agent sees only the prompt you give it and returns a single final report. Put full detail in the prompt and state exactly what it should return — unless an agent type below says it inherits your conversation instead.
3403
3496
  - The agent's report is not shown to the user; relay a summary yourself.
3404
- - Tell the agent whether to create content, analyze, or only research, since it cannot see the user's intent.
3497
+ - Tell the agent whether to create content, analyze, or only research, since it can't necessarily see the user's intent unless it inherits your conversation, as noted per agent type below.
3405
3498
  - If an agent's description says to use it proactively, do so without waiting to be asked.
3406
3499
  - When only general-purpose is available, use it for any complex, context-heavy task; it has the same capabilities as the main agent.
3407
3500
  `;
3408
3501
  }
3502
+ const FORKED_SUBAGENT_TOOL_NOTE = " (inherits your full conversation and system prompt — no need to restate context here)";
3503
+ const COMPILED_FORKED_SUBAGENT_TOOL_NOTE = " (inherits your conversation history — its system prompt is fixed in its own runnable)";
3504
+ /** Render one subagent's listing line for the task tool description. */
3505
+ function describeSubagentForTool(name, description, forked, compiled = false) {
3506
+ return `- ${name}: ${description}${forked ? compiled ? COMPILED_FORKED_SUBAGENT_TOOL_NOTE : FORKED_SUBAGENT_TOOL_NOTE : ""}`;
3507
+ }
3508
+ const FORK_TASK_PREAMBLE = "[The messages above are a prior conversation you are continuing as the subagent that was just invoked. Any mention in them of delegating to a subagent already happened — you are that subagent, not the one being asked to delegate further. If you try to delegate to another subagent yourself, it will be refused — complete this task directly. Use the specific facts, figures, and identifiers already established in that conversation when completing the task below — do not answer generically when exact details are already available above. Your actual task is below.]\n\n";
3509
+ /**
3510
+ * Whether a declarative subagent spec has `mode: "fork"` set.
3511
+ *
3512
+ * A plain boolean, not a type predicate: `SubAgent` covers both `"fork"` and
3513
+ * `"isolated"`, so there's no distinct type left to narrow to.
3514
+ */
3409
3515
  function isForkedSubAgent(value) {
3410
3516
  if (typeof value !== "object" || value == null) return false;
3411
3517
  if (!("mode" in value)) return false;
3412
- if (value.mode !== "fork") return false;
3413
- return true;
3518
+ return value.mode === "fork";
3414
3519
  }
3415
3520
  /**
3416
3521
  * Base specification for the general-purpose subagent.
@@ -3453,15 +3558,26 @@ const GENERAL_PURPOSE_SUBAGENT = {
3453
3558
  name: "general-purpose",
3454
3559
  description: DEFAULT_GENERAL_PURPOSE_DESCRIPTION,
3455
3560
  systemPrompt: DEFAULT_SUBAGENT_PROMPT,
3456
- mode: "handoff"
3561
+ mode: "isolated"
3457
3562
  };
3563
+ function filterState(state, excludedKeys) {
3564
+ const filtered = {};
3565
+ for (const [key, value] of Object.entries(state)) if (!excludedKeys.includes(key)) filtered[key] = value;
3566
+ return filtered;
3567
+ }
3458
3568
  /**
3459
3569
  * Filter state to exclude certain keys when passing to subagents
3460
3570
  */
3461
3571
  function filterStateForSubagent(state) {
3462
- const filtered = {};
3463
- for (const [key, value] of Object.entries(state)) if (!EXCLUDED_STATE_KEYS.includes(key)) filtered[key] = value;
3464
- return filtered;
3572
+ return filterState(state, EXCLUDED_STATE_KEYS);
3573
+ }
3574
+ /**
3575
+ * Filter state to exclude only the keys a declarative fork must not resume
3576
+ * (structured response, summarization event/session) — see
3577
+ * `FORK_EXCLUDED_STATE_KEYS`.
3578
+ */
3579
+ function filterStateForFork(state) {
3580
+ return filterState(state, FORK_EXCLUDED_STATE_KEYS);
3465
3581
  }
3466
3582
  /**
3467
3583
  * Invalid tool message block types
@@ -3505,6 +3621,16 @@ function stripInFlightAIMessage(messages) {
3505
3621
  const last = messages.at(-1);
3506
3622
  return AIMessage$1.isInstance(last) && (last.tool_calls?.length ?? 0) > 0 ? messages.slice(0, -1) : messages;
3507
3623
  }
3624
+ const ForkedContextStateSchema = z.object({ [FORKED_CONTEXT_KEY]: z.boolean().optional() });
3625
+ function createForkTaskToolMiddleware(taskTool) {
3626
+ return createMiddleware({
3627
+ name: "forkTaskToolMiddleware",
3628
+ tracePolicy: { processInputs: omitPayload },
3629
+ stateSchema: ForkedContextStateSchema,
3630
+ tools: [taskTool],
3631
+ beforeAgent: () => ({ [FORKED_CONTEXT_KEY]: true })
3632
+ });
3633
+ }
3508
3634
  /**
3509
3635
  * Create a runnable agent from a declarative `SubAgent` spec.
3510
3636
  *
@@ -3534,6 +3660,17 @@ function createSubAgent(spec, options) {
3534
3660
  });
3535
3661
  }
3536
3662
  /**
3663
+ * Resolve a fork's system prompt: the parent's inherited prompt, with the
3664
+ * fork's own systemPrompt (if any) appended as an addendum rather than
3665
+ * replacing it.
3666
+ */
3667
+ function resolveForkSystemPrompt(parentSystemPrompt, forkAddendum) {
3668
+ if (!forkAddendum) return parentSystemPrompt ?? "";
3669
+ const addendumText = typeof forkAddendum === "string" ? forkAddendum : forkAddendum.text;
3670
+ if (SystemMessage.isInstance(parentSystemPrompt)) return appendToSystemMessage(parentSystemPrompt, addendumText);
3671
+ return parentSystemPrompt ? `${parentSystemPrompt}\n\n${addendumText}` : addendumText;
3672
+ }
3673
+ /**
3537
3674
  * Create subagent instances from specifications.
3538
3675
  *
3539
3676
  * Returns compiled agents, raw specs keyed by name (for on-demand
@@ -3541,13 +3678,18 @@ function createSubAgent(spec, options) {
3541
3678
  * of names that should fork the parent's conversation.
3542
3679
  */
3543
3680
  function getSubagents(options) {
3544
- const { defaultModel, defaultTools, defaultMiddleware, generalPurposeMiddleware: gpMiddleware, defaultInterruptOn, subagents, generalPurposeAgent, parentSystemPrompt = null } = options;
3681
+ const { defaultModel, defaultTools, defaultMiddleware, generalPurposeMiddleware: gpMiddleware, defaultInterruptOn, subagents, generalPurposeAgent, parentSystemPrompt = null, mirroredTaskTool } = options;
3545
3682
  const defaultSubagentMiddleware = defaultMiddleware || [];
3546
3683
  const generalPurposeMiddlewareBase = gpMiddleware || defaultSubagentMiddleware;
3547
3684
  const agents = {};
3548
3685
  const specsByName = {};
3549
3686
  const subagentDescriptions = [];
3550
3687
  const forkModeNames = /* @__PURE__ */ new Set();
3688
+ const seenNames = new Set(generalPurposeAgent ? ["general-purpose"] : []);
3689
+ for (const agentParams of subagents) {
3690
+ if (seenNames.has(agentParams.name)) throw new Error(`Duplicate subagent name '${agentParams.name}'; each subagent must have a unique name.`);
3691
+ seenNames.add(agentParams.name);
3692
+ }
3551
3693
  if (generalPurposeAgent) {
3552
3694
  const generalPurposeMiddleware = [...generalPurposeMiddlewareBase];
3553
3695
  if (defaultInterruptOn) generalPurposeMiddleware.push(humanInTheLoopMiddleware({ interruptOn: defaultInterruptOn }));
@@ -3561,24 +3703,34 @@ function getSubagents(options) {
3561
3703
  };
3562
3704
  agents["general-purpose"] = createSubAgent(gpSpec);
3563
3705
  specsByName["general-purpose"] = gpSpec;
3564
- subagentDescriptions.push(`- general-purpose: ${DEFAULT_GENERAL_PURPOSE_DESCRIPTION}`);
3706
+ subagentDescriptions.push(describeSubagentForTool("general-purpose", DEFAULT_GENERAL_PURPOSE_DESCRIPTION, false));
3565
3707
  }
3566
3708
  for (const agentParams of subagents) {
3567
3709
  const rawMode = agentParams.mode;
3568
- if (rawMode != null && rawMode !== "handoff" && rawMode !== "fork") throw new Error(`SubAgent '${agentParams.name}' has invalid mode '${rawMode}' — must be "handoff" or "fork".`);
3569
- subagentDescriptions.push(`- ${agentParams.name}: ${agentParams.description}`);
3710
+ if (rawMode != null && rawMode !== "isolated" && rawMode !== "fork" && rawMode !== "handoff") throw new Error(`SubAgent '${agentParams.name}' has invalid mode '${rawMode}' — must be "isolated" or "fork".`);
3711
+ const forked = isForkedSubAgent(agentParams);
3712
+ const compiled = "runnable" in agentParams;
3713
+ subagentDescriptions.push(describeSubagentForTool(agentParams.name, agentParams.description, forked, compiled));
3570
3714
  if ("runnable" in agentParams) {
3571
3715
  agents[agentParams.name] = agentParams.runnable;
3572
3716
  specsByName[agentParams.name] = agentParams;
3573
- if (isForkedSubAgent(agentParams)) forkModeNames.add(agentParams.name);
3574
- } else if (isForkedSubAgent(agentParams)) {
3717
+ if (forked) forkModeNames.add(agentParams.name);
3718
+ continue;
3719
+ }
3720
+ const subagentMiddleware = [...defaultSubagentMiddleware, ...agentParams.middleware ?? []];
3721
+ if (forked) {
3722
+ const rawSkills = agentParams.skills;
3723
+ if (Array.isArray(rawSkills) && rawSkills.length > 0) throw new Error(`SubAgent '${agentParams.name}' cannot set skills under mode: "fork"; the parent's skills are inherited instead.`);
3724
+ const resolvedSystemPrompt = resolveForkSystemPrompt(parentSystemPrompt, agentParams.systemPrompt);
3725
+ const fsIndex = subagentMiddleware.findIndex((m) => m.name === "FilesystemMiddleware");
3726
+ subagentMiddleware.splice(fsIndex + 1, 0, createForkTaskToolMiddleware(mirroredTaskTool));
3575
3727
  const resolvedSpec = {
3576
3728
  ...agentParams,
3577
- systemPrompt: parentSystemPrompt ?? "",
3729
+ systemPrompt: resolvedSystemPrompt,
3578
3730
  mode: void 0,
3579
3731
  model: agentParams.model ?? defaultModel,
3580
3732
  tools: agentParams.tools ?? defaultTools,
3581
- middleware: [...defaultSubagentMiddleware, ...agentParams.middleware ?? []],
3733
+ middleware: subagentMiddleware,
3582
3734
  interruptOn: agentParams.interruptOn ?? defaultInterruptOn ?? void 0
3583
3735
  };
3584
3736
  agents[agentParams.name] = createSubAgent(resolvedSpec);
@@ -3587,10 +3739,10 @@ function getSubagents(options) {
3587
3739
  } else {
3588
3740
  const resolvedSpec = {
3589
3741
  ...agentParams,
3590
- mode: "handoff",
3742
+ mode: "isolated",
3591
3743
  model: agentParams.model ?? defaultModel,
3592
3744
  tools: agentParams.tools ?? defaultTools,
3593
- middleware: [...defaultSubagentMiddleware, ...agentParams.middleware ?? []],
3745
+ middleware: subagentMiddleware,
3594
3746
  interruptOn: agentParams.interruptOn ?? defaultInterruptOn ?? void 0
3595
3747
  };
3596
3748
  agents[agentParams.name] = createSubAgent(resolvedSpec);
@@ -3609,16 +3761,12 @@ function getSubagents(options) {
3609
3761
  */
3610
3762
  function createTaskTool(options) {
3611
3763
  const { defaultModel, defaultTools, defaultMiddleware, generalPurposeMiddleware, defaultInterruptOn, subagents, generalPurposeAgent, taskDescription, parentSystemPrompt = null } = options;
3612
- const { agents: subagentGraphs, specsByName, descriptions: subagentDescriptions, forkModeNames } = getSubagents({
3613
- defaultModel,
3614
- defaultTools,
3615
- defaultMiddleware,
3616
- generalPurposeMiddleware,
3617
- defaultInterruptOn,
3618
- subagents,
3619
- generalPurposeAgent,
3620
- parentSystemPrompt
3621
- });
3764
+ const subagentNames = [...generalPurposeAgent ? ["general-purpose"] : [], ...subagents.map((spec) => spec.name)];
3765
+ const subagentDescriptions = [...generalPurposeAgent ? [describeSubagentForTool("general-purpose", DEFAULT_GENERAL_PURPOSE_DESCRIPTION, false)] : [], ...subagents.map((spec) => describeSubagentForTool(spec.name, spec.description, isForkedSubAgent(spec), "runnable" in spec))];
3766
+ const finalTaskDescription = taskDescription ? taskDescription : getTaskToolDescription(subagentDescriptions);
3767
+ let subagentGraphs = {};
3768
+ let specsByName = {};
3769
+ let forkModeNames = /* @__PURE__ */ new Set();
3622
3770
  function selectSubagent(subagentType, config) {
3623
3771
  const spec = specsByName[subagentType];
3624
3772
  const responseFormat = config.configurable?.[SUBAGENT_RESPONSE_FORMAT_CONFIG_KEY];
@@ -3626,18 +3774,19 @@ function createTaskTool(options) {
3626
3774
  if ("runnable" in spec || responseFormat == null) return subagentGraphs[subagentType];
3627
3775
  return createSubAgent(spec, { responseFormat });
3628
3776
  }
3629
- const finalTaskDescription = taskDescription ? taskDescription : getTaskToolDescription(subagentDescriptions);
3630
- return tool(async (input, config) => {
3777
+ async function runTask(input, config) {
3631
3778
  const { description, subagent_type } = input;
3779
+ const currentState = getCurrentTaskInput();
3780
+ if (currentState[FORKED_CONTEXT_KEY]) return FORK_RECURSION_REFUSAL;
3632
3781
  if (!(subagent_type in subagentGraphs)) {
3633
3782
  const allowedTypes = Object.keys(subagentGraphs).map((k) => `\`${k}\``).join(", ");
3634
3783
  throw new Error(`Error: invoked agent of type ${subagent_type}, the only allowed types are ${allowedTypes}`);
3635
3784
  }
3636
3785
  const shouldFork = forkModeNames.has(subagent_type);
3637
3786
  const subagent = selectSubagent(subagent_type, config);
3638
- const currentState = getCurrentTaskInput();
3639
- const subagentState = filterStateForSubagent(currentState);
3640
- if (shouldFork) subagentState.messages = [...getEffectiveMessages(stripInFlightAIMessage(currentState.messages ?? []), currentState), new HumanMessage$1({ content: description })];
3787
+ const spec = specsByName[subagent_type];
3788
+ const subagentState = shouldFork && !("runnable" in spec) ? filterStateForFork(currentState) : filterStateForSubagent(currentState);
3789
+ if (shouldFork) subagentState.messages = [...getEffectiveMessages(stripInFlightAIMessage(currentState.messages ?? []), currentState), new HumanMessage$1({ content: FORK_TASK_PREAMBLE + description })];
3641
3790
  else subagentState.messages = [new HumanMessage$1({ content: description })];
3642
3791
  subagentState._summarizationSessionId = `session_${crypto.randomUUID().substring(0, 8)}`;
3643
3792
  const subagentConfig = {
@@ -3664,14 +3813,35 @@ function createTaskTool(options) {
3664
3813
  return content;
3665
3814
  }
3666
3815
  return returnCommandWithStateUpdate(result, config.toolCall.id);
3667
- }, {
3816
+ }
3817
+ const taskToolSchema = z.object({
3818
+ description: z.string().describe("The task to execute with the selected agent"),
3819
+ subagent_type: z.string().describe(`Name of the agent to use. Available: ${subagentNames.join(", ")}`)
3820
+ });
3821
+ const taskTool = tool(runTask, {
3668
3822
  name: "task",
3669
3823
  description: finalTaskDescription,
3670
- schema: z.object({
3671
- description: z.string().describe("The task to execute with the selected agent"),
3672
- subagent_type: z.string().describe(`Name of the agent to use. Available: ${Object.keys(subagentGraphs).join(", ")}`)
3824
+ schema: taskToolSchema
3825
+ });
3826
+ const { agents, specsByName: resolvedSpecsByName, forkModeNames: resolvedForkModeNames } = getSubagents({
3827
+ defaultModel,
3828
+ defaultTools,
3829
+ defaultMiddleware,
3830
+ generalPurposeMiddleware,
3831
+ defaultInterruptOn,
3832
+ subagents,
3833
+ generalPurposeAgent,
3834
+ parentSystemPrompt,
3835
+ mirroredTaskTool: tool(runTask, {
3836
+ name: "task",
3837
+ description: finalTaskDescription,
3838
+ schema: taskToolSchema
3673
3839
  })
3674
3840
  });
3841
+ subagentGraphs = agents;
3842
+ specsByName = resolvedSpecsByName;
3843
+ forkModeNames = resolvedForkModeNames;
3844
+ return taskTool;
3675
3845
  }
3676
3846
  /**
3677
3847
  * Create subagent middleware with task tool
@@ -3691,6 +3861,7 @@ function createSubAgentMiddleware(options) {
3691
3861
  });
3692
3862
  return createMiddleware({
3693
3863
  name: "subAgentMiddleware",
3864
+ tracePolicy: { processInputs: omitPayload },
3694
3865
  tools: [taskTool],
3695
3866
  wrapModelCall: async (request, handler) => {
3696
3867
  if (systemPrompt !== null) return handler({
@@ -3795,6 +3966,7 @@ function patchDanglingToolCalls(messages) {
3795
3966
  function createPatchToolCallsMiddleware() {
3796
3967
  return createMiddleware({
3797
3968
  name: "patchToolCallsMiddleware",
3969
+ tracePolicy: { processInputs: omitPayload },
3798
3970
  beforeAgent: async (state) => {
3799
3971
  const messages = state.messages;
3800
3972
  if (!messages || messages.length === 0) return;
@@ -4156,6 +4328,7 @@ function createMemoryMiddleware(options) {
4156
4328
  const { backend, sources, addCacheControl = false } = options;
4157
4329
  return createMiddleware({
4158
4330
  name: "MemoryMiddleware",
4331
+ tracePolicy: { processInputs: omitPayload },
4159
4332
  stateSchema: MemoryStateSchema,
4160
4333
  async beforeAgent(state) {
4161
4334
  if ("memoryContents" in state && state.memoryContents != null) return;
@@ -4640,6 +4813,7 @@ function createSkillsMiddleware(options) {
4640
4813
  let loadedSkills = [];
4641
4814
  return createMiddleware({
4642
4815
  name: "SkillsMiddleware",
4816
+ tracePolicy: { processInputs: omitPayload },
4643
4817
  stateSchema: SkillsStateSchema,
4644
4818
  async beforeAgent(state) {
4645
4819
  const stateHasSkills = "skillsMetadata" in state && Array.isArray(state.skillsMetadata) && state.skillsMetadata.length > 0;
@@ -4673,43 +4847,6 @@ function createSkillsMiddleware(options) {
4673
4847
  });
4674
4848
  }
4675
4849
  //#endregion
4676
- //#region src/middleware/utils.ts
4677
- /**
4678
- * Merge custom middleware into an assembled stack by `.name`.
4679
- *
4680
- * Matching custom middleware replaces the existing entry in place. New
4681
- * middleware is appended after the base stack in caller-provided order.
4682
- */
4683
- function mergeMiddleware$1(base, custom) {
4684
- const merged = new Map(base.map((middleware) => [middleware.name, middleware]));
4685
- for (const middleware of custom) merged.set(middleware.name, middleware);
4686
- return [...merged.values()];
4687
- }
4688
- function middlewareNames(middleware) {
4689
- return new Set(middleware.map((entry) => entry.name));
4690
- }
4691
- function matchingMiddleware(middleware, names) {
4692
- return middleware.filter((entry) => names.has(entry.name));
4693
- }
4694
- /**
4695
- * Merge custom middleware into default and tail middleware segments.
4696
- *
4697
- * Same-name custom entries replace matching defaults in either segment. Novel
4698
- * custom entries are inserted between the default and tail segments unless
4699
- * `appendNew` is false.
4700
- */
4701
- function mergeMiddlewareStack(defaultMiddleware, customMiddleware, tailMiddleware = [], options = {}) {
4702
- const defaultMiddlewareNames = middlewareNames(defaultMiddleware);
4703
- const tailMiddlewareNames = middlewareNames(tailMiddleware);
4704
- const knownMiddlewareNames = /* @__PURE__ */ new Set([...defaultMiddlewareNames, ...tailMiddlewareNames]);
4705
- const novelMiddleware = options.appendNew === false ? [] : customMiddleware.filter((entry) => !knownMiddlewareNames.has(entry.name));
4706
- return [
4707
- ...mergeMiddleware$1(defaultMiddleware, matchingMiddleware(customMiddleware, defaultMiddlewareNames)),
4708
- ...novelMiddleware,
4709
- ...mergeMiddleware$1(tailMiddleware, matchingMiddleware(customMiddleware, tailMiddlewareNames))
4710
- ];
4711
- }
4712
- //#endregion
4713
4850
  //#region src/middleware/completion_callback.ts
4714
4851
  /**
4715
4852
  * Callback middleware for async subagents.
@@ -4921,6 +5058,7 @@ function createCompletionCallbackMiddleware(options) {
4921
5058
  }
4922
5059
  return createMiddleware({
4923
5060
  name: "CompletionCallbackMiddleware",
5061
+ tracePolicy: { processInputs: omitPayload },
4924
5062
  stateSchema: CompletionCallbackStateSchema,
4925
5063
  /**
4926
5064
  * After-agent hook: fires when the subagent completes successfully.
@@ -5462,6 +5600,7 @@ function createAsyncSubAgentMiddleware(options) {
5462
5600
  const fullSystemPrompt = systemPrompt ? `${systemPrompt}\n\nAvailable async subagent types:\n${agentsDescription}` : null;
5463
5601
  return createMiddleware({
5464
5602
  name: "asyncSubAgentMiddleware",
5603
+ tracePolicy: { processInputs: omitPayload },
5465
5604
  stateSchema: AsyncTaskStateSchema,
5466
5605
  tools,
5467
5606
  wrapModelCall: async (request, handler) => {
@@ -5544,6 +5683,7 @@ var ConfigurationError = class ConfigurationError extends Error {
5544
5683
  function createCacheBreakpointMiddleware() {
5545
5684
  return createMiddleware({
5546
5685
  name: "CacheBreakpointMiddleware",
5686
+ tracePolicy: { processInputs: omitPayload },
5547
5687
  wrapModelCall(request, handler) {
5548
5688
  if (!isAnthropicModel(request.model)) return handler(request);
5549
5689
  const existingContent = request.systemMessage.content;
@@ -5578,6 +5718,7 @@ function hasToolName(tool) {
5578
5718
  function createToolExclusionMiddleware(excludedTools) {
5579
5719
  return createMiddleware({
5580
5720
  name: "_ToolExclusionMiddleware",
5721
+ tracePolicy: { processInputs: omitPayload },
5581
5722
  wrapModelCall(request, handler) {
5582
5723
  return handler({
5583
5724
  ...request,
@@ -6338,8 +6479,18 @@ function createDeepAgent(params = {}) {
6338
6479
  providerHint: getModelProvider(model),
6339
6480
  identifierHint: getModelIdentifier(model)
6340
6481
  });
6341
- const filesystemTools = FILESYSTEM_TOOL_NAMES.filter((toolName) => !harnessProfile.excludedTools.has(toolName));
6342
- const profileFilesystemTools = filesystemTools.length === FILESYSTEM_TOOL_NAMES.length ? void 0 : filesystemTools.includes("read_file") ? filesystemTools : ["read_file", ...filesystemTools];
6482
+ const computeProfileFilesystemTools = (profile) => {
6483
+ const filesystemTools = FILESYSTEM_TOOL_NAMES.filter((toolName) => !profile.excludedTools.has(toolName));
6484
+ return filesystemTools.length === FILESYSTEM_TOOL_NAMES.length ? void 0 : filesystemTools.includes("read_file") ? filesystemTools : ["read_file", ...filesystemTools];
6485
+ };
6486
+ const profileFilesystemTools = computeProfileFilesystemTools(harnessProfile);
6487
+ const resolveSubagentProfile = (subagentModel) => {
6488
+ if (subagentModel == null || subagentModel === model) return harnessProfile;
6489
+ return typeof subagentModel === "string" ? resolveHarnessProfile({ spec: subagentModel }) : resolveHarnessProfile({
6490
+ providerHint: getModelProvider(subagentModel),
6491
+ identifierHint: getModelIdentifier(subagentModel)
6492
+ });
6493
+ };
6343
6494
  const toolOverrides = harnessProfile.toolDescriptionOverrides;
6344
6495
  const effectiveTools = Object.keys(toolOverrides).length > 0 ? tools.map((t) => t.name in toolOverrides ? Object.assign(Object.create(Object.getPrototypeOf(t)), t, { description: toolOverrides[t.name] }) : t) : tools;
6345
6496
  const anthropicModel = isAnthropicModel(model);
@@ -6375,44 +6526,50 @@ function createDeepAgent(params = {}) {
6375
6526
  * Only the general-purpose subagent inherits the main agent's skills.
6376
6527
  * If a custom subagent needs skills, it must specify its own `skills` array.
6377
6528
  */
6378
- const createSubagentDefaultMiddleware = (input) => {
6529
+ const createSubagentDefaultMiddleware = (input, subagentProfile, forked) => {
6379
6530
  const effectivePermissions = input.permissions ?? permissions;
6380
6531
  return [
6381
6532
  createFilesystemMiddleware({
6382
6533
  backend,
6383
6534
  permissions: effectivePermissions,
6384
- tools: profileFilesystemTools
6535
+ tools: computeProfileFilesystemTools(subagentProfile)
6385
6536
  }),
6386
6537
  createSummarizationMiddleware({ backend }),
6387
6538
  createPatchToolCallsMiddleware(),
6388
- ...input.skills != null && input.skills.length > 0 ? [createSkillsMiddleware({
6539
+ ...!forked && input.skills != null && input.skills.length > 0 ? [createSkillsMiddleware({
6389
6540
  backend,
6390
6541
  sources: input.skills
6391
6542
  })] : []
6392
6543
  ];
6393
6544
  };
6394
- const buildSubagentMiddleware = (input, isForkable) => {
6395
- let subagentMiddleware = mergeMiddlewareStack(createSubagentDefaultMiddleware(input), input.middleware ?? [], [
6396
- ...resolveMiddleware(harnessProfile.extraMiddleware),
6545
+ const buildSubagentMiddleware = (input) => {
6546
+ const subagentProfile = resolveSubagentProfile(input.model);
6547
+ const forked = isForkedSubAgent(input);
6548
+ const subagentDefaultMiddleware = createSubagentDefaultMiddleware(input, subagentProfile, forked);
6549
+ if (forked && skills != null && skills.length > 0) subagentDefaultMiddleware.unshift(createSkillsMiddleware({
6550
+ backend,
6551
+ sources: skills
6552
+ }));
6553
+ let subagentMiddleware = mergeMiddlewareStack(subagentDefaultMiddleware, forked && customMiddleware.length > 0 ? mergeMiddleware$1(customMiddleware, input.middleware ?? []) : input.middleware ?? [], [
6554
+ ...resolveMiddleware(subagentProfile.extraMiddleware),
6397
6555
  ...cacheMiddleware,
6398
- ...isForkable ? memoryMiddleware : []
6556
+ ...forked && memory != null && memory.length > 0 ? [createMemoryMiddleware({
6557
+ backend,
6558
+ sources: memory,
6559
+ addCacheControl: anthropicModel
6560
+ })] : []
6399
6561
  ]);
6400
- if (harnessProfile.excludedMiddleware.size > 0) subagentMiddleware = subagentMiddleware.filter((middleware) => !harnessProfile.excludedMiddleware.has(middleware.name));
6562
+ if (subagentProfile.excludedMiddleware.size > 0) subagentMiddleware = subagentMiddleware.filter((middleware) => !subagentProfile.excludedMiddleware.has(middleware.name));
6563
+ if (subagentProfile.excludedTools.size > 0) subagentMiddleware.push(createToolExclusionMiddleware(subagentProfile.excludedTools));
6401
6564
  return subagentMiddleware;
6402
6565
  };
6403
6566
  const normalizeSubagentSpec = (input) => ({
6404
6567
  ...input,
6405
- tools: input.tools ?? [],
6406
- middleware: buildSubagentMiddleware(input, false)
6407
- });
6408
- const normalizeForkedSubagentSpec = (input) => ({
6409
- ...input,
6410
- tools: input.tools ?? [],
6411
- middleware: buildSubagentMiddleware(input, true)
6568
+ middleware: buildSubagentMiddleware(input)
6412
6569
  });
6413
6570
  const allSubagents = subagents;
6414
6571
  const asyncSubAgents = allSubagents.filter((item) => isAsyncSubAgent(item));
6415
- const inlineSubagents = allSubagents.filter((item) => !isAsyncSubAgent(item)).map((item) => "runnable" in item ? item : isForkedSubAgent(item) ? normalizeForkedSubagentSpec(item) : normalizeSubagentSpec(item));
6572
+ const inlineSubagents = allSubagents.filter((item) => !isAsyncSubAgent(item)).map((item) => "runnable" in item ? item : normalizeSubagentSpec(item));
6416
6573
  const gpConfig = harnessProfile.generalPurposeSubagent;
6417
6574
  if (!(gpConfig?.enabled === false) && !inlineSubagents.some((item) => item.name === GENERAL_PURPOSE_SUBAGENT["name"])) {
6418
6575
  const gpSystemPrompt = gpConfig?.systemPrompt ?? applyProfilePrompt(harnessProfile, GENERAL_PURPOSE_SUBAGENT.systemPrompt);
@@ -8585,4 +8742,4 @@ var LangSmithSandbox = class LangSmithSandbox extends BaseSandbox {
8585
8742
  //#endregion
8586
8743
  export { DEFAULT_GENERAL_PURPOSE_DESCRIPTION as A, StateBackend as B, MAX_SKILL_DESCRIPTION_LENGTH as C, createMemoryMiddleware as D, createSkillsMiddleware as E, createSubAgentMiddleware as F, resolveBackend as G, applyGrepMaxCount as H, computeSummarizationDefaults as I, checkEmptyContent as J, adaptBackendProtocol as K, createSummarizationMiddleware as L, GENERAL_PURPOSE_SUBAGENT as M, SUBAGENT_RESPONSE_FORMAT_CONFIG_KEY as N, filesValue as O, createSubAgent as P, performStringReplacement as Q, createFilesystemMiddleware as R, createCompletionCallbackMiddleware as S, MAX_SKILL_NAME_LENGTH as T, isSandboxBackend as U, SandboxError as V, isSandboxProtocol as W, isTextMimeType as X, getMimeType as Y, normalizeReadPagination as Z, createHarnessProfile as _, ASYNC_TASK_SYSTEM_PROMPT as a, createAsyncSubAgentMiddleware as b, TASK_SYSTEM_PROMPT as c, registerHarnessProfile as d, generalPurposeSubagentConfigSchema as f, EMPTY_HARNESS_PROFILE as g, serializeProfile as h, StoreBackend as i, DEFAULT_SUBAGENT_PROMPT as j, createPatchToolCallsMiddleware as k, createDeepAgent as l, parseHarnessProfileConfig as m, BaseSandbox as n, BASE_AGENT_PROMPT as o, harnessProfileConfigSchema as p, adaptSandboxProtocol as q, ContextHubBackend as r, EXECUTION_SYSTEM_PROMPT as s, LangSmithSandbox as t, getHarnessProfile as u, REQUIRED_MIDDLEWARE_NAMES as v, MAX_SKILL_FILE_SIZE as w, isAsyncSubAgent as x, ConfigurationError as y, CompositeBackend as z };
8587
8744
 
8588
- //# sourceMappingURL=langsmith-BBV5JlNW.js.map
8745
+ //# sourceMappingURL=langsmith-CkXiO0e9.js.map