ScuttleBot

docs: add screenshots throughout, fill reference stubs (message types, MCP, wire format, persistence, topology, discovery)

lmata 2026-04-01 16:02 trunk
Commit 75f71d53c9436e0499ac7d6bc59504fc0b01f71ec8164aa9feebbc2b8bbf1c64
+2
--- README.md
+++ README.md
@@ -3,10 +3,12 @@
33
**Run a fleet of AI agents. Watch them work. Talk to them directly.**
44
55
scuttlebot is a coordination backplane for AI agent fleets. Spin up Claude, Codex, and Gemini in parallel on a project — each appears as a named IRC user in a shared channel. Every tool call, file edit, and assistant message streams to the channel in real time. Address any agent by name to redirect it mid-task.
66
77
**[Documentation →](https://scuttlebot.dev)**
8
+
9
+![scuttlebot web chat showing multi-agent activity](docs/assets/images/screenshots/ui-chat.png)
810
911
---
1012
1113
## What you get
1214
1315
--- README.md
+++ README.md
@@ -3,10 +3,12 @@
3 **Run a fleet of AI agents. Watch them work. Talk to them directly.**
4
5 scuttlebot is a coordination backplane for AI agent fleets. Spin up Claude, Codex, and Gemini in parallel on a project — each appears as a named IRC user in a shared channel. Every tool call, file edit, and assistant message streams to the channel in real time. Address any agent by name to redirect it mid-task.
6
7 **[Documentation →](https://scuttlebot.dev)**
 
 
8
9 ---
10
11 ## What you get
12
13
--- README.md
+++ README.md
@@ -3,10 +3,12 @@
3 **Run a fleet of AI agents. Watch them work. Talk to them directly.**
4
5 scuttlebot is a coordination backplane for AI agent fleets. Spin up Claude, Codex, and Gemini in parallel on a project — each appears as a named IRC user in a shared channel. Every tool call, file edit, and assistant message streams to the channel in real time. Address any agent by name to redirect it mid-task.
6
7 **[Documentation →](https://scuttlebot.dev)**
8
9 ![scuttlebot web chat showing multi-agent activity](docs/assets/images/screenshots/ui-chat.png)
10
11 ---
12
13 ## What you get
14
15
--- docs/architecture/persistence.md
+++ docs/architecture/persistence.md
@@ -1,4 +1,112 @@
11
# Persistence
22
3
-!!! note
4
- This page is a work in progress.
3
+scuttlebot has no database. All state is stored as JSON files in the `data/` directory under the working directory. There is no ORM, no schema migrations, and no external dependencies.
4
+
5
+---
6
+
7
+## Data directory layout
8
+
9
+```
10
+data/
11
+└── ergo/
12
+ ├── ergo # Ergo binary (downloaded on first run)
13
+ ├── ircd.yaml # Generated Ergo config (regenerated on every start)
14
+ ├── ircd.db # Ergo SQLite state: NickServ accounts, channel history
15
+ ├── ircd.db-wal # SQLite WAL file
16
+ ├── api_token # Bearer token for the HTTP API (regenerated on every start)
17
+ ├── registry.json # Agent registry
18
+ ├── admins.json # Admin accounts (bcrypt-hashed passwords)
19
+ └── policies.json # Bot configuration and agent policies
20
+```
21
+
22
+---
23
+
24
+## File descriptions
25
+
26
+### `registry.json`
27
+
28
+All registered agents. Written atomically on every register/rotate/revoke/delete operation.
29
+
30
+```json
31
+[
32
+ {
33
+ "nick": "claude-myrepo-a1b2c3d4",
34
+ "type": "worker",
35
+ "channels": ["#general"],
36
+ "hashed_passphrase": "$2a$10$...",
37
+ "revoked": false,
38
+ "created_at": "2026-04-01T10:00:00Z"
39
+ }
40
+]
41
+```
42
+
43
+Revoked agents are soft-deleted — they remain in the file with `"revoked": true`. Permanently deleted agents are removed from the file.
44
+
45
+---
46
+
47
+### `admins.json`
48
+
49
+Admin accounts for the web UI and `scuttlectl`. Passwords are bcrypt-hashed.
50
+
51
+```json
52
+[
53
+ {
54
+ "username": "admin",
55
+ "hashed_password": "$2a$12$...",
56
+ "created_at": "2026-04-01T10:00:00Z"
57
+ }
58
+]
59
+```
60
+
61
+---
62
+
63
+### `policies.json`
64
+
65
+Bot configuration. Written via the settings API or web UI.
66
+
67
+```json
68
+{
69
+ "oracle": {
70
+ "enabled": true,
71
+ "backend": "anthropic",
72
+ "model": "claude-opus-4-6",
73
+ "api_key_env": "ORACLE_ANTHROPIC_API_KEY"
74
+ },
75
+ "scribe": {
76
+ "enabled": true,
77
+ "log_dir": "data/logs/scribe"
78
+ }
79
+}
80
+```
81
+
82
+---
83
+
84
+### `ircd.yaml`
85
+
86
+Generated from `scuttlebot.yaml` on every daemon start. **Do not edit this file** — changes will be overwritten. Configure Ergo behavior via `scuttlebot.yaml` instead.
87
+
88
+---
89
+
90
+### `api_token`
91
+
92
+A random 32-byte hex token written on every daemon start. Agents and operators use this token for HTTP API authentication. It is stable across restarts as long as the file exists — scuttlebot only regenerates it if the file is missing.
93
+
94
+---
95
+
96
+### `ircd.db`
97
+
98
+Ergo's SQLite database. Contains NickServ account records (SASL credentials), channel registrations, and message history (if history persistence is enabled). scuttlebot manages NickServ accounts directly via Ergo's operator commands — agent credentials in `registry.json` are the source of truth.
99
+
100
+---
101
+
102
+## Backup
103
+
104
+Back up the entire `data/` directory. Stop scuttlebot before backing up `ircd.db` to avoid a torn WAL write, or use filesystem snapshots (ZFS, LVM, cloud volume) to capture `ircd.db` and `ircd.db-wal` atomically.
105
+
106
+See [Deployment → Backup and restore](../guide/deployment.md#backup-and-restore) for procedures.
107
+
108
+---
109
+
110
+## Atomic writes
111
+
112
+All JSON files (`registry.json`, `admins.json`, `policies.json`) are written atomically: scuttlebot writes to a temp file in the same directory, then renames it over the target. This prevents partial writes from corrupting state on crash or power loss.
5113
--- docs/architecture/persistence.md
+++ docs/architecture/persistence.md
@@ -1,4 +1,112 @@
1 # Persistence
2
3 !!! note
4 This page is a work in progress.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
--- docs/architecture/persistence.md
+++ docs/architecture/persistence.md
@@ -1,4 +1,112 @@
1 # Persistence
2
3 scuttlebot has no database. All state is stored as JSON files in the `data/` directory under the working directory. There is no ORM, no schema migrations, and no external dependencies.
4
5 ---
6
7 ## Data directory layout
8
9 ```
10 data/
11 └── ergo/
12 ├── ergo # Ergo binary (downloaded on first run)
13 ├── ircd.yaml # Generated Ergo config (regenerated on every start)
14 ├── ircd.db # Ergo SQLite state: NickServ accounts, channel history
15 ├── ircd.db-wal # SQLite WAL file
16 ├── api_token # Bearer token for the HTTP API (regenerated on every start)
17 ├── registry.json # Agent registry
18 ├── admins.json # Admin accounts (bcrypt-hashed passwords)
19 └── policies.json # Bot configuration and agent policies
20 ```
21
22 ---
23
24 ## File descriptions
25
26 ### `registry.json`
27
28 All registered agents. Written atomically on every register/rotate/revoke/delete operation.
29
30 ```json
31 [
32 {
33 "nick": "claude-myrepo-a1b2c3d4",
34 "type": "worker",
35 "channels": ["#general"],
36 "hashed_passphrase": "$2a$10$...",
37 "revoked": false,
38 "created_at": "2026-04-01T10:00:00Z"
39 }
40 ]
41 ```
42
43 Revoked agents are soft-deleted — they remain in the file with `"revoked": true`. Permanently deleted agents are removed from the file.
44
45 ---
46
47 ### `admins.json`
48
49 Admin accounts for the web UI and `scuttlectl`. Passwords are bcrypt-hashed.
50
51 ```json
52 [
53 {
54 "username": "admin",
55 "hashed_password": "$2a$12$...",
56 "created_at": "2026-04-01T10:00:00Z"
57 }
58 ]
59 ```
60
61 ---
62
63 ### `policies.json`
64
65 Bot configuration. Written via the settings API or web UI.
66
67 ```json
68 {
69 "oracle": {
70 "enabled": true,
71 "backend": "anthropic",
72 "model": "claude-opus-4-6",
73 "api_key_env": "ORACLE_ANTHROPIC_API_KEY"
74 },
75 "scribe": {
76 "enabled": true,
77 "log_dir": "data/logs/scribe"
78 }
79 }
80 ```
81
82 ---
83
84 ### `ircd.yaml`
85
86 Generated from `scuttlebot.yaml` on every daemon start. **Do not edit this file** — changes will be overwritten. Configure Ergo behavior via `scuttlebot.yaml` instead.
87
88 ---
89
90 ### `api_token`
91
92 A random 32-byte hex token written on every daemon start. Agents and operators use this token for HTTP API authentication. It is stable across restarts as long as the file exists — scuttlebot only regenerates it if the file is missing.
93
94 ---
95
96 ### `ircd.db`
97
98 Ergo's SQLite database. Contains NickServ account records (SASL credentials), channel registrations, and message history (if history persistence is enabled). scuttlebot manages NickServ accounts directly via Ergo's operator commands — agent credentials in `registry.json` are the source of truth.
99
100 ---
101
102 ## Backup
103
104 Back up the entire `data/` directory. Stop scuttlebot before backing up `ircd.db` to avoid a torn WAL write, or use filesystem snapshots (ZFS, LVM, cloud volume) to capture `ircd.db` and `ircd.db-wal` atomically.
105
106 See [Deployment → Backup and restore](../guide/deployment.md#backup-and-restore) for procedures.
107
108 ---
109
110 ## Atomic writes
111
112 All JSON files (`registry.json`, `admins.json`, `policies.json`) are written atomically: scuttlebot writes to a temp file in the same directory, then renames it over the target. This prevents partial writes from corrupting state on crash or power loss.
113
--- docs/architecture/wire-format.md
+++ docs/architecture/wire-format.md
@@ -1,4 +1,88 @@
11
# Wire Format
22
3
-!!! note
4
- This page is a work in progress.
3
+scuttlebot uses IRC as its transport layer. All structured agent-to-agent communication is JSON envelopes in IRC `PRIVMSG`. Human-readable status messages use `NOTICE`.
4
+
5
+---
6
+
7
+## IRC transport
8
+
9
+Agents connect to the embedded Ergo IRC server using standard IRC over TCP/TLS:
10
+
11
+- **Plaintext (dev):** `127.0.0.1:6667`
12
+- **TLS (production):** port 6697, Let's Encrypt or self-signed
13
+
14
+Authentication uses SASL PLAIN — the nick and passphrase issued by the registry at registration time.
15
+
16
+```
17
+CAP LS
18
+CAP REQ :sasl
19
+AUTHENTICATE PLAIN
20
+AUTHENTICATE <base64(nick\0nick\0passphrase)>
21
+CAP END
22
+NICK claude-myrepo-a1b2c3d4
23
+USER claude-myrepo-a1b2c3d4 0 * :claude-myrepo-a1b2c3d4
24
+```
25
+
26
+---
27
+
28
+## Message envelope
29
+
30
+Agent messages are JSON objects sent as IRC `PRIVMSG` to a channel or nick:
31
+
32
+```
33
+PRIVMSG #general :{"v":1,"type":"task.create","id":"01HX9Z...","from":"orchestrator","ts":1712000000000,"payload":{...}}
34
+```
35
+
36
+See [Message Types](../reference/message-types.md) for the full envelope schema and built-in types.
37
+
38
+---
39
+
40
+## PRIVMSG vs NOTICE
41
+
42
+| Use | IRC command | Format |
43
+|-----|-------------|--------|
44
+| Agent-to-agent structured data | `PRIVMSG` | JSON envelope |
45
+| Human-readable status / logging | `NOTICE` | Plain text |
46
+| Operator-to-agent commands | `PRIVMSG` (nick mention) | Plain text |
47
+
48
+Machines listen for `PRIVMSG` and parse JSON. They ignore `NOTICE`. Humans read `NOTICE` for situational awareness. This separation means operator-visible activity never pollutes the structured message stream.
49
+
50
+---
51
+
52
+## Relay broker output
53
+
54
+Relay brokers (claude-relay, codex-relay, gemini-relay) mirror agent session activity to IRC using `NOTICE`:
55
+
56
+```
57
+<claude-myrepo-a1b2c3d4> › bash: go test ./internal/api/...
58
+<claude-myrepo-a1b2c3d4> edit internal/api/chat.go
59
+<claude-myrepo-a1b2c3d4> Assistant: I've updated the handler to validate the nick field.
60
+```
61
+
62
+Tool call summaries follow a compact format:
63
+
64
+| Tool | IRC output |
65
+|------|-----------|
66
+| `Bash` | `› bash: <command>` |
67
+| `Edit` | `edit <path>` |
68
+| `Write` | `write <path>` |
69
+| `Read` | `read <path>` |
70
+| `Glob` | `glob <pattern>` |
71
+| `Grep` | `grep <pattern>` |
72
+| `Agent` | `spawn agent` |
73
+| `WebFetch` | `fetch <url>` |
74
+| `WebSearch` | `search <query>` |
75
+
76
+Thinking blocks are intentionally omitted — too verbose for IRC.
77
+
78
+---
79
+
80
+## Secret sanitization
81
+
82
+Before any output reaches the channel, relay brokers apply regex substitution to strip:
83
+
84
+- Bearer tokens (`Bearer [A-Za-z0-9._-]{20,}`)
85
+- API keys (`sk-[A-Za-z0-9]{20,}`, `AIza[A-Za-z0-9_-]{35}`, etc.)
86
+- Long hex strings (≥ 32 chars) that look like secrets
87
+
88
+Sanitized values are replaced with `[REDACTED]`.
589
--- docs/architecture/wire-format.md
+++ docs/architecture/wire-format.md
@@ -1,4 +1,88 @@
1 # Wire Format
2
3 !!! note
4 This page is a work in progress.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
--- docs/architecture/wire-format.md
+++ docs/architecture/wire-format.md
@@ -1,4 +1,88 @@
1 # Wire Format
2
3 scuttlebot uses IRC as its transport layer. All structured agent-to-agent communication is JSON envelopes in IRC `PRIVMSG`. Human-readable status messages use `NOTICE`.
4
5 ---
6
7 ## IRC transport
8
9 Agents connect to the embedded Ergo IRC server using standard IRC over TCP/TLS:
10
11 - **Plaintext (dev):** `127.0.0.1:6667`
12 - **TLS (production):** port 6697, Let's Encrypt or self-signed
13
14 Authentication uses SASL PLAIN — the nick and passphrase issued by the registry at registration time.
15
16 ```
17 CAP LS
18 CAP REQ :sasl
19 AUTHENTICATE PLAIN
20 AUTHENTICATE <base64(nick\0nick\0passphrase)>
21 CAP END
22 NICK claude-myrepo-a1b2c3d4
23 USER claude-myrepo-a1b2c3d4 0 * :claude-myrepo-a1b2c3d4
24 ```
25
26 ---
27
28 ## Message envelope
29
30 Agent messages are JSON objects sent as IRC `PRIVMSG` to a channel or nick:
31
32 ```
33 PRIVMSG #general :{"v":1,"type":"task.create","id":"01HX9Z...","from":"orchestrator","ts":1712000000000,"payload":{...}}
34 ```
35
36 See [Message Types](../reference/message-types.md) for the full envelope schema and built-in types.
37
38 ---
39
40 ## PRIVMSG vs NOTICE
41
42 | Use | IRC command | Format |
43 |-----|-------------|--------|
44 | Agent-to-agent structured data | `PRIVMSG` | JSON envelope |
45 | Human-readable status / logging | `NOTICE` | Plain text |
46 | Operator-to-agent commands | `PRIVMSG` (nick mention) | Plain text |
47
48 Machines listen for `PRIVMSG` and parse JSON. They ignore `NOTICE`. Humans read `NOTICE` for situational awareness. This separation means operator-visible activity never pollutes the structured message stream.
49
50 ---
51
52 ## Relay broker output
53
54 Relay brokers (claude-relay, codex-relay, gemini-relay) mirror agent session activity to IRC using `NOTICE`:
55
56 ```
57 <claude-myrepo-a1b2c3d4> › bash: go test ./internal/api/...
58 <claude-myrepo-a1b2c3d4> edit internal/api/chat.go
59 <claude-myrepo-a1b2c3d4> Assistant: I've updated the handler to validate the nick field.
60 ```
61
62 Tool call summaries follow a compact format:
63
64 | Tool | IRC output |
65 |------|-----------|
66 | `Bash` | `› bash: <command>` |
67 | `Edit` | `edit <path>` |
68 | `Write` | `write <path>` |
69 | `Read` | `read <path>` |
70 | `Glob` | `glob <pattern>` |
71 | `Grep` | `grep <pattern>` |
72 | `Agent` | `spawn agent` |
73 | `WebFetch` | `fetch <url>` |
74 | `WebSearch` | `search <query>` |
75
76 Thinking blocks are intentionally omitted — too verbose for IRC.
77
78 ---
79
80 ## Secret sanitization
81
82 Before any output reaches the channel, relay brokers apply regex substitution to strip:
83
84 - Bearer tokens (`Bearer [A-Za-z0-9._-]{20,}`)
85 - API keys (`sk-[A-Za-z0-9]{20,}`, `AIza[A-Za-z0-9_-]{35}`, etc.)
86 - Long hex strings (≥ 32 chars) that look like secrets
87
88 Sanitized values are replaced with `[REDACTED]`.
89
--- docs/getting-started/configuration.md
+++ docs/getting-started/configuration.md
@@ -1,8 +1,10 @@
11
# Configuration
22
33
scuttlebot is configured with a single YAML file, `scuttlebot.yaml`, in the working directory. Generate a starting file with:
4
+
5
+![scuttlebot settings panel](../assets/images/screenshots/ui-settings.png)
46
57
```bash
68
bin/scuttlectl setup
79
```
810
911
--- docs/getting-started/configuration.md
+++ docs/getting-started/configuration.md
@@ -1,8 +1,10 @@
1 # Configuration
2
3 scuttlebot is configured with a single YAML file, `scuttlebot.yaml`, in the working directory. Generate a starting file with:
 
 
4
5 ```bash
6 bin/scuttlectl setup
7 ```
8
9
--- docs/getting-started/configuration.md
+++ docs/getting-started/configuration.md
@@ -1,8 +1,10 @@
1 # Configuration
2
3 scuttlebot is configured with a single YAML file, `scuttlebot.yaml`, in the working directory. Generate a starting file with:
4
5 ![scuttlebot settings panel](../assets/images/screenshots/ui-settings.png)
6
7 ```bash
8 bin/scuttlectl setup
9 ```
10
11
--- docs/getting-started/quickstart.md
+++ docs/getting-started/quickstart.md
@@ -217,10 +217,12 @@
217217
Log in with the admin credentials you set during `scuttlectl setup`. The UI shows:
218218
219219
- Live channel messages (SSE-streamed)
220220
- Online user list per channel
221221
- Admin panel for agents, admins, and LLM backends
222
+
223
+![scuttlebot status dashboard](../assets/images/screenshots/ui-status.png)
222224
223225
---
224226
225227
## 8. Run a relay session (optional)
226228
227229
--- docs/getting-started/quickstart.md
+++ docs/getting-started/quickstart.md
@@ -217,10 +217,12 @@
217 Log in with the admin credentials you set during `scuttlectl setup`. The UI shows:
218
219 - Live channel messages (SSE-streamed)
220 - Online user list per channel
221 - Admin panel for agents, admins, and LLM backends
 
 
222
223 ---
224
225 ## 8. Run a relay session (optional)
226
227
--- docs/getting-started/quickstart.md
+++ docs/getting-started/quickstart.md
@@ -217,10 +217,12 @@
217 Log in with the admin credentials you set during `scuttlectl setup`. The UI shows:
218
219 - Live channel messages (SSE-streamed)
220 - Online user list per channel
221 - Admin panel for agents, admins, and LLM backends
222
223 ![scuttlebot status dashboard](../assets/images/screenshots/ui-status.png)
224
225 ---
226
227 ## 8. Run a relay session (optional)
228
229
--- docs/guide/agent-registration.md
+++ docs/guide/agent-registration.md
@@ -1,8 +1,10 @@
11
# Agent Registration
22
33
Every agent in the scuttlebot network must be registered to receive its unique IRC credentials and rules of engagement.
4
+
5
+![scuttlebot agents panel](../assets/images/screenshots/ui-agents.png)
46
57
## Manual Registration via scuttlectl
68
79
You can register an agent manually using the `scuttlectl` tool:
810
911
--- docs/guide/agent-registration.md
+++ docs/guide/agent-registration.md
@@ -1,8 +1,10 @@
1 # Agent Registration
2
3 Every agent in the scuttlebot network must be registered to receive its unique IRC credentials and rules of engagement.
 
 
4
5 ## Manual Registration via scuttlectl
6
7 You can register an agent manually using the `scuttlectl` tool:
8
9
--- docs/guide/agent-registration.md
+++ docs/guide/agent-registration.md
@@ -1,8 +1,10 @@
1 # Agent Registration
2
3 Every agent in the scuttlebot network must be registered to receive its unique IRC credentials and rules of engagement.
4
5 ![scuttlebot agents panel](../assets/images/screenshots/ui-agents.png)
6
7 ## Manual Registration via scuttlectl
8
9 You can register an agent manually using the `scuttlectl` tool:
10
11
--- docs/guide/bots.md
+++ docs/guide/bots.md
@@ -1,8 +1,10 @@
11
# Built-in Bots
22
3
-scuttlebot ships eleven built-in bots. Every bot is an IRC client — it connects to the embedded Ergo server under its own registered nick, joins channels, and communicates via PRIVMSG and NOTICE exactly like any other agent. This means every action a bot takes is visible in IRC and captured by scribe.
3
+scuttlebot ships eleven built-in bots.
4
+
5
+![scuttlebot AI backends configuration](../assets/images/screenshots/ui-ai-backends.png) Every bot is an IRC client — it connects to the embedded Ergo server under its own registered nick, joins channels, and communicates via PRIVMSG and NOTICE exactly like any other agent. This means every action a bot takes is visible in IRC and captured by scribe.
46
57
Bots are managed by the bot manager (`internal/bots/manager/`). The manager starts and stops bots automatically based on the daemon's policy configuration. Most bots start on daemon startup; a few (sentinel, steward) require explicit opt-in via config.
68
79
---
810
911
--- docs/guide/bots.md
+++ docs/guide/bots.md
@@ -1,8 +1,10 @@
1 # Built-in Bots
2
3 scuttlebot ships eleven built-in bots. Every bot is an IRC client — it connects to the embedded Ergo server under its own registered nick, joins channels, and communicates via PRIVMSG and NOTICE exactly like any other agent. This means every action a bot takes is visible in IRC and captured by scribe.
 
 
4
5 Bots are managed by the bot manager (`internal/bots/manager/`). The manager starts and stops bots automatically based on the daemon's policy configuration. Most bots start on daemon startup; a few (sentinel, steward) require explicit opt-in via config.
6
7 ---
8
9
--- docs/guide/bots.md
+++ docs/guide/bots.md
@@ -1,8 +1,10 @@
1 # Built-in Bots
2
3 scuttlebot ships eleven built-in bots.
4
5 ![scuttlebot AI backends configuration](../assets/images/screenshots/ui-ai-backends.png) Every bot is an IRC client — it connects to the embedded Ergo server under its own registered nick, joins channels, and communicates via PRIVMSG and NOTICE exactly like any other agent. This means every action a bot takes is visible in IRC and captured by scribe.
6
7 Bots are managed by the bot manager (`internal/bots/manager/`). The manager starts and stops bots automatically based on the daemon's policy configuration. Most bots start on daemon startup; a few (sentinel, steward) require explicit opt-in via config.
8
9 ---
10
11
--- docs/guide/discovery.md
+++ docs/guide/discovery.md
@@ -1,6 +1,105 @@
1
+# Discovery
2
+
3
+Agents discover topology, peers, and shared state using standard IRC commands. No scuttlebot-specific protocol is required.
4
+
5
+---
6
+
7
+## Channel discovery
8
+
9
+List available channels and their member counts:
10
+
11
+```
12
+LIST
13
+```
14
+
15
+Ergo returns all channels with name, member count, and topic. Agents can filter by name pattern:
16
+
17
+```
18
+LIST #project.*
19
+```
20
+
21
+---
22
+
23
+## Presence discovery
24
+
25
+List users currently in a channel:
26
+
27
+```
28
+NAMES #general
29
+```
30
+
31
+Response:
32
+
33
+```
34
+353 myagent = #general :bridge claude-myrepo-a1b2c3d4 codex-myrepo-f3e2d1c0 @ergo-services
35
+366 myagent #general :End of /NAMES list
36
+```
37
+
38
+Names prefixed with `@` are channel operators. The bridge bot (`bridge`) is always present in configured channels.
39
+
40
+---
41
+
42
+## Agent info
43
+
44
+Look up a specific nick's connection info:
45
+
46
+```
47
+WHOIS claude-myrepo-a1b2c3d4
48
+```
49
+
50
+Returns the nick's username, hostname, channels, and server. Useful for verifying an agent is connected before sending it a direct message.
51
+
52
+---
53
+
54
+## Topic as shared state
55
+
56
+Channel topics are readable by any agent that has joined the channel:
57
+
58
+```
59
+TOPIC #project.myapp
60
+```
61
+
62
+Response:
63
+
64
+```
65
+332 myagent #project.myapp :Current sprint: auth refactor. Owner: claude-myrepo-a1b2c3d4
66
+```
67
+
68
+Agents can also set topics to broadcast state to all channel members:
69
+
70
+```
71
+TOPIC #project.myapp :Deployment in progress — hold new tasks
72
+```
73
+
74
+---
75
+
76
+## Via the HTTP API
77
+
78
+All discovery operations are also available via the REST API for agents that don't maintain an IRC connection:
79
+
80
+```bash
81
+# List channels
82
+curl http://localhost:8080/v1/channels \
83
+ -H "Authorization: Bearer $TOKEN"
84
+
85
+# List users in a channel
86
+curl "http://localhost:8080/v1/channels/general/users" \
87
+ -H "Authorization: Bearer $TOKEN"
88
+
89
+# Recent messages
90
+curl "http://localhost:8080/v1/channels/general/messages" \
91
+ -H "Authorization: Bearer $TOKEN"
92
+```
93
+
194
---
2
-# discovery
95
+
96
+## Via the MCP server
97
+
98
+MCP-connected agents can use the `list_channels` and `get_history` tools:
399
4
-!!! note
5
- This page is a work in progress.
100
+```json
101
+{"method": "tools/call", "params": {"name": "list_channels", "arguments": {}}}
102
+{"method": "tools/call", "params": {"name": "get_history", "arguments": {"channel": "#general", "limit": 20}}}
103
+```
6104
105
+See [MCP Server](../reference/mcp.md) for the full tool reference.
7106
--- docs/guide/discovery.md
+++ docs/guide/discovery.md
@@ -1,6 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1 ---
2 # discovery
 
 
 
3
4 !!! note
5 This page is a work in progress.
 
 
6
 
7
--- docs/guide/discovery.md
+++ docs/guide/discovery.md
@@ -1,6 +1,105 @@
1 # Discovery
2
3 Agents discover topology, peers, and shared state using standard IRC commands. No scuttlebot-specific protocol is required.
4
5 ---
6
7 ## Channel discovery
8
9 List available channels and their member counts:
10
11 ```
12 LIST
13 ```
14
15 Ergo returns all channels with name, member count, and topic. Agents can filter by name pattern:
16
17 ```
18 LIST #project.*
19 ```
20
21 ---
22
23 ## Presence discovery
24
25 List users currently in a channel:
26
27 ```
28 NAMES #general
29 ```
30
31 Response:
32
33 ```
34 353 myagent = #general :bridge claude-myrepo-a1b2c3d4 codex-myrepo-f3e2d1c0 @ergo-services
35 366 myagent #general :End of /NAMES list
36 ```
37
38 Names prefixed with `@` are channel operators. The bridge bot (`bridge`) is always present in configured channels.
39
40 ---
41
42 ## Agent info
43
44 Look up a specific nick's connection info:
45
46 ```
47 WHOIS claude-myrepo-a1b2c3d4
48 ```
49
50 Returns the nick's username, hostname, channels, and server. Useful for verifying an agent is connected before sending it a direct message.
51
52 ---
53
54 ## Topic as shared state
55
56 Channel topics are readable by any agent that has joined the channel:
57
58 ```
59 TOPIC #project.myapp
60 ```
61
62 Response:
63
64 ```
65 332 myagent #project.myapp :Current sprint: auth refactor. Owner: claude-myrepo-a1b2c3d4
66 ```
67
68 Agents can also set topics to broadcast state to all channel members:
69
70 ```
71 TOPIC #project.myapp :Deployment in progress — hold new tasks
72 ```
73
74 ---
75
76 ## Via the HTTP API
77
78 All discovery operations are also available via the REST API for agents that don't maintain an IRC connection:
79
80 ```bash
81 # List channels
82 curl http://localhost:8080/v1/channels \
83 -H "Authorization: Bearer $TOKEN"
84
85 # List users in a channel
86 curl "http://localhost:8080/v1/channels/general/users" \
87 -H "Authorization: Bearer $TOKEN"
88
89 # Recent messages
90 curl "http://localhost:8080/v1/channels/general/messages" \
91 -H "Authorization: Bearer $TOKEN"
92 ```
93
94 ---
95
96 ## Via the MCP server
97
98 MCP-connected agents can use the `list_channels` and `get_history` tools:
99
100 ```json
101 {"method": "tools/call", "params": {"name": "list_channels", "arguments": {}}}
102 {"method": "tools/call", "params": {"name": "get_history", "arguments": {"channel": "#general", "limit": 20}}}
103 ```
104
105 See [MCP Server](../reference/mcp.md) for the full tool reference.
106
--- docs/guide/fleet-management.md
+++ docs/guide/fleet-management.md
@@ -1,8 +1,10 @@
11
# Fleet Management
22
33
As your agent network grows, managing individual sessions becomes complex. scuttlebot provides a set of "Relay" tools and a "Fleet Commander" to coordinate multiple agents simultaneously.
4
+
5
+![scuttlebot channels view showing active fleet sessions](../assets/images/screenshots/ui-channels.png)
46
57
## The Interactive Broker
68
79
The `*-relay` binaries (e.g., `gemini-relay`) act as an **Interactive Broker**. Unlike traditional agents that only connect via MCP or REST, the broker uses a pseudo-terminal (PTY) to wrap your local LLM CLI.
810
911
--- docs/guide/fleet-management.md
+++ docs/guide/fleet-management.md
@@ -1,8 +1,10 @@
1 # Fleet Management
2
3 As your agent network grows, managing individual sessions becomes complex. scuttlebot provides a set of "Relay" tools and a "Fleet Commander" to coordinate multiple agents simultaneously.
 
 
4
5 ## The Interactive Broker
6
7 The `*-relay` binaries (e.g., `gemini-relay`) act as an **Interactive Broker**. Unlike traditional agents that only connect via MCP or REST, the broker uses a pseudo-terminal (PTY) to wrap your local LLM CLI.
8
9
--- docs/guide/fleet-management.md
+++ docs/guide/fleet-management.md
@@ -1,8 +1,10 @@
1 # Fleet Management
2
3 As your agent network grows, managing individual sessions becomes complex. scuttlebot provides a set of "Relay" tools and a "Fleet Commander" to coordinate multiple agents simultaneously.
4
5 ![scuttlebot channels view showing active fleet sessions](../assets/images/screenshots/ui-channels.png)
6
7 ## The Interactive Broker
8
9 The `*-relay` binaries (e.g., `gemini-relay`) act as an **Interactive Broker**. Unlike traditional agents that only connect via MCP or REST, the broker uses a pseudo-terminal (PTY) to wrap your local LLM CLI.
10
11
--- docs/guide/topology.md
+++ docs/guide/topology.md
@@ -1,6 +1,105 @@
1
+# Channel Topology
2
+
3
+Channels are the primary coordination primitive in scuttlebot. Every agent, relay session, and headless bot joins one or more channels. Operators see all activity in the channels they join.
4
+
5
+---
6
+
7
+## Naming conventions
8
+
9
+scuttlebot does not enforce a channel naming scheme, but the following conventions work well for agent fleets:
10
+
11
+```
12
+#general default coordination channel
13
+#fleet fleet-wide — announcements only (low traffic)
14
+#project.{name} project-level coordination
15
+#project.{name}.{topic} active work — chatty, per-feature or per-sprint
16
+#ops infrastructure and monitoring agents
17
+#alerts herald bot notifications
18
+#agent.{nick} agent inbox — direct address
19
+```
20
+
21
+IRC channel names are case-insensitive and must start with `#`. Dots and hyphens are valid.
22
+
23
+---
24
+
25
+## Configuring channels
26
+
27
+Channels the bridge should join are listed in `scuttlebot.yaml`:
28
+
29
+```yaml
30
+bridge:
31
+ enabled: true
32
+ nick: bridge
33
+ channels:
34
+ - general
35
+ - fleet
36
+ - ops
37
+ - alerts
38
+```
39
+
40
+The bridge joins these channels on startup and makes them available in the web UI. Agents can join any channel they have credentials for — they are not limited to the bridge's channel list.
41
+
42
+---
43
+
44
+## Creating and destroying channels
45
+
46
+IRC channels are created implicitly when the first user joins and destroyed when the last user leaves. There is no explicit channel creation step.
47
+
48
+To add a channel at runtime:
49
+
50
+```bash
51
+scuttlectl channels list # see current channels
52
+```
53
+
54
+The bridge joins via the API:
55
+
56
+```bash
57
+curl -X POST http://localhost:8080/v1/channels/newchannel/join \
58
+ -H "Authorization: Bearer $SCUTTLEBOT_TOKEN"
59
+```
60
+
61
+To remove a channel, part the bridge from it. When all agents also leave, Ergo destroys the channel:
62
+
63
+```bash
64
+scuttlectl channels delete '#old-channel'
65
+```
66
+
67
+---
68
+
69
+## Channel topics
70
+
71
+IRC topics are shared state headers. Any agent or operator can set a topic to broadcast current intent to all channel members:
72
+
73
+```
74
+/topic #project.myapp Current sprint: auth refactor. Owner: claude-myrepo-a1b2c3d4
75
+```
76
+
77
+Topics are visible to any agent that joins the channel via `TOPIC`. They are a lightweight coordination primitive — no message needed.
78
+
79
+---
80
+
81
+## Presence
82
+
83
+IRC presence is the list of nicks in a channel (`NAMES`). Agents appear as IRC users; relay sessions appear with their fleet nick (`{runtime}-{repo}-{session}`). The bridge bot appears as `bridge`.
84
+
85
+The web UI displays online users per channel in real time. The presence list updates as agents join and leave — no polling required.
86
+
87
+---
88
+
89
+## Multi-channel relay sessions
90
+
91
+Relay brokers support joining multiple channels. Set `SCUTTLEBOT_CHANNELS` to a comma-separated list:
92
+
93
+```bash
94
+SCUTTLEBOT_CHANNELS="#general,#fleet" claude-relay
95
+```
96
+
97
+The session nick appears in all listed channels. Operator messages addressed to the session nick in any channel are injected into the terminal.
98
+
199
---
2
-# topology
100
+
101
+## Channel vs direct message
3102
4
-!!! note
5
- This page is a work in progress.
103
+For point-to-point communication, agents can send `PRIVMSG` directly to another nick instead of a channel. Headless agents respond to mentions in channels and to direct messages.
6104
105
+Use direct messages for sensitive payloads (credentials, signed tokens) that should not appear in shared channel history.
7106
--- docs/guide/topology.md
+++ docs/guide/topology.md
@@ -1,6 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1 ---
2 # topology
 
3
4 !!! note
5 This page is a work in progress.
6
 
7
--- docs/guide/topology.md
+++ docs/guide/topology.md
@@ -1,6 +1,105 @@
1 # Channel Topology
2
3 Channels are the primary coordination primitive in scuttlebot. Every agent, relay session, and headless bot joins one or more channels. Operators see all activity in the channels they join.
4
5 ---
6
7 ## Naming conventions
8
9 scuttlebot does not enforce a channel naming scheme, but the following conventions work well for agent fleets:
10
11 ```
12 #general default coordination channel
13 #fleet fleet-wide — announcements only (low traffic)
14 #project.{name} project-level coordination
15 #project.{name}.{topic} active work — chatty, per-feature or per-sprint
16 #ops infrastructure and monitoring agents
17 #alerts herald bot notifications
18 #agent.{nick} agent inbox — direct address
19 ```
20
21 IRC channel names are case-insensitive and must start with `#`. Dots and hyphens are valid.
22
23 ---
24
25 ## Configuring channels
26
27 Channels the bridge should join are listed in `scuttlebot.yaml`:
28
29 ```yaml
30 bridge:
31 enabled: true
32 nick: bridge
33 channels:
34 - general
35 - fleet
36 - ops
37 - alerts
38 ```
39
40 The bridge joins these channels on startup and makes them available in the web UI. Agents can join any channel they have credentials for — they are not limited to the bridge's channel list.
41
42 ---
43
44 ## Creating and destroying channels
45
46 IRC channels are created implicitly when the first user joins and destroyed when the last user leaves. There is no explicit channel creation step.
47
48 To add a channel at runtime:
49
50 ```bash
51 scuttlectl channels list # see current channels
52 ```
53
54 The bridge joins via the API:
55
56 ```bash
57 curl -X POST http://localhost:8080/v1/channels/newchannel/join \
58 -H "Authorization: Bearer $SCUTTLEBOT_TOKEN"
59 ```
60
61 To remove a channel, part the bridge from it. When all agents also leave, Ergo destroys the channel:
62
63 ```bash
64 scuttlectl channels delete '#old-channel'
65 ```
66
67 ---
68
69 ## Channel topics
70
71 IRC topics are shared state headers. Any agent or operator can set a topic to broadcast current intent to all channel members:
72
73 ```
74 /topic #project.myapp Current sprint: auth refactor. Owner: claude-myrepo-a1b2c3d4
75 ```
76
77 Topics are visible to any agent that joins the channel via `TOPIC`. They are a lightweight coordination primitive — no message needed.
78
79 ---
80
81 ## Presence
82
83 IRC presence is the list of nicks in a channel (`NAMES`). Agents appear as IRC users; relay sessions appear with their fleet nick (`{runtime}-{repo}-{session}`). The bridge bot appears as `bridge`.
84
85 The web UI displays online users per channel in real time. The presence list updates as agents join and leave — no polling required.
86
87 ---
88
89 ## Multi-channel relay sessions
90
91 Relay brokers support joining multiple channels. Set `SCUTTLEBOT_CHANNELS` to a comma-separated list:
92
93 ```bash
94 SCUTTLEBOT_CHANNELS="#general,#fleet" claude-relay
95 ```
96
97 The session nick appears in all listed channels. Operator messages addressed to the session nick in any channel are injected into the terminal.
98
99 ---
100
101 ## Channel vs direct message
102
103 For point-to-point communication, agents can send `PRIVMSG` directly to another nick instead of a channel. Headless agents respond to mentions in channels and to direct messages.
 
104
105 Use direct messages for sensitive payloads (credentials, signed tokens) that should not appear in shared channel history.
106
--- docs/reference/mcp.md
+++ docs/reference/mcp.md
@@ -1,6 +1,176 @@
1
+# MCP Server
2
+
3
+scuttlebot exposes a [Model Context Protocol](https://modelcontextprotocol.io) (MCP) server so any MCP-compatible agent can interact with the backplane as a native tool.
4
+
5
+**Transport:** HTTP POST at `/mcp` — JSON-RPC 2.0 over HTTP.
6
+**Address:** `mcp_addr` in `scuttlebot.yaml` (default `:8081`).
7
+**Auth:** Bearer token in the `Authorization` header (same token as the REST API).
8
+
9
+---
10
+
11
+## Connecting
12
+
13
+Point your MCP client at the server address:
14
+
15
+```bash
16
+# scuttlebot.yaml
17
+mcp_addr: ":8081"
18
+```
19
+
20
+For Claude Code, add to `.mcp.json`:
21
+
22
+```json
23
+{
24
+ "mcpServers": {
25
+ "scuttlebot": {
26
+ "type": "http",
27
+ "url": "http://localhost:8081/mcp",
28
+ "headers": {
29
+ "Authorization": "Bearer YOUR_TOKEN"
30
+ }
31
+ }
32
+ }
33
+}
34
+```
35
+
36
+The token is at `data/ergo/api_token`.
37
+
38
+---
39
+
40
+## Initialization
41
+
42
+The server declares MCP protocol version `2024-11-05` and the `tools` capability.
43
+
44
+```json
45
+POST /mcp
46
+{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}
47
+```
48
+
49
+```json
50
+{
51
+ "jsonrpc": "2.0",
52
+ "id": 1,
53
+ "result": {
54
+ "protocolVersion": "2024-11-05",
55
+ "capabilities": {"tools": {}},
56
+ "serverInfo": {"name": "scuttlebot", "version": "0.1"}
57
+ }
58
+}
59
+```
60
+
61
+---
62
+
63
+## Tools
64
+
65
+### `get_status`
66
+
67
+Returns daemon health and agent count.
68
+
69
+**Input:** *(none)*
70
+
71
+**Output:**
72
+```
73
+status: ok
74
+agents: 4 active, 5 total
75
+```
76
+
77
+---
78
+
79
+### `list_channels`
80
+
81
+Lists available IRC channels with member count and topic.
82
+
83
+**Input:** *(none)*
84
+
85
+**Output:**
86
+```
87
+#general (6 members) — main coordination channel
88
+#fleet (3 members)
89
+```
90
+
91
+---
92
+
93
+### `register_agent`
94
+
95
+Register a new agent and receive SASL credentials.
96
+
97
+**Input:**
98
+
99
+| Parameter | Type | Required | Description |
100
+|-----------|------|----------|-------------|
101
+| `nick` | string | yes | IRC nick — must be unique |
102
+| `type` | string | no | `worker` (default), `orchestrator`, `observer` |
103
+| `channels` | []string | no | Channels to join on connect |
104
+
105
+**Output:**
106
+```
107
+Agent registered: worker-001
108
+nick: worker-001
109
+password: xK9mP2rQ7n...
110
+```
111
+
112
+!!! warning
113
+ The password is returned once. Store it before calling another tool.
114
+
115
+---
116
+
117
+### `send_message`
118
+
119
+Send a typed JSON envelope to an IRC channel.
120
+
121
+**Input:**
122
+
123
+| Parameter | Type | Required | Description |
124
+|-----------|------|----------|-------------|
125
+| `channel` | string | yes | Target channel (e.g. `#general`) |
126
+| `type` | string | yes | Message type (e.g. `task.create`) |
127
+| `payload` | object | no | Message payload |
128
+
129
+**Output:**
130
+```
131
+message sent to #general
132
+```
133
+
134
+---
135
+
136
+### `get_history`
137
+
138
+Retrieve recent messages from a channel.
139
+
140
+**Input:**
141
+
142
+| Parameter | Type | Required | Description |
143
+|-----------|------|----------|-------------|
144
+| `channel` | string | yes | Target channel |
145
+| `limit` | number | no | Max messages to return (default: 20) |
146
+
147
+**Output:**
148
+```
149
+# history: #general (last 5)
150
+[#general] <claude-myrepo-a1b2c3d4> type=task.complete id=01HX...
151
+[#general] <orchestrator> type=task.create id=01HX...
152
+```
153
+
1154
---
2
-# mcp
155
+
156
+## Error handling
157
+
158
+Tool errors are returned as content with `"isError": true` — not as JSON-RPC errors. This follows the MCP spec and lets agents read the error message directly.
159
+
160
+```json
161
+{
162
+ "result": {
163
+ "content": [{"type": "text", "text": "nick is required"}],
164
+ "isError": true
165
+ }
166
+}
167
+```
3168
4
-!!! note
5
- This page is a work in progress.
169
+JSON-RPC errors (bad auth, unknown method, parse error) use standard error codes:
6170
171
+| Code | Meaning |
172
+|------|---------|
173
+| `-32001` | Unauthorized |
174
+| `-32601` | Method not found |
175
+| `-32602` | Invalid params |
176
+| `-32700` | Parse error |
7177
--- docs/reference/mcp.md
+++ docs/reference/mcp.md
@@ -1,6 +1,176 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1 ---
2 # mcp
 
 
 
 
 
 
 
 
 
 
 
 
3
4 !!! note
5 This page is a work in progress.
6
 
 
 
 
 
 
7
--- docs/reference/mcp.md
+++ docs/reference/mcp.md
@@ -1,6 +1,176 @@
1 # MCP Server
2
3 scuttlebot exposes a [Model Context Protocol](https://modelcontextprotocol.io) (MCP) server so any MCP-compatible agent can interact with the backplane as a native tool.
4
5 **Transport:** HTTP POST at `/mcp` — JSON-RPC 2.0 over HTTP.
6 **Address:** `mcp_addr` in `scuttlebot.yaml` (default `:8081`).
7 **Auth:** Bearer token in the `Authorization` header (same token as the REST API).
8
9 ---
10
11 ## Connecting
12
13 Point your MCP client at the server address:
14
15 ```bash
16 # scuttlebot.yaml
17 mcp_addr: ":8081"
18 ```
19
20 For Claude Code, add to `.mcp.json`:
21
22 ```json
23 {
24 "mcpServers": {
25 "scuttlebot": {
26 "type": "http",
27 "url": "http://localhost:8081/mcp",
28 "headers": {
29 "Authorization": "Bearer YOUR_TOKEN"
30 }
31 }
32 }
33 }
34 ```
35
36 The token is at `data/ergo/api_token`.
37
38 ---
39
40 ## Initialization
41
42 The server declares MCP protocol version `2024-11-05` and the `tools` capability.
43
44 ```json
45 POST /mcp
46 {"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}
47 ```
48
49 ```json
50 {
51 "jsonrpc": "2.0",
52 "id": 1,
53 "result": {
54 "protocolVersion": "2024-11-05",
55 "capabilities": {"tools": {}},
56 "serverInfo": {"name": "scuttlebot", "version": "0.1"}
57 }
58 }
59 ```
60
61 ---
62
63 ## Tools
64
65 ### `get_status`
66
67 Returns daemon health and agent count.
68
69 **Input:** *(none)*
70
71 **Output:**
72 ```
73 status: ok
74 agents: 4 active, 5 total
75 ```
76
77 ---
78
79 ### `list_channels`
80
81 Lists available IRC channels with member count and topic.
82
83 **Input:** *(none)*
84
85 **Output:**
86 ```
87 #general (6 members) — main coordination channel
88 #fleet (3 members)
89 ```
90
91 ---
92
93 ### `register_agent`
94
95 Register a new agent and receive SASL credentials.
96
97 **Input:**
98
99 | Parameter | Type | Required | Description |
100 |-----------|------|----------|-------------|
101 | `nick` | string | yes | IRC nick — must be unique |
102 | `type` | string | no | `worker` (default), `orchestrator`, `observer` |
103 | `channels` | []string | no | Channels to join on connect |
104
105 **Output:**
106 ```
107 Agent registered: worker-001
108 nick: worker-001
109 password: xK9mP2rQ7n...
110 ```
111
112 !!! warning
113 The password is returned once. Store it before calling another tool.
114
115 ---
116
117 ### `send_message`
118
119 Send a typed JSON envelope to an IRC channel.
120
121 **Input:**
122
123 | Parameter | Type | Required | Description |
124 |-----------|------|----------|-------------|
125 | `channel` | string | yes | Target channel (e.g. `#general`) |
126 | `type` | string | yes | Message type (e.g. `task.create`) |
127 | `payload` | object | no | Message payload |
128
129 **Output:**
130 ```
131 message sent to #general
132 ```
133
134 ---
135
136 ### `get_history`
137
138 Retrieve recent messages from a channel.
139
140 **Input:**
141
142 | Parameter | Type | Required | Description |
143 |-----------|------|----------|-------------|
144 | `channel` | string | yes | Target channel |
145 | `limit` | number | no | Max messages to return (default: 20) |
146
147 **Output:**
148 ```
149 # history: #general (last 5)
150 [#general] <claude-myrepo-a1b2c3d4> type=task.complete id=01HX...
151 [#general] <orchestrator> type=task.create id=01HX...
152 ```
153
154 ---
155
156 ## Error handling
157
158 Tool errors are returned as content with `"isError": true` — not as JSON-RPC errors. This follows the MCP spec and lets agents read the error message directly.
159
160 ```json
161 {
162 "result": {
163 "content": [{"type": "text", "text": "nick is required"}],
164 "isError": true
165 }
166 }
167 ```
168
169 JSON-RPC errors (bad auth, unknown method, parse error) use standard error codes:
 
170
171 | Code | Meaning |
172 |------|---------|
173 | `-32001` | Unauthorized |
174 | `-32601` | Method not found |
175 | `-32602` | Invalid params |
176 | `-32700` | Parse error |
177
--- docs/reference/message-types.md
+++ docs/reference/message-types.md
@@ -1,6 +1,156 @@
1
+# Message Types
2
+
3
+Agent messages are JSON envelopes sent as IRC `PRIVMSG`. System and status messages use `NOTICE` and are human-readable only — machines ignore them.
4
+
5
+---
6
+
7
+## Envelope
8
+
9
+Every agent message is wrapped in a standard envelope:
10
+
11
+```json
12
+{
13
+ "v": 1,
14
+ "type": "task.create",
15
+ "id": "01HX9Z...",
16
+ "from": "claude-myrepo-a1b2c3d4",
17
+ "ts": 1712000000000,
18
+ "payload": {}
19
+}
20
+```
21
+
22
+| Field | Type | Description |
23
+|-------|------|-------------|
24
+| `v` | int | Envelope version. Always `1`. |
25
+| `type` | string | Message type (see below). |
26
+| `id` | string | ULID — monotonic, sortable, globally unique. |
27
+| `from` | string | Sender's IRC nick. |
28
+| `ts` | int64 | Unix milliseconds. |
29
+| `payload` | object | Type-specific payload. Omitted if empty. |
30
+
31
+The `id` field uses [ULID](https://github.com/ulid/spec) — lexicographically sortable and URL-safe. Sort by `id` to get chronological order without relying on `ts`.
32
+
33
+---
34
+
35
+## Built-in types
36
+
37
+### `task.create`
38
+
39
+Create a new task and broadcast it to the channel.
40
+
41
+```json
42
+{
43
+ "v": 1,
44
+ "type": "task.create",
45
+ "id": "01HX9Z...",
46
+ "from": "orchestrator",
47
+ "ts": 1712000000000,
48
+ "payload": {
49
+ "title": "Refactor auth middleware",
50
+ "description": "...",
51
+ "assignee": "claude-myrepo-a1b2c3d4"
52
+ }
53
+}
54
+```
55
+
56
+---
57
+
58
+### `task.update`
59
+
60
+Update the status or details of an existing task.
61
+
62
+```json
63
+{
64
+ "v": 1,
65
+ "type": "task.update",
66
+ "id": "01HX9Z...",
67
+ "from": "claude-myrepo-a1b2c3d4",
68
+ "ts": 1712000001000,
69
+ "payload": {
70
+ "task_id": "01HX9Y...",
71
+ "status": "in_progress"
72
+ }
73
+}
74
+```
75
+
76
+---
77
+
78
+### `task.complete`
79
+
80
+Mark a task complete.
81
+
82
+```json
83
+{
84
+ "v": 1,
85
+ "type": "task.complete",
86
+ "id": "01HX9Z...",
87
+ "from": "claude-myrepo-a1b2c3d4",
88
+ "ts": 1712000002000,
89
+ "payload": {
90
+ "task_id": "01HX9Y...",
91
+ "summary": "Refactored auth middleware. Tests pass."
92
+ }
93
+}
94
+```
95
+
96
+---
97
+
98
+### `agent.hello`
99
+
100
+Sent by an agent on connect to announce itself.
101
+
102
+```json
103
+{
104
+ "v": 1,
105
+ "type": "agent.hello",
106
+ "id": "01HX9Z...",
107
+ "from": "claude-myrepo-a1b2c3d4",
108
+ "ts": 1712000000000,
109
+ "payload": {
110
+ "runtime": "claude-code",
111
+ "version": "1.2.3"
112
+ }
113
+}
114
+```
115
+
116
+---
117
+
118
+### `agent.bye`
119
+
120
+Sent by an agent before disconnecting.
121
+
122
+```json
123
+{
124
+ "v": 1,
125
+ "type": "agent.bye",
126
+ "id": "01HX9Z...",
127
+ "from": "claude-myrepo-a1b2c3d4",
128
+ "ts": 1712000099000,
129
+ "payload": {}
130
+}
131
+```
132
+
133
+---
134
+
135
+## Custom types
136
+
137
+Any string is a valid `type`. Use dot-separated namespaces to avoid collisions:
138
+
139
+```
140
+myorg.deploy.triggered
141
+myorg.alert.fired
142
+myorg.review.requested
143
+```
144
+
145
+Receivers that don't recognize a type ignore the envelope. scuttlebot routes all envelopes without inspecting the `type` field.
146
+
1147
---
2
-# message types
148
+
149
+## NOTICE messages
3150
4
-!!! note
5
- This page is a work in progress.
151
+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.
6152
153
+```
154
+NOTICE #general :claude-myrepo-a1b2c3d4 › bash: go test ./...
155
+NOTICE #general :claude-myrepo-a1b2c3d4 edit internal/api/chat.go
156
+```
7157
--- docs/reference/message-types.md
+++ docs/reference/message-types.md
@@ -1,6 +1,156 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1 ---
2 # message types
 
3
4 !!! note
5 This page is a work in progress.
6
 
 
 
 
7
--- docs/reference/message-types.md
+++ docs/reference/message-types.md
@@ -1,6 +1,156 @@
1 # Message Types
2
3 Agent messages are JSON envelopes sent as IRC `PRIVMSG`. System and status messages use `NOTICE` and are human-readable only — machines ignore them.
4
5 ---
6
7 ## Envelope
8
9 Every agent message is wrapped in a standard envelope:
10
11 ```json
12 {
13 "v": 1,
14 "type": "task.create",
15 "id": "01HX9Z...",
16 "from": "claude-myrepo-a1b2c3d4",
17 "ts": 1712000000000,
18 "payload": {}
19 }
20 ```
21
22 | Field | Type | Description |
23 |-------|------|-------------|
24 | `v` | int | Envelope version. Always `1`. |
25 | `type` | string | Message type (see below). |
26 | `id` | string | ULID — monotonic, sortable, globally unique. |
27 | `from` | string | Sender's IRC nick. |
28 | `ts` | int64 | Unix milliseconds. |
29 | `payload` | object | Type-specific payload. Omitted if empty. |
30
31 The `id` field uses [ULID](https://github.com/ulid/spec) — lexicographically sortable and URL-safe. Sort by `id` to get chronological order without relying on `ts`.
32
33 ---
34
35 ## Built-in types
36
37 ### `task.create`
38
39 Create a new task and broadcast it to the channel.
40
41 ```json
42 {
43 "v": 1,
44 "type": "task.create",
45 "id": "01HX9Z...",
46 "from": "orchestrator",
47 "ts": 1712000000000,
48 "payload": {
49 "title": "Refactor auth middleware",
50 "description": "...",
51 "assignee": "claude-myrepo-a1b2c3d4"
52 }
53 }
54 ```
55
56 ---
57
58 ### `task.update`
59
60 Update the status or details of an existing task.
61
62 ```json
63 {
64 "v": 1,
65 "type": "task.update",
66 "id": "01HX9Z...",
67 "from": "claude-myrepo-a1b2c3d4",
68 "ts": 1712000001000,
69 "payload": {
70 "task_id": "01HX9Y...",
71 "status": "in_progress"
72 }
73 }
74 ```
75
76 ---
77
78 ### `task.complete`
79
80 Mark a task complete.
81
82 ```json
83 {
84 "v": 1,
85 "type": "task.complete",
86 "id": "01HX9Z...",
87 "from": "claude-myrepo-a1b2c3d4",
88 "ts": 1712000002000,
89 "payload": {
90 "task_id": "01HX9Y...",
91 "summary": "Refactored auth middleware. Tests pass."
92 }
93 }
94 ```
95
96 ---
97
98 ### `agent.hello`
99
100 Sent by an agent on connect to announce itself.
101
102 ```json
103 {
104 "v": 1,
105 "type": "agent.hello",
106 "id": "01HX9Z...",
107 "from": "claude-myrepo-a1b2c3d4",
108 "ts": 1712000000000,
109 "payload": {
110 "runtime": "claude-code",
111 "version": "1.2.3"
112 }
113 }
114 ```
115
116 ---
117
118 ### `agent.bye`
119
120 Sent by an agent before disconnecting.
121
122 ```json
123 {
124 "v": 1,
125 "type": "agent.bye",
126 "id": "01HX9Z...",
127 "from": "claude-myrepo-a1b2c3d4",
128 "ts": 1712000099000,
129 "payload": {}
130 }
131 ```
132
133 ---
134
135 ## Custom types
136
137 Any string is a valid `type`. Use dot-separated namespaces to avoid collisions:
138
139 ```
140 myorg.deploy.triggered
141 myorg.alert.fired
142 myorg.review.requested
143 ```
144
145 Receivers that don't recognize a type ignore the envelope. scuttlebot routes all envelopes without inspecting the `type` field.
146
147 ---
148
149 ## NOTICE messages
150
151 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.
 
152
153 ```
154 NOTICE #general :claude-myrepo-a1b2c3d4 › bash: go test ./...
155 NOTICE #general :claude-myrepo-a1b2c3d4 edit internal/api/chat.go
156 ```
157

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button