This guide explains how to build conversational AI agents using LangGraph and LangChain. It covers core concepts, components, and patterns for creating flexible, stateful agents.
from typing import TypedDict, List, Dict
class AgentState(TypedDict):
messages: List # Conversation history
context: Dict # Current context/domain
parameters: Dict # Extracted parameters
analysis: Dict # Analysis results
current_step: str # Current workflow stepfrom langgraph.graph import StateGraph, START, END
from langgraph.prebuilt import ToolNode, tools_condition
# Basic graph structure
builder = StateGraph(AgentState)
builder.add_node("process_input", process_input)
builder.add_node("tools", ToolNode(tools))
builder.add_edge(START, "process_input")def example_tool(param1: str, param2: int) -> Dict:
"""Tools must have type hints and docstrings"""
return {"result": "processed"}
tools = [
example_tool,
another_tool
]
# Bind tools to LLM
llm_with_tools = llm.bind_tools(tools)def route_condition(state: AgentState) -> str:
"""Route to next node based on state"""
if "calculation" in state["context"]:
return "calculator"
return "END"
builder.add_conditional_edges(
"process_input",
route_condition,
{
"calculator": "calculate",
"END": END
}
)from langchain_core.messages import SystemMessage
sys_msg = SystemMessage(content="""You are a helpful assistant that can:
1. [Capability 1]
2. [Capability 2]
Always: [Behavior rules]
Never: [Restrictions]""")def classify_intent(state: AgentState) -> Dict:
"""Determine user's intent"""
intent_prompt = SystemMessage(content="""
RESPOND WITH ONE WORD from: [list of intents]
Message: {user_message}
""")
response = llm.invoke([intent_prompt])
return {"intent": response.content}def extract_parameters(state: AgentState) -> Dict:
"""Extract parameters from user message"""
extraction_prompt = SystemMessage(content="""
Extract parameters as JSON:
Message: {message}
Parameters: [list parameters]
""")
return {"parameters": extracted_params}def generate_response(state: AgentState) -> Dict:
"""Generate contextual response"""
context = state["context"]
analysis = state["analysis"]
response_prompt = SystemMessage(content="""
Based on:
Context: {context}
Analysis: {analysis}
Generate response that: [requirements]
""")
return {"messages": [response]}User Input → Intent Classification → Parameter Extraction → Processing → Response
User Input → Analysis → Intermediate State → Response Generation → Output
User Input → Tool Selection → Tool Execution → Result Processing → Response
def update_state(old_state: Dict, new_data: Dict) -> Dict:
"""Preserve important state while updating"""
return {
**old_state,
"context": {**old_state["context"], **new_data},
"messages": old_state["messages"] + [new_message]
}def store_analysis(state: Dict, analysis: Dict) -> Dict:
"""Store analysis results for future reference"""
return {
**state,
"analysis": {
"timestamp": current_time,
"results": analysis,
"context": state["context"]
}
}-
State Management
- Keep all relevant data in state
- Use TypedDict for type safety
- Preserve conversation history
-
Tool Design
- Clear docstrings
- Type hints
- Error handling
- Deterministic outputs
-
Prompt Engineering
- Clear instructions
- Examples
- Constraints
- Expected output format
-
Error Handling
- State recovery
- Graceful degradation
- User feedback
from langchain_core.messages import SystemMessage, HumanMessage
from langchain_openai import ChatOpenAI
from langgraph.graph import StateGraph, MessagesState, START, END
from langgraph.prebuilt import ToolNode, tools_condition
# 1. Define tools
tools = [tool1, tool2, tool3]
# 2. Initialize LLM
llm = ChatOpenAI(
model="gpt-4",
temperature=0
)
llm_with_tools = llm.bind_tools(tools)
# 3. Define system message
sys_msg = SystemMessage(content="System instructions...")
# 4. Create nodes
def process_input(state: MessagesState):
"""Process user input"""
return {"messages": processed}
# 5. Build graph
builder = StateGraph(MessagesState)
builder.add_node("process", process_input)
builder.add_node("tools", ToolNode(tools))
# 6. Add edges
builder.add_edge(START, "process")
builder.add_conditional_edges(
"process",
tools_condition,
)
builder.add_edge("tools", "process")
# 7. Compile
graph = builder.compile()- Basic Interaction Testing
state = {"messages": [sys_msg]}
response = graph.invoke(state)- Tool Testing
test_inputs = [
"use tool1 with param x",
"calculate something",
]- Edge Case Testing
error_cases = [
"", # Empty input
"unknown command", # Invalid input
"quit", # Exit commands
]- Not preserving state properly
- Missing error handling
- Unclear tool definitions
- Overly complex routing logic
- Insufficient prompt engineering
- LangGraph Documentation
- LangChain Documentation
- OpenAI API Documentation
- Example Agents Repository