UNPKG

langchain

Version:
1 lines • 46.4 kB
{"version":3,"file":"AgentNode.cjs","names":["AIMessage","isCommand","RunnableCallable","isConfigurableModel","transformResponseFormat","ProviderStrategy","ToolStrategy","ToolMessage","Command","initChatModel","mergeAbortSignals","raceWithSignal","StructuredOutputParsingError","interopParse","toPartialZodObject","isClientTool","SystemMessage","MiddlewareError","MultipleStructuredOutputsError","hasToolCalls","getSchemaDescription","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 {\n MultipleStructuredOutputsError,\n MiddlewareError,\n StructuredOutputParsingError,\n} 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 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 successfully\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 lastMessage.status !== \"error\" &&\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 // `openai:` model strings default to the Responses API; pass a model instance to opt out.\n return initChatModel(\n this.#options.model,\n this.#options.model.startsWith(\"openai:\")\n ? { useResponsesApi: true }\n : undefined\n );\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 /**\n * If the model produced a terminal response (no tool calls) but the\n * output failed to satisfy the provider strategy's schema, throw an\n * informative error instead of silently exiting with\n * `structuredResponse: undefined`. If tool calls are present, the\n * agent loop continues and a subsequent terminal step will get\n * another chance to produce a valid structured response.\n */\n if (!response.tool_calls || response.tool_calls.length === 0) {\n const schemaTitle =\n typeof structuredResponseFormat.strategy.schema?.title === \"string\"\n ? structuredResponseFormat.strategy.schema.title\n : \"providerStrategy\";\n throw new StructuredOutputParsingError(\n schemaTitle,\n [\"Model output did not satisfy the provided response schema.\"],\n response\n );\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 * Track the exact values thrown by the inner handler so an error this\n * middleware merely propagated is not re-attributed to it as a\n * MiddlewareError. Mirrors `wrapToolCall` in utils.ts, so the\n * model-call and tool-call paths treat pass-through errors the same.\n */\n const downstreamErrors = new Set<unknown>();\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 let innerHandlerResult: InternalModelResponse<StructuredResponseFormat>;\n try {\n innerHandlerResult = await innerHandler(normalizedReq);\n } catch (error) {\n /**\n * The error was raised below this middleware and only propagated\n * through it. Record it so the outer catch re-throws it unchanged\n * instead of wrapping it as a failure of this middleware.\n */\n downstreamErrors.add(error);\n throw error;\n }\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 (\n isCommand(middlewareResponse) &&\n !collectedCommands.includes(middlewareResponse)\n ) {\n collectedCommands.push(middlewareResponse);\n }\n\n return middlewareResponse;\n } catch (error) {\n /**\n * An error the inner handler raised and this middleware only\n * re-threw keeps its identity, so `retryOn` and other consumers see\n * it as thrown. Errors originating in the middleware are wrapped so\n * MiddlewareError can still attribute the failure to it.\n */\n if (downstreamErrors.has(error)) {\n throw error;\n }\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\n /**\n * Don't force strict on tools: it makes Anthropic's combined grammar\n * \"too complex for compilation\", and only OpenAI Chat Completions needs\n * it (re-applied there). Honor an explicit override; else leave unset.\n */\n strict: preparedOptions?.modelSettings?.strict,\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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"}