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].textKey points:
- Input and output are state dicts with a
messageslist. The result contains the whole transcript: the user message, AI tool requests, ToolMessages and the final AIMessage. modelcan be a string or a configured chat model instance.response_format=Schemamakes the agent finish with a structured answer inresult["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.