deepagents 1.13.2 → 1.13.3

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.
@@ -3382,6 +3382,83 @@ function createSummarizationMiddleware(options) {
3382
3382
  });
3383
3383
  }
3384
3384
  //#endregion
3385
+ //#region src/middleware/utils.ts
3386
+ /**
3387
+ * Utility functions for middleware.
3388
+ *
3389
+ * This module provides shared helpers used across middleware implementations.
3390
+ */
3391
+ /**
3392
+ * Merge custom middleware into an assembled stack by `.name`.
3393
+ *
3394
+ * Matching custom middleware replaces the existing entry in place. New
3395
+ * middleware is appended after the base stack in caller-provided order.
3396
+ */
3397
+ function mergeMiddleware$1(base, custom) {
3398
+ const merged = new Map(base.map((middleware) => [middleware.name, middleware]));
3399
+ for (const middleware of custom) merged.set(middleware.name, middleware);
3400
+ return [...merged.values()];
3401
+ }
3402
+ function middlewareNames(middleware) {
3403
+ return new Set(middleware.map((entry) => entry.name));
3404
+ }
3405
+ function matchingMiddleware(middleware, names) {
3406
+ return middleware.filter((entry) => names.has(entry.name));
3407
+ }
3408
+ /**
3409
+ * Merge custom middleware into default and tail middleware segments.
3410
+ *
3411
+ * Same-name custom entries replace matching defaults in either segment. Novel
3412
+ * custom entries are inserted between the default and tail segments unless
3413
+ * `appendNew` is false.
3414
+ */
3415
+ function mergeMiddlewareStack(defaultMiddleware, customMiddleware, tailMiddleware = [], options = {}) {
3416
+ const defaultMiddlewareNames = middlewareNames(defaultMiddleware);
3417
+ const tailMiddlewareNames = middlewareNames(tailMiddleware);
3418
+ const knownMiddlewareNames = /* @__PURE__ */ new Set([...defaultMiddlewareNames, ...tailMiddlewareNames]);
3419
+ const novelMiddleware = options.appendNew === false ? [] : customMiddleware.filter((entry) => !knownMiddlewareNames.has(entry.name));
3420
+ return [
3421
+ ...mergeMiddleware$1(defaultMiddleware, matchingMiddleware(customMiddleware, defaultMiddlewareNames)),
3422
+ ...novelMiddleware,
3423
+ ...mergeMiddleware$1(tailMiddleware, matchingMiddleware(customMiddleware, tailMiddlewareNames))
3424
+ ];
3425
+ }
3426
+ /**
3427
+ * Append text to a system message.
3428
+ *
3429
+ * Creates a new SystemMessage with the text appended to the existing content.
3430
+ * If the original message has content, the new text is separated by two newlines.
3431
+ *
3432
+ * @param systemMessage - Existing system message or null/undefined.
3433
+ * @param text - Text to add to the system message.
3434
+ * @returns New SystemMessage with the text appended.
3435
+ *
3436
+ * @example
3437
+ * ```typescript
3438
+ * const original = new SystemMessage({ content: "You are a helpful assistant." });
3439
+ * const updated = appendToSystemMessage(original, "Always be concise.");
3440
+ * // Result: SystemMessage with content "You are a helpful assistant.\n\nAlways be concise."
3441
+ * ```
3442
+ */
3443
+ function appendToSystemMessage(systemMessage, text) {
3444
+ if (!systemMessage) return new _langchain_core_messages.SystemMessage({ content: text });
3445
+ const existingContent = systemMessage.content;
3446
+ if (typeof existingContent === "string") {
3447
+ const newContent = existingContent ? `${existingContent}\n\n${text}` : text;
3448
+ return new _langchain_core_messages.SystemMessage({ content: newContent });
3449
+ }
3450
+ if (Array.isArray(existingContent)) {
3451
+ const newContent = [...existingContent];
3452
+ const textToAdd = newContent.length > 0 ? `\n\n${text}` : text;
3453
+ newContent.push({
3454
+ type: "text",
3455
+ text: textToAdd
3456
+ });
3457
+ return new _langchain_core_messages.SystemMessage({ content: newContent });
3458
+ }
3459
+ return new _langchain_core_messages.SystemMessage({ content: text });
3460
+ }
3461
+ //#endregion
3385
3462
  //#region src/middleware/subagents.ts
3386
3463
  /**
3387
3464
  * Config key used by task-tool callers to request dynamic response format.
@@ -3395,6 +3472,8 @@ const SUBAGENT_RESPONSE_FORMAT_CONFIG_KEY = "__deepagents_subagent_response_form
3395
3472
  * Provides a minimal base prompt that can be extended by specific subagent configurations.
3396
3473
  */
3397
3474
  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.";
3475
+ const FORKED_CONTEXT_KEY = "_deepagentsForkedContext";
3476
+ const FORK_RECURSION_REFUSAL = "You are a subagent and cannot delegate to another subagent. Complete this task yourself instead of calling this tool again.";
3398
3477
  /**
3399
3478
  * State keys excluded when passing state to subagents and when returning
3400
3479
  * updates from subagents. Summarization keys are excluded because their
@@ -3407,6 +3486,18 @@ const EXCLUDED_STATE_KEYS = [
3407
3486
  "skillsMetadata",
3408
3487
  "memoryContents",
3409
3488
  "_summarizationEvent",
3489
+ "_summarizationSessionId",
3490
+ FORKED_CONTEXT_KEY
3491
+ ];
3492
+ /**
3493
+ * State keys excluded when inheriting state into a declarative fork.
3494
+ * Narrower than `EXCLUDED_STATE_KEYS`: a fork's mirrored middleware needs
3495
+ * the parent's private channels (skills metadata, memory contents, etc.)
3496
+ * to rebuild an equivalent prompt.
3497
+ */
3498
+ const FORK_EXCLUDED_STATE_KEYS = [
3499
+ "structuredResponse",
3500
+ "_summarizationEvent",
3410
3501
  "_summarizationSessionId"
3411
3502
  ];
3412
3503
  /**
@@ -3416,25 +3507,37 @@ const EXCLUDED_STATE_KEYS = [
3416
3507
  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.";
3417
3508
  function getTaskToolDescription(subagentDescriptions) {
3418
3509
  return langchain.context`
3419
- Launch an ephemeral subagent to handle a complex, multi-step task in an isolated context window.
3510
+ Launch an ephemeral subagent to handle a complex, multi-step task.
3420
3511
 
3421
3512
  Available agent types and the tools they have access to:
3422
3513
  ${subagentDescriptions.join("\n")}
3423
3514
 
3424
3515
  Specify subagent_type to select the agent. Usage notes:
3425
3516
  - Launch multiple agents concurrently when their tasks are independent, using a single message with multiple tool calls.
3426
- - 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.
3517
+ - 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.
3427
3518
  - The agent's report is not shown to the user; relay a summary yourself.
3428
- - Tell the agent whether to create content, analyze, or only research, since it cannot see the user's intent.
3519
+ - 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.
3429
3520
  - If an agent's description says to use it proactively, do so without waiting to be asked.
3430
3521
  - When only general-purpose is available, use it for any complex, context-heavy task; it has the same capabilities as the main agent.
3431
3522
  `;
3432
3523
  }
3524
+ const FORKED_SUBAGENT_TOOL_NOTE = " (inherits your full conversation and system prompt — no need to restate context here)";
3525
+ const COMPILED_FORKED_SUBAGENT_TOOL_NOTE = " (inherits your conversation history — its system prompt is fixed in its own runnable)";
3526
+ /** Render one subagent's listing line for the task tool description. */
3527
+ function describeSubagentForTool(name, description, forked, compiled = false) {
3528
+ return `- ${name}: ${description}${forked ? compiled ? COMPILED_FORKED_SUBAGENT_TOOL_NOTE : FORKED_SUBAGENT_TOOL_NOTE : ""}`;
3529
+ }
3530
+ 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";
3531
+ /**
3532
+ * Whether a declarative subagent spec has `mode: "fork"` set.
3533
+ *
3534
+ * A plain boolean, not a type predicate: `SubAgent` covers both `"fork"` and
3535
+ * `"isolated"`, so there's no distinct type left to narrow to.
3536
+ */
3433
3537
  function isForkedSubAgent(value) {
3434
3538
  if (typeof value !== "object" || value == null) return false;
3435
3539
  if (!("mode" in value)) return false;
3436
- if (value.mode !== "fork") return false;
3437
- return true;
3540
+ return value.mode === "fork";
3438
3541
  }
3439
3542
  /**
3440
3543
  * Base specification for the general-purpose subagent.
@@ -3477,15 +3580,26 @@ const GENERAL_PURPOSE_SUBAGENT = {
3477
3580
  name: "general-purpose",
3478
3581
  description: DEFAULT_GENERAL_PURPOSE_DESCRIPTION,
3479
3582
  systemPrompt: DEFAULT_SUBAGENT_PROMPT,
3480
- mode: "handoff"
3583
+ mode: "isolated"
3481
3584
  };
3585
+ function filterState(state, excludedKeys) {
3586
+ const filtered = {};
3587
+ for (const [key, value] of Object.entries(state)) if (!excludedKeys.includes(key)) filtered[key] = value;
3588
+ return filtered;
3589
+ }
3482
3590
  /**
3483
3591
  * Filter state to exclude certain keys when passing to subagents
3484
3592
  */
3485
3593
  function filterStateForSubagent(state) {
3486
- const filtered = {};
3487
- for (const [key, value] of Object.entries(state)) if (!EXCLUDED_STATE_KEYS.includes(key)) filtered[key] = value;
3488
- return filtered;
3594
+ return filterState(state, EXCLUDED_STATE_KEYS);
3595
+ }
3596
+ /**
3597
+ * Filter state to exclude only the keys a declarative fork must not resume
3598
+ * (structured response, summarization event/session) — see
3599
+ * `FORK_EXCLUDED_STATE_KEYS`.
3600
+ */
3601
+ function filterStateForFork(state) {
3602
+ return filterState(state, FORK_EXCLUDED_STATE_KEYS);
3489
3603
  }
3490
3604
  /**
3491
3605
  * Invalid tool message block types
@@ -3529,6 +3643,15 @@ function stripInFlightAIMessage(messages) {
3529
3643
  const last = messages.at(-1);
3530
3644
  return _langchain_core_messages.AIMessage.isInstance(last) && (last.tool_calls?.length ?? 0) > 0 ? messages.slice(0, -1) : messages;
3531
3645
  }
3646
+ const ForkedContextStateSchema = zod_v4.z.object({ [FORKED_CONTEXT_KEY]: zod_v4.z.boolean().optional() });
3647
+ function createForkTaskToolMiddleware(taskTool) {
3648
+ return (0, langchain.createMiddleware)({
3649
+ name: "forkTaskToolMiddleware",
3650
+ stateSchema: ForkedContextStateSchema,
3651
+ tools: [taskTool],
3652
+ beforeAgent: () => ({ [FORKED_CONTEXT_KEY]: true })
3653
+ });
3654
+ }
3532
3655
  /**
3533
3656
  * Create a runnable agent from a declarative `SubAgent` spec.
3534
3657
  *
@@ -3558,6 +3681,17 @@ function createSubAgent(spec, options) {
3558
3681
  });
3559
3682
  }
3560
3683
  /**
3684
+ * Resolve a fork's system prompt: the parent's inherited prompt, with the
3685
+ * fork's own systemPrompt (if any) appended as an addendum rather than
3686
+ * replacing it.
3687
+ */
3688
+ function resolveForkSystemPrompt(parentSystemPrompt, forkAddendum) {
3689
+ if (!forkAddendum) return parentSystemPrompt ?? "";
3690
+ const addendumText = typeof forkAddendum === "string" ? forkAddendum : forkAddendum.text;
3691
+ if (langchain.SystemMessage.isInstance(parentSystemPrompt)) return appendToSystemMessage(parentSystemPrompt, addendumText);
3692
+ return parentSystemPrompt ? `${parentSystemPrompt}\n\n${addendumText}` : addendumText;
3693
+ }
3694
+ /**
3561
3695
  * Create subagent instances from specifications.
3562
3696
  *
3563
3697
  * Returns compiled agents, raw specs keyed by name (for on-demand
@@ -3565,13 +3699,18 @@ function createSubAgent(spec, options) {
3565
3699
  * of names that should fork the parent's conversation.
3566
3700
  */
3567
3701
  function getSubagents(options) {
3568
- const { defaultModel, defaultTools, defaultMiddleware, generalPurposeMiddleware: gpMiddleware, defaultInterruptOn, subagents, generalPurposeAgent, parentSystemPrompt = null } = options;
3702
+ const { defaultModel, defaultTools, defaultMiddleware, generalPurposeMiddleware: gpMiddleware, defaultInterruptOn, subagents, generalPurposeAgent, parentSystemPrompt = null, mirroredTaskTool } = options;
3569
3703
  const defaultSubagentMiddleware = defaultMiddleware || [];
3570
3704
  const generalPurposeMiddlewareBase = gpMiddleware || defaultSubagentMiddleware;
3571
3705
  const agents = {};
3572
3706
  const specsByName = {};
3573
3707
  const subagentDescriptions = [];
3574
3708
  const forkModeNames = /* @__PURE__ */ new Set();
3709
+ const seenNames = new Set(generalPurposeAgent ? ["general-purpose"] : []);
3710
+ for (const agentParams of subagents) {
3711
+ if (seenNames.has(agentParams.name)) throw new Error(`Duplicate subagent name '${agentParams.name}'; each subagent must have a unique name.`);
3712
+ seenNames.add(agentParams.name);
3713
+ }
3575
3714
  if (generalPurposeAgent) {
3576
3715
  const generalPurposeMiddleware = [...generalPurposeMiddlewareBase];
3577
3716
  if (defaultInterruptOn) generalPurposeMiddleware.push((0, langchain.humanInTheLoopMiddleware)({ interruptOn: defaultInterruptOn }));
@@ -3585,24 +3724,34 @@ function getSubagents(options) {
3585
3724
  };
3586
3725
  agents["general-purpose"] = createSubAgent(gpSpec);
3587
3726
  specsByName["general-purpose"] = gpSpec;
3588
- subagentDescriptions.push(`- general-purpose: ${DEFAULT_GENERAL_PURPOSE_DESCRIPTION}`);
3727
+ subagentDescriptions.push(describeSubagentForTool("general-purpose", DEFAULT_GENERAL_PURPOSE_DESCRIPTION, false));
3589
3728
  }
3590
3729
  for (const agentParams of subagents) {
3591
3730
  const rawMode = agentParams.mode;
3592
- if (rawMode != null && rawMode !== "handoff" && rawMode !== "fork") throw new Error(`SubAgent '${agentParams.name}' has invalid mode '${rawMode}' — must be "handoff" or "fork".`);
3593
- subagentDescriptions.push(`- ${agentParams.name}: ${agentParams.description}`);
3731
+ if (rawMode != null && rawMode !== "isolated" && rawMode !== "fork" && rawMode !== "handoff") throw new Error(`SubAgent '${agentParams.name}' has invalid mode '${rawMode}' — must be "isolated" or "fork".`);
3732
+ const forked = isForkedSubAgent(agentParams);
3733
+ const compiled = "runnable" in agentParams;
3734
+ subagentDescriptions.push(describeSubagentForTool(agentParams.name, agentParams.description, forked, compiled));
3594
3735
  if ("runnable" in agentParams) {
3595
3736
  agents[agentParams.name] = agentParams.runnable;
3596
3737
  specsByName[agentParams.name] = agentParams;
3597
- if (isForkedSubAgent(agentParams)) forkModeNames.add(agentParams.name);
3598
- } else if (isForkedSubAgent(agentParams)) {
3738
+ if (forked) forkModeNames.add(agentParams.name);
3739
+ continue;
3740
+ }
3741
+ const subagentMiddleware = [...defaultSubagentMiddleware, ...agentParams.middleware ?? []];
3742
+ if (forked) {
3743
+ const rawSkills = agentParams.skills;
3744
+ 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.`);
3745
+ const resolvedSystemPrompt = resolveForkSystemPrompt(parentSystemPrompt, agentParams.systemPrompt);
3746
+ const fsIndex = subagentMiddleware.findIndex((m) => m.name === "FilesystemMiddleware");
3747
+ subagentMiddleware.splice(fsIndex + 1, 0, createForkTaskToolMiddleware(mirroredTaskTool));
3599
3748
  const resolvedSpec = {
3600
3749
  ...agentParams,
3601
- systemPrompt: parentSystemPrompt ?? "",
3750
+ systemPrompt: resolvedSystemPrompt,
3602
3751
  mode: void 0,
3603
3752
  model: agentParams.model ?? defaultModel,
3604
3753
  tools: agentParams.tools ?? defaultTools,
3605
- middleware: [...defaultSubagentMiddleware, ...agentParams.middleware ?? []],
3754
+ middleware: subagentMiddleware,
3606
3755
  interruptOn: agentParams.interruptOn ?? defaultInterruptOn ?? void 0
3607
3756
  };
3608
3757
  agents[agentParams.name] = createSubAgent(resolvedSpec);
@@ -3611,10 +3760,10 @@ function getSubagents(options) {
3611
3760
  } else {
3612
3761
  const resolvedSpec = {
3613
3762
  ...agentParams,
3614
- mode: "handoff",
3763
+ mode: "isolated",
3615
3764
  model: agentParams.model ?? defaultModel,
3616
3765
  tools: agentParams.tools ?? defaultTools,
3617
- middleware: [...defaultSubagentMiddleware, ...agentParams.middleware ?? []],
3766
+ middleware: subagentMiddleware,
3618
3767
  interruptOn: agentParams.interruptOn ?? defaultInterruptOn ?? void 0
3619
3768
  };
3620
3769
  agents[agentParams.name] = createSubAgent(resolvedSpec);
@@ -3633,16 +3782,12 @@ function getSubagents(options) {
3633
3782
  */
3634
3783
  function createTaskTool(options) {
3635
3784
  const { defaultModel, defaultTools, defaultMiddleware, generalPurposeMiddleware, defaultInterruptOn, subagents, generalPurposeAgent, taskDescription, parentSystemPrompt = null } = options;
3636
- const { agents: subagentGraphs, specsByName, descriptions: subagentDescriptions, forkModeNames } = getSubagents({
3637
- defaultModel,
3638
- defaultTools,
3639
- defaultMiddleware,
3640
- generalPurposeMiddleware,
3641
- defaultInterruptOn,
3642
- subagents,
3643
- generalPurposeAgent,
3644
- parentSystemPrompt
3645
- });
3785
+ const subagentNames = [...generalPurposeAgent ? ["general-purpose"] : [], ...subagents.map((spec) => spec.name)];
3786
+ const subagentDescriptions = [...generalPurposeAgent ? [describeSubagentForTool("general-purpose", DEFAULT_GENERAL_PURPOSE_DESCRIPTION, false)] : [], ...subagents.map((spec) => describeSubagentForTool(spec.name, spec.description, isForkedSubAgent(spec), "runnable" in spec))];
3787
+ const finalTaskDescription = taskDescription ? taskDescription : getTaskToolDescription(subagentDescriptions);
3788
+ let subagentGraphs = {};
3789
+ let specsByName = {};
3790
+ let forkModeNames = /* @__PURE__ */ new Set();
3646
3791
  function selectSubagent(subagentType, config) {
3647
3792
  const spec = specsByName[subagentType];
3648
3793
  const responseFormat = config.configurable?.[SUBAGENT_RESPONSE_FORMAT_CONFIG_KEY];
@@ -3650,18 +3795,19 @@ function createTaskTool(options) {
3650
3795
  if ("runnable" in spec || responseFormat == null) return subagentGraphs[subagentType];
3651
3796
  return createSubAgent(spec, { responseFormat });
3652
3797
  }
3653
- const finalTaskDescription = taskDescription ? taskDescription : getTaskToolDescription(subagentDescriptions);
3654
- return (0, langchain.tool)(async (input, config) => {
3798
+ async function runTask(input, config) {
3655
3799
  const { description, subagent_type } = input;
3800
+ const currentState = (0, _langchain_langgraph.getCurrentTaskInput)();
3801
+ if (currentState[FORKED_CONTEXT_KEY]) return FORK_RECURSION_REFUSAL;
3656
3802
  if (!(subagent_type in subagentGraphs)) {
3657
3803
  const allowedTypes = Object.keys(subagentGraphs).map((k) => `\`${k}\``).join(", ");
3658
3804
  throw new Error(`Error: invoked agent of type ${subagent_type}, the only allowed types are ${allowedTypes}`);
3659
3805
  }
3660
3806
  const shouldFork = forkModeNames.has(subagent_type);
3661
3807
  const subagent = selectSubagent(subagent_type, config);
3662
- const currentState = (0, _langchain_langgraph.getCurrentTaskInput)();
3663
- const subagentState = filterStateForSubagent(currentState);
3664
- if (shouldFork) subagentState.messages = [...getEffectiveMessages(stripInFlightAIMessage(currentState.messages ?? []), currentState), new _langchain_core_messages.HumanMessage({ content: description })];
3808
+ const spec = specsByName[subagent_type];
3809
+ const subagentState = shouldFork && !("runnable" in spec) ? filterStateForFork(currentState) : filterStateForSubagent(currentState);
3810
+ if (shouldFork) subagentState.messages = [...getEffectiveMessages(stripInFlightAIMessage(currentState.messages ?? []), currentState), new _langchain_core_messages.HumanMessage({ content: FORK_TASK_PREAMBLE + description })];
3665
3811
  else subagentState.messages = [new _langchain_core_messages.HumanMessage({ content: description })];
3666
3812
  subagentState._summarizationSessionId = `session_${crypto.randomUUID().substring(0, 8)}`;
3667
3813
  const subagentConfig = {
@@ -3688,14 +3834,35 @@ function createTaskTool(options) {
3688
3834
  return content;
3689
3835
  }
3690
3836
  return returnCommandWithStateUpdate(result, config.toolCall.id);
3691
- }, {
3837
+ }
3838
+ const taskToolSchema = zod_v4.z.object({
3839
+ description: zod_v4.z.string().describe("The task to execute with the selected agent"),
3840
+ subagent_type: zod_v4.z.string().describe(`Name of the agent to use. Available: ${subagentNames.join(", ")}`)
3841
+ });
3842
+ const taskTool = (0, langchain.tool)(runTask, {
3692
3843
  name: "task",
3693
3844
  description: finalTaskDescription,
3694
- schema: zod_v4.z.object({
3695
- description: zod_v4.z.string().describe("The task to execute with the selected agent"),
3696
- subagent_type: zod_v4.z.string().describe(`Name of the agent to use. Available: ${Object.keys(subagentGraphs).join(", ")}`)
3845
+ schema: taskToolSchema
3846
+ });
3847
+ const { agents, specsByName: resolvedSpecsByName, forkModeNames: resolvedForkModeNames } = getSubagents({
3848
+ defaultModel,
3849
+ defaultTools,
3850
+ defaultMiddleware,
3851
+ generalPurposeMiddleware,
3852
+ defaultInterruptOn,
3853
+ subagents,
3854
+ generalPurposeAgent,
3855
+ parentSystemPrompt,
3856
+ mirroredTaskTool: (0, langchain.tool)(runTask, {
3857
+ name: "task",
3858
+ description: finalTaskDescription,
3859
+ schema: taskToolSchema
3697
3860
  })
3698
3861
  });
3862
+ subagentGraphs = agents;
3863
+ specsByName = resolvedSpecsByName;
3864
+ forkModeNames = resolvedForkModeNames;
3865
+ return taskTool;
3699
3866
  }
3700
3867
  /**
3701
3868
  * Create subagent middleware with task tool
@@ -4697,48 +4864,6 @@ function createSkillsMiddleware(options) {
4697
4864
  });
4698
4865
  }
4699
4866
  //#endregion
4700
- //#region src/middleware/utils.ts
4701
- /**
4702
- * Utility functions for middleware.
4703
- *
4704
- * This module provides shared helpers used across middleware implementations.
4705
- */
4706
- /**
4707
- * Merge custom middleware into an assembled stack by `.name`.
4708
- *
4709
- * Matching custom middleware replaces the existing entry in place. New
4710
- * middleware is appended after the base stack in caller-provided order.
4711
- */
4712
- function mergeMiddleware$1(base, custom) {
4713
- const merged = new Map(base.map((middleware) => [middleware.name, middleware]));
4714
- for (const middleware of custom) merged.set(middleware.name, middleware);
4715
- return [...merged.values()];
4716
- }
4717
- function middlewareNames(middleware) {
4718
- return new Set(middleware.map((entry) => entry.name));
4719
- }
4720
- function matchingMiddleware(middleware, names) {
4721
- return middleware.filter((entry) => names.has(entry.name));
4722
- }
4723
- /**
4724
- * Merge custom middleware into default and tail middleware segments.
4725
- *
4726
- * Same-name custom entries replace matching defaults in either segment. Novel
4727
- * custom entries are inserted between the default and tail segments unless
4728
- * `appendNew` is false.
4729
- */
4730
- function mergeMiddlewareStack(defaultMiddleware, customMiddleware, tailMiddleware = [], options = {}) {
4731
- const defaultMiddlewareNames = middlewareNames(defaultMiddleware);
4732
- const tailMiddlewareNames = middlewareNames(tailMiddleware);
4733
- const knownMiddlewareNames = /* @__PURE__ */ new Set([...defaultMiddlewareNames, ...tailMiddlewareNames]);
4734
- const novelMiddleware = options.appendNew === false ? [] : customMiddleware.filter((entry) => !knownMiddlewareNames.has(entry.name));
4735
- return [
4736
- ...mergeMiddleware$1(defaultMiddleware, matchingMiddleware(customMiddleware, defaultMiddlewareNames)),
4737
- ...novelMiddleware,
4738
- ...mergeMiddleware$1(tailMiddleware, matchingMiddleware(customMiddleware, tailMiddlewareNames))
4739
- ];
4740
- }
4741
- //#endregion
4742
4867
  //#region src/middleware/completion_callback.ts
4743
4868
  /**
4744
4869
  * Callback middleware for async subagents.
@@ -6367,8 +6492,18 @@ function createDeepAgent(params = {}) {
6367
6492
  providerHint: getModelProvider(model),
6368
6493
  identifierHint: getModelIdentifier(model)
6369
6494
  });
6370
- const filesystemTools = FILESYSTEM_TOOL_NAMES.filter((toolName) => !harnessProfile.excludedTools.has(toolName));
6371
- const profileFilesystemTools = filesystemTools.length === FILESYSTEM_TOOL_NAMES.length ? void 0 : filesystemTools.includes("read_file") ? filesystemTools : ["read_file", ...filesystemTools];
6495
+ const computeProfileFilesystemTools = (profile) => {
6496
+ const filesystemTools = FILESYSTEM_TOOL_NAMES.filter((toolName) => !profile.excludedTools.has(toolName));
6497
+ return filesystemTools.length === FILESYSTEM_TOOL_NAMES.length ? void 0 : filesystemTools.includes("read_file") ? filesystemTools : ["read_file", ...filesystemTools];
6498
+ };
6499
+ const profileFilesystemTools = computeProfileFilesystemTools(harnessProfile);
6500
+ const resolveSubagentProfile = (subagentModel) => {
6501
+ if (subagentModel == null || subagentModel === model) return harnessProfile;
6502
+ return typeof subagentModel === "string" ? resolveHarnessProfile({ spec: subagentModel }) : resolveHarnessProfile({
6503
+ providerHint: getModelProvider(subagentModel),
6504
+ identifierHint: getModelIdentifier(subagentModel)
6505
+ });
6506
+ };
6372
6507
  const toolOverrides = harnessProfile.toolDescriptionOverrides;
6373
6508
  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;
6374
6509
  const anthropicModel = isAnthropicModel(model);
@@ -6404,44 +6539,50 @@ function createDeepAgent(params = {}) {
6404
6539
  * Only the general-purpose subagent inherits the main agent's skills.
6405
6540
  * If a custom subagent needs skills, it must specify its own `skills` array.
6406
6541
  */
6407
- const createSubagentDefaultMiddleware = (input) => {
6542
+ const createSubagentDefaultMiddleware = (input, subagentProfile, forked) => {
6408
6543
  const effectivePermissions = input.permissions ?? permissions;
6409
6544
  return [
6410
6545
  createFilesystemMiddleware({
6411
6546
  backend,
6412
6547
  permissions: effectivePermissions,
6413
- tools: profileFilesystemTools
6548
+ tools: computeProfileFilesystemTools(subagentProfile)
6414
6549
  }),
6415
6550
  createSummarizationMiddleware({ backend }),
6416
6551
  createPatchToolCallsMiddleware(),
6417
- ...input.skills != null && input.skills.length > 0 ? [createSkillsMiddleware({
6552
+ ...!forked && input.skills != null && input.skills.length > 0 ? [createSkillsMiddleware({
6418
6553
  backend,
6419
6554
  sources: input.skills
6420
6555
  })] : []
6421
6556
  ];
6422
6557
  };
6423
- const buildSubagentMiddleware = (input, isForkable) => {
6424
- let subagentMiddleware = mergeMiddlewareStack(createSubagentDefaultMiddleware(input), input.middleware ?? [], [
6425
- ...resolveMiddleware(harnessProfile.extraMiddleware),
6558
+ const buildSubagentMiddleware = (input) => {
6559
+ const subagentProfile = resolveSubagentProfile(input.model);
6560
+ const forked = isForkedSubAgent(input);
6561
+ const subagentDefaultMiddleware = createSubagentDefaultMiddleware(input, subagentProfile, forked);
6562
+ if (forked && skills != null && skills.length > 0) subagentDefaultMiddleware.unshift(createSkillsMiddleware({
6563
+ backend,
6564
+ sources: skills
6565
+ }));
6566
+ let subagentMiddleware = mergeMiddlewareStack(subagentDefaultMiddleware, forked && customMiddleware.length > 0 ? mergeMiddleware$1(customMiddleware, input.middleware ?? []) : input.middleware ?? [], [
6567
+ ...resolveMiddleware(subagentProfile.extraMiddleware),
6426
6568
  ...cacheMiddleware,
6427
- ...isForkable ? memoryMiddleware : []
6569
+ ...forked && memory != null && memory.length > 0 ? [createMemoryMiddleware({
6570
+ backend,
6571
+ sources: memory,
6572
+ addCacheControl: anthropicModel
6573
+ })] : []
6428
6574
  ]);
6429
- if (harnessProfile.excludedMiddleware.size > 0) subagentMiddleware = subagentMiddleware.filter((middleware) => !harnessProfile.excludedMiddleware.has(middleware.name));
6575
+ if (subagentProfile.excludedMiddleware.size > 0) subagentMiddleware = subagentMiddleware.filter((middleware) => !subagentProfile.excludedMiddleware.has(middleware.name));
6576
+ if (subagentProfile.excludedTools.size > 0) subagentMiddleware.push(createToolExclusionMiddleware(subagentProfile.excludedTools));
6430
6577
  return subagentMiddleware;
6431
6578
  };
6432
6579
  const normalizeSubagentSpec = (input) => ({
6433
6580
  ...input,
6434
- tools: input.tools ?? [],
6435
- middleware: buildSubagentMiddleware(input, false)
6436
- });
6437
- const normalizeForkedSubagentSpec = (input) => ({
6438
- ...input,
6439
- tools: input.tools ?? [],
6440
- middleware: buildSubagentMiddleware(input, true)
6581
+ middleware: buildSubagentMiddleware(input)
6441
6582
  });
6442
6583
  const allSubagents = subagents;
6443
6584
  const asyncSubAgents = allSubagents.filter((item) => isAsyncSubAgent(item));
6444
- const inlineSubagents = allSubagents.filter((item) => !isAsyncSubAgent(item)).map((item) => "runnable" in item ? item : isForkedSubAgent(item) ? normalizeForkedSubagentSpec(item) : normalizeSubagentSpec(item));
6585
+ const inlineSubagents = allSubagents.filter((item) => !isAsyncSubAgent(item)).map((item) => "runnable" in item ? item : normalizeSubagentSpec(item));
6445
6586
  const gpConfig = harnessProfile.generalPurposeSubagent;
6446
6587
  if (!(gpConfig?.enabled === false) && !inlineSubagents.some((item) => item.name === GENERAL_PURPOSE_SUBAGENT["name"])) {
6447
6588
  const gpSystemPrompt = gpConfig?.systemPrompt ?? applyProfilePrompt(harnessProfile, GENERAL_PURPOSE_SUBAGENT.systemPrompt);
@@ -8931,4 +9072,4 @@ Object.defineProperty(exports, "serializeProfile", {
8931
9072
  }
8932
9073
  });
8933
9074
 
8934
- //# sourceMappingURL=langsmith-DL32swQ3.cjs.map
9075
+ //# sourceMappingURL=langsmith-Ynj9VKxb.cjs.map