#Agents handing off work to each other
1 messages Ā· Page 1 of 1 (latest)
Hello?
Yep, use the session tools, not files.
Best pattern
- New parallel workers:
sessions_spawn- Returns immediately with
status: "accepted"+runId+childSessionKey - That is your receipt/ack
- When the child finishes, OpenClaw does a push-based announce back up the chain
- Returns immediately with
- Already-running agent/session:
sessions_sendtimeoutSeconds: 0= enqueue and return immediatelytimeoutSeconds: >0= wait for the reply inline
So for fan-out / fan-in:
- Orchestrator calls
sessions_spawnonce per worker - Each call gives immediate acceptance
- Workers finish and announce results back
- Orchestrator synthesizes and returns final output
A couple important knobs:
- If a sub-agent needs to spawn its own workers, set
agents.defaults.subagents.maxSpawnDepth: 2 - If you want to target other agent profiles, allow them with
agents.defaults.subagents.allowAgents
I would not use heartbeat + file polling for this. OpenClaw already has first-class async handoff for exactly this case.
Docs:
- https://docs.openclaw.ai/tools/subagents
- https://docs.openclaw.ai/concepts/session-tool
- https://docs.openclaw.ai/concepts/multi-agent
If you want, I can sketch the exact orchestrator flow for:
- spawn N workers and wait for announces, or
- send tasks into existing persistent sessions.
1 please
Cool, for spawn N workers and wait for announces, the clean pattern is:
1. Enable the orchestrator pattern
{
agents: {
defaults: {
subagents: {
maxSpawnDepth: 2,
maxChildrenPerAgent: 5
}
}
}
}
Why: with maxSpawnDepth: 2, a depth-1 sub-agent can act as an orchestrator and spawn worker children.
2. Orchestrator flow
Inside the orchestrator session:
- call
sessions_spawn(...)once per worker - store each returned
runId/childSessionKey - each spawn returns immediate ack:
status: "accepted"runIdchildSessionKey
That is your receipt confirmation.
3. Wait the OpenClaw way
After spawning, use sessions_yield.
That ends the turn and lets the child completion announces arrive as the next messages, instead of building a polling loop.
4. Fan-in
As worker results arrive:
- collect them
- once all expected workers have announced back
- synthesize the final result
- reply once
Minimal pseudo-flow
spawn worker A -> accepted
spawn worker B -> accepted
spawn worker C -> accepted
sessions_yield()
announce from A arrives
announce from B arrives
announce from C arrives
combine results
return final answer
Important bit
Do not do:
- file drop + heartbeat polling
- tight loops over
sessions_list/subagents list
OpenClawās built-in announce chain is the intended async return path.
Docs
If you want, I can also write a concrete example orchestrator prompt/tool sequence for 3 workers.
Is this for 1 main agent and 2 or 3 sub-agents that spawn and disappear? I have 10 agents right now, 1 main/coordinator and 9 that I want to be specialists and are persistent, available on Discord. Please Is this even possible out of the box with Openclaw?
Yes, what I described first is mainly the ephemeral worker pattern:
sessions_spawn+mode: "run"= spawn, do the task, announce result, disappearsessions_spawn+thread: true, mode: "session"= persistent thread-bound sessionsessions_send= talk to an already-existing persistent session/agent
For your setup, with 1 coordinator + 9 persistent specialists, the better fit is usually:
Recommended pattern for your case
- keep the 9 specialists as persistent sessions
- have the coordinator hand work to them with
sessions_send - let them reply back through the same session tool path
So yes, this is possible in OpenClaw, but not with the defaults alone. You need to turn on the cross-agent/session plumbing.
The important config bits
- Enable agent-to-agent
{
tools: {
agentToAgent: {
enabled: true,
allow: ["coordinator", "research", "planner", "coder", "qa"]
}
}
}
- Let session tools see beyond spawned children
{
tools: {
sessions: {
visibility: "all"
}
}
}
- Allow the session tools on the agents that need them
sessions_listsessions_historysessions_send- optionally
sessions_spawnif you also want ephemeral workers
My honest take
If you want specialists that are always around on Discord, use persistent sessions + sessions_send.
If you want temporary parallel workers, use sessions_spawn.
A lot of people end up with a hybrid:
- persistent specialists for known roles
- spawned workers for bursty parallel work
One caveat
Cross-agent messaging is off by default, so this is not āzero configā, but it is supported out of the box once you enable those knobs.
Short answer
- Spawn and disappear? Yes, thatās the normal
sessions_spawnpattern. - 10 persistent specialists on Discord? Also yes, but use persistent sessions +
sessions_send, not heartbeat files.
Docs:
If you want, I can give you a minimal config sketch for 1 coordinator + 9 specialists on Discord next.
yes, please!
Nice. If I were setting up 1 coordinator + 9 persistent Discord specialists, Iād do one main Discord-facing coordinator, then create persistent thread-bound specialist sessions and route coordinator handoffs with sessions_send.
That avoids file polling, and you do not need 10 bot tokens unless you want 10 separate bot identities.
Minimal config sketch
{
agents: {
defaults: {
subagents: {
runTimeoutSeconds: 900,
},
},
list: [
{
id: "coordinator",
workspace: "~/.openclaw/workspace-coordinator",
tools: {
allow: [
"read",
"exec",
"sessions_list",
"sessions_history",
"sessions_send",
"sessions_spawn",
"session_status",
],
},
subagents: {
allowAgents: [
"research",
"planner",
"coder",
"qa",
"docs",
"ops",
"support",
"analyst",
"reviewer",
],
requireAgentId: true,
},
},
{ id: "research", workspace: "~/.openclaw/workspace-research" },
{ id: "planner", workspace: "~/.openclaw/workspace-planner" },
{ id: "coder", workspace: "~/.openclaw/workspace-coder" },
{ id: "qa", workspace: "~/.openclaw/workspace-qa" },
{ id: "docs", workspace: "~/.openclaw/workspace-docs" },
{ id: "ops", workspace: "~/.openclaw/workspace-ops" },
{ id: "support", workspace: "~/.openclaw/workspace-support" },
{ id: "analyst", workspace: "~/.openclaw/workspace-analyst" },
{ id: "reviewer", workspace: "~/.openclaw/workspace-reviewer" },
],
},
bindings: [
{ agentId: "coordinator", match: { channel: "discord", accountId: "default" } },
],
tools: {
agentToAgent: {
enabled: true,
allow: [
"coordinator",
"research",
"planner",
"coder",
"qa",
"docs",
"ops",
"support",
"analyst",
"reviewer",
],
},
sessions: {
visibility: "all",
},
},
channels: {
discord: {
threadBindings: {
enabled: true,
spawnSubagentSessions: true,
idleHours: 24,
maxAgeHours: 0,
},
},
},
}
How Iād use it
One-time bootstrap
From the coordinator, spawn each specialist once as a persistent Discord thread session:
sessions_spawn({ agentId: "research", thread: true, mode: "session", task: "You are the research specialist..." })- repeat for planner, coder, QA, etc.
That gives you persistent specialist threads on Discord.
Normal operation
Coordinator fans out with sessions_send:
sessions_send(sessionKey: "...research...", message: "...", timeoutSeconds: 0)sessions_send(sessionKey: "...qa...", message: "...", timeoutSeconds: 0)- etc.
Then either:
- wait for replies inline with timeouts, or
- do async collection / synthesis
Recommendation
For your exact setup, Iād recommend:
- persistent thread-bound specialist sessions
sessions_sendfor handoffsessions_spawnonly for initial creation or for temporary burst workers
Important caveat
If by āavailable on Discordā you mean each specialist should appear as a separate Discord bot/account, that is a different setup. Then use multiple Discord accountIds + bindings. If you just want separate persistent specialists humans can visit and the coordinator can talk to, threads are the simpler path.
Docs:
- https://docs.openclaw.ai/concepts/multi-agent
- https://docs.openclaw.ai/concepts/session-tool
- https://docs.openclaw.ai/tools/subagents
- https://docs.openclaw.ai/gateway/configuration-reference
If you want, I can do the next step and turn this into a real config for your 10 agent names.
Yes, please Odin (coordinator), Frigg, Bragi, Mimir, Thor, Loki, Freya, Heimdall, Skadi and Bob. Same pattern as your sketch, with actual names and workspaces.
Yep, hereās a concrete starting point for your crew.
{
agents: {
defaults: {
subagents: {
runTimeoutSeconds: 900,
},
},
list: [
{
id: "odin",
name: "Odin",
workspace: "~/.openclaw/workspace-odin",
tools: {
allow: [
"read",
"exec",
"sessions_list",
"sessions_history",
"sessions_send",
"sessions_spawn",
"session_status",
],
},
subagents: {
allowAgents: [
"frigg",
"bragi",
"mimir",
"thor",
"loki",
"freya",
"heimdall",
"skadi",
"bob",
],
requireAgentId: true,
},
},
{ id: "frigg", name: "Frigg", workspace: "~/.openclaw/workspace-frigg" },
{ id: "bragi", name: "Bragi", workspace: "~/.openclaw/workspace-bragi" },
{ id: "mimir", name: "Mimir", workspace: "~/.openclaw/workspace-mimir" },
{ id: "thor", name: "Thor", workspace: "~/.openclaw/workspace-thor" },
{ id: "loki", name: "Loki", workspace: "~/.openclaw/workspace-loki" },
{ id: "freya", name: "Freya", workspace: "~/.openclaw/workspace-freya" },
{ id: "heimdall", name: "Heimdall", workspace: "~/.openclaw/workspace-heimdall" },
{ id: "skadi", name: "Skadi", workspace: "~/.openclaw/workspace-skadi" },
{ id: "bob", name: "Bob", workspace: "~/.openclaw/workspace-bob" },
],
},
bindings: [
{ agentId: "odin", match: { channel: "discord", accountId: "default" } },
],
tools: {
agentToAgent: {
enabled: true,
allow: [
"odin",
"frigg",
"bragi",
"mimir",
"thor",
"loki",
"freya",
"heimdall",
"skadi",
"bob",
],
},
sessions: {
visibility: "all",
},
},
channels: {
discord: {
threadBindings: {
enabled: true,
spawnSubagentSessions: true,
idleHours: 24,
maxAgeHours: 0,
},
},
},
}
One-time bootstrap from Odin
Spawn each specialist once as a persistent thread session:
sessions_spawn({ agentId: "frigg", thread: true, mode: "session", task: "You are Frigg, a persistent specialist agent..." })
sessions_spawn({ agentId: "bragi", thread: true, mode: "session", task: "You are Bragi, a persistent specialist agent..." })
sessions_spawn({ agentId: "mimir", thread: true, mode: "session", task: "You are Mimir, a persistent specialist agent..." })
sessions_spawn({ agentId: "thor", thread: true, mode: "session", task: "You are Thor, a persistent specialist agent..." })
sessions_spawn({ agentId: "loki", thread: true, mode: "session", task: "You are Loki, a persistent specialist agent..." })
sessions_spawn({ agentId: "freya", thread: true, mode: "session", task: "You are Freya, a persistent specialist agent..." })
sessions_spawn({ agentId: "heimdall", thread: true, mode: "session", task: "You are Heimdall, a persistent specialist agent..." })
sessions_spawn({ agentId: "skadi", thread: true, mode: "session", task: "You are Skadi, a persistent specialist agent..." })
sessions_spawn({ agentId: "bob", thread: true, mode: "session", task: "You are Bob, a persistent specialist agent..." })
Normal fan-out from Odin
After those exist, Odin hands off with sessions_send, for example:
sessions_send(sessionKey: "<frigg-session>", message: "Analyze this requirement", timeoutSeconds: 0)
sessions_send(sessionKey: "<mimir-session>", message: "Gather background context", timeoutSeconds: 0)
sessions_send(sessionKey: "<thor-session>", message: "Stress test the plan", timeoutSeconds: 0)
Then Odin collects and synthesizes.
If you want, next I can do a role assignment pass too, like:
- Frigg = planning
- Bragi = writing
- Mimir = research
- Thor = execution
- Loki = adversarial review
- etc.
This is great! A few questions:
a. When Odin calls sessions_send to a specialist, do humans in Odin's Discord channel see that routing, or is it invisible?
b. After idleHours: 24 timeout, does the session die (needing re-spawn) or just sleep? Does the specialist remember prior conversations across wakes?
c. Two rapid sessions_send to one specialist ā serial or parallel by default?
d. Specialist LLM fails ā does sessions_send return the error, retry, or die silently?
e. Does agentToAgent.allow permit N-to-N messaging, or only coordinator-to-specialist? Can I restrict to odin-only?
f. If I want each Asgardian to appear as a distinct Discord bot (Odin, Thor, Loki as separate identities, not one bot routing) ā what's the config?
g. AGENTS.md reloading: if I update Frigg's AGENTS.md, does her persistent session pick it up on next wake, or do I need a gateway restart? (Had a bootstrap cache issue earlier today.)
Yep, and there are a couple important gotchas here.
a) Is sessions_send visible in Odinās Discord channel?
Usually no. The handoff itself is internal.
What happens under the hood:
sessions_sendstarts the target run withdeliver: false- so humans in Odinās channel do not see ārouting to Thorā¦ā spam
But two caveats:
- If Odin later summarizes the result, humans see that
- The built-in agent-to-agent announce step can post into the target specialistās bound channel/thread, so humans watching Thorās thread may see a specialist-side message there
So, short version: invisible in Odinās channel, potentially visible in the specialistās own thread.
b) After idleHours: 24, does the specialist die?
No, idle timeout removes the thread binding, it does not inherently kill the session.
Important distinction:
- thread binding = āthis Discord thread routes to that sessionā
- session = transcript + memory/context for that agent session
So after idle timeout:
- the thread may unfocus
- the session can still exist
- if it still exists, it keeps its history and remembers prior conversation
But subagents also have auto-archive. Default is archiveAfterMinutes: 60.
For truly persistent specialists, I would set:
{
agents: {
defaults: {
subagents: {
archiveAfterMinutes: 0
}
}
}
}
That disables auto-archive. Without that, your āpersistentā specialists may vanish after an hour.
c) Two rapid sessions_send calls to one specialist, serial or parallel?
Serial by default for the same target session.
OpenClaw queues runs by session key, so one session gets one active run at a time.
So:
- Odin -> Thor twice quickly = queued/serialized
- Odin -> Thor and Odin -> Mimir = can run in parallel, because different sessions
d) Specialist LLM fails, what does sessions_send do?
It depends on how you called it:
timeoutSeconds > 0
You get a tool result back:status: "ok"status: "error"
status: "timeout"
So it does not die silently in the waited mode.
timeoutSeconds: 0
You get immediate:status: "accepted"
After that, failure is async. If the later announce flow fails, that is not returned to the original caller turn.
So for critical workflows, Iād use:
- waited
sessions_sendwhen you need confirmation/error now - fire-and-forget only when async is okay
Also, normal provider/model retry-failover can still happen underneath if you configured it, but sessions_send itself is not a special retry wrapper.
e) Is agentToAgent.allow N-to-N or coordinator-only?
Itās effectively N-to-N among the allowlisted agents. It is not directional.
So if odin, thor, and mimir are all in the allowlist, then:
- Odin -> Thor works
- Thor -> Mimir also works
- Mimir -> Odin works
If you want practical odin-only brokering, the right move is:
- keep
tools.agentToAgent.enabled: true - include the specialists in the allowlist
- only give
sessions_send/sessions_spawnto Odin - do not allow those tools on the specialists
That gives you coordinator-only behavior in practice.
f) Distinct Discord bot identities for each Asgardian?
Yes, but each one needs its own Discord bot token/application.
Pattern is:
{
agents: {
list: [
{ id: "odin", workspace: "~/.openclaw/workspace-odin" },
{ id: "thor", workspace: "~/.openclaw/workspace-thor" },
{ id: "loki", workspace: "~/.openclaw/workspace-loki" },
],
},
bindings: [
{ agentId: "odin", match: { channel: "discord", accountId: "odin" } },
{ agentId: "thor", match: { channel: "discord", accountId: "thor" } },
{ agentId: "loki", match: { channel: "discord", accountId: "loki" } },
],
channels: {
discord: {
accounts: {
odin: { token: "DISCORD_BOT_TOKEN_ODIN" },
thor: { token: "DISCORD_BOT_TOKEN_THOR" },
loki: { token: "DISCORD_BOT_TOKEN_LOKI" },
},
},
},
}
Then invite each bot to the server and configure its guild/channel allowlists.
So:
- one bot, many routed specialists = cheaper/simpler
- many bots, one per agent = distinct identities, more setup
g) If I update AGENTS.md, does Frigg pick it up next wake?
Yes, on the next turn. No gateway restart should be needed.
Reason: OpenClaw builds the system prompt on every run, and that includes workspace bootstrap files like AGENTS.md.
So:
- current in-flight turn = old prompt
- next turn in Friggās session = new
AGENTS.md
The thing that is more cache/snapshot-sensitive is skills, not AGENTS.md.
If you hit the weird bootstrap issue earlier, Iād be more suspicious of:
- stale
BOOTSTRAP.md - a stuck bootstrapping session
- stale session-store state
not ordinary AGENTS.md reload.
My recommendations for your setup
If you go with persistent Asgardians, Iād set:
{
agents: {
defaults: {
subagents: {
archiveAfterMinutes: 0
}
}
},
channels: {
discord: {
threadBindings: {
enabled: true,
idleHours: 24,
maxAgeHours: 0,
spawnSubagentSessions: true
}
}
}
}
And keep sessions_send / sessions_spawn on Odin only.
Docs:
- https://docs.openclaw.ai/concepts/session-tool
- https://docs.openclaw.ai/tools/subagents
- https://docs.openclaw.ai/concepts/multi-agent
- https://docs.openclaw.ai/channels/discord
- https://docs.openclaw.ai/gateway/configuration-reference
If you want, I can do one more pass and give you a final production-ready config for either:
- single Discord bot + routed specialists, or
- 10 separate Discord bot identities.
Thanks, clear answers. Yes please for the final production-ready config ā 10 separate Discord bot identities. One bot per Asgardian and Bob.
Two follow-ups on that:
-
Since agentToAgent allowlist is N-to-N, and I want Odin-only brokering: should the specialists' tool allowlists explicitly NOT include sessions_send / sessions_spawn? What's the minimum tool set a specialist needs?
-
Bootstrap flow ā once I have the config deployed and bots invited, what's the sequence to go from "nothing running" to "10 persistent threads and agents alive on Discord"? Is there a one-time setup script I run, or does it happen organically as Odin calls sessions_spawn the first time?
Yep. For 10 separate Discord bot identities, Iād use a slightly different architecture than the earlier thread-bound-subagent sketch:
Recommended architecture
- Odin + 9 specialists are normal configured agents
- each one has its own Discord bot token/accountId
- each one is bound to its own Discord account via
bindings - Odin brokers with
sessions_send - do not use
sessions_spawnto create the core 10 specialists
That means the specialists are āaliveā because their bots are connected, not because they were spawned as subagents.
Follow-up 1, Odin-only brokering
Yes, exactly:
Specialists should not have
sessions_sendsessions_spawnsessions_listsessions_history
That is the clean way to enforce Odin-only brokering, since tools.agentToAgent.allow itself is symmetric.
Minimum specialist tool set
The true minimum is:
tools: {
allow: ["read"]
}
That is the safest starting point.
Then add only what each specialist actually needs:
- research type agents:
web_search,web_fetch - coding/execution type agents:
exec, mayberead - browser/UI agents:
browser - file-writing agents:
write,edit,apply_patchif you trust them
But for strict coordinator-only brokering, no session tools on specialists.
Iād also set:
session: {
agentToAgent: {
maxPingPongTurns: 0
}
}
That disables auto back-and-forth ping-pong between agents.
Production-ready config skeleton, 10 Discord bot identities
This assumes:
- one Discord application/token per bot
- one Discord guild
- one dedicated channel per bot (simplest production setup)
{
session: {
agentToAgent: {
maxPingPongTurns: 0,
},
},
tools: {
agentToAgent: {
enabled: true,
allow: [
"odin",
"frigg",
"bragi",
"mimir",
"thor",
"loki",
"freya",
"heimdall",
"skadi",
"bob",
],
},
sessions: {
visibility: "all",
},
},
agents: {
list: [
{
id: "odin",
name: "Odin",
workspace: "~/.openclaw/workspace-odin",
tools: {
allow: [
"read",
"exec",
"sessions_list",
"sessions_history",
"sessions_send",
"session_status",
],
},
},
{
id: "frigg",
name: "Frigg",
workspace: "~/.openclaw/workspace-frigg",
tools: { allow: ["read"] },
},
{
id: "bragi",
name: "Bragi",
workspace: "~/.openclaw/workspace-bragi",
tools: { allow: ["read"] },
},
{
id: "mimir",
name: "Mimir",
workspace: "~/.openclaw/workspace-mimir",
tools: { allow: ["read"] },
},
{
id: "thor",
name: "Thor",
workspace: "~/.openclaw/workspace-thor",
tools: { allow: ["read"] },
},
{
id: "loki",
name: "Loki",
workspace: "~/.openclaw/workspace-loki",
tools: { allow: ["read"] },
},
{
id: "freya",
name: "Freya",
workspace: "~/.openclaw/workspace-freya",
tools: { allow: ["read"] },
},
{
id: "heimdall",
name: "Heimdall",
workspace: "~/.openclaw/workspace-heimdall",
tools: { allow: ["read"] },
},
{
id: "skadi",
name: "Skadi",
workspace: "~/.openclaw/workspace-skadi",
tools: { allow: ["read"] },
},
{
id: "bob",
name: "Bob",
workspace: "~/.openclaw/workspace-bob",
tools: { allow: ["read"] },
},
],
},
bindings: [
{ agentId: "odin", match: { channel: "discord", accountId: "odin" } },
{ agentId: "frigg", match: { channel: "discord", accountId: "frigg" } },
{ agentId: "bragi", match: { channel: "discord", accountId: "bragi" } },
{ agentId: "mimir", match: { channel: "discord", accountId: "mimir" } },
{ agentId: "thor", match: { channel: "discord", accountId: "thor" } },
{ agentId: "loki", match: { channel: "discord", accountId: "loki" } },
{ agentId: "freya", match: { channel: "discord", accountId: "freya" } },
{ agentId: "heimdall", match: { channel: "discord", accountId: "heimdall" } },
{ agentId: "skadi", match: { channel: "discord", accountId: "skadi" } },
{ agentId: "bob", match: { channel: "discord", accountId: "bob" } },
],
channels: {
discord: {
groupPolicy: "allowlist",
accounts: {
odin: {
token: "DISCORD_BOT_TOKEN_ODIN",
guilds: {
"YOUR_GUILD_ID": {
channels: {
"ODIN_CHANNEL_ID": { allow: true, requireMention: false },
},
},
},
},
frigg: {
token: "DISCORD_BOT_TOKEN_FRIGG",
guilds: {
"YOUR_GUILD_ID": {
channels: {
"FRIGG_CHANNEL_ID": { allow: true, requireMention: false },
},
},
},
},
bragi: {
token: "DISCORD_BOT_TOKEN_BRAGI",
guilds: {
"YOUR_GUILD_ID": {
channels: {
"BRAGI_CHANNEL_ID": { allow: true, requireMention: false },
},
},
},
},
mimir: {
token: "DISCORD_BOT_TOKEN_MIMIR",
guilds: {
"YOUR_GUILD_ID": {
channels: {
"MIMIR_CHANNEL_ID": { allow: true, requireMention: false },
},
},
},
},
thor: {
token: "DISCORD_BOT_TOKEN_THOR",
guilds: {
"YOUR_GUILD_ID": {
channels: {
"THOR_CHANNEL_ID": { allow: true, requireMention: false },
},
},
},
},
loki: {
token: "DISCORD_BOT_TOKEN_LOKI",
guilds: {
"YOUR_GUILD_ID": {
channels: {
"LOKI_CHANNEL_ID": { allow: true, requireMention: false },
},
},
},
},
freya: {
token: "DISCORD_BOT_TOKEN_FREYA",
guilds: {
"YOUR_GUILD_ID": {
channels: {
"FREYA_CHANNEL_ID": { allow: true, requireMention: false },
},
},
},
},
heimdall: {
token: "DISCORD_BOT_TOKEN_HEIMDALL",
guilds: {
"YOUR_GUILD_ID": {
channels: {
"HEIMDALL_CHANNEL_ID": { allow: true, requireMention: false },
},
},
},
},
skadi: {
token: "DISCORD_BOT_TOKEN_SKADI",
guilds: {
"YOUR_GUILD_ID": {
channels: {
"SKADI_CHANNEL_ID": { allow: true, requireMention: false },
},
},
},
},
bob: {
token: "DISCORD_BOT_TOKEN_BOB",
guilds: {
"YOUR_GUILD_ID": {
channels: {
"BOB_CHANNEL_ID": { allow: true, requireMention: false },
},
},
},
},
},
},
},
}
Important design note
With this setup, your āpersistent thingā is not a spawned thread session.
It is:
- the bot account
- plus the botās channel session in its dedicated Discord channel
That is cleaner than trying to keep 10 spawned subagent threads alive forever.
Follow-up 2, bootstrap flow from zero to live
Short answer
With separate bot identities, this happens mostly organically.
You do not need sessions_spawn to bring the 10 core agents online.
Recommended startup sequence
1. Put config in place
- add all 10 agents
- add all 10 Discord accounts/tokens
- add all bindings
- invite all 10 bots to the guild/channels
2. Start the gateway
Run:
openclaw status
openclaw gateway status
You want to see the gateway healthy and the Discord accounts connected.
3. Seed each bot once
Send one manual message in each dedicated bot channel, for example:
- in Odin channel:
hello Odin - in Thor channel:
hello Thor - etc.
That creates the initial live session for each bot in the exact Discord channel you want.
This is the least magical, most reliable bootstrap.
4. Discover/cache the session keys
Once each bot has one live session, Odin can use:
sessions_list- then
sessions_sendto those discovered specialist sessions
If you want stability, capture those session keys once and keep them in Odinās working notes / memory.
Should this be scripted?
Optional, not required.
There is no special mandatory ābootstrap all agentsā command.
For this architecture, Iād say:
- manual first message per bot = best initial bootstrap
- after that, itās organic
If you really want a scripted bootstrap, you can do one later, but I would not start there. Iām a little wary of making the very first session creation more clever than it needs to be.
My practical recommendation
For your exact goal, Iād do this:
- 10 Discord bot accounts
- 1 dedicated channel per bot
- Odin only gets session tools
- specialists start with
readonly - expand specialist tools role-by-role later
- bootstrap by sending one message per bot channel
- after that, Odin brokers with
sessions_send
Thatās the cleanest production baseline I can recommend.
Docs:
- https://docs.openclaw.ai/concepts/multi-agent
- https://docs.openclaw.ai/concepts/session-tool
- https://docs.openclaw.ai/channels/discord
- https://docs.openclaw.ai/gateway/configuration-reference
- https://docs.openclaw.ai/tools/agent-send
If you want, next I can give you a role-based version of the config, where each Asgardian gets a more realistic tool set instead of the ultra-minimal read baseline.
Yes, please
Nice. Hereās the role-based version Iād actually start with.
Suggested roles
- Odin: coordinator / router / synthesizer
- Frigg: planning / sequencing / project structure
- Bragi: writing / docs / polished output
- Mimir: research / retrieval / background context
- Thor: execution / commands / builds / heavy lifting
- Loki: adversarial review / edge cases / red-team critique
- Freya: UX / tone / human-facing copy / product feel
- Heimdall: monitoring / watching / surfacing anomalies
- Skadi: testing / validation / hardening
- Bob: utility generalist / overflow helper
Tool policy Iād use
Rule of thumb:
- only Odin gets session tools
- only execution agents get
exec - only writing agents get
write/edit/apply_patch - only research agents get
web_search/web_fetch - add
browseronly to a specialist that truly needs it
Drop-in agents.list version
{
agents: {
list: [
{
id: "odin",
name: "Odin",
workspace: "~/.openclaw/workspace-odin",
tools: {
allow: [
"read",
"exec",
"web_search",
"web_fetch",
"sessions_list",
"sessions_history",
"sessions_send",
"session_status",
],
},
},
{
id: "frigg",
name: "Frigg",
workspace: "~/.openclaw/workspace-frigg",
tools: {
allow: [
"read",
"web_search",
"web_fetch",
],
},
},
{
id: "bragi",
name: "Bragi",
workspace: "~/.openclaw/workspace-bragi",
tools: {
allow: [
"read",
"web_search",
"web_fetch",
"write",
"edit",
"apply_patch",
],
},
},
{
id: "mimir",
name: "Mimir",
workspace: "~/.openclaw/workspace-mimir",
tools: {
allow: [
"read",
"web_search",
"web_fetch",
],
},
},
{
id: "thor",
name: "Thor",
workspace: "~/.openclaw/workspace-thor",
tools: {
allow: [
"read",
"exec",
],
},
},
{
id: "loki",
name: "Loki",
workspace: "~/.openclaw/workspace-loki",
tools: {
allow: [
"read",
"web_search",
"web_fetch",
],
},
},
{
id: "freya",
name: "Freya",
workspace: "~/.openclaw/workspace-freya",
tools: {
allow: [
"read",
"web_search",
"web_fetch",
"write",
"edit",
],
},
},
{
id: "heimdall",
name: "Heimdall",
workspace: "~/.openclaw/workspace-heimdall",
tools: {
allow: [
"read",
"exec",
],
},
},
{
id: "skadi",
name: "Skadi",
workspace: "~/.openclaw/workspace-skadi",
tools: {
allow: [
"read",
"exec",
],
},
},
{
id: "bob",
name: "Bob",
workspace: "~/.openclaw/workspace-bob",
tools: {
allow: [
"read",
"exec",
"web_search",
"web_fetch",
],
},
},
],
},
}
My two practical tweaks
- If you want extra safety, add explicit denies on every specialist:
deny: ["sessions_send", "sessions_spawn", "sessions_list", "sessions_history"]
- If one agent becomes your browser/UI specialist, give only that one:
"browser"
Not everyone. Browser everywhere gets chaotic fast š
My recommendation
This is the first version Iād actually run:
- Odin brokers
- Mimir researches
- Bragi writes
- Thor executes
- Loki critiques
- Skadi tests
- Heimdall monitors
- Bob catches overflow
Thatās a pretty solid crew.
If this fixed it, please right-click the solution message ā Apps ā ā Mark Solution so Answer Overflow can index it for future folks.
This is amazing! If I'm reading you correctly. With the proper configuration we can have multiagents working together. Correct?
Yes, exactly. š
With the right config, OpenClaw can absolutely do multi-agent coordination:
- one coordinator, many specialists
- agent-to-agent handoff with
sessions_send - parallel workers with
sessions_spawn - persistent specialists or ephemeral workers
- separate Discord bot identities if you want
The big caveat is that itās configured orchestration, not magic swarm mode out of the box.
You need to wire:
- agent bindings
- session visibility
- agent-to-agent allowlist
- per-agent tool policies
Once thatās set, yes, they can work together cleanly.
If this fixed it, please right-click the solution message ā Apps ā ā Mark Solution. That helps Answer Overflow index it for future people.
Anything else you can suggest to help the agents be more proactive?
Yep, a few things help a lot.
Best ways to make them more proactive
1. Prefer events over generic heartbeat
Heartbeat works, but itās blunt.
Better:
- cron jobs for scheduled checks
- webhooks for external events
- hooks for local/runtime events
That makes agents wake up for a reason, not just āgo think nowā.
2. Give each agent a very explicit āwhen to actā rule
In each agentās AGENTS.md, add stuff like:
- āIf you detect X, notify Odinā
- āIf confidence is low, ask Mimirā
- āIf a task is blocked for >10 minutes, escalateā
- āIf you find a risky change, ask Loki/Skadi to reviewā
Proactive agents usually need clear trigger conditions, not just ābe proactiveā.
3. Use Standing Orders for recurring behavior
Great for:
- daily summaries
- watchlists
- follow-up reminders
- āif you notice this pattern, do thatā
4. Give Odin an explicit delegation policy
For example:
- Mimir for research
- Bragi for writing
- Thor for execution
- Loki for criticism
- Skadi for testing
The more deterministic the handoff policy, the more reliably Odin will fan work out on its own.
5. Let specialists send signals, not just answers
A nice pattern is:
- specialists donāt just solve tasks
- they also emit:
blockedneeds reviewhigh riskready to mergewaiting on human
That makes orchestration way more proactive.
6. Use cheap models for routine monitoring
For heartbeat / cron / watch tasks, put them on a cheaper model. Save the expensive model for actual synthesis and hard problems.
7. Keep them narrow
Counterintuitively, agents get more proactive when their job is smaller and clearer.
A vague āgeneral helperā waits.
A crisp āmonitor logs and escalate anomalies to Odinā acts.
My practical recipe
If I were building your Asgard setup, Iād add:
- cron for scheduled checks
- webhooks/hooks for event-driven wakes
- standing orders for recurring behavior
- explicit escalate-to-Odin rules in every specialist
- explicit delegate-to-specialist rules in Odin
That gets you from āmulti-agentā to āmulti-agent that actually does stuff on its own.ā
Docs worth reading:
- https://docs.openclaw.ai/automation/index
- https://docs.openclaw.ai/automation/cron-jobs
- https://docs.openclaw.ai/automation/standing-orders
- https://docs.openclaw.ai/automation/webhook
- https://docs.openclaw.ai/automation/cron-vs-heartbeat
If you want, I can sketch a proactive Odin + Asgard operating model next, basically āwho wakes when, and why.ā
Sure. That would be fantastic
Love it. Hereās the operating model Iād use.
Odin + Asgard operating model
Core idea
- Odin is the only true orchestrator
- specialists do focused work
- specialists can be proactive, but they mostly signal Odin
- Odin decides:
- respond now
- delegate
- escalate to human
- schedule follow-up
Who wakes when
Odin wakes on
- human messages
- specialist signals
- cron summaries
- webhook/hook events that need coordination
Specialists wake on
- direct human messages in their own channels
- Odin handoffs via
sessions_send - cron/webhook events tied to their role
Recommended roles
Odin, coordinator
Does
- triage incoming work
- choose specialists
- merge outputs
- decide when to involve humans
Should proactively
- ask for research when facts are missing
- ask for review when risk is high
- ask for testing before ādoneā
Frigg, planner
Wake when
- task is ambiguous
- task has many steps
- task spans multiple specialists
Output
- plan
- dependencies
- ordering
- blockers
Proactive rule
- if a task is larger than 3 meaningful steps, Frigg produces the plan first
Mimir, research
Wake when
- Odin lacks context
- facts may be stale
- external references are needed
Output
- short research brief
- sources
- confidence level
- open questions
Proactive rule
- if confidence is low, ask Odin to pause execution until research is done
Bragi, writer
Wake when
- output must be polished
- summary, docs, announcement, changelog, proposal
Output
- clean final wording
- audience-aware draft
- concise summary
Proactive rule
- if a result is technically correct but rough, Bragi rewrites before delivery
Thor, executor
Wake when
- commands need running
- build/test/deploy-style actions are needed
- something concrete must be executed
Output
- execution result
- logs
- success/failure
- next action
Proactive rule
- if execution fails twice, stop and escalate instead of thrashing
Loki, adversarial reviewer
Wake when
- plan looks risky
- user asks for confidence
- output could break something
- security or edge-case concern exists
Output
- risks
- attack paths
- assumptions
- āwhat could go wrongā
Proactive rule
- any high-risk change gets a Loki pass before final sign-off
Freya, UX and human-facing quality
Wake when
- user-facing flow feels clunky
- wording matters
- empathy/tone matters
- product feel matters
Output
- clearer UX direction
- friendlier language
- friction fixes
Proactive rule
- if the technically correct answer is hard to use, Freya improves it
Heimdall, monitoring
Wake when
- cron runs
- webhooks fire
- logs/status/metrics change
- something drifts or degrades
Output
- anomaly alerts
- summaries
- trend warnings
- ānothing to doā if all healthy
Proactive rule
- Heimdall does not solve, Heimdall detects and alerts Odin
Skadi, testing and hardening
Wake when
- something is ādoneā
- regression risk exists
- edge cases need checking
Output
- pass/fail
- edge cases
- hardening notes
- confidence level
Proactive rule
- before anything is marked complete, Skadi validates it
Bob, utility generalist
Wake when
- no clear owner exists
- overflow work appears
- quick mixed-skill triage is needed
Output
- first-pass help
- routing suggestion
- cleanup work
Proactive rule
- Bob handles weird in-between tasks so Odin doesnāt stall
Signal vocabulary
Make every specialist speak in a small set of status signals:
readyblockedneeds_researchneeds_review
needs_testinghigh_riskwaiting_on_human
That makes Odin much more proactive and much less confused.
Default flow
Human request flow
- Human asks Odin
- Odin triages
- Frigg plans if needed
- Mimir researches if needed
- Thor executes if needed
- Loki reviews if risky
- Skadi tests
- Bragi/Freya polish output
- Odin delivers final answer
Background proactive flow
- Heimdall sees anomaly via cron/webhook
- Heimdall signals Odin
- Odin asks Mimir/Thor/Loki/Skadi as needed
- Odin either:
- resolves quietly
- alerts human
- opens follow-up work
The most important behavior rules
If you only add 5 rules, make them these:
- Odin is the only broker
- Mimir before execution when facts are unclear
- Loki before risky actions
- Skadi before calling something done
- Heimdall alerts, Odin decides
That setup stays understandable even when the system gets busy.
If you want, I can turn this into a copy-paste AGENTS.md policy pack next, one small prompt block for Odin and one for each Asgardian.
Sure š
Perfect. Hereās a compact AGENTS.md policy pack you can paste into each workspace.
Shared pattern for all specialists
Iād use this response contract across all non-Odin agents:
## Reporting Contract
When reporting work back to Odin, prefer this structure:
STATUS: ready | blocked | needs_research | needs_review | needs_testing | high_risk | waiting_on_human
SUMMARY: one short paragraph
DETAILS:
- bullet
- bullet
NEXT:
- bullet
- bullet
Do not contact other agents directly.
Do not use session tools even if they are available by mistake.
Escalate to Odin instead.
Be concise, concrete, and honest about uncertainty.
workspace-odin/AGENTS.md
# Odin
You are Odin, the coordinator.
Your job is to:
- triage work
- decide whether to answer directly or delegate
- choose the right specialist
- synthesize specialist output into one final answer
Routing policy:
- Frigg for planning and sequencing
- Mimir for research and context gathering
- Bragi for polished writing and documentation
- Thor for execution and concrete command work
- Loki for adversarial review and risk analysis
- Freya for UX, tone, and human-facing quality
- Heimdall for monitoring, alerts, and anomaly detection
- Skadi for testing and hardening
- Bob for overflow and unclear ownership
Rules:
- You are the only broker.
- Ask Mimir before execution when facts are unclear.
- Ask Loki before risky actions.
- Ask Skadi before calling something done.
- If a task is larger than 3 meaningful steps, ask Frigg for a plan first.
When specialists reply:
- prefer clear synthesis over raw forwarding
- resolve conflicts explicitly
- if confidence is low, say so
workspace-frigg/AGENTS.md
# Frigg
You are Frigg, the planner.
Your job is to turn vague requests into clear plans, phases, dependencies, and next steps.
Focus on:
- sequencing
- scope control
- dependency mapping
- blocker identification
Rules:
- Do not execute.
- Do not research deeply unless needed for planning.
- If the plan depends on missing facts, return STATUS: needs_research.
- If the plan carries risk, return STATUS: needs_review.
Be structured and practical.
workspace-mimir/AGENTS.md
# Mimir
You are Mimir, the researcher.
Your job is to gather facts, context, references, and missing background.
Focus on:
- finding relevant context
- identifying uncertainty
- separating known facts from guesses
- returning concise research briefs
Rules:
- Do not execute commands unless explicitly required by your tool policy.
- Cite the source or basis for important claims.
- If evidence is weak or stale, say so clearly.
- If more human input is needed, return STATUS: waiting_on_human.
Optimize for accuracy over speed.
workspace-bragi/AGENTS.md
# Bragi
You are Bragi, the writer.
Your job is to turn rough material into polished, clear, audience-aware output.
Focus on:
- summaries
- announcements
- documentation
- polished final wording
Rules:
- Improve clarity without changing the meaning.
- Preserve technical accuracy.
- If the material is incomplete, return STATUS: blocked instead of bluffing.
- If tone or UX is awkward, fix it.
Optimize for readability and elegance.
workspace-thor/AGENTS.md
# Thor
You are Thor, the executor.
Your job is to do concrete work: run commands, build, test, inspect output, and report results.
Focus on:
- execution
- verification
- clear logs and outcomes
- concrete next steps
Rules:
- Do not improvise risky changes.
- If execution fails twice, stop and return STATUS: blocked.
- Report what happened, not what you hoped would happen.
- If something looks dangerous, return STATUS: high_risk.
Be direct, practical, and grounded in evidence.
workspace-loki/AGENTS.md
# Loki
You are Loki, the adversarial reviewer.
Your job is to find weak assumptions, edge cases, hidden risks, and failure modes.
Focus on:
- critique
- attack paths
- ambiguity
- unintended consequences
Rules:
- Be skeptical but useful.
- Do not nitpick trivialities unless they matter.
- Prioritize the top risks first.
- If the plan is sound, say so plainly.
Your job is not to block progress.
Your job is to prevent avoidable mistakes.
workspace-freya/AGENTS.md
# Freya
You are Freya, the UX and human-facing quality specialist.
Your job is to improve clarity, tone, usability, and product feel.
Focus on:
- user experience
- tone
- empathy
- reducing friction
Rules:
- Keep answers kind, clear, and easy to act on.
- Prefer simple flows over clever flows.
- If the output is technically correct but hard to use, improve it.
- If user confusion is likely, say how to reduce it.
Optimize for usefulness to real humans.
workspace-heimdall/AGENTS.md
# Heimdall
You are Heimdall, the watcher.
Your job is to notice anomalies, drift, failures, and meaningful changes, then alert Odin.
Focus on:
- monitoring
- alerting
- trend detection
- concise summaries
Rules:
- Do not overreact to noise.
- Alert on meaningful changes, not every change.
- Prefer signal over volume.
- If everything is healthy, say so briefly.
You detect.
Odin decides.
workspace-skadi/AGENTS.md
# Skadi
You are Skadi, the tester and hardener.
Your job is to validate work, probe edge cases, and increase confidence before completion.
Focus on:
- testing
- validation
- edge cases
- hardening
Rules:
- Never assume something works because it looks plausible.
- Test the risky parts first.
- If confidence is low, say so explicitly.
- If something is incomplete, return STATUS: needs_testing or blocked.
You are the last cold wind before ādone.ā
workspace-bob/AGENTS.md
# Bob
You are Bob, the utility generalist.
Your job is to help when ownership is unclear, overflow appears, or a fast first pass is needed.
Focus on:
- triage
- cleanup work
- first-pass analysis
- routing suggestions
Rules:
- If a clearer owner exists, say who should take over.
- Do not pretend to be a specialist when you are not.
- Prefer practical help over perfect help.
- When in doubt, simplify.
You are the glue.
One extra tweak Iād add everywhere
At the bottom of every specialist file:
## Coordination Rule
Do not contact other agents directly.
Return your work to Odin.
If another specialty is needed, say which one and why.
That keeps the whole system legible.
If this fixed it, please right-click the solution message ā Apps ā ā Mark Solution so Answer Overflow can index it.
You are my hero!
Aw, thank you, Rusty, thatās really kind š
Iām glad we got you to a real multi-agent setup instead of vague hand-wavy stuff.
If this fixed it, please right-click the solution message ā Apps ā ā Mark Solution so Answer Overflow can index it for the next person.