[ PROMPT_NODE_22209 ]
Agents Langchain – Agents
[ SKILL_DOCUMENTATION ]
# LangChain Agents Guide
Complete guide to building agents with ReAct, tool calling, and streaming.
## What are agents?
Agents combine language models with tools to solve complex tasks through reasoning and action:
1. **Reasoning**: LLM decides what to do
2. **Acting**: Execute tools based on reasoning
3. **Observation**: Receive tool results
4. **Loop**: Repeat until task complete
This is the **ReAct pattern** (Reasoning + Acting).
## Basic agent creation
```python
from langchain.agents import create_agent
from langchain_anthropic import ChatAnthropic
# Define tools
def calculator(expression: str) -> str:
"""Evaluate a math expression."""
return str(eval(expression))
def search(query: str) -> str:
"""Search for information."""
return f"Results for: {query}"
# Create agent
agent = create_agent(
model=ChatAnthropic(model="claude-sonnet-4-5-20250929"),
tools=[calculator, search],
system_prompt="You are a helpful assistant. Use tools when needed."
)
# Run agent
result = agent.invoke({
"messages": [{"role": "user", "content": "What is 25 * 17?"}]
})
print(result["messages"][-1].content)
```
## Agent components
### 1. Model - The reasoning engine
```python
from langchain_openai import ChatOpenAI
from langchain_anthropic import ChatAnthropic
# OpenAI
model = ChatOpenAI(model="gpt-4o", temperature=0)
# Anthropic (better for complex reasoning)
model = ChatAnthropic(model="claude-sonnet-4-5-20250929", temperature=0)
# Dynamic model selection
def select_model(task_complexity: str):
if task_complexity == "high":
return ChatAnthropic(model="claude-sonnet-4-5-20250929")
else:
return ChatOpenAI(model="gpt-4o-mini")
```
### 2. Tools - Actions the agent can take
```python
from langchain.tools import tool
# Simple function tool
@tool
def get_current_time() -> str:
"""Get the current time."""
from datetime import datetime
return datetime.now().strftime("%H:%M:%S")
# Tool with parameters
@tool
def fetch_weather(city: str, units: str = "fahrenheit") -> str:
"""Fetch weather for a city.
Args:
city: City name
units: Temperature units (fahrenheit or celsius)
"""
# Your weather API call here
return f"Weather in {city}: 72°{units[0].upper()}"
# Tool with error handling
@tool
def risky_api_call(endpoint: str) -> str:
"""Call an external API that might fail."""
try:
response = requests.get(endpoint, timeout=5)
return response.text
except Exception as e:
return f"Error calling API: {str(e)}"
```
### 3. System prompt - Agent behavior
```python
# General assistant
system_prompt = "You are a helpful assistant. Use tools when needed."
# Domain expert
system_prompt = """You are a financial analyst assistant.
- Use the calculator for precise calculations
- Search for recent financial data
- Provide data-driven recommendations
- Always cite your sources"""
# Constrained agent
system_prompt = """You are a customer support agent.
- Only use search_kb tool to find answers
- If answer not found, escalate to human
- Be concise and professional
- Never make up information"""
```
## Agent types
### 1. Tool-calling agent (recommended)
Uses native function calling for best performance:
```python
from langchain.agents import create_tool_calling_agent, AgentExecutor
from langchain.prompts import ChatPromptTemplate
# Create prompt
prompt = ChatPromptTemplate.from_messages([
("system", "You are a helpful assistant"),
("human", "{input}"),
("placeholder", "{agent_scratchpad}"),
])
# Create agent
agent = create_tool_calling_agent(
llm=model,
tools=[calculator, search],
prompt=prompt
)
# Wrap in executor
agent_executor = AgentExecutor(
agent=agent,
tools=[calculator, search],
verbose=True,
max_iterations=5,
handle_parsing_errors=True
)
# Run
result = agent_executor.invoke({"input": "What is the weather in Paris?"})
```
### 2. ReAct agent (reasoning trace)
Shows step-by-step reasoning:
```python
from langchain.agents import create_react_agent
# ReAct prompt shows thought process
react_prompt = """Answer the following questions as best you can. You have access to the following tools:
{tools}
Use the following format:
Question: the input question you must answer
Thought: you should always think about what to do
Action: the action to take, should be one of [{tool_names}]
Action Input: the input to the action
Observation: the result of the action
... (this Thought/Action/Action Input/Observation can repeat N times)
Thought: I now know the final answer
Final Answer: the final answer to the original input question
Begin!
Question: {input}
Thought: {agent_scratchpad}"""
agent = create_react_agent(
llm=model,
tools=[calculator, search],
prompt=ChatPromptTemplate.from_template(react_prompt)
)
# Run with visible reasoning
result = agent_executor.invoke({"input": "What is 25 * 17 + 142?"})
```
### 3. Conversational agent (with memory)
Remembers conversation history:
```python
from langchain.agents import create_conversational_retrieval_agent
from langchain.memory import ConversationBufferMemory
# Add memory
memory = ConversationBufferMemory(
memory_key="chat_history",
return_messages=True
)
# Conversational agent
agent_executor = AgentExecutor(
agent=agent,
tools=[calculator, search],
memory=memory,
verbose=True
)
# Multi-turn conversation
agent_executor.invoke({"input": "My name is Alice"})
agent_executor.invoke({"input": "What's my name?"}) # Remembers "Alice"
agent_executor.invoke({"input": "What is 25 * 17?"})
```
## Tool execution patterns
### Parallel tool execution
```python
# Agent automatically parallelizes independent calls
agent = create_tool_calling_agent(llm=model, tools=[get_weather, search])
# This calls get_weather("Paris") and get_weather("London") in parallel
result = agent_executor.invoke({
"input": "Compare weather in Paris and London"
})
```
### Sequential tool chaining
```python
# Agent chains tools automatically
@tool
def search_company(name: str) -> str:
"""Search for company information."""
return f"Company ID: 12345, Industry: Tech"
@tool
def get_stock_price(company_id: str) -> str:
"""Get stock price for a company."""
return f"${150.00}"
# Agent will: search_company → get_stock_price
result = agent_executor.invoke({
"input": "What is Apple's current stock price?"
})
```
### Conditional tool usage
```python
# Agent decides when to use tools
@tool
def expensive_tool(query: str) -> str:
"""Use only when necessary - costs $0.10 per call."""
return perform_expensive_operation(query)
# Agent uses tool only if needed
result = agent_executor.invoke({
"input": "What is 2+2?" # Won't use expensive_tool
})
```
## Streaming
### Stream agent steps
```python
# Stream intermediate steps
for step in agent_executor.stream({"input": "Research quantum computing"}):
if "actions" in step:
action = step["actions"][0]
print(f"Tool: {action.tool}, Input: {action.tool_input}")
if "steps" in step:
print(f"Observation: {step['steps'][0].observation}")
if "output" in step:
print(f"Final: {step['output']}")
```
### Stream LLM tokens
```python
from langchain.callbacks import StreamingStdOutCallbackHandler
# Stream model responses
agent_executor = AgentExecutor(
agent=agent,
tools=[calculator],
callbacks=[StreamingStdOutCallbackHandler()],
verbose=True
)
result = agent_executor.invoke({"input": "Explain quantum computing"})
```
## Error handling
### Tool error handling
```python
@tool
def fallible_tool(query: str) -> str:
"""A tool that might fail."""
try:
result = risky_operation(query)
return f"Success: {result}"
except Exception as e:
return f"Error: {str(e)}. Please try a different approach."
# Agent adapts to errors
agent_executor = AgentExecutor(
agent=agent,
tools=[fallible_tool],
handle_parsing_errors=True, # Handle malformed tool calls
max_iterations=5
)
```
### Timeout handling
```python
from langchain.callbacks import TimeoutCallback
# Set timeout
agent_executor = AgentExecutor(
agent=agent,
tools=[slow_tool],
callbacks=[TimeoutCallback(timeout=30)], # 30 second timeout
max_iterations=10
)
```
### Retry logic
```python
from langchain.callbacks import RetryCallback
# Retry on failure
agent_executor = AgentExecutor(
agent=agent,
tools=[unreliable_tool],
callbacks=[RetryCallback(max_retries=3)],
max_execution_time=60
)
```
## Advanced patterns
### Dynamic tool selection
```python
# Select tools based on context
def get_tools_for_user(user_role: str):
if user_role == "admin":
return [search, calculator, database_query, delete_data]
elif user_role == "analyst":
return [search, calculator, database_query]
else:
return [search, calculator]
# Create agent with role-based tools
tools = get_tools_for_user(current_user.role)
agent = create_agent(model=model, tools=tools)
```
### Multi-step reasoning
```python
# Agent plans multiple steps
system_prompt = """Break down complex tasks into steps:
1. Analyze the question
2. Determine required information
3. Use tools to gather data
4. Synthesize findings
5. Provide final answer"""
agent = create_agent(
model=model,
tools=[search, calculator, database],
system_prompt=system_prompt
)
result = agent.invoke({
"input": "Compare revenue growth of top 3 tech companies over 5 years"
})
```
### Structured output from agents
```python
from langchain_core.pydantic_v1 import BaseModel, Field
class ResearchReport(BaseModel):
summary: str = Field(description="Executive summary")
findings: list[str] = Field(description="Key findings")
sources: list[str] = Field(description="Source URLs")
# Agent returns structured output
structured_agent = agent.with_structured_output(ResearchReport)
report = structured_agent.invoke({"input": "Research AI safety"})
print(report.summary, report.findings)
```
## Middleware & customization
### Custom agent middleware
```python
from langchain.agents import AgentExecutor
def logging_middleware(agent_executor):
"""Log all agent actions."""
original_invoke = agent_executor.invoke
def wrapped_invoke(*args, **kwargs):
print(f"Agent invoked with: {args[0]}")
result = original_invoke(*args, **kwargs)
print(f"Agent result: {result}")
return result
agent_executor.invoke = wrapped_invoke
return agent_executor
# Apply middleware
agent_executor = logging_middleware(agent_executor)
```
### Custom stopping conditions
```python
from langchain.agents import EarlyStoppingMethod
# Stop early if confident
agent_executor = AgentExecutor(
agent=agent,
tools=[search],
early_stopping_method=EarlyStoppingMethod.GENERATE, # or FORCE
max_iterations=10
)
```
## Best practices
1. **Use tool-calling agents** - Fastest and most reliable
2. **Keep tool descriptions clear** - Agent needs to understand when to use each tool
3. **Add error handling** - Tools will fail, handle gracefully
4. **Set max_iterations** - Prevent infinite loops (default: 15)
5. **Enable streaming** - Better UX for long tasks
6. **Use verbose=True during dev** - See agent reasoning
7. **Test tool combinations** - Ensure tools work together
8. **Monitor with LangSmith** - Essential for production
9. **Cache tool results** - Avoid redundant API calls
10. **Version system prompts** - Track changes in behavior
## Common pitfalls
1. **Vague tool descriptions** - Agent won't know when to use tool
2. **Too many tools** - Agent gets confused (limit to 5-10)
3. **Tools without error handling** - One failure crashes agent
4. **Circular tool dependencies** - Agent gets stuck in loops
5. **Missing max_iterations** - Agent runs forever
6. **Poor system prompts** - Agent doesn't follow instructions
## Debugging agents
```python
# Enable verbose logging
agent_executor = AgentExecutor(
agent=agent,
tools=[calculator],
verbose=True, # See all steps
return_intermediate_steps=True # Get full trace
)
result = agent_executor.invoke({"input": "Calculate 25 * 17"})
# Inspect intermediate steps
for step in result["intermediate_steps"]:
print(f"Action: {step[0].tool}")
print(f"Input: {step[0].tool_input}")
print(f"Output: {step[1]}")
```
## Resources
- **ReAct Paper**: https://arxiv.org/abs/2210.03629
- **LangChain Agents Docs**: https://docs.langchain.com/oss/python/langchain/agents
- **LangSmith Debugging**: https://smith.langchain.com
Source: claude-code-templates (MIT). See About Us for full credits.