From Single to Multi-Agent Systems
A single agent works well for simple tasks, but complex problems benefit from multiple specialized agents working together — just like how a company has different departments (engineering, design, marketing) rather than one person doing everything.
Architecture Patterns
| Pattern | Description | Best For |
|---|---|---|
| Single Agent | One LLM with tools, handles everything | Simple, well-defined tasks |
| Multi-Agent (Flat) | Multiple peers collaborate as equals | Brainstorming, debate, diverse perspectives |
| Hierarchical | Manager delegates to specialized workers | Complex projects with distinct sub-tasks |
| Pipeline | Agents in sequence, each refining output | Content creation, code review pipelines |
The Orchestrator/Worker Pattern
The most common multi-agent architecture. An orchestrator agent receives the user's request, breaks it into sub-tasks, delegates to worker agents, and aggregates their results.
User Request — "Build me a landing page"
Orchestrator — Plans tasks, assigns to workers
Design Agent — Creates layout and color scheme
Code Agent — Writes HTML/CSS/JS
Copy Agent — Writes compelling text content
Orchestrator — Combines results, ensures quality
Final Response — Complete landing page delivered
// Orchestrator/Worker agent pattern
interface AgentResult {
agent: string;
output: string;
status: 'success' | 'error';
}
interface WorkerAgent {
name: string;
description: string;
execute(task: string, context: Record<string, string>): Promise<AgentResult>;
}
class Orchestrator {
private workers: Map<string, WorkerAgent> = new Map();
registerWorker(agent: WorkerAgent): void {
this.workers.set(agent.name, agent);
}
async handleRequest(userRequest: string): Promise<string> {
// Step 1: Plan — break request into sub-tasks
const plan = await this.planTasks(userRequest);
console.log("Plan:", plan.map(t => t.task));
// Step 2: Execute — delegate to workers
const results: AgentResult[] = [];
const context: Record<string, string> = {};
for (const step of plan) {
const worker = this.workers.get(step.agent);
if (!worker) throw new Error(`No worker: ${step.agent}`);
const result = await worker.execute(step.task, context);
results.push(result);
// Share results with subsequent agents
context[step.agent] = result.output;
}
// Step 3: Aggregate — combine worker outputs
return this.aggregate(userRequest, results);
}
private async planTasks(request: string) {
// LLM decomposes request into steps
return [
{ agent: 'researcher', task: 'Research the topic' },
{ agent: 'writer', task: 'Write the content' },
{ agent: 'reviewer', task: 'Review and refine' },
];
}
private async aggregate(request: string, results: AgentResult[]) {
return results.map(r => r.output).join('\n\n');
}
}
Agent Memory Systems
Agents need memory to be effective. There are three types:
| Memory Type | Duration | Implementation | Use Case |
|---|---|---|---|
| Short-Term | Current conversation | Context window / chat history | Tracking current task state |
| Working Memory | Current session | Scratchpad / variables | Intermediate results, plans |
| Long-Term | Across sessions | Vector database / knowledge base | User preferences, learned facts |
Vector Database for Long-Term Memory
Long-term memory typically uses a vector database. Text is converted to embeddings (dense vectors), stored, and retrieved by semantic similarity — so the agent can recall relevant information even if the exact wording differs.
New Information — Agent learns something worth remembering
Embed — Convert text to vector embedding
Store — Save in vector database with metadata
Later: Query — Search for relevant memories by similarity
Recall — Retrieved memories added to agent context
Architecture Decision Guide
Use Single Agent
- Task is well-defined and bounded
- Can be done with 3-5 tool calls
- Low latency requirement
- Simple workflow, no sub-tasks
Use Multi-Agent
- Task requires diverse expertise
- Multiple independent sub-tasks
- Quality benefits from specialization
- Complex workflows with dependencies
Multi-agent systems add complexity. Each agent call has latency and cost. Start with a single agent and only add more when you've identified clear sub-tasks that benefit from specialization.
Key Takeaways
- Single agent for simple tasks; multi-agent for complex ones requiring diverse expertise
- The orchestrator/worker pattern delegates sub-tasks to specialized agents
- Agent memory: short-term (context), working (scratchpad), long-term (vector DB)
- Vector databases enable semantic memory retrieval across sessions
- Start simple — add agents only when complexity demands it