How to Use Tools in LangChain and Build Powerful AI Agents

🔧 How to Use Tools in LangChain and Build Powerful AI Agents
LangChain makes it super easy to build powerful AI agents that can reason, call external tools, and provide dynamic responses. In this tutorial, we’ll walk through a simple example using LangChain's tool interface and how to integrate it with LangChain agents using both the classic AgentExecutor and the newer createReactAgent.
🧠 What We’re Building
We’ll build a basic AI agent that can call a custom function called magic_function. This function takes two numbers and returns their sum with a little twist: it adds 2 to the result!
For example:
magic_function(input=3, addedNumber=10) ➜ 15
🔨 Step 1: Define the LLM
LangChain agents are powered by language models. We'll use OpenAI’s gpt-3.5-turbo via LangChain:
const llm = new ChatOpenAI({
model: 'gpt-3.5-turbo',
temperature: 0.7,
});
🪄 Step 2: Create a Tool
Using LangChain’s tool() utility, we define a function that can be invoked by the agent when needed.
const magicTool = tool(
async ({ input, addedNumber }: { input: number; addedNumber: number }) => {
return `${input + 2 + addedNumber}`;
},
{
name: 'magic_function',
description: 'Applies a magic function to an input.',
schema: z.object({
input: z.number(),
addedNumber: z.number(),
}),
}
);
This function uses Zod to validate the inputs, making sure our tool gets only valid data.
🧰 Step 3: Add Tools to the Agent
Next, we gather our tools into an array:
const tools = [magicTool];
We also define a prompt template for the agent:
const prompt = ChatPromptTemplate.fromMessages([
['system', 'You are a helpful assistant'],
['human', '{input}'],
['placeholder', '{agent_scratchpad}'],
]);
Sure! Here's the explanation you can place right under the line:
['placeholder', '{agent_scratchpad}'],
🧠 What Is {agent_scratchpad} and Why Do We Need It?
The {agent_scratchpad} placeholder is essential for agent reasoning. It serves as a dynamic placeholder in the prompt where the agent will keep track of its thoughts, previous actions, and intermediate results.
When the agent is working on a task, it may need to:
- Think through the steps it will take
- Call one or more tools
- Reflect on tool outputs
- Decide what to do next
LangChain automatically fills in {agent_scratchpad} during execution with:
- The tool it decided to use
- The input it gave that tool
- The output it received
This lets the agent "see" what it's done so far and continue its reasoning. Without this placeholder, the model wouldn't have access to its own thinking process, which is critical for complex tasks that require multi-step reasoning or tool chaining.
So in short:
✅ It gives memory to the agent within the current task
✅ It enables transparent and interpretable reasoning
✅ It supports iterative tool use when needed
🤖 Step 4: Create and Run an AgentExecutor
Now we create an agent that knows how to call tools based on user input:
const agent = createToolCallingAgent({
llm,
tools,
prompt,
});
const agentExecutor = new AgentExecutor({
agent,
tools,
});
To run it:
const query =
'what is the value of magic_function with input=3 and addedNumber=10?';
await agentExecutor.invoke({ input: query });
⚛️ Bonus: Using React Agents with LangGraph
LangChain also supports React-style agents via createReactAgent, which provides a more dynamic interaction flow using LangGraph under the hood:
const app = createReactAgent({
llm,
tools,
});
Then we invoke it like this:
let agentOutput = await app.invoke({
messages: [
{
role: 'user',
content: query,
},
],
});
console.log(agentOutput);
🤔 What Is createReactAgent Doing?
The createReactAgent function is a higher-level abstraction that builds a LangGraph-based agent. Here's what it handles behind the scenes:
- Dynamic Tool Use: It interprets user messages and decides which tools (like
magic_function) to call, and in what order, using a step-by-step reasoning process. - Stateful Interactions: Unlike simple agents, LangGraph agents are capable of managing more complex control flows and decision trees. This allows the agent to loop, retry, or take conditional paths in its logic.
- Multi-Turn Support: It handles sequences of messages as part of a conversation, not just a single prompt.
- Built-in Scratchpad: The agent automatically maintains a record of previous tool calls, messages, and decisions in a "scratchpad" memory. This helps the LLM reason more effectively.
- Tool Routing: It routes each decision to the appropriate tool, parses arguments based on Zod schemas, and executes them with the correct inputs.
In short, createReactAgent makes it easier to build graph-style agents that are robust, adaptable, and ready for real-world applications.
This is perfect for use cases where you want to process multi-turn dialogues or have more complex workflows.
🧪 Final Code
Here’s a condensed version of the whole flow:
// ... (imports)
const llm = new ChatOpenAI({ model: 'gpt-4-mini', temperature: 0.7 });
const magicTool = tool(
async ({ input, addedNumber }) => `${input + 2 + addedNumber}`,
{
name: 'magic_function',
description: 'Applies a magic function to an input.',
schema: z.object({
input: z.number(),
addedNumber: z.number(),
}),
}
);
const tools = [magicTool];
const query = 'what is the value of magic_function with input=3 and addedNumber=10?';
const prompt = ChatPromptTemplate.fromMessages([
['system', 'You are a helpful assistant'],
['human', '{input}'],
['placeholder', '{agent_scratchpad}'],
]);
const agent = createToolCallingAgent({ llm, tools, prompt });
const agentExecutor = new AgentExecutor({ agent, tools });
const main = async () => {
await agentExecutor.invoke({ input: query });
const app = createReactAgent({ llm, tools });
let agentOutput = await app.invoke({
messages: [{ role: 'user', content: query }],
});
console.log(agentOutput);
};
main();
🚀 Conclusion
LangChain’s tool and agent system lets you build intelligent, interactive apps with minimal effort. Whether you're creating smart chatbots, automating tasks, or building data agents, LangChain gives you the right primitives to succeed.