3 Multi-Agent Patterns in OpenClaw
A complete guide to building AI agent teams — from persistent teams that know each other, to an army of workers that spawn on-demand.
You want to run multiple AI agents on a single OpenClaw Gateway. But what does "multiple agents" actually look like?
A team of 4 agents chatting with each other? One boss that spawns 20 workers simultaneously? A combination of both?
There are three main patterns:
- Role-Based — A persistent team with personality, memory, and expertise
- Orchestrator + Workers — One smart brain that spawns ephemeral workers on-demand
- Hybrid — A persistent team that can also spawn workers
Each pattern has trade-offs. This article breaks down all three — architecture, config, use cases, and when to pick which.
Role-Based Pattern
A startup team — everyone has a role, they know each other, and they remember everything.
Think of it like a company org chart. There's a CEO, CTO, CMO. Each agent has its own desk, brain, and personality. They run persistently, communicate via session tools, and each one has a domain of expertise.
What makes this different from just "running multiple agents" is that these agents are always alive. They're not disposable. They remember. They have opinions.
Key characteristics
- Persistent — always alive, not disposable
- Specialized — each has a domain of expertise
- Personalized — each has a personality via SOUL.md
- Isolated — workspace, memory, and sessions are separate
- Communicative — can message each other via
sessions_send
Architecture
A single Gateway process handles all agents. The routing engine (bindings) decides which agent gets which message — Discord #coding goes to Bob, Telegram goes to Milo.
Here's an example team of four agents, each with a different model suited to its role:
| Agent | Role | Model | Channel |
|---|---|---|---|
| Milo | Leader / Coordinator | Claude Opus | #general, Telegram |
| Bob | Senior Developer | Claude Sonnet | #coding |
| Angela | Marketing & Content | Gemini Pro | #marketing |
| Josh | Business Development | Claude Sonnet | #business |
The config looks like this:
{
"agents": {
"list": [
{
"id": "milo",
"name": "Milo",
"default": true,
"workspace": "~/.openclaw/workspace-milo",
"model": "anthropic/claude-opus-4-6",
},
{
"id": "bob",
"name": "Bob",
"workspace": "~/.openclaw/workspace-bob",
"model": "anthropic/claude-sonnet-4-6",
},
{
"id": "angela",
"name": "Angela",
"workspace": "~/.openclaw/workspace-angela",
"model": "google/gemini-2.5-pro",
"tools": { "deny": ["terminal"] },
},
{
"id": "josh",
"name": "Josh",
"workspace": "~/.openclaw/workspace-josh",
"model": "anthropic/claude-sonnet-4-6",
"tools": { "deny": ["terminal"] },
},
],
},
"bindings": [
{
"agentId": "milo",
"match": {
"channel": "discord",
"peer": { "kind": "channel", "id": "GENERAL_ID" },
},
},
{
"agentId": "bob",
"match": {
"channel": "discord",
"peer": { "kind": "channel", "id": "CODING_ID" },
},
},
{
"agentId": "angela",
"match": {
"channel": "discord",
"peer": { "kind": "channel", "id": "MARKETING_ID" },
},
},
{
"agentId": "josh",
"match": {
"channel": "discord",
"peer": { "kind": "channel", "id": "BUSINESS_ID" },
},
},
{ "agentId": "milo", "match": { "channel": "telegram" } },
],
"tools": {
"agentToAgent": {
"enabled": true,
"allow": ["milo", "bob", "angela", "josh"],
},
},
}
What makes an agent "alive"
Each agent has a workspace. This is their brain:
~/.openclaw/workspace-milo/
├── SOUL.md ← Who they are (personality)
├── AGENTS.md ← SOPs and protocols
├── MEMORY.md ← Long-term memory
├── memory/ ← Daily notes (auto-loaded)
└── skills/ ← Domain-specific skills
SOUL.md defines who the agent is. It's their personality, their rules, their identity:
# Milo — Team Leader
## Identity
You are Milo, the team leader. You manage Bob (dev), Angela (marketing), Josh (business).
## Personality
- Decisive, strategic, no fluff
- ALWAYS delegate coding to Bob, content to Angela, analysis to Josh
- YOU focus on coordination and reporting
Inter-agent communication
This is what makes Role-Based powerful. Agents can talk to each other:
Milo → Bob: "Fix auth bug. Priority HIGH." (sessions_send)
Bob → Milo: "Done. PR #45 ready for review." (response)
Milo → Angela: "Write announcement for this fix." (sessions_send)
The leader can broadcast to everyone, compile status, and report back. All automatic.
Memory — agents that remember
Each agent maintains its own memory system:
- MEMORY.md — persistent notes, loaded every session
- memory/YYYY-MM-DD.md — daily notes, auto-loaded for today and yesterday
- Cross-agent search — the leader can search across all agents' memory
Bob remembers coding patterns. Angela remembers which content performs well. Milo remembers strategic decisions. Everything persists across sessions.
When to use Role-Based
Good fit:
- Small team (2–6 agents) with different domain expertise
- Need persistent memory per domain
- Need personality and ongoing collaboration
- Long-running operational work
Not ideal for:
- One-off batch tasks that need parallelism
- Hundreds of ephemeral workers
- Very limited budget
Orchestrator + Workers
A project manager with freelancers — one smart brain, many fast hands.
One main agent (the Orchestrator) receives all tasks, breaks them into sub-tasks, then spawns worker agents on-demand via sessions_spawn.
Workers are ephemeral. They live for the duration of the task, report results, then die. This isn't a team that knows each other. This is a boss hiring freelancers.
How they compare
| Orchestrator | Workers |
|---|---|
| Persistent (always alive) | Ephemeral (per task) |
| 1 agent | Dynamic — 1 up to 20+ |
| Strongest model (Opus) | Model suited to task |
| Has memory & personality | Disposable, no memory |
| Decompose + compile | Execute single sub-task |
Architecture
The lifecycle is simple: Spawn, Work, Report, Die. Workers have no memory. All learning lives in the Orchestrator.
Config
The setup is minimal. One agent. One workspace. Done.
{
"agents": {
"list": [
{
"id": "orchestrator",
"name": "Orchestrator",
"default": true,
"workspace": "~/.openclaw/workspace",
"model": "anthropic/claude-opus-4-6",
"sandbox": "non-main",
},
],
},
"tools": {
"subAgents": { "enabled": true, "maxConcurrent": 10 },
},
"memory": { "enabled": true, "dailyNotes": true },
}
Compare that with Role-Based, which needs 4+ agent definitions and bindings.
External coding agents via ACP
The Orchestrator can also spawn external tools like Codex or Claude Code:
{
"acp": {
"enabled": true,
"backend": "acpx",
"agents": {
"codex": { "type": "codex", "model": "codex-1" },
"claude-code": { "type": "claude-code", "model": "claude-sonnet-4-6" },
},
},
}
Spawning patterns
There are three ways to spawn workers.
Parallel — for independent sub-tasks:
├── Spawn Worker 1: "Build registration endpoint"
├── Spawn Worker 2: "Build login endpoint"
├── Spawn Worker 3: "Build profile CRUD"
└── All run simultaneously → compile
Sequential — when output A feeds into input B:
Worker 1: Research → output
└→ Worker 2: Outline (from research)
└→ Worker 3: Full draft (from outline)
Fan-out / Fan-in — parallel execution, then compile:
┌── Worker 1: Research A ──┐
├── Worker 2: Research B ──┼── Worker 4: Compile report
└── Worker 3: Research C ──┘
Model selection
The Orchestrator picks the right model for each task:
| Task | Model | Why |
|---|---|---|
| Code generation | Sonnet | Fast, great at code |
| Code review | Opus | Deep reasoning |
| Research | Gemini Pro | Good at synthesis |
| Simple text | GPT-4.1-mini | Cheap |
| GitHub PRs | Codex (ACP) | Native integration |
The Orchestrator's brain
The SOUL.md focuses entirely on decomposition and delegation:
# Orchestrator
## Principles
1. Decompose first — break into independent sub-tasks
2. Parallel when possible — don't serialize independent work
3. Right model for the job
4. Review before deliver — always QA worker output
5. Learn — log patterns in MEMORY.md
## You do NOT: code, research, or write content yourself
## You DO: plan, decompose, delegate, review, compile
And MEMORY.md holds accumulated wisdom from previous runs:
# Patterns Learned
- API features: (endpoints, tests, docs) → parallel
- Blog posts: (research → outline → draft → review) → sequential
- Don't spawn >10 workers at once — diminishing returns
Overnight automation
This is a community favorite. The Orchestrator works while you sleep:
cron: {
jobs: [
{ name: "overnight-start", schedule: "0 23 * * *", agentId: "orchestrator",
message: "Process all pending tasks in MEMORY.md." },
{ name: "morning-report", schedule: "0 7 * * *", agentId: "orchestrator",
message: "Compile overnight results. Send morning brief." },
],
},
heartbeat: {
agents: { orchestrator: { intervalHours: 2, message: "Check worker progress." } },
},
At 11 PM it spawns workers. Every 2 hours it checks progress. At 7 AM you get a morning brief.
When to use Orchestrator
Good fit:
- Parallel tasks that can be decomposed
- One-off batch jobs
- Scale-out (spawn 10+ workers)
- Mixed-model workflows
- Cost optimization (workers pay per use)
Not ideal for:
- Ongoing team collaboration
- Tasks that need deep context across workers
- Need persistent specialists with memory
Hybrid Pattern
A startup team with freelancers — a core team that can hire helpers on-demand.
This is where it gets interesting. You take a persistent team that knows each other (Role-Based) and add the ability to spawn workers when you need to scale (Orchestrator).
This is the most commonly used pattern in production. And for good reason.
Architecture
The key insight: every persistent agent can spawn its own workers. Bob spawns 5 coding workers. Angela spawns 3 content writers. Milo spawns cross-functional research workers.
How it works
Layer 1 — Persistent Team. The core team knows each other, has memory, and communicates via sessions_send:
- Milo (leader) → coordinate
- Bob (dev) → deep coding with context
- Angela (marketing) → content with brand voice
Layer 2 — Ephemeral Workers. Persistent agents spawn workers when they need to scale:
User → Bob: "Refactor the entire auth module — 12 files"
Bob (thinks): "12 files sequential = too slow. Spawn workers."
├── sessions_spawn("Refactor auth/login.ts...")
├── sessions_spawn("Refactor auth/register.ts...")
├── sessions_spawn("Refactor auth/middleware.ts...")
└── ... (9 more workers, parallel)
Workers execute → Bob reviews all results → delivers
Layer 3 — Cross-Team + Workers. Milo combines persistent agents and ephemeral workers in a single plan:
User → Milo: "Launch the new pricing page"
Milo's plan:
1. sessions_send(bob, "Build pricing page frontend") ← persistent
2. sessions_send(angela, "Write copy for pricing tiers") ← persistent
3. sessions_spawn("Research top 10 SaaS pricing pages") ← ephemeral
4. sessions_spawn("Check our page for SEO issues") ← ephemeral
Deep work goes to persistent agents (they have context). Quick tasks go to ephemeral workers (they run in parallel).
### Config
```jsonc
{
"agents": {
"list": [
{
"id": "milo",
"name": "Milo",
"default": true,
"workspace": "~/.openclaw/workspace-milo",
"model": "anthropic/claude-opus-4-6",
"sandbox": "non-main",
},
{
"id": "bob",
"name": "Bob",
"workspace": "~/.openclaw/workspace-bob",
"model": "anthropic/claude-sonnet-4-6",
"sandbox": "non-main",
},
{
"id": "angela",
"name": "Angela",
"workspace": "~/.openclaw/workspace-angela",
"model": "google/gemini-2.5-pro",
"tools": { "deny": ["terminal"] },
},
],
},
"bindings": [
{
"agentId": "milo",
"match": {
"channel": "discord",
"peer": { "kind": "channel", "id": "GENERAL_ID" },
},
},
{
"agentId": "bob",
"match": {
"channel": "discord",
"peer": { "kind": "channel", "id": "CODING_ID" },
},
},
{
"agentId": "angela",
"match": {
"channel": "discord",
"peer": { "kind": "channel", "id": "MARKETING_ID" },
},
},
{ "agentId": "milo", "match": { "channel": "telegram" } },
],
"tools": {
"agentToAgent": { "enabled": true, "allow": ["milo", "bob", "angela"] },
"subAgents": { "enabled": true, "maxConcurrent": 15 },
},
}
The difference from pure Role-Based? You added subAgents.enabled.
The difference from pure Orchestrator? Multiple agents, bindings, and agentToAgent.
Send vs Spawn — a decision framework
When should you use a persistent agent, and when should you spawn a worker?
| When | sessions_send | sessions_spawn |
|---|---|---|
| Need domain expertise | Yes | No |
| Need memory/context | Yes | No |
| Ongoing collaboration | Yes | No |
| Simple, well-defined task | No | Yes |
| Parallel grunt work | No | Yes |
| One-off execution | No | Yes |
Rule of thumb: if the task needs judgment, send it to a persistent agent. If it needs execution, spawn a worker.
A real-world scenario: product launch
Day 1 — Planning (Role-Based layer)
────────────────────────────────────
Milo → Bob: "Review codebase, create release checklist"
Milo → Angela: "Draft launch content plan"
All persistent agents work with full context. They remember past launches.
Day 3 — Execution (Worker layer)
─────────────────────────────────
Bob → spawns 5 workers: fix bug, migration script, API docs, security audit, changelog
Angela → spawns 4 workers: blog post, Twitter thread, LinkedIn post, press release
All workers parallel. Bob & Angela review results.
Day 5 — Delivery (Role-Based layer)
────────────────────────────────────
Milo collects status from everyone → compiles → reports to boss
When to use Hybrid
Almost always. Hybrid is the default recommendation unless:
- You're just starting out — begin with Orchestrator, evolve to Hybrid
- You only do batch processing — pure Orchestrator is enough
- You have a very limited budget — pure Orchestrator with 1 agent
If you're seriously building an AI team for production, go Hybrid.
Putting It All Together
Side-by-side comparison
| Aspect | Role-Based | Orchestrator | Hybrid |
|---|---|---|---|
| Persistent agents | All (4+) | 1 only | Core team (2-4) |
| Ephemeral workers | None | All workers | On-demand |
| Memory | Per agent | Orchestrator only | Per persistent agent |
| Personality | Per agent | Orchestrator only | Per persistent agent |
| Communication | sessions_send | sessions_spawn | Both |
| Config complexity | High | Low | Medium |
| Scaling | Limited (fixed) | High (spawn∞) | Best of both |
| Cost | Steady | Pay per worker | Balanced |
| Analogy | Startup team | PM + freelancers | Team + freelancers |
Decision tree
Need a "team" that knows each other & remembers?
├── Yes → Need scaling (spawn workers)?
│ ├── Yes → HYBRID
│ └── No → ROLE-BASED
└── No → Need parallel batch processing?
├── Yes → ORCHESTRATOR
└── No → A single agent is enough
Migration path
Starting from scratch:
- Start with 1 agent + worker spawning (Orchestrator)
- Notice repeating domains → promote to persistent agents
- Now you have Hybrid
Upgrading from Role-Based to Hybrid:
Add one line — tools: { subAgents: { enabled: true } }
Upgrading from Orchestrator to Hybrid:
Add persistent agents, bindings, and agentToAgent.
From the Community
Here's how real users are running their setups:
| User | Pattern | Setup |
|---|---|---|
| @iamtrebuh | Role-Based | 4 agents, VPS, Telegram, different models |
| @jdrhyne | Role-Based | 15+ agents, 3 machines, 1 Discord server |
| @nateliason | Orchestrator | Spawns Codex for PRs, Claude reviews |
| @bffmike | Orchestrator | Overnight coding agents |
| @antonplex | Orchestrator | Cron + scientist sub-agents |
| @danpeguine | Hybrid | 2 OpenClaw instances, 1 WhatsApp group |
Final Thoughts
All three patterns have their place.
Role-Based is for when you want a team that's alive — agents that know each other and remember everything. The config is more involved, but the result is powerful.
Orchestrator + Workers is for when you want one smart brain that can parallelize work. Simple config, great scaling, pay-per-use economics.
Hybrid combines both. A persistent team that can spawn an army of workers when needed. This is the default recommendation for production.
The best part? You don't have to choose upfront. Start simple with one Orchestrator. As patterns emerge, promote repeating domains into persistent agents. Before you know it, you're running a Hybrid.
OpenClaw's flexibility lets you start from any pattern and migrate to another without rebuilding from scratch.