Skip to content

Inter-Agent Comms

Version: 1.0 — 2026-02-23 — Winnie 🦁

All agent-to-agent communication routes through two patterns. Choosing the wrong one wastes tokens and breaks delivery. There is no middle ground.

Pattern 1: sessions_send — Persistent Named Agents

Section titled “Pattern 1: sessions_send — Persistent Named Agents”

Use for: Winnie, Frankel, Shield, Vinyl, Sentry. These agents run persistent sessions with memory.

sessions_send(
sessionKey="agent:<agentId>:main",
message="...",
timeoutSeconds=0 # ALWAYS — fire-and-forget
)

Examples:

sessions_send(sessionKey="agent:pm-r6records:main", message="...", timeoutSeconds=0)
sessions_send(sessionKey="agent:pm-frankel:main", message="...", timeoutSeconds=0)
sessions_send(sessionKey="agent:monitor:main", message="...", timeoutSeconds=0)

Rules:

  • timeoutSeconds=0 is MANDATORY. Without it, concurrent runs will timeout and appear to fail (message still delivered but error thrown).
  • Returns { status: "accepted" } — this means queued and delivered.
  • To check the result later: sessions_history(sessionKey="agent:<id>:main", limit=5)
  • Never wait for a result inline — cross-agent runs share a single-concurrency lane.

Pattern 2: sessions_spawn — Spawn-Only Worker Templates

Section titled “Pattern 2: sessions_spawn — Spawn-Only Worker Templates”

Use for: dev-backend, dev-frontend, research. These are stateless workers — no persistent memory.

sessions_spawn(
agentId="dev-backend", # or dev-frontend, research
task="...",
label="short-label", # REQUIRED: for tracking
runTimeoutSeconds=600, # REQUIRED: always set a timeout
cleanup="keep", # REQUIRED: so output is readable
model="anthropic/claude-sonnet-4-6" # optional override
)

Mandatory spawn contract — every spawn MUST include:

  1. label — short descriptive name (e.g. "r6-discogs-setup")
  2. runTimeoutSeconds — max execution time. Use 300 for S tasks, 600 for M, 1200 for L.
  3. cleanup="keep" — retains transcript for debugging
  4. Disk-write instruction in task brief: "Write results to /home/winnie/.openclaw/workspace/checkpoints/subagent-<label>.md"

All tasks follow: backlog → in_progress → review → done

TransitionWho does itWhen
backlog → in_progressAgent claiming the taskAt start of work
in_progress → reviewAgent completing the taskWork done, needs Chris review
in_progress → doneAgent (if no review needed)Ops/infra tasks, auto-completeable
review → doneChris or WinnieAfter human sign-off
any → blockedAny agentWhen blocked; add blocker note

API pattern:

Terminal window
# Claim
curl -s -X PATCH "http://127.0.0.1:3001/api/tasks/<ID>" \
-H "Content-Type: application/json" \
-d '{"status":"in_progress","agent":"<Name>"}'
# Complete
curl -s -X PATCH "http://127.0.0.1:3001/api/tasks/<ID>" \
-H "Content-Type: application/json" \
-d '{"status":"done","agent":"<Name>"}'

Who updates what:

  • Named agents (Winnie, PMs) → update their own tasks directly
  • Sub-agents (dev-backend, research, etc.) → spawning agent updates MC after receiving results
  • Heartbeat → Winnie syncs her active task status at each 30m tick
Agent IDTypeHow to reach
mainNamed (Winnie)sessions_send(sessionKey="agent:main:main", ...)
pm-frankelNamed (Frankel)sessions_send(sessionKey="agent:pm-frankel:main", ...)
pm-r6recordsNamed (Vinyl)sessions_send(sessionKey="agent:pm-r6records:main", ...)
pm-s1defenceNamed (Shield)sessions_send(sessionKey="agent:pm-s1defence:main", ...) — compartmentalised
monitorNamed (Sentry)sessions_send(sessionKey="agent:monitor:main", ...)
dev-backendSpawn-onlysessions_spawn(agentId="dev-backend", ...)
dev-frontendSpawn-onlysessions_spawn(agentId="dev-frontend", ...)
dev-opsSpawn-onlysessions_spawn(agentId="dev-ops", ...)
researchSpawn-onlysessions_spawn(agentId="research", ...)
Sub-agent result → spawning agent verifies → updates MC → notifies PM if needed
PM decision → Winnie (sessions_send) → Chris if blocked
System alert → Sentry → Winnie (sessions_send) → Chris if critical
  • sessions_send without timeoutSeconds=0 — will appear to fail under load
  • sessions_spawn without label, runTimeoutSeconds, cleanup — loses output
  • ❌ Busy-polling sub-agents — one check after timeout + 2m max
  • ❌ Sub-agent updates MC directly — spawning agent owns MC transitions
  • sessions_send to spawn-only workers — they have no persistent session
  • ❌ Named agent announcing during DND (03:00–08:00) — write to disk, morning brief handles it