GuideDec 12, 2024

How to Build a LangChain Agent Efficiently

By 2028, one of every three enterprise software applications will include agentic AI. Daily workplace decisions will be made autonomously because intelligent agents transform industries by automating complex workflows with minimal human intervention. (Gartner, 2024)

Build Apps Faster with LangFlow
How to Build a LangChain Agent Efficiently

If you’ve ever wondered how to create an AI assistant to search the web, write code, or help with daily tasks, LangChain is the power plug for creating intelligent agents. This guide walks through creating a LangChain agent step by step, which shows how to make the complex world of AI agents accessible and fun.

Ready to build the next breakthrough AI application? Let’s go!

Setting up your environment

Before diving into agent creation, let's prepare our development environment. Think of it like preparing your kitchen before cooking—you need all the right ingredients.

Create a new directory for your project and set up a Python virtual environment. Please ensure that you have a modern version of Python (preferably 3.8+):

# Create a virtual environment
python -m venv langchain-env

# Activate the virtual environment
# On Windows:
langchain-env\Scripts\activate
# On macOS/Linux:
source langchain-env/bin/activate

Then, you'll need to install the latest LangChain packages:

# Install required packages
pip install langchain openai python-dotenv requests rich ruff

Next, let's create a secret file to store our private API keys. This file should not be shared with anyone or uploaded anywhere. We can create a .env file:

OPENAI_API_KEY=
TAVILY_API_KEY=

Grab the OpenAI API key from the OpenAI console or use Tavily, a search tool made specifically for use with LLMs.

Create a basic LangChain model

Now comes the exciting part—bringing your AI assistant to life!

With LangChain, creating an agent is extremely straightforward since LangChain enables all the abstractions needed to get up and running fast.

import os
from dotenv import load_dotenv
from langchain_community.tools.tavily_search import TavilySearchResults
from langchain_openai import ChatOpenAI
from langchain.agents import AgentExecutor, create_openai_tools_agent
from langchain_core.tools import tool
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.messages import HumanMessage, AIMessage, SystemMessage

# Load environment variables
load_dotenv()

In the above code block, we import a few adapters, namely:

  • ChatOpenAI to connect to OpenAI chat models
  • TavilySearchResults to create a tool to search the web (more on this later)
  • Tool to define a custom function
  • AgentExecutor to create a runtime for agents
  • ChatPromptTemplate to create a prompt template that we can change at runtime by passing our inputs
  • HumanMessage, AIMessage, and SystemMessage classes to create the appropriate message type

Before we create an agent, let's connect to an LLM and test if everything works properly:

llm = ChatOpenAI(
api_key=os.getenv("OPENAI_API_KEY"),
model="gpt-4o-mini",
)

response = llm.invoke([HumanMessage(content="Hello, what is the capital of France?")])
print(response)

And just like that, we have connected to the OpenAI model. You should see a response of the type AIMessage with a "content" key that says something like "The capital of France is Paris." More information is attached to the response, but safely ignore it for now.

Language models are incapable of executing actions; they are configured to only output text. That's where the concept of agents come in. At the core, agents are systems that take a high-level task, use an LLM as a reasoning engine, and decide on the sequence of actions to take.

Defining the tools

Tools give your AI assistant special abilities. Want it to search the web?

There's a tool for that.

Need it to solve math problems? There's a tool for that too! Under the hood, these tools convert into functions that large language models are trained to recognize.

In this example, let's add two tools:

  1. a tool to search the web
  2. a custom tool that adds two numbers

Search tool

For this, we will use Tavily to provide information on current events to the model

search_tool = TavilySearchResults(max_results=3)
search_result = search_tool.invoke("Paris weather")
print(search_result)

Custom tool

For this, we will write a Python function with an appropriate tool name and convert it using the @tool decorator.

@tool
def add_numbers(a: int, b: int) -> int:
"""Add two numbers together."""
return a + b
print(add_numbers.invoke({"a": 1, "b": 2}))
With the two tools defined and tested, we can proceed with connecting them to our language model.
tools = [search_tool, add_numbers]

llm_with_tools = llm.bind_tools(tools)

response_with_tools = llm_with_tools.invoke(
input=[HumanMessage(content="When did the first man land on the moon? What is 40 + 24?")]
)

print(response_with_tools)

We use the bind_tools method to attach the tools to our LLM, and then call it with two questions. If everything is set up correctly, you should see an empty content key, but the tool_calls should be populated with the tools we described above.

The LLM is stating that it wants to call these tools to fetch information, and then provide us with an answer. Note that the LLM does not have the ability to run these tools yet.

Building and configuring the agent

Like every superhero needs their costume and catchphrase, your AI assistant needs its own personality and instructions. Let's start by defining the prompt template:

prompt = ChatPromptTemplate.from_messages(
[
(
"system",
"You are a helpful assistant. Use the available tools to answer the user's question.",
),
("human", "{input}"),
MessagesPlaceholder(variable_name="agent_scratchpad", optional=True),
]
)

prompt.invoke({"input": "When did the first man land on the moon? What is 40 + 24?"})

This creates a prompt object that we can now pass our input to, and it will attach the system prompt automatically. We also have a placeholder message (similar to a scratchpad) for the agent to think and write about its reasoning.

Now that we have the LLM, the tools, and the prompt template in place, we can finally define our agent:

agent = create_openai_tools_agent(llm, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools)

Testing and refining the agent

It’s time to see your assistant in action! Let's give it some tasks to handle:

# Test the agent with some queries
questions = [
"What's the weather like in Paris today?",
"What is 400 + 234?",
]

# Print the results
for question in questions:
response = agent_executor.invoke({"input": question})
print(f"\nQuestion: {question}")
print(f"Answer: {response['output']}")

If you see the responses with the answers to the questions, congratulations! You've just created an agent using the LangChain framework!

Advanced agent development

Agent development is rapidly growing. The above example introduced the basic concepts of an agent and how to create a simple tool-calling agent with LangChain. Advanced features such as retrieval, memory, human-in-the-loop, and dynamic breakpoints evolve these agents into assistants capable of reasoning and executing multiple tasks.

The AgentExecutor is a good starting point and transitions into LangGraph, a library for building stateful, multi-actor applications with LLMs.

Next steps

Congratulations! You've just built your own AI assistant. But this is just the beginning - there's so much more you can do. Try adding new tools, experimenting with different prompts, or teaching your assistant new skills.

A common use case connects agents to vector databases such as Astra DB to enable retrieval-augmented generation (RAG) by defining a retriever tool.

Remember, the best way to learn is by doing. Start small, experiment often, and don't be afraid to make mistakes. Please refer to the LangChain documentation for any queries.

Build Your Own AI Assistant

Create a LangChain agent to build your own AI assistant that automates tasks and integrate advanced tools seamlessly with the DataStax AI Platform.

FAQs

What is a LangChain agent, and how does it work?

A LangChain agent is a dynamic AI agent built within the LangChain framework that uses a language model, such as GPT-4o or Claude 3.5 Sonnet, to reason through tasks. It can call tools like a web search tool, stock price tool, or custom tools dynamically based on user input. By utilizing an internal router, the agent determines the correct tool to use and how to process the final response. LangChain agents are particularly powerful for creating agents that handle multi-step workflows, specific tasks, or external tool integrations.


What are the key components for creating LangChain agents?

To create agents using the LangChain framework, you'll need several key components:

  • A language model: This powers the agent's reasoning engine. Models like OpenAI's GPT-4o are commonly used.
  • Agent tools: These include built-in tools like the web search tool, Wikipedia tool, or custom tools defined using tools.import tool.
  • An agent executor: This handles tool calling and ensures the agent takes the correct intermediate steps to process user input.
  • System prompts and chat history: These provide context to help the agent maintain reasoning across multiple steps or previous interactions.

Should I use a pre-built LangChain agent or create my own agent?

Pre-built LangChain agents, such as the OpenAI tools agent, are ideal for simple tasks like answering queries or performing calculations. However, if you need an agent to handle specific tasks or integrate with proprietary systems, creating a custom agent is the better choice. By defining tools and leveraging the LangChain / LangGraph framework, you can build an agent that works with APIs, search tools, or custom logic. Don’t forget to securely manage API keys and environment variables for external tool integration.


One-stop Data API for Production GenAI

Astra DB gives JavaScript developers a complete data API and out-of-the-box integrations that make it easier to build production RAG apps with high relevancy and low latency.