Loading...
Loading...
Create LangChain agents with create_agent, define tools, and use middleware for human-in-the-loop and error handling
npx skill4agent add langchain-ai/langchain-skills langchain-fundamentalsfrom langchain.agents import create_agent
from langchain_core.tools import tool
@tool
def search(query: str) -> str:
"""Search for information on the web.
Args:
query: The search query
"""
return f"Results for: {query}"
agent = create_agent(
model="anthropic:claude-sonnet-4-5",
tools=[search],
system_prompt="You are a helpful assistant."
)
result = agent.invoke({"messages": [("user", "Search for LangChain docs")]})Results for: ${query}</typescript>
</quick_start>
<create_agent>
## Creating Agents with create_agent
`create_agent()` is the recommended way to build agents. It handles the agent loop, tool execution, and state management.
### Agent Configuration Options
| Parameter | Purpose | Example |
|-----------|---------|---------|
| `model` | LLM to use | `"anthropic:claude-sonnet-4-5"` or model instance |
| `tools` | List of tools | `[search, calculator]` |
| `system_prompt` / `systemPrompt` | Agent instructions | `"You are a helpful assistant"` |
| `checkpointer` | State persistence | `MemorySaver()` |
| `middleware` | Processing hooks | `[human_in_the_loop_middleware]` |
| `max_iterations` / `maxIterations` | Loop limit | `10` |
</create_agent>
<ex-basic-agent>
<python>
Create a basic agent with a weather tool and invoke it with a user query.
```python
from langchain.agents import create_agent
from langchain_core.tools import tool
@tool
def get_weather(location: str) -> str:
"""Get current weather for a location.
Args:
location: City name
"""
return f"Weather in {location}: Sunny, 72F"
agent = create_agent(
model="anthropic:claude-sonnet-4-5",
tools=[get_weather],
system_prompt="You are a helpful assistant."
)
result = agent.invoke({
"messages": [{"role": "user", "content": "What's the weather in Paris?"}]
})
print(result["messages"][-1].content)Weather in ${location}: Sunny, 72F</typescript>
</ex-basic-agent>
<ex-agent-with-persistence>
<python>
Add MemorySaver checkpointer to maintain conversation state across invocations.
```python
from langchain.agents import create_agent
from langgraph.checkpoint.memory import MemorySaver
checkpointer = MemorySaver()
agent = create_agent(
model="anthropic:claude-sonnet-4-5",
tools=[search],
checkpointer=checkpointer,
)
config = {"configurable": {"thread_id": "user-123"}}
agent.invoke({"messages": [{"role": "user", "content": "My name is Alice"}]}, config=config)
result = agent.invoke({"messages": [{"role": "user", "content": "What's my name?"}]}, config=config)
# Agent remembers: "Your name is Alice"</typescript>
</ex-agent-with-persistence>
<tools>
## Defining Tools
Tools are functions that agents can call. Use the `@tool` decorator (Python) or `tool()` function (TypeScript).
</tools>
<ex-basic-tool>
<python>
Define a calculator tool using the @tool decorator with parameter types.
```python
from langchain_core.tools import tool
@tool
def calculate(expression: str) -> str:
"""Evaluate a mathematical expression safely.
Args:
expression: Math expression like "2 + 2" or "10 * 5"
"""
allowed = set('0123456789+-*/(). ')
if not all(c in allowed for c in expression):
return "Error: Invalid characters in expression"
try:
return str(eval(expression))
except Exception as e:
return f"Error: {e}"Error: ${e}</typescript>
</ex-basic-tool>
<middleware>
## Middleware for Agent Control
Middleware intercepts the agent loop to add human approval, error handling, logging, etc.
</middleware>
<ex-hitl-middleware>
<python>
Require human approval before executing sensitive tools like delete operations.
```python
from langchain.agents import create_agent, human_in_the_loop_middleware
@tool
def delete_record(record_id: str) -> str:
"""Delete a database record permanently.
Args:
record_id: ID of record to delete
"""
db.delete(record_id)
return f"Deleted record {record_id}"
agent = create_agent(
model="anthropic:claude-sonnet-4-5",
tools=[delete_record, search],
middleware=[
human_in_the_loop_middleware(
tools_requiring_approval=["delete_record"]
)
],
)Deleted record ${recordId}</typescript>
</ex-hitl-middleware>
<ex-error-middleware>
<python>
Catch and handle tool errors gracefully with custom middleware.
```python
from langchain.agents import create_agent, wrap_tool_call
@wrap_tool_call
async def error_handler(tool_call, handler):
try:
return await handler(tool_call)
except Exception as error:
return {
**tool_call,
"content": f"Tool error: {str(error)}. Please try a different approach.",
}
agent = create_agent(
model="anthropic:claude-sonnet-4-5",
tools=[risky_tool],
middleware=[error_handler],
)Tool error: ${error}. Please try a different approach.</typescript>
</ex-error-middleware>
<model_config>
## Model Configuration
`create_agent` accepts model strings in `provider:model` format:
</model_config>
<ex-model-instance>
<python>
Pass a model instance with custom settings instead of a model string.
```python
from langchain_anthropic import ChatAnthropic
model = ChatAnthropic(model="claude-sonnet-4-5", temperature=0)
agent = create_agent(model=model, tools=[...])</typescript>
</ex-model-instance>
<fix-missing-tool-description>
<python>
Clear descriptions help the agent know when to use each tool.
```python
# WRONG: Vague or missing description
@tool
def bad_tool(input: str) -> str:
"""Does stuff."""
return "result"
# CORRECT: Clear, specific description with Args
@tool
def search(query: str) -> str:
"""Search the web for current information about a topic.
Use this when you need recent data or facts.
Args:
query: The search query (2-10 words recommended)
"""
return web_search(query)</typescript>
</fix-missing-tool-description>
<fix-no-checkpointer>
<python>
Add checkpointer and thread_id for conversation memory across invocations.
```python
# WRONG: No persistence - agent forgets between calls
agent = create_agent(model="anthropic:claude-sonnet-4-5", tools=[search])
agent.invoke({"messages": [{"role": "user", "content": "I'm Bob"}]})
agent.invoke({"messages": [{"role": "user", "content": "What's my name?"}]})
# Agent doesn't remember!
# CORRECT: Add checkpointer and thread_id
from langgraph.checkpoint.memory import MemorySaver
agent = create_agent(
model="anthropic:claude-sonnet-4-5",
tools=[search],
checkpointer=MemorySaver(),
)
config = {"configurable": {"thread_id": "session-1"}}
agent.invoke({"messages": [{"role": "user", "content": "I'm Bob"}]}, config=config)
agent.invoke({"messages": [{"role": "user", "content": "What's my name?"}]}, config=config)
# Agent remembers: "Your name is Bob"</typescript>
</fix-no-checkpointer>
<fix-infinite-loop>
<python>
Set max_iterations to prevent runaway agent loops.
```python
# WRONG: No iteration limit - could loop forever
agent = create_agent(model="anthropic:claude-sonnet-4-5", tools=[search])
# CORRECT: Set max_iterations
agent = create_agent(
model="anthropic:claude-sonnet-4-5",
tools=[search],
max_iterations=10, # Stop after 10 tool calls
)</typescript>
</fix-infinite-loop>
<fix-accessing-result-wrong>
<python>
Access the messages array from the result, not result.content directly.
```python
# WRONG: Trying to access result.content directly
result = agent.invoke({"messages": [{"role": "user", "content": "Hello"}]})
print(result.content) # AttributeError!
# CORRECT: Access messages from result dict
result = agent.invoke({"messages": [{"role": "user", "content": "Hello"}]})
print(result["messages"][-1].content) # Last message content</typescript>
</fix-accessing-result-wrong>
<related_skills>
- **langgraph-fundamentals**: For custom graph-based agents with StateGraph
- **langgraph-persistence**: For advanced persistence patterns with checkpointers
- **langchain-output**: For structured output with Pydantic/Zod models
- **langchain-rag**: For RAG pipelines with vector stores
</related_skills>