Claude Code Swarm (Part 3): Mailbox Message Types (Schema Catalog)
A practical catalog of the swarm mailbox message types you need to implement, plus recommended JSON payload shapes and semantics.
If you want multi-agent swarms to be reliable, you need something boring: a finite set of typed control-plane messages.
This post catalogs the core swarm mailbox message types and gives implementable payload shapes for each. The goal is correctness under retries, busy sessions, and partial delivery.
Part 3 of 3. Prev: /swarm-state-machines/. Full series: /swarm-mailbox-protocol/, /swarm-state-machines/, /swarm-mailbox-type-catalog/.
What You’ll Learn
- The canonical control-plane
typeset. - Recommended JSON schemas (fields, requiredness, and semantics).
- Which messages must be applied as side effects before chat delivery.
Envelope vs Payload
Assume mailbox entries have an envelope with a text field.
- For human chat,
textis plain text. - For coordination,
textis a JSON string with atypefield.
This catalog is about the typed JSON payloads.
Canonical Control-Plane Types
These are the message types that matter for shipping swarms:
task_assignmenttask_progresstask_completedidle_notificationplan_approval_requestplan_approval_responsepermission_requestpermission_responsesandbox_permission_requestsandbox_permission_responsemode_set_requestteam_permission_updateshutdown_requestshutdown_approvedshutdown_rejected
If you implement these with idempotency and clear state transitions, you can build a reproduction-grade swarm protocol.
Common Fields (Use These Everywhere)
Make every payload include:
type(string)timestamp(ISO string)
For request/response style messages, also include:
requestId(string)
And for routing and traceability, strongly consider:
teamName(string)agentId(string)agentName(string)
You can omit the routing fields in a purely local filesystem design, but you will want them the moment you add remote sessions or logs.
Schemas (Recommended)
All schemas below are “recommended shapes” designed for implementability. Exact field names vary in real bundles, but the semantics do not.
task_assignment
Sent by leader to worker.
{
"type": "task_assignment",
"requestId": "task-123",
"timestamp": "[iso8601]",
"task": {
"title": "Short label",
"instructions": "What to do",
"context": "Optional extra context",
"planModeRequired": true
}
}
Semantics:
- If
planModeRequiredis true, the worker must not take irreversible action until plan approval completes.
task_progress
Sent by worker to leader.
{
"type": "task_progress",
"requestId": "task-123",
"timestamp": "[iso8601]",
"progress": {
"phase": "analyzing | implementing | verifying | blocked | done",
"message": "Human-readable progress update"
}
}
Semantics:
- “Progress” is informational. It should never trigger side effects.
task_completed
Sent by worker to leader.
{
"type": "task_completed",
"requestId": "task-123",
"timestamp": "[iso8601]",
"result": {
"summary": "What changed",
"artifacts": ["optional references"],
"errors": []
}
}
Semantics:
- Terminal for the task. Safe to deliver as chat after any required side effects.
idle_notification
Sent by worker to leader.
{
"type": "idle_notification",
"timestamp": "[iso8601]",
"state": "idle"
}
Semantics:
- Used to improve delivery behavior (deliver immediately when idle, queue when busy).
plan_approval_request
Sent by worker to leader.
{
"type": "plan_approval_request",
"requestId": "plan-456",
"timestamp": "[iso8601]",
"plan": {
"goal": "What will be done",
"steps": ["step 1", "step 2"],
"risks": ["what could go wrong"],
"tooling": ["tools expected to be used"]
}
}
Semantics:
- The worker is blocked until a response arrives.
plan_approval_response
Sent by leader to worker.
{
"type": "plan_approval_response",
"requestId": "plan-456",
"timestamp": "[iso8601]",
"approved": true,
"notes": "Optional reviewer notes",
"policy": {
"permissionMode": "default"
}
}
Semantics:
- This is a side-effect message. Apply policy updates before delivering any queued chat.
permission_request
Sent by worker to leader (or to the main session) when a tool needs approval.
{
"type": "permission_request",
"requestId": "perm-789",
"timestamp": "[iso8601]",
"tool": {
"name": "Bash",
"arguments": "redacted or summarized"
},
"reason": "Why this tool is needed"
}
Semantics:
- The worker must not execute the tool while blocked on this request id.
permission_response
Sent by leader to worker.
{
"type": "permission_response",
"requestId": "perm-789",
"timestamp": "[iso8601]",
"approved": true,
"mode": "default | locked-down",
"notes": "Optional reason or instruction"
}
Semantics:
- Side-effect message. Apply decision (and any mode/policy update) before resuming execution.
sandbox_permission_request
Sent by worker to leader when a sandbox capability is needed (most commonly network).
{
"type": "sandbox_permission_request",
"requestId": "net-101",
"timestamp": "[iso8601]",
"capability": "network",
"details": {
"hostnames": ["example.com"],
"reason": "Why network is needed"
}
}
sandbox_permission_response
Sent by leader to worker.
{
"type": "sandbox_permission_response",
"requestId": "net-101",
"timestamp": "[iso8601]",
"approved": true,
"scope": "session | one-shot",
"notes": "Optional"
}
Semantics:
- Side-effect message. Apply capability update before resuming execution.
mode_set_request
Sent by leader to worker to push a mode/policy change.
{
"type": "mode_set_request",
"timestamp": "[iso8601]",
"mode": "default | plan | safe",
"policy": {
"permissionMode": "default"
}
}
Semantics:
- Side-effect message. Apply before delivering queued chat.
team_permission_update
Sent by leader to workers to synchronize team-wide allow/deny rules.
{
"type": "team_permission_update",
"timestamp": "[iso8601]",
"rules": {
"allowedTools": ["Bash(git:*)", "Read", "Edit"],
"disallowedTools": ["Bash(rm -rf:*)"]
}
}
Semantics:
- Side-effect message. Apply before tool execution continues.
shutdown_request
Sent by leader to worker.
{
"type": "shutdown_request",
"requestId": "shutdown-1",
"timestamp": "[iso8601]",
"reason": "Optional"
}
shutdown_approved / shutdown_rejected
Sent by worker to leader.
{
"type": "shutdown_approved",
"requestId": "shutdown-1",
"timestamp": "[iso8601]"
}
{
"type": "shutdown_rejected",
"requestId": "shutdown-1",
"timestamp": "[iso8601]",
"reason": "Optional"
}
Semantics:
- Shutdown must be idempotent. Duplicate requests must not restart work.
Apply-Before-Deliver Rule
If you implement one runtime rule, make it this:
- Apply side effects (mode changes, approvals, permission updates, shutdown) before delivering queued chat.
That ordering prevents inconsistent states when the main session is busy.
Related
/swarm-mailbox-protocol//swarm-state-machines//permission-control-plane/