AI Agent Design Patterns: ReAct, Multi-Agent, Graph Workflows, and Handoffs
Part 2 of the AI Agent Tech Stack series. See also: Core Architecture · Framework Comparison · Protocol Layer · Production Practices.
1. ReAct Loop
The most fundamental pattern. The agent cycles through Think → Act → Observe until the task is complete.
Thought: I need to find the current stock price of AAPL.
Action: search("AAPL stock price today")
Observation: AAPL is trading at $198.50.
Thought: Now I have the price. Let me calculate the portfolio value.
Action: calculate(shares=100, price=198.50)
Observation: Portfolio value = $19,850.00
Thought: I have all the information. Let me respond.
Best for: Single-agent tasks with tool use. Frameworks: LangChain, OpenAI Agents SDK.
Reference: ReAct Paper: Synergizing Reasoning and Acting in LLMs
2. Multi-Agent Collaboration
Distribute complex tasks across specialized agents: Planner decomposes, Coder implements, Reviewer checks quality, Executor runs and tests.
Best for: Complex workflows requiring different expertise. Frameworks: CrewAI, AutoGen.
3. Tool-Augmented Agent
The LLM selects and invokes the right tool based on current state. Implemented via Function Calling or MCP.
Best for: Agents needing to interact with external systems. Frameworks: PydanticAI, OpenAI Agents SDK.
4. Graph-Based Workflow (LangGraph)
Model agent logic as a directed graph with stateful nodes and conditional edges. Supports cycles, persistence, and human-in-the-loop.
from langgraph.graph import StateGraph, START, END
graph = StateGraph(AgentState)
graph.add_node("agent", call_model)
graph.add_node("tools", call_tools)
graph.add_edge(START, "agent")
graph.add_conditional_edges("agent", should_continue, {
"continue": "tools", "end": END
})
graph.add_edge("tools", "agent") # loop back
app = graph.compile()
Best for: Complex control flows with state management. Framework: LangGraph.
5. Agent Handoff (OpenAI Agents SDK)
A triage agent classifies user intent and seamlessly delegates to specialized agents (Sales/Support/Tech), preserving full conversation context.
from agents import Agent, Runner
triage = Agent(
name="Triage", instructions="Route to the right specialist.",
handoffs=[sales_agent, support_agent, tech_agent],
)
result = await Runner.run(triage, user_message)
Best for: Customer-facing multi-domain agents. Framework: OpenAI Agents SDK.
Choosing a Pattern
| Pattern | Complexity | Best For |
|---|---|---|
| ReAct | Low | Single-agent + tools |
| Multi-Agent | Medium | Team-based task decomposition |
| Tool-Augmented | Low | External system integration |
| Graph Workflow | High | Stateful multi-step pipelines |
| Handoff | Medium | Multi-domain routing |