{"version":3,"file":"AgentNode.cjs","names":["AIMessage","RunnableCallable","#run","#options","#systemMessage","#getResponseFormat","isConfigurableModel","transformResponseFormat","ProviderStrategy","ToolStrategy","ToolMessage","Command","#invokeModel","#areMoreStepsNeeded","initChatModel","#deriveModel","#bindTools","mergeAbortSignals","#handleMultipleStructuredOutputs","#handleSingleStructuredOutput","toPartialZodObject","isClientTool","SystemMessage","MiddlewareError","MultipleStructuredOutputsError","#handleToolStrategyError","hasToolCalls","bindTools","withAgentName"],"sources":["../../../src/agents/nodes/AgentNode.ts"],"sourcesContent":["/* oxlint-disable no-instanceof/no-instanceof */\nimport { Runnable, RunnableConfig } from \"@langchain/core/runnables\";\nimport {\n  BaseMessage,\n  AIMessage,\n  ToolMessage,\n  SystemMessage,\n} from \"@langchain/core/messages\";\nimport {\n  Command,\n  isCommand,\n  type LangGraphRunnableConfig,\n} from \"@langchain/langgraph\";\nimport { type BaseChatModelCallOptions } from \"@langchain/core/language_models/chat_models\";\nimport {\n  InteropZodObject,\n  getSchemaDescription,\n  interopParse,\n} from \"@langchain/core/utils/types\";\nimport { raceWithSignal } from \"@langchain/core/runnables\";\nimport type { ToolCall } from \"@langchain/core/messages/tool\";\nimport type { ClientTool, ServerTool } from \"@langchain/core/tools\";\n\nimport { initChatModel } from \"../../chat_models/universal.js\";\nimport { MultipleStructuredOutputsError, MiddlewareError } from \"../errors.js\";\nimport { RunnableCallable } from \"../RunnableCallable.js\";\nimport type { AgentLanguageModelLike as LanguageModelLike } from \"../model.js\";\nimport {\n  bindTools,\n  validateLLMHasNoBoundTools,\n  hasToolCalls,\n  isClientTool,\n} from \"../utils.js\";\nimport { isConfigurableModel } from \"../model.js\";\nimport { mergeAbortSignals, toPartialZodObject } from \"../nodes/utils.js\";\nimport { CreateAgentParams } from \"../types.js\";\nimport type { InternalAgentState, Runtime } from \"../runtime.js\";\nimport type {\n  AgentMiddleware,\n  AnyAnnotationRoot,\n  WrapModelCallHandler,\n} from \"../middleware/types.js\";\nimport type { ModelRequest } from \"./types.js\";\nimport { withAgentName } from \"../withAgentName.js\";\nimport {\n  ToolStrategy,\n  ProviderStrategy,\n  transformResponseFormat,\n  ToolStrategyError,\n  type ResponseFormatInput,\n} from \"../responses.js\";\n\ntype ResponseHandlerResult<StructuredResponseFormat> =\n  | {\n      structuredResponse: StructuredResponseFormat;\n      messages: BaseMessage[];\n    }\n  | Promise<Command>;\n\n/**\n * Wrap the base handler with middleware wrapModelCall hooks\n * Middleware are composed so the first middleware is the outermost wrapper\n * Example: [auth, retry, cache] means auth wraps retry wraps cache wraps baseHandler\n */\ntype InternalModelResponse<StructuredResponseFormat> =\n  | AIMessage\n  | ResponseHandlerResult<StructuredResponseFormat>\n  | Command;\n\n/**\n * Check if the response is an internal model response.\n * @param response - The response to check.\n * @returns True if the response is an internal model response, false otherwise.\n */\nfunction isInternalModelResponse<StructuredResponseFormat>(\n  response: unknown\n): response is InternalModelResponse<StructuredResponseFormat> {\n  return (\n    AIMessage.isInstance(response) ||\n    isCommand(response) ||\n    (typeof response === \"object\" &&\n      response !== null &&\n      \"structuredResponse\" in response &&\n      \"messages\" in response)\n  );\n}\n\n/**\n * The name of the agent node in the state graph.\n */\nexport const AGENT_NODE_NAME = \"model_request\";\n\nexport interface AgentNodeOptions<\n  StructuredResponseFormat extends Record<string, unknown> = Record<\n    string,\n    unknown\n  >,\n  StateSchema extends AnyAnnotationRoot | InteropZodObject = AnyAnnotationRoot,\n  ContextSchema extends AnyAnnotationRoot | InteropZodObject =\n    AnyAnnotationRoot,\n> extends Pick<\n  CreateAgentParams<StructuredResponseFormat, StateSchema, ContextSchema>,\n  \"model\" | \"includeAgentName\" | \"name\" | \"responseFormat\" | \"middleware\"\n> {\n  toolClasses: (ClientTool | ServerTool)[];\n  shouldReturnDirect: Set<string>;\n  signal?: AbortSignal;\n  systemMessage: SystemMessage;\n  wrapModelCallHookMiddleware?: (\n    | AgentMiddleware\n    | [AgentMiddleware, (...args: unknown[]) => Record<string, unknown>]\n  )[];\n}\n\ninterface NativeResponseFormat {\n  type: \"native\";\n  strategy: ProviderStrategy;\n}\n\ninterface ToolResponseFormat {\n  type: \"tool\";\n  tools: Record<string, ToolStrategy>;\n}\n\ntype ResponseFormat = NativeResponseFormat | ToolResponseFormat;\n\nexport class AgentNode<\n  StructuredResponseFormat extends Record<string, unknown> = Record<\n    string,\n    unknown\n  >,\n  ContextSchema extends AnyAnnotationRoot | InteropZodObject =\n    AnyAnnotationRoot,\n> extends RunnableCallable<\n  InternalAgentState<StructuredResponseFormat>,\n  | Command[]\n  | {\n      messages: BaseMessage[];\n      structuredResponse: StructuredResponseFormat;\n    }\n> {\n  #options: AgentNodeOptions<StructuredResponseFormat, ContextSchema>;\n  #systemMessage: SystemMessage;\n\n  constructor(\n    options: AgentNodeOptions<StructuredResponseFormat, ContextSchema>\n  ) {\n    super({\n      name: options.name ?? \"model\",\n      func: (input, config) => this.#run(input, config as RunnableConfig),\n    });\n\n    this.#options = options;\n    this.#systemMessage = options.systemMessage;\n  }\n\n  /**\n   * Returns response format primtivies based on given model and response format provided by the user.\n   *\n   * If the user selects a tool output:\n   * - return a record of tools to extract structured output from the model's response\n   *\n   * if the the user selects a native schema output or if the model supports JSON schema output:\n   * - return a provider strategy to extract structured output from the model's response\n   *\n   * @param model - The model to get the response format for.\n   * @returns The response format.\n   */\n  async #getResponseFormat(\n    model: string | LanguageModelLike,\n    responseFormat: ResponseFormatInput | undefined = this.#options\n      .responseFormat\n  ): Promise<ResponseFormat | undefined> {\n    if (!responseFormat) {\n      return undefined;\n    }\n\n    let resolvedModel: LanguageModelLike | undefined;\n    if (isConfigurableModel(model)) {\n      resolvedModel = await (\n        model as unknown as {\n          _getModelInstance: () => Promise<LanguageModelLike>;\n        }\n      )._getModelInstance();\n    } else if (typeof model !== \"string\") {\n      resolvedModel = model;\n    }\n\n    const strategies = transformResponseFormat(\n      responseFormat,\n      undefined,\n      resolvedModel\n    );\n\n    if (strategies.length === 0) {\n      return undefined;\n    }\n\n    /**\n     * we either define a list of provider strategies or a list of tool strategies\n     */\n    const isProviderStrategy = strategies.every(\n      (format) => format instanceof ProviderStrategy\n    );\n\n    /**\n     * Populate a list of structured tool info.\n     */\n    if (!isProviderStrategy) {\n      return {\n        type: \"tool\",\n        tools: (\n          strategies.filter(\n            (format) => format instanceof ToolStrategy\n          ) as ToolStrategy[]\n        ).reduce(\n          (acc, format) => {\n            acc[format.name] = format;\n            return acc;\n          },\n          {} as Record<string, ToolStrategy>\n        ),\n      };\n    }\n\n    return {\n      type: \"native\",\n      /**\n       * there can only be one provider strategy\n       */\n      strategy: strategies[0] as ProviderStrategy,\n    };\n  }\n\n  async #run(\n    state: InternalAgentState<StructuredResponseFormat>,\n    config: RunnableConfig\n  ) {\n    /**\n     * Check if we just executed a returnDirect tool\n     * If so, we should generate structured response (if needed) and stop\n     */\n    const lastMessage = state.messages.at(-1);\n    if (\n      lastMessage &&\n      ToolMessage.isInstance(lastMessage) &&\n      lastMessage.name &&\n      this.#options.shouldReturnDirect.has(lastMessage.name)\n    ) {\n      return [new Command({ update: { messages: [] } })];\n    }\n\n    const { response, lastAiMessage, collectedCommands } =\n      await this.#invokeModel(state, config);\n\n    /**\n     * structuredResponse — return as a plain state update dict (not a Command)\n     * because the structuredResponse channel uses UntrackedValue(guard=true)\n     * which only allows a single write per step.\n     */\n    if (\n      typeof response === \"object\" &&\n      response !== null &&\n      \"structuredResponse\" in response &&\n      \"messages\" in response\n    ) {\n      const { structuredResponse, messages } = response as {\n        structuredResponse: StructuredResponseFormat;\n        messages: BaseMessage[];\n      };\n      return {\n        messages: [...state.messages, ...messages],\n        structuredResponse,\n      };\n    }\n\n    const commands: Command[] = [];\n    const aiMessage: AIMessage | null = AIMessage.isInstance(response)\n      ? response\n      : lastAiMessage;\n\n    // messages\n    if (aiMessage) {\n      aiMessage.name = this.name;\n      aiMessage.lc_kwargs.name = this.name;\n\n      if (this.#areMoreStepsNeeded(state, aiMessage)) {\n        commands.push(\n          new Command({\n            update: {\n              messages: [\n                new AIMessage({\n                  content: \"Sorry, need more steps to process this request.\",\n                  name: this.name,\n                  id: aiMessage.id,\n                }),\n              ],\n            },\n          })\n        );\n      } else {\n        commands.push(new Command({ update: { messages: [aiMessage] } }));\n      }\n    }\n\n    // Commands (from base handler retries or middleware)\n    if (isCommand(response) && !collectedCommands.includes(response)) {\n      commands.push(response);\n    }\n    commands.push(...collectedCommands);\n\n    return commands;\n  }\n\n  /**\n   * Derive the model from the options.\n   * @param state - The state of the agent.\n   * @param config - The config of the agent.\n   * @returns The model.\n   */\n  #deriveModel() {\n    if (typeof this.#options.model === \"string\") {\n      return initChatModel(this.#options.model);\n    }\n\n    if (this.#options.model) {\n      return this.#options.model;\n    }\n\n    throw new Error(\"No model option was provided, either via `model` option.\");\n  }\n\n  async #invokeModel(\n    state: InternalAgentState<StructuredResponseFormat>,\n    config: RunnableConfig,\n    options: {\n      lastMessage?: string;\n    } = {}\n  ): Promise<{\n    response: InternalModelResponse<StructuredResponseFormat>;\n    lastAiMessage: AIMessage | null;\n    collectedCommands: Command[];\n  }> {\n    const model = await this.#deriveModel();\n    const lgConfig = config as LangGraphRunnableConfig;\n\n    /**\n     * Create a local variable for current system message to avoid concurrency issues\n     * Each invocation gets its own copy\n     */\n    let currentSystemMessage = this.#systemMessage;\n\n    /**\n     * Shared tracking state for AIMessage and Command collection.\n     * lastAiMessage tracks the effective AIMessage through the middleware chain.\n     * collectedCommands accumulates Commands returned by middleware (not base handler).\n     */\n    let lastAiMessage: AIMessage | null = null;\n    const collectedCommands: Command[] = [];\n\n    /**\n     * Create the base handler that performs the actual model invocation\n     */\n    const baseHandler = async (\n      request: ModelRequest\n    ): Promise<AIMessage | ResponseHandlerResult<StructuredResponseFormat>> => {\n      /**\n       * Check if the LLM already has bound tools and throw if it does.\n       */\n      validateLLMHasNoBoundTools(request.model);\n\n      const structuredResponseFormat = await this.#getResponseFormat(\n        request.model,\n        request.responseFormat\n      );\n      const modelWithTools = await this.#bindTools(\n        request.model,\n        request,\n        structuredResponseFormat\n      );\n\n      /**\n       * prepend the system message to the messages if it is not empty\n       */\n      const messages = [\n        ...(currentSystemMessage.text === \"\" ? [] : [currentSystemMessage]),\n        ...request.messages,\n      ];\n\n      const signal = mergeAbortSignals(this.#options.signal, config.signal);\n      const response = (await raceWithSignal(\n        modelWithTools.invoke(messages, {\n          ...config,\n          signal,\n        }),\n        signal\n      )) as AIMessage;\n\n      lastAiMessage = response;\n\n      /**\n       * if the user requests a native schema output, try to parse the response\n       * and return the structured response if it is valid\n       */\n      if (structuredResponseFormat?.type === \"native\") {\n        const structuredResponse =\n          structuredResponseFormat.strategy.parse(response);\n        if (structuredResponse) {\n          return { structuredResponse, messages: [response] };\n        }\n\n        return response;\n      }\n\n      if (!structuredResponseFormat || !response.tool_calls) {\n        return response;\n      }\n\n      const toolCalls = response.tool_calls.filter(\n        (call) => call.name in structuredResponseFormat.tools\n      );\n\n      /**\n       * if there were not structured tool calls, we can return the response\n       */\n      if (toolCalls.length === 0) {\n        return response;\n      }\n\n      /**\n       * if there were multiple structured tool calls, we should throw an error as this\n       * scenario is not defined/supported.\n       */\n      if (toolCalls.length > 1) {\n        return this.#handleMultipleStructuredOutputs(\n          response,\n          toolCalls,\n          structuredResponseFormat\n        );\n      }\n\n      const toolStrategy = structuredResponseFormat.tools[toolCalls[0].name];\n      const toolMessageContent = toolStrategy?.options?.toolMessageContent;\n      return this.#handleSingleStructuredOutput(\n        response,\n        toolCalls[0],\n        structuredResponseFormat,\n        toolMessageContent ?? options.lastMessage\n      );\n    };\n\n    const wrapperMiddleware = this.#options.wrapModelCallHookMiddleware ?? [];\n    let wrappedHandler: (\n      request: ModelRequest<\n        InternalAgentState<StructuredResponseFormat>,\n        unknown\n      >\n    ) => Promise<InternalModelResponse<StructuredResponseFormat>> = baseHandler;\n\n    /**\n     * Build composed handler from last to first so first middleware becomes outermost\n     */\n    for (let i = wrapperMiddleware.length - 1; i >= 0; i--) {\n      const middlewareEntry = wrapperMiddleware[i];\n      const middleware = Array.isArray(middlewareEntry)\n        ? middlewareEntry[0]\n        : middlewareEntry;\n      if (middleware.wrapModelCall) {\n        const innerHandler = wrappedHandler;\n        const currentMiddleware = middleware;\n\n        wrappedHandler = async (\n          request: ModelRequest<\n            InternalAgentState<StructuredResponseFormat>,\n            unknown\n          >\n        ): Promise<InternalModelResponse<StructuredResponseFormat>> => {\n          const baselineSystemMessage = currentSystemMessage;\n\n          /**\n           * Merge context with default context of middleware\n           */\n          const context = currentMiddleware.contextSchema\n            ? interopParse(\n                currentMiddleware.contextSchema,\n                lgConfig?.context || {}\n              )\n            : lgConfig?.context;\n\n          /**\n           * Create runtime\n           */\n          const runtime: Runtime<unknown> = Object.freeze({\n            context,\n            store: lgConfig.store,\n            configurable: lgConfig.configurable,\n            writer: lgConfig.writer,\n            interrupt: lgConfig.interrupt,\n            signal: lgConfig.signal,\n          });\n\n          /**\n           * Create the request with state and runtime\n           */\n          const requestWithStateAndRuntime: ModelRequest<\n            InternalAgentState<StructuredResponseFormat>,\n            unknown\n          > = {\n            ...request,\n            state: {\n              ...(middleware.stateSchema\n                ? interopParse(\n                    toPartialZodObject(middleware.stateSchema),\n                    state\n                  )\n                : {}),\n              messages: state.messages,\n            } as InternalAgentState<StructuredResponseFormat>,\n            runtime,\n          };\n\n          /**\n           * Create handler that validates tools and calls the inner handler\n           */\n          const handlerWithValidation = async (\n            req: ModelRequest<\n              InternalAgentState<StructuredResponseFormat>,\n              unknown\n            >\n          ): Promise<InternalModelResponse<StructuredResponseFormat>> => {\n            currentSystemMessage = baselineSystemMessage;\n\n            /**\n             * Validate tool modifications in wrapModelCall.\n             *\n             * Classify each client tool as either:\n             * - \"added\": a genuinely new tool name not in the static toolClasses\n             * - \"replaced\": same name as a registered tool but different instance\n             *\n             * Added tools are allowed when a wrapToolCall middleware exists to\n             * handle their execution. Replaced tools are always rejected to\n             * preserve ToolNode execution identity.\n             */\n            const modifiedTools = req.tools ?? [];\n            const registeredToolsByName = new Map(\n              this.#options.toolClasses\n                .filter(isClientTool)\n                .map((t) => [t.name, t] as const)\n            );\n\n            const addedClientTools = modifiedTools.filter(\n              (tool) =>\n                isClientTool(tool) && !registeredToolsByName.has(tool.name)\n            );\n\n            const replacedClientTools = modifiedTools.filter((tool) => {\n              if (!isClientTool(tool)) return false;\n              const original = registeredToolsByName.get(tool.name);\n              return original != null && original !== tool;\n            });\n\n            if (addedClientTools.length > 0) {\n              const hasWrapToolCallHandler = this.#options.middleware?.some(\n                (m) => m.wrapToolCall != null\n              );\n              if (!hasWrapToolCallHandler) {\n                throw new Error(\n                  `You have added a new tool in \"wrapModelCall\" hook of middleware \"${\n                    currentMiddleware.name\n                  }\": ${addedClientTools\n                    .map((tool) => tool.name)\n                    .join(\n                      \", \"\n                    )}. This is not supported unless a middleware provides a \"wrapToolCall\" handler to execute it.`\n                );\n              }\n            }\n\n            if (replacedClientTools.length > 0) {\n              throw new Error(\n                `You have modified a tool in \"wrapModelCall\" hook of middleware \"${\n                  currentMiddleware.name\n                }\": ${replacedClientTools\n                  .map((tool) => tool.name)\n                  .join(\", \")}. This is not supported.`\n              );\n            }\n\n            let normalizedReq = req;\n            const hasSystemPromptChanged =\n              req.systemPrompt !== currentSystemMessage.text;\n            const hasSystemMessageChanged =\n              req.systemMessage !== currentSystemMessage;\n            if (hasSystemPromptChanged && hasSystemMessageChanged) {\n              throw new Error(\n                \"Cannot change both systemPrompt and systemMessage in the same request.\"\n              );\n            }\n\n            /**\n             * Check if systemPrompt is a string was changed, if so create a new SystemMessage\n             */\n            if (hasSystemPromptChanged) {\n              currentSystemMessage = new SystemMessage({\n                content: [{ type: \"text\", text: req.systemPrompt }],\n              });\n              normalizedReq = {\n                ...req,\n                systemPrompt: currentSystemMessage.text,\n                systemMessage: currentSystemMessage,\n              };\n            }\n            /**\n             * If the systemMessage was changed, update the current system message\n             */\n            if (hasSystemMessageChanged) {\n              currentSystemMessage = new SystemMessage({\n                ...req.systemMessage,\n              });\n              normalizedReq = {\n                ...req,\n                systemPrompt: currentSystemMessage.text,\n                systemMessage: currentSystemMessage,\n              };\n            }\n\n            const innerHandlerResult = await innerHandler(normalizedReq);\n\n            /**\n             * Normalize Commands so middleware always sees AIMessage from handler().\n             * When an inner handler (base handler or nested middleware) returns a\n             * Command (e.g. structured-output retry), substitute the tracked\n             * lastAiMessage so the middleware sees an AIMessage, and collect the\n             * raw Command so the framework can still propagate it (e.g. for retries).\n             *\n             * Only collect if not already present: Commands from inner middleware\n             * are already tracked via the middleware validation layer (line ~627).\n             */\n            if (isCommand(innerHandlerResult) && lastAiMessage) {\n              if (!collectedCommands.includes(innerHandlerResult)) {\n                collectedCommands.push(innerHandlerResult);\n              }\n              return lastAiMessage as InternalModelResponse<StructuredResponseFormat>;\n            }\n\n            return innerHandlerResult;\n          };\n\n          // Call middleware's wrapModelCall with the validation handler\n          if (!currentMiddleware.wrapModelCall) {\n            return handlerWithValidation(requestWithStateAndRuntime);\n          }\n\n          try {\n            const middlewareResponse = await currentMiddleware.wrapModelCall(\n              requestWithStateAndRuntime,\n              handlerWithValidation as WrapModelCallHandler\n            );\n\n            /**\n             * Validate that this specific middleware returned a valid response\n             */\n            if (!isInternalModelResponse(middlewareResponse)) {\n              throw new Error(\n                `Invalid response from \"wrapModelCall\" in middleware \"${\n                  currentMiddleware.name\n                }\": expected AIMessage or Command, got ${typeof middlewareResponse}`\n              );\n            }\n\n            if (AIMessage.isInstance(middlewareResponse)) {\n              lastAiMessage = middlewareResponse;\n            } else if (isCommand(middlewareResponse)) {\n              collectedCommands.push(middlewareResponse);\n            }\n\n            return middlewareResponse;\n          } catch (error) {\n            throw MiddlewareError.wrap(error, currentMiddleware.name);\n          }\n        };\n      }\n    }\n\n    /**\n     * Execute the wrapped handler with the initial request\n     * Reset current system prompt to initial state and convert to string using .text getter\n     * for backwards compatibility with ModelRequest\n     */\n    currentSystemMessage = this.#systemMessage;\n    const initialRequest: ModelRequest<\n      InternalAgentState<StructuredResponseFormat>,\n      unknown\n    > = {\n      model,\n      responseFormat: this.#options.responseFormat,\n      systemPrompt: currentSystemMessage?.text,\n      systemMessage: currentSystemMessage,\n      messages: state.messages,\n      tools: this.#options.toolClasses,\n      state,\n      runtime: Object.freeze({\n        context: lgConfig?.context,\n        store: lgConfig.store,\n        configurable: lgConfig.configurable,\n        writer: lgConfig.writer,\n        interrupt: lgConfig.interrupt,\n        signal: lgConfig.signal,\n      }) as Runtime<unknown>,\n    };\n\n    const response = await wrappedHandler(initialRequest);\n    return { response, lastAiMessage, collectedCommands };\n  }\n\n  /**\n   * If the model returns multiple structured outputs, we need to handle it.\n   * @param response - The response from the model\n   * @param toolCalls - The tool calls that were made\n   * @returns The response from the model\n   */\n  #handleMultipleStructuredOutputs(\n    response: AIMessage,\n    toolCalls: ToolCall[],\n    responseFormat: ToolResponseFormat\n  ): Promise<Command> {\n    const multipleStructuredOutputsError = new MultipleStructuredOutputsError(\n      toolCalls.map((call) => call.name)\n    );\n\n    return this.#handleToolStrategyError(\n      multipleStructuredOutputsError,\n      response,\n      toolCalls[0],\n      responseFormat\n    );\n  }\n\n  /**\n   * If the model returns a single structured output, we need to handle it.\n   * @param toolCall - The tool call that was made\n   * @returns The structured response and a message to the LLM if needed\n   */\n  #handleSingleStructuredOutput(\n    response: AIMessage,\n    toolCall: ToolCall,\n    responseFormat: ToolResponseFormat,\n    lastMessage?: string\n  ): ResponseHandlerResult<StructuredResponseFormat> {\n    const tool = responseFormat.tools[toolCall.name];\n\n    try {\n      const structuredResponse = tool.parse(\n        toolCall.args\n      ) as StructuredResponseFormat;\n\n      return {\n        structuredResponse,\n        messages: [\n          response,\n          new ToolMessage({\n            tool_call_id: toolCall.id ?? \"\",\n            content: JSON.stringify(structuredResponse),\n            name: toolCall.name,\n          }),\n          new AIMessage(\n            lastMessage ??\n              `Returning structured response: ${JSON.stringify(\n                structuredResponse\n              )}`\n          ),\n        ],\n      };\n    } catch (error) {\n      return this.#handleToolStrategyError(\n        error as ToolStrategyError,\n        response,\n        toolCall,\n        responseFormat\n      );\n    }\n  }\n\n  async #handleToolStrategyError(\n    error: ToolStrategyError,\n    response: AIMessage,\n    toolCall: ToolCall,\n    responseFormat: ToolResponseFormat\n  ): Promise<Command> {\n    /**\n     * Using the `errorHandler` option of the first `ToolStrategy` entry is sufficient here.\n     * There is technically only one `ToolStrategy` entry in `structuredToolInfo` if the user\n     * uses `toolStrategy` to define the response format. If the user applies a list of json\n     * schema objects, these will be transformed into multiple `ToolStrategy` entries but all\n     * with the same `handleError` option.\n     */\n    const errorHandler = Object.values(responseFormat.tools).at(0)?.options\n      ?.handleError;\n\n    const toolCallId = toolCall.id;\n    if (!toolCallId) {\n      throw new Error(\n        \"Tool call ID is required to handle tool output errors. Please provide a tool call ID.\"\n      );\n    }\n\n    /**\n     * Default behavior: retry if `errorHandler` is undefined or truthy.\n     * Only throw if explicitly set to `false`.\n     */\n    if (errorHandler === false) {\n      throw error;\n    }\n\n    /**\n     * retry if:\n     */\n    if (\n      /**\n       * if the user has provided truthy value as the `errorHandler`, return a new AIMessage\n       * with the error message and retry the tool call.\n       */\n      errorHandler === undefined ||\n      (typeof errorHandler === \"boolean\" && errorHandler) ||\n      /**\n       * if `errorHandler` is an array and contains MultipleStructuredOutputsError\n       */\n      (Array.isArray(errorHandler) &&\n        errorHandler.some((h) => h instanceof MultipleStructuredOutputsError))\n    ) {\n      return new Command({\n        update: {\n          messages: [\n            response,\n            new ToolMessage({\n              content: error.message,\n              tool_call_id: toolCallId,\n            }),\n          ],\n        },\n        goto: AGENT_NODE_NAME,\n      });\n    }\n\n    /**\n     * if `errorHandler` is a string, retry the tool call with given string\n     */\n    if (typeof errorHandler === \"string\") {\n      return new Command({\n        update: {\n          messages: [\n            response,\n            new ToolMessage({\n              content: errorHandler,\n              tool_call_id: toolCallId,\n            }),\n          ],\n        },\n        goto: AGENT_NODE_NAME,\n      });\n    }\n\n    /**\n     * if `errorHandler` is a function, retry the tool call with the function\n     */\n    if (typeof errorHandler === \"function\") {\n      const content = await errorHandler(error);\n      if (typeof content !== \"string\") {\n        throw new Error(\"Error handler must return a string.\");\n      }\n\n      return new Command({\n        update: {\n          messages: [\n            response,\n            new ToolMessage({\n              content,\n              tool_call_id: toolCallId,\n            }),\n          ],\n        },\n        goto: AGENT_NODE_NAME,\n      });\n    }\n\n    /**\n     * Default: retry if we reach here\n     */\n    return new Command({\n      update: {\n        messages: [\n          response,\n          new ToolMessage({\n            content: error.message,\n            tool_call_id: toolCallId,\n          }),\n        ],\n      },\n      goto: AGENT_NODE_NAME,\n    });\n  }\n\n  #areMoreStepsNeeded(\n    state: InternalAgentState<StructuredResponseFormat>,\n    response: BaseMessage\n  ): boolean {\n    const allToolsReturnDirect =\n      AIMessage.isInstance(response) &&\n      response.tool_calls?.every((call) =>\n        this.#options.shouldReturnDirect.has(call.name)\n      );\n    const remainingSteps =\n      \"remainingSteps\" in state ? (state.remainingSteps as number) : undefined;\n    return Boolean(\n      remainingSteps &&\n      ((remainingSteps < 1 && allToolsReturnDirect) ||\n        (remainingSteps < 2 && hasToolCalls(state.messages.at(-1))))\n    );\n  }\n\n  async #bindTools(\n    model: LanguageModelLike,\n    preparedOptions: ModelRequest | undefined,\n    structuredResponseFormat: ResponseFormat | undefined\n  ): Promise<LanguageModelLike | Runnable> {\n    const options: Partial<BaseChatModelCallOptions> = {};\n    const structuredTools = Object.values(\n      structuredResponseFormat && \"tools\" in structuredResponseFormat\n        ? structuredResponseFormat.tools\n        : {}\n    );\n\n    /**\n     * Use tools from preparedOptions if provided, otherwise use default tools\n     */\n    const allTools = [\n      ...(preparedOptions?.tools ?? this.#options.toolClasses),\n      ...structuredTools.map((toolStrategy) => toolStrategy.tool),\n    ];\n\n    /**\n     * If there are structured tools, we need to set the tool choice to \"any\"\n     * so that the model can choose to use a structured tool or not.\n     */\n    const toolChoice =\n      preparedOptions?.toolChoice ||\n      (structuredTools.length > 0 ? \"any\" : undefined);\n\n    /**\n     * check if the user requests a native schema output\n     */\n    if (structuredResponseFormat?.type === \"native\") {\n      const resolvedStrict =\n        preparedOptions?.modelSettings?.strict ??\n        structuredResponseFormat?.strategy?.strict ??\n        true;\n\n      const jsonSchemaParams = {\n        name: structuredResponseFormat.strategy.schema?.name ?? \"extract\",\n        description: getSchemaDescription(\n          structuredResponseFormat.strategy.schema\n        ),\n        schema: structuredResponseFormat.strategy.schema,\n        strict: resolvedStrict,\n      };\n\n      Object.assign(options, {\n        /**\n         * OpenAI-style options\n         * Used by ChatOpenAI, ChatXAI, and other OpenAI-compatible providers.\n         */\n        response_format: {\n          type: \"json_schema\",\n          json_schema: jsonSchemaParams,\n        },\n\n        /**\n         * Anthropic-style options\n         */\n        outputConfig: {\n          format: {\n            type: \"json_schema\",\n            schema: structuredResponseFormat.strategy.schema,\n          },\n        },\n\n        /**\n         * Google-style options\n         * Used by ChatGoogle and other Gemini-based providers.\n         */\n        responseSchema: structuredResponseFormat.strategy.schema,\n\n        /**\n         * for LangSmith structured output tracing\n         */\n        ls_structured_output_format: {\n          kwargs: { method: \"json_schema\" },\n          schema: structuredResponseFormat.strategy.schema,\n        },\n        strict: resolvedStrict,\n      });\n    }\n\n    /**\n     * Bind tools to the model if they are not already bound.\n     */\n    const modelWithTools = await bindTools(model, allTools, {\n      ...options,\n      ...preparedOptions?.modelSettings,\n      tool_choice: toolChoice,\n    });\n\n    /**\n     * Create a model runnable with the prompt and agent name\n     * Use current SystemMessage state (which may have been modified by middleware)\n     */\n    const modelRunnable =\n      this.#options.includeAgentName === \"inline\"\n        ? withAgentName(modelWithTools, this.#options.includeAgentName)\n        : modelWithTools;\n\n    return modelRunnable;\n  }\n\n  /**\n   * Returns internal bookkeeping state for StateManager, not graph output.\n   * The return shape differs from the node's output type (Command).\n   */\n  // @ts-expect-error Internal state shape differs from graph output type\n  getState(): { messages: BaseMessage[] } {\n    const state = super.getState();\n    const origState = state && !isCommand(state) ? state : {};\n\n    return {\n      messages: [],\n      ...origState,\n    };\n  }\n}\n"],"mappings":"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"}