A node that runs the tools requested in the last AIMessage. It can be used either in StateGraph with a "messages" key or in MessageGraph. If multiple tool calls are requested, they will be run in parallel. The output will be a list of ToolMessages, one for each tool call.
class ToolNodeRunnableCallable<T, T>import { ToolNode } from "@langchain/langgraph/prebuilt";
import { tool } from "@langchain/core/tools";
import { z } from "zod";
import { AIMessage } from "@langchain/core/messages";
const getWeather = tool((input) => {
if (["sf", "san francisco"].includes(input.location.toLowerCase())) {
return "It's 60 degrees and foggy.";
} else {
return "It's 90 degrees and sunny.";
}
}, {
name: "get_weather",
description: "Call to get the current weather.",
schema: z.object({
location: z.string().describe("Location to get the weather for."),
}),
});
const tools = [getWeather];
const toolNode = new ToolNode(tools);
const messageWithSingleToolCall = new AIMessage({
content: "",
tool_calls: [
{
name: "get_weather",
args: { location: "sf" },
id: "tool_call_id",
type: "tool_call",
}
]
})
await toolNode.invoke({ messages: [messageWithSingleToolCall] });
// Returns tool invocation responses as:
// { messages: ToolMessage[] }import {
StateGraph,
MessagesAnnotation,
} from "@langchain/langgraph";
import { ToolNode } from "@langchain/langgraph/prebuilt";
import { tool } from "@langchain/core/tools";
import { z } from "zod";
import { ChatAnthropic } from "@langchain/anthropic";
const getWeather = tool((input) => {
if (["sf", "san francisco"].includes(input.location.toLowerCase())) {
return "It's 60 degrees and foggy.";
} else {
return "It's 90 degrees and sunny.";
}
}, {
name: "get_weather",
description: "Call to get the current weather.",
schema: z.object({
location: z.string().describe("Location to get the weather for."),
}),
});
const tools = [getWeather];
const modelWithTools = new ChatAnthropic({
model: "claude-3-haiku-20240307",
temperature: 0
}).bindTools(tools);
const toolNodeForGraph = new ToolNode(tools)
const shouldContinue = (state: typeof MessagesAnnotation.State) => {
const { messages } = state;
const lastMessage = messages[messages.length - 1];
if ("tool_calls" in lastMessage && Array.isArray(lastMessage.tool_calls) && lastMessage.tool_calls?.length) {
return "tools";
}
return "__end__";
}
const callModel = async (state: typeof MessagesAnnotation.State) => {
const { messages } = state;
const response = await modelWithTools.invoke(messages);
return { messages: response };
}
const graph = new StateGraph(MessagesAnnotation)
.addNode("agent", callModel)
.addNode("tools", toolNodeForGraph)
.addEdge("__start__", "agent")
.addConditionalEdges("agent", shouldContinue)
.addEdge("tools", "agent")
.compile();
const inputs = {
messages: [{ role: "user", content: "what is the weather in SF?" }],
};
const stream = await graph.stream(inputs, {
streamMode: "values",
});
for await (const { messages } of stream) {
console.log(messages);
}
// Returns the messages in the state at each step of executionimport { ToolNode } from "@langchain/langgraph/prebuilt";
import { StateGraph, MessagesZodState } from "@langchain/langgraph";
import { tool, type ToolRuntime } from "@langchain/core/tools";
import { z } from "zod";
// Define the graph state with a Zod schema. The extra `userId` key becomes
// part of the state that the ToolNode forwards to its tools via `runtime.state`.
const AgentState = z.object({
...MessagesZodState.shape,
userId: z.string(),
});
const getUserInfo = tool(
async (_input, runtime: ToolRuntime<typeof AgentState>) => {
// Read the current graph state directly from the second argument.
const userId = runtime.state.userId;
return userId === "user_123" ? "User is John Smith" : "Unknown user";
},
{
name: "get_user_info",
description: "Look up user info.",
schema: z.object({}),
}
);
// Wire the ToolNode into a StateGraph that uses `AgentState`. Because the
// node runs with the graph state as its input, the tool can read `userId`.
const graph = new StateGraph(AgentState)
.addNode("tools", new ToolNode([getUserInfo]))
.addEdge("__start__", "tools")
.compile();
await graph.invoke({ messages: [...], userId: "user_123" });A path to the module that contains the class, eg. ["langchain", "llms"] Usually should be the same as the entrypoint the class is exported from.
Default streaming implementation. Subclasses should override this method if they support streaming output.
Execute multiple operations in a single batch. This is more efficient than executing operations individually.
Create a new runnable sequence that runs each individual runnable in series, piping the output of one runnable into another runnable or runnable-like.
Streams the execution of the graph, emitting state updates as they occur. This is the primary method for observing graph execution in real-time.
Stream modes:
Creates a new instance of the Pregel graph with updated configuration. This method follows the immutable pattern - instead of modifying the current instance, it returns a new instance with the merged configuration.
The name of the serializable. Override to provide an alias or to preserve the serialized module name in minified environments.
Implemented as a static method to support loading logic.
Returns a drawable representation of the computation graph.