@trusted-ai/xbot 0.1.0
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.txt +21 -0
- package/README.md +214 -0
- package/bin/xbot.js +50 -0
- package/docs/ARCHITECTURE.md +161 -0
- package/docs/HYBRID_MODELS.md +156 -0
- package/docs/INSTALLATION.md +78 -0
- package/docs/OPERATIONS.md +211 -0
- package/docs/USAGE.md +1002 -0
- package/docs/xbot.png +0 -0
- package/package.json +53 -0
- package/scripts/install.js +123 -0
- package/skills/README.md +10 -0
- package/skills/clawhub/SKILL.md +71 -0
- package/skills/cron/SKILL.md +64 -0
- package/skills/data-analyst/SKILL.md +31 -0
- package/skills/delivery-rules/SKILL.md +23 -0
- package/skills/github/SKILL.md +99 -0
- package/skills/github-cli/SKILL.md +35 -0
- package/skills/memory/SKILL.md +70 -0
- package/skills/memory-entry-writer/SKILL.md +26 -0
- package/skills/memory-hygiene/SKILL.md +34 -0
- package/skills/project-context/SKILL.md +23 -0
- package/skills/project-init/SKILL.md +84 -0
- package/skills/scheduled-ops/SKILL.md +24 -0
- package/skills/skill-creator/SKILL.md +202 -0
- package/skills/software-engineer/SKILL.md +44 -0
- package/skills/summarize/SKILL.md +72 -0
- package/skills/tmux/SKILL.md +122 -0
- package/skills/weather/SKILL.md +54 -0
- package/skills/workspace-operator/SKILL.md +24 -0
package/docs/USAGE.md
ADDED
|
@@ -0,0 +1,1002 @@
|
|
|
1
|
+
# xbot Usage Guide
|
|
2
|
+
|
|
3
|
+
## 1. Install and Initialize
|
|
4
|
+
|
|
5
|
+
From the project root:
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
cd xbot
|
|
9
|
+
cargo run --release -- onboard
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
For packaged installs through npm, `.deb`, or `cargo install`, see [Installation](./INSTALLATION.md).
|
|
13
|
+
|
|
14
|
+
This creates:
|
|
15
|
+
|
|
16
|
+
- `~/.xbot/config.json`
|
|
17
|
+
- `~/.xbot/workspace/`
|
|
18
|
+
- a hidden runtime state directory at `<workspace>/.xbot/`
|
|
19
|
+
- workspace bootstrap files such as `.xbot/AGENTS.md`, `.xbot/SOUL.md`, `.xbot/USER.md`, `.xbot/TOOLS.md`, `.xbot/HEARTBEAT.md`, and memory files
|
|
20
|
+
- starter workspace skills under `.xbot/skills/`, including a memory-hygiene skill and editable project templates
|
|
21
|
+
|
|
22
|
+
## 2. Interactive Configuration
|
|
23
|
+
|
|
24
|
+
Instead of manually editing `~/.xbot/config.json`, you can use the interactive CLI:
|
|
25
|
+
|
|
26
|
+
### 2.1 Provider Configuration
|
|
27
|
+
|
|
28
|
+
Configure your LLM providers (OpenAI, Anthropic, OpenRouter, Ollama, vLLM, etc.):
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
cargo run --release -- config --provider
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
The CLI will guide you through:
|
|
35
|
+
1. Selecting a provider from the list.
|
|
36
|
+
2. Entering your API key (if required).
|
|
37
|
+
3. Fetching and selecting from available models.
|
|
38
|
+
4. Setting the default model and provider for the agent.
|
|
39
|
+
5. Optionally configuring a separate provider/API base or model for background subagents.
|
|
40
|
+
|
|
41
|
+
### 2.2 Channel Configuration
|
|
42
|
+
|
|
43
|
+
Configure communication channels (Telegram, Slack, Email, etc.):
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
cargo run --release -- config --channel
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
You can selectively enable channels, set permissions (`allowFrom`), and provide necessary tokens or secrets interactively.
|
|
50
|
+
|
|
51
|
+
## 3. Choose a Provider (Manual)
|
|
52
|
+
|
|
53
|
+
`xbot` talks to providers through an OpenAI-compatible chat interface.
|
|
54
|
+
|
|
55
|
+
Supported practical modes:
|
|
56
|
+
|
|
57
|
+
- Remote API providers such as OpenAI-compatible gateways
|
|
58
|
+
- Local engines such as Ollama and vLLM
|
|
59
|
+
- Custom local or remote OpenAI-compatible servers
|
|
60
|
+
|
|
61
|
+
### Openrouter example
|
|
62
|
+
|
|
63
|
+
```json
|
|
64
|
+
{
|
|
65
|
+
"agents": {
|
|
66
|
+
"defaults": {
|
|
67
|
+
"model": "minimax/minimax-m2.7",
|
|
68
|
+
"provider": "openrouter"
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
"providers": {
|
|
72
|
+
"openrouter": {
|
|
73
|
+
"apiKey": "sk-or-v1-...",
|
|
74
|
+
"extraHeaders": {}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### OpenAI-compatible remote example
|
|
81
|
+
|
|
82
|
+
```json
|
|
83
|
+
{
|
|
84
|
+
"agents": {
|
|
85
|
+
"defaults": {
|
|
86
|
+
"model": "openai/gpt-4.1-mini",
|
|
87
|
+
"provider": "openai"
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
"providers": {
|
|
91
|
+
"openai": {
|
|
92
|
+
"apiKey": "sk-..."
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Ollama example
|
|
99
|
+
|
|
100
|
+
`xbot` supports Ollama as a local provider without requiring an API key.
|
|
101
|
+
|
|
102
|
+
Start Ollama first:
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
ollama serve
|
|
106
|
+
ollama pull qwen2.5-coder:7b
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Then configure:
|
|
110
|
+
|
|
111
|
+
```json
|
|
112
|
+
{
|
|
113
|
+
"agents": {
|
|
114
|
+
"defaults": {
|
|
115
|
+
"model": "ollama/qwen2.5-coder:7b",
|
|
116
|
+
"provider": "ollama"
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
"providers": {
|
|
120
|
+
"ollama": {
|
|
121
|
+
"apiBase": "http://localhost:11434/v1"
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### vLLM example
|
|
128
|
+
|
|
129
|
+
If you are serving a model with vLLM on port `8000`:
|
|
130
|
+
|
|
131
|
+
```json
|
|
132
|
+
{
|
|
133
|
+
"agents": {
|
|
134
|
+
"defaults": {
|
|
135
|
+
"model": "vllm/Qwen/Qwen2.5-7B-Instruct",
|
|
136
|
+
"provider": "vllm"
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
"providers": {
|
|
140
|
+
"vllm": {
|
|
141
|
+
"apiBase": "http://localhost:8000/v1"
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### LM Studio or another local OpenAI-compatible server
|
|
148
|
+
|
|
149
|
+
Use the `custom` provider:
|
|
150
|
+
|
|
151
|
+
```json
|
|
152
|
+
{
|
|
153
|
+
"agents": {
|
|
154
|
+
"defaults": {
|
|
155
|
+
"model": "custom/local-model",
|
|
156
|
+
"provider": "custom"
|
|
157
|
+
}
|
|
158
|
+
},
|
|
159
|
+
"providers": {
|
|
160
|
+
"custom": {
|
|
161
|
+
"apiBase": "http://127.0.0.1:1234/v1",
|
|
162
|
+
"apiKey": ""
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Notes:
|
|
169
|
+
|
|
170
|
+
- Known local providers such as `ollama` and `vllm` do not require an API key.
|
|
171
|
+
- Custom providers can use an empty API key when the upstream server does not require auth.
|
|
172
|
+
- The model string can be any identifier accepted by the target backend.
|
|
173
|
+
|
|
174
|
+
### Subagent model/provider override
|
|
175
|
+
|
|
176
|
+
By default, background subagents use the same provider and model as the main task. You can run subagents on a cheaper or faster model by setting `agents.subagents`.
|
|
177
|
+
|
|
178
|
+
For a complete remote-main/local-subagent walkthrough, including DeepSeek `deepseek-v4-pro` as the main model and a local Qwen model for subagents, see [Hybrid Remote Main + Local Subagents](./HYBRID_MODELS.md).
|
|
179
|
+
|
|
180
|
+
Example: main task uses a heavier OpenAI model, while subagents use a local OpenAI-compatible server:
|
|
181
|
+
|
|
182
|
+
```json
|
|
183
|
+
{
|
|
184
|
+
"agents": {
|
|
185
|
+
"defaults": {
|
|
186
|
+
"model": "openai/gpt-4.1",
|
|
187
|
+
"provider": "openai"
|
|
188
|
+
},
|
|
189
|
+
"subagents": {
|
|
190
|
+
"model": "qwen2.5-coder:7b",
|
|
191
|
+
"provider": "subagent-fast",
|
|
192
|
+
"apiBase": "http://127.0.0.1:8001/v1"
|
|
193
|
+
}
|
|
194
|
+
},
|
|
195
|
+
"providers": {
|
|
196
|
+
"openai": {
|
|
197
|
+
"apiKey": "sk-..."
|
|
198
|
+
},
|
|
199
|
+
"subagent-fast": {
|
|
200
|
+
"apiKey": "",
|
|
201
|
+
"apiBase": "http://127.0.0.1:8001/v1"
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
`agents.subagents.model` is optional. If it is empty or omitted, subagents inherit the main task model. `agents.subagents.provider` defaults to `"auto"`. For an OpenAI-compatible local or remote backend, use a provider key such as `subagent-fast` and set `apiBase` either under `agents.subagents` or in the matching `providers` entry.
|
|
208
|
+
|
|
209
|
+
## 3. Run Modes
|
|
210
|
+
|
|
211
|
+
### One-shot prompt
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
cargo run --release -- chat "summarize the codebase"
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### Interactive shell
|
|
218
|
+
|
|
219
|
+
```bash
|
|
220
|
+
cargo run --release -- repl
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
The interactive shell is designed for day-to-day agent work:
|
|
224
|
+
|
|
225
|
+
- `repl` and `chat` bootstrap the current directory as a project workspace by creating `<cwd>/.xbot/` by default
|
|
226
|
+
- persistent command history in `<workspace>/.xbot/history.txt`
|
|
227
|
+
- streamed model output instead of waiting for the full reply
|
|
228
|
+
- queued prompts while a turn is already running; queued turns start automatically when the current turn ends
|
|
229
|
+
- local shell commands: `/help`, `/clear`, `/exit`
|
|
230
|
+
- agent commands forwarded to the runtime: `/new`, `/status`, `/stop`
|
|
231
|
+
- multiline input by ending a line with `\`
|
|
232
|
+
- the welcome header shows both the current working directory and the active workspace
|
|
233
|
+
- the header also shows the active hidden state root under `<workspace>/.xbot`
|
|
234
|
+
- tool activity is shown with emoji-based pills such as file, shell, web, message, and cron actions
|
|
235
|
+
- fenced code blocks in replies are syntax-highlighted in the CLI by language when ANSI colors are available
|
|
236
|
+
- CLI session history is scoped by current working directory, so different projects do not share the same chat thread
|
|
237
|
+
|
|
238
|
+
To force `repl` or `chat` to use the configured global workspace, pass `--global`:
|
|
239
|
+
|
|
240
|
+
```bash
|
|
241
|
+
xbot repl --global
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
To use a specific workspace path instead, pass `--workspace`:
|
|
245
|
+
|
|
246
|
+
```bash
|
|
247
|
+
xbot repl --workspace ~/.xbot/workspace
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
## 3.1 Workspace Memory
|
|
251
|
+
|
|
252
|
+
`xbot` uses two memory files inside `workspace/.xbot/`:
|
|
253
|
+
|
|
254
|
+
- `.xbot/memory/MEMORY.md`: permanent memory store, capped at `agents.defaults.memoryMaxBytes` bytes
|
|
255
|
+
- `.xbot/memory/HISTORY.md`: resettable history log for later search and consolidation
|
|
256
|
+
|
|
257
|
+
Operational rule:
|
|
258
|
+
|
|
259
|
+
- completed user tasks are summarized into `MEMORY.md` with title, summary, attention points, and finish time through the `memory-entry-writer` skill
|
|
260
|
+
- explicit `memorize` or `/memorize <text>` requests are summarized through the same skill and stored in `MEMORY.md` as user instructed memory
|
|
261
|
+
- new tasks load only topic-relevant slices from `MEMORY.md`, not the entire file
|
|
262
|
+
- `clear` / `/clear` / `new` / `/new` resets the current session and restores `HISTORY.md` to the default template
|
|
263
|
+
|
|
264
|
+
New workspaces now include starter guidance, an always-on memory skill, and a dedicated `memory-entry-writer` skill so memory writes stay compact instead of copying large reply fragments.
|
|
265
|
+
|
|
266
|
+
Example config:
|
|
267
|
+
|
|
268
|
+
```json
|
|
269
|
+
{
|
|
270
|
+
"agents": {
|
|
271
|
+
"defaults": {
|
|
272
|
+
"memoryMaxBytes": 32768
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
### Long-running backend
|
|
279
|
+
|
|
280
|
+
```bash
|
|
281
|
+
cargo run --release -- run
|
|
282
|
+
```
|
|
283
|
+
|
|
284
|
+
`run` uses the workspace configured in `~/.xbot/config.json` by default. To run the backend against a project-local workspace, pass it explicitly:
|
|
285
|
+
|
|
286
|
+
```bash
|
|
287
|
+
xbot run --workspace .
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
`run` starts:
|
|
291
|
+
|
|
292
|
+
- the provider client
|
|
293
|
+
- the agent runtime
|
|
294
|
+
- cron jobs
|
|
295
|
+
- heartbeat review
|
|
296
|
+
- enabled channels
|
|
297
|
+
- the HTTP gateway
|
|
298
|
+
- the admin API and UI
|
|
299
|
+
- the metrics endpoint
|
|
300
|
+
|
|
301
|
+
### Slack without a public webhook
|
|
302
|
+
|
|
303
|
+
Slack supports two practical modes in `xbot`:
|
|
304
|
+
|
|
305
|
+
- `webhook`: Slack sends Events API requests to your public HTTPS endpoint
|
|
306
|
+
- `socket`: `xbot` opens an outbound WebSocket to Slack and does not require a public webhook URL (Public)
|
|
307
|
+
|
|
308
|
+
Example Socket Mode config:
|
|
309
|
+
|
|
310
|
+
```json
|
|
311
|
+
{
|
|
312
|
+
"channels": {
|
|
313
|
+
"slack": {
|
|
314
|
+
"enabled": true,
|
|
315
|
+
"mode": "socket",
|
|
316
|
+
"allowFrom": ["*"],
|
|
317
|
+
"botToken": "xoxb-...",
|
|
318
|
+
"appToken": "xapp-...",
|
|
319
|
+
"replyInThread": true,
|
|
320
|
+
"groupPolicy": "mention"
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
Notes:
|
|
327
|
+
|
|
328
|
+
- `mode: "socket"` requires both `botToken` and `appToken`
|
|
329
|
+
- you do not need `signingSecret` or a public `/slack/events` URL in socket mode
|
|
330
|
+
- in webhook mode, you still need a public HTTPS URL configured in Slack Event Subscriptions
|
|
331
|
+
|
|
332
|
+
## 4. Gateway Endpoints
|
|
333
|
+
|
|
334
|
+
When `run` is active, the gateway exposes:
|
|
335
|
+
|
|
336
|
+
- `GET /healthz`
|
|
337
|
+
- `GET /readyz`
|
|
338
|
+
- `GET /status`
|
|
339
|
+
- `GET /metrics`
|
|
340
|
+
- `GET /admin`
|
|
341
|
+
- `GET /api/admin/overview`
|
|
342
|
+
- `GET /api/admin/sessions`
|
|
343
|
+
- `GET /api/admin/cron`
|
|
344
|
+
|
|
345
|
+
The bind address comes from:
|
|
346
|
+
|
|
347
|
+
```json
|
|
348
|
+
{
|
|
349
|
+
"gateway": {
|
|
350
|
+
"host": "0.0.0.0",
|
|
351
|
+
"port": 18790
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
```
|
|
355
|
+
|
|
356
|
+
Admin and metrics paths can also be customized:
|
|
357
|
+
|
|
358
|
+
```json
|
|
359
|
+
{
|
|
360
|
+
"gateway": {
|
|
361
|
+
"admin": {
|
|
362
|
+
"enabled": true,
|
|
363
|
+
"path": "/admin"
|
|
364
|
+
},
|
|
365
|
+
"metrics": {
|
|
366
|
+
"enabled": true,
|
|
367
|
+
"path": "/metrics"
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
## 5. Channel Configuration
|
|
374
|
+
|
|
375
|
+
### Email
|
|
376
|
+
|
|
377
|
+
Email is polling-driven and does not require webhooks.
|
|
378
|
+
|
|
379
|
+
```json
|
|
380
|
+
{
|
|
381
|
+
"channels": {
|
|
382
|
+
"email": {
|
|
383
|
+
"enabled": true,
|
|
384
|
+
"allowFrom": ["*"],
|
|
385
|
+
"consentGranted": true,
|
|
386
|
+
"imapHost": "imap.example.com",
|
|
387
|
+
"imapPort": 993,
|
|
388
|
+
"imapUsername": "bot@example.com",
|
|
389
|
+
"imapPassword": "...",
|
|
390
|
+
"imapMailbox": "INBOX",
|
|
391
|
+
"imapUseSsl": true,
|
|
392
|
+
"smtpHost": "smtp.example.com",
|
|
393
|
+
"smtpPort": 587,
|
|
394
|
+
"smtpUsername": "bot@example.com",
|
|
395
|
+
"smtpPassword": "...",
|
|
396
|
+
"smtpUseTls": true,
|
|
397
|
+
"fromAddress": "bot@example.com",
|
|
398
|
+
"autoReplyEnabled": true,
|
|
399
|
+
"pollIntervalSeconds": 30
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
### Slack
|
|
406
|
+
|
|
407
|
+
Slack is currently webhook-driven in `xbot`.
|
|
408
|
+
|
|
409
|
+
```json
|
|
410
|
+
{
|
|
411
|
+
"channels": {
|
|
412
|
+
"sendProgress": true,
|
|
413
|
+
"sendToolHints": false,
|
|
414
|
+
"slack": {
|
|
415
|
+
"enabled": true,
|
|
416
|
+
"allowFrom": ["*"],
|
|
417
|
+
"botToken": "xoxb-...",
|
|
418
|
+
"signingSecret": "...",
|
|
419
|
+
"webhookPath": "/slack/events",
|
|
420
|
+
"replyInThread": true,
|
|
421
|
+
"groupPolicy": "mention"
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
Operational notes:
|
|
428
|
+
|
|
429
|
+
- `signingSecret` is required for startup validation.
|
|
430
|
+
- Point Slack event subscriptions at `http://<host>:<port>/slack/events`.
|
|
431
|
+
- Send software-development tasks as normal messages or mentions, for example: `review this repo, run tests, and fix failures`.
|
|
432
|
+
- `channels.sendToolHints` defaults to `false`; in that mode, `xbot` sends a muted-tool notice on the first tool call and batch summaries every 10 tool calls or before the next non-tool reply.
|
|
433
|
+
- Set `channels.sendToolHints` to `true` if you want every tool execution hint sent back to Slack while a task is running.
|
|
434
|
+
|
|
435
|
+
### Telegram
|
|
436
|
+
|
|
437
|
+
Telegram is currently webhook-driven in `xbot`.
|
|
438
|
+
|
|
439
|
+
```json
|
|
440
|
+
{
|
|
441
|
+
"channels": {
|
|
442
|
+
"sendProgress": true,
|
|
443
|
+
"sendToolHints": false,
|
|
444
|
+
"telegram": {
|
|
445
|
+
"enabled": true,
|
|
446
|
+
"allowFrom": ["*"],
|
|
447
|
+
"token": "<bot-token>",
|
|
448
|
+
"webhookPath": "/telegram/webhook",
|
|
449
|
+
"webhookSecret": "optional-shared-secret",
|
|
450
|
+
"replyToMessage": true,
|
|
451
|
+
"groupPolicy": "mention"
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
Set the Telegram webhook externally to:
|
|
458
|
+
|
|
459
|
+
`https://<your-domain>/telegram/webhook`
|
|
460
|
+
|
|
461
|
+
If `webhookSecret` is configured, Telegram requests must include the matching secret header.
|
|
462
|
+
|
|
463
|
+
Usage notes:
|
|
464
|
+
|
|
465
|
+
- Send development or analysis tasks as plain messages to the bot.
|
|
466
|
+
- In groups, `groupPolicy: "mention"` keeps the bot from reacting to every message.
|
|
467
|
+
- `channels.sendToolHints` defaults to `false`; in that mode, `xbot` sends a muted-tool notice on the first tool call and batch summaries every 10 tool calls or before the next non-tool reply.
|
|
468
|
+
- Set `channels.sendToolHints` to `true` if you want every tool execution hint sent back to Telegram while a task is running.
|
|
469
|
+
|
|
470
|
+
### Feishu
|
|
471
|
+
|
|
472
|
+
Feishu runs through the webhook gateway and supports inbound text, post, interactive cards, replies, and media/resource download.
|
|
473
|
+
|
|
474
|
+
```json
|
|
475
|
+
{
|
|
476
|
+
"channels": {
|
|
477
|
+
"sendProgress": true,
|
|
478
|
+
"sendToolHints": false,
|
|
479
|
+
"feishu": {
|
|
480
|
+
"enabled": true,
|
|
481
|
+
"allowFrom": ["*"],
|
|
482
|
+
"appId": "cli_xxx",
|
|
483
|
+
"appSecret": "...",
|
|
484
|
+
"verificationToken": "...",
|
|
485
|
+
"webhookPath": "/feishu/events",
|
|
486
|
+
"groupPolicy": "mention",
|
|
487
|
+
"replyToMessage": true,
|
|
488
|
+
"reactEmoji": "THUMBSUP"
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
Point Feishu event subscriptions at:
|
|
495
|
+
|
|
496
|
+
`https://<your-domain>/feishu/events`
|
|
497
|
+
|
|
498
|
+
Usage notes:
|
|
499
|
+
|
|
500
|
+
- Mention the bot in group chats when using `groupPolicy: "mention"`.
|
|
501
|
+
- Development tasks can be sent as normal text instructions, and Feishu replies can include dedicated tool-hint cards during execution.
|
|
502
|
+
- `channels.sendToolHints` defaults to `false`; in that mode, `xbot` sends a muted-tool notice on the first tool call and batch summaries every 10 tool calls or before the next non-tool reply.
|
|
503
|
+
- Set `channels.sendToolHints` to `true` if you want every tool execution hint card sent back during execution. Non-tool progress messages are still controlled by `channels.sendProgress`.
|
|
504
|
+
|
|
505
|
+
## 6. Combined Example
|
|
506
|
+
|
|
507
|
+
```json
|
|
508
|
+
{
|
|
509
|
+
"agents": {
|
|
510
|
+
"defaults": {
|
|
511
|
+
"workspace": "~/.xbot/workspace",
|
|
512
|
+
"model": "ollama/qwen2.5-coder:7b",
|
|
513
|
+
"provider": "ollama",
|
|
514
|
+
"maxToolIterations": 0,
|
|
515
|
+
"contextWindowTokens": 65536
|
|
516
|
+
},
|
|
517
|
+
"subagents": {
|
|
518
|
+
"model": "",
|
|
519
|
+
"provider": "auto"
|
|
520
|
+
}
|
|
521
|
+
},
|
|
522
|
+
"providers": {
|
|
523
|
+
"ollama": {
|
|
524
|
+
"apiBase": "http://localhost:11434/v1"
|
|
525
|
+
}
|
|
526
|
+
},
|
|
527
|
+
"gateway": {
|
|
528
|
+
"host": "0.0.0.0",
|
|
529
|
+
"port": 18790,
|
|
530
|
+
"heartbeat": {
|
|
531
|
+
"enabled": true,
|
|
532
|
+
"intervalS": 1800
|
|
533
|
+
}
|
|
534
|
+
},
|
|
535
|
+
"channels": {
|
|
536
|
+
"telegram": {
|
|
537
|
+
"enabled": true,
|
|
538
|
+
"allowFrom": ["*"],
|
|
539
|
+
"token": "<bot-token>",
|
|
540
|
+
"webhookPath": "/telegram/webhook"
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
```
|
|
545
|
+
|
|
546
|
+
`maxToolIterations: 0` means the agent loop is unbounded. Use a positive number only when you want a hard ceiling on tool calls.
|
|
547
|
+
|
|
548
|
+
## 7. MCP Tool Servers
|
|
549
|
+
|
|
550
|
+
`xbot` supports MCP over `stdio`. Enabled MCP tools are registered as native tools using names like `mcp_<server>_<tool>`.
|
|
551
|
+
|
|
552
|
+
Example:
|
|
553
|
+
|
|
554
|
+
```json
|
|
555
|
+
{
|
|
556
|
+
"tools": {
|
|
557
|
+
"mcpServers": {
|
|
558
|
+
"github": {
|
|
559
|
+
"enabled": true,
|
|
560
|
+
"type": "stdio",
|
|
561
|
+
"command": "npx",
|
|
562
|
+
"args": ["-y", "@modelcontextprotocol/server-github"],
|
|
563
|
+
"enabledTools": ["*"],
|
|
564
|
+
"toolTimeout": 30
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
```
|
|
570
|
+
|
|
571
|
+
Current scope:
|
|
572
|
+
|
|
573
|
+
- `stdio` transport is supported
|
|
574
|
+
- startup validation fails fast if an enabled MCP server has no command
|
|
575
|
+
- unsupported transports are rejected during startup
|
|
576
|
+
|
|
577
|
+
## 8. Built-in Skills
|
|
578
|
+
|
|
579
|
+
Built-in skills ship with the repository under `xbot/skills/`.
|
|
580
|
+
|
|
581
|
+
Current built-in set:
|
|
582
|
+
|
|
583
|
+
- `memory-hygiene` (always-on)
|
|
584
|
+
- `memory` (always-on)
|
|
585
|
+
- `memory-entry-writer`
|
|
586
|
+
- `workspace-operator`
|
|
587
|
+
- `software-engineer`
|
|
588
|
+
- `data-analyst`
|
|
589
|
+
- `github-cli`
|
|
590
|
+
- `github`
|
|
591
|
+
- `scheduled-ops`
|
|
592
|
+
- `cron`
|
|
593
|
+
- `clawhub`
|
|
594
|
+
- `skill-creator`
|
|
595
|
+
- `summarize`
|
|
596
|
+
- `weather`
|
|
597
|
+
- `tmux`
|
|
598
|
+
|
|
599
|
+
Behavior:
|
|
600
|
+
|
|
601
|
+
- always-on skills are injected automatically
|
|
602
|
+
- relevant task-specific skills are suggested and loaded based on prompt keywords
|
|
603
|
+
- skills with unmet requirements (missing binaries, env vars, or OS) are marked unavailable
|
|
604
|
+
- workspace-local skills live under `<workspace>/.xbot/skills/<name>/SKILL.md`
|
|
605
|
+
- new workspaces also get starter workspace skill templates that you can edit for project-specific context and delivery rules
|
|
606
|
+
|
|
607
|
+
### Skill Management
|
|
608
|
+
|
|
609
|
+
List all skills and their availability:
|
|
610
|
+
|
|
611
|
+
```bash
|
|
612
|
+
cargo run -- skills list
|
|
613
|
+
```
|
|
614
|
+
|
|
615
|
+
Scaffold a new skill:
|
|
616
|
+
|
|
617
|
+
```bash
|
|
618
|
+
cargo run -- skills init my-custom-skill
|
|
619
|
+
```
|
|
620
|
+
|
|
621
|
+
This creates `<workspace>/.xbot/skills/my-custom-skill/SKILL.md` with a starter template.
|
|
622
|
+
|
|
623
|
+
## 9. Useful Commands
|
|
624
|
+
|
|
625
|
+
Print the resolved config:
|
|
626
|
+
|
|
627
|
+
```bash
|
|
628
|
+
cargo run -- print-config
|
|
629
|
+
```
|
|
630
|
+
|
|
631
|
+
Run a different model without changing config:
|
|
632
|
+
|
|
633
|
+
```bash
|
|
634
|
+
cargo run --release -- run --model ollama/qwen2.5-coder:7b
|
|
635
|
+
```
|
|
636
|
+
|
|
637
|
+
Start a one-shot request against a specific model:
|
|
638
|
+
|
|
639
|
+
```bash
|
|
640
|
+
cargo run --release -- chat --model ollama/qwen2.5-coder:7b "list the next implementation tasks"
|
|
641
|
+
```
|
|
642
|
+
|
|
643
|
+
Inspect runtime state without starting the daemon:
|
|
644
|
+
|
|
645
|
+
```bash
|
|
646
|
+
cargo run -- sessions # List active chat sessions
|
|
647
|
+
cargo run -- jobs # List scheduled cron jobs
|
|
648
|
+
cargo run -- print-config # Print current resolved config
|
|
649
|
+
cargo run -- config --provider # Interactive provider setup
|
|
650
|
+
cargo run -- config --channel # Interactive channel setup
|
|
651
|
+
```
|
|
652
|
+
|
|
653
|
+
### Channel Management
|
|
654
|
+
|
|
655
|
+
```bash
|
|
656
|
+
cargo run -- channels list # List all available channels
|
|
657
|
+
cargo run -- channels status # Show enabled/disabled state per channel
|
|
658
|
+
cargo run -- channels login # Interactive login (e.g. Weixin QR code scan)
|
|
659
|
+
cargo run -- channels login weixin # Login to a specific channel
|
|
660
|
+
cargo run -- channels setup # Show setup instructions for a channel
|
|
661
|
+
cargo run -- channels setup discord # Setup instructions for a specific channel
|
|
662
|
+
```
|
|
663
|
+
|
|
664
|
+
### Skill Management
|
|
665
|
+
|
|
666
|
+
```bash
|
|
667
|
+
cargo run -- skills list # List skills with availability status
|
|
668
|
+
cargo run -- skills init NAME # Scaffold a new skill directory
|
|
669
|
+
```
|
|
670
|
+
|
|
671
|
+
## 10. Operational Notes
|
|
672
|
+
|
|
673
|
+
- `run` validates enabled channel config before startup.
|
|
674
|
+
- `run` also validates enabled MCP server configuration before startup.
|
|
675
|
+
- Local providers are accepted without API keys when the provider is recognized as local.
|
|
676
|
+
- Outbound runtime/system errors are surfaced through the runtime logs instead of being silently dropped.
|
|
677
|
+
- Feishu media downloads are stored under `~/.xbot/media/feishu`.
|
|
678
|
+
- The admin UI polls the runtime every few seconds and exposes channel controls plus heartbeat triggering.
|
|
679
|
+
- The metrics endpoint exposes Prometheus-compatible counters and gauges for message counts, provider requests, token totals, latency, and throughput.
|
|
680
|
+
|
|
681
|
+
## 11. Additional Channel Configuration
|
|
682
|
+
|
|
683
|
+
Each channel section below includes how to obtain the required credentials and the config format. You can also run `xbot channels setup <name>` to see setup instructions in the terminal.
|
|
684
|
+
|
|
685
|
+
### DingTalk
|
|
686
|
+
|
|
687
|
+
DingTalk uses the Stream gateway WebSocket protocol.
|
|
688
|
+
|
|
689
|
+
**How to obtain credentials:**
|
|
690
|
+
|
|
691
|
+
1. Go to <https://open-dev.dingtalk.com> and create a robot application
|
|
692
|
+
2. Under **Credentials**, copy the Client ID (AppKey) and Client Secret (AppSecret)
|
|
693
|
+
3. Under **Robot**, enable the robot and copy the Robot Code
|
|
694
|
+
|
|
695
|
+
```json
|
|
696
|
+
{
|
|
697
|
+
"channels": {
|
|
698
|
+
"dingtalk": {
|
|
699
|
+
"enabled": true,
|
|
700
|
+
"allowFrom": ["*"],
|
|
701
|
+
"clientId": "<AppKey from developer console>",
|
|
702
|
+
"clientSecret": "<AppSecret from developer console>",
|
|
703
|
+
"robotCode": "<Robot Code>"
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
```
|
|
708
|
+
|
|
709
|
+
### Discord
|
|
710
|
+
|
|
711
|
+
Discord connects via the Gateway v10 WebSocket.
|
|
712
|
+
|
|
713
|
+
**How to obtain credentials:**
|
|
714
|
+
|
|
715
|
+
1. Go to <https://discord.com/developers/applications> and create an application
|
|
716
|
+
2. Under **Bot**, click "Add Bot" and copy the bot token
|
|
717
|
+
3. Under **Bot**, enable "Message Content Intent" in Privileged Gateway Intents
|
|
718
|
+
4. Under **OAuth2 > URL Generator**, select `bot` scope with `Send Messages` permission
|
|
719
|
+
5. Use the generated URL to invite the bot to your server
|
|
720
|
+
|
|
721
|
+
```json
|
|
722
|
+
{
|
|
723
|
+
"channels": {
|
|
724
|
+
"discord": {
|
|
725
|
+
"enabled": true,
|
|
726
|
+
"allowFrom": ["*"],
|
|
727
|
+
"botToken": "<your-bot-token>",
|
|
728
|
+
"groupPolicy": "mention"
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
```
|
|
733
|
+
|
|
734
|
+
`groupPolicy` options: `"mention"` (respond only when @mentioned), `"open"` (respond to all messages).
|
|
735
|
+
|
|
736
|
+
### Matrix
|
|
737
|
+
|
|
738
|
+
Matrix uses the CS API v3 long-poll `/sync` endpoint.
|
|
739
|
+
|
|
740
|
+
**How to obtain credentials:**
|
|
741
|
+
|
|
742
|
+
1. Create a bot account on your Matrix homeserver
|
|
743
|
+
2. Obtain an access token (e.g. via Element: Settings > Help & About > Access Token)
|
|
744
|
+
3. Note the full user ID (e.g. `@bot:example.com`)
|
|
745
|
+
4. Invite the bot to the rooms where it should respond
|
|
746
|
+
|
|
747
|
+
```json
|
|
748
|
+
{
|
|
749
|
+
"channels": {
|
|
750
|
+
"matrix": {
|
|
751
|
+
"enabled": true,
|
|
752
|
+
"allowFrom": ["*"],
|
|
753
|
+
"homeserverUrl": "https://matrix.example.com",
|
|
754
|
+
"accessToken": "<your-access-token>",
|
|
755
|
+
"userId": "@bot:example.com"
|
|
756
|
+
}
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
```
|
|
760
|
+
|
|
761
|
+
Note: End-to-end encrypted rooms (`m.room.encrypted`) are not supported; the bot will skip encrypted messages.
|
|
762
|
+
|
|
763
|
+
### WhatsApp
|
|
764
|
+
|
|
765
|
+
WhatsApp connects to a Node.js Baileys bridge via WebSocket.
|
|
766
|
+
|
|
767
|
+
**Setup steps:**
|
|
768
|
+
|
|
769
|
+
1. Install Node.js v18+
|
|
770
|
+
2. Clone the Baileys bridge: `git clone https://github.com/nicepkg/whatsapp-bridge`
|
|
771
|
+
3. `cd whatsapp-bridge && npm install && npm start`
|
|
772
|
+
4. Scan the QR code displayed in the bridge terminal with WhatsApp
|
|
773
|
+
5. The bridge saves auth state — subsequent starts reconnect automatically
|
|
774
|
+
|
|
775
|
+
Run `xbot channels login whatsapp` for step-by-step guidance.
|
|
776
|
+
|
|
777
|
+
```json
|
|
778
|
+
{
|
|
779
|
+
"channels": {
|
|
780
|
+
"whatsapp": {
|
|
781
|
+
"enabled": true,
|
|
782
|
+
"allowFrom": ["*"],
|
|
783
|
+
"bridgeUrl": "ws://localhost:3001",
|
|
784
|
+
"bridgeToken": "",
|
|
785
|
+
"groupPolicy": "open"
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
```
|
|
790
|
+
|
|
791
|
+
The bridge must be running before `xbot run`. Set `bridgeToken` if your bridge instance requires authentication.
|
|
792
|
+
|
|
793
|
+
### QQ
|
|
794
|
+
|
|
795
|
+
QQ uses the QQ Bot API with WebSocket gateway.
|
|
796
|
+
|
|
797
|
+
**How to obtain credentials:**
|
|
798
|
+
|
|
799
|
+
1. Go to <https://q.qq.com> and register as a QQ Bot developer
|
|
800
|
+
2. Create a bot application and obtain the App ID and Secret
|
|
801
|
+
3. Configure the bot's intents and permissions in the developer console
|
|
802
|
+
|
|
803
|
+
```json
|
|
804
|
+
{
|
|
805
|
+
"channels": {
|
|
806
|
+
"qq": {
|
|
807
|
+
"enabled": true,
|
|
808
|
+
"allowFrom": ["*"],
|
|
809
|
+
"appId": "<your-app-id>",
|
|
810
|
+
"secret": "<your-secret>"
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
```
|
|
815
|
+
|
|
816
|
+
### WeCom
|
|
817
|
+
|
|
818
|
+
WeCom (Enterprise WeChat) uses the AI Bot WebSocket protocol.
|
|
819
|
+
|
|
820
|
+
**How to obtain credentials:**
|
|
821
|
+
|
|
822
|
+
1. Log in to <https://work.weixin.qq.com> admin console
|
|
823
|
+
2. Create a self-built application under **App Management**
|
|
824
|
+
3. Note the Corp ID (from **My Enterprise**), Agent ID, and Secret
|
|
825
|
+
|
|
826
|
+
```json
|
|
827
|
+
{
|
|
828
|
+
"channels": {
|
|
829
|
+
"wecom": {
|
|
830
|
+
"enabled": true,
|
|
831
|
+
"allowFrom": ["*"],
|
|
832
|
+
"corpId": "<your-corp-id>",
|
|
833
|
+
"agentId": "<your-agent-id>",
|
|
834
|
+
"secret": "<your-secret>"
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
```
|
|
839
|
+
|
|
840
|
+
All three fields (`corpId`, `agentId`, `secret`) are required — `agentId`/`secret` for WebSocket auth, `corpId` for outbound message delivery.
|
|
841
|
+
|
|
842
|
+
### Weixin
|
|
843
|
+
|
|
844
|
+
Weixin (personal WeChat) uses HTTP long-poll with QR code login via the ilinkai API.
|
|
845
|
+
|
|
846
|
+
**Login flow:**
|
|
847
|
+
|
|
848
|
+
1. Enable the channel in config (no token needed initially)
|
|
849
|
+
2. Run `xbot channels login weixin` — a QR code URL will be printed
|
|
850
|
+
3. Open the URL in WeChat and scan to authorize
|
|
851
|
+
4. The token is saved to `<stateDir>/account.json` for future sessions
|
|
852
|
+
|
|
853
|
+
Alternatively, run `xbot run` and the QR login starts automatically if no saved token is found.
|
|
854
|
+
|
|
855
|
+
```json
|
|
856
|
+
{
|
|
857
|
+
"channels": {
|
|
858
|
+
"weixin": {
|
|
859
|
+
"enabled": true,
|
|
860
|
+
"allowFrom": ["*"]
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
```
|
|
865
|
+
|
|
866
|
+
### Mochat
|
|
867
|
+
|
|
868
|
+
Mochat connects to a Mochat/OpenClaw instance via HTTP polling.
|
|
869
|
+
|
|
870
|
+
**How to obtain credentials:**
|
|
871
|
+
|
|
872
|
+
1. Obtain a Claw Token from your Mochat or OpenClaw instance admin
|
|
873
|
+
2. Note the session IDs and/or panel IDs you want the bot to monitor
|
|
874
|
+
|
|
875
|
+
```json
|
|
876
|
+
{
|
|
877
|
+
"channels": {
|
|
878
|
+
"mochat": {
|
|
879
|
+
"enabled": true,
|
|
880
|
+
"allowFrom": ["*"],
|
|
881
|
+
"baseUrl": "https://your-instance.com",
|
|
882
|
+
"clawToken": "<your-token>",
|
|
883
|
+
"sessions": ["session-id-1"],
|
|
884
|
+
"panels": []
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
```
|
|
889
|
+
|
|
890
|
+
## 12. Additional Provider Configuration
|
|
891
|
+
|
|
892
|
+
### Anthropic
|
|
893
|
+
|
|
894
|
+
Anthropic is supported natively with the Messages API:
|
|
895
|
+
|
|
896
|
+
```json
|
|
897
|
+
{
|
|
898
|
+
"agents": {
|
|
899
|
+
"defaults": {
|
|
900
|
+
"model": "anthropic/claude-sonnet-4-20250514",
|
|
901
|
+
"provider": "anthropic"
|
|
902
|
+
}
|
|
903
|
+
},
|
|
904
|
+
"providers": {
|
|
905
|
+
"anthropic": {
|
|
906
|
+
"apiKey": "sk-ant-..."
|
|
907
|
+
}
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
```
|
|
911
|
+
|
|
912
|
+
Optional `reasoningEffort` can be set to control extended thinking behavior.
|
|
913
|
+
|
|
914
|
+
### GitHub Copilot
|
|
915
|
+
|
|
916
|
+
GitHub Copilot is an OAuth provider and does not require an API key:
|
|
917
|
+
|
|
918
|
+
```json
|
|
919
|
+
{
|
|
920
|
+
"agents": {
|
|
921
|
+
"defaults": {
|
|
922
|
+
"model": "github_copilot/gpt-4o",
|
|
923
|
+
"provider": "github_copilot"
|
|
924
|
+
}
|
|
925
|
+
},
|
|
926
|
+
"providers": {
|
|
927
|
+
"github_copilot": {}
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
```
|
|
931
|
+
|
|
932
|
+
### Cursor
|
|
933
|
+
|
|
934
|
+
Cursor requires an explicit `apiBase`:
|
|
935
|
+
|
|
936
|
+
```json
|
|
937
|
+
{
|
|
938
|
+
"agents": {
|
|
939
|
+
"defaults": {
|
|
940
|
+
"model": "cursor/gpt-4o",
|
|
941
|
+
"provider": "cursor"
|
|
942
|
+
}
|
|
943
|
+
},
|
|
944
|
+
"providers": {
|
|
945
|
+
"cursor": {
|
|
946
|
+
"apiKey": "your-key",
|
|
947
|
+
"apiBase": "https://your-cursor-api-base"
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
```
|
|
952
|
+
|
|
953
|
+
## 13. Concurrency Configuration
|
|
954
|
+
|
|
955
|
+
Control how many inbound messages are processed concurrently:
|
|
956
|
+
|
|
957
|
+
```json
|
|
958
|
+
{
|
|
959
|
+
"agents": {
|
|
960
|
+
"defaults": {
|
|
961
|
+
"maxConcurrentRequests": 3
|
|
962
|
+
}
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
```
|
|
966
|
+
|
|
967
|
+
Messages for the same session are always serialized regardless of this setting.
|
|
968
|
+
|
|
969
|
+
## 14. Channel Delivery Configuration
|
|
970
|
+
|
|
971
|
+
Configure outbound delivery behavior:
|
|
972
|
+
|
|
973
|
+
```json
|
|
974
|
+
{
|
|
975
|
+
"channels": {
|
|
976
|
+
"sendProgress": true,
|
|
977
|
+
"sendToolHints": false,
|
|
978
|
+
"sendMaxRetries": 3
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
```
|
|
982
|
+
|
|
983
|
+
- `sendMaxRetries`: number of delivery attempts with exponential backoff (1s, 2s, 4s...) before giving up.
|
|
984
|
+
|
|
985
|
+
## 15. Current Scope
|
|
986
|
+
|
|
987
|
+
The supported production channel set in this repository is:
|
|
988
|
+
|
|
989
|
+
- `email`
|
|
990
|
+
- `slack`
|
|
991
|
+
- `telegram`
|
|
992
|
+
- `feishu`
|
|
993
|
+
- `dingtalk`
|
|
994
|
+
- `discord`
|
|
995
|
+
- `matrix`
|
|
996
|
+
- `whatsapp`
|
|
997
|
+
- `qq`
|
|
998
|
+
- `wecom`
|
|
999
|
+
- `weixin`
|
|
1000
|
+
- `mochat`
|
|
1001
|
+
|
|
1002
|
+
The runtime is designed so additional providers and transports can be added behind the same trait boundaries without changing the agent loop.
|