Skip to main content

Tool calling agent

info

Tool calling is only available with supported models.

Tool calling allows a model to respond to a given prompt by generating output that matches a user-defined schema. By supplying the model with a schema that matches up with a LangChain tool’s signature, along with a name and description of what the tool does, we can get the model to reliably generate valid input.

We can take advantage of this structured output, combined with the fact that tool calling chat models can choose which tool to call in a given situation, to create an agent that repeatedly calls tools and receives results until a query is resolved.

This is a more generalized version of the OpenAI tools agent, which was designed for OpenAI’s specific style of tool calling. It uses LangChain’s ToolCall interface to support a wider range of provider implementations, such as Anthropic, Google Gemini, and Mistral in addition to OpenAI.

Setup

Most models that support tool calling can be used in this agent. See this list for the most up-to-date information.

This demo also uses Tavily, but you can also swap in another built in tool. You’ll need to sign up for an API key and set it as process.env.TAVILY_API_KEY.

Pick your chat model:

Install dependencies

yarn add @langchain/anthropic @langchain/community

Add environment variables

ANTHROPIC_API_KEY=your-api-key

Instantiate the model

import { ChatAnthropic } from "@langchain/anthropic";

const llm = new ChatAnthropic({
model: "claude-3-sonnet-20240229",
temperature: 0
});

Initialize Tools

We will first create a tool that can search the web:

import { TavilySearchResults } from "@langchain/community/tools/tavily_search";

// Define the tools the agent will have access to.
const tools = [new TavilySearchResults({ maxResults: 1 })];

Create Agent

Next, let’s initialize our tool calling agent:

import { createToolCallingAgent } from "langchain/agents";
import { ChatPromptTemplate } from "@langchain/core/prompts";

// Prompt template must have "input" and "agent_scratchpad input variables"
const prompt = ChatPromptTemplate.fromMessages([
["system", "You are a helpful assistant"],
["placeholder", "{chat_history}"],
["human", "{input}"],
["placeholder", "{agent_scratchpad}"],
]);

const agent = await createToolCallingAgent({
llm,
tools,
prompt,
});

Run Agent

Now, let’s initialize the executor that will run our agent and invoke it!

import { AgentExecutor } from "langchain/agents";

const agentExecutor = new AgentExecutor({
agent,
tools,
});

const result = await agentExecutor.invoke({
input: "what is LangChain?",
});

console.log(result);
{
input: "what is LangChain?",
output: "LangChain is an open-source framework for building applications with large language models (LLMs). S"... 983 more characters
}

Using with chat history

This type of agent can optionally take chat messages representing previous conversation turns. It can use that previous history to respond conversationally. For more details, see this section of the agent quickstart.

import { AIMessage, HumanMessage } from "@langchain/core/messages";

const result2 = await agentExecutor.invoke({
input: "what's my name?",
chat_history: [
new HumanMessage("hi! my name is cob"),
new AIMessage("Hello Cob! How can I assist you today?"),
],
});

console.log(result2);
{
input: "what's my name?",
chat_history: [
HumanMessage {
lc_serializable: true,
lc_kwargs: {
content: "hi! my name is cob",
additional_kwargs: {},
response_metadata: {}
},
lc_namespace: [ "langchain_core", "messages" ],
content: "hi! my name is cob",
name: undefined,
additional_kwargs: {},
response_metadata: {}
},
AIMessage {
lc_serializable: true,
lc_kwargs: {
content: "Hello Cob! How can I assist you today?",
tool_calls: [],
invalid_tool_calls: [],
additional_kwargs: {},
response_metadata: {}
},
lc_namespace: [ "langchain_core", "messages" ],
content: "Hello Cob! How can I assist you today?",
name: undefined,
additional_kwargs: {},
response_metadata: {},
tool_calls: [],
invalid_tool_calls: []
}
],
output: "You said your name is Cob."
}

Help us out by providing feedback on this documentation page: