Three progressively complex patterns for orchestrating LLM-based agents, each solving a real limitation of the previous one.
Use case: An information retrieval agent that searches the web, filters results, generates summaries, and outputs formatted reports.
Search → Filter → Summarize → Format
The simplest approach. Four steps execute in fixed order. Works when the happy path always succeeds.
Limitation: If search returns no results or the summary is low quality, the pipeline blindly continues and outputs garbage.
Input → LLM Classifier → Route to Specialized Handler
├── Funding Handler (tables, amounts, investors)
├── Tech News Handler (GitHub stars, tech stack)
├── Research Handler (papers, experiments, metrics)
└── General Handler (generic summary)
Adds an LLM-based classifier (routes.py) that categorizes the input topic and routes to a domain-specific handler with a tailored prompt. Each handler produces a report format optimized for its domain.
Key design: Classification uses temperature=0.1 + regex fallback + keyword fallback for robustness. Parsing LLM output for routing decisions is inherently fragile, so the triple-fallback chain ensures graceful degradation.
Limitation: Each handler is still a sequential pipeline internally. No retry, no self-correction, no quality control.
Search ──→ Filter ──→ Summarize ──→ Format ──→ End
│ ↑ │ ↑ │ ↑
↓ │ ↓ │ ↓ │
Retry? Expand? Regenerate?
│ │ │
↓ ↓ ↓
Error Search/ Summarize/
Lower Use Current
Threshold
A state machine where nodes (processing steps) and decisions (conditional routing) are separate, composable functions. The AgentState dataclass carries all intermediate results, retry counts, quality scores, and execution logs.
Self-healing mechanisms:
- Search failure → retry up to 3x with exponential backoff
- Too few filtered results → expand search range (2x), then lower filter threshold
- Low quality summary (score < 0.7) → regenerate up to 2x, then graceful degradation
- Max 50 steps to prevent infinite loops
Key insight: Separating nodes.py (what to do) from decisions.py (what to do next) makes the graph easy to extend. Adding a new recovery strategy = adding one decision function, zero changes to existing nodes.
v1_sequential/
info_agent.py # 4-step pipeline
tools.py # search_web + call_llm wrappers
v2_router/
routes.py # LLM classifier with triple-fallback parsing
info_agent.py # 4 domain-specific handlers + router
tools.py
v3_state_graph/
state.py # AgentState dataclass (all intermediate state)
nodes.py # 5 processing nodes
decisions.py # 6 decision functions
graph.py # StateGraph executor (node dispatch + decision routing)
test_report_*.md # Sample outputs
| Pattern | When to use | Trade-off |
|---|---|---|
| Sequential | Prototyping, deterministic tasks | Simple but fragile |
| Router | Multiple domains, different output formats | Better prompts per domain, but no error recovery |
| State Graph | Production agents that must handle failures | Robust but more code to maintain |
The progression mirrors real agent development: start sequential, add routing when prompts get too generic, add state graph when reliability matters.
# Requires DEEPSEEK_API_KEY and SERPER_API_KEY in environment
cd v1_sequential && python info_agent.py
cd v2_router && python info_agent.py
cd v3_state_graph && python graph.py