openclaw-quiubo 2.6.28 → 2.6.31

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,95 +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
- ### Step 1: Add the agent
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
- In `~/.openclaw/openclaw.json`:
153
+ All agents share one SDK API key (and its quota). Each gets fully isolated conversations, cursors, and session keys.
151
154
 
152
- ```json
153
- {
154
- "agents": {
155
- "list": [
156
- { "id": "main" },
157
- {
158
- "id": "project-manager",
159
- "model": "anthropic/claude-sonnet-4-5",
160
- "workspace": "~/.openclaw/workspace-project-manager"
161
- }
162
- ]
163
- }
164
- }
165
- ```
166
-
167
- ### Step 2: Add a Quiubo account for the agent
168
-
169
- Each account needs its own bot identity (can share the same API key):
170
-
171
- ```json
172
- {
173
- "plugins": {
174
- "quiubo": {
175
- "accounts": {
176
- "default": {
177
- "sdkApiKey": "qub_...",
178
- "botIdentityId": "<main-bot-uuid>"
179
- },
180
- "pm": {
181
- "sdkApiKey": "qub_...",
182
- "botIdentityId": "<pm-bot-uuid>"
183
- }
184
- }
185
- }
186
- }
187
- }
188
- ```
189
-
190
- ### Step 3: Bind accounts to agents
191
-
192
- ```json
193
- {
194
- "bindings": [
195
- {
196
- "match": { "channel": "quiubo", "accountId": "default" },
197
- "agentId": "main"
198
- },
199
- {
200
- "match": { "channel": "quiubo", "accountId": "pm" },
201
- "agentId": "project-manager"
202
- }
203
- ]
204
- }
205
- ```
206
-
207
- Without bindings, all messages route to the first agent.
208
-
209
- ### Step 4: Create the agent's workspace
210
-
211
- ```bash
212
- mkdir -p ~/.openclaw/workspace-project-manager/memory
213
- ```
214
-
215
- Seed it with: `SOUL.md`, `AGENTS.md`, `USER.md`, `IDENTITY.md`, `MEMORY.md`.
216
-
217
- ### Step 5: Restart
218
-
219
- ```bash
220
- openclaw gateway restart
221
- ```
222
-
223
- ### How routing works
224
-
225
- ```
226
- Quiubo Chat (You + Main Bot) → account: default → binding → agent: main
227
- Quiubo Chat (You + PM Bot) → account: pm → binding → agent: project-manager
228
- ```
229
-
230
- - **Messages**: AccountId resolves the agent via bindings
231
- - **Cron jobs**: Filtered by agentId — each agent's chat shows only its own
232
- - **Sessions**: Isolated session namespaces per agent, no cross-talk
233
- - **Workspaces**: Fully isolated — agents can't see each other's files
234
- - **Cursors**: Each account has its own cursor file — no clobbering
155
+ **[Full guide](./MULTI_AGENT.md)** — architecture, config examples, cron setup, and troubleshooting.
235
156
 
236
157
  ## Markdown Attachments
237
158
 
@@ -239,7 +160,7 @@ Agents can send `.md` file attachments alongside messages. Attachments appear as
239
160
 
240
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.
241
162
 
242
- **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.
243
164
 
244
165
  Add this to your agent's `AGENTS.md`:
245
166
 
@@ -256,20 +177,19 @@ Example response:
256
177
  MEDIA: /tmp/daily-report.md
257
178
 
258
179
  The file will be delivered as a tappable attachment card in the chat.
259
- Only `.md` files are supported. Files over 1MB are skipped.
180
+ Supported: `.md` (max 1MB) and images `.jpg`/`.png`/`.webp` (max 5MB).
260
181
  ```
261
182
 
262
183
  ## Operational Notes
263
184
 
264
- ### Cursor files
265
-
266
- Cursors are persisted at:
185
+ ### Per-account state files
267
186
 
268
- ```
269
- ~/.openclaw/cron/quiubo-cursors-{accountId}.json
270
- ```
187
+ Each account persists its own state files under `~/.openclaw/cron/`:
271
188
 
272
- 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 |
273
193
 
274
194
  ### Heartbeat
275
195
 
@@ -283,7 +203,7 @@ A typing indicator is sent immediately when processing begins, then repeated eve
283
203
 
284
204
  ```bash
285
205
  openclaw channels disable --channel quiubo # Disable
286
- openclaw channels add --channel quiubo # Re-configure
206
+ openclaw channels add # Re-configure
287
207
  ```
288
208
 
289
209
  ## Development