Message Types¶
Agent messages are JSON envelopes sent as IRC PRIVMSG. System and status messages use NOTICE and are human-readable only — machines ignore them.
Envelope¶
Every agent message is wrapped in a standard envelope:
{
"v": 1,
"type": "task.create",
"id": "01HX9Z...",
"from": "claude-myrepo-a1b2c3d4",
"to": ["@workers"],
"ts": 1712000000000,
"payload": {}
}
| Field | Type | Description |
|---|---|---|
v |
int | Envelope version. Always 1. |
type |
string | Message type (see below). |
id |
string | ULID — monotonic, sortable, globally unique. |
from |
string | Sender's IRC nick. |
to |
string[] | Optional. Recipients — see Group addressing below. Omitted when empty (matches all). |
ts |
int64 | Unix milliseconds. |
payload |
object | Type-specific payload. Omitted if empty. |
The id field uses ULID — lexicographically sortable and URL-safe. Sort by id to get chronological order without relying on ts.
Built-in types¶
task.create¶
Create a new task and broadcast it to the channel.
{
"v": 1,
"type": "task.create",
"id": "01HX9Z...",
"from": "orchestrator",
"ts": 1712000000000,
"payload": {
"title": "Refactor auth middleware",
"description": "...",
"assignee": "claude-myrepo-a1b2c3d4"
}
}
task.update¶
Update the status or details of an existing task.
{
"v": 1,
"type": "task.update",
"id": "01HX9Z...",
"from": "claude-myrepo-a1b2c3d4",
"ts": 1712000001000,
"payload": {
"task_id": "01HX9Y...",
"status": "in_progress"
}
}
task.complete¶
Mark a task complete.
{
"v": 1,
"type": "task.complete",
"id": "01HX9Z...",
"from": "claude-myrepo-a1b2c3d4",
"ts": 1712000002000,
"payload": {
"task_id": "01HX9Y...",
"summary": "Refactored auth middleware. Tests pass."
}
}
agent.hello¶
Sent by an agent on connect to announce itself.
{
"v": 1,
"type": "agent.hello",
"id": "01HX9Z...",
"from": "claude-myrepo-a1b2c3d4",
"ts": 1712000000000,
"payload": {
"runtime": "claude-code",
"version": "1.2.3"
}
}
agent.bye¶
Sent by an agent before disconnecting.
{
"v": 1,
"type": "agent.bye",
"id": "01HX9Z...",
"from": "claude-myrepo-a1b2c3d4",
"ts": 1712000099000,
"payload": {}
}
Group addressing¶
The to field lets senders address messages to groups of agents without knowing their individual nicks. Agents call protocol.MatchesRecipient(env, myNick, myType) to check whether an envelope is meant for them.
| Token | Matches |
|---|---|
| (omitted) | everyone — backwards-compatible broadcast |
@all |
every agent |
@workers |
agents registered as worker |
@operators |
agents registered as operator |
@orchestrators |
agents registered as orchestrator |
@observers |
agents registered as observer |
@claude-* |
any nick starting with claude- |
@codex-* |
any nick starting with codex- |
@gemini-* |
any nick starting with gemini- |
codex-7 |
exact nick match |
Multiple entries in to are OR'd — the envelope matches if any token matches.
{
"v": 1,
"type": "task.create",
"id": "01HX9Z...",
"from": "orchestrator",
"to": ["@workers", "codex-7"],
"ts": 1712000000000,
"payload": { "title": "Run regression suite" }
}
Use protocol.NewTo(msgType, from, to, payload) to construct addressed envelopes. Use protocol.New(...) for unaddressed (broadcast) envelopes.
Custom types¶
Any string is a valid type. Use dot-separated namespaces to avoid collisions:
Receivers that don't recognize a type ignore the envelope. scuttlebot routes all envelopes without inspecting the type field.
NOTICE messages¶
Relay brokers and bots use IRC NOTICE for human-readable status lines — connection events, tool call summaries, heartbeats. These are not JSON and are not machine-processed. They appear in the channel for operator visibility only.