Agents with create_agent

LangChain · Practical · 14 min

Agents let the model decide which tools to call and when, which most assistant-style apps need.

An agent runs a loop: call the model; if it requested tools, run them and feed back the results; repeat until the model answers without tool calls. create_agent builds this loop on LangGraph:

agent = create_agent(model="openai:gpt-5-mini", tools=[search, get_weather],
                     system_prompt="You are a helpful travel assistant.")
result = agent.invoke({"messages": [{"role": "user", "content": "Weather in Rome?"}]})
result["messages"][-1].text

Key points:

  • Input and output are state dicts with a messages list. The result contains the whole transcript: the user message, AI tool requests, ToolMessages and the final AIMessage.
  • model can be a string or a configured chat model instance.
  • response_format=Schema makes the agent finish with a structured answer in result["structured_response"].
  • checkpointer= adds memory across calls (a later lesson); middleware=[...] customizes behaviour.
  • agent.stream(..., stream_mode="updates") shows each step as it happens.

The agent is a compiled LangGraph graph, so everything LangGraph offers (streaming modes, persistence, interrupts, visualization) applies.

Good agents depend mostly on tool design: few, well-named tools with clear docstrings, compact outputs and helpful error messages. Cap runaway loops with a recursion limit (config={"recursion_limit": 25}) or ModelCallLimitMiddleware.

This replaces the older AgentExecutor and LangGraph's create_react_agent.

Example

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

@tool
def get_weather(city: str) -> str:
    """Get the current weather for a city."""
    return {"rome": "sunny, 24 C", "oslo": "rain, 9 C"}.get(city.lower(), "unknown")

agent = create_agent(
    model="openai:gpt-5-mini",
    tools=[get_weather],
    system_prompt="You are a concise travel assistant.",
)
result = agent.invoke(
    {"messages": [{"role": "user", "content": "Should I pack an umbrella for Oslo?"}]})

for m in result["messages"]:
    print(m.type, "|", m.text or m.tool_calls)
# human | Should I pack an umbrella for Oslo?
# ai | [{'name': 'get_weather', 'args': {'city': 'Oslo'}, ...}]
# tool | rain, 9 C
# ai | Yes, it's raining in Oslo (9 C), so pack an umbrella.

Remember

  • create_agent(model, tools, system_prompt) builds a model-tool loop on LangGraph
  • Invoke with {"messages": [...]}; the result holds the full transcript
  • Tool design and loop limits matter more than prompt tricks

Watch out for

  • Giving an agent dozens of overlapping tools, which makes tool selection unreliable and slow.

Check yourself

  1. When does a create_agent loop stop by default?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: docs.langchain.com/oss/python/langchain/agents