@langchain/langgraph
Version:
LangGraph
137 lines (136 loc) • 4.5 kB
TypeScript
import { BaseMessage } from "@langchain/core/messages";
import { RunnableConfig, RunnableToolLike } from "@langchain/core/runnables";
import { DynamicTool, StructuredToolInterface } from "@langchain/core/tools";
import { RunnableCallable } from "../utils.js";
import { MessagesAnnotation } from "../graph/messages_annotation.js";
import { END } from "../constants.js";
export type ToolNodeOptions = {
name?: string;
tags?: string[];
handleToolErrors?: boolean;
};
/**
* 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.
*
* @example
* ```ts
* 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[] }
* ```
*
* @example
* ```ts
* 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 execution
* ```
*/
export declare class ToolNode<T = any> extends RunnableCallable<T, T> {
tools: (StructuredToolInterface | DynamicTool | RunnableToolLike)[];
handleToolErrors: boolean;
trace: boolean;
constructor(tools: (StructuredToolInterface | DynamicTool | RunnableToolLike)[], options?: ToolNodeOptions);
protected run(input: any, config: RunnableConfig): Promise<T>;
}
export declare function toolsCondition(state: BaseMessage[] | typeof MessagesAnnotation.State): "tools" | typeof END;