Multi-Agent Design Patterns
Multiple agents collaborating: Group Chat, Hand-off, Round Robin, and when to use them
When Do You Need Multi-Agent?
A single agent is enough for most tasks. But some scenarios need multiple agents:
- Specialization: Each agent excels in one area (code, design, research…)
- Scale: Tasks too large for one agent
- Natural interaction: Agents discuss to reach better outcomes
- Checks & balances: Agent A reviews Agent B’s output
Key Patterns
1. Sequential (Hand-off)
Agents pass results to each other in a chain:
Agent A → Agent B → Agent C → Final Output
import { generateText, tool } from "ai";
import { openai } from "@ai-sdk/openai";
async function researcher(topic: string) {
const result = await generateText({
model: openai("gpt-4o"),
system: "You are a researcher. Find detailed information on the topic.",
tools: { searchWeb },
maxSteps: 5,
prompt: `Research: ${topic}`
});
return result.text;
}
async function writer(research: string) {
const result = await generateText({
model: openai("gpt-4o"),
system: "You are a tech writer. Write articles from research data.",
prompt: `Write a blog from this research:\n${research}`
});
return result.text;
}
async function editor(draft: string) {
const result = await generateText({
model: openai("gpt-4o"),
system: "You are an editor. Review and improve the article.",
prompt: `Review and edit:\n${draft}`
});
return result.text;
}
async function contentPipeline(topic: string) {
const research = await researcher(topic);
const draft = await writer(research);
const finalArticle = await editor(draft);
return finalArticle;
}
2. Parallel (Concurrent)
Agents work simultaneously, results are aggregated:
async function parallelAnalysis(codebase: string) {
const [security, performance, accessibility] = await Promise.all([
generateText({
model: openai("gpt-4o"),
system: "You are a security auditor. Find vulnerabilities.",
prompt: `Audit security:\n${codebase}`
}),
generateText({
model: openai("gpt-4o"),
system: "You are a performance engineer. Find bottlenecks.",
prompt: `Audit performance:\n${codebase}`
}),
generateText({
model: openai("gpt-4o"),
system: "You are an accessibility expert. Check WCAG compliance.",
prompt: `Audit accessibility:\n${codebase}`
})
]);
return {
security: security.text,
performance: performance.text,
accessibility: accessibility.text
};
}
3. Group Chat
Multiple agents discuss with each other, like a meeting:
interface AgentConfig {
name: string;
role: string;
system: string;
}
async function groupChat(
agents: AgentConfig[],
topic: string,
maxRounds: number = 5
) {
const messages: { agent: string; content: string }[] = [];
for (let round = 0; round < maxRounds; round++) {
for (const agent of agents) {
const context = messages
.map(m => `[${m.agent}]: ${m.content}`)
.join("\n");
const response = await generateText({
model: openai("gpt-4o-mini"),
system: `${agent.system}
You are in a group discussion.
Keep responses concise, focused on your role's perspective.
If consensus is reached, say "CONSENSUS".`,
prompt: `Topic: ${topic}\n\nDiscussion history:\n${context}\n\nYour response:`
});
messages.push({ agent: agent.name, content: response.text });
if (response.text.includes("CONSENSUS")) {
return { messages, consensus: true };
}
}
}
return { messages, consensus: false };
}
const result = await groupChat(
[
{ name: "Frontend Dev", role: "frontend", system: "You are a React frontend developer." },
{ name: "Backend Dev", role: "backend", system: "You are a Node.js backend developer." },
{ name: "DevOps", role: "devops", system: "You are a DevOps engineer." }
],
"Should we use SSR or CSR for an e-commerce app?"
);
4. Supervisor Pattern
One agent orchestrates the others:
async function supervisor(task: string) {
const { object: plan } = await generateObject({
model: openai("gpt-4o"),
schema: z.object({
subtasks: z.array(z.object({
description: z.string(),
assignTo: z.enum(["researcher", "coder", "reviewer"]),
priority: z.number()
}))
}),
prompt: `Analyze and assign to appropriate agents: ${task}`
});
const results = [];
for (const subtask of plan.subtasks.sort((a, b) => a.priority - b.priority)) {
const agentFn = getAgent(subtask.assignTo);
const result = await agentFn(subtask.description);
results.push({ subtask: subtask.description, result });
}
return results;
}
Multi-Agent With CrewAI (Python)
from crewai import Agent, Task, Crew, Process
pm = Agent(
role="Product Manager",
goal="Define requirements and prioritize features",
llm="gpt-4o-mini"
)
dev = Agent(
role="Senior Developer",
goal="Implement features according to requirements",
llm="gpt-4o-mini"
)
qa = Agent(
role="QA Engineer",
goal="Test and find bugs in implementation",
llm="gpt-4o-mini"
)
crew = Crew(
agents=[pm, dev, qa],
tasks=[
Task(description="Analyze requirements", agent=pm),
Task(description="Implement solution", agent=dev),
Task(description="Test and review", agent=qa)
],
process=Process.sequential # or Process.hierarchical
)
Which Pattern to Choose?
| Scenario | Pattern |
|---|---|
| Content pipeline (research → write → edit) | Sequential |
| Code audit (security + performance + a11y) | Parallel |
| Design review needing multiple perspectives | Group Chat |
| Complex task requiring coordination | Supervisor |
| Simple automation chain | Sequential |
Summary
- Sequential: Pass results through a chain of agents
- Parallel: Agents work simultaneously, results aggregated
- Group Chat: Agents discuss to reach consensus
- Supervisor: One agent orchestrates the others
- Start with a single agent, only use multi-agent when truly needed