@mutirolabs/openclaw-brain 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/CHANGELOG.md +50 -0
- package/LICENSE +15 -0
- package/README.md +266 -0
- package/docs/guides/manage-allowlist.md +184 -0
- package/docs/guides/use-openclaw-as-brain.md +401 -0
- package/index.ts +21 -0
- package/openclaw.plugin.json +47 -0
- package/package.json +79 -0
- package/src/actions.ts +53 -0
- package/src/agent-tools.ts +640 -0
- package/src/bridge-client.ts +236 -0
- package/src/bridge-messages.ts +307 -0
- package/src/bridge-protocol.ts +77 -0
- package/src/bridge-session.ts +433 -0
- package/src/channel.runtime.ts +454 -0
- package/src/channel.ts +130 -0
- package/src/config.ts +100 -0
- package/src/inbound.ts +151 -0
- package/src/live-snapshot.ts +210 -0
- package/src/outbound.ts +326 -0
- package/src/setup-surface.ts +281 -0
- package/src/signal-forwarder.ts +153 -0
|
@@ -0,0 +1,401 @@
|
|
|
1
|
+
# Use OpenClaw as the Brain for Your Mutiro Agent
|
|
2
|
+
|
|
3
|
+
Copy the prompt below into your AI assistant (Claude, Cursor, Windsurf, or similar) and it will walk you through pointing [OpenClaw](https://openclaw.ai) at a [Mutiro](https://mutiro.com) agent through `chatbridge`. Mutiro stays the messaging platform; OpenClaw becomes the brain.
|
|
4
|
+
|
|
5
|
+
## The Prompt
|
|
6
|
+
|
|
7
|
+
````
|
|
8
|
+
You are helping me run an existing Mutiro agent with OpenClaw as its brain over `chatbridge`. Mutiro keeps the agent identity, connectivity, messaging, auth, and media plumbing. OpenClaw becomes the thinking layer and drives outbound replies through the bridge.
|
|
9
|
+
|
|
10
|
+
Walk me through this step by step. Be proactive — run commands, check outputs, and make smart decisions based on what you find. Don't ask me things you can figure out by running a command. Only pause to ask when you genuinely need my input (like which LLM provider to use or what personality I want). When you need my input, ask me directly and wait for my response.
|
|
11
|
+
|
|
12
|
+
**Important:** Both CLIs have extensive built-in help. Use `mutiro --help`, `openclaw --help`, and their `<command> --help` variants. Check the CLI help first rather than guessing.
|
|
13
|
+
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
### Step 1: Make Sure a Mutiro Agent Exists
|
|
17
|
+
|
|
18
|
+
This guide assumes I already have a working Mutiro agent directory. If I don't, stop and point me at the Mutiro create-agent guide first:
|
|
19
|
+
|
|
20
|
+
> https://www.mutiro.com/docs/guides/create-agent.md
|
|
21
|
+
|
|
22
|
+
Check what's already set up:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
mutiro auth whoami
|
|
26
|
+
mutiro agents list
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
If either fails, walk me through that guide first and come back here.
|
|
30
|
+
|
|
31
|
+
Once I have an agent, ask me which one I want to wire into OpenClaw, then confirm the agent directory path. The agent directory is the folder containing `.mutiro-agent.yaml`.
|
|
32
|
+
|
|
33
|
+
Record the absolute path — every later step uses it.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
### Step 2: Stop the Built-in Mutiro Brain
|
|
38
|
+
|
|
39
|
+
**Do not run the built-in Mutiro brain and OpenClaw against the same agent at the same time.** Two brains on one agent will fight over the same conversations.
|
|
40
|
+
|
|
41
|
+
If Mutiro's built-in brain is currently running for that agent, stop it:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
# Inside the agent directory
|
|
45
|
+
cd /path/to/agent-directory
|
|
46
|
+
pkill -f "mutiro agent run" || true
|
|
47
|
+
# Or, if you launched it with `mutiro start`, stop that process.
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Verify nothing is holding the agent:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
mutiro agent doctor
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
### Step 3: Install the OpenClaw CLI
|
|
59
|
+
|
|
60
|
+
Check if it's already installed:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
openclaw --version
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
If not found, install it:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
curl -fsSL https://openclaw.ai/install.sh | bash
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Or, if I already use npm globally:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
npm i -g openclaw@latest
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Verify before continuing:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
openclaw --version
|
|
82
|
+
openclaw doctor
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
### Step 4: Install the openclaw-brain Plugin
|
|
88
|
+
|
|
89
|
+
This plugin is the piece that lets OpenClaw speak Mutiro's `chatbridge`. It spawns `mutiro agent host --mode=bridge` as a subprocess and translates NDJSON envelopes into OpenClaw inbound messages and outbound send/react/forward/voice/card/forward calls.
|
|
90
|
+
|
|
91
|
+
Install from the published package:
|
|
92
|
+
|
|
93
|
+
```bash
|
|
94
|
+
openclaw plugins install --dangerously-force-unsafe-install @mutirolabs/openclaw-brain
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Or clone and install from source while iterating:
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
git clone https://github.com/mutirolabs/openclaw-brain ~/src/openclaw-brain
|
|
101
|
+
cd ~/src/openclaw-brain
|
|
102
|
+
# Skip node_modules — OpenClaw's install scanner walks the source tree and
|
|
103
|
+
# caps at 10k directories. Run `npm install` again later if you want local
|
|
104
|
+
# typecheck.
|
|
105
|
+
openclaw plugins install --dangerously-force-unsafe-install "file:$(pwd)"
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
**About `--dangerously-force-unsafe-install`**: this plugin legitimately
|
|
109
|
+
spawns `mutiro agent host --mode=bridge` as a subprocess — that is the
|
|
110
|
+
entire `chatbridge` adapter. OpenClaw's install scanner correctly flags any
|
|
111
|
+
plugin that uses `child_process` as sensitive and requires this flag as an
|
|
112
|
+
explicit acknowledgement. Before you pass it, confirm you are installing
|
|
113
|
+
from the signed [`mutirolabs/openclaw-brain`](https://github.com/mutirolabs/openclaw-brain)
|
|
114
|
+
source (or the `@mutirolabs/openclaw-brain` npm package). Review the
|
|
115
|
+
`spawn` call at [`src/bridge-client.ts`](https://github.com/mutirolabs/openclaw-brain/blob/main/src/bridge-client.ts)
|
|
116
|
+
if you want to see exactly what the plugin executes.
|
|
117
|
+
|
|
118
|
+
Verify OpenClaw sees the channel:
|
|
119
|
+
|
|
120
|
+
```bash
|
|
121
|
+
openclaw plugins list | grep -i mutiro
|
|
122
|
+
openclaw channels list | grep -i mutiro
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
### Step 5: Point OpenClaw at the Mutiro Agent Directory
|
|
128
|
+
|
|
129
|
+
**Preferred — interactive wizard.** Run the bare `channels add` command (no
|
|
130
|
+
`--channel` flag; passing one skips the wizard and falls through to the
|
|
131
|
+
non-interactive adapter):
|
|
132
|
+
|
|
133
|
+
```bash
|
|
134
|
+
openclaw channels add
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Pick `mutiro` from the list. The wizard detects the `mutiro` CLI, asks for
|
|
138
|
+
the agent directory, validates it, runs `mutiro auth whoami`, and writes the
|
|
139
|
+
config.
|
|
140
|
+
|
|
141
|
+
**Non-interactive alternative.** Use the single-account shorthand if I only
|
|
142
|
+
have one Mutiro agent:
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
openclaw config set channels.mutiro.accounts.default.agentDir /absolute/path/to/agent-directory
|
|
146
|
+
openclaw config set channels.mutiro.enabled true --strict-json
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
For multiple Mutiro agents, use named accounts:
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
openclaw config set channels.mutiro.accounts.coach.agentDir /path/to/coach-agent
|
|
153
|
+
openclaw config set channels.mutiro.accounts.assistant.agentDir /path/to/assistant-agent
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
The plugin will spawn one `mutiro agent host --mode=bridge` process per configured account and keep it alive across conversations.
|
|
157
|
+
|
|
158
|
+
Confirm the config was written:
|
|
159
|
+
|
|
160
|
+
```bash
|
|
161
|
+
openclaw config get channels.mutiro
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
### Step 6: Pick an LLM Provider for OpenClaw
|
|
167
|
+
|
|
168
|
+
OpenClaw runs its own agent with its own system prompt, tools, and provider. The Mutiro `.mutiro-agent.yaml` provider settings are ignored while OpenClaw is the brain — Mutiro is just the messaging surface.
|
|
169
|
+
|
|
170
|
+
Check what provider keys are already in my environment:
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
echo "ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY:+set}" \
|
|
174
|
+
"OPENAI_API_KEY=${OPENAI_API_KEY:+set}" \
|
|
175
|
+
"GEMINI_API_KEY=${GEMINI_API_KEY:+set}" \
|
|
176
|
+
"GOOGLE_API_KEY=${GOOGLE_API_KEY:+set}"
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
If one is set, suggest using that provider. Otherwise ask:
|
|
180
|
+
|
|
181
|
+
| Provider | Best for | Env var |
|
|
182
|
+
|----------|----------|---------|
|
|
183
|
+
| Anthropic Claude | Reasoning, coding, careful tool use | `ANTHROPIC_API_KEY` |
|
|
184
|
+
| OpenAI | GPT models, broad ecosystem | `OPENAI_API_KEY` |
|
|
185
|
+
| Google Gemini | Fast, good free tier | `GEMINI_API_KEY` |
|
|
186
|
+
| Ollama | Local/private | (no key) |
|
|
187
|
+
| LM Studio | Local/private, GUI | (no key) |
|
|
188
|
+
|
|
189
|
+
Configure the default model with whatever OpenClaw expects for that provider (check `openclaw models --help`). For example:
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
openclaw models auth login --provider anthropic
|
|
193
|
+
openclaw models set-default anthropic/claude-opus-4-7
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
If the provider requires no auth (Ollama, LM Studio), point OpenClaw at the local endpoint with `openclaw models` commands and skip the login step.
|
|
197
|
+
|
|
198
|
+
---
|
|
199
|
+
|
|
200
|
+
### Step 7: Write the Agent Instructions (OpenClaw Side)
|
|
201
|
+
|
|
202
|
+
OpenClaw's agent is configured through OpenClaw — not through `.mutiro-agent.yaml`. Its system prompt shapes how the brain thinks, what tools it reaches for, and how it speaks back through the bridge.
|
|
203
|
+
|
|
204
|
+
Ask me the same framing questions as a normal agent setup — you can ask them all at once:
|
|
205
|
+
|
|
206
|
+
1. **Role:** What should this agent do? (coach, coding helper, research agent, etc.)
|
|
207
|
+
2. **Personality:** Tone and style in chat.
|
|
208
|
+
3. **Language:** Primary language for conversation.
|
|
209
|
+
4. **Voice:** Should it send voice replies through Mutiro TTS? (if yes, pick a voice — same IDs as the Mutiro create-agent guide: `en-US-Chirp3-HD-Orus`, `en-US-Chirp3-HD-Zephyr`, `pt-BR-Chirp3-HD-Callirrhoe`, etc.)
|
|
210
|
+
|
|
211
|
+
Write the system prompt into the OpenClaw agent's instruction file (check `openclaw agents --help` for the exact path — typically `~/.openclaw/agents/<agent-id>/system.md` or a configured system prompt field). Follow the same structure as Mutiro's create-agent guide:
|
|
212
|
+
|
|
213
|
+
```markdown
|
|
214
|
+
# <Agent Name> — <One-line role>
|
|
215
|
+
|
|
216
|
+
## Who You Are
|
|
217
|
+
<identity and personality in 2–3 sentences>
|
|
218
|
+
|
|
219
|
+
## Your Mission
|
|
220
|
+
<what this agent exists to do>
|
|
221
|
+
|
|
222
|
+
## How You Communicate
|
|
223
|
+
<tone, length, style — remember replies go through chat>
|
|
224
|
+
|
|
225
|
+
## What You Do
|
|
226
|
+
<core behaviors>
|
|
227
|
+
|
|
228
|
+
## Rules
|
|
229
|
+
<hard constraints, especially tool usage>
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
---
|
|
233
|
+
|
|
234
|
+
### Step 8: Enable the Mutiro Channel Tools for the Agent
|
|
235
|
+
|
|
236
|
+
The openclaw-brain plugin ships three extra agent tools on top of the built-in reply surface:
|
|
237
|
+
|
|
238
|
+
| Tool | Purpose |
|
|
239
|
+
|------|---------|
|
|
240
|
+
| `mutiro_send_voice_message` | Reply with a host-synthesized voice message (TTS stays inside Mutiro). |
|
|
241
|
+
| `mutiro_send_card` | Send an interactive A2UI card (v0.8 JSONL). |
|
|
242
|
+
| `mutiro_forward_message` | Forward an existing message to another conversation or user. |
|
|
243
|
+
|
|
244
|
+
These are **channel-scoped agent tools**. They live in a different registry from regular plugin tools, which means the `alsoAllow` list has to match the tool names exactly or via a tool-name glob — group names like `mutiro` or `group:plugins` silently block.
|
|
245
|
+
|
|
246
|
+
Correct forms:
|
|
247
|
+
|
|
248
|
+
```yaml
|
|
249
|
+
tools:
|
|
250
|
+
profile: messaging # baseline: message, sessions_*, session_status
|
|
251
|
+
alsoAllow:
|
|
252
|
+
- "mutiro*" # glob — enables all Mutiro tools
|
|
253
|
+
# or, explicitly:
|
|
254
|
+
- mutiro_send_voice_message
|
|
255
|
+
- mutiro_send_card
|
|
256
|
+
- mutiro_forward_message
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
Apply that to the agent's config (use `openclaw agents ...` or edit the agent YAML, depending on how the agent was set up). If I skip this step the agent can still reply with plain text but voice/card/forward tools will be unavailable.
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
### Step 9: Start OpenClaw
|
|
264
|
+
|
|
265
|
+
```bash
|
|
266
|
+
openclaw gateway run
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
Watch the logs for these signals:
|
|
270
|
+
|
|
271
|
+
- `channel=mutiro account=default started` — the plugin spawned `mutiro agent host --mode=bridge`.
|
|
272
|
+
- `bridge handshake ok` — `session.initialize` and `subscription.set` completed.
|
|
273
|
+
- No `Handshake failed` or `Host error` lines.
|
|
274
|
+
|
|
275
|
+
If this is a local checkout and new source files were added recently, force a rebuild:
|
|
276
|
+
|
|
277
|
+
```bash
|
|
278
|
+
OPENCLAW_FORCE_BUILD=1 openclaw gateway run
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
OpenClaw runs from its built output — dirty-tree detection only looks at `.ts`/`.js` files, so brand-new files in the plugin may not trigger a rebuild on their own.
|
|
282
|
+
|
|
283
|
+
---
|
|
284
|
+
|
|
285
|
+
### Step 10: Test It
|
|
286
|
+
|
|
287
|
+
Talk to the agent from any Mutiro surface:
|
|
288
|
+
|
|
289
|
+
- **Web app:** https://app.mutiro.com — sign in and open the conversation with the agent
|
|
290
|
+
- **CLI chat:** `mutiro chat` — terminal UI
|
|
291
|
+
- **Mobile:** Mutiro app on iOS and Android
|
|
292
|
+
- **Desktop:** Mutiro desktop app on macOS, Windows, Linux
|
|
293
|
+
|
|
294
|
+
Or send a quick test message from the shell:
|
|
295
|
+
|
|
296
|
+
```bash
|
|
297
|
+
mutiro user message send <agent-username> "Hello! Who are you?"
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
Within a second or two I should see:
|
|
301
|
+
|
|
302
|
+
- a typing/thinking signal on the Mutiro UI (from `signal.emit`)
|
|
303
|
+
- the agent reply threaded under my message
|
|
304
|
+
- OpenClaw logs showing `message.observed` → reply dispatch → `message.send` → `turn.end`
|
|
305
|
+
|
|
306
|
+
If no reply lands, jump to the troubleshooting section below.
|
|
307
|
+
|
|
308
|
+
---
|
|
309
|
+
|
|
310
|
+
### Step 11: Iterate
|
|
311
|
+
|
|
312
|
+
- **Wrong tone or behavior?** → Edit the OpenClaw system prompt and restart the gateway.
|
|
313
|
+
- **Missing capability?** → Add the tool to the agent's `alsoAllow` list (remember: exact name or `mutiro*` glob for channel tools).
|
|
314
|
+
- **Wrong model?** → Change the default via `openclaw models set-default`.
|
|
315
|
+
- **Agent hangs or double-replies?** → Make sure the built-in Mutiro brain is not also running against the same agent.
|
|
316
|
+
|
|
317
|
+
Restart with `openclaw gateway run` after any config change.
|
|
318
|
+
|
|
319
|
+
---
|
|
320
|
+
|
|
321
|
+
### Step 12: Signals and Live Call Handoff
|
|
322
|
+
|
|
323
|
+
OpenClaw's tool activity is forwarded to Mutiro as bridge signals, so Mutiro surfaces "thinking", "web searching", "recalling", "sending voice", etc. in real time while the agent works. The plugin maps 26 OpenClaw tool names to Mutiro `SignalType` enums; anything outside the map falls back to `SIGNAL_TYPE_CUSTOM` with a detail label.
|
|
324
|
+
|
|
325
|
+
For live voice calls, Mutiro sends `task.request` with a compact observed-turn payload and expects a plain-text result. The plugin handles this by accumulating the agent's reply text and returning it as `ChatBridgeTaskResult.text`. It also answers `session.snapshot` from recent messages cached per-conversation so Mutiro can bootstrap the live lane.
|
|
326
|
+
|
|
327
|
+
Voice call **summaries** flow as normal `message.observed` envelopes tagged `live_call`. OpenClaw treats them as regular inbound turns — nothing extra to configure.
|
|
328
|
+
|
|
329
|
+
---
|
|
330
|
+
|
|
331
|
+
### Step 13: Troubleshooting
|
|
332
|
+
|
|
333
|
+
These are the six silent-fail gotchas that cause most first-run issues. Walk through them in order:
|
|
334
|
+
|
|
335
|
+
**1. "Unknown target conv_..."** — The plugin exposes a `targetResolver` that recognizes `conv_*` conversation IDs and `@username` direct sends. If you see this error, the plugin probably did not load; check `openclaw plugins list` and rebuild.
|
|
336
|
+
|
|
337
|
+
**2. "Channel mutiro is unavailable for message actions"** — Reactions rely on the plugin's message-action adapter. Same cause as (1) — plugin not registered. Rebuild and restart.
|
|
338
|
+
|
|
339
|
+
**3. Agent can't use `mutiro_send_voice_message`, `mutiro_send_card`, or `mutiro_forward_message`** — The `alsoAllow` list uses the wrong form. Channel agent tools need exact names or `mutiro*` glob. `mutiro` (group name) silently blocks because channel tools use a separate metadata registry.
|
|
340
|
+
|
|
341
|
+
**4. Media upload succeeds but the reply fails with "path not allowed"** — OpenClaw's sandbox rejects any media path outside `~/.openclaw/media/`. Do not stage files to `/tmp/`; use `saveMediaBuffer` (already wired inside the plugin).
|
|
342
|
+
|
|
343
|
+
**5. New plugin source files are ignored** — The gateway runs from `dist/`, and dirty-tree detection only inspects `.ts`/`.js`. Force a rebuild with `OPENCLAW_FORCE_BUILD=1 openclaw gateway run` after adding new files.
|
|
344
|
+
|
|
345
|
+
**6. Gateway loops restarting the channel** — Usually means `startAccount` resolved early and was interpreted as "channel exited". The plugin fixes this by returning a lifecycle `Promise` that only resolves on host exit or abort; if you are on an older version, update.
|
|
346
|
+
|
|
347
|
+
**Log inspection:**
|
|
348
|
+
|
|
349
|
+
```bash
|
|
350
|
+
openclaw channels status --probe
|
|
351
|
+
openclaw channels logs --channel mutiro
|
|
352
|
+
openclaw doctor
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
---
|
|
356
|
+
|
|
357
|
+
### Step 14: Security
|
|
358
|
+
|
|
359
|
+
OpenClaw-as-brain inherits both sides' risk surface:
|
|
360
|
+
|
|
361
|
+
- Every Mutiro message, forwarded content, voice transcript, and uploaded file is potential prompt-injection input.
|
|
362
|
+
- OpenClaw's tool set defines the blast radius if an injection succeeds.
|
|
363
|
+
|
|
364
|
+
Apply the same Exposure × Blast Radius thinking as the Mutiro create-agent guide:
|
|
365
|
+
|
|
366
|
+
- **Personal agent, only you message it:** defaults are fine. Still careful with forwarded content.
|
|
367
|
+
- **Shared with trusted people:** keep memory writes scoped; prefer per-user workspace isolation.
|
|
368
|
+
- **Open to everyone:** restrict OpenClaw tools to reply-only — no file writes, no memory writes, no web fetch.
|
|
369
|
+
- **Agent fetches untrusted web content:** separate it into a "research" agent (reads web, reports back) and an "action" agent (only takes instructions from you).
|
|
370
|
+
|
|
371
|
+
The lethal combination: (1) ingests untrusted data, (2) takes consequential actions, (3) runs without human oversight. Do not build one agent that is all three.
|
|
372
|
+
|
|
373
|
+
Help me review OpenClaw's `tools.profile` / `tools.alsoAllow` and the Mutiro `allowlist` together — the weakest link decides the real risk.
|
|
374
|
+
|
|
375
|
+
---
|
|
376
|
+
|
|
377
|
+
### Reference
|
|
378
|
+
|
|
379
|
+
**OpenClaw commands:**
|
|
380
|
+
- `openclaw plugins list` — show installed plugins
|
|
381
|
+
- `openclaw channels list` — show registered channels
|
|
382
|
+
- `openclaw channels status --probe` — live channel health
|
|
383
|
+
- `openclaw channels logs --channel mutiro` — plugin logs
|
|
384
|
+
- `openclaw config get channels.mutiro` — view bridge config
|
|
385
|
+
- `openclaw gateway run` — start the gateway
|
|
386
|
+
- `openclaw doctor` — diagnose
|
|
387
|
+
- `openclaw agents --help` — agent setup options
|
|
388
|
+
|
|
389
|
+
**Mutiro commands:**
|
|
390
|
+
- `mutiro agents list` — see your agents
|
|
391
|
+
- `mutiro agents get <username>` — agent details
|
|
392
|
+
- `mutiro agents allowlist get <username>` — who can message it
|
|
393
|
+
- `mutiro user message send <agent-username> "<text>"` — send a test message
|
|
394
|
+
- `mutiro agent doctor` — diagnose the Mutiro side
|
|
395
|
+
|
|
396
|
+
**Docs:**
|
|
397
|
+
- OpenClaw: https://openclaw.ai
|
|
398
|
+
- Mutiro: https://mutiro.com
|
|
399
|
+
- Create a Mutiro agent: https://www.mutiro.com/docs/guides/create-agent.md
|
|
400
|
+
- openclaw-brain repo: https://github.com/mutirolabs/openclaw-brain
|
|
401
|
+
````
|
package/index.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
// Plugin entry. Consumed by OpenClaw's bundled channel loader via the
|
|
2
|
+
// `openclaw.extensions` field in package.json.
|
|
3
|
+
//
|
|
4
|
+
// `defineBundledChannelEntry` wires the channel plugin descriptor (loaded
|
|
5
|
+
// from ./src/channel.ts) into OpenClaw's registry. The heavier runtime
|
|
6
|
+
// module (./src/channel.runtime.ts) is loaded lazily from inside the channel
|
|
7
|
+
// plugin itself (via `createLazyRuntimeNamedExport`), so we do not need to
|
|
8
|
+
// register it here as a `PluginRuntime` setter.
|
|
9
|
+
|
|
10
|
+
import { defineBundledChannelEntry } from "openclaw/plugin-sdk/channel-entry-contract";
|
|
11
|
+
|
|
12
|
+
export default defineBundledChannelEntry({
|
|
13
|
+
id: "mutiro",
|
|
14
|
+
name: "Mutiro",
|
|
15
|
+
description: "Mutiro chatbridge channel plugin",
|
|
16
|
+
importMetaUrl: import.meta.url,
|
|
17
|
+
plugin: {
|
|
18
|
+
specifier: "./src/channel.js",
|
|
19
|
+
exportName: "mutiroPlugin",
|
|
20
|
+
},
|
|
21
|
+
});
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
{
|
|
2
|
+
"id": "mutiro",
|
|
3
|
+
"channels": ["mutiro"],
|
|
4
|
+
"channelEnvVars": {
|
|
5
|
+
"mutiro": ["MUTIRO_AGENT_API_KEY"]
|
|
6
|
+
},
|
|
7
|
+
"configSchema": {
|
|
8
|
+
"type": "object",
|
|
9
|
+
"additionalProperties": false,
|
|
10
|
+
"properties": {
|
|
11
|
+
"agentDir": {
|
|
12
|
+
"type": "string",
|
|
13
|
+
"description": "Single-account shortcut: absolute path to the Mutiro agent workspace."
|
|
14
|
+
},
|
|
15
|
+
"clientName": {
|
|
16
|
+
"type": "string",
|
|
17
|
+
"description": "Identifier sent to the host in session.initialize."
|
|
18
|
+
},
|
|
19
|
+
"requestedOptionalCapabilities": {
|
|
20
|
+
"type": "array",
|
|
21
|
+
"items": { "type": "string" },
|
|
22
|
+
"description": "Optional capabilities advertised in session.initialize."
|
|
23
|
+
},
|
|
24
|
+
"enabled": {
|
|
25
|
+
"type": "boolean"
|
|
26
|
+
},
|
|
27
|
+
"accounts": {
|
|
28
|
+
"type": "object",
|
|
29
|
+
"additionalProperties": {
|
|
30
|
+
"type": "object",
|
|
31
|
+
"additionalProperties": false,
|
|
32
|
+
"required": ["agentDir"],
|
|
33
|
+
"properties": {
|
|
34
|
+
"agentDir": { "type": "string" },
|
|
35
|
+
"clientName": { "type": "string" },
|
|
36
|
+
"requestedOptionalCapabilities": {
|
|
37
|
+
"type": "array",
|
|
38
|
+
"items": { "type": "string" }
|
|
39
|
+
},
|
|
40
|
+
"enabled": { "type": "boolean" },
|
|
41
|
+
"name": { "type": "string" }
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@mutirolabs/openclaw-brain",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "OpenClaw channel plugin that drives a Mutiro agent over chatbridge. OpenClaw becomes the brain; Mutiro stays the messaging surface.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "ISC",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/mutirolabs/openclaw-brain.git"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/mutirolabs/openclaw-brain#readme",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/mutirolabs/openclaw-brain/issues"
|
|
14
|
+
},
|
|
15
|
+
"scripts": {
|
|
16
|
+
"check": "tsc -p tsconfig.json --noEmit",
|
|
17
|
+
"gateway": "openclaw gateway run",
|
|
18
|
+
"prepublishOnly": "npm run check"
|
|
19
|
+
},
|
|
20
|
+
"publishConfig": {
|
|
21
|
+
"access": "public"
|
|
22
|
+
},
|
|
23
|
+
"keywords": [
|
|
24
|
+
"mutiro",
|
|
25
|
+
"chatbridge",
|
|
26
|
+
"openclaw",
|
|
27
|
+
"channel",
|
|
28
|
+
"plugin",
|
|
29
|
+
"agent"
|
|
30
|
+
],
|
|
31
|
+
"files": [
|
|
32
|
+
"index.ts",
|
|
33
|
+
"src",
|
|
34
|
+
"docs",
|
|
35
|
+
"openclaw.plugin.json",
|
|
36
|
+
"README.md",
|
|
37
|
+
"LICENSE",
|
|
38
|
+
"CHANGELOG.md"
|
|
39
|
+
],
|
|
40
|
+
"engines": {
|
|
41
|
+
"node": ">=22"
|
|
42
|
+
},
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"@sinclair/typebox": "^0.34.49"
|
|
45
|
+
},
|
|
46
|
+
"peerDependencies": {
|
|
47
|
+
"openclaw": ">=2026.4.10"
|
|
48
|
+
},
|
|
49
|
+
"peerDependenciesMeta": {
|
|
50
|
+
"openclaw": {
|
|
51
|
+
"optional": true
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"@types/node": "^22.0.0",
|
|
56
|
+
"openclaw": "^2026.4.15",
|
|
57
|
+
"typescript": "^5.6.0"
|
|
58
|
+
},
|
|
59
|
+
"openclaw": {
|
|
60
|
+
"extensions": [
|
|
61
|
+
"./index.ts"
|
|
62
|
+
],
|
|
63
|
+
"channel": {
|
|
64
|
+
"id": "mutiro",
|
|
65
|
+
"label": "Mutiro",
|
|
66
|
+
"selectionLabel": "Mutiro (plugin)",
|
|
67
|
+
"docsPath": "/channels/mutiro",
|
|
68
|
+
"docsLabel": "mutiro",
|
|
69
|
+
"blurb": "chatbridge channel; configure a Mutiro agent directory to enable.",
|
|
70
|
+
"order": 80,
|
|
71
|
+
"quickstartAllowFrom": true
|
|
72
|
+
},
|
|
73
|
+
"install": {
|
|
74
|
+
"npmSpec": "@mutirolabs/openclaw-brain",
|
|
75
|
+
"defaultChoice": "npm",
|
|
76
|
+
"minHostVersion": ">=2026.4.10"
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
package/src/actions.ts
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// Message-action adapter for the shared `message` tool. Teaches OpenClaw
|
|
2
|
+
// which actions our plugin handles (react, forward) and dispatches them
|
|
3
|
+
// into the bridge via `channel.runtime.ts`. Without this adapter the tool
|
|
4
|
+
// rejects with "Channel mutiro is unavailable for message actions".
|
|
5
|
+
//
|
|
6
|
+
// Kept compact: `describeMessageTool` returns a fixed action list, and
|
|
7
|
+
// `handleAction` does a dynamic import so the heavy runtime stays off the
|
|
8
|
+
// hot plugin-registration path.
|
|
9
|
+
|
|
10
|
+
import type {
|
|
11
|
+
ChannelMessageActionAdapter,
|
|
12
|
+
ChannelMessageActionContext,
|
|
13
|
+
ChannelMessageActionName,
|
|
14
|
+
} from "openclaw/plugin-sdk/channel-contract";
|
|
15
|
+
|
|
16
|
+
const MUTIRO_HANDLED_ACTIONS: readonly ChannelMessageActionName[] = [
|
|
17
|
+
"react",
|
|
18
|
+
] as const;
|
|
19
|
+
|
|
20
|
+
const MUTIRO_HANDLED_ACTION_SET = new Set<ChannelMessageActionName>(MUTIRO_HANDLED_ACTIONS);
|
|
21
|
+
|
|
22
|
+
const readStringArg = (
|
|
23
|
+
params: Record<string, unknown>,
|
|
24
|
+
...keys: string[]
|
|
25
|
+
): string | undefined => {
|
|
26
|
+
for (const key of keys) {
|
|
27
|
+
const value = params[key];
|
|
28
|
+
if (typeof value === "string") {
|
|
29
|
+
const trimmed = value.trim();
|
|
30
|
+
if (trimmed) return trimmed;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return undefined;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export const mutiroMessageActions: ChannelMessageActionAdapter = {
|
|
37
|
+
describeMessageTool: () => ({
|
|
38
|
+
actions: MUTIRO_HANDLED_ACTIONS,
|
|
39
|
+
capabilities: [],
|
|
40
|
+
}),
|
|
41
|
+
|
|
42
|
+
supportsAction: ({ action }) => MUTIRO_HANDLED_ACTION_SET.has(action),
|
|
43
|
+
|
|
44
|
+
handleAction: async (ctx: ChannelMessageActionContext) => {
|
|
45
|
+
const { handleMutiroMessageAction } = await import("./channel.runtime.js");
|
|
46
|
+
return handleMutiroMessageAction({
|
|
47
|
+
action: ctx.action,
|
|
48
|
+
params: ctx.params,
|
|
49
|
+
accountId: ctx.accountId ?? undefined,
|
|
50
|
+
readStringArg,
|
|
51
|
+
});
|
|
52
|
+
},
|
|
53
|
+
};
|