Types of AI Agents and Architectures
Not all agents are built the same way. Understanding the major patterns helps you choose the right architecture for each problem.
ReAct: Reason + Act
The most common pattern. The model alternates between reasoning steps (thoughts) and action steps (tool calls). Claude handles this naturally through the Messages API — you do not need to inject special "Thought:" tokens like older ReAct implementations.
# Claude automatically interleaves reasoning and tool use
response = client.messages.create(
model="claude-sonnet-4-5",
max_tokens=2048,
system="You are a research assistant. Think through each problem carefully before calling tools.",
tools=[search_tool, calculator_tool],
messages=[{"role": "user", "content": "What is 15% of the GDP of Germany in 2023?"}],
)
# Claude reasons: "I need Germany's GDP, then calculate 15%"
# Claude calls: search("Germany GDP 2023")
# Claude reasons: "GDP is ~$4.1T, so 15% = $615B"
# Claude returns final answer
Plan-and-Execute
Separate planning and execution phases. A planner model creates a task list; executor agents complete each task in parallel or sequence.
# Phase 1: Plan
plan = planner_model.create_plan(goal)
# => ["Search for competitors", "Analyze pricing", "Summarize findings"]
# Phase 2: Execute
results = [executor.run(task) for task in plan]
# Phase 3: Synthesize
final_answer = synthesizer.combine(results)
Good for long, complex tasks where you want visibility into progress.
Reflexion
The agent evaluates its own output, critiques it, and regenerates an improved version. Useful for writing tasks and code generation.
import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic();
async function reflexionLoop(task, maxIterations = 3) {
let draft = await generateDraft(task);
for (let i = 0; i < maxIterations; i++) {
const critique = await client.messages.create({
model: "claude-sonnet-4-5",
max_tokens: 1024,
messages: [
{
role: "user",
content: `Critique this draft and identify specific improvements:\n\n${draft}`,
},
],
});
const improved = await client.messages.create({
model: "claude-sonnet-4-5",
max_tokens: 2048,
messages: [
{
role: "user",
content: `Improve this draft based on the critique.\n\nDraft: ${draft}\n\nCritique: ${critique.content[0].text}`,
},
],
});
draft = improved.content[0].text;
}
return draft;
}
Choosing the Right Architecture
| Use Case | Recommended Pattern |
|---|---|
| Q&A with tool lookups | ReAct |
| Long research tasks | Plan-and-Execute |
| Creative writing / code | Reflexion |
| Complex pipelines | Multi-Agent (Chapter 6) |