@langchain/langgraph 1.4.0 → 1.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"tool_node.cjs","names":["isBaseMessage","RunnableCallable","isCommand","ToolMessage","isGraphInterrupt","Command","_isSend","END"],"sources":["../../src/prebuilt/tool_node.ts"],"sourcesContent":["import {\n BaseMessage,\n ToolMessage,\n AIMessage,\n isBaseMessage,\n isAIMessage,\n} from \"@langchain/core/messages\";\nimport { RunnableConfig, RunnableToolLike } from \"@langchain/core/runnables\";\nimport { DynamicTool, StructuredToolInterface } from \"@langchain/core/tools\";\nimport type { ToolCall } from \"@langchain/core/messages/tool\";\nimport { RunnableCallable } from \"../utils.js\";\nimport { MessagesAnnotation } from \"../graph/messages_annotation.js\";\nimport { isGraphInterrupt } from \"../errors.js\";\nimport { END, isCommand, Command, _isSend, Send } from \"../constants.js\";\n\nexport type ToolNodeOptions = {\n name?: string;\n tags?: string[];\n handleToolErrors?: boolean;\n};\n\nconst isBaseMessageArray = (input: unknown): input is BaseMessage[] =>\n Array.isArray(input) && input.every(isBaseMessage);\n\nconst isMessagesState = (\n input: unknown\n): input is { messages: BaseMessage[] } =>\n typeof input === \"object\" &&\n input != null &&\n \"messages\" in input &&\n isBaseMessageArray(input.messages);\n\nconst isSendInput = (input: unknown): input is { lg_tool_call: ToolCall } =>\n typeof input === \"object\" && input != null && \"lg_tool_call\" in input;\n\n/**\n * A node that runs the tools requested in the last AIMessage. It can be used\n * either in StateGraph with a \"messages\" key or in MessageGraph. If multiple\n * tool calls are requested, they will be run in parallel. The output will be\n * a list of ToolMessages, one for each tool call.\n *\n * @example\n * ```ts\n * import { ToolNode } from \"@langchain/langgraph/prebuilt\";\n * import { tool } from \"@langchain/core/tools\";\n * import { z } from \"zod\";\n * import { AIMessage } from \"@langchain/core/messages\";\n *\n * const getWeather = tool((input) => {\n * if ([\"sf\", \"san francisco\"].includes(input.location.toLowerCase())) {\n * return \"It's 60 degrees and foggy.\";\n * } else {\n * return \"It's 90 degrees and sunny.\";\n * }\n * }, {\n * name: \"get_weather\",\n * description: \"Call to get the current weather.\",\n * schema: z.object({\n * location: z.string().describe(\"Location to get the weather for.\"),\n * }),\n * });\n *\n * const tools = [getWeather];\n * const toolNode = new ToolNode(tools);\n *\n * const messageWithSingleToolCall = new AIMessage({\n * content: \"\",\n * tool_calls: [\n * {\n * name: \"get_weather\",\n * args: { location: \"sf\" },\n * id: \"tool_call_id\",\n * type: \"tool_call\",\n * }\n * ]\n * })\n *\n * await toolNode.invoke({ messages: [messageWithSingleToolCall] });\n * // Returns tool invocation responses as:\n * // { messages: ToolMessage[] }\n * ```\n *\n * @example\n * ```ts\n * import {\n * StateGraph,\n * MessagesAnnotation,\n * } from \"@langchain/langgraph\";\n * import { ToolNode } from \"@langchain/langgraph/prebuilt\";\n * import { tool } from \"@langchain/core/tools\";\n * import { z } from \"zod\";\n * import { ChatAnthropic } from \"@langchain/anthropic\";\n *\n * const getWeather = tool((input) => {\n * if ([\"sf\", \"san francisco\"].includes(input.location.toLowerCase())) {\n * return \"It's 60 degrees and foggy.\";\n * } else {\n * return \"It's 90 degrees and sunny.\";\n * }\n * }, {\n * name: \"get_weather\",\n * description: \"Call to get the current weather.\",\n * schema: z.object({\n * location: z.string().describe(\"Location to get the weather for.\"),\n * }),\n * });\n *\n * const tools = [getWeather];\n * const modelWithTools = new ChatAnthropic({\n * model: \"claude-3-haiku-20240307\",\n * temperature: 0\n * }).bindTools(tools);\n *\n * const toolNodeForGraph = new ToolNode(tools)\n *\n * const shouldContinue = (state: typeof MessagesAnnotation.State) => {\n * const { messages } = state;\n * const lastMessage = messages[messages.length - 1];\n * if (\"tool_calls\" in lastMessage && Array.isArray(lastMessage.tool_calls) && lastMessage.tool_calls?.length) {\n * return \"tools\";\n * }\n * return \"__end__\";\n * }\n *\n * const callModel = async (state: typeof MessagesAnnotation.State) => {\n * const { messages } = state;\n * const response = await modelWithTools.invoke(messages);\n * return { messages: response };\n * }\n *\n * const graph = new StateGraph(MessagesAnnotation)\n * .addNode(\"agent\", callModel)\n * .addNode(\"tools\", toolNodeForGraph)\n * .addEdge(\"__start__\", \"agent\")\n * .addConditionalEdges(\"agent\", shouldContinue)\n * .addEdge(\"tools\", \"agent\")\n * .compile();\n *\n * const inputs = {\n * messages: [{ role: \"user\", content: \"what is the weather in SF?\" }],\n * };\n *\n * const stream = await graph.stream(inputs, {\n * streamMode: \"values\",\n * });\n *\n * for await (const { messages } of stream) {\n * console.log(messages);\n * }\n * // Returns the messages in the state at each step of execution\n * ```\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport class ToolNode<T = any> extends RunnableCallable<T, T> {\n tools: (StructuredToolInterface | DynamicTool | RunnableToolLike)[];\n\n handleToolErrors = true;\n\n trace = false;\n\n constructor(\n tools: (StructuredToolInterface | DynamicTool | RunnableToolLike)[],\n options?: ToolNodeOptions\n ) {\n const { name, tags, handleToolErrors } = options ?? {};\n super({ name, tags, func: (input, config) => this.run(input, config) });\n this.tools = tools;\n this.handleToolErrors = handleToolErrors ?? this.handleToolErrors;\n }\n\n protected async runTool(\n call: ToolCall,\n config: RunnableConfig\n ): Promise<ToolMessage | Command> {\n const tool = this.tools.find((tool) => tool.name === call.name);\n try {\n if (tool === undefined) {\n throw new Error(`Tool \"${call.name}\" not found.`);\n }\n const output = await tool.invoke({ ...call, type: \"tool_call\" }, config);\n\n if (\n (isBaseMessage(output) && output.getType() === \"tool\") ||\n isCommand(output)\n ) {\n return output as ToolMessage | Command;\n }\n\n return new ToolMessage({\n status: \"success\",\n name: tool.name,\n content: typeof output === \"string\" ? output : JSON.stringify(output),\n tool_call_id: call.id!,\n });\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (e: any) {\n if (!this.handleToolErrors) throw e;\n\n if (isGraphInterrupt(e)) {\n // `NodeInterrupt` errors are a breakpoint to bring a human into the loop.\n // As such, they are not recoverable by the agent and shouldn't be fed\n // back. Instead, re-throw these errors even when `handleToolErrors = true`.\n throw e;\n }\n\n return new ToolMessage({\n status: \"error\",\n content: `Error: ${e.message}\\n Please fix your mistakes.`,\n name: call.name,\n tool_call_id: call.id ?? \"\",\n });\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n protected async run(input: unknown, config: RunnableConfig): Promise<T> {\n let outputs: (ToolMessage | Command)[];\n\n if (isSendInput(input)) {\n outputs = [await this.runTool(input.lg_tool_call, config)];\n } else {\n let messages: BaseMessage[];\n if (isBaseMessageArray(input)) {\n messages = input;\n } else if (isMessagesState(input)) {\n messages = input.messages;\n } else {\n throw new Error(\n \"ToolNode only accepts BaseMessage[] or { messages: BaseMessage[] } as input.\"\n );\n }\n\n const toolMessageIds: Set<string> = new Set(\n messages\n .filter((msg) => msg.getType() === \"tool\")\n .map((msg) => (msg as ToolMessage).tool_call_id)\n );\n\n let aiMessage: AIMessage | undefined;\n for (let i = messages.length - 1; i >= 0; i -= 1) {\n const message = messages[i];\n if (isAIMessage(message)) {\n aiMessage = message;\n break;\n }\n }\n\n if (aiMessage == null || !isAIMessage(aiMessage)) {\n throw new Error(\"ToolNode only accepts AIMessages as input.\");\n }\n\n outputs = await Promise.all(\n aiMessage.tool_calls\n ?.filter((call) => call.id == null || !toolMessageIds.has(call.id))\n .map((call) => this.runTool(call, config)) ?? []\n );\n }\n\n // Preserve existing behavior for non-command tool outputs for backwards compatibility\n if (!outputs.some(isCommand)) {\n return (Array.isArray(input) ? outputs : { messages: outputs }) as T;\n }\n\n // Handle mixed Command and non-Command outputs\n const combinedOutputs: (\n | { messages: BaseMessage[] }\n | BaseMessage[]\n | Command\n )[] = [];\n let parentCommand: Command | null = null;\n\n for (const output of outputs) {\n if (isCommand(output)) {\n if (\n output.graph === Command.PARENT &&\n Array.isArray(output.goto) &&\n output.goto.every((send) => _isSend(send))\n ) {\n if (parentCommand) {\n (parentCommand.goto as Send[]).push(...(output.goto as Send[]));\n } else {\n parentCommand = new Command({\n graph: Command.PARENT,\n goto: output.goto,\n });\n }\n } else {\n combinedOutputs.push(output);\n }\n } else {\n combinedOutputs.push(\n Array.isArray(input) ? [output] : { messages: [output] }\n );\n }\n }\n\n if (parentCommand) {\n combinedOutputs.push(parentCommand);\n }\n\n return combinedOutputs as T;\n }\n}\n\n/**\n * A conditional edge function that determines whether to route to a tools node or end the graph.\n *\n * This function is designed to be used as a conditional edge in a LangGraph state graph to implement\n * the common pattern of checking if an AI message contains tool calls that need to be executed.\n *\n * @param state - The current state of the graph, which can be either:\n * - An array of `BaseMessage` objects, where the last message is checked for tool calls\n * - A state object conforming to `MessagesAnnotation.State`, which contains a `messages` array\n *\n * @returns A string indicating the next node to route to:\n * - `\"tools\"` - If the last message contains tool calls that need to be executed\n * - `END` - If there are no tool calls, indicating the graph should terminate\n *\n * @example\n * ```typescript\n * import { StateGraph, MessagesAnnotation, END, START } from \"@langchain/langgraph\";\n * import { ToolNode, toolsCondition } from \"@langchain/langgraph/prebuilt\";\n *\n * const graph = new StateGraph(MessagesAnnotation)\n * .addNode(\"agent\", agentNode)\n * .addNode(\"tools\", new ToolNode([searchTool, calculatorTool]))\n * .addEdge(START, \"agent\")\n * .addConditionalEdges(\"agent\", toolsCondition, [\"tools\", END])\n * .addEdge(\"tools\", \"agent\")\n * .compile();\n * ```\n *\n * @remarks\n * The function checks the last message in the state for the presence of `tool_calls`.\n * If the message is an `AIMessage` with one or more tool calls, it returns `\"tools\"`,\n * indicating that the graph should route to a tools node (typically a `ToolNode`) to\n * execute those tool calls. Otherwise, it returns `END` to terminate the graph execution.\n *\n * This is a common pattern in agentic workflows where an AI model decides whether to\n * use tools or provide a final response.\n */\nexport function toolsCondition(\n state: BaseMessage[] | typeof MessagesAnnotation.State\n): \"tools\" | typeof END {\n const message = Array.isArray(state)\n ? state[state.length - 1]\n : state.messages[state.messages.length - 1];\n\n if (\n message !== undefined &&\n \"tool_calls\" in message &&\n ((message as AIMessage).tool_calls?.length ?? 0) > 0\n ) {\n return \"tools\";\n } else {\n return END;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"tool_node.cjs","names":["isBaseMessage","RunnableCallable","isCommand","ToolMessage","isGraphInterrupt","Command","_isSend","END"],"sources":["../../src/prebuilt/tool_node.ts"],"sourcesContent":["import {\n BaseMessage,\n ToolMessage,\n AIMessage,\n isBaseMessage,\n isAIMessage,\n} from \"@langchain/core/messages\";\nimport { RunnableToolLike } from \"@langchain/core/runnables\";\nimport {\n DynamicTool,\n StructuredToolInterface,\n type ToolRuntime,\n} from \"@langchain/core/tools\";\nimport type { ToolCall } from \"@langchain/core/messages/tool\";\nimport { RunnableCallable } from \"../utils.js\";\nimport { MessagesAnnotation } from \"../graph/messages_annotation.js\";\nimport { isGraphInterrupt } from \"../errors.js\";\nimport { END, isCommand, Command, _isSend, Send } from \"../constants.js\";\nimport type { LangGraphRunnableConfig } from \"../pregel/runnable_types.js\";\n\nexport type ToolNodeOptions = {\n name?: string;\n tags?: string[];\n handleToolErrors?: boolean;\n};\n\nconst isBaseMessageArray = (input: unknown): input is BaseMessage[] =>\n Array.isArray(input) && input.every(isBaseMessage);\n\nconst isMessagesState = (\n input: unknown\n): input is { messages: BaseMessage[] } =>\n typeof input === \"object\" &&\n input != null &&\n \"messages\" in input &&\n isBaseMessageArray(input.messages);\n\nconst isSendInput = (input: unknown): input is { lg_tool_call: ToolCall } =>\n typeof input === \"object\" && input != null && \"lg_tool_call\" in input;\n\n/**\n * A node that runs the tools requested in the last AIMessage. It can be used\n * either in StateGraph with a \"messages\" key or in MessageGraph. If multiple\n * tool calls are requested, they will be run in parallel. The output will be\n * a list of ToolMessages, one for each tool call.\n *\n * @example\n * ```ts\n * import { ToolNode } from \"@langchain/langgraph/prebuilt\";\n * import { tool } from \"@langchain/core/tools\";\n * import { z } from \"zod\";\n * import { AIMessage } from \"@langchain/core/messages\";\n *\n * const getWeather = tool((input) => {\n * if ([\"sf\", \"san francisco\"].includes(input.location.toLowerCase())) {\n * return \"It's 60 degrees and foggy.\";\n * } else {\n * return \"It's 90 degrees and sunny.\";\n * }\n * }, {\n * name: \"get_weather\",\n * description: \"Call to get the current weather.\",\n * schema: z.object({\n * location: z.string().describe(\"Location to get the weather for.\"),\n * }),\n * });\n *\n * const tools = [getWeather];\n * const toolNode = new ToolNode(tools);\n *\n * const messageWithSingleToolCall = new AIMessage({\n * content: \"\",\n * tool_calls: [\n * {\n * name: \"get_weather\",\n * args: { location: \"sf\" },\n * id: \"tool_call_id\",\n * type: \"tool_call\",\n * }\n * ]\n * })\n *\n * await toolNode.invoke({ messages: [messageWithSingleToolCall] });\n * // Returns tool invocation responses as:\n * // { messages: ToolMessage[] }\n * ```\n *\n * @example\n * ```ts\n * import {\n * StateGraph,\n * MessagesAnnotation,\n * } from \"@langchain/langgraph\";\n * import { ToolNode } from \"@langchain/langgraph/prebuilt\";\n * import { tool } from \"@langchain/core/tools\";\n * import { z } from \"zod\";\n * import { ChatAnthropic } from \"@langchain/anthropic\";\n *\n * const getWeather = tool((input) => {\n * if ([\"sf\", \"san francisco\"].includes(input.location.toLowerCase())) {\n * return \"It's 60 degrees and foggy.\";\n * } else {\n * return \"It's 90 degrees and sunny.\";\n * }\n * }, {\n * name: \"get_weather\",\n * description: \"Call to get the current weather.\",\n * schema: z.object({\n * location: z.string().describe(\"Location to get the weather for.\"),\n * }),\n * });\n *\n * const tools = [getWeather];\n * const modelWithTools = new ChatAnthropic({\n * model: \"claude-3-haiku-20240307\",\n * temperature: 0\n * }).bindTools(tools);\n *\n * const toolNodeForGraph = new ToolNode(tools)\n *\n * const shouldContinue = (state: typeof MessagesAnnotation.State) => {\n * const { messages } = state;\n * const lastMessage = messages[messages.length - 1];\n * if (\"tool_calls\" in lastMessage && Array.isArray(lastMessage.tool_calls) && lastMessage.tool_calls?.length) {\n * return \"tools\";\n * }\n * return \"__end__\";\n * }\n *\n * const callModel = async (state: typeof MessagesAnnotation.State) => {\n * const { messages } = state;\n * const response = await modelWithTools.invoke(messages);\n * return { messages: response };\n * }\n *\n * const graph = new StateGraph(MessagesAnnotation)\n * .addNode(\"agent\", callModel)\n * .addNode(\"tools\", toolNodeForGraph)\n * .addEdge(\"__start__\", \"agent\")\n * .addConditionalEdges(\"agent\", shouldContinue)\n * .addEdge(\"tools\", \"agent\")\n * .compile();\n *\n * const inputs = {\n * messages: [{ role: \"user\", content: \"what is the weather in SF?\" }],\n * };\n *\n * const stream = await graph.stream(inputs, {\n * streamMode: \"values\",\n * });\n *\n * for await (const { messages } of stream) {\n * console.log(messages);\n * }\n * // Returns the messages in the state at each step of execution\n * ```\n *\n * ### Accessing graph state and runtime context from tools\n *\n * Tools executed by a `ToolNode` only receive the arguments produced by the\n * model. To give a tool access to the surrounding graph state or other runtime\n * context, read them from the {@link ToolRuntime} that is passed as the\n * second argument to every tool:\n *\n * - `runtime.state` — the input the `ToolNode` was invoked with. When the\n * `ToolNode` runs as a graph node (e.g. inside `createReactAgent`), this is\n * the current graph state. This works in any runtime, including web browsers,\n * because it does not rely on `node:async_hooks`/`AsyncLocalStorage`.\n * - `runtime.config`, `runtime.context`, `runtime.store`, etc. — other\n * run-scoped values.\n *\n * @example\n * ```ts\n * import { ToolNode } from \"@langchain/langgraph/prebuilt\";\n * import { StateGraph, MessagesZodState } from \"@langchain/langgraph\";\n * import { tool, type ToolRuntime } from \"@langchain/core/tools\";\n * import { z } from \"zod\";\n *\n * // Define the graph state with a Zod schema. The extra `userId` key becomes\n * // part of the state that the ToolNode forwards to its tools via `runtime.state`.\n * const AgentState = z.object({\n * ...MessagesZodState.shape,\n * userId: z.string(),\n * });\n *\n * const getUserInfo = tool(\n * async (_input, runtime: ToolRuntime<typeof AgentState>) => {\n * // Read the current graph state directly from the second argument.\n * const userId = runtime.state.userId;\n * return userId === \"user_123\" ? \"User is John Smith\" : \"Unknown user\";\n * },\n * {\n * name: \"get_user_info\",\n * description: \"Look up user info.\",\n * schema: z.object({}),\n * }\n * );\n *\n * // Wire the ToolNode into a StateGraph that uses `AgentState`. Because the\n * // node runs with the graph state as its input, the tool can read `userId`.\n * const graph = new StateGraph(AgentState)\n * .addNode(\"tools\", new ToolNode([getUserInfo]))\n * .addEdge(\"__start__\", \"tools\")\n * .compile();\n *\n * await graph.invoke({ messages: [...], userId: \"user_123\" });\n * ```\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport class ToolNode<T = any> extends RunnableCallable<T, T> {\n tools: (StructuredToolInterface | DynamicTool | RunnableToolLike)[];\n\n handleToolErrors = true;\n\n trace = false;\n\n constructor(\n tools: (StructuredToolInterface | DynamicTool | RunnableToolLike)[],\n options?: ToolNodeOptions\n ) {\n const { name, tags, handleToolErrors } = options ?? {};\n super({ name, tags, func: (input, config) => this.run(input, config) });\n this.tools = tools;\n this.handleToolErrors = handleToolErrors ?? this.handleToolErrors;\n }\n\n protected async runTool(\n call: ToolCall,\n config: LangGraphRunnableConfig,\n state: unknown\n ): Promise<ToolMessage | Command> {\n const tool = this.tools.find((tool) => tool.name === call.name);\n try {\n if (tool === undefined) {\n throw new Error(`Tool \"${call.name}\" not found.`);\n }\n const toolCall = { ...call, type: \"tool_call\" } as ToolCall;\n const runtime: ToolRuntime = {\n ...config,\n state,\n toolCallId: call.id ?? \"\",\n config,\n context: config.context,\n store: (config.store as ToolRuntime[\"store\"] | undefined) ?? null,\n writer: config.writer ?? config.configurable?.writer ?? null,\n };\n const output = await tool.invoke(toolCall, runtime);\n\n if (\n (isBaseMessage(output) && output.getType() === \"tool\") ||\n isCommand(output)\n ) {\n return output as ToolMessage | Command;\n }\n\n return new ToolMessage({\n status: \"success\",\n name: tool.name,\n content: typeof output === \"string\" ? output : JSON.stringify(output),\n tool_call_id: call.id!,\n });\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (e: any) {\n if (!this.handleToolErrors) throw e;\n\n if (isGraphInterrupt(e)) {\n // `NodeInterrupt` errors are a breakpoint to bring a human into the loop.\n // As such, they are not recoverable by the agent and shouldn't be fed\n // back. Instead, re-throw these errors even when `handleToolErrors = true`.\n throw e;\n }\n\n return new ToolMessage({\n status: \"error\",\n content: `Error: ${e.message}\\n Please fix your mistakes.`,\n name: call.name,\n tool_call_id: call.id ?? \"\",\n });\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n protected async run(\n input: unknown,\n config: LangGraphRunnableConfig\n ): Promise<T> {\n let outputs: (ToolMessage | Command)[];\n\n if (isSendInput(input)) {\n // Drop the internal `lg_tool_call` routing key so tools only see state.\n const { lg_tool_call: toolCall, ...state } = input as {\n lg_tool_call: ToolCall;\n } & Record<string, unknown>;\n outputs = [await this.runTool(toolCall, config, state)];\n } else {\n let messages: BaseMessage[];\n if (isBaseMessageArray(input)) {\n messages = input;\n } else if (isMessagesState(input)) {\n messages = input.messages;\n } else {\n throw new Error(\n \"ToolNode only accepts BaseMessage[] or { messages: BaseMessage[] } as input.\"\n );\n }\n\n const toolMessageIds: Set<string> = new Set(\n messages\n .filter((msg) => msg.getType() === \"tool\")\n .map((msg) => (msg as ToolMessage).tool_call_id)\n );\n\n let aiMessage: AIMessage | undefined;\n for (let i = messages.length - 1; i >= 0; i -= 1) {\n const message = messages[i];\n if (isAIMessage(message)) {\n aiMessage = message;\n break;\n }\n }\n\n if (aiMessage == null || !isAIMessage(aiMessage)) {\n throw new Error(\"ToolNode only accepts AIMessages as input.\");\n }\n\n outputs = await Promise.all(\n aiMessage.tool_calls\n ?.filter((call) => call.id == null || !toolMessageIds.has(call.id))\n .map((call) => this.runTool(call, config, input)) ?? []\n );\n }\n\n // Preserve existing behavior for non-command tool outputs for backwards compatibility\n if (!outputs.some(isCommand)) {\n return (Array.isArray(input) ? outputs : { messages: outputs }) as T;\n }\n\n // Handle mixed Command and non-Command outputs\n const combinedOutputs: (\n | { messages: BaseMessage[] }\n | BaseMessage[]\n | Command\n )[] = [];\n let parentCommand: Command | null = null;\n\n for (const output of outputs) {\n if (isCommand(output)) {\n if (\n output.graph === Command.PARENT &&\n Array.isArray(output.goto) &&\n output.goto.every((send) => _isSend(send))\n ) {\n if (parentCommand) {\n (parentCommand.goto as Send[]).push(...(output.goto as Send[]));\n } else {\n parentCommand = new Command({\n graph: Command.PARENT,\n goto: output.goto,\n });\n }\n } else {\n combinedOutputs.push(output);\n }\n } else {\n combinedOutputs.push(\n Array.isArray(input) ? [output] : { messages: [output] }\n );\n }\n }\n\n if (parentCommand) {\n combinedOutputs.push(parentCommand);\n }\n\n return combinedOutputs as T;\n }\n}\n\n/**\n * A conditional edge function that determines whether to route to a tools node or end the graph.\n *\n * This function is designed to be used as a conditional edge in a LangGraph state graph to implement\n * the common pattern of checking if an AI message contains tool calls that need to be executed.\n *\n * @param state - The current state of the graph, which can be either:\n * - An array of `BaseMessage` objects, where the last message is checked for tool calls\n * - A state object conforming to `MessagesAnnotation.State`, which contains a `messages` array\n *\n * @returns A string indicating the next node to route to:\n * - `\"tools\"` - If the last message contains tool calls that need to be executed\n * - `END` - If there are no tool calls, indicating the graph should terminate\n *\n * @example\n * ```typescript\n * import { StateGraph, MessagesAnnotation, END, START } from \"@langchain/langgraph\";\n * import { ToolNode, toolsCondition } from \"@langchain/langgraph/prebuilt\";\n *\n * const graph = new StateGraph(MessagesAnnotation)\n * .addNode(\"agent\", agentNode)\n * .addNode(\"tools\", new ToolNode([searchTool, calculatorTool]))\n * .addEdge(START, \"agent\")\n * .addConditionalEdges(\"agent\", toolsCondition, [\"tools\", END])\n * .addEdge(\"tools\", \"agent\")\n * .compile();\n * ```\n *\n * @remarks\n * The function checks the last message in the state for the presence of `tool_calls`.\n * If the message is an `AIMessage` with one or more tool calls, it returns `\"tools\"`,\n * indicating that the graph should route to a tools node (typically a `ToolNode`) to\n * execute those tool calls. Otherwise, it returns `END` to terminate the graph execution.\n *\n * This is a common pattern in agentic workflows where an AI model decides whether to\n * use tools or provide a final response.\n */\nexport function toolsCondition(\n state: BaseMessage[] | typeof MessagesAnnotation.State\n): \"tools\" | typeof END {\n const message = Array.isArray(state)\n ? state[state.length - 1]\n : state.messages[state.messages.length - 1];\n\n if (\n message !== undefined &&\n \"tool_calls\" in message &&\n ((message as AIMessage).tool_calls?.length ?? 0) > 0\n ) {\n return \"tools\";\n } else {\n return END;\n }\n}\n"],"mappings":"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"}
@@ -1,7 +1,8 @@
1
1
  import { Command, END } from "../constants.cjs";
2
+ import { LangGraphRunnableConfig } from "../pregel/runnable_types.cjs";
2
3
  import { RunnableCallable } from "../utils.cjs";
3
4
  import { MessagesAnnotation } from "../graph/messages_annotation.cjs";
4
- import { RunnableConfig, RunnableToolLike } from "@langchain/core/runnables";
5
+ import { RunnableToolLike } from "@langchain/core/runnables";
5
6
  import { BaseMessage, ToolMessage } from "@langchain/core/messages";
6
7
  import { DynamicTool, StructuredToolInterface } from "@langchain/core/tools";
7
8
  import { ToolCall } from "@langchain/core/messages/tool";
@@ -128,14 +129,65 @@ type ToolNodeOptions = {
128
129
  * }
129
130
  * // Returns the messages in the state at each step of execution
130
131
  * ```
132
+ *
133
+ * ### Accessing graph state and runtime context from tools
134
+ *
135
+ * Tools executed by a `ToolNode` only receive the arguments produced by the
136
+ * model. To give a tool access to the surrounding graph state or other runtime
137
+ * context, read them from the {@link ToolRuntime} that is passed as the
138
+ * second argument to every tool:
139
+ *
140
+ * - `runtime.state` — the input the `ToolNode` was invoked with. When the
141
+ * `ToolNode` runs as a graph node (e.g. inside `createReactAgent`), this is
142
+ * the current graph state. This works in any runtime, including web browsers,
143
+ * because it does not rely on `node:async_hooks`/`AsyncLocalStorage`.
144
+ * - `runtime.config`, `runtime.context`, `runtime.store`, etc. — other
145
+ * run-scoped values.
146
+ *
147
+ * @example
148
+ * ```ts
149
+ * import { ToolNode } from "@langchain/langgraph/prebuilt";
150
+ * import { StateGraph, MessagesZodState } from "@langchain/langgraph";
151
+ * import { tool, type ToolRuntime } from "@langchain/core/tools";
152
+ * import { z } from "zod";
153
+ *
154
+ * // Define the graph state with a Zod schema. The extra `userId` key becomes
155
+ * // part of the state that the ToolNode forwards to its tools via `runtime.state`.
156
+ * const AgentState = z.object({
157
+ * ...MessagesZodState.shape,
158
+ * userId: z.string(),
159
+ * });
160
+ *
161
+ * const getUserInfo = tool(
162
+ * async (_input, runtime: ToolRuntime<typeof AgentState>) => {
163
+ * // Read the current graph state directly from the second argument.
164
+ * const userId = runtime.state.userId;
165
+ * return userId === "user_123" ? "User is John Smith" : "Unknown user";
166
+ * },
167
+ * {
168
+ * name: "get_user_info",
169
+ * description: "Look up user info.",
170
+ * schema: z.object({}),
171
+ * }
172
+ * );
173
+ *
174
+ * // Wire the ToolNode into a StateGraph that uses `AgentState`. Because the
175
+ * // node runs with the graph state as its input, the tool can read `userId`.
176
+ * const graph = new StateGraph(AgentState)
177
+ * .addNode("tools", new ToolNode([getUserInfo]))
178
+ * .addEdge("__start__", "tools")
179
+ * .compile();
180
+ *
181
+ * await graph.invoke({ messages: [...], userId: "user_123" });
182
+ * ```
131
183
  */
132
184
  declare class ToolNode<T = any> extends RunnableCallable<T, T> {
133
185
  tools: (StructuredToolInterface | DynamicTool | RunnableToolLike)[];
134
186
  handleToolErrors: boolean;
135
187
  trace: boolean;
136
188
  constructor(tools: (StructuredToolInterface | DynamicTool | RunnableToolLike)[], options?: ToolNodeOptions);
137
- protected runTool(call: ToolCall, config: RunnableConfig): Promise<ToolMessage | Command>;
138
- protected run(input: unknown, config: RunnableConfig): Promise<T>;
189
+ protected runTool(call: ToolCall, config: LangGraphRunnableConfig, state: unknown): Promise<ToolMessage | Command>;
190
+ protected run(input: unknown, config: LangGraphRunnableConfig): Promise<T>;
139
191
  }
140
192
  /**
141
193
  * A conditional edge function that determines whether to route to a tools node or end the graph.
@@ -1 +1 @@
1
- {"version":3,"file":"tool_node.d.cts","names":[],"sources":["../../src/prebuilt/tool_node.ts"],"mappings":";;;;;;;;;KAeY,eAAA;EACV,IAAA;EACA,IAAA;EACA,gBAAA;AAAA;;;;;;;AAuIF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4LA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cA5La,QAAA,kBAA0B,gBAAA,CAAiB,CAAA,EAAG,CAAA;EACzD,KAAA,GAAQ,uBAAA,GAA0B,WAAA,GAAc,gBAAA;EAEhD,gBAAA;EAEA,KAAA;EAEA,WAAA,CACE,KAAA,GAAQ,uBAAA,GAA0B,WAAA,GAAc,gBAAA,KAChD,OAAA,GAAU,eAAA;EAAA,UAQI,OAAA,CACd,IAAA,EAAM,QAAA,EACN,MAAA,EAAQ,cAAA,GACP,OAAA,CAAQ,WAAA,GAAc,OAAA;EAAA,UA0CT,GAAA,CAAI,KAAA,WAAgB,MAAA,EAAQ,cAAA,GAAiB,OAAA,CAAQ,CAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA8HvD,cAAA,CACd,KAAA,EAAO,WAAA,YAAuB,kBAAA,CAAmB,KAAA,oBAC/B,GAAA"}
1
+ {"version":3,"file":"tool_node.d.cts","names":[],"sources":["../../src/prebuilt/tool_node.ts"],"mappings":";;;;;;;;;;KAoBY,eAAA;EACV,IAAA;EACA,IAAA;EACA,gBAAA;AAAA;;;;;;;AA0LF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8MA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cA9Ma,QAAA,kBAA0B,gBAAA,CAAiB,CAAA,EAAG,CAAA;EACzD,KAAA,GAAQ,uBAAA,GAA0B,WAAA,GAAc,gBAAA;EAEhD,gBAAA;EAEA,KAAA;EAEA,WAAA,CACE,KAAA,GAAQ,uBAAA,GAA0B,WAAA,GAAc,gBAAA,KAChD,OAAA,GAAU,eAAA;EAAA,UAQI,OAAA,CACd,IAAA,EAAM,QAAA,EACN,MAAA,EAAQ,uBAAA,EACR,KAAA,YACC,OAAA,CAAQ,WAAA,GAAc,OAAA;EAAA,UAoDT,GAAA,CACd,KAAA,WACA,MAAA,EAAQ,uBAAA,GACP,OAAA,CAAQ,CAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAkIG,cAAA,CACd,KAAA,EAAO,WAAA,YAAuB,kBAAA,CAAmB,KAAA,oBAC/B,GAAA"}
@@ -1,7 +1,8 @@
1
1
  import { Command, END } from "../constants.js";
2
+ import { LangGraphRunnableConfig } from "../pregel/runnable_types.js";
2
3
  import { RunnableCallable } from "../utils.js";
3
4
  import { MessagesAnnotation } from "../graph/messages_annotation.js";
4
- import { RunnableConfig, RunnableToolLike } from "@langchain/core/runnables";
5
+ import { RunnableToolLike } from "@langchain/core/runnables";
5
6
  import { BaseMessage, ToolMessage } from "@langchain/core/messages";
6
7
  import { DynamicTool, StructuredToolInterface } from "@langchain/core/tools";
7
8
  import { ToolCall } from "@langchain/core/messages/tool";
@@ -128,14 +129,65 @@ type ToolNodeOptions = {
128
129
  * }
129
130
  * // Returns the messages in the state at each step of execution
130
131
  * ```
132
+ *
133
+ * ### Accessing graph state and runtime context from tools
134
+ *
135
+ * Tools executed by a `ToolNode` only receive the arguments produced by the
136
+ * model. To give a tool access to the surrounding graph state or other runtime
137
+ * context, read them from the {@link ToolRuntime} that is passed as the
138
+ * second argument to every tool:
139
+ *
140
+ * - `runtime.state` — the input the `ToolNode` was invoked with. When the
141
+ * `ToolNode` runs as a graph node (e.g. inside `createReactAgent`), this is
142
+ * the current graph state. This works in any runtime, including web browsers,
143
+ * because it does not rely on `node:async_hooks`/`AsyncLocalStorage`.
144
+ * - `runtime.config`, `runtime.context`, `runtime.store`, etc. — other
145
+ * run-scoped values.
146
+ *
147
+ * @example
148
+ * ```ts
149
+ * import { ToolNode } from "@langchain/langgraph/prebuilt";
150
+ * import { StateGraph, MessagesZodState } from "@langchain/langgraph";
151
+ * import { tool, type ToolRuntime } from "@langchain/core/tools";
152
+ * import { z } from "zod";
153
+ *
154
+ * // Define the graph state with a Zod schema. The extra `userId` key becomes
155
+ * // part of the state that the ToolNode forwards to its tools via `runtime.state`.
156
+ * const AgentState = z.object({
157
+ * ...MessagesZodState.shape,
158
+ * userId: z.string(),
159
+ * });
160
+ *
161
+ * const getUserInfo = tool(
162
+ * async (_input, runtime: ToolRuntime<typeof AgentState>) => {
163
+ * // Read the current graph state directly from the second argument.
164
+ * const userId = runtime.state.userId;
165
+ * return userId === "user_123" ? "User is John Smith" : "Unknown user";
166
+ * },
167
+ * {
168
+ * name: "get_user_info",
169
+ * description: "Look up user info.",
170
+ * schema: z.object({}),
171
+ * }
172
+ * );
173
+ *
174
+ * // Wire the ToolNode into a StateGraph that uses `AgentState`. Because the
175
+ * // node runs with the graph state as its input, the tool can read `userId`.
176
+ * const graph = new StateGraph(AgentState)
177
+ * .addNode("tools", new ToolNode([getUserInfo]))
178
+ * .addEdge("__start__", "tools")
179
+ * .compile();
180
+ *
181
+ * await graph.invoke({ messages: [...], userId: "user_123" });
182
+ * ```
131
183
  */
132
184
  declare class ToolNode<T = any> extends RunnableCallable<T, T> {
133
185
  tools: (StructuredToolInterface | DynamicTool | RunnableToolLike)[];
134
186
  handleToolErrors: boolean;
135
187
  trace: boolean;
136
188
  constructor(tools: (StructuredToolInterface | DynamicTool | RunnableToolLike)[], options?: ToolNodeOptions);
137
- protected runTool(call: ToolCall, config: RunnableConfig): Promise<ToolMessage | Command>;
138
- protected run(input: unknown, config: RunnableConfig): Promise<T>;
189
+ protected runTool(call: ToolCall, config: LangGraphRunnableConfig, state: unknown): Promise<ToolMessage | Command>;
190
+ protected run(input: unknown, config: LangGraphRunnableConfig): Promise<T>;
139
191
  }
140
192
  /**
141
193
  * A conditional edge function that determines whether to route to a tools node or end the graph.
@@ -1 +1 @@
1
- {"version":3,"file":"tool_node.d.ts","names":[],"sources":["../../src/prebuilt/tool_node.ts"],"mappings":";;;;;;;;;KAeY,eAAA;EACV,IAAA;EACA,IAAA;EACA,gBAAA;AAAA;;;;;;;AAuIF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4LA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cA5La,QAAA,kBAA0B,gBAAA,CAAiB,CAAA,EAAG,CAAA;EACzD,KAAA,GAAQ,uBAAA,GAA0B,WAAA,GAAc,gBAAA;EAEhD,gBAAA;EAEA,KAAA;EAEA,WAAA,CACE,KAAA,GAAQ,uBAAA,GAA0B,WAAA,GAAc,gBAAA,KAChD,OAAA,GAAU,eAAA;EAAA,UAQI,OAAA,CACd,IAAA,EAAM,QAAA,EACN,MAAA,EAAQ,cAAA,GACP,OAAA,CAAQ,WAAA,GAAc,OAAA;EAAA,UA0CT,GAAA,CAAI,KAAA,WAAgB,MAAA,EAAQ,cAAA,GAAiB,OAAA,CAAQ,CAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBA8HvD,cAAA,CACd,KAAA,EAAO,WAAA,YAAuB,kBAAA,CAAmB,KAAA,oBAC/B,GAAA"}
1
+ {"version":3,"file":"tool_node.d.ts","names":[],"sources":["../../src/prebuilt/tool_node.ts"],"mappings":";;;;;;;;;;KAoBY,eAAA;EACV,IAAA;EACA,IAAA;EACA,gBAAA;AAAA;;;;;;;AA0LF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8MA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cA9Ma,QAAA,kBAA0B,gBAAA,CAAiB,CAAA,EAAG,CAAA;EACzD,KAAA,GAAQ,uBAAA,GAA0B,WAAA,GAAc,gBAAA;EAEhD,gBAAA;EAEA,KAAA;EAEA,WAAA,CACE,KAAA,GAAQ,uBAAA,GAA0B,WAAA,GAAc,gBAAA,KAChD,OAAA,GAAU,eAAA;EAAA,UAQI,OAAA,CACd,IAAA,EAAM,QAAA,EACN,MAAA,EAAQ,uBAAA,EACR,KAAA,YACC,OAAA,CAAQ,WAAA,GAAc,OAAA;EAAA,UAoDT,GAAA,CACd,KAAA,WACA,MAAA,EAAQ,uBAAA,GACP,OAAA,CAAQ,CAAA;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;iBAkIG,cAAA,CACd,KAAA,EAAO,WAAA,YAAuB,kBAAA,CAAmB,KAAA,oBAC/B,GAAA"}
@@ -122,6 +122,57 @@ const isSendInput = (input) => typeof input === "object" && input != null && "lg
122
122
  * }
123
123
  * // Returns the messages in the state at each step of execution
124
124
  * ```
125
+ *
126
+ * ### Accessing graph state and runtime context from tools
127
+ *
128
+ * Tools executed by a `ToolNode` only receive the arguments produced by the
129
+ * model. To give a tool access to the surrounding graph state or other runtime
130
+ * context, read them from the {@link ToolRuntime} that is passed as the
131
+ * second argument to every tool:
132
+ *
133
+ * - `runtime.state` — the input the `ToolNode` was invoked with. When the
134
+ * `ToolNode` runs as a graph node (e.g. inside `createReactAgent`), this is
135
+ * the current graph state. This works in any runtime, including web browsers,
136
+ * because it does not rely on `node:async_hooks`/`AsyncLocalStorage`.
137
+ * - `runtime.config`, `runtime.context`, `runtime.store`, etc. — other
138
+ * run-scoped values.
139
+ *
140
+ * @example
141
+ * ```ts
142
+ * import { ToolNode } from "@langchain/langgraph/prebuilt";
143
+ * import { StateGraph, MessagesZodState } from "@langchain/langgraph";
144
+ * import { tool, type ToolRuntime } from "@langchain/core/tools";
145
+ * import { z } from "zod";
146
+ *
147
+ * // Define the graph state with a Zod schema. The extra `userId` key becomes
148
+ * // part of the state that the ToolNode forwards to its tools via `runtime.state`.
149
+ * const AgentState = z.object({
150
+ * ...MessagesZodState.shape,
151
+ * userId: z.string(),
152
+ * });
153
+ *
154
+ * const getUserInfo = tool(
155
+ * async (_input, runtime: ToolRuntime<typeof AgentState>) => {
156
+ * // Read the current graph state directly from the second argument.
157
+ * const userId = runtime.state.userId;
158
+ * return userId === "user_123" ? "User is John Smith" : "Unknown user";
159
+ * },
160
+ * {
161
+ * name: "get_user_info",
162
+ * description: "Look up user info.",
163
+ * schema: z.object({}),
164
+ * }
165
+ * );
166
+ *
167
+ * // Wire the ToolNode into a StateGraph that uses `AgentState`. Because the
168
+ * // node runs with the graph state as its input, the tool can read `userId`.
169
+ * const graph = new StateGraph(AgentState)
170
+ * .addNode("tools", new ToolNode([getUserInfo]))
171
+ * .addEdge("__start__", "tools")
172
+ * .compile();
173
+ *
174
+ * await graph.invoke({ messages: [...], userId: "user_123" });
175
+ * ```
125
176
  */
126
177
  var ToolNode = class extends RunnableCallable {
127
178
  tools;
@@ -137,14 +188,24 @@ var ToolNode = class extends RunnableCallable {
137
188
  this.tools = tools;
138
189
  this.handleToolErrors = handleToolErrors ?? this.handleToolErrors;
139
190
  }
140
- async runTool(call, config) {
191
+ async runTool(call, config, state) {
141
192
  const tool = this.tools.find((tool) => tool.name === call.name);
142
193
  try {
143
194
  if (tool === void 0) throw new Error(`Tool "${call.name}" not found.`);
144
- const output = await tool.invoke({
195
+ const toolCall = {
145
196
  ...call,
146
197
  type: "tool_call"
147
- }, config);
198
+ };
199
+ const runtime = {
200
+ ...config,
201
+ state,
202
+ toolCallId: call.id ?? "",
203
+ config,
204
+ context: config.context,
205
+ store: config.store ?? null,
206
+ writer: config.writer ?? config.configurable?.writer ?? null
207
+ };
208
+ const output = await tool.invoke(toolCall, runtime);
148
209
  if (isBaseMessage(output) && output.getType() === "tool" || isCommand(output)) return output;
149
210
  return new ToolMessage({
150
211
  status: "success",
@@ -165,8 +226,10 @@ var ToolNode = class extends RunnableCallable {
165
226
  }
166
227
  async run(input, config) {
167
228
  let outputs;
168
- if (isSendInput(input)) outputs = [await this.runTool(input.lg_tool_call, config)];
169
- else {
229
+ if (isSendInput(input)) {
230
+ const { lg_tool_call: toolCall, ...state } = input;
231
+ outputs = [await this.runTool(toolCall, config, state)];
232
+ } else {
170
233
  let messages;
171
234
  if (isBaseMessageArray(input)) messages = input;
172
235
  else if (isMessagesState(input)) messages = input.messages;
@@ -181,7 +244,7 @@ var ToolNode = class extends RunnableCallable {
181
244
  }
182
245
  }
183
246
  if (aiMessage == null || !isAIMessage(aiMessage)) throw new Error("ToolNode only accepts AIMessages as input.");
184
- outputs = await Promise.all(aiMessage.tool_calls?.filter((call) => call.id == null || !toolMessageIds.has(call.id)).map((call) => this.runTool(call, config)) ?? []);
247
+ outputs = await Promise.all(aiMessage.tool_calls?.filter((call) => call.id == null || !toolMessageIds.has(call.id)).map((call) => this.runTool(call, config, input)) ?? []);
185
248
  }
186
249
  if (!outputs.some(isCommand)) return Array.isArray(input) ? outputs : { messages: outputs };
187
250
  const combinedOutputs = [];
@@ -1 +1 @@
1
- {"version":3,"file":"tool_node.js","names":[],"sources":["../../src/prebuilt/tool_node.ts"],"sourcesContent":["import {\n BaseMessage,\n ToolMessage,\n AIMessage,\n isBaseMessage,\n isAIMessage,\n} from \"@langchain/core/messages\";\nimport { RunnableConfig, RunnableToolLike } from \"@langchain/core/runnables\";\nimport { DynamicTool, StructuredToolInterface } from \"@langchain/core/tools\";\nimport type { ToolCall } from \"@langchain/core/messages/tool\";\nimport { RunnableCallable } from \"../utils.js\";\nimport { MessagesAnnotation } from \"../graph/messages_annotation.js\";\nimport { isGraphInterrupt } from \"../errors.js\";\nimport { END, isCommand, Command, _isSend, Send } from \"../constants.js\";\n\nexport type ToolNodeOptions = {\n name?: string;\n tags?: string[];\n handleToolErrors?: boolean;\n};\n\nconst isBaseMessageArray = (input: unknown): input is BaseMessage[] =>\n Array.isArray(input) && input.every(isBaseMessage);\n\nconst isMessagesState = (\n input: unknown\n): input is { messages: BaseMessage[] } =>\n typeof input === \"object\" &&\n input != null &&\n \"messages\" in input &&\n isBaseMessageArray(input.messages);\n\nconst isSendInput = (input: unknown): input is { lg_tool_call: ToolCall } =>\n typeof input === \"object\" && input != null && \"lg_tool_call\" in input;\n\n/**\n * A node that runs the tools requested in the last AIMessage. It can be used\n * either in StateGraph with a \"messages\" key or in MessageGraph. If multiple\n * tool calls are requested, they will be run in parallel. The output will be\n * a list of ToolMessages, one for each tool call.\n *\n * @example\n * ```ts\n * import { ToolNode } from \"@langchain/langgraph/prebuilt\";\n * import { tool } from \"@langchain/core/tools\";\n * import { z } from \"zod\";\n * import { AIMessage } from \"@langchain/core/messages\";\n *\n * const getWeather = tool((input) => {\n * if ([\"sf\", \"san francisco\"].includes(input.location.toLowerCase())) {\n * return \"It's 60 degrees and foggy.\";\n * } else {\n * return \"It's 90 degrees and sunny.\";\n * }\n * }, {\n * name: \"get_weather\",\n * description: \"Call to get the current weather.\",\n * schema: z.object({\n * location: z.string().describe(\"Location to get the weather for.\"),\n * }),\n * });\n *\n * const tools = [getWeather];\n * const toolNode = new ToolNode(tools);\n *\n * const messageWithSingleToolCall = new AIMessage({\n * content: \"\",\n * tool_calls: [\n * {\n * name: \"get_weather\",\n * args: { location: \"sf\" },\n * id: \"tool_call_id\",\n * type: \"tool_call\",\n * }\n * ]\n * })\n *\n * await toolNode.invoke({ messages: [messageWithSingleToolCall] });\n * // Returns tool invocation responses as:\n * // { messages: ToolMessage[] }\n * ```\n *\n * @example\n * ```ts\n * import {\n * StateGraph,\n * MessagesAnnotation,\n * } from \"@langchain/langgraph\";\n * import { ToolNode } from \"@langchain/langgraph/prebuilt\";\n * import { tool } from \"@langchain/core/tools\";\n * import { z } from \"zod\";\n * import { ChatAnthropic } from \"@langchain/anthropic\";\n *\n * const getWeather = tool((input) => {\n * if ([\"sf\", \"san francisco\"].includes(input.location.toLowerCase())) {\n * return \"It's 60 degrees and foggy.\";\n * } else {\n * return \"It's 90 degrees and sunny.\";\n * }\n * }, {\n * name: \"get_weather\",\n * description: \"Call to get the current weather.\",\n * schema: z.object({\n * location: z.string().describe(\"Location to get the weather for.\"),\n * }),\n * });\n *\n * const tools = [getWeather];\n * const modelWithTools = new ChatAnthropic({\n * model: \"claude-3-haiku-20240307\",\n * temperature: 0\n * }).bindTools(tools);\n *\n * const toolNodeForGraph = new ToolNode(tools)\n *\n * const shouldContinue = (state: typeof MessagesAnnotation.State) => {\n * const { messages } = state;\n * const lastMessage = messages[messages.length - 1];\n * if (\"tool_calls\" in lastMessage && Array.isArray(lastMessage.tool_calls) && lastMessage.tool_calls?.length) {\n * return \"tools\";\n * }\n * return \"__end__\";\n * }\n *\n * const callModel = async (state: typeof MessagesAnnotation.State) => {\n * const { messages } = state;\n * const response = await modelWithTools.invoke(messages);\n * return { messages: response };\n * }\n *\n * const graph = new StateGraph(MessagesAnnotation)\n * .addNode(\"agent\", callModel)\n * .addNode(\"tools\", toolNodeForGraph)\n * .addEdge(\"__start__\", \"agent\")\n * .addConditionalEdges(\"agent\", shouldContinue)\n * .addEdge(\"tools\", \"agent\")\n * .compile();\n *\n * const inputs = {\n * messages: [{ role: \"user\", content: \"what is the weather in SF?\" }],\n * };\n *\n * const stream = await graph.stream(inputs, {\n * streamMode: \"values\",\n * });\n *\n * for await (const { messages } of stream) {\n * console.log(messages);\n * }\n * // Returns the messages in the state at each step of execution\n * ```\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport class ToolNode<T = any> extends RunnableCallable<T, T> {\n tools: (StructuredToolInterface | DynamicTool | RunnableToolLike)[];\n\n handleToolErrors = true;\n\n trace = false;\n\n constructor(\n tools: (StructuredToolInterface | DynamicTool | RunnableToolLike)[],\n options?: ToolNodeOptions\n ) {\n const { name, tags, handleToolErrors } = options ?? {};\n super({ name, tags, func: (input, config) => this.run(input, config) });\n this.tools = tools;\n this.handleToolErrors = handleToolErrors ?? this.handleToolErrors;\n }\n\n protected async runTool(\n call: ToolCall,\n config: RunnableConfig\n ): Promise<ToolMessage | Command> {\n const tool = this.tools.find((tool) => tool.name === call.name);\n try {\n if (tool === undefined) {\n throw new Error(`Tool \"${call.name}\" not found.`);\n }\n const output = await tool.invoke({ ...call, type: \"tool_call\" }, config);\n\n if (\n (isBaseMessage(output) && output.getType() === \"tool\") ||\n isCommand(output)\n ) {\n return output as ToolMessage | Command;\n }\n\n return new ToolMessage({\n status: \"success\",\n name: tool.name,\n content: typeof output === \"string\" ? output : JSON.stringify(output),\n tool_call_id: call.id!,\n });\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (e: any) {\n if (!this.handleToolErrors) throw e;\n\n if (isGraphInterrupt(e)) {\n // `NodeInterrupt` errors are a breakpoint to bring a human into the loop.\n // As such, they are not recoverable by the agent and shouldn't be fed\n // back. Instead, re-throw these errors even when `handleToolErrors = true`.\n throw e;\n }\n\n return new ToolMessage({\n status: \"error\",\n content: `Error: ${e.message}\\n Please fix your mistakes.`,\n name: call.name,\n tool_call_id: call.id ?? \"\",\n });\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n protected async run(input: unknown, config: RunnableConfig): Promise<T> {\n let outputs: (ToolMessage | Command)[];\n\n if (isSendInput(input)) {\n outputs = [await this.runTool(input.lg_tool_call, config)];\n } else {\n let messages: BaseMessage[];\n if (isBaseMessageArray(input)) {\n messages = input;\n } else if (isMessagesState(input)) {\n messages = input.messages;\n } else {\n throw new Error(\n \"ToolNode only accepts BaseMessage[] or { messages: BaseMessage[] } as input.\"\n );\n }\n\n const toolMessageIds: Set<string> = new Set(\n messages\n .filter((msg) => msg.getType() === \"tool\")\n .map((msg) => (msg as ToolMessage).tool_call_id)\n );\n\n let aiMessage: AIMessage | undefined;\n for (let i = messages.length - 1; i >= 0; i -= 1) {\n const message = messages[i];\n if (isAIMessage(message)) {\n aiMessage = message;\n break;\n }\n }\n\n if (aiMessage == null || !isAIMessage(aiMessage)) {\n throw new Error(\"ToolNode only accepts AIMessages as input.\");\n }\n\n outputs = await Promise.all(\n aiMessage.tool_calls\n ?.filter((call) => call.id == null || !toolMessageIds.has(call.id))\n .map((call) => this.runTool(call, config)) ?? []\n );\n }\n\n // Preserve existing behavior for non-command tool outputs for backwards compatibility\n if (!outputs.some(isCommand)) {\n return (Array.isArray(input) ? outputs : { messages: outputs }) as T;\n }\n\n // Handle mixed Command and non-Command outputs\n const combinedOutputs: (\n | { messages: BaseMessage[] }\n | BaseMessage[]\n | Command\n )[] = [];\n let parentCommand: Command | null = null;\n\n for (const output of outputs) {\n if (isCommand(output)) {\n if (\n output.graph === Command.PARENT &&\n Array.isArray(output.goto) &&\n output.goto.every((send) => _isSend(send))\n ) {\n if (parentCommand) {\n (parentCommand.goto as Send[]).push(...(output.goto as Send[]));\n } else {\n parentCommand = new Command({\n graph: Command.PARENT,\n goto: output.goto,\n });\n }\n } else {\n combinedOutputs.push(output);\n }\n } else {\n combinedOutputs.push(\n Array.isArray(input) ? [output] : { messages: [output] }\n );\n }\n }\n\n if (parentCommand) {\n combinedOutputs.push(parentCommand);\n }\n\n return combinedOutputs as T;\n }\n}\n\n/**\n * A conditional edge function that determines whether to route to a tools node or end the graph.\n *\n * This function is designed to be used as a conditional edge in a LangGraph state graph to implement\n * the common pattern of checking if an AI message contains tool calls that need to be executed.\n *\n * @param state - The current state of the graph, which can be either:\n * - An array of `BaseMessage` objects, where the last message is checked for tool calls\n * - A state object conforming to `MessagesAnnotation.State`, which contains a `messages` array\n *\n * @returns A string indicating the next node to route to:\n * - `\"tools\"` - If the last message contains tool calls that need to be executed\n * - `END` - If there are no tool calls, indicating the graph should terminate\n *\n * @example\n * ```typescript\n * import { StateGraph, MessagesAnnotation, END, START } from \"@langchain/langgraph\";\n * import { ToolNode, toolsCondition } from \"@langchain/langgraph/prebuilt\";\n *\n * const graph = new StateGraph(MessagesAnnotation)\n * .addNode(\"agent\", agentNode)\n * .addNode(\"tools\", new ToolNode([searchTool, calculatorTool]))\n * .addEdge(START, \"agent\")\n * .addConditionalEdges(\"agent\", toolsCondition, [\"tools\", END])\n * .addEdge(\"tools\", \"agent\")\n * .compile();\n * ```\n *\n * @remarks\n * The function checks the last message in the state for the presence of `tool_calls`.\n * If the message is an `AIMessage` with one or more tool calls, it returns `\"tools\"`,\n * indicating that the graph should route to a tools node (typically a `ToolNode`) to\n * execute those tool calls. Otherwise, it returns `END` to terminate the graph execution.\n *\n * This is a common pattern in agentic workflows where an AI model decides whether to\n * use tools or provide a final response.\n */\nexport function toolsCondition(\n state: BaseMessage[] | typeof MessagesAnnotation.State\n): \"tools\" | typeof END {\n const message = Array.isArray(state)\n ? state[state.length - 1]\n : state.messages[state.messages.length - 1];\n\n if (\n message !== undefined &&\n \"tool_calls\" in message &&\n ((message as AIMessage).tool_calls?.length ?? 0) > 0\n ) {\n return \"tools\";\n } else {\n return END;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"tool_node.js","names":[],"sources":["../../src/prebuilt/tool_node.ts"],"sourcesContent":["import {\n BaseMessage,\n ToolMessage,\n AIMessage,\n isBaseMessage,\n isAIMessage,\n} from \"@langchain/core/messages\";\nimport { RunnableToolLike } from \"@langchain/core/runnables\";\nimport {\n DynamicTool,\n StructuredToolInterface,\n type ToolRuntime,\n} from \"@langchain/core/tools\";\nimport type { ToolCall } from \"@langchain/core/messages/tool\";\nimport { RunnableCallable } from \"../utils.js\";\nimport { MessagesAnnotation } from \"../graph/messages_annotation.js\";\nimport { isGraphInterrupt } from \"../errors.js\";\nimport { END, isCommand, Command, _isSend, Send } from \"../constants.js\";\nimport type { LangGraphRunnableConfig } from \"../pregel/runnable_types.js\";\n\nexport type ToolNodeOptions = {\n name?: string;\n tags?: string[];\n handleToolErrors?: boolean;\n};\n\nconst isBaseMessageArray = (input: unknown): input is BaseMessage[] =>\n Array.isArray(input) && input.every(isBaseMessage);\n\nconst isMessagesState = (\n input: unknown\n): input is { messages: BaseMessage[] } =>\n typeof input === \"object\" &&\n input != null &&\n \"messages\" in input &&\n isBaseMessageArray(input.messages);\n\nconst isSendInput = (input: unknown): input is { lg_tool_call: ToolCall } =>\n typeof input === \"object\" && input != null && \"lg_tool_call\" in input;\n\n/**\n * A node that runs the tools requested in the last AIMessage. It can be used\n * either in StateGraph with a \"messages\" key or in MessageGraph. If multiple\n * tool calls are requested, they will be run in parallel. The output will be\n * a list of ToolMessages, one for each tool call.\n *\n * @example\n * ```ts\n * import { ToolNode } from \"@langchain/langgraph/prebuilt\";\n * import { tool } from \"@langchain/core/tools\";\n * import { z } from \"zod\";\n * import { AIMessage } from \"@langchain/core/messages\";\n *\n * const getWeather = tool((input) => {\n * if ([\"sf\", \"san francisco\"].includes(input.location.toLowerCase())) {\n * return \"It's 60 degrees and foggy.\";\n * } else {\n * return \"It's 90 degrees and sunny.\";\n * }\n * }, {\n * name: \"get_weather\",\n * description: \"Call to get the current weather.\",\n * schema: z.object({\n * location: z.string().describe(\"Location to get the weather for.\"),\n * }),\n * });\n *\n * const tools = [getWeather];\n * const toolNode = new ToolNode(tools);\n *\n * const messageWithSingleToolCall = new AIMessage({\n * content: \"\",\n * tool_calls: [\n * {\n * name: \"get_weather\",\n * args: { location: \"sf\" },\n * id: \"tool_call_id\",\n * type: \"tool_call\",\n * }\n * ]\n * })\n *\n * await toolNode.invoke({ messages: [messageWithSingleToolCall] });\n * // Returns tool invocation responses as:\n * // { messages: ToolMessage[] }\n * ```\n *\n * @example\n * ```ts\n * import {\n * StateGraph,\n * MessagesAnnotation,\n * } from \"@langchain/langgraph\";\n * import { ToolNode } from \"@langchain/langgraph/prebuilt\";\n * import { tool } from \"@langchain/core/tools\";\n * import { z } from \"zod\";\n * import { ChatAnthropic } from \"@langchain/anthropic\";\n *\n * const getWeather = tool((input) => {\n * if ([\"sf\", \"san francisco\"].includes(input.location.toLowerCase())) {\n * return \"It's 60 degrees and foggy.\";\n * } else {\n * return \"It's 90 degrees and sunny.\";\n * }\n * }, {\n * name: \"get_weather\",\n * description: \"Call to get the current weather.\",\n * schema: z.object({\n * location: z.string().describe(\"Location to get the weather for.\"),\n * }),\n * });\n *\n * const tools = [getWeather];\n * const modelWithTools = new ChatAnthropic({\n * model: \"claude-3-haiku-20240307\",\n * temperature: 0\n * }).bindTools(tools);\n *\n * const toolNodeForGraph = new ToolNode(tools)\n *\n * const shouldContinue = (state: typeof MessagesAnnotation.State) => {\n * const { messages } = state;\n * const lastMessage = messages[messages.length - 1];\n * if (\"tool_calls\" in lastMessage && Array.isArray(lastMessage.tool_calls) && lastMessage.tool_calls?.length) {\n * return \"tools\";\n * }\n * return \"__end__\";\n * }\n *\n * const callModel = async (state: typeof MessagesAnnotation.State) => {\n * const { messages } = state;\n * const response = await modelWithTools.invoke(messages);\n * return { messages: response };\n * }\n *\n * const graph = new StateGraph(MessagesAnnotation)\n * .addNode(\"agent\", callModel)\n * .addNode(\"tools\", toolNodeForGraph)\n * .addEdge(\"__start__\", \"agent\")\n * .addConditionalEdges(\"agent\", shouldContinue)\n * .addEdge(\"tools\", \"agent\")\n * .compile();\n *\n * const inputs = {\n * messages: [{ role: \"user\", content: \"what is the weather in SF?\" }],\n * };\n *\n * const stream = await graph.stream(inputs, {\n * streamMode: \"values\",\n * });\n *\n * for await (const { messages } of stream) {\n * console.log(messages);\n * }\n * // Returns the messages in the state at each step of execution\n * ```\n *\n * ### Accessing graph state and runtime context from tools\n *\n * Tools executed by a `ToolNode` only receive the arguments produced by the\n * model. To give a tool access to the surrounding graph state or other runtime\n * context, read them from the {@link ToolRuntime} that is passed as the\n * second argument to every tool:\n *\n * - `runtime.state` — the input the `ToolNode` was invoked with. When the\n * `ToolNode` runs as a graph node (e.g. inside `createReactAgent`), this is\n * the current graph state. This works in any runtime, including web browsers,\n * because it does not rely on `node:async_hooks`/`AsyncLocalStorage`.\n * - `runtime.config`, `runtime.context`, `runtime.store`, etc. — other\n * run-scoped values.\n *\n * @example\n * ```ts\n * import { ToolNode } from \"@langchain/langgraph/prebuilt\";\n * import { StateGraph, MessagesZodState } from \"@langchain/langgraph\";\n * import { tool, type ToolRuntime } from \"@langchain/core/tools\";\n * import { z } from \"zod\";\n *\n * // Define the graph state with a Zod schema. The extra `userId` key becomes\n * // part of the state that the ToolNode forwards to its tools via `runtime.state`.\n * const AgentState = z.object({\n * ...MessagesZodState.shape,\n * userId: z.string(),\n * });\n *\n * const getUserInfo = tool(\n * async (_input, runtime: ToolRuntime<typeof AgentState>) => {\n * // Read the current graph state directly from the second argument.\n * const userId = runtime.state.userId;\n * return userId === \"user_123\" ? \"User is John Smith\" : \"Unknown user\";\n * },\n * {\n * name: \"get_user_info\",\n * description: \"Look up user info.\",\n * schema: z.object({}),\n * }\n * );\n *\n * // Wire the ToolNode into a StateGraph that uses `AgentState`. Because the\n * // node runs with the graph state as its input, the tool can read `userId`.\n * const graph = new StateGraph(AgentState)\n * .addNode(\"tools\", new ToolNode([getUserInfo]))\n * .addEdge(\"__start__\", \"tools\")\n * .compile();\n *\n * await graph.invoke({ messages: [...], userId: \"user_123\" });\n * ```\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport class ToolNode<T = any> extends RunnableCallable<T, T> {\n tools: (StructuredToolInterface | DynamicTool | RunnableToolLike)[];\n\n handleToolErrors = true;\n\n trace = false;\n\n constructor(\n tools: (StructuredToolInterface | DynamicTool | RunnableToolLike)[],\n options?: ToolNodeOptions\n ) {\n const { name, tags, handleToolErrors } = options ?? {};\n super({ name, tags, func: (input, config) => this.run(input, config) });\n this.tools = tools;\n this.handleToolErrors = handleToolErrors ?? this.handleToolErrors;\n }\n\n protected async runTool(\n call: ToolCall,\n config: LangGraphRunnableConfig,\n state: unknown\n ): Promise<ToolMessage | Command> {\n const tool = this.tools.find((tool) => tool.name === call.name);\n try {\n if (tool === undefined) {\n throw new Error(`Tool \"${call.name}\" not found.`);\n }\n const toolCall = { ...call, type: \"tool_call\" } as ToolCall;\n const runtime: ToolRuntime = {\n ...config,\n state,\n toolCallId: call.id ?? \"\",\n config,\n context: config.context,\n store: (config.store as ToolRuntime[\"store\"] | undefined) ?? null,\n writer: config.writer ?? config.configurable?.writer ?? null,\n };\n const output = await tool.invoke(toolCall, runtime);\n\n if (\n (isBaseMessage(output) && output.getType() === \"tool\") ||\n isCommand(output)\n ) {\n return output as ToolMessage | Command;\n }\n\n return new ToolMessage({\n status: \"success\",\n name: tool.name,\n content: typeof output === \"string\" ? output : JSON.stringify(output),\n tool_call_id: call.id!,\n });\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n } catch (e: any) {\n if (!this.handleToolErrors) throw e;\n\n if (isGraphInterrupt(e)) {\n // `NodeInterrupt` errors are a breakpoint to bring a human into the loop.\n // As such, they are not recoverable by the agent and shouldn't be fed\n // back. Instead, re-throw these errors even when `handleToolErrors = true`.\n throw e;\n }\n\n return new ToolMessage({\n status: \"error\",\n content: `Error: ${e.message}\\n Please fix your mistakes.`,\n name: call.name,\n tool_call_id: call.id ?? \"\",\n });\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n protected async run(\n input: unknown,\n config: LangGraphRunnableConfig\n ): Promise<T> {\n let outputs: (ToolMessage | Command)[];\n\n if (isSendInput(input)) {\n // Drop the internal `lg_tool_call` routing key so tools only see state.\n const { lg_tool_call: toolCall, ...state } = input as {\n lg_tool_call: ToolCall;\n } & Record<string, unknown>;\n outputs = [await this.runTool(toolCall, config, state)];\n } else {\n let messages: BaseMessage[];\n if (isBaseMessageArray(input)) {\n messages = input;\n } else if (isMessagesState(input)) {\n messages = input.messages;\n } else {\n throw new Error(\n \"ToolNode only accepts BaseMessage[] or { messages: BaseMessage[] } as input.\"\n );\n }\n\n const toolMessageIds: Set<string> = new Set(\n messages\n .filter((msg) => msg.getType() === \"tool\")\n .map((msg) => (msg as ToolMessage).tool_call_id)\n );\n\n let aiMessage: AIMessage | undefined;\n for (let i = messages.length - 1; i >= 0; i -= 1) {\n const message = messages[i];\n if (isAIMessage(message)) {\n aiMessage = message;\n break;\n }\n }\n\n if (aiMessage == null || !isAIMessage(aiMessage)) {\n throw new Error(\"ToolNode only accepts AIMessages as input.\");\n }\n\n outputs = await Promise.all(\n aiMessage.tool_calls\n ?.filter((call) => call.id == null || !toolMessageIds.has(call.id))\n .map((call) => this.runTool(call, config, input)) ?? []\n );\n }\n\n // Preserve existing behavior for non-command tool outputs for backwards compatibility\n if (!outputs.some(isCommand)) {\n return (Array.isArray(input) ? outputs : { messages: outputs }) as T;\n }\n\n // Handle mixed Command and non-Command outputs\n const combinedOutputs: (\n | { messages: BaseMessage[] }\n | BaseMessage[]\n | Command\n )[] = [];\n let parentCommand: Command | null = null;\n\n for (const output of outputs) {\n if (isCommand(output)) {\n if (\n output.graph === Command.PARENT &&\n Array.isArray(output.goto) &&\n output.goto.every((send) => _isSend(send))\n ) {\n if (parentCommand) {\n (parentCommand.goto as Send[]).push(...(output.goto as Send[]));\n } else {\n parentCommand = new Command({\n graph: Command.PARENT,\n goto: output.goto,\n });\n }\n } else {\n combinedOutputs.push(output);\n }\n } else {\n combinedOutputs.push(\n Array.isArray(input) ? [output] : { messages: [output] }\n );\n }\n }\n\n if (parentCommand) {\n combinedOutputs.push(parentCommand);\n }\n\n return combinedOutputs as T;\n }\n}\n\n/**\n * A conditional edge function that determines whether to route to a tools node or end the graph.\n *\n * This function is designed to be used as a conditional edge in a LangGraph state graph to implement\n * the common pattern of checking if an AI message contains tool calls that need to be executed.\n *\n * @param state - The current state of the graph, which can be either:\n * - An array of `BaseMessage` objects, where the last message is checked for tool calls\n * - A state object conforming to `MessagesAnnotation.State`, which contains a `messages` array\n *\n * @returns A string indicating the next node to route to:\n * - `\"tools\"` - If the last message contains tool calls that need to be executed\n * - `END` - If there are no tool calls, indicating the graph should terminate\n *\n * @example\n * ```typescript\n * import { StateGraph, MessagesAnnotation, END, START } from \"@langchain/langgraph\";\n * import { ToolNode, toolsCondition } from \"@langchain/langgraph/prebuilt\";\n *\n * const graph = new StateGraph(MessagesAnnotation)\n * .addNode(\"agent\", agentNode)\n * .addNode(\"tools\", new ToolNode([searchTool, calculatorTool]))\n * .addEdge(START, \"agent\")\n * .addConditionalEdges(\"agent\", toolsCondition, [\"tools\", END])\n * .addEdge(\"tools\", \"agent\")\n * .compile();\n * ```\n *\n * @remarks\n * The function checks the last message in the state for the presence of `tool_calls`.\n * If the message is an `AIMessage` with one or more tool calls, it returns `\"tools\"`,\n * indicating that the graph should route to a tools node (typically a `ToolNode`) to\n * execute those tool calls. Otherwise, it returns `END` to terminate the graph execution.\n *\n * This is a common pattern in agentic workflows where an AI model decides whether to\n * use tools or provide a final response.\n */\nexport function toolsCondition(\n state: BaseMessage[] | typeof MessagesAnnotation.State\n): \"tools\" | typeof END {\n const message = Array.isArray(state)\n ? state[state.length - 1]\n : state.messages[state.messages.length - 1];\n\n if (\n message !== undefined &&\n \"tool_calls\" in message &&\n ((message as AIMessage).tool_calls?.length ?? 0) > 0\n ) {\n return \"tools\";\n } else {\n return END;\n }\n}\n"],"mappings":"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"}
@@ -110,8 +110,22 @@ function getConfig() {
110
110
  return _langchain_core_singletons.AsyncLocalStorageProviderSingleton.getRunnableConfig();
111
111
  }
112
112
  /**
113
- * A helper utility function that returns the input for the currently executing task
113
+ * A helper utility function that returns the input for the currently executing
114
+ * task.
114
115
  *
116
+ * Note: When called without arguments, this relies on `node:async_hooks` /
117
+ * `AsyncLocalStorage`, which is available in many JavaScript environments
118
+ * (Node.js, Deno, Cloudflare Workers) but not in web browsers. In environments
119
+ * without `AsyncLocalStorage` support, pass the `config` that your node/tool
120
+ * function receives directly, e.g. `getCurrentTaskInput(config)`.
121
+ *
122
+ * Tip: Inside a tool run by a `ToolNode`, prefer reading graph state from
123
+ * `runtime.state` on the second tool argument (typed as `ToolRuntime` from
124
+ * `@langchain/core/tools`). It works in every runtime, including web browsers.
125
+ *
126
+ * @param config - Optional {@link LangGraphRunnableConfig} to read the task
127
+ * input from. Provide this when running in an environment without
128
+ * `AsyncLocalStorage` support (e.g. web browsers).
115
129
  * @returns the input for the currently executing task
116
130
  */
117
131
  function getCurrentTaskInput(config) {
@@ -1 +1 @@
1
- {"version":3,"file":"config.cjs","names":["AsyncLocalStorageProviderSingleton","CONFIG_KEY_SCRATCHPAD"],"sources":["../../../src/pregel/utils/config.ts"],"sourcesContent":["import { RunnableConfig } from \"@langchain/core/runnables\";\nimport { AsyncLocalStorageProviderSingleton } from \"@langchain/core/singletons\";\nimport { BaseStore } from \"@langchain/langgraph-checkpoint\";\nimport { LangGraphRunnableConfig } from \"../runnable_types.js\";\nimport {\n CHECKPOINT_NAMESPACE_END,\n CHECKPOINT_NAMESPACE_SEPARATOR,\n CONFIG_KEY_SCRATCHPAD,\n} from \"../../constants.js\";\n\nconst COPIABLE_KEYS = [\"tags\", \"metadata\", \"callbacks\", \"configurable\"];\n\nconst CONFIG_KEYS = [\n \"tags\",\n \"metadata\",\n \"callbacks\",\n \"runName\",\n \"maxConcurrency\",\n \"recursionLimit\",\n \"configurable\",\n \"runId\",\n \"outputKeys\",\n \"streamMode\",\n \"store\",\n \"writer\",\n \"interrupt\",\n \"context\",\n \"interruptBefore\",\n \"interruptAfter\",\n \"checkpointDuring\",\n \"durability\",\n \"signal\",\n \"heartbeat\",\n \"executionInfo\",\n \"serverInfo\",\n \"control\",\n];\n\nconst DEFAULT_RECURSION_LIMIT = 25;\nexport const PROPAGATE_TO_METADATA = new Set([\n \"thread_id\",\n \"checkpoint_id\",\n \"checkpoint_ns\",\n \"task_id\",\n \"run_id\",\n \"assistant_id\",\n \"graph_id\",\n]);\n\nexport function propagateConfigurableToMetadata(\n configurable?: Record<string, unknown>,\n metadata?: Record<string, unknown>\n): Record<string, unknown> | undefined {\n if (!configurable) {\n return metadata;\n }\n const result = metadata ?? {};\n for (const key of PROPAGATE_TO_METADATA) {\n if (key in result) {\n continue;\n }\n const value = configurable[key];\n if (value !== undefined) {\n result[key] = value;\n }\n }\n return result;\n}\n\nexport function ensureLangGraphConfig(\n ...configs: (LangGraphRunnableConfig | undefined)[]\n): RunnableConfig {\n const empty: LangGraphRunnableConfig = {\n tags: [],\n metadata: {},\n callbacks: undefined,\n recursionLimit: DEFAULT_RECURSION_LIMIT,\n configurable: {},\n };\n\n const implicitConfig: RunnableConfig =\n AsyncLocalStorageProviderSingleton.getRunnableConfig();\n if (implicitConfig !== undefined) {\n for (const [k, v] of Object.entries(implicitConfig)) {\n if (v !== undefined) {\n if (COPIABLE_KEYS.includes(k)) {\n let copiedValue;\n if (Array.isArray(v)) {\n copiedValue = [...v];\n } else if (typeof v === \"object\") {\n if (\n k === \"callbacks\" &&\n \"copy\" in v &&\n typeof v.copy === \"function\"\n ) {\n copiedValue = v.copy();\n } else {\n copiedValue = { ...v };\n }\n } else {\n copiedValue = v;\n }\n empty[k as keyof RunnableConfig] = copiedValue;\n } else {\n empty[k as keyof RunnableConfig] = v;\n }\n }\n }\n }\n\n for (const config of configs) {\n if (config === undefined) {\n continue;\n }\n\n for (const [k, v] of Object.entries(config)) {\n if (v !== undefined && CONFIG_KEYS.includes(k)) {\n empty[k as keyof LangGraphRunnableConfig] = v;\n }\n }\n }\n\n empty.metadata =\n propagateConfigurableToMetadata(\n empty.configurable as Record<string, unknown> | undefined,\n empty.metadata as Record<string, unknown> | undefined\n ) ?? {};\n return empty;\n}\n\n/**\n * A helper utility function that returns the {@link BaseStore} that was set when the graph was initialized\n *\n * @returns a reference to the {@link BaseStore} that was set when the graph was initialized\n */\nexport function getStore(\n config?: LangGraphRunnableConfig\n): BaseStore | undefined {\n const runConfig: LangGraphRunnableConfig =\n config ?? AsyncLocalStorageProviderSingleton.getRunnableConfig();\n\n if (runConfig === undefined) {\n throw new Error(\n [\n \"Config not retrievable. This is likely because you are running in an environment without support for AsyncLocalStorage.\",\n \"If you're running `getStore` in such environment, pass the `config` from the node function directly.\",\n ].join(\"\\n\")\n );\n }\n\n return runConfig?.store;\n}\n\n/**\n * A helper utility function that returns the {@link LangGraphRunnableConfig#writer} if \"custom\" stream mode is enabled, otherwise undefined.\n *\n * @returns a reference to the {@link LangGraphRunnableConfig#writer} if \"custom\" stream mode is enabled, otherwise undefined\n */\nexport function getWriter(\n config?: LangGraphRunnableConfig\n): ((chunk: unknown) => void) | undefined {\n const runConfig: LangGraphRunnableConfig =\n config ?? AsyncLocalStorageProviderSingleton.getRunnableConfig();\n\n if (runConfig === undefined) {\n throw new Error(\n [\n \"Config not retrievable. This is likely because you are running in an environment without support for AsyncLocalStorage.\",\n \"If you're running `getWriter` in such environment, pass the `config` from the node function directly.\",\n ].join(\"\\n\")\n );\n }\n\n return runConfig?.writer || runConfig?.configurable?.writer;\n}\n\n/**\n * A helper utility function that returns the {@link LangGraphRunnableConfig} that was set when the graph was initialized.\n *\n * Note: This only works when running in an environment that supports node:async_hooks and AsyncLocalStorage. If you're running this in a\n * web environment, access the LangGraphRunnableConfig from the node function directly.\n *\n * @returns the {@link LangGraphRunnableConfig} that was set when the graph was initialized\n */\nexport function getConfig(): LangGraphRunnableConfig {\n return AsyncLocalStorageProviderSingleton.getRunnableConfig();\n}\n\n/**\n * A helper utility function that returns the input for the currently executing task\n *\n * @returns the input for the currently executing task\n */\nexport function getCurrentTaskInput<T = unknown>(\n config?: LangGraphRunnableConfig\n): T {\n const runConfig: LangGraphRunnableConfig =\n config ?? AsyncLocalStorageProviderSingleton.getRunnableConfig();\n\n if (runConfig === undefined) {\n throw new Error(\n [\n \"Config not retrievable. This is likely because you are running in an environment without support for AsyncLocalStorage.\",\n \"If you're running `getCurrentTaskInput` in such environment, pass the `config` from the node function directly.\",\n ].join(\"\\n\")\n );\n }\n\n if (\n runConfig.configurable?.[CONFIG_KEY_SCRATCHPAD]?.currentTaskInput ===\n undefined\n ) {\n throw new Error(\"BUG: internal scratchpad not initialized.\");\n }\n\n return runConfig!.configurable![CONFIG_KEY_SCRATCHPAD]!.currentTaskInput as T;\n}\n\nexport function recastCheckpointNamespace(namespace: string): string {\n return namespace\n .split(CHECKPOINT_NAMESPACE_SEPARATOR)\n .filter((part) => !part.match(/^\\d+$/))\n .map((part) => part.split(CHECKPOINT_NAMESPACE_END)[0])\n .join(CHECKPOINT_NAMESPACE_SEPARATOR);\n}\n\nexport function getParentCheckpointNamespace(namespace: string): string {\n const parts = namespace.split(CHECKPOINT_NAMESPACE_SEPARATOR);\n while (parts.length > 1 && parts[parts.length - 1].match(/^\\d+$/)) {\n parts.pop();\n }\n return parts.slice(0, -1).join(CHECKPOINT_NAMESPACE_SEPARATOR);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"config.cjs","names":["AsyncLocalStorageProviderSingleton","CONFIG_KEY_SCRATCHPAD"],"sources":["../../../src/pregel/utils/config.ts"],"sourcesContent":["import { RunnableConfig } from \"@langchain/core/runnables\";\nimport { AsyncLocalStorageProviderSingleton } from \"@langchain/core/singletons\";\nimport { BaseStore } from \"@langchain/langgraph-checkpoint\";\nimport { LangGraphRunnableConfig } from \"../runnable_types.js\";\nimport {\n CHECKPOINT_NAMESPACE_END,\n CHECKPOINT_NAMESPACE_SEPARATOR,\n CONFIG_KEY_SCRATCHPAD,\n} from \"../../constants.js\";\n\nconst COPIABLE_KEYS = [\"tags\", \"metadata\", \"callbacks\", \"configurable\"];\n\nconst CONFIG_KEYS = [\n \"tags\",\n \"metadata\",\n \"callbacks\",\n \"runName\",\n \"maxConcurrency\",\n \"recursionLimit\",\n \"configurable\",\n \"runId\",\n \"outputKeys\",\n \"streamMode\",\n \"store\",\n \"writer\",\n \"interrupt\",\n \"context\",\n \"interruptBefore\",\n \"interruptAfter\",\n \"checkpointDuring\",\n \"durability\",\n \"signal\",\n \"heartbeat\",\n \"executionInfo\",\n \"serverInfo\",\n \"control\",\n];\n\nconst DEFAULT_RECURSION_LIMIT = 25;\nexport const PROPAGATE_TO_METADATA = new Set([\n \"thread_id\",\n \"checkpoint_id\",\n \"checkpoint_ns\",\n \"task_id\",\n \"run_id\",\n \"assistant_id\",\n \"graph_id\",\n]);\n\nexport function propagateConfigurableToMetadata(\n configurable?: Record<string, unknown>,\n metadata?: Record<string, unknown>\n): Record<string, unknown> | undefined {\n if (!configurable) {\n return metadata;\n }\n const result = metadata ?? {};\n for (const key of PROPAGATE_TO_METADATA) {\n if (key in result) {\n continue;\n }\n const value = configurable[key];\n if (value !== undefined) {\n result[key] = value;\n }\n }\n return result;\n}\n\nexport function ensureLangGraphConfig(\n ...configs: (LangGraphRunnableConfig | undefined)[]\n): RunnableConfig {\n const empty: LangGraphRunnableConfig = {\n tags: [],\n metadata: {},\n callbacks: undefined,\n recursionLimit: DEFAULT_RECURSION_LIMIT,\n configurable: {},\n };\n\n const implicitConfig: RunnableConfig =\n AsyncLocalStorageProviderSingleton.getRunnableConfig();\n if (implicitConfig !== undefined) {\n for (const [k, v] of Object.entries(implicitConfig)) {\n if (v !== undefined) {\n if (COPIABLE_KEYS.includes(k)) {\n let copiedValue;\n if (Array.isArray(v)) {\n copiedValue = [...v];\n } else if (typeof v === \"object\") {\n if (\n k === \"callbacks\" &&\n \"copy\" in v &&\n typeof v.copy === \"function\"\n ) {\n copiedValue = v.copy();\n } else {\n copiedValue = { ...v };\n }\n } else {\n copiedValue = v;\n }\n empty[k as keyof RunnableConfig] = copiedValue;\n } else {\n empty[k as keyof RunnableConfig] = v;\n }\n }\n }\n }\n\n for (const config of configs) {\n if (config === undefined) {\n continue;\n }\n\n for (const [k, v] of Object.entries(config)) {\n if (v !== undefined && CONFIG_KEYS.includes(k)) {\n empty[k as keyof LangGraphRunnableConfig] = v;\n }\n }\n }\n\n empty.metadata =\n propagateConfigurableToMetadata(\n empty.configurable as Record<string, unknown> | undefined,\n empty.metadata as Record<string, unknown> | undefined\n ) ?? {};\n return empty;\n}\n\n/**\n * A helper utility function that returns the {@link BaseStore} that was set when the graph was initialized\n *\n * @returns a reference to the {@link BaseStore} that was set when the graph was initialized\n */\nexport function getStore(\n config?: LangGraphRunnableConfig\n): BaseStore | undefined {\n const runConfig: LangGraphRunnableConfig =\n config ?? AsyncLocalStorageProviderSingleton.getRunnableConfig();\n\n if (runConfig === undefined) {\n throw new Error(\n [\n \"Config not retrievable. This is likely because you are running in an environment without support for AsyncLocalStorage.\",\n \"If you're running `getStore` in such environment, pass the `config` from the node function directly.\",\n ].join(\"\\n\")\n );\n }\n\n return runConfig?.store;\n}\n\n/**\n * A helper utility function that returns the {@link LangGraphRunnableConfig#writer} if \"custom\" stream mode is enabled, otherwise undefined.\n *\n * @returns a reference to the {@link LangGraphRunnableConfig#writer} if \"custom\" stream mode is enabled, otherwise undefined\n */\nexport function getWriter(\n config?: LangGraphRunnableConfig\n): ((chunk: unknown) => void) | undefined {\n const runConfig: LangGraphRunnableConfig =\n config ?? AsyncLocalStorageProviderSingleton.getRunnableConfig();\n\n if (runConfig === undefined) {\n throw new Error(\n [\n \"Config not retrievable. This is likely because you are running in an environment without support for AsyncLocalStorage.\",\n \"If you're running `getWriter` in such environment, pass the `config` from the node function directly.\",\n ].join(\"\\n\")\n );\n }\n\n return runConfig?.writer || runConfig?.configurable?.writer;\n}\n\n/**\n * A helper utility function that returns the {@link LangGraphRunnableConfig} that was set when the graph was initialized.\n *\n * Note: This only works when running in an environment that supports node:async_hooks and AsyncLocalStorage. If you're running this in a\n * web environment, access the LangGraphRunnableConfig from the node function directly.\n *\n * @returns the {@link LangGraphRunnableConfig} that was set when the graph was initialized\n */\nexport function getConfig(): LangGraphRunnableConfig {\n return AsyncLocalStorageProviderSingleton.getRunnableConfig();\n}\n\n/**\n * A helper utility function that returns the input for the currently executing\n * task.\n *\n * Note: When called without arguments, this relies on `node:async_hooks` /\n * `AsyncLocalStorage`, which is available in many JavaScript environments\n * (Node.js, Deno, Cloudflare Workers) but not in web browsers. In environments\n * without `AsyncLocalStorage` support, pass the `config` that your node/tool\n * function receives directly, e.g. `getCurrentTaskInput(config)`.\n *\n * Tip: Inside a tool run by a `ToolNode`, prefer reading graph state from\n * `runtime.state` on the second tool argument (typed as `ToolRuntime` from\n * `@langchain/core/tools`). It works in every runtime, including web browsers.\n *\n * @param config - Optional {@link LangGraphRunnableConfig} to read the task\n * input from. Provide this when running in an environment without\n * `AsyncLocalStorage` support (e.g. web browsers).\n * @returns the input for the currently executing task\n */\nexport function getCurrentTaskInput<T = unknown>(\n config?: LangGraphRunnableConfig\n): T {\n const runConfig: LangGraphRunnableConfig =\n config ?? AsyncLocalStorageProviderSingleton.getRunnableConfig();\n\n if (runConfig === undefined) {\n throw new Error(\n [\n \"Config not retrievable. This is likely because you are running in an environment without support for AsyncLocalStorage.\",\n \"If you're running `getCurrentTaskInput` in such environment, pass the `config` from the node function directly.\",\n ].join(\"\\n\")\n );\n }\n\n if (\n runConfig.configurable?.[CONFIG_KEY_SCRATCHPAD]?.currentTaskInput ===\n undefined\n ) {\n throw new Error(\"BUG: internal scratchpad not initialized.\");\n }\n\n return runConfig!.configurable![CONFIG_KEY_SCRATCHPAD]!.currentTaskInput as T;\n}\n\nexport function recastCheckpointNamespace(namespace: string): string {\n return namespace\n .split(CHECKPOINT_NAMESPACE_SEPARATOR)\n .filter((part) => !part.match(/^\\d+$/))\n .map((part) => part.split(CHECKPOINT_NAMESPACE_END)[0])\n .join(CHECKPOINT_NAMESPACE_SEPARATOR);\n}\n\nexport function getParentCheckpointNamespace(namespace: string): string {\n const parts = namespace.split(CHECKPOINT_NAMESPACE_SEPARATOR);\n while (parts.length > 1 && parts[parts.length - 1].match(/^\\d+$/)) {\n parts.pop();\n }\n return parts.slice(0, -1).join(CHECKPOINT_NAMESPACE_SEPARATOR);\n}\n"],"mappings":"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"}
@@ -25,8 +25,22 @@ declare function getWriter(config?: LangGraphRunnableConfig): ((chunk: unknown)
25
25
  */
26
26
  declare function getConfig(): LangGraphRunnableConfig;
27
27
  /**
28
- * A helper utility function that returns the input for the currently executing task
28
+ * A helper utility function that returns the input for the currently executing
29
+ * task.
29
30
  *
31
+ * Note: When called without arguments, this relies on `node:async_hooks` /
32
+ * `AsyncLocalStorage`, which is available in many JavaScript environments
33
+ * (Node.js, Deno, Cloudflare Workers) but not in web browsers. In environments
34
+ * without `AsyncLocalStorage` support, pass the `config` that your node/tool
35
+ * function receives directly, e.g. `getCurrentTaskInput(config)`.
36
+ *
37
+ * Tip: Inside a tool run by a `ToolNode`, prefer reading graph state from
38
+ * `runtime.state` on the second tool argument (typed as `ToolRuntime` from
39
+ * `@langchain/core/tools`). It works in every runtime, including web browsers.
40
+ *
41
+ * @param config - Optional {@link LangGraphRunnableConfig} to read the task
42
+ * input from. Provide this when running in an environment without
43
+ * `AsyncLocalStorage` support (e.g. web browsers).
30
44
  * @returns the input for the currently executing task
31
45
  */
32
46
  declare function getCurrentTaskInput<T = unknown>(config?: LangGraphRunnableConfig): T;
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.cts","names":[],"sources":["../../../src/pregel/utils/config.ts"],"mappings":";;;;;;;;;;iBAuIgB,QAAA,CACd,MAAA,GAAS,uBAAA,GACR,SAAA;;;AAqBH;;;iBAAgB,SAAA,CACd,MAAA,GAAS,uBAAA,KACN,KAAA;;;;;;AAwBL;;;iBAAgB,SAAA,CAAA,GAAa,uBAAA;;AAS7B;;;;iBAAgB,mBAAA,aAAA,CACd,MAAA,GAAS,uBAAA,GACR,CAAA"}
1
+ {"version":3,"file":"config.d.cts","names":[],"sources":["../../../src/pregel/utils/config.ts"],"mappings":";;;;;;;;;;iBAuIgB,QAAA,CACd,MAAA,GAAS,uBAAA,GACR,SAAA;;;AAqBH;;;iBAAgB,SAAA,CACd,MAAA,GAAS,uBAAA,KACN,KAAA;;;;;;AAwBL;;;iBAAgB,SAAA,CAAA,GAAa,uBAAA;;AAuB7B;;;;;;;;;;;;;;;;;;iBAAgB,mBAAA,aAAA,CACd,MAAA,GAAS,uBAAA,GACR,CAAA"}
@@ -25,8 +25,22 @@ declare function getWriter(config?: LangGraphRunnableConfig): ((chunk: unknown)
25
25
  */
26
26
  declare function getConfig(): LangGraphRunnableConfig;
27
27
  /**
28
- * A helper utility function that returns the input for the currently executing task
28
+ * A helper utility function that returns the input for the currently executing
29
+ * task.
29
30
  *
31
+ * Note: When called without arguments, this relies on `node:async_hooks` /
32
+ * `AsyncLocalStorage`, which is available in many JavaScript environments
33
+ * (Node.js, Deno, Cloudflare Workers) but not in web browsers. In environments
34
+ * without `AsyncLocalStorage` support, pass the `config` that your node/tool
35
+ * function receives directly, e.g. `getCurrentTaskInput(config)`.
36
+ *
37
+ * Tip: Inside a tool run by a `ToolNode`, prefer reading graph state from
38
+ * `runtime.state` on the second tool argument (typed as `ToolRuntime` from
39
+ * `@langchain/core/tools`). It works in every runtime, including web browsers.
40
+ *
41
+ * @param config - Optional {@link LangGraphRunnableConfig} to read the task
42
+ * input from. Provide this when running in an environment without
43
+ * `AsyncLocalStorage` support (e.g. web browsers).
30
44
  * @returns the input for the currently executing task
31
45
  */
32
46
  declare function getCurrentTaskInput<T = unknown>(config?: LangGraphRunnableConfig): T;
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","names":[],"sources":["../../../src/pregel/utils/config.ts"],"mappings":";;;;;;;;;;iBAuIgB,QAAA,CACd,MAAA,GAAS,uBAAA,GACR,SAAA;;;AAqBH;;;iBAAgB,SAAA,CACd,MAAA,GAAS,uBAAA,KACN,KAAA;;;;;;AAwBL;;;iBAAgB,SAAA,CAAA,GAAa,uBAAA;;AAS7B;;;;iBAAgB,mBAAA,aAAA,CACd,MAAA,GAAS,uBAAA,GACR,CAAA"}
1
+ {"version":3,"file":"config.d.ts","names":[],"sources":["../../../src/pregel/utils/config.ts"],"mappings":";;;;;;;;;;iBAuIgB,QAAA,CACd,MAAA,GAAS,uBAAA,GACR,SAAA;;;AAqBH;;;iBAAgB,SAAA,CACd,MAAA,GAAS,uBAAA,KACN,KAAA;;;;;;AAwBL;;;iBAAgB,SAAA,CAAA,GAAa,uBAAA;;AAuB7B;;;;;;;;;;;;;;;;;;iBAAgB,mBAAA,aAAA,CACd,MAAA,GAAS,uBAAA,GACR,CAAA"}
@@ -110,8 +110,22 @@ function getConfig() {
110
110
  return AsyncLocalStorageProviderSingleton.getRunnableConfig();
111
111
  }
112
112
  /**
113
- * A helper utility function that returns the input for the currently executing task
113
+ * A helper utility function that returns the input for the currently executing
114
+ * task.
114
115
  *
116
+ * Note: When called without arguments, this relies on `node:async_hooks` /
117
+ * `AsyncLocalStorage`, which is available in many JavaScript environments
118
+ * (Node.js, Deno, Cloudflare Workers) but not in web browsers. In environments
119
+ * without `AsyncLocalStorage` support, pass the `config` that your node/tool
120
+ * function receives directly, e.g. `getCurrentTaskInput(config)`.
121
+ *
122
+ * Tip: Inside a tool run by a `ToolNode`, prefer reading graph state from
123
+ * `runtime.state` on the second tool argument (typed as `ToolRuntime` from
124
+ * `@langchain/core/tools`). It works in every runtime, including web browsers.
125
+ *
126
+ * @param config - Optional {@link LangGraphRunnableConfig} to read the task
127
+ * input from. Provide this when running in an environment without
128
+ * `AsyncLocalStorage` support (e.g. web browsers).
115
129
  * @returns the input for the currently executing task
116
130
  */
117
131
  function getCurrentTaskInput(config) {