Multi-Agent Systems
A Multi-Agent System is a collection of AI Agents that work together — each specialising in a specific role — to solve complex problems that a single agent cannot handle well on its own.
Think of it like a well-run company. One agent acts as the manager (orchestrator), another handles research, another writes content, and another reviews it. Each agent does what it is best at, and together they produce results far superior to what any single agent could achieve alone.
Why Use Multiple Agents?
A single agent trying to do everything — research, write, review, code, and test — will eventually struggle. Here is why multiple agents are better:
| Challenge with Single Agent | How Multi-Agent Solves It |
|---|---|
| Context window fills up on long tasks | Each agent handles a smaller, focused portion |
| Single agents make more errors on complex tasks | Specialised agents have deeper focus in their domain |
| No parallel execution possible | Multiple agents can work simultaneously |
| Hard to debug monolithic agent logic | Each agent's input and output can be inspected separately |
Multi-Agent Architecture Patterns
Pattern 1 — Orchestrator + Workers
A central Orchestrator Agent manages the workflow. It breaks the task into sub-tasks, assigns them to Worker Agents, collects results, and synthesises the final answer.
[User Request]
|
[Orchestrator Agent]
/ | \
[Research [Writer [Reviewer
Agent] Agent] Agent]
\ | /
[Orchestrator Agent]
|
[Final Answer]
Pattern 2 — Sequential Pipeline
Agents work in a chain — the output of one agent becomes the input of the next. Each agent transforms the data in a specific way.
[Data Collector] → [Analyser] → [Writer] → [Editor] → [Final Output]
Pattern 3 — Parallel Agents
Multiple agents run at the same time on different sub-tasks, then their results are merged.
[Task Split]
/ | \
[Agent A] [Agent B] [Agent C]
(Finance) (Market) (Risk)
\ | /
[Merge Results]
|
[Final Report]
Building a Multi-Agent System from Scratch
A Blog Writing Multi-Agent System will be built with three specialised agents:
- Research Agent — Gathers information on the topic
- Writer Agent — Writes a blog post from the research
- Editor Agent — Reviews and improves the draft
# multi_agent_blog.py
import os
from dotenv import load_dotenv
import openai
load_dotenv()
client = openai.OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
# ─── Base Agent Class ─────────────────────────────────────────────
class Agent:
def __init__(self, name: str, role: str, model: str = "gpt-4o"):
self.name = name
self.role = role
self.model = model
def run(self, task: str, context: str = "") -> str:
"""Run the agent with a task and optional context from previous agents."""
messages = [
{"role": "system", "content": self.role}
]
if context:
messages.append({
"role": "user",
"content": f"Context from previous steps:\n{context}\n\nYour task:\n{task}"
})
else:
messages.append({"role": "user", "content": task})
response = client.chat.completions.create(
model=self.model,
messages=messages,
temperature=0.4,
max_tokens=1000
)
result = response.choices[0].message.content
print(f"\n{'─'*50}")
print(f"[{self.name}] completed task")
print(f"Output preview: {result[:200]}...")
print(f"{'─'*50}")
return result
# ─── Define Specialised Agents ────────────────────────────────────
research_agent = Agent(
name="Research Agent",
role="""You are a research specialist. When given a topic:
1. List the 5 most important facts about it
2. Identify the main challenges or debates around it
3. Note any recent developments
4. Provide a concise, factual summary suitable for a blog post
Keep the output structured and factual. Do not write the blog — only research."""
)
writer_agent = Agent(
name="Writer Agent",
role="""You are an expert blog writer. When given research:
1. Write an engaging blog post (600-800 words)
2. Start with an attention-grabbing introduction
3. Use clear headings (H2 and H3)
4. Include the key facts naturally in the text
5. End with a strong conclusion
Write in a clear, friendly tone for a general audience."""
)
editor_agent = Agent(
name="Editor Agent",
role="""You are a professional editor. When given a blog draft:
1. Check for clarity and flow
2. Fix any awkward sentences
3. Ensure headings are logical
4. Improve the opening and closing if needed
5. Return the FULL improved version of the blog post
Make targeted improvements without changing the core content."""
)
# ─── Orchestrator ─────────────────────────────────────────────────
class BlogOrchestrator:
def __init__(self):
self.research_agent = research_agent
self.writer_agent = writer_agent
self.editor_agent = editor_agent
def run(self, topic: str) -> str:
print(f"\n{'='*55}")
print(f"🎯 Topic: {topic}")
print(f"{'='*55}")
# Step 1: Research
print("\n📚 Step 1: Research Agent working...")
research = self.research_agent.run(
task=f"Research this topic thoroughly: {topic}"
)
# Step 2: Write
print("\n✍️ Step 2: Writer Agent working...")
draft = self.writer_agent.run(
task=f"Write a blog post about: {topic}",
context=research
)
# Step 3: Edit
print("\n🔍 Step 3: Editor Agent working...")
final_post = self.editor_agent.run(
task="Review and improve this blog post draft",
context=draft
)
print(f"\n{'='*55}")
print("✅ FINAL BLOG POST:")
print(f"{'='*55}")
print(final_post)
return final_post
# Test
if __name__ == "__main__":
orchestrator = BlogOrchestrator()
orchestrator.run("The Rise of AI Agents in 2024")
Adding an Agent Communication Protocol
In more advanced systems, agents need to communicate with each other — not just pass data forward. Here is a simple message bus pattern:
class AgentMessage:
def __init__(self, sender: str, recipient: str,
content: str, message_type: str = "task"):
self.sender = sender
self.recipient = recipient
self.content = content
self.message_type = message_type # "task", "result", "error"
self.timestamp = __import__("datetime").datetime.now()
class MessageBus:
def __init__(self):
self.messages = []
def send(self, message: AgentMessage):
self.messages.append(message)
print(f"[{message.sender}] → [{message.recipient}]: {message.content[:80]}...")
def get_messages_for(self, agent_name: str) -> list:
return [m for m in self.messages if m.recipient == agent_name]
Parallel Execution with Multi-Agent
import concurrent.futures
def run_agents_in_parallel(agents_and_tasks: list) -> list:
"""
Run multiple agents simultaneously.
agents_and_tasks: list of (agent, task) tuples
"""
results = []
with concurrent.futures.ThreadPoolExecutor() as executor:
futures = {
executor.submit(agent.run, task): (agent.name, task)
for agent, task in agents_and_tasks
}
for future in concurrent.futures.as_completed(futures):
agent_name, task = futures[future]
result = future.result()
results.append({"agent": agent_name, "result": result})
print(f"✅ {agent_name} finished")
return results
# Example: Research 3 topics simultaneously
tasks = [
(research_agent, "Python programming language"),
(research_agent, "JavaScript frameworks in 2024"),
(research_agent, "Rust programming language")
]
parallel_results = run_agents_in_parallel(tasks)
Real-World Multi-Agent Use Cases
| System | Agents Involved |
|---|---|
| E-commerce Order Processing | Order Agent, Payment Agent, Inventory Agent, Notification Agent |
| Software Development Pipeline | Requirements Agent, Coder Agent, Test Writer Agent, Code Reviewer Agent |
| Financial Analysis Platform | Data Collector Agent, Analyser Agent, Risk Agent, Report Generator Agent |
| Customer Support System | Triage Agent, FAQ Agent, Escalation Agent, Follow-up Agent |
Best Practices for Multi-Agent Systems
- Keep each agent focused: Each agent should do one thing well
- Define clear interfaces: Standardise how agents pass data to each other
- Log every agent interaction: Makes debugging and auditing possible
- Handle failures gracefully: If one agent fails, the system should recover
- Test agents independently: Each agent should work correctly on its own before being combined
Summary
Multi-Agent Systems enable complex, high-quality work by dividing it among specialised agents. The Orchestrator + Workers pattern is the most common architecture — with a central coordinator managing specialised workers for research, writing, editing, coding, and more. Agents can run sequentially, in pipelines, or in parallel. This pattern is what powers production-level AI applications that go far beyond simple question-and-answer.
