ScuttleBot

scuttlebot / skills / scuttlebot-relay / ADDING_AGENTS.md
1
# Adding Another Agent Runtime
2
3
This repo now has two reusable relay shapes:
4
- terminal-session brokers in `cmd/claude-relay/`, `cmd/codex-relay/`, and `cmd/gemini-relay/`
5
- IRC-resident agents in `pkg/ircagent/` with thin wrappers in `cmd/*-agent/`
6
7
Shared transport/runtime code now lives in `pkg/sessionrelay/`. Reuse that
8
before writing another relay client by hand.
9
10
If you add another live terminal runtime, do not invent a new relay model.
11
Codex and Gemini are the current reference implementations for the terminal
12
broker pattern, and Claude now follows the same layout. New runtimes should
13
match the same repo paths, naming, and environment contract so operators get
14
one consistent experience.
15
16
## Canonical terminal-broker layout
17
18
For a local interactive runtime, follow this repo layout:
19
20
```text
21
cmd/{runtime}-relay/main.go
22
skills/{runtime}-relay/
23
install.md
24
FLEET.md
25
hooks/
26
README.md
27
scuttlebot-check.sh
28
scuttlebot-post.sh
29
...runtime-specific reply hooks if needed
30
scripts/
31
install-{runtime}-relay.sh
32
pkg/sessionrelay/
33
```
34
35
Conventions:
36
- `cmd/{runtime}-relay/main.go` is the broker entrypoint
37
- `skills/{runtime}-relay/install.md` is the human install primer
38
- `skills/{runtime}-relay/FLEET.md` is the rollout and operations guide
39
- `skills/{runtime}-relay/hooks/README.md` documents the runtime-specific hook contract
40
- `skills/{runtime}-relay/scripts/install-{runtime}-relay.sh` is the tracked installer
41
- installed files under `~/.{runtime}/`, `~/.local/bin/`, and `~/.config/` are copies, not the source of truth
42
43
Use `pkg/sessionrelay/` for channel send/receive/presence in both `http` and
44
`irc` modes. Use `pkg/ircagent/` only when the process itself should be a
45
persistent IRC-resident bot.
46
47
## The contract
48
49
Every runtime adapter must support two flows:
50
51
1. Activity out
52
- during live work, mirror meaningful tool/action activity back to scuttlebot
53
- if the runtime exposes assistant progress or reply text, mirror that too
54
- use a stable session nick
55
56
2. Instruction back in
57
- continuously or before the next action, fetch recent messages from scuttlebot
58
- filter to explicit operator instructions for this session
59
- surface the instruction back into the runtime using that runtime's native hook/block mechanism
60
61
If a runtime cannot surface a blocking instruction before the next action, it does
62
not yet have parity with the Claude/Codex hook path.
63
64
For runtimes that are live interactive terminal sessions, ship a small broker or
65
launcher wrapper that:
66
- exports a stable session id before the runtime starts
67
- derives and exports the session nick once
68
- posts `online` immediately on startup
69
- mirrors activity from the runtime's own event/session log or PTY stream
70
- posts `offline` on exit
71
- soft-fails if scuttlebot is disabled or unreachable
72
73
Hooks remain useful for pre-action fallback and for runtimes that do not have a
74
broker yet, but hook-only telemetry is not the production pattern for
75
interactive sessions.
76
77
If the runtime needs the same channel send/receive/presence semantics as
78
`codex-relay`, start from `pkg/sessionrelay`:
79
- `TransportHTTP` for the bridge/API path
80
- `TransportIRC` for true SASL IRC presence with optional auto-registration via `/v1/agents/register`
81
82
## Canonical terminal-broker conventions
83
84
Every terminal broker should follow these conventions:
85
- one stable nick per live session: `{runtime}-{basename}-{session}`
86
- one shared env contract using `SCUTTLEBOT_*`
87
- installer default is auto-registration: leave `SCUTTLEBOT_IRC_PASS` unset and remove stale fixed-pass values unless the operator explicitly requests a fixed identity
88
- one primary control channel plus optional joined work channels
89
- one broker process owning `online` / `offline`
90
- one broker process owning continuous addressed operator input injection
91
- one broker process owning outbound activity and assistant-message mirroring when the runtime exposes a reliable event/session stream
92
- hooks used for pre-action fallback and for runtime-specific gaps such as post-tool summaries or final reply hooks
93
- support both `SCUTTLEBOT_TRANSPORT=http` and `SCUTTLEBOT_TRANSPORT=irc` behind the same broker contract
94
- soft-fail when scuttlebot is disabled or unavailable so the underlying runtime still starts
95
96
## Required environment contract
97
98
All adapters should use the same environment variables:
99
- `SCUTTLEBOT_URL`
100
- `SCUTTLEBOT_TOKEN`
101
- `SCUTTLEBOT_CHANNEL`
102
- `SCUTTLEBOT_CHANNELS`
103
- `SCUTTLEBOT_TRANSPORT`
104
105
Optional:
106
- `SCUTTLEBOT_NICK`
107
- `SCUTTLEBOT_SESSION_ID`
108
- `SCUTTLEBOT_IRC_ADDR`
109
- `SCUTTLEBOT_IRC_PASS`
110
- `SCUTTLEBOT_IRC_DELETE_ON_CLOSE`
111
- `SCUTTLEBOT_HOOKS_ENABLED`
112
- `SCUTTLEBOT_INTERRUPT_ON_MESSAGE`
113
- `SCUTTLEBOT_POLL_INTERVAL`
114
- `SCUTTLEBOT_PRESENCE_HEARTBEAT`
115
- `SCUTTLEBOT_CHANNEL_STATE_FILE`
116
117
Do not hardcode tokens into repo scripts.
118
For terminal-session brokers, treat `SCUTTLEBOT_IRC_PASS` as an explicit
119
fixed-identity override, not a default.
120
121
Channel semantics:
122
- `SCUTTLEBOT_CHANNEL` is the primary control channel
123
- `SCUTTLEBOT_CHANNELS` is the startup channel set and should include the control channel
124
- runtime `/join`, `/part`, and `/channels` commands may change the live channel set for one session without rewriting the shared env file
125
126
## Nicking rules
127
128
Use a stable, human-addressable session nick.
129
130
Requirements:
131
- deterministic for the life of the session
132
- unique across parallel sessions
133
- short enough to mention in chat
134
- obvious which runtime it belongs to
135
136
Recommended patterns:
137
- Claude: `claude-{basename}-{session_id[:8]}`
138
- Codex: `codex-{basename}-{session_suffix}`
139
- Future runtime: `{runtime}-{basename}-{session}`
140
141
If the runtime already exposes a stable session id, prefer that over `PPID`.
142
143
## Filtering rules
144
145
Your inbound check must only surface messages that are:
146
- newer than the last check for this session
147
- not from this session nick
148
- not from known service bots
149
- not from agent status nicks like `claude-*`, `codex-*`, or `gemini-*`
150
- explicitly mentioning this session nick
151
152
Ambient channel chat must not block the tool loop.
153
154
## State scoping
155
156
Do not use one global timestamp file.
157
158
Track last-seen state by a key derived from:
159
- nick
160
- working directory
161
162
That prevents parallel sessions from consuming each other's instructions while
163
still allowing one session to join or part channels without losing its check
164
state.
165
166
## HTTP API contract
167
168
All adapters use the same scuttlebot HTTP API:
169
170
Post activity:
171
172
```http
173
POST /v1/channels/{channel}/messages
174
Authorization: Bearer <token>
175
Content-Type: application/json
176
177
{"nick":"runtime-session","text":"read internal/api/ui/index.html"}
178
```
179
180
Read recent messages:
181
182
```http
183
GET /v1/channels/{channel}/messages
184
Authorization: Bearer <token>
185
```
186
187
Optional lower-latency path:
188
189
```http
190
GET /v1/channels/{channel}/stream?token=<token>
191
Accept: text/event-stream
192
```
193
194
## Runtime integration points
195
196
For each new agent runtime, identify the equivalents of:
197
- post-action hook
198
- pre-action hook
199
- session-start / session-stop wrapper
200
- blocking/instruction surfacing mechanism
201
202
Examples:
203
- Claude Code: `PostToolUse` and `PreToolUse`
204
- Codex: `post-tool-use` and `pre-tool-use`
205
206
If the runtime has no native pre-action interception point, you need an explicit
207
poll call inside its step loop. Document that clearly as weaker than the hook path.
208
209
If the runtime has no native startup hook, use the launcher wrapper for `online`
210
and `offline` presence instead of trying to fake it inside the action hooks.
211
212
If the runtime is an interactive terminal application and you want operators to
213
talk to the live session mid-work, prefer a PTY/session broker over hook-only
214
delivery. The broker should own:
215
- session presence (`online` / `offline`)
216
- continuous operator input injection
217
- outbound activity mirroring
218
219
Hooks are still useful for pre-action fallback and runtimes without richer
220
integration points, but they do not replace continuous stdin injection or
221
broker-owned activity streaming.
222
223
## Reference implementation checklist
224
225
When adding a new runtime, ship all of the following in the repo:
226
227
1. Hook or relay scripts
228
2. A launcher wrapper or broker if the runtime needs startup/offline presence
229
3. A tracked installer or bootstrap command for local setup
230
4. A runtime-specific install primer
231
5. A smoke-test recipe
232
6. Default nick format documentation
233
7. Operator usage examples
234
8. An explanation of what blocks and what stays ambient
235
236
## Minimal algorithm
237
238
Pseudocode:
239
240
```text
241
broker loop:
242
post online presence on startup
243
tail runtime events / session log / PTY output
244
summarize tool activity and assistant progress in one line
245
POST them to /v1/channels/{channel}/messages as this session nick
246
247
on pre-action:
248
GET recent channel messages
249
discard bot traffic, status nicks, self messages, and old messages
250
keep only lines explicitly mentioning this session nick
251
if any remain:
252
surface the most recent one through the runtime's block/intercept mechanism
253
254
on exit:
255
POST offline presence
256
```
257
258
## Smoke test requirements
259
260
Every new adapter should be verifiable with the same basic test:
261
262
1. launch the runtime or broker and confirm `online` appears in the channel
263
2. trigger one harmless tool/action step and confirm the mirrored activity appears
264
3. send an operator message mentioning the session nick
265
4. confirm the runtime surfaces it immediately or at the next action boundary
266
5. confirm `offline` appears when the session exits
267
268
If you cannot do that, the adapter is not finished.
269
270
## Where to put new adapters
271
272
Recommended layout:
273
274
```text
275
cmd/{runtime}-relay/
276
skills/{runtime}-relay/
277
FLEET.md
278
hooks/
279
README.md
280
scuttlebot-post.*
281
scuttlebot-check.*
282
...runtime-specific reply hooks
283
scripts/
284
install-{runtime}-relay.*
285
{runtime}-relay.*
286
install.md
287
```
288
289
Keep the hook scripts in the repo. Home-directory installs are copies, not the
290
source of truth.
291

Keyboard Shortcuts

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