openclaw-quiubo 2.6.29 → 2.6.32

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/MULTI_AGENT.md ADDED
@@ -0,0 +1,281 @@
1
+ # Multi-Agent Setup
2
+
3
+ One gateway. Multiple agents. Each with its own chat, model, workspace, and schedule — completely isolated from each other.
4
+
5
+ ## What You Get
6
+
7
+ - **Own chat** — separate Quiubo identity and conversation thread
8
+ - **Own model** — Opus for heavy thinking, Haiku for lightweight jobs
9
+ - **Own workspace** — files, memory, history are private
10
+ - **Own schedule** — cron jobs scoped per agent
11
+ - **One key** — all agents share your SDK API key (and its quota — see [API Key Quota](#api-key-quota))
12
+
13
+ ## Example
14
+
15
+ **Bob** is your personal assistant (Opus, handles research and writing).
16
+ **Sam** is your project manager (Sonnet, runs standups and tracks tasks).
17
+
18
+ Both appear as separate chats in Quiubo — independent conversations, independent workspaces.
19
+
20
+ ## Setup
21
+
22
+ ### 1. Add a bot identity
23
+
24
+ Run the interactive wizard to add a new account:
25
+
26
+ ```bash
27
+ openclaw channels add
28
+ ```
29
+
30
+ The wizard asks for three things:
31
+ - **Account ID** — short name for this agent (e.g. `pm`, `research`). Your first agent uses `default`.
32
+ - **SDK API Key** — reuse your existing `qub_...` key.
33
+ - **Bot identity** — choose "Create new bot identity" to give this agent its own name in Quiubo.
34
+
35
+ ### 2. Register the agent
36
+
37
+ Add an entry to `agents.list` in `~/.openclaw/openclaw.json`. Give it a unique ID and its own workspace path:
38
+
39
+ ```json
40
+ {
41
+ "agents": {
42
+ "defaults": {
43
+ "workspace": "~/.openclaw/workspace"
44
+ },
45
+ "list": [
46
+ {
47
+ "id": "main",
48
+ "subagents": { "allowAgents": ["*"] }
49
+ },
50
+ {
51
+ "id": "project-manager",
52
+ "name": "Sam",
53
+ "model": "anthropic/claude-sonnet-4-5",
54
+ "workspace": "~/.openclaw/workspace-project-manager",
55
+ "agentDir": "~/.openclaw/agents/project-manager/agent",
56
+ "subagents": { "allowAgents": ["*"] }
57
+ }
58
+ ]
59
+ }
60
+ }
61
+ ```
62
+
63
+ The `main` agent inherits `workspace` from `agents.defaults`. Non-main agents override it with their own path.
64
+
65
+ - **`workspace`** — the agent's working directory (files it creates, edits, and reads during tasks).
66
+ - **`agentDir`** — the agent's identity/state directory (`IDENTITY.md`, `SOUL.md`, `AGENTS.md`, memory). Optional — defaults to a path under `~/.openclaw/agents/{id}/agent`. Set it explicitly if you want control over where identity files live.
67
+
68
+ ### 3. Bind account to agent
69
+
70
+ Tell OpenClaw which Quiubo account maps to which agent using the `bindings` array:
71
+
72
+ ```json
73
+ {
74
+ "bindings": [
75
+ {
76
+ "agentId": "main",
77
+ "match": {
78
+ "channel": "quiubo",
79
+ "accountId": "default"
80
+ }
81
+ },
82
+ {
83
+ "agentId": "project-manager",
84
+ "match": {
85
+ "channel": "quiubo",
86
+ "accountId": "pm"
87
+ }
88
+ }
89
+ ]
90
+ }
91
+ ```
92
+
93
+ *Without bindings, all messages route to the first agent in the list.*
94
+
95
+ ### 4. Create the workspace
96
+
97
+ ```bash
98
+ mkdir -p ~/.openclaw/workspace-project-manager
99
+ mkdir -p ~/.openclaw/agents/project-manager/agent/memory
100
+ ```
101
+
102
+ Seed the agent dir with identity files: `SOUL.md`, `AGENTS.md`, `USER.md`, `IDENTITY.md`, `MEMORY.md`.
103
+
104
+ To help the agent understand the multi-agent setup, add this to its `AGENTS.md`:
105
+
106
+ ```markdown
107
+ ## Multi-Agent Architecture
108
+ This agent runs as part of a multi-agent OpenClaw gateway.
109
+ Each agent has its own chat, workspace, and cron jobs.
110
+ ```
111
+
112
+ > **Note:** If you use auth profiles (e.g. GitHub tokens), each agent workspace needs its own `config.json` or shared auth config.
113
+
114
+ ### 5. Restart
115
+
116
+ ```bash
117
+ openclaw gateway restart
118
+ ```
119
+
120
+ The new agent gets its own welcome chat automatically.
121
+
122
+ ## Config Integrity Warning
123
+
124
+ Your config will have account data in **two** places:
125
+
126
+ | Location | Who writes it | Who reads it |
127
+ |----------|---------------|--------------|
128
+ | `channels.quiubo.accounts` | `openclaw channels add` wizard | **The plugin** (source of truth) |
129
+ | `plugins.entries.openclaw-quiubo.config.accounts` | OpenClaw core (mirrors plugin config) | OpenClaw core |
130
+
131
+ The plugin reads **only** from `channels.quiubo.accounts`. If that section is missing or empty, the plugin silently does nothing — no `[quiubo]` logs, no errors, just gone.
132
+
133
+ > **The #1 footgun:** an agent running `config.patch` that omits `channels` will wipe `channels.quiubo.accounts` entirely. The plugin dies on the next restart while everything else looks fine.
134
+ >
135
+ > **Rule of thumb:** never do a full config write/patch that doesn't preserve `channels`. Always merge rather than replace.
136
+
137
+ ## API Key Quota
138
+
139
+ All accounts sharing the same `qub_...` API key share its monthly request quota. If one agent is chatty enough to exhaust the limit, **all** agents using that key stop working on the next restart.
140
+
141
+ Options:
142
+ - **One key, shared quota** — simpler setup, fine for low-traffic agents.
143
+ - **Separate keys per account** — independent quotas, each agent can hit its own ceiling without affecting others.
144
+
145
+ ## How It Works
146
+
147
+ ```
148
+ ┌─────────────────────────┐
149
+ │ OpenClaw Gateway │
150
+ └────────┬────────────────┘
151
+
152
+ ┌──────────────┼──────────────┐
153
+ ▼ ▼ ▼
154
+ account:default account:pm account:research
155
+ │ │ │
156
+ ┌────┴────┐ ┌────┴────┐ ┌────┴────┐
157
+ │ gateway │ │ gateway │ │ gateway │
158
+ │ client │ │ client │ │ client │
159
+ │ logger │ │ logger │ │ logger │
160
+ │ cursor │ │ cursor │ │ cursor │
161
+ └────┬────┘ └────┬────┘ └────┬────┘
162
+ │ │ │
163
+ binding ──→ binding ──→ binding ──→
164
+ agent:main agent:pm agent:research
165
+ ```
166
+
167
+ **Isolation boundaries:**
168
+
169
+ - **Per-account Maps** — each account gets its own gateway, API client, config, and logger.
170
+ - **Per-account cursors** — `~/.openclaw/cron/quiubo-cursors-{accountId}.json` — no clobbering between agents.
171
+ - **Per-account E2EE keys** — `~/.openclaw/cron/quiubo-keys-{accountId}.json` — each account's key seed. If lost, the agent re-enrolls its keys (may break E2EE for existing conversations).
172
+ - **Session keys** — main agent uses `quiubo:{groupId}`, others use `agent:{agentId}:quiubo:{groupId}` — conversations never cross.
173
+ - **Cron jobs** — filtered by `agentId` in `getActivityData()` — each agent's chat shows only its own scheduled jobs.
174
+ - **Auto-provisioning** — each new account gets a welcome `agent_channel` group with `externalGroupId: auto-{accountId}`.
175
+ - **Auto-registration** — on first startup, each account auto-registers an agent record in the Quiubo directory if none exists for its bot identity.
176
+
177
+ **Agent resolution** (`resolveAgentId`): searches `bindings[]` for matching channel + accountId. Falls back to first agent in `agents.list`, then to `"main"`.
178
+
179
+ ## Cron Jobs
180
+
181
+ Cron jobs are scoped per agent via the `agentId` field:
182
+
183
+ ```json
184
+ {
185
+ "jobs": [
186
+ {
187
+ "id": "daily-standup",
188
+ "agentId": "project-manager",
189
+ "schedule": "0 9 * * 1-5",
190
+ "enabled": true,
191
+ "delivery": {
192
+ "channel": "quiubo",
193
+ "to": "<group-uuid>"
194
+ }
195
+ }
196
+ ]
197
+ }
198
+ ```
199
+
200
+ - **`agentId`**: Ensures only the "project-manager" agent sees/runs this job. **Required** — jobs without `agentId` are invisible to all agents.
201
+ - **`delivery.channel`**: Must be `"quiubo"`.
202
+ - **`delivery.to`**: The raw group UUID (e.g. `eec8a4ce-d08d-483a-ba5d-90a43ce8f521`). Find it in the agent's welcome chat or via the API.
203
+
204
+ > **Multi-agent caveat:** The fallback resolver (`resolveAnnounceGroupId`) reads cron jobs from disk but does not filter by accountId. If multiple agents have cron jobs, it may resolve to the wrong agent's target group. Keep one cron job per agent, or ensure each agent's delivery target is unambiguous.
205
+
206
+ ## Full Config Reference
207
+
208
+ Quiubo-relevant sections of `openclaw.json` for a 2-agent setup:
209
+
210
+ ```json
211
+ {
212
+ "agents": {
213
+ "defaults": {
214
+ "workspace": "~/.openclaw/workspace"
215
+ },
216
+ "list": [
217
+ {
218
+ "id": "main",
219
+ "subagents": { "allowAgents": ["*"] }
220
+ },
221
+ {
222
+ "id": "project-manager",
223
+ "name": "Sam",
224
+ "model": "anthropic/claude-sonnet-4-5",
225
+ "workspace": "~/.openclaw/workspace-project-manager",
226
+ "agentDir": "~/.openclaw/agents/project-manager/agent",
227
+ "subagents": { "allowAgents": ["*"] }
228
+ }
229
+ ]
230
+ },
231
+ "bindings": [
232
+ {
233
+ "agentId": "main",
234
+ "match": {
235
+ "channel": "quiubo",
236
+ "accountId": "default"
237
+ }
238
+ },
239
+ {
240
+ "agentId": "project-manager",
241
+ "match": {
242
+ "channel": "quiubo",
243
+ "accountId": "pm"
244
+ }
245
+ }
246
+ ],
247
+ "channels": {
248
+ "quiubo": {
249
+ "accounts": {
250
+ "default": {
251
+ "enabled": true,
252
+ "apiKey": "qub_your_key_here",
253
+ "botIdentityId": "<main-bot-uuid>",
254
+ "apiUrl": "https://api.quiubo.io"
255
+ },
256
+ "pm": {
257
+ "enabled": true,
258
+ "apiKey": "qub_your_key_here",
259
+ "botIdentityId": "<pm-bot-uuid>",
260
+ "apiUrl": "https://api.quiubo.io"
261
+ }
262
+ }
263
+ }
264
+ }
265
+ }
266
+ ```
267
+
268
+ > **Note:** OpenClaw also mirrors account data into `plugins.entries.openclaw-quiubo.config.accounts`. The plugin ignores that copy — `channels.quiubo.accounts` is the only location that matters. See [Config Integrity Warning](#config-integrity-warning).
269
+
270
+ ## Troubleshooting
271
+
272
+ | Symptom | Fix |
273
+ |---------|-----|
274
+ | Plugin silently stops — no `[quiubo]` logs on startup | `channels.quiubo.accounts` is missing from config. An agent's `config.patch` likely wiped it. Restore the `channels` block and restart. |
275
+ | Second agent doesn't respond | Check `bindings[]` — accountId must match exactly. Run `openclaw gateway restart`. |
276
+ | Both agents reply to the same message | Missing or duplicate bindings. Each accountId needs exactly one binding. |
277
+ | Agent dies on restart, others work fine | Check logs for `[FATAL] STARTUP FAILED`. Common causes: invalid/expired API key (401), permission error (403), or quota exhausted. Rotate the key or check usage. |
278
+ | Cron job runs in wrong chat | Verify `agentId` on the job matches the target agent, and `delivery.to` uses the correct group UUID. |
279
+ | "welcome group already exists" on restart | Normal — auto-provisioning is safe. The existing group is reused. |
280
+ | Agent shows other agent's cron jobs | The `agentId` on the job doesn't match. Double-check spelling. |
281
+ | Cron job never runs / missing from activity | Missing `agentId` field on the job. Untagged jobs are invisible to all agents — the filter requires an exact match. |
package/README.md CHANGED
@@ -17,7 +17,7 @@ openclaw plugins update openclaw-quiubo
17
17
  ## Setup
18
18
 
19
19
  ```bash
20
- openclaw channels add --channel quiubo
20
+ openclaw channels add
21
21
  ```
22
22
 
23
23
  The interactive wizard will:
@@ -58,7 +58,7 @@ channels:
58
58
 
59
59
  ### Multiple accounts
60
60
 
61
- Run the setup wizard again and enter a different Account ID when prompted (e.g., `support-bot`, `sales-bot`). Each account gets its own gateway instance, cursor file, and bot config cache.
61
+ Run the setup wizard again and enter a different Account ID when prompted (e.g., `support-bot`, `sales-bot`). Each account gets its own gateway instance, cursor file, and bot config cache. For full multi-agent isolation (separate workspaces, models, cron jobs), see the **[Multi-Agent Setup guide](./MULTI_AGENT.md)**.
62
62
 
63
63
  ## Architecture
64
64
 
@@ -98,7 +98,7 @@ Four layers prevent old messages from being reprocessed on restart:
98
98
 
99
99
  The plugin supports Quiubo's E2EE protocol for groups that require it:
100
100
 
101
- - **Key generation**: Deterministic Ed25519 + X25519 keypairs derived from a 32-byte seed (persisted in config)
101
+ - **Key generation**: Deterministic Ed25519 + X25519 keypairs derived from a 32-byte seed (persisted to `~/.openclaw/cron/quiubo-keys-{accountId}.json`)
102
102
  - **Auto-enrollment**: On first startup, generates keypair and enrolls via challenge-response (`requestKeyChallenge` > `signChallenge` > `verifyKeyChallenge`)
103
103
  - **Inbound decryption**: GroupEnvelopeV2 messages decrypted using XChaCha20-Poly1305 with epoch keys
104
104
  - **Outbound encryption**: Plaintext encrypted before sending when E2EE is granted for the group
@@ -143,125 +143,16 @@ On first gateway startup, if the bot has no groups, the plugin automatically cre
143
143
 
144
144
  ## Multi-Agent Setup
145
145
 
146
- Run multiple AI agents on a single OpenClaw gateway — each with their own Quiubo chat, workspace, model, and cron jobs.
146
+ Run multiple agents on a single gateway — each with its own chat, model, workspace, and cron jobs.
147
147
 
148
- Each agent needs two things: a **bot identity** in Quiubo (so it has its own chat presence) and an **agent entry** in OpenClaw (so it has its own workspace and model). They can share the same SDK API key.
148
+ 1. `openclaw channels add` create a new bot identity
149
+ 2. Add the agent and binding to `~/.openclaw/openclaw.json`
150
+ 3. Create the agent's workspace
151
+ 4. `openclaw gateway restart`
149
152
 
150
- ### Step 1: Create a bot identity in Quiubo
153
+ All agents share one SDK API key (and its quota). Each gets fully isolated conversations, cursors, and session keys.
151
154
 
152
- Each agent needs its own bot identity. You create one by running the setup wizard with a new account ID:
153
-
154
- ```bash
155
- openclaw channels add --channel quiubo
156
- ```
157
-
158
- The wizard will:
159
-
160
- 1. Ask for an **Account ID** — enter a short name for this agent (e.g. `pm`, `support`, `research`). Your first/default agent uses `default`.
161
- 2. Ask for your **SDK API Key** — you can reuse the same `qub_...` key across all agents.
162
- 3. **Create or select a bot identity** — choose "Create new bot identity" to give this agent its own username and display name in Quiubo.
163
-
164
- > **Where to get an SDK API Key:** In the Quiubo app, go to **Settings > Developer > API Keys**. One key works for all agents under the same app.
165
-
166
- After the wizard completes, the new account is saved to `~/.openclaw/openclaw.json` automatically:
167
-
168
- ```json
169
- {
170
- "plugins": {
171
- "quiubo": {
172
- "accounts": {
173
- "default": {
174
- "apiKey": "qub_...",
175
- "botIdentityId": "<main-bot-uuid>"
176
- },
177
- "pm": {
178
- "apiKey": "qub_...",
179
- "botIdentityId": "<pm-bot-uuid>"
180
- }
181
- }
182
- }
183
- }
184
- }
185
- ```
186
-
187
- ### Step 2: Add the agent to OpenClaw
188
-
189
- In `~/.openclaw/openclaw.json`, add an entry to the agents list:
190
-
191
- ```json
192
- {
193
- "agents": {
194
- "list": [
195
- { "id": "main" },
196
- {
197
- "id": "project-manager",
198
- "model": "anthropic/claude-sonnet-4-5",
199
- "workspace": "~/.openclaw/workspace-project-manager"
200
- }
201
- ]
202
- }
203
- }
204
- ```
205
-
206
- Each agent can have its own model, workspace, and system prompt.
207
-
208
- ### Step 3: Bind the Quiubo account to the agent
209
-
210
- Tell OpenClaw which Quiubo account maps to which agent:
211
-
212
- ```json
213
- {
214
- "bindings": [
215
- {
216
- "match": { "channel": "quiubo", "accountId": "default" },
217
- "agentId": "main"
218
- },
219
- {
220
- "match": { "channel": "quiubo", "accountId": "pm" },
221
- "agentId": "project-manager"
222
- }
223
- ]
224
- }
225
- ```
226
-
227
- Without bindings, all messages route to the first agent.
228
-
229
- ### Step 4: Create the agent's workspace
230
-
231
- ```bash
232
- mkdir -p ~/.openclaw/workspace-project-manager/memory
233
- ```
234
-
235
- Seed it with: `SOUL.md`, `AGENTS.md`, `USER.md`, `IDENTITY.md`, `MEMORY.md`.
236
-
237
- ### Step 5: Restart
238
-
239
- ```bash
240
- openclaw gateway restart
241
- ```
242
-
243
- ### How routing works
244
-
245
- ```
246
- Quiubo Chat (You + Main Bot) → account: default → binding → agent: main
247
- Quiubo Chat (You + PM Bot) → account: pm → binding → agent: project-manager
248
- ```
249
-
250
- - **Messages**: AccountId resolves the agent via bindings
251
- - **Cron jobs**: Filtered by agentId — each agent's chat shows only its own
252
- - **Sessions**: Isolated session namespaces per agent, no cross-talk
253
- - **Workspaces**: Fully isolated — agents can't see each other's files
254
- - **Cursors**: Each account has its own cursor file — no clobbering
255
-
256
- ### Adding more agents
257
-
258
- Repeat steps 1–5 for each new agent. The key command is:
259
-
260
- ```bash
261
- openclaw channels add --channel quiubo
262
- ```
263
-
264
- Enter a unique Account ID each time (e.g. `support`, `research`). The wizard handles identity creation and config — then add the agent, binding, and workspace as shown above.
155
+ **[Full guide](./MULTI_AGENT.md)** architecture, config examples, cron setup, and troubleshooting.
265
156
 
266
157
  ## Markdown Attachments
267
158
 
@@ -269,7 +160,7 @@ Agents can send `.md` file attachments alongside messages. Attachments appear as
269
160
 
270
161
  OpenClaw's `MEDIA:` token protocol is used: when an agent writes a file and includes `MEDIA: /path/to/file.md` in its response, the plugin reads the file and sends it as a structured attachment.
271
162
 
272
- **Supported:** `.md` files only, max 1MB each. Source tracking distinguishes `agent` vs `subagent` attachments.
163
+ **Supported:** `.md` files (max 1MB) and images — `.jpg`, `.jpeg`, `.png`, `.webp` (max 5MB, uploaded via S3 presign). Source tracking distinguishes `agent` vs `subagent` attachments.
273
164
 
274
165
  Add this to your agent's `AGENTS.md`:
275
166
 
@@ -286,20 +177,19 @@ Example response:
286
177
  MEDIA: /tmp/daily-report.md
287
178
 
288
179
  The file will be delivered as a tappable attachment card in the chat.
289
- Only `.md` files are supported. Files over 1MB are skipped.
180
+ Supported: `.md` (max 1MB) and images `.jpg`/`.png`/`.webp` (max 5MB).
290
181
  ```
291
182
 
292
183
  ## Operational Notes
293
184
 
294
- ### Cursor files
185
+ ### Per-account state files
295
186
 
296
- Cursors are persisted at:
297
-
298
- ```
299
- ~/.openclaw/cron/quiubo-cursors-{accountId}.json
300
- ```
187
+ Each account persists its own state files under `~/.openclaw/cron/`:
301
188
 
302
- Each account writes to its own file to avoid clobbering in multi-account setups. Safe to delete — the gateway will `seekToLatest()` on next start (no replay).
189
+ | File | Purpose | Safe to delete? |
190
+ |------|---------|-----------------|
191
+ | `quiubo-cursors-{accountId}.json` | Message cursor positions | Yes — gateway will `seekToLatest()` on next start (no replay) |
192
+ | `quiubo-keys-{accountId}.json` | E2EE key seed (32 bytes) | **No** — deleting forces re-enrollment, may break E2EE for existing conversations |
303
193
 
304
194
  ### Heartbeat
305
195
 
@@ -313,7 +203,7 @@ A typing indicator is sent immediately when processing begins, then repeated eve
313
203
 
314
204
  ```bash
315
205
  openclaw channels disable --channel quiubo # Disable
316
- openclaw channels add --channel quiubo # Re-configure
206
+ openclaw channels add # Re-configure
317
207
  ```
318
208
 
319
209
  ## Development