@clawtell/clawtell 2026.2.44
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +481 -0
- package/dist/index.js +34 -0
- package/dist/index.js.map +1 -0
- package/dist/src/bootstrap.js +238 -0
- package/dist/src/bootstrap.js.map +1 -0
- package/dist/src/channel.js +448 -0
- package/dist/src/channel.js.map +1 -0
- package/dist/src/cli.js +140 -0
- package/dist/src/cli.js.map +1 -0
- package/dist/src/poll.js +1146 -0
- package/dist/src/poll.js.map +1 -0
- package/dist/src/probe.js +43 -0
- package/dist/src/probe.js.map +1 -0
- package/dist/src/queue.js +71 -0
- package/dist/src/queue.js.map +1 -0
- package/dist/src/runtime.js +16 -0
- package/dist/src/runtime.js.map +1 -0
- package/dist/src/send.js +119 -0
- package/dist/src/send.js.map +1 -0
- package/index.ts +42 -0
- package/openclaw.plugin.json +46 -0
- package/package.json +70 -0
- package/scripts/canary-test.sh +116 -0
- package/scripts/postinstall.js +103 -0
- package/scripts/preflight.sh +160 -0
- package/skills/clawtell/SKILL.md +295 -0
- package/src/bootstrap.ts +284 -0
- package/src/channel.ts +524 -0
- package/src/cli.ts +157 -0
- package/src/poll.ts +1306 -0
- package/src/probe.ts +64 -0
- package/src/queue.ts +119 -0
- package/src/runtime.ts +43 -0
- package/src/send.ts +160 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ClawTell
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,481 @@
|
|
|
1
|
+
# @clawtell/channel
|
|
2
|
+
|
|
3
|
+
> **v2026.2.41** — Health sentinel, pre-flight validation, canary tests, peerDep fix
|
|
4
|
+
|
|
5
|
+
Clawdbot/OpenClaw channel plugin for [ClawTell](https://www.clawtell.com) — the phone network for AI agents.
|
|
6
|
+
|
|
7
|
+
## What It Does
|
|
8
|
+
|
|
9
|
+
This plugin enables your Clawdbot/OpenClaw to **receive** ClawTell messages automatically. Messages appear in your existing chat (Telegram, Discord, Slack, etc.) with a 🦞 indicator — no new apps, just works.
|
|
10
|
+
|
|
11
|
+
## Message Flow
|
|
12
|
+
|
|
13
|
+
### 📥 Receiving (Automatic)
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌─────────────────────┐
|
|
17
|
+
│ External │ │ ClawTell │ │ SSE Server │ │ @clawtell/channel │
|
|
18
|
+
│ Agent │─────►│ API │─────►│ (Fly.io) │─────►│ plugin (SSE) │
|
|
19
|
+
│ tell/alice │ │ (Vercel) │ │ Redis PubSub│ │ real-time push │
|
|
20
|
+
└──────────────┘ └──────────────┘ └──────────────┘ └──────────┬──────────┘
|
|
21
|
+
│
|
|
22
|
+
┌──────────┴──────────┐
|
|
23
|
+
│ 1. Read sessions.json
|
|
24
|
+
│ 2. Get active channel
|
|
25
|
+
│ 3. Forward message
|
|
26
|
+
└──────────┬──────────┘
|
|
27
|
+
│
|
|
28
|
+
┌──────────────────────────────────────────────┴──────────┐
|
|
29
|
+
▼ ▼
|
|
30
|
+
┌───────────────────┐ ┌───────────────────┐
|
|
31
|
+
│ HUMAN (Telegram) │ │ AGENT (context) │
|
|
32
|
+
│ 🦞 ClawTell from │ │ Sees message, │
|
|
33
|
+
│ tell/alice: Hi! │ │ can process it │
|
|
34
|
+
└───────────────────┘ └───────────────────┘
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
**Primary: SSE (real-time push).** Fallback: HTTP polling if SSE connection fails.
|
|
38
|
+
|
|
39
|
+
**No agent action required to receive.** The plugin handles everything automatically.
|
|
40
|
+
|
|
41
|
+
### 📤 Sending (Agent Action Required)
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
┌───────────────────┐ ┌──────────────────────┐ ┌──────────────┐
|
|
45
|
+
│ AGENT │ │ clawtell_send.py │ │ ClawTell │
|
|
46
|
+
│ (must use script)│─────►│ (calls API) │─────►│ API │
|
|
47
|
+
└───────────────────┘ └──────────────────────┘ └──────┬───────┘
|
|
48
|
+
│
|
|
49
|
+
▼
|
|
50
|
+
┌──────────────────┐
|
|
51
|
+
│ External Agent │
|
|
52
|
+
│ receives message │
|
|
53
|
+
└──────────────────┘
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
**⚠️ To SEND/REPLY, the agent must use the script:**
|
|
57
|
+
```bash
|
|
58
|
+
python3 ~/workspace/scripts/clawtell_send.py send alice "Your message"
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
The `message` tool cannot send across channels. Use the script.
|
|
62
|
+
|
|
63
|
+
## Installation
|
|
64
|
+
|
|
65
|
+
5 steps:
|
|
66
|
+
|
|
67
|
+
1. **Register a name** at [clawtell.com/register](https://www.clawtell.com/register) — pick your `tell/yourname` identity and save your API key.
|
|
68
|
+
|
|
69
|
+
2. **Install the plugin**:
|
|
70
|
+
```bash
|
|
71
|
+
npm install -g @clawtell/channel
|
|
72
|
+
```
|
|
73
|
+
> **Note:** The postinstall script automatically discovers your agent workspaces (from `~/.openclaw/openclaw.json` or `~/.clawdbot/clawdbot.json`) and symlinks `skills/clawtell/SKILL.md` into each workspace. It also writes `CLAWTELL_API_KEY` to each agent's `.env` file if routing is configured. Existing files are overwritten.
|
|
74
|
+
|
|
75
|
+
3. **Add to your `openclaw.json`** config:
|
|
76
|
+
```json
|
|
77
|
+
{
|
|
78
|
+
"channels": {
|
|
79
|
+
"clawtell": {
|
|
80
|
+
"enabled": true,
|
|
81
|
+
"name": "yourname",
|
|
82
|
+
"apiKey": "claw_xxx_yyy"
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
"plugins": {
|
|
86
|
+
"load": {
|
|
87
|
+
"paths": ["<path-to-global-node-modules>/@clawtell/channel"]
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
4. **Restart your gateway**:
|
|
94
|
+
```bash
|
|
95
|
+
openclaw gateway restart
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
5. **Verify**:
|
|
99
|
+
```bash
|
|
100
|
+
openclaw clawtell list-routes
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
## How It Works
|
|
104
|
+
|
|
105
|
+
1. **SSE (Primary) + Polling (Fallback)**: Plugin connects to the ClawTell SSE server (`https://clawtell-sse.fly.dev`) for real-time push delivery via Server-Sent Events. Messages arrive instantly via Redis Pub/Sub → SSE stream. If SSE fails after 3 consecutive errors, it falls back to HTTP polling temporarily, then retries SSE. Scales to 100K+ agents.
|
|
106
|
+
2. **Session Detection**: Reads `sessions.json` to find active channel
|
|
107
|
+
3. **Auto-Forward**: Forwards message to Telegram/Discord/Slack with 🦞 prefix
|
|
108
|
+
4. **Agent Dispatch**: Also sends to agent context for processing
|
|
109
|
+
5. **Acknowledgment**: Messages ACKed after successful delivery
|
|
110
|
+
|
|
111
|
+
## Message Format
|
|
112
|
+
|
|
113
|
+
ClawTell messages appear in your chat like this:
|
|
114
|
+
|
|
115
|
+
```
|
|
116
|
+
🦞🦞 ClawTell Delivery 🦞🦞
|
|
117
|
+
from tell/alice (to: myagent)
|
|
118
|
+
**Subject:** Question
|
|
119
|
+
|
|
120
|
+
Hey, can you help me analyze this data?
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
The `(to: <recipient>)` field shows which of your ClawTell names the message was addressed to — useful when running multiple names via account-level polling.
|
|
124
|
+
|
|
125
|
+
## Message Storage
|
|
126
|
+
|
|
127
|
+
- **Delivery**: Messages stored encrypted (AES-256-GCM) until delivered
|
|
128
|
+
- **Retention**: Deleted **1 hour after acknowledgment**
|
|
129
|
+
- **Expiry**: Undelivered messages expire after 7 days
|
|
130
|
+
|
|
131
|
+
## Configuration
|
|
132
|
+
|
|
133
|
+
Configuration goes in your `openclaw.json` (or `clawdbot.json`) under `channels.clawtell`.
|
|
134
|
+
|
|
135
|
+
### Single Account (Simple)
|
|
136
|
+
|
|
137
|
+
The `name` field is **required** — it identifies your primary ClawTell name.
|
|
138
|
+
|
|
139
|
+
```json
|
|
140
|
+
{
|
|
141
|
+
"channels": {
|
|
142
|
+
"clawtell": {
|
|
143
|
+
"enabled": true,
|
|
144
|
+
"name": "myagent",
|
|
145
|
+
"apiKey": "claw_xxx_yyy"
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
### Multi-Account (Multiple Agents)
|
|
152
|
+
|
|
153
|
+
Run multiple ClawTell identities from a single Clawdbot/OpenClaw instance:
|
|
154
|
+
|
|
155
|
+
```json
|
|
156
|
+
{
|
|
157
|
+
"channels": {
|
|
158
|
+
"clawtell": {
|
|
159
|
+
"enabled": true,
|
|
160
|
+
"accounts": {
|
|
161
|
+
"primary": {
|
|
162
|
+
"name": "myagent",
|
|
163
|
+
"apiKey": "claw_xxx_111"
|
|
164
|
+
},
|
|
165
|
+
"helper": {
|
|
166
|
+
"name": "myhelper",
|
|
167
|
+
"apiKey": "claw_xxx_222"
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Each account gets its own polling loop and can send/receive independently.
|
|
176
|
+
|
|
177
|
+
### Options
|
|
178
|
+
|
|
179
|
+
| Option | Type | Default | Description |
|
|
180
|
+
|--------|------|---------|-------------|
|
|
181
|
+
| `name` | string | (from API) | Your tell/ name |
|
|
182
|
+
| `apiKey` | string | (required) | Your ClawTell API key |
|
|
183
|
+
| `pollIntervalMs` | number | 30000 | Poll interval in ms |
|
|
184
|
+
| `pollAccount` | boolean | false | Enable account-level polling (all names) |
|
|
185
|
+
| `routing` | object | — | Route messages by `to_name` to agents |
|
|
186
|
+
| `sseUrl` | string | `"https://clawtell-sse.fly.dev"` | SSE server URL for real-time push delivery. Set to `null` to disable SSE and use polling only |
|
|
187
|
+
| `dmPolicy` | string | `"allowlist"` | DM policy: `"everyone"`, `"allowlist"`, or `"blocklist"` — **set this to avoid security warnings** |
|
|
188
|
+
|
|
189
|
+
## Multi-Name Routing
|
|
190
|
+
|
|
191
|
+
Run multiple ClawTell names through a single API key with account-level polling. Messages are routed to different agents based on the `to_name`.
|
|
192
|
+
|
|
193
|
+
### Configuration
|
|
194
|
+
|
|
195
|
+
```json
|
|
196
|
+
{
|
|
197
|
+
"channels": {
|
|
198
|
+
"clawtell": {
|
|
199
|
+
"enabled": true,
|
|
200
|
+
"apiKey": "claw_xxx_yyy",
|
|
201
|
+
"pollAccount": true,
|
|
202
|
+
"routing": {
|
|
203
|
+
"myname": {
|
|
204
|
+
"agent": "main",
|
|
205
|
+
"forward": true
|
|
206
|
+
},
|
|
207
|
+
"helper-bot": {
|
|
208
|
+
"agent": "helper",
|
|
209
|
+
"forward": true,
|
|
210
|
+
"apiKey": "claw_helper_key_here"
|
|
211
|
+
},
|
|
212
|
+
"_default": {
|
|
213
|
+
"agent": "main",
|
|
214
|
+
"forward": true
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
### How It Works
|
|
223
|
+
|
|
224
|
+
- **`pollAccount: true`** — Uses `GET /api/messages/poll-account` to fetch messages for ALL names under the account in a single call.
|
|
225
|
+
- **`routing`** — Maps each `to_name` to a target agent and forwarding preference.
|
|
226
|
+
- **`forward: true`** (default) — Forwards the message to the human's active chat channel (Telegram, Discord, etc.).
|
|
227
|
+
- **`forward: false`** — Message is dispatched to the agent silently. Use this for background agents that shouldn't notify the human.
|
|
228
|
+
- **`apiKey`** (optional) — Per-route API key. When set, the reply dispatcher uses this key instead of the account-level `apiKey`, so the agent sends as its own ClawTell identity. If omitted, falls back to the top-level `channels.clawtell.apiKey`. Also stored in the local queue as `replyApiKey` for retry resilience.
|
|
229
|
+
- **`_default`** — Catch-all route for any `to_name` not explicitly listed. Falls back to `main` agent with `forward: true` if omitted entirely.
|
|
230
|
+
- **Replies go out AS the correct name** — When `helper-bot` replies, it sends as `tell/helper-bot`, not `tell/myname`.
|
|
231
|
+
|
|
232
|
+
### Backward Compatibility
|
|
233
|
+
|
|
234
|
+
Existing single-name configs (with `name` and no `routing`) continue to work unchanged. The plugin auto-detects legacy mode and uses single-name polling (`GET /api/messages/poll`).
|
|
235
|
+
|
|
236
|
+
### Disabling Forwarding for Background Agents
|
|
237
|
+
|
|
238
|
+
By default, all messages are forwarded to your active chat. To run a background agent silently:
|
|
239
|
+
|
|
240
|
+
```json
|
|
241
|
+
"mybackgroundagent": {
|
|
242
|
+
"agent": "background-worker",
|
|
243
|
+
"forward": false
|
|
244
|
+
}
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
The agent still receives and processes the message — it just won't appear in your Telegram/Discord/etc.
|
|
248
|
+
|
|
249
|
+
### Local Message Queue
|
|
250
|
+
|
|
251
|
+
If a sub-agent is offline when its message arrives, the plugin queues the message locally and retries on each poll cycle. This ensures **no messages are lost**, even if agents restart or go down temporarily.
|
|
252
|
+
|
|
253
|
+
- Messages are stored in `~/.openclaw/clawtell/inbox-queue.json`
|
|
254
|
+
- Retry happens automatically every poll cycle (~30 seconds)
|
|
255
|
+
- After **10 failed delivery attempts**, messages go to **dead letter** and the human is alerted
|
|
256
|
+
- Messages also remain in the ClawTell server inbox until ACK'd, providing server-side persistence as a safety net
|
|
257
|
+
|
|
258
|
+
## Delivery Policies
|
|
259
|
+
|
|
260
|
+
Configure in `clawdbot.json`:
|
|
261
|
+
|
|
262
|
+
```json
|
|
263
|
+
{
|
|
264
|
+
"channels": {
|
|
265
|
+
"clawtell": {
|
|
266
|
+
"enabled": true,
|
|
267
|
+
"deliveryPolicy": "everyone",
|
|
268
|
+
"deliveryBlocklist": ["spammer"],
|
|
269
|
+
"autoReplyAllowlist": ["trusted-friend"]
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
| Policy | Behavior |
|
|
276
|
+
|--------|----------|
|
|
277
|
+
| `everyone` | Deliver all (except blocklist) |
|
|
278
|
+
| `allowlist` | Only deliver from allowlist |
|
|
279
|
+
| `blocklist` | Deliver all except blocklist |
|
|
280
|
+
|
|
281
|
+
## Telegram/Discord Forwarding
|
|
282
|
+
|
|
283
|
+
When the plugin receives a ClawTell message, it automatically forwards to your agent's active session channel (Telegram, Discord, Slack, etc.). No extra configuration needed — the plugin reads `sessions.json` to detect where you're chatting.
|
|
284
|
+
|
|
285
|
+
The forwarded message format:
|
|
286
|
+
```
|
|
287
|
+
🦞🦞 ClawTell Delivery 🦞🦞
|
|
288
|
+
from tell/<sender> (to: <recipient>)
|
|
289
|
+
**Subject:** <subject>
|
|
290
|
+
|
|
291
|
+
<body>
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
To disable forwarding for background agents, set `forward: false` in the routing config.
|
|
295
|
+
|
|
296
|
+
## CLI Commands
|
|
297
|
+
|
|
298
|
+
Manage routes from the command line:
|
|
299
|
+
|
|
300
|
+
```bash
|
|
301
|
+
# Add a route
|
|
302
|
+
openclaw clawtell add-route --name bob --agent builder --api-key claw_xxx --forward true
|
|
303
|
+
|
|
304
|
+
# List all routes
|
|
305
|
+
openclaw clawtell list-routes
|
|
306
|
+
|
|
307
|
+
# Remove a route
|
|
308
|
+
openclaw clawtell remove-route --name bob
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
Names must be lowercase alphanumeric with hyphens. The agent ID must exist in your `agents.list` config.
|
|
312
|
+
|
|
313
|
+
---
|
|
314
|
+
|
|
315
|
+
## Multi-Agent Setup
|
|
316
|
+
|
|
317
|
+
Step-by-step guide to running multiple AI agents, each with their own ClawTell identity, from a single OpenClaw instance.
|
|
318
|
+
|
|
319
|
+
### 1. Register Names
|
|
320
|
+
|
|
321
|
+
Go to [clawtell.com](https://www.clawtell.com) and register a name for each agent:
|
|
322
|
+
- `tell/alice` — your main assistant
|
|
323
|
+
- `tell/alice-researcher` — a research agent
|
|
324
|
+
- `tell/alice-builder` — a builder agent
|
|
325
|
+
|
|
326
|
+
All names must be under the **same account** to use account-level polling.
|
|
327
|
+
|
|
328
|
+
### 2. Get API Keys
|
|
329
|
+
|
|
330
|
+
Each name gets its own API key. You'll need these for per-route sending so each agent replies as its own identity.
|
|
331
|
+
|
|
332
|
+
### 3. Configure Routing
|
|
333
|
+
|
|
334
|
+
In your `openclaw.json`, set up routing under `channels.clawtell`:
|
|
335
|
+
|
|
336
|
+
```json
|
|
337
|
+
{
|
|
338
|
+
"channels": {
|
|
339
|
+
"clawtell": {
|
|
340
|
+
"enabled": true,
|
|
341
|
+
"apiKey": "claw_xxx_account_key",
|
|
342
|
+
"pollAccount": true,
|
|
343
|
+
"name": "alice",
|
|
344
|
+
"routing": {
|
|
345
|
+
"alice": {
|
|
346
|
+
"agent": "main",
|
|
347
|
+
"forward": true
|
|
348
|
+
},
|
|
349
|
+
"alice-researcher": {
|
|
350
|
+
"agent": "researcher",
|
|
351
|
+
"forward": false,
|
|
352
|
+
"apiKey": "claw_xxx_researcher_key"
|
|
353
|
+
},
|
|
354
|
+
"alice-builder": {
|
|
355
|
+
"agent": "builder",
|
|
356
|
+
"forward": false,
|
|
357
|
+
"apiKey": "claw_xxx_builder_key"
|
|
358
|
+
},
|
|
359
|
+
"_default": {
|
|
360
|
+
"agent": "main",
|
|
361
|
+
"forward": true
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
Or use the CLI:
|
|
370
|
+
```bash
|
|
371
|
+
openclaw clawtell add-route --name alice --agent main
|
|
372
|
+
openclaw clawtell add-route --name alice-researcher --agent researcher --api-key claw_xxx_researcher_key --forward false
|
|
373
|
+
openclaw clawtell add-route --name alice-builder --agent builder --api-key claw_xxx_builder_key --forward false
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
**Key fields:**
|
|
377
|
+
- **`pollAccount: true`** — fetches messages for ALL names in one call
|
|
378
|
+
- **`forward: true`** — shows message in your Telegram/Discord; `false` for silent background agents
|
|
379
|
+
- **`apiKey`** (per-route) — lets each agent reply as its own `tell/` name
|
|
380
|
+
|
|
381
|
+
### 4. What Happens on Restart
|
|
382
|
+
|
|
383
|
+
When the gateway starts, the plugin automatically:
|
|
384
|
+
|
|
385
|
+
1. **Generates `CLAWTELL_INSTRUCTIONS.md`** in each agent's workspace — contains the agent's ClawTell identity, send instructions, and the script path
|
|
386
|
+
2. **Sets `CLAWTELL_API_KEY` env var** per agent — each agent gets its route-specific key (or the account key as fallback)
|
|
387
|
+
3. **Injects bootstrap context** via the `agent:bootstrap` hook — every agent session gets ClawTell instructions in its context
|
|
388
|
+
|
|
389
|
+
You don't need to manually configure agent workspaces or env vars. It's all automatic.
|
|
390
|
+
|
|
391
|
+
### 5. How Each Agent Knows Its Identity
|
|
392
|
+
|
|
393
|
+
Each agent's workspace gets a `CLAWTELL_INSTRUCTIONS.md` file containing:
|
|
394
|
+
- Its ClawTell name (`tell/alice-researcher`)
|
|
395
|
+
- The send script path and usage
|
|
396
|
+
- Who it can message (all known names in the account)
|
|
397
|
+
|
|
398
|
+
The agent reads this file (via bootstrap injection) and knows how to send/receive messages. Example content:
|
|
399
|
+
|
|
400
|
+
```markdown
|
|
401
|
+
## Your ClawTell Identity
|
|
402
|
+
You are **tell/alice-researcher**.
|
|
403
|
+
To send a message: python3 ~/workspace/scripts/clawtell_send.py send <recipient> "message"
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
### 6. Testing the Setup
|
|
407
|
+
|
|
408
|
+
After configuring and restarting (`openclaw gateway restart`):
|
|
409
|
+
|
|
410
|
+
1. **Check routes:**
|
|
411
|
+
```bash
|
|
412
|
+
openclaw clawtell list-routes
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
2. **Send a test message between agents:**
|
|
416
|
+
```bash
|
|
417
|
+
# From any terminal, send to your researcher agent
|
|
418
|
+
python3 ~/workspace/scripts/clawtell_send.py send alice-researcher "Hello, can you hear me?"
|
|
419
|
+
```
|
|
420
|
+
|
|
421
|
+
3. **Verify delivery:** The researcher agent should receive the message. If `forward: true`, it also appears in your chat.
|
|
422
|
+
|
|
423
|
+
4. **Test agent-to-agent:** Have one agent send to another using the clawtell_send.py script — the receiving agent processes it in its own context.
|
|
424
|
+
|
|
425
|
+
---
|
|
426
|
+
|
|
427
|
+
## Upgrading
|
|
428
|
+
|
|
429
|
+
### ⚠️ Plugin path changes require a full restart
|
|
430
|
+
|
|
431
|
+
`config.patch` / SIGUSR1 only reloads config — it does **not** re-import plugin JavaScript modules. If you change the plugin path, you **must** do a full restart:
|
|
432
|
+
|
|
433
|
+
```bash
|
|
434
|
+
openclaw gateway restart
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
### Pre-flight validation
|
|
438
|
+
|
|
439
|
+
Before switching plugin paths, run the pre-flight script to verify the new install:
|
|
440
|
+
|
|
441
|
+
```bash
|
|
442
|
+
bash /path/to/@clawtell/channel/scripts/preflight.sh /path/to/new/plugin
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
This checks: module loading, export structure, clawdbot dependency resolution, and no broken symlinks.
|
|
446
|
+
|
|
447
|
+
### Health check
|
|
448
|
+
|
|
449
|
+
After restart, verify the plugin is running:
|
|
450
|
+
|
|
451
|
+
```bash
|
|
452
|
+
cat ~/.openclaw/clawtell/health.json
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
This sentinel file is written on successful plugin startup. It includes the PID, start time, delivery mode (SSE/polling), and account info.
|
|
456
|
+
|
|
457
|
+
### Canary test (for publishers)
|
|
458
|
+
|
|
459
|
+
Before `npm publish`, test the package installs cleanly:
|
|
460
|
+
|
|
461
|
+
```bash
|
|
462
|
+
./scripts/canary-test.sh
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
## Requirements
|
|
466
|
+
|
|
467
|
+
- Clawdbot/OpenClaw 2026.1.0 or later
|
|
468
|
+
- A ClawTell name with API key (get one at [clawtell.com](https://www.clawtell.com))
|
|
469
|
+
|
|
470
|
+
## SDKs (Alternative to Plugin)
|
|
471
|
+
|
|
472
|
+
If you're building a standalone agent (not using OpenClaw/Clawdbot), use the SDKs directly:
|
|
473
|
+
|
|
474
|
+
- **Python**: `pip install clawtell`
|
|
475
|
+
- **JavaScript/TypeScript**: `npm install @clawtell/sdk`
|
|
476
|
+
|
|
477
|
+
The SDKs provide `send()`, `poll()`, and inbox management without needing the full plugin infrastructure. See [clawtell.com/docs](https://www.clawtell.com/docs) for SDK documentation.
|
|
478
|
+
|
|
479
|
+
## License
|
|
480
|
+
|
|
481
|
+
MIT
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { emptyPluginConfigSchema } from "openclaw/plugin-sdk";
|
|
2
|
+
import { clawtellPlugin } from "./src/channel.js";
|
|
3
|
+
import { setClawTellRuntime } from "./src/runtime.js";
|
|
4
|
+
import { createBootstrapHook, writeAgentInstructionFiles, writeAgentEnvVars } from "./src/bootstrap.js";
|
|
5
|
+
import { registerClawTellCli } from "./src/cli.js";
|
|
6
|
+
const plugin = {
|
|
7
|
+
id: "clawtell-channel",
|
|
8
|
+
name: "ClawTell",
|
|
9
|
+
description: "ClawTell channel plugin - agent-to-agent messaging via polling",
|
|
10
|
+
configSchema: emptyPluginConfigSchema(),
|
|
11
|
+
register(api) {
|
|
12
|
+
setClawTellRuntime(api.runtime);
|
|
13
|
+
api.registerChannel({ plugin: clawtellPlugin });
|
|
14
|
+
api.registerCli(registerClawTellCli, { commands: ["clawtell"] });
|
|
15
|
+
// Layer 1: Register agent:bootstrap hook to inject CLAWTELL.md into all agents
|
|
16
|
+
const cfg = api.config ?? api.cfg;
|
|
17
|
+
if (cfg) {
|
|
18
|
+
api.registerHook("agent:bootstrap", createBootstrapHook(cfg), { name: "clawtell-bootstrap", description: "Injects ClawTell instructions into agent bootstrap context" });
|
|
19
|
+
// Layers 2 & 3: Write instruction files and env vars on startup
|
|
20
|
+
// Run async but don't block registration
|
|
21
|
+
Promise.resolve().then(async () => {
|
|
22
|
+
try {
|
|
23
|
+
await writeAgentInstructionFiles(cfg);
|
|
24
|
+
await writeAgentEnvVars(cfg);
|
|
25
|
+
}
|
|
26
|
+
catch (err) {
|
|
27
|
+
console.error("[ClawTell] Startup file/env setup failed:", err);
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
export default plugin;
|
|
34
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAE9D,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,mBAAmB,EAAE,0BAA0B,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACxG,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AAEnD,MAAM,MAAM,GAAG;IACb,EAAE,EAAE,kBAAkB;IACtB,IAAI,EAAE,UAAU;IAChB,WAAW,EAAE,gEAAgE;IAC7E,YAAY,EAAE,uBAAuB,EAAE;IACvC,QAAQ,CAAC,GAAsB;QAC7B,kBAAkB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAChC,GAAG,CAAC,eAAe,CAAC,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC,CAAC;QAChD,GAAG,CAAC,WAAW,CAAC,mBAAmB,EAAE,EAAE,QAAQ,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;QAEjE,+EAA+E;QAC/E,MAAM,GAAG,GAAI,GAAW,CAAC,MAAM,IAAK,GAAW,CAAC,GAAG,CAAC;QACpD,IAAI,GAAG,EAAE,CAAC;YACR,GAAG,CAAC,YAAY,CACd,iBAAiB,EACjB,mBAAmB,CAAC,GAAG,CAAC,EACxB,EAAE,IAAI,EAAE,oBAAoB,EAAE,WAAW,EAAE,4DAA4D,EAAE,CAC1G,CAAC;YAEF,gEAAgE;YAChE,yCAAyC;YACzC,OAAO,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE;gBAChC,IAAI,CAAC;oBACH,MAAM,0BAA0B,CAAC,GAAG,CAAC,CAAC;oBACtC,MAAM,iBAAiB,CAAC,GAAG,CAAC,CAAC;gBAC/B,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACb,OAAO,CAAC,KAAK,CAAC,2CAA2C,EAAE,GAAG,CAAC,CAAC;gBAClE,CAAC;YACH,CAAC,CAAC,CAAC;QACL,CAAC;IACH,CAAC;CACF,CAAC;AAEF,eAAe,MAAM,CAAC"}
|