Build Your First LangChain Agent with create_agent

A
Author
08 Nov, 2026 4 min read 0 views

The fastest way to build a tool-using agent in LangChain is create_agent. You give it a model, a list of tools and a system prompt, and it returns a runnable agent that loops between the model and the tools until it has an answer. This post builds one, shows how to read the result and explains what happens inside the loop.

Install and import

pip install langchain langchain-anthropic python-dotenv

create_agent lives in langchain.agents in current LangChain releases. Older tutorials use create_react_agent from langgraph.prebuilt, which works in a similar way. If your installed version does not have create_agent, upgrade LangChain or use that older function.

The agent

from dotenv import load_dotenv
from langchain.agents import create_agent
from langchain_core.tools import tool

load_dotenv()

@tool
def get_weather(city: str) -> str:
    """Get the current weather for a city."""
    data = {"Paris": "18C and cloudy", "Tokyo": "25C and sunny"}
    return data.get(city, "no data for that city")

@tool
def convert_c_to_f(celsius: float) -> float:
    """Convert degrees Celsius to Fahrenheit."""
    return celsius * 9 / 5 + 32

agent = create_agent(
    model="anthropic:claude-sonnet-5-5",
    tools=[get_weather, convert_c_to_f],
    system_prompt="You are a concise weather assistant. Use tools for facts.",
)

result = agent.invoke(
    {"messages": [{"role": "user", "content": "What is the weather in Tokyo in Fahrenheit?"}]}
)
print(result["messages"][-1].content)

The input is a dictionary with a messages list. The output has the same shape, with every message from the run appended. The last message is the final answer, here a sentence saying Tokyo is about 77 degrees Fahrenheit and sunny.

Read the trace

The agent made several model calls. Printing the full message list shows each step:

for message in result["messages"]:
    print(type(message).__name__, "->", message.content)
    if getattr(message, "tool_calls", None):
        print("   tool calls:", message.tool_calls)

You will see this sequence:

  1. HumanMessage: the question.
  2. AIMessage with a tool call to get_weather for Tokyo.
  3. ToolMessage: "25C and sunny".
  4. AIMessage with a tool call to convert_c_to_f.
  5. ToolMessage: 77.0.
  6. AIMessage: the final answer with no tool calls, which ends the loop.

The exact path can vary, since the model chooses it, but reading the trace is the best way to debug an agent.

Stream the steps

for step in agent.stream(
    {"messages": [{"role": "user", "content": "Weather in Paris?"}]},
    stream_mode="updates",
):
    print(step)

With stream_mode="updates", each item shows which node ran (the model or the tools) and the messages it added. This is useful for progress displays.

Under the hood

The returned agent is a LangGraph graph with a model node and a tools node and a conditional edge between them. That is why the same agent supports checkpointers, streaming modes and interrupts, which later posts cover. You can start simple and use those features without rewriting the agent.

Common mistakes

  • Passing a string instead of the {"messages": [...]} dictionary to invoke.
  • Writing tool docstrings that are empty or vague, so the model picks the wrong tool.
  • Expecting memory across invoke calls. Without a checkpointer, each call starts fresh.
  • No limit on steps. Set a recursion limit in the config when you move to production: agent.invoke(input, config={"recursion_limit": 10}).

Adding a system prompt that works

The system prompt is where you set the agent's role, its limits and its habits. Keep it short and concrete. Say what the agent is for, which tools to prefer, how to format answers and what to do when it cannot help. For example, "If a tool returns no data, say so instead of guessing" prevents a common failure where the model fills gaps with invented facts. Test the prompt by asking questions the tools cannot answer and checking that the agent admits it.

Choosing the model for an agent

Agents need models that follow tool schemas reliably. Larger models make fewer wrong tool choices, and smaller ones are cheaper and faster. A sensible workflow is to build with a strong model, write a handful of test questions, then try a smaller model and keep it only if the tests still pass. Because LangChain accepts a model string, this experiment means changing one line. Keep temperature low for agents, since random variation in tool arguments rarely helps.

Where to go next

Once this agent works, the useful upgrades are memory, so that follow-up questions work, and tracing, so that you can see why a run went wrong. Both are covered later in this course. Until then, keep tools small, test them alone, and build a short list of example questions you can run after every change. That list becomes your first regression test.

Was this article helpful?

Comments

No comments yet. Have a question or a tip? Be the first to share it.

Leave a comment

Comments are reviewed before they appear.