Compare commits

..

1 Commits

Author SHA1 Message Date
Josh Palmer
d8a88971ba 🤖 feat: add Feishu/Lark channel support
What:
- clean up Feishu port for lint/type safety and error handling
- allow buffers in Feishu media uploads and tighten config merging
- increase Discord/Telegram unit test timeouts to reduce parallel flake

Why:
- backport Feishu support from openclaw-cn
- keep local test runs stable under parallel load

Tests:
- pnpm lint
- pnpm build
- pnpm vitest run --config vitest.unit.config.ts src/telegram/bot.media.downloads-media-file-path-no-file-download.test.ts --maxWorkers 1
- pnpm vitest run --config vitest.unit.config.ts src/discord/monitor.tool-result.accepts-guild-messages-mentionpatterns-match.test.ts --maxWorkers 1
- pnpm test:all (fails in pnpm test:e2e: missing OPENCLAW_GATEWAY_TOKEN / gateway token mismatch; failing e2e tests include server.ios-client-id, gateway.multi, server.agent/chat/health/hooks/roles-allowlist/sessions-send, media-understanding.auto gemini, directive model list/help)
2026-02-03 00:25:43 +01:00
716 changed files with 15741 additions and 29427 deletions

6
.github/labeler.yml vendored
View File

@@ -9,12 +9,6 @@
- "src/discord/**"
- "extensions/discord/**"
- "docs/channels/discord.md"
"channel: feishu":
- changed-files:
- any-glob-to-any-file:
- "src/feishu/**"
- "extensions/feishu/**"
- "docs/channels/feishu.md"
"channel: googlechat":
- changed-files:
- any-glob-to-any-file:

View File

@@ -89,6 +89,9 @@ jobs:
- runtime: bun
task: test
command: pnpm canvas:a2ui:bundle && bunx vitest run
- runtime: bun
task: build
command: bunx tsc -p tsconfig.json --noEmit false
steps:
- name: Checkout
uses: actions/checkout@v4

View File

@@ -16,6 +16,7 @@
"oxc/no-map-spread": "off",
"typescript/no-explicit-any": "error",
"typescript/no-extraneous-class": "off",
"typescript/no-redundant-type-constituents": "off",
"typescript/no-unsafe-type-assertion": "off",
"unicorn/consistent-function-scoping": "off",
"unicorn/require-post-message-target-origin": "off"

View File

@@ -28,14 +28,6 @@
- README (GitHub): keep absolute docs URLs (`https://docs.openclaw.ai/...`) so links work on GitHub.
- Docs content must be generic: no personal device names/hostnames/paths; use placeholders like `user@gateway-host` and “gateway host”.
## Docs i18n (zh-CN)
- `docs/zh-CN/**` is generated; do not edit unless the user explicitly asks.
- Pipeline: update English docs → adjust glossary (`docs/.i18n/glossary.zh-CN.json`) → run `scripts/docs-i18n` → apply targeted fixes only if instructed.
- Translation memory: `docs/.i18n/zh-CN.tm.jsonl` (generated).
- See `docs/.i18n/README.md`.
- The pipeline can be slow/inefficient; if its dragging, ping @jospalmbier on Discord instead of hacking around it.
## exe.dev VM ops (general)
- Access: stable path is `ssh exe.dev` then `ssh vm-name` (assume SSH key already set).

View File

@@ -2,97 +2,22 @@
Docs: https://docs.openclaw.ai
## 2026.2.3
### Changes
- Onboarding: add Moonshot (.cn) auth choice and keep the China base URL when preserving defaults. (#7180) Thanks @waynelwz.
- Docs: clarify tmux send-keys for TUI by splitting text and Enter. (#7737) Thanks @Wangnov.
- Cron: add announce delivery mode for isolated jobs (CLI + Control UI) and delivery mode config.
- Cron: default isolated jobs to announce delivery; accept ISO 8601 `schedule.at` in tool inputs.
- Cron: hard-migrate isolated jobs to announce/none delivery; drop legacy post-to-main/payload delivery fields and `atMs` inputs.
- Cron: delete one-shot jobs after success by default; add `--keep-after-run` for CLI.
- Cron: suppress messaging tools during announce delivery so summaries post consistently.
- Cron: avoid duplicate deliveries when isolated runs send messages directly.
### Fixes
- Telegram: honor session model overrides in inline model selection. (#8193) Thanks @gildo.
- iMessage: skip echo replies using recent outbound IDs before falling back to text matching. (#8680) Thanks @Iranb.
- Web UI: resolve header logo path when `gateway.controlUi.basePath` is set. (#7178) Thanks @Yeom-JinHo.
- Web UI: apply button styling to the new-messages indicator.
- Security: keep untrusted channel metadata out of system prompts (Slack/Discord). Thanks @KonstantinMirin.
- Voice call: harden webhook verification with host allowlists/proxy trust and keep ngrok loopback bypass.
- Cron: accept epoch timestamps and 0ms durations in CLI `--at` parsing.
- Cron: reload store data when the store file is recreated or mtime changes.
- Cron: deliver announce runs directly, honor delivery mode, and respect wakeMode for summaries. (#8540) Thanks @tyler6204.
- Telegram: include forward_from_chat metadata in forwarded messages and harden cron delivery target checks. (#8392) Thanks @Glucksberg.
## 2026.2.2-3
### Fixes
- Update: ship legacy daemon-cli shim for pre-tsdown update imports (fixes daemon restart after npm update).
## 2026.2.2-2
### Changes
- Docs: promote BlueBubbles as the recommended iMessage integration; mark imsg channel as legacy. (#8415) Thanks @tyler6204.
### Fixes
- CLI status: resolve build-info from bundled dist output (fixes "unknown" commit in npm builds).
## 2026.2.2-1
### Fixes
- CLI status: fall back to build-info for version detection (fixes "unknown" in beta builds). Thanks @gumadeira.
## 2026.2.2
### Changes
- Feishu: add Feishu/Lark plugin support + docs. (#7313) Thanks @jiulingyun (openclaw-cn).
- Web UI: add Agents dashboard for managing agent files, tools, skills, models, channels, and cron jobs.
- Subagents: discourage direct messaging tool use unless a specific external recipient is requested.
- Memory: implement the opt-in QMD backend for workspace memory. (#3160) Thanks @vignesh07.
- Security: add healthcheck skill and bootstrap audit guidance. (#7641) Thanks @Takhoffman.
- Docs: seed zh-CN translations. (#6619) Thanks @joshp123.
- Docs: expand zh-Hans navigation and fix zh-CN index asset paths. (#7242) Thanks @joshp123.
- Docs: add zh-CN landing notice + AI-translated image. (#7303) Thanks @joshp123.
- Config: allow setting a default subagent thinking level via `agents.defaults.subagents.thinking` (and per-agent `agents.list[].subagents.thinking`). (#7372) Thanks @tyler6204.
- Docs: zh-CN translations seed + polish, pipeline guidance, nav/landing updates, and typo fixes. (#8202, #6995, #6619, #7242, #7303, #7415) Thanks @AaronWander, @taiyi747, @Explorer1092, @rendaoyuan, @joshp123, @lailoo.
- Docs: add zh-CN i18n guardrails to avoid editing generated translations. (#8416) Thanks @joshp123.
- Feishu: add Feishu/Lark plugin support + docs. Thanks @jiulingyun (openclaw-cn).
### Fixes
- Docs: finish renaming the QMD memory docs to reference the OpenClaw state dir.
- Onboarding: keep TUI flow exclusive (skip completion prompt + background Web UI seed).
- Onboarding: drop completion prompt now handled by install/update.
- TUI: block onboarding output while TUI is active and restore terminal state on exit.
- CLI: cache shell completion scripts in state dir and source cached files in profiles.
- Zsh completion: escape option descriptions to avoid invalid option errors.
- Agents: repair malformed tool calls and session transcripts. (#7473) Thanks @justinhuangcode.
- fix(agents): validate AbortSignal instances before calling AbortSignal.any() (#7277) (thanks @Elarwei001)
- fix(webchat): respect user scroll position during streaming and refresh (#7226) (thanks @marcomarandiz)
- Telegram: recover from grammY long-poll timed out errors. (#7466) Thanks @macmimi23.
- Media understanding: skip binary media from file text extraction. (#7475) Thanks @AlexZhangji.
- Security: enforce access-group gating for Slack slash commands when channel type lookup fails.
- Security: require validated shared-secret auth before skipping device identity on gateway connect.
- Security: guard skill installer downloads with SSRF checks (block private/localhost URLs).
- Security: harden Windows exec allowlist; block cmd.exe bypass via single &. Thanks @simecek.
- fix(voice-call): harden inbound allowlist; reject anonymous callers; require Telnyx publicKey for allowlist; token-gate Twilio media streams; cap webhook body size (thanks @simecek)
- Media understanding: apply SSRF guardrails to provider fetches; allow private baseUrl overrides explicitly.
- fix(webchat): respect user scroll position during streaming and refresh (#7226) (thanks @marcomarandiz)
- Telegram: recover from grammY long-poll timed out errors. (#7466) Thanks @macmimi23.
- Agents: repair malformed tool calls and session transcripts. (#7473) Thanks @justinhuangcode.
- fix(agents): validate AbortSignal instances before calling AbortSignal.any() (#7277) (thanks @Elarwei001)
- Media understanding: skip binary media from file text extraction. (#7475) Thanks @AlexZhangji.
- Onboarding: keep TUI flow exclusive (skip completion prompt + background Web UI seed); completion prompt now handled by install/update.
- TUI: block onboarding output while TUI is active and restore terminal state on exit.
- CLI/Zsh completion: cache scripts in state dir and escape option descriptions to avoid invalid option errors.
- fix(ui): resolve Control UI asset path correctly.
- fix(ui): refresh agent files after external edits.
- Docs: finish renaming the QMD memory docs to reference the OpenClaw state dir.
- Tests: stub SSRF DNS pinning in web auto-reply + Gemini video coverage. (#6619) Thanks @joshp123.
## 2026.2.1

View File

@@ -35,21 +35,6 @@ Welcome to the lobster tank! 🦞
- Keep PRs focused (one thing per PR)
- Describe what & why
## Control UI Decorators
The Control UI uses Lit with **legacy** decorators (current Rollup parsing does not support
`accessor` fields required for standard decorators). When adding reactive fields, keep the
legacy style:
```ts
@state() foo = "bar";
@property({ type: Number }) count = 0;
```
The root `tsconfig.json` is configured for legacy decorators (`experimentalDecorators: true`)
with `useDefineForClassFields: false`. Avoid flipping these unless you are also updating the UI
build tooling to support standard decorators.
## AI/Vibe-Coded PRs Welcome! 🤖
Built with Codex, Claude, or other AI tools? **Awesome - just mark it!**

View File

@@ -120,7 +120,7 @@ Run `openclaw doctor` to surface risky/misconfigured DM policies.
## Highlights
- **[Local-first Gateway](https://docs.openclaw.ai/gateway)** — single control plane for sessions, channels, tools, and events.
- **[Multi-channel inbox](https://docs.openclaw.ai/channels)** — WhatsApp, Telegram, Slack, Discord, Google Chat, Signal, BlueBubbles (iMessage), iMessage (legacy), Microsoft Teams, Matrix, Zalo, Zalo Personal, WebChat, macOS, iOS/Android.
- **[Multi-channel inbox](https://docs.openclaw.ai/channels)** — WhatsApp, Telegram, Slack, Discord, Google Chat, Signal, iMessage, BlueBubbles, Microsoft Teams, Matrix, Zalo, Zalo Personal, WebChat, macOS, iOS/Android.
- **[Multi-agent routing](https://docs.openclaw.ai/gateway/configuration)** — route inbound channels/accounts/peers to isolated agents (workspaces + per-agent sessions).
- **[Voice Wake](https://docs.openclaw.ai/nodes/voicewake) + [Talk Mode](https://docs.openclaw.ai/nodes/talk)** — always-on speech for macOS/iOS/Android with ElevenLabs.
- **[Live Canvas](https://docs.openclaw.ai/platforms/mac/canvas)** — agent-driven visual workspace with [A2UI](https://docs.openclaw.ai/platforms/mac/canvas#canvas-a2ui).
@@ -144,7 +144,7 @@ Run `openclaw doctor` to surface risky/misconfigured DM policies.
### Channels
- [Channels](https://docs.openclaw.ai/channels): [WhatsApp](https://docs.openclaw.ai/channels/whatsapp) (Baileys), [Telegram](https://docs.openclaw.ai/channels/telegram) (grammY), [Slack](https://docs.openclaw.ai/channels/slack) (Bolt), [Discord](https://docs.openclaw.ai/channels/discord) (discord.js), [Google Chat](https://docs.openclaw.ai/channels/googlechat) (Chat API), [Signal](https://docs.openclaw.ai/channels/signal) (signal-cli), [BlueBubbles](https://docs.openclaw.ai/channels/bluebubbles) (iMessage, recommended), [iMessage](https://docs.openclaw.ai/channels/imessage) (legacy imsg), [Microsoft Teams](https://docs.openclaw.ai/channels/msteams) (extension), [Matrix](https://docs.openclaw.ai/channels/matrix) (extension), [Zalo](https://docs.openclaw.ai/channels/zalo) (extension), [Zalo Personal](https://docs.openclaw.ai/channels/zalouser) (extension), [WebChat](https://docs.openclaw.ai/web/webchat).
- [Channels](https://docs.openclaw.ai/channels): [WhatsApp](https://docs.openclaw.ai/channels/whatsapp) (Baileys), [Telegram](https://docs.openclaw.ai/channels/telegram) (grammY), [Slack](https://docs.openclaw.ai/channels/slack) (Bolt), [Discord](https://docs.openclaw.ai/channels/discord) (discord.js), [Google Chat](https://docs.openclaw.ai/channels/googlechat) (Chat API), [Signal](https://docs.openclaw.ai/channels/signal) (signal-cli), [iMessage](https://docs.openclaw.ai/channels/imessage) (imsg), [BlueBubbles](https://docs.openclaw.ai/channels/bluebubbles) (extension), [Microsoft Teams](https://docs.openclaw.ai/channels/msteams) (extension), [Matrix](https://docs.openclaw.ai/channels/matrix) (extension), [Zalo](https://docs.openclaw.ai/channels/zalo) (extension), [Zalo Personal](https://docs.openclaw.ai/channels/zalouser) (extension), [WebChat](https://docs.openclaw.ai/web/webchat).
- [Group routing](https://docs.openclaw.ai/concepts/group-messages): mention gating, reply tags, per-channel chunking and routing. Channel rules: [Channels](https://docs.openclaw.ai/channels).
### Apps + nodes
@@ -375,15 +375,9 @@ Details: [Security guide](https://docs.openclaw.ai/gateway/security) · [Docker
- Requires `signal-cli` and a `channels.signal` config section.
### [BlueBubbles (iMessage)](https://docs.openclaw.ai/channels/bluebubbles)
### [iMessage](https://docs.openclaw.ai/channels/imessage)
- **Recommended** iMessage integration.
- Configure `channels.bluebubbles.serverUrl` + `channels.bluebubbles.password` and a webhook (`channels.bluebubbles.webhookPath`).
- The BlueBubbles server runs on macOS; the Gateway can run on macOS or elsewhere.
### [iMessage (legacy)](https://docs.openclaw.ai/channels/imessage)
- Legacy macOS-only integration via `imsg` (Messages must be signed in).
- macOS only; Messages must be signed in.
- If `channels.imessage.groups` is set, it becomes a group allowlist; include `"*"` to allow all.
### [Microsoft Teams](https://docs.openclaw.ai/channels/msteams)

View File

@@ -2,50 +2,6 @@
<rss xmlns:sparkle="http://www.andymatuschak.org/xml-namespaces/sparkle" version="2.0">
<channel>
<title>OpenClaw</title>
<item>
<title>2026.2.2</title>
<pubDate>Tue, 03 Feb 2026 17:04:17 -0800</pubDate>
<link>https://raw.githubusercontent.com/openclaw/openclaw/main/appcast.xml</link>
<sparkle:version>8809</sparkle:version>
<sparkle:shortVersionString>2026.2.2</sparkle:shortVersionString>
<sparkle:minimumSystemVersion>15.0</sparkle:minimumSystemVersion>
<description><![CDATA[<h2>OpenClaw 2026.2.2</h2>
<h3>Changes</h3>
<ul>
<li>Feishu: add Feishu/Lark plugin support + docs. (#7313) Thanks @jiulingyun (openclaw-cn).</li>
<li>Web UI: add Agents dashboard for managing agent files, tools, skills, models, channels, and cron jobs.</li>
<li>Memory: implement the opt-in QMD backend for workspace memory. (#3160) Thanks @vignesh07.</li>
<li>Security: add healthcheck skill and bootstrap audit guidance. (#7641) Thanks @Takhoffman.</li>
<li>Config: allow setting a default subagent thinking level via <code>agents.defaults.subagents.thinking</code> (and per-agent <code>agents.list[].subagents.thinking</code>). (#7372) Thanks @tyler6204.</li>
<li>Docs: zh-CN translations seed + polish, pipeline guidance, nav/landing updates, and typo fixes. (#8202, #6995, #6619, #7242, #7303, #7415) Thanks @AaronWander, @taiyi747, @Explorer1092, @rendaoyuan, @joshp123, @lailoo.</li>
</ul>
<h3>Fixes</h3>
<ul>
<li>Security: require operator.approvals for gateway /approve commands. (#1) Thanks @mitsuhiko, @yueyueL.</li>
<li>Security: Matrix allowlists now require full MXIDs; ambiguous name resolution no longer grants access. Thanks @MegaManSec.</li>
<li>Security: enforce access-group gating for Slack slash commands when channel type lookup fails.</li>
<li>Security: require validated shared-secret auth before skipping device identity on gateway connect.</li>
<li>Security: guard skill installer downloads with SSRF checks (block private/localhost URLs).</li>
<li>Security: harden Windows exec allowlist; block cmd.exe bypass via single &. Thanks @simecek.</li>
<li>fix(voice-call): harden inbound allowlist; reject anonymous callers; require Telnyx publicKey for allowlist; token-gate Twilio media streams; cap webhook body size (thanks @simecek)</li>
<li>Media understanding: apply SSRF guardrails to provider fetches; allow private baseUrl overrides explicitly.</li>
<li>fix(webchat): respect user scroll position during streaming and refresh (#7226) (thanks @marcomarandiz)</li>
<li>Telegram: recover from grammY long-poll timed out errors. (#7466) Thanks @macmimi23.</li>
<li>Agents: repair malformed tool calls and session transcripts. (#7473) Thanks @justinhuangcode.</li>
<li>fix(agents): validate AbortSignal instances before calling AbortSignal.any() (#7277) (thanks @Elarwei001)</li>
<li>Media understanding: skip binary media from file text extraction. (#7475) Thanks @AlexZhangji.</li>
<li>Onboarding: keep TUI flow exclusive (skip completion prompt + background Web UI seed); completion prompt now handled by install/update.</li>
<li>TUI: block onboarding output while TUI is active and restore terminal state on exit.</li>
<li>CLI/Zsh completion: cache scripts in state dir and escape option descriptions to avoid invalid option errors.</li>
<li>fix(ui): resolve Control UI asset path correctly.</li>
<li>fix(ui): refresh agent files after external edits.</li>
<li>Docs: finish renaming the QMD memory docs to reference the OpenClaw state dir.</li>
<li>Tests: stub SSRF DNS pinning in web auto-reply + Gemini video coverage. (#6619) Thanks @joshp123.</li>
</ul>
<p><a href="https://github.com/openclaw/openclaw/blob/main/CHANGELOG.md">View full changelog</a></p>
]]></description>
<enclosure url="https://github.com/openclaw/openclaw/releases/download/v2026.2.2/OpenClaw-2026.2.2.zip" length="22519052" type="application/octet-stream" sparkle:edSignature="a6viD+aS5EfY/RkPIPMfoQQNkJCk6QTdV5WobXFxyYwURskUm8/nXTHVXsCh1c5+0WKUnmlDIyf0i+6IWiavAA=="/>
</item>
<item>
<title>2026.2.1</title>
<pubDate>Mon, 02 Feb 2026 03:53:03 -0800</pubDate>
@@ -157,5 +113,137 @@
]]></description>
<enclosure url="https://github.com/openclaw/openclaw/releases/download/v2026.1.30/OpenClaw-2026.1.30.zip" length="22458594" type="application/octet-stream" sparkle:edSignature="77/GuEcruKGgu2CJyMq+OVwzaJ2v1VzRQC9NmOirKO3uH5Nn5HaoouwrOHnOanrzlD4OvPW0FS5GH2E4Ntu4CQ=="/>
</item>
<item>
<title>2026.1.29</title>
<pubDate>Fri, 30 Jan 2026 06:24:15 +0100</pubDate>
<link>https://raw.githubusercontent.com/openclaw/openclaw/main/appcast.xml</link>
<sparkle:version>8345</sparkle:version>
<sparkle:shortVersionString>2026.1.29</sparkle:shortVersionString>
<sparkle:minimumSystemVersion>15.0</sparkle:minimumSystemVersion>
<description><![CDATA[<h2>OpenClaw 2026.1.29</h2>
Status: stable.
<h3>Changes</h3>
<ul>
<li>Rebrand: rename the npm package/CLI to <code>openclaw</code>, add a <code>openclaw</code> compatibility shim, and move extensions to the <code>@openclaw/*</code> scope.</li>
<li>Onboarding: strengthen security warning copy for beta + access control expectations.</li>
<li>Onboarding: add Venice API key to non-interactive flow. (#1893) Thanks @jonisjongithub.</li>
<li>Config: auto-migrate legacy state/config paths and keep config resolution consistent across legacy filenames.</li>
<li>Gateway: warn on hook tokens via query params; document header auth preference. (#2200) Thanks @YuriNachos.</li>
<li>Gateway: add dangerous Control UI device auth bypass flag + audit warnings. (#2248)</li>
<li>Doctor: warn on gateway exposure without auth. (#2016) Thanks @Alex-Alaniz.</li>
<li>Web UI: keep sub-agent announce replies visible in WebChat. (#1977) Thanks @andrescardonas7.</li>
<li>Browser: route browser control via gateway/node; remove standalone browser control command and control URL config.</li>
<li>Browser: route <code>browser.request</code> via node proxies when available; honor proxy timeouts; derive browser ports from <code>gateway.port</code>.</li>
<li>Browser: fall back to URL matching for extension relay target resolution. (#1999) Thanks @jonit-dev.</li>
<li>Telegram: allow caption param for media sends. (#1888) Thanks @mguellsegarra.</li>
<li>Telegram: support plugin sendPayload channelData (media/buttons) and validate plugin commands. (#1917) Thanks @JoshuaLelon.</li>
<li>Telegram: avoid block replies when streaming is disabled. (#1885) Thanks @ivancasco.</li>
<li>Telegram: add optional silent send flag (disable notifications). (#2382) Thanks @Suksham-sharma.</li>
<li>Telegram: support editing sent messages via message(action="edit"). (#2394) Thanks @marcelomar21.</li>
<li>Telegram: support quote replies for message tool and inbound context. (#2900) Thanks @aduk059.</li>
<li>Telegram: add sticker receive/send with vision caching. (#2629) Thanks @longjos.</li>
<li>Telegram: send sticker pixels to vision models. (#2650)</li>
<li>Telegram: keep topic IDs in restart sentinel notifications. (#1807) Thanks @hsrvc.</li>
<li>Discord: add configurable privileged gateway intents for presences/members. (#2266) Thanks @kentaro.</li>
<li>Slack: clear ack reaction after streamed replies. (#2044) Thanks @fancyboi999.</li>
<li>Matrix: switch plugin SDK to @vector-im/matrix-bot-sdk.</li>
<li>Tlon: format thread reply IDs as @ud. (#1837) Thanks @wca4a.</li>
<li>Tools: add per-sender group tool policies and fix precedence. (#1757) Thanks @adam91holt.</li>
<li>Agents: summarize dropped messages during compaction safeguard pruning. (#2509) Thanks @jogi47.</li>
<li>Agents: expand cron tool description with full schema docs. (#1988) Thanks @tomascupr.</li>
<li>Agents: honor tools.exec.safeBins in exec allowlist checks. (#2281)</li>
<li>Memory Search: allow extra paths for memory indexing (ignores symlinks). (#3600) Thanks @kira-ariaki.</li>
<li>Skills: add multi-image input support to Nano Banana Pro skill. (#1958) Thanks @tyler6204.</li>
<li>Skills: add missing dependency metadata for GitHub, Notion, Slack, Discord. (#1995) Thanks @jackheuberger.</li>
<li>Commands: group /help and /commands output with Telegram paging. (#2504) Thanks @hougangdev.</li>
<li>Routing: add per-account DM session scope and document multi-account isolation. (#3095) Thanks @jarvis-sam.</li>
<li>Routing: precompile session key regexes. (#1697) Thanks @Ray0907.</li>
<li>CLI: use Node's module compile cache for faster startup. (#2808) Thanks @pi0.</li>
<li>Auth: show copyable Google auth URL after ASCII prompt. (#1787) Thanks @robbyczgw-cla.</li>
<li>TUI: avoid width overflow when rendering selection lists. (#1686) Thanks @mossein.</li>
<li>macOS: finish OpenClaw app rename for macOS sources, bundle identifiers, and shared kit paths. (#2844) Thanks @fal3.</li>
<li>Branding: update launchd labels, mobile bundle IDs, and logging subsystems to bot.molt (legacy bundle ID migrations). Thanks @thewilloftheshadow.</li>
<li>macOS: limit project-local <code>node_modules/.bin</code> PATH preference to debug builds (reduce PATH hijacking risk).</li>
<li>macOS: keep custom SSH usernames in remote target. (#2046) Thanks @algal.</li>
<li>macOS: avoid crash when rendering code blocks by bumping Textual to 0.3.1. (#2033) Thanks @garricn.</li>
<li>Update: ignore dist/control-ui for dirty checks and restore after ui builds. (#1976) Thanks @Glucksberg.</li>
<li>Build: bundle A2UI assets during build and stop tracking generated bundles. (#2455) Thanks @0oAstro.</li>
<li>CI: increase Node heap size for macOS checks. (#1890) Thanks @realZachi.</li>
<li>Config: apply config.env before ${VAR} substitution. (#1813) Thanks @spanishflu-est1918.</li>
<li>Gateway: prefer newest session metadata when combining stores. (#1823) Thanks @emanuelst.</li>
<li>Docs: tighten Fly private deployment steps. (#2289) Thanks @dguido.</li>
<li>Docs: add migration guide for moving to a new machine. (#2381)</li>
<li>Docs: add Northflank one-click deployment guide. (#2167) Thanks @AdeboyeDN.</li>
<li>Docs: add Vercel AI Gateway to providers sidebar. (#1901) Thanks @jerilynzheng.</li>
<li>Docs: add Render deployment guide. (#1975) Thanks @anurag.</li>
<li>Docs: add Claude Max API Proxy guide. (#1875) Thanks @atalovesyou.</li>
<li>Docs: add DigitalOcean deployment guide. (#1870) Thanks @0xJonHoldsCrypto.</li>
<li>Docs: add Oracle Cloud (OCI) platform guide + cross-links. (#2333) Thanks @hirefrank.</li>
<li>Docs: add Raspberry Pi install guide. (#1871) Thanks @0xJonHoldsCrypto.</li>
<li>Docs: add GCP Compute Engine deployment guide. (#1848) Thanks @hougangdev.</li>
<li>Docs: add LINE channel guide. Thanks @thewilloftheshadow.</li>
<li>Docs: credit both contributors for Control UI refresh. (#1852) Thanks @EnzeD.</li>
<li>Docs: keep docs header sticky so navbar stays visible while scrolling. (#2445) Thanks @chenyuan99.</li>
<li>Docs: update exe.dev install instructions. (#https://github.com/openclaw/openclaw/pull/3047) Thanks @zackerthescar.</li>
</ul>
<h3>Breaking</h3>
<ul>
<li><strong>BREAKING:</strong> Gateway auth mode "none" is removed; gateway now requires token/password (Tailscale Serve identity still allowed).</li>
</ul>
<h3>Fixes</h3>
<ul>
<li>Telegram: avoid silent empty replies by tracking normalization skips before fallback. (#3796)</li>
<li>Mentions: honor mentionPatterns even when explicit mentions are present. (#3303) Thanks @HirokiKobayashi-R.</li>
<li>Discord: restore username directory lookup in target resolution. (#3131) Thanks @bonald.</li>
<li>Agents: align MiniMax base URL test expectation with default provider config. (#3131) Thanks @bonald.</li>
<li>Agents: prevent retries on oversized image errors and surface size limits. (#2871) Thanks @Suksham-sharma.</li>
<li>Agents: inherit provider baseUrl/api for inline models. (#2740) Thanks @lploc94.</li>
<li>Memory Search: keep auto provider model defaults and only include remote when configured. (#2576) Thanks @papago2355.</li>
<li>Telegram: include AccountId in native command context for multi-agent routing. (#2942) Thanks @Chloe-VP.</li>
<li>Telegram: handle video note attachments in media extraction. (#2905) Thanks @mylukin.</li>
<li>TTS: read OPENAI_TTS_BASE_URL at runtime instead of module load to honor config.env. (#3341) Thanks @hclsys.</li>
<li>macOS: auto-scroll to bottom when sending a new message while scrolled up. (#2471) Thanks @kennyklee.</li>
<li>Web UI: auto-expand the chat compose textarea while typing (with sensible max height). (#2950) Thanks @shivamraut101.</li>
<li>Gateway: prevent crashes on transient network errors (fetch failures, timeouts, DNS). Added fatal error detection to only exit on truly critical errors. Fixes #2895, #2879, #2873. (#2980) Thanks @elliotsecops.</li>
<li>Agents: guard channel tool listActions to avoid plugin crashes. (#2859) Thanks @mbelinky.</li>
<li>Discord: stop resolveDiscordTarget from passing directory params into messaging target parsers. Fixes #3167. Thanks @thewilloftheshadow.</li>
<li>Discord: avoid resolving bare channel names to user DMs when a username matches. Thanks @thewilloftheshadow.</li>
<li>Discord: fix directory config type import for target resolution. Thanks @thewilloftheshadow.</li>
<li>Providers: update MiniMax API endpoint and compatibility mode. (#3064) Thanks @hlbbbbbbb.</li>
<li>Telegram: treat more network errors as recoverable in polling. (#3013) Thanks @ryancontent.</li>
<li>Discord: resolve usernames to user IDs for outbound messages. (#2649) Thanks @nonggialiang.</li>
<li>Providers: update Moonshot Kimi model references to kimi-k2.5. (#2762) Thanks @MarvinCui.</li>
<li>Gateway: suppress AbortError and transient network errors in unhandled rejections. (#2451) Thanks @Glucksberg.</li>
<li>TTS: keep /tts status replies on text-only commands and avoid duplicate block-stream audio. (#2451) Thanks @Glucksberg.</li>
<li>Security: pin npm overrides to keep tar@7.5.4 for install toolchains.</li>
<li>Security: properly test Windows ACL audit for config includes. (#2403) Thanks @dominicnunez.</li>
<li>CLI: recognize versioned Node executables when parsing argv. (#2490) Thanks @David-Marsh-Photo.</li>
<li>CLI: avoid prompting for gateway runtime under the spinner. (#2874)</li>
<li>BlueBubbles: coalesce inbound URL link preview messages. (#1981) Thanks @tyler6204.</li>
<li>Cron: allow payloads containing "heartbeat" in event filter. (#2219) Thanks @dwfinkelstein.</li>
<li>CLI: avoid loading config for global help/version while registering plugin commands. (#2212) Thanks @dial481.</li>
<li>Agents: include memory.md when bootstrapping memory context. (#2318) Thanks @czekaj.</li>
<li>Agents: release session locks on process termination and cover more signals. (#2483) Thanks @janeexai.</li>
<li>Agents: skip cooldowned providers during model failover. (#2143) Thanks @YiWang24.</li>
<li>Telegram: harden polling + retry behavior for transient network errors and Node 22 transport issues. (#2420) Thanks @techboss.</li>
<li>Telegram: ignore non-forum group message_thread_id while preserving DM thread sessions. (#2731) Thanks @dylanneve1.</li>
<li>Telegram: wrap reasoning italics per line to avoid raw underscores. (#2181) Thanks @YuriNachos.</li>
<li>Telegram: centralize API error logging for delivery and bot calls. (#2492) Thanks @altryne.</li>
<li>Voice Call: enforce Twilio webhook signature verification for ngrok URLs; disable ngrok free tier bypass by default.</li>
<li>Security: harden Tailscale Serve auth by validating identity via local tailscaled before trusting headers.</li>
<li>Media: fix text attachment MIME misclassification with CSV/TSV inference and UTF-16 detection; add XML attribute escaping for file output. (#3628) Thanks @frankekn.</li>
<li>Build: align memory-core peer dependency with lockfile.</li>
<li>Security: add mDNS discovery mode with minimal default to reduce information disclosure. (#1882) Thanks @orlyjamie.</li>
<li>Security: harden URL fetches with DNS pinning to reduce rebinding risk. Thanks Chris Zheng.</li>
<li>Web UI: improve WebChat image paste previews and allow image-only sends. (#1925) Thanks @smartprogrammer93.</li>
<li>Security: wrap external hook content by default with a per-hook opt-out. (#1827) Thanks @mertcicekci0.</li>
<li>Gateway: default auth now fail-closed (token/password required; Tailscale Serve identity remains allowed).</li>
<li>Gateway: treat loopback + non-local Host connections as remote unless trusted proxy headers are present.</li>
<li>Onboarding: remove unsupported gateway auth "off" choice from onboarding/configure flows and CLI flags.</li>
</ul>
<p><a href="https://github.com/openclaw/openclaw/blob/main/CHANGELOG.md">View full changelog</a></p>
]]></description>
<enclosure url="https://github.com/openclaw/openclaw/releases/download/v2026.1.29/OpenClaw-2026.1.29.zip" length="22458204" type="application/octet-stream" sparkle:edSignature="HqHwZHQyG/CEfBuQnQ/RffJQPKpSbCVrho9C6rgt93S5ek4AH6hUhB3BBKY8sbX1IVFATKK5QZZNE0YPAf7eBw=="/>
</item>
</channel>
</rss>

View File

@@ -21,8 +21,8 @@ android {
applicationId = "ai.openclaw.android"
minSdk = 31
targetSdk = 36
versionCode = 202602030
versionName = "2026.2.3"
versionCode = 202602010
versionName = "2026.2.1"
}
buildTypes {

View File

@@ -19,9 +19,9 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>2026.2.3</string>
<string>2026.2.1</string>
<key>CFBundleVersion</key>
<string>20260202</string>
<string>20260201</string>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoadsInWebContent</key>

View File

@@ -17,8 +17,8 @@
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>2026.2.3</string>
<string>2026.2.1</string>
<key>CFBundleVersion</key>
<string>20260202</string>
<string>20260201</string>
</dict>
</plist>

View File

@@ -81,8 +81,8 @@ targets:
properties:
CFBundleDisplayName: OpenClaw
CFBundleIconName: AppIcon
CFBundleShortVersionString: "2026.2.3"
CFBundleVersion: "20260202"
CFBundleShortVersionString: "2026.2.1"
CFBundleVersion: "20260201"
UILaunchScreen: {}
UIApplicationSceneManifest:
UIApplicationSupportsMultipleScenes: false
@@ -130,5 +130,5 @@ targets:
path: Tests/Info.plist
properties:
CFBundleDisplayName: OpenClawTests
CFBundleShortVersionString: "2026.2.3"
CFBundleVersion: "20260202"
CFBundleShortVersionString: "2026.2.1"
CFBundleVersion: "20260201"

View File

@@ -20,11 +20,9 @@ extension CronJobEditor {
self.wakeMode = job.wakeMode
switch job.schedule {
case let .at(at):
case let .at(atMs):
self.scheduleKind = .at
if let date = CronSchedule.parseAtDate(at) {
self.atDate = date
}
self.atDate = Date(timeIntervalSince1970: TimeInterval(atMs) / 1000)
case let .every(everyMs, _):
self.scheduleKind = .every
self.everyText = self.formatDuration(ms: everyMs)
@@ -38,22 +36,19 @@ extension CronJobEditor {
case let .systemEvent(text):
self.payloadKind = .systemEvent
self.systemEventText = text
case let .agentTurn(message, thinking, timeoutSeconds, _, _, _, _):
case let .agentTurn(message, thinking, timeoutSeconds, deliver, channel, to, bestEffortDeliver):
self.payloadKind = .agentTurn
self.agentMessage = message
self.thinking = thinking ?? ""
self.timeoutSeconds = timeoutSeconds.map(String.init) ?? ""
self.deliver = deliver ?? false
let trimmed = (channel ?? "").trimmingCharacters(in: .whitespacesAndNewlines)
self.channel = trimmed.isEmpty ? "last" : trimmed
self.to = to ?? ""
self.bestEffortDeliver = bestEffortDeliver ?? false
}
if let delivery = job.delivery {
self.deliveryMode = delivery.mode == .announce ? .announce : .none
let trimmed = (delivery.channel ?? "").trimmingCharacters(in: .whitespacesAndNewlines)
self.channel = trimmed.isEmpty ? "last" : trimmed
self.to = delivery.to ?? ""
self.bestEffortDeliver = delivery.bestEffort ?? false
} else if self.sessionTarget == .isolated {
self.deliveryMode = .announce
}
self.postPrefix = job.isolation?.postToMainPrefix ?? "Cron"
}
func save() {
@@ -93,29 +88,15 @@ extension CronJobEditor {
}
if self.sessionTarget == .isolated {
root["delivery"] = self.buildDelivery()
let trimmed = self.postPrefix.trimmingCharacters(in: .whitespacesAndNewlines)
root["isolation"] = [
"postToMainPrefix": trimmed.isEmpty ? "Cron" : trimmed,
]
}
return root.mapValues { AnyCodable($0) }
}
func buildDelivery() -> [String: Any] {
let mode = self.deliveryMode == .announce ? "announce" : "none"
var delivery: [String: Any] = ["mode": mode]
if self.deliveryMode == .announce {
let trimmed = self.channel.trimmingCharacters(in: .whitespacesAndNewlines)
delivery["channel"] = trimmed.isEmpty ? "last" : trimmed
let to = self.to.trimmingCharacters(in: .whitespacesAndNewlines)
if !to.isEmpty { delivery["to"] = to }
if self.bestEffortDeliver {
delivery["bestEffort"] = true
} else if self.job?.delivery?.bestEffort == true {
delivery["bestEffort"] = false
}
}
return delivery
}
func trimmed(_ value: String) -> String {
value.trimmingCharacters(in: .whitespacesAndNewlines)
}
@@ -134,7 +115,7 @@ extension CronJobEditor {
func buildSchedule() throws -> [String: Any] {
switch self.scheduleKind {
case .at:
return ["kind": "at", "at": CronSchedule.formatIsoDate(self.atDate)]
return ["kind": "at", "atMs": Int(self.atDate.timeIntervalSince1970 * 1000)]
case .every:
guard let ms = Self.parseDurationMs(self.everyText) else {
throw NSError(
@@ -228,6 +209,14 @@ extension CronJobEditor {
let thinking = self.thinking.trimmingCharacters(in: .whitespacesAndNewlines)
if !thinking.isEmpty { payload["thinking"] = thinking }
if let n = Int(self.timeoutSeconds), n > 0 { payload["timeoutSeconds"] = n }
payload["deliver"] = self.deliver
if self.deliver {
let trimmed = self.channel.trimmingCharacters(in: .whitespacesAndNewlines)
payload["channel"] = trimmed.isEmpty ? "last" : trimmed
let to = self.to.trimmingCharacters(in: .whitespacesAndNewlines)
if !to.isEmpty { payload["to"] = to }
payload["bestEffortDeliver"] = self.bestEffortDeliver
}
return payload
}

View File

@@ -13,12 +13,13 @@ extension CronJobEditor {
self.payloadKind = .agentTurn
self.agentMessage = "Run diagnostic"
self.deliveryMode = .announce
self.deliver = true
self.channel = "last"
self.to = "+15551230000"
self.thinking = "low"
self.timeoutSeconds = "90"
self.bestEffortDeliver = true
self.postPrefix = "Cron"
_ = self.buildAgentTurnPayload()
_ = try? self.buildPayload()

View File

@@ -16,13 +16,16 @@ struct CronJobEditor: View {
+ "Use an isolated session for agent turns so your main chat stays clean."
static let sessionTargetNote =
"Main jobs post a system event into the current main session. "
+ "Isolated jobs run OpenClaw in a dedicated session and can announce results to a channel."
+ "Isolated jobs run OpenClaw in a dedicated session and can deliver results (WhatsApp/Telegram/Discord/etc)."
static let scheduleKindNote =
"“At” runs once, “Every” repeats with a duration, “Cron” uses a 5-field Unix expression."
static let isolatedPayloadNote =
"Isolated jobs always run an agent turn. Announce sends a short summary to a channel."
"Isolated jobs always run an agent turn. The result can be delivered to a channel, "
+ "and a short summary is posted back to your main chat."
static let mainPayloadNote =
"System events are injected into the current main session. Agent turns require an isolated session target."
static let mainSummaryNote =
"Controls the label used when posting the completion summary back to the main session."
@State var name: String = ""
@State var description: String = ""
@@ -43,13 +46,13 @@ struct CronJobEditor: View {
@State var payloadKind: PayloadKind = .systemEvent
@State var systemEventText: String = ""
@State var agentMessage: String = ""
enum DeliveryChoice: String, CaseIterable, Identifiable { case announce, none; var id: String { rawValue } }
@State var deliveryMode: DeliveryChoice = .announce
@State var deliver: Bool = false
@State var channel: String = "last"
@State var to: String = ""
@State var thinking: String = ""
@State var timeoutSeconds: String = ""
@State var bestEffortDeliver: Bool = false
@State var postPrefix: String = "Cron"
var channelOptions: [String] {
let ordered = self.channelsStore.orderedChannelIds()
@@ -245,6 +248,27 @@ struct CronJobEditor: View {
}
}
if self.sessionTarget == .isolated {
GroupBox("Main session summary") {
Grid(alignment: .leadingFirstTextBaseline, horizontalSpacing: 14, verticalSpacing: 10) {
GridRow {
self.gridLabel("Prefix")
TextField("Cron", text: self.$postPrefix)
.textFieldStyle(.roundedBorder)
.frame(maxWidth: .infinity)
}
GridRow {
Color.clear
.frame(width: self.labelColumnWidth, height: 1)
Text(
Self.mainSummaryNote)
.font(.footnote)
.foregroundStyle(.secondary)
.frame(maxWidth: .infinity, alignment: .leading)
}
}
}
}
}
.frame(maxWidth: .infinity, alignment: .leading)
.padding(.vertical, 2)
@@ -316,17 +340,13 @@ struct CronJobEditor: View {
.frame(width: 180, alignment: .leading)
}
GridRow {
self.gridLabel("Delivery")
Picker("", selection: self.$deliveryMode) {
Text("Announce summary").tag(DeliveryChoice.announce)
Text("None").tag(DeliveryChoice.none)
}
.labelsHidden()
.pickerStyle(.segmented)
self.gridLabel("Deliver")
Toggle("Deliver result to a channel", isOn: self.$deliver)
.toggleStyle(.switch)
}
}
if self.deliveryMode == .announce {
if self.deliver {
Grid(alignment: .leadingFirstTextBaseline, horizontalSpacing: 14, verticalSpacing: 10) {
GridRow {
self.gridLabel("Channel")
@@ -347,7 +367,7 @@ struct CronJobEditor: View {
}
GridRow {
self.gridLabel("Best-effort")
Toggle("Do not fail the job if announce fails", isOn: self.$bestEffortDeliver)
Toggle("Do not fail the job if delivery fails", isOn: self.$bestEffortDeliver)
.toggleStyle(.switch)
}
}

View File

@@ -14,26 +14,12 @@ enum CronWakeMode: String, CaseIterable, Identifiable, Codable {
var id: String { self.rawValue }
}
enum CronDeliveryMode: String, CaseIterable, Identifiable, Codable {
case none
case announce
var id: String { self.rawValue }
}
struct CronDelivery: Codable, Equatable {
var mode: CronDeliveryMode
var channel: String?
var to: String?
var bestEffort: Bool?
}
enum CronSchedule: Codable, Equatable {
case at(at: String)
case at(atMs: Int)
case every(everyMs: Int, anchorMs: Int?)
case cron(expr: String, tz: String?)
enum CodingKeys: String, CodingKey { case kind, at, atMs, everyMs, anchorMs, expr, tz }
enum CodingKeys: String, CodingKey { case kind, atMs, everyMs, anchorMs, expr, tz }
var kind: String {
switch self {
@@ -48,21 +34,7 @@ enum CronSchedule: Codable, Equatable {
let kind = try container.decode(String.self, forKey: .kind)
switch kind {
case "at":
if let at = try container.decodeIfPresent(String.self, forKey: .at),
!at.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
{
self = .at(at: at)
return
}
if let atMs = try container.decodeIfPresent(Int.self, forKey: .atMs) {
let date = Date(timeIntervalSince1970: TimeInterval(atMs) / 1000)
self = .at(at: Self.formatIsoDate(date))
return
}
throw DecodingError.dataCorruptedError(
forKey: .at,
in: container,
debugDescription: "Missing schedule.at")
self = try .at(atMs: container.decode(Int.self, forKey: .atMs))
case "every":
self = try .every(
everyMs: container.decode(Int.self, forKey: .everyMs),
@@ -83,8 +55,8 @@ enum CronSchedule: Codable, Equatable {
var container = encoder.container(keyedBy: CodingKeys.self)
try container.encode(self.kind, forKey: .kind)
switch self {
case let .at(at):
try container.encode(at, forKey: .at)
case let .at(atMs):
try container.encode(atMs, forKey: .atMs)
case let .every(everyMs, anchorMs):
try container.encode(everyMs, forKey: .everyMs)
try container.encodeIfPresent(anchorMs, forKey: .anchorMs)
@@ -93,29 +65,6 @@ enum CronSchedule: Codable, Equatable {
try container.encodeIfPresent(tz, forKey: .tz)
}
}
static func parseAtDate(_ value: String) -> Date? {
let trimmed = value.trimmingCharacters(in: .whitespacesAndNewlines)
if trimmed.isEmpty { return nil }
if let date = isoFormatterWithFractional.date(from: trimmed) { return date }
return isoFormatter.date(from: trimmed)
}
static func formatIsoDate(_ date: Date) -> String {
isoFormatter.string(from: date)
}
private static let isoFormatter: ISO8601DateFormatter = {
let formatter = ISO8601DateFormatter()
formatter.formatOptions = [.withInternetDateTime]
return formatter
}()
private static let isoFormatterWithFractional: ISO8601DateFormatter = {
let formatter = ISO8601DateFormatter()
formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
return formatter
}()
}
enum CronPayload: Codable, Equatable {
@@ -182,6 +131,10 @@ enum CronPayload: Codable, Equatable {
}
}
struct CronIsolation: Codable, Equatable {
var postToMainPrefix: String?
}
struct CronJobState: Codable, Equatable {
var nextRunAtMs: Int?
var runningAtMs: Int?
@@ -204,7 +157,7 @@ struct CronJob: Identifiable, Codable, Equatable {
let sessionTarget: CronSessionTarget
let wakeMode: CronWakeMode
let payload: CronPayload
let delivery: CronDelivery?
let isolation: CronIsolation?
let state: CronJobState
var displayName: String {

View File

@@ -17,11 +17,9 @@ extension CronSettings {
func scheduleSummary(_ schedule: CronSchedule) -> String {
switch schedule {
case let .at(at):
if let date = CronSchedule.parseAtDate(at) {
return "at \(date.formatted(date: .abbreviated, time: .standard))"
}
return "at \(at)"
case let .at(atMs):
let date = Date(timeIntervalSince1970: TimeInterval(atMs) / 1000)
return "at \(date.formatted(date: .abbreviated, time: .standard))"
case let .every(everyMs, _):
return "every \(self.formatDuration(ms: everyMs))"
case let .cron(expr, tz):

View File

@@ -128,7 +128,7 @@ extension CronSettings {
.foregroundStyle(.orange)
.textSelection(.enabled)
}
self.payloadSummary(job)
self.payloadSummary(job.payload)
}
.frame(maxWidth: .infinity, alignment: .leading)
.padding(10)
@@ -205,8 +205,7 @@ extension CronSettings {
.padding(.vertical, 4)
}
func payloadSummary(_ job: CronJob) -> some View {
let payload = job.payload
func payloadSummary(_ payload: CronPayload) -> some View {
VStack(alignment: .leading, spacing: 6) {
Text("Payload")
.font(.caption.weight(.semibold))
@@ -216,7 +215,7 @@ extension CronSettings {
Text(text)
.font(.callout)
.textSelection(.enabled)
case let .agentTurn(message, thinking, timeoutSeconds, _, _, _, _):
case let .agentTurn(message, thinking, timeoutSeconds, deliver, provider, to, _):
VStack(alignment: .leading, spacing: 4) {
Text(message)
.font(.callout)
@@ -224,19 +223,10 @@ extension CronSettings {
HStack(spacing: 8) {
if let thinking, !thinking.isEmpty { StatusPill(text: "think \(thinking)", tint: .secondary) }
if let timeoutSeconds { StatusPill(text: "\(timeoutSeconds)s", tint: .secondary) }
if job.sessionTarget == .isolated {
let delivery = job.delivery
if let delivery {
if delivery.mode == .announce {
StatusPill(text: "announce", tint: .secondary)
if let channel = delivery.channel, !channel.isEmpty {
StatusPill(text: channel, tint: .secondary)
}
if let to = delivery.to, !to.isEmpty { StatusPill(text: to, tint: .secondary) }
} else {
StatusPill(text: "no delivery", tint: .secondary)
}
}
if deliver ?? false {
StatusPill(text: "deliver", tint: .secondary)
if let provider, !provider.isEmpty { StatusPill(text: provider, tint: .secondary) }
if let to, !to.isEmpty { StatusPill(text: to, tint: .secondary) }
}
}
}

View File

@@ -21,11 +21,11 @@ struct CronSettings_Previews: PreviewProvider {
message: "Summarize inbox",
thinking: "low",
timeoutSeconds: 600,
deliver: nil,
channel: nil,
deliver: true,
channel: "last",
to: nil,
bestEffortDeliver: nil),
delivery: CronDelivery(mode: .announce, channel: "last", to: nil, bestEffort: true),
bestEffortDeliver: true),
isolation: CronIsolation(postToMainPrefix: "Cron"),
state: CronJobState(
nextRunAtMs: Int(Date().addingTimeInterval(3600).timeIntervalSince1970 * 1000),
runningAtMs: nil,
@@ -75,11 +75,11 @@ extension CronSettings {
message: "Summarize",
thinking: "low",
timeoutSeconds: 120,
deliver: nil,
channel: nil,
to: nil,
bestEffortDeliver: nil),
delivery: CronDelivery(mode: .announce, channel: "whatsapp", to: "+15551234567", bestEffort: true),
deliver: true,
channel: "whatsapp",
to: "+15551234567",
bestEffortDeliver: true),
isolation: CronIsolation(postToMainPrefix: "[cron] "),
state: CronJobState(
nextRunAtMs: 1_700_000_200_000,
runningAtMs: nil,
@@ -111,7 +111,7 @@ extension CronSettings {
_ = view.detailCard(job)
_ = view.runHistoryCard(job)
_ = view.runRow(run)
_ = view.payloadSummary(job)
_ = view.payloadSummary(job.payload)
_ = view.scheduleSummary(job.schedule)
_ = view.statusTint(job.state.lastStatus)
_ = view.nextRunLabel(Date())

View File

@@ -15,9 +15,9 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>2026.2.3</string>
<string>2026.2.1</string>
<key>CFBundleVersion</key>
<string>202602020</string>
<string>202602010</string>
<key>CFBundleIconFile</key>
<string>OpenClaw</string>
<key>CFBundleURLTypes</key>

View File

@@ -589,24 +589,20 @@ public struct AgentIdentityResult: Codable, Sendable {
public let agentid: String
public let name: String?
public let avatar: String?
public let emoji: String?
public init(
agentid: String,
name: String?,
avatar: String?,
emoji: String?
avatar: String?
) {
self.agentid = agentid
self.name = name
self.avatar = avatar
self.emoji = emoji
}
private enum CodingKeys: String, CodingKey {
case agentid = "agentId"
case name
case avatar
case emoji
}
}
@@ -1560,157 +1556,6 @@ public struct AgentSummary: Codable, Sendable {
}
}
public struct AgentsFileEntry: Codable, Sendable {
public let name: String
public let path: String
public let missing: Bool
public let size: Int?
public let updatedatms: Int?
public let content: String?
public init(
name: String,
path: String,
missing: Bool,
size: Int?,
updatedatms: Int?,
content: String?
) {
self.name = name
self.path = path
self.missing = missing
self.size = size
self.updatedatms = updatedatms
self.content = content
}
private enum CodingKeys: String, CodingKey {
case name
case path
case missing
case size
case updatedatms = "updatedAtMs"
case content
}
}
public struct AgentsFilesListParams: Codable, Sendable {
public let agentid: String
public init(
agentid: String
) {
self.agentid = agentid
}
private enum CodingKeys: String, CodingKey {
case agentid = "agentId"
}
}
public struct AgentsFilesListResult: Codable, Sendable {
public let agentid: String
public let workspace: String
public let files: [AgentsFileEntry]
public init(
agentid: String,
workspace: String,
files: [AgentsFileEntry]
) {
self.agentid = agentid
self.workspace = workspace
self.files = files
}
private enum CodingKeys: String, CodingKey {
case agentid = "agentId"
case workspace
case files
}
}
public struct AgentsFilesGetParams: Codable, Sendable {
public let agentid: String
public let name: String
public init(
agentid: String,
name: String
) {
self.agentid = agentid
self.name = name
}
private enum CodingKeys: String, CodingKey {
case agentid = "agentId"
case name
}
}
public struct AgentsFilesGetResult: Codable, Sendable {
public let agentid: String
public let workspace: String
public let file: AgentsFileEntry
public init(
agentid: String,
workspace: String,
file: AgentsFileEntry
) {
self.agentid = agentid
self.workspace = workspace
self.file = file
}
private enum CodingKeys: String, CodingKey {
case agentid = "agentId"
case workspace
case file
}
}
public struct AgentsFilesSetParams: Codable, Sendable {
public let agentid: String
public let name: String
public let content: String
public init(
agentid: String,
name: String,
content: String
) {
self.agentid = agentid
self.name = name
self.content = content
}
private enum CodingKeys: String, CodingKey {
case agentid = "agentId"
case name
case content
}
}
public struct AgentsFilesSetResult: Codable, Sendable {
public let ok: Bool
public let agentid: String
public let workspace: String
public let file: AgentsFileEntry
public init(
ok: Bool,
agentid: String,
workspace: String,
file: AgentsFileEntry
) {
self.ok = ok
self.agentid = agentid
self.workspace = workspace
self.file = file
}
private enum CodingKeys: String, CodingKey {
case ok
case agentid = "agentId"
case workspace
case file
}
}
public struct AgentsListParams: Codable, Sendable {
}
@@ -1785,16 +1630,6 @@ public struct ModelsListResult: Codable, Sendable {
}
public struct SkillsStatusParams: Codable, Sendable {
public let agentid: String?
public init(
agentid: String?
) {
self.agentid = agentid
}
private enum CodingKeys: String, CodingKey {
case agentid = "agentId"
}
}
public struct SkillsBinsParams: Codable, Sendable {
@@ -1872,7 +1707,7 @@ public struct CronJob: Codable, Sendable {
public let sessiontarget: AnyCodable
public let wakemode: AnyCodable
public let payload: AnyCodable
public let delivery: [String: AnyCodable]?
public let isolation: [String: AnyCodable]?
public let state: [String: AnyCodable]
public init(
@@ -1888,7 +1723,7 @@ public struct CronJob: Codable, Sendable {
sessiontarget: AnyCodable,
wakemode: AnyCodable,
payload: AnyCodable,
delivery: [String: AnyCodable]?,
isolation: [String: AnyCodable]?,
state: [String: AnyCodable]
) {
self.id = id
@@ -1903,7 +1738,7 @@ public struct CronJob: Codable, Sendable {
self.sessiontarget = sessiontarget
self.wakemode = wakemode
self.payload = payload
self.delivery = delivery
self.isolation = isolation
self.state = state
}
private enum CodingKeys: String, CodingKey {
@@ -1919,7 +1754,7 @@ public struct CronJob: Codable, Sendable {
case sessiontarget = "sessionTarget"
case wakemode = "wakeMode"
case payload
case delivery
case isolation
case state
}
}
@@ -1950,7 +1785,7 @@ public struct CronAddParams: Codable, Sendable {
public let sessiontarget: AnyCodable
public let wakemode: AnyCodable
public let payload: AnyCodable
public let delivery: [String: AnyCodable]?
public let isolation: [String: AnyCodable]?
public init(
name: String,
@@ -1962,7 +1797,7 @@ public struct CronAddParams: Codable, Sendable {
sessiontarget: AnyCodable,
wakemode: AnyCodable,
payload: AnyCodable,
delivery: [String: AnyCodable]?
isolation: [String: AnyCodable]?
) {
self.name = name
self.agentid = agentid
@@ -1973,7 +1808,7 @@ public struct CronAddParams: Codable, Sendable {
self.sessiontarget = sessiontarget
self.wakemode = wakemode
self.payload = payload
self.delivery = delivery
self.isolation = isolation
}
private enum CodingKeys: String, CodingKey {
case name
@@ -1985,7 +1820,7 @@ public struct CronAddParams: Codable, Sendable {
case sessiontarget = "sessionTarget"
case wakemode = "wakeMode"
case payload
case delivery
case isolation
}
}

View File

@@ -40,11 +40,11 @@ struct CronJobEditorSmokeTests {
message: "Summarize the last day",
thinking: "low",
timeoutSeconds: 120,
deliver: nil,
channel: nil,
to: nil,
bestEffortDeliver: nil),
delivery: CronDelivery(mode: .announce, channel: "whatsapp", to: "+15551234567", bestEffort: true),
deliver: true,
channel: "whatsapp",
to: "+15551234567",
bestEffortDeliver: true),
isolation: CronIsolation(postToMainPrefix: "Cron"),
state: CronJobState(
nextRunAtMs: 1_700_000_100_000,
runningAtMs: nil,

View File

@@ -5,24 +5,12 @@ import Testing
@Suite
struct CronModelsTests {
@Test func scheduleAtEncodesAndDecodes() throws {
let schedule = CronSchedule.at(at: "2026-02-03T18:00:00Z")
let schedule = CronSchedule.at(atMs: 123)
let data = try JSONEncoder().encode(schedule)
let decoded = try JSONDecoder().decode(CronSchedule.self, from: data)
#expect(decoded == schedule)
}
@Test func scheduleAtDecodesLegacyAtMs() throws {
let json = """
{"kind":"at","atMs":1700000000000}
"""
let decoded = try JSONDecoder().decode(CronSchedule.self, from: Data(json.utf8))
if case let .at(at) = decoded {
#expect(at.hasPrefix("2023-"))
} else {
#expect(Bool(false))
}
}
@Test func scheduleEveryEncodesAndDecodesWithAnchor() throws {
let schedule = CronSchedule.every(everyMs: 5000, anchorMs: 10000)
let data = try JSONEncoder().encode(schedule)
@@ -61,11 +49,11 @@ struct CronModelsTests {
deleteAfterRun: true,
createdAtMs: 0,
updatedAtMs: 0,
schedule: .at(at: "2026-02-03T18:00:00Z"),
schedule: .at(atMs: 1_700_000_000_000),
sessionTarget: .main,
wakeMode: .now,
payload: .systemEvent(text: "ping"),
delivery: nil,
isolation: nil,
state: CronJobState())
let data = try JSONEncoder().encode(job)
let decoded = try JSONDecoder().decode(CronJob.self, from: data)
@@ -74,7 +62,7 @@ struct CronModelsTests {
@Test func scheduleDecodeRejectsUnknownKind() {
let json = """
{"kind":"wat","at":"2026-02-03T18:00:00Z"}
{"kind":"wat","atMs":1}
"""
#expect(throws: DecodingError.self) {
_ = try JSONDecoder().decode(CronSchedule.self, from: Data(json.utf8))
@@ -100,11 +88,11 @@ struct CronModelsTests {
deleteAfterRun: nil,
createdAtMs: 0,
updatedAtMs: 0,
schedule: .at(at: "2026-02-03T18:00:00Z"),
schedule: .at(atMs: 0),
sessionTarget: .main,
wakeMode: .now,
payload: .systemEvent(text: "hi"),
delivery: nil,
isolation: nil,
state: CronJobState())
#expect(base.displayName == "hello")
@@ -123,11 +111,11 @@ struct CronModelsTests {
deleteAfterRun: nil,
createdAtMs: 0,
updatedAtMs: 0,
schedule: .at(at: "2026-02-03T18:00:00Z"),
schedule: .at(atMs: 0),
sessionTarget: .main,
wakeMode: .now,
payload: .systemEvent(text: "hi"),
delivery: nil,
isolation: nil,
state: CronJobState(
nextRunAtMs: 1_700_000_000_000,
runningAtMs: nil,

View File

@@ -23,7 +23,7 @@ struct SettingsViewSmokeTests {
sessionTarget: .main,
wakeMode: .now,
payload: .systemEvent(text: "ping"),
delivery: nil,
isolation: nil,
state: CronJobState(
nextRunAtMs: 1_700_000_200_000,
runningAtMs: nil,
@@ -48,11 +48,11 @@ struct SettingsViewSmokeTests {
message: "hello",
thinking: "low",
timeoutSeconds: 30,
deliver: nil,
channel: nil,
to: nil,
bestEffortDeliver: nil),
delivery: CronDelivery(mode: .announce, channel: "sms", to: "+15551234567", bestEffort: true),
deliver: true,
channel: "sms",
to: "+15551234567",
bestEffortDeliver: true),
isolation: CronIsolation(postToMainPrefix: "[cron] "),
state: CronJobState(
nextRunAtMs: nil,
runningAtMs: nil,

View File

@@ -589,24 +589,20 @@ public struct AgentIdentityResult: Codable, Sendable {
public let agentid: String
public let name: String?
public let avatar: String?
public let emoji: String?
public init(
agentid: String,
name: String?,
avatar: String?,
emoji: String?
avatar: String?
) {
self.agentid = agentid
self.name = name
self.avatar = avatar
self.emoji = emoji
}
private enum CodingKeys: String, CodingKey {
case agentid = "agentId"
case name
case avatar
case emoji
}
}
@@ -1560,157 +1556,6 @@ public struct AgentSummary: Codable, Sendable {
}
}
public struct AgentsFileEntry: Codable, Sendable {
public let name: String
public let path: String
public let missing: Bool
public let size: Int?
public let updatedatms: Int?
public let content: String?
public init(
name: String,
path: String,
missing: Bool,
size: Int?,
updatedatms: Int?,
content: String?
) {
self.name = name
self.path = path
self.missing = missing
self.size = size
self.updatedatms = updatedatms
self.content = content
}
private enum CodingKeys: String, CodingKey {
case name
case path
case missing
case size
case updatedatms = "updatedAtMs"
case content
}
}
public struct AgentsFilesListParams: Codable, Sendable {
public let agentid: String
public init(
agentid: String
) {
self.agentid = agentid
}
private enum CodingKeys: String, CodingKey {
case agentid = "agentId"
}
}
public struct AgentsFilesListResult: Codable, Sendable {
public let agentid: String
public let workspace: String
public let files: [AgentsFileEntry]
public init(
agentid: String,
workspace: String,
files: [AgentsFileEntry]
) {
self.agentid = agentid
self.workspace = workspace
self.files = files
}
private enum CodingKeys: String, CodingKey {
case agentid = "agentId"
case workspace
case files
}
}
public struct AgentsFilesGetParams: Codable, Sendable {
public let agentid: String
public let name: String
public init(
agentid: String,
name: String
) {
self.agentid = agentid
self.name = name
}
private enum CodingKeys: String, CodingKey {
case agentid = "agentId"
case name
}
}
public struct AgentsFilesGetResult: Codable, Sendable {
public let agentid: String
public let workspace: String
public let file: AgentsFileEntry
public init(
agentid: String,
workspace: String,
file: AgentsFileEntry
) {
self.agentid = agentid
self.workspace = workspace
self.file = file
}
private enum CodingKeys: String, CodingKey {
case agentid = "agentId"
case workspace
case file
}
}
public struct AgentsFilesSetParams: Codable, Sendable {
public let agentid: String
public let name: String
public let content: String
public init(
agentid: String,
name: String,
content: String
) {
self.agentid = agentid
self.name = name
self.content = content
}
private enum CodingKeys: String, CodingKey {
case agentid = "agentId"
case name
case content
}
}
public struct AgentsFilesSetResult: Codable, Sendable {
public let ok: Bool
public let agentid: String
public let workspace: String
public let file: AgentsFileEntry
public init(
ok: Bool,
agentid: String,
workspace: String,
file: AgentsFileEntry
) {
self.ok = ok
self.agentid = agentid
self.workspace = workspace
self.file = file
}
private enum CodingKeys: String, CodingKey {
case ok
case agentid = "agentId"
case workspace
case file
}
}
public struct AgentsListParams: Codable, Sendable {
}
@@ -1785,16 +1630,6 @@ public struct ModelsListResult: Codable, Sendable {
}
public struct SkillsStatusParams: Codable, Sendable {
public let agentid: String?
public init(
agentid: String?
) {
self.agentid = agentid
}
private enum CodingKeys: String, CodingKey {
case agentid = "agentId"
}
}
public struct SkillsBinsParams: Codable, Sendable {
@@ -1872,7 +1707,7 @@ public struct CronJob: Codable, Sendable {
public let sessiontarget: AnyCodable
public let wakemode: AnyCodable
public let payload: AnyCodable
public let delivery: [String: AnyCodable]?
public let isolation: [String: AnyCodable]?
public let state: [String: AnyCodable]
public init(
@@ -1888,7 +1723,7 @@ public struct CronJob: Codable, Sendable {
sessiontarget: AnyCodable,
wakemode: AnyCodable,
payload: AnyCodable,
delivery: [String: AnyCodable]?,
isolation: [String: AnyCodable]?,
state: [String: AnyCodable]
) {
self.id = id
@@ -1903,7 +1738,7 @@ public struct CronJob: Codable, Sendable {
self.sessiontarget = sessiontarget
self.wakemode = wakemode
self.payload = payload
self.delivery = delivery
self.isolation = isolation
self.state = state
}
private enum CodingKeys: String, CodingKey {
@@ -1919,7 +1754,7 @@ public struct CronJob: Codable, Sendable {
case sessiontarget = "sessionTarget"
case wakemode = "wakeMode"
case payload
case delivery
case isolation
case state
}
}
@@ -1950,7 +1785,7 @@ public struct CronAddParams: Codable, Sendable {
public let sessiontarget: AnyCodable
public let wakemode: AnyCodable
public let payload: AnyCodable
public let delivery: [String: AnyCodable]?
public let isolation: [String: AnyCodable]?
public init(
name: String,
@@ -1962,7 +1797,7 @@ public struct CronAddParams: Codable, Sendable {
sessiontarget: AnyCodable,
wakemode: AnyCodable,
payload: AnyCodable,
delivery: [String: AnyCodable]?
isolation: [String: AnyCodable]?
) {
self.name = name
self.agentid = agentid
@@ -1973,7 +1808,7 @@ public struct CronAddParams: Codable, Sendable {
self.sessiontarget = sessiontarget
self.wakemode = wakemode
self.payload = payload
self.delivery = delivery
self.isolation = isolation
}
private enum CodingKeys: String, CodingKey {
case name
@@ -1985,7 +1820,7 @@ public struct CronAddParams: Codable, Sendable {
case sessiontarget = "sessionTarget"
case wakemode = "wakeMode"
case payload
case delivery
case isolation
}
}

View File

@@ -5,7 +5,7 @@
},
{
"source": "Gateway",
"target": "Gateway 网关"
"target": "Gateway网关"
},
{
"source": "Pi",
@@ -17,11 +17,11 @@
},
{
"source": "Skills config",
"target": "Skills 配置"
"target": "Skills配置"
},
{
"source": "Skills Config",
"target": "Skills 配置"
"target": "Skills配置"
},
{
"source": "local loopback",
@@ -47,22 +47,6 @@
"source": "DM",
"target": "私信"
},
{
"source": "sandbox",
"target": "沙箱"
},
{
"source": "Sandbox",
"target": "沙箱"
},
{
"source": "sandboxing",
"target": "沙箱隔离"
},
{
"source": "Sandboxing",
"target": "沙箱隔离"
},
{
"source": "sandboxed",
"target": "沙箱隔离"
@@ -71,46 +55,6 @@
"source": "Sandboxed",
"target": "沙箱隔离"
},
{
"source": "Sandboxing note",
"target": "沙箱注意事项"
},
{
"source": "Companion apps",
"target": "配套应用"
},
{
"source": "expected keys",
"target": "预期键名"
},
{
"source": "block streaming",
"target": "分块流式传输"
},
{
"source": "Block streaming",
"target": "分块流式传输"
},
{
"source": "Discovery + transports",
"target": "设备发现 + 传输协议"
},
{
"source": "Discovery",
"target": "设备发现"
},
{
"source": "Network model",
"target": "网络模型"
},
{
"source": "for full details",
"target": "了解详情"
},
{
"source": "First 60 seconds",
"target": "最初的六十秒"
},
{
"source": "Auth: where it lives (important)",
"target": "凭证:存储位置(重要)"

View File

@@ -3,10 +3,13 @@
{"cache_key":"00ee1ece05b05ab7b12cfe673000c037bb2037fe93a069a71ec2368184e83944","segment_id":"index.md:45e6d69dbe995a36","source_path":"index.md","text_hash":"45e6d69dbe995a36f7bc20755eff4eb4d2afaaedbcac4668ab62540c57219f32","text":"macOS app","translated":"macOS 应用","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:05:06Z"}
{"cache_key":"00eeb87b1774979860c4b016d48e416ab9157539c41f5f3f0c58c1deb8f075c9","segment_id":"environment.md:frontmatter:read_when:2","source_path":"environment.md:frontmatter:read_when:2","text_hash":"822b3d74ce16c1be19059fad4ca5bf7ae9327f58fa1ff4e75e78d5afa75c038f","text":"You are documenting provider auth or deployment environments","translated":"你正在记录提供商认证或部署环境的相关文档","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:15:51Z"}
{"cache_key":"01063749652c55481b7da485911a80de3049ded0257874b376efbc55a14293a7","segment_id":"start/wizard.md:037b8f564390e097","source_path":"start/wizard.md","text_hash":"037b8f564390e09742421c621a1f785d2ee5338d0c680c76f7a9b991518e909d","text":" and optional ","translated":" 和可选的 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:48:48Z"}
{"cache_key":"011732db491eea64ff252f1a211df0eee3edbf29b3839a36468aff0d600565a8","segment_id":"index.md:58d30d963f28264b","source_path":"index.md","text_hash":"58d30d963f28264bd9ba0e2d4c07c2c43c0ac1c1609c25b3fccf475eebf41727","text":"Skills config","translated":"技能配置","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:52:44Z"}
{"cache_key":"01814fd9d09399c075081056c6fa2befa388c67ba4f8745122804fd044fd82d6","segment_id":"start/getting-started.md:d1564fd156e28160","source_path":"start/getting-started.md","text_hash":"d1564fd156e28160c83922ad7a18428ce2c966e790f477e740d1d9f6cadd51e9","text":"WhatsApp (QR login)","translated":"WhatsApp二维码登录","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:37:08Z"}
{"cache_key":"019f9aef85c71dc5ed35acd441246cf7ca7e8734347c659aff797b91a593805e","segment_id":"index.md:22159a426e4f2635","source_path":"index.md","text_hash":"22159a426e4f26356382cc3ac9b2e7af5123c1309250332f5dcbbc6e6f952b0e","text":"Network model","translated":"网络 模型","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:48:28Z"}
{"cache_key":"01b87576d7ade6b91ca28935f65c167c2f4fb5d1b6bfd1189fd416b229500af4","segment_id":"start/getting-started.md:7421b911bc203f6f","source_path":"start/getting-started.md","text_hash":"7421b911bc203f6fe3c677d752379f23dc314719d39d18179406da675f58d039","text":"Scan via WhatsApp → Settings → Linked Devices.","translated":"通过 WhatsApp → 设置 → 已关联设备 进行扫描。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:37:10Z"}
{"cache_key":"01d8d8ec84ad8f4c74e29e254e56c02f7d75005160c27d99e9ce183767e16c55","segment_id":"index.md:6b8ebac7903757ce","source_path":"index.md","text_hash":"6b8ebac7903757ce7399cc729651a27e459903c24c64aa94827b20d8a2a411d2","text":"For Tailnet access, run ","translated":"如需 Tailnet 访问,请运行 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:00:08Z"}
{"cache_key":"024efbb5ac15e07c191effa78c0b23bf173c8af6725e988743ea055e9a4e8c3b","segment_id":"index.md:f9b8279bc46e847b","source_path":"index.md","text_hash":"f9b8279bc46e847bfcc47b8701fd5c5dc27baa304d5add8278a7f97925c3ec13","text":"Mattermost (plugin)","translated":"Mattermost插件","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:32:40Z"}
{"cache_key":"025574196252a6e36b88a27c440de11b7f0e0d981df3595a0aefda198b2cde9c","segment_id":"index.md:4d705f0fa835fd21","source_path":"index.md","text_hash":"4d705f0fa835fd216c4fd6dea0ee851d33720e23fb714c4c9ea74ac3211fccdc","text":"Discovery + transports","translated":"发现 + 传输","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:53:02Z"}
{"cache_key":"02d1e10492e8721462f16e39467b94ad3197e4eb76f6d671a09b4246d5b4d27b","segment_id":"start/getting-started.md:7ac362063b9f2046","source_path":"start/getting-started.md","text_hash":"7ac362063b9f204602f38f9f1ec9cf047f03e0d7b83896571c9df6d31ad41e9c","text":"Nodes","translated":"节点","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:38:28Z"}
{"cache_key":"02f39c075115bee6bdb015a49436f2b2a56365b87558fdd7aff7b17cb83bff6c","segment_id":"environment.md:frontmatter:summary","source_path":"environment.md:frontmatter:summary","text_hash":"78351223e7068721146d2de022fdf440c2866b2ee02fbbb50bf64369b999820b","text":"Where OpenClaw loads environment variables and the precedence order","translated":"OpenClaw 加载环境变量的位置及优先级顺序","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:19:12Z"}
{"cache_key":"02f4067265058ed8929f3772d87e1c5dc0af8422b8e7b513b7db155108a422c3","segment_id":"start/wizard.md:961eb43699731759","source_path":"start/wizard.md","text_hash":"961eb43699731759fd0d04f177bb24f09971bddd41426702276e761269d0a5b9","text":" does ","translated":" 会 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:40:48Z"}
@@ -16,8 +19,13 @@
{"cache_key":"0457a19cd3a82171f6cdb92d82d5a0f6358da4c1220d42d5b0575bde871e7f91","segment_id":"environment.md:e234227b0e001687","source_path":"environment.md","text_hash":"e234227b0e001687821541fac3af38fc6be293ec6e13910c6826b9afc8ca33be","text":" syntax:","translated":" 语法:","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:13:00Z"}
{"cache_key":"045fb6f3989827561e347dfa56a164069bf8b7afaa50d2d02c20ad264495d351","segment_id":"index.md:e9f63c8876aec738","source_path":"index.md","text_hash":"e9f63c8876aec7381ffb5a68efb39f50525f9fc4e732857488561516d47f5654","text":" — Uses Baileys for WhatsApp Web protocol","translated":" — 使用 Baileys 实现 WhatsApp Web 协议","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:29:31Z"}
{"cache_key":"046c83b658b7dd8bce829f07bd09dcee3413753ab72cf95d638925aa163d3486","segment_id":"start/getting-started.md:f4117324994aaad1","source_path":"start/getting-started.md","text_hash":"f4117324994aaad1d3413064ade8f2037e43ab2fac0b385d731ff154925ec3b3","text":"Windows (PowerShell):","translated":"Windows (PowerShell)","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:35:51Z"}
{"cache_key":"04b1191bfbfc3062975be3fbc5b169b9c3151d3fbce07bfffc05483c40191c76","segment_id":"environment.md:28e19c6e69c7a2aa","source_path":"environment.md","text_hash":"28e19c6e69c7a2aa071951dda3ff0a11ca178e3fb295dae8d6ed7dcc994434a4","text":" for full details.","translated":" 了解完整详情。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:13:07Z"}
{"cache_key":"04d48cfdb6b444cb4691ea55a5deb23df20694659ae1bc5e082e242e749f5e3c","segment_id":"help/index.md:bfc5930cc2660330","source_path":"help/index.md","text_hash":"bfc5930cc2660330260afd407e98d86adaec0af48dd72b88dc33ef8e9066e2c9","text":"Install sanity (Node/npm/PATH):","translated":"安装完整性检查Node/npm/PATH","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:39:38Z"}
{"cache_key":"04fee8dc5ef25d6bc83852bc30abc64dab335a974f1a9aa3528d0a463f3df80e","segment_id":"environment.md:a42cc4a7174c83a8","source_path":"environment.md","text_hash":"a42cc4a7174c83a853752b3e74cb001a234f3eca099688fdf0dd2540c60bb1e2","text":" expected keys:","translated":" 预期密钥:","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:16:53Z"}
{"cache_key":"05405710e256b2e1031234be855a7c11cf1505c627df14884d655fa42a1568a7","segment_id":"index.md:f0a7f9d068cb7a14","source_path":"index.md","text_hash":"f0a7f9d068cb7a146d0bb89b3703688d690ed0b92734b78bcdb909aace617dbf","text":"WhatsApp group messages","translated":"WhatsApp 群组消息","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:32:45Z"}
{"cache_key":"060d0a2c79a17edab07399082756201b03bbc948813e274fd902e138a7188268","segment_id":"start/getting-started.md:9bb7dee21b23322b","source_path":"start/getting-started.md","text_hash":"9bb7dee21b23322b15ce4a4400e6fe70a582d3d15f7e61f2c4cdf68654de1f09","text":" is also supported if you want to reuse Claude Code credentials.","translated":" 如果您想复用 Claude Code 凭据,也受支持。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:36:35Z"}
{"cache_key":"0644dfe5ea449a35c3a87047a17fb132ee1ef58000d49c1849006ad247310f90","segment_id":"index.md:f14185309c5ab262","source_path":"index.md","text_hash":"f14185309c5ab26233fde49831f9fc27857a6e7ac200e91dc247ae3e3b74be27","text":"Companion apps:","translated":"伴侣应用:","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:05:03Z"}
{"cache_key":"06489e87ae62a43327838658fac6a96383f6c84a0f1e59319d89b2ce6a6f34b9","segment_id":"environment.md:e4255aa4e8f9e525","source_path":"environment.md","text_hash":"e4255aa4e8f9e52571c9bc93336d0774bcd7f017b7b5297fb33b8e1986166f92","text":"), applied only for missing expected keys.","translated":"),仅对缺失的预期密钥应用。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:57:57Z"}
{"cache_key":"064dcdb5051313b748c0b775ec69683149e1861d84fa47a74c68ddd8086bdebc","segment_id":"index.md:81a1c0449ea684aa","source_path":"index.md","text_hash":"81a1c0449ea684aadad54a7f8575061ddc5bfa713b6ca3eb8a0228843d2a3ea1","text":"Nodes (iOS/Android)","translated":"节点iOS/Android","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:52:57Z"}
{"cache_key":"0687549a28e71ec1e17b261001a9e818e27784ce3286b7d21e856e37c07915a6","segment_id":"start/getting-started.md:bad5d156dc5e0cd3","source_path":"start/getting-started.md","text_hash":"bad5d156dc5e0cd39db3a90645cd150e846743103f3acfa5182ad5a003a172dc","text":"0) Prereqs","translated":"0前提条件","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:35:23Z"}
{"cache_key":"06c13f0dfc6cd5fa142e329fd2cfb2538e19e33de83c4b9d366542f0d03cdf08","segment_id":"index.md:c3af076f92c5ed8d","source_path":"index.md","text_hash":"c3af076f92c5ed8dcb0d0b0d36dd120bc31b68264efea96cf8019ca19f1c13a3","text":"Troubleshooting","translated":"故障排除","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:33:14Z"}
@@ -32,6 +40,7 @@
{"cache_key":"08a071c1e71388ad18ffca39565a37edb304794146d2f7ea1e2bac93493f89d6","segment_id":"start/wizard.md:903ea1cf1f2831b3","source_path":"start/wizard.md","text_hash":"903ea1cf1f2831b3e836aff6e23c7d261a83381614361e65df16ade48e84b26c","text":" (API keys + OAuth).","translated":" API 密钥 + OAuth。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:43:34Z"}
{"cache_key":"08b4ff7a8e04409d740ca4090c8d83bc3b05d7084bce4b83fa4c91b930eb7161","segment_id":"environment.md:62d66b8c36a6c9aa","source_path":"environment.md","text_hash":"62d66b8c36a6c9aa7134c8f9fe5912435cb0b3bfce3172712646a187954e7040","text":"See [Configuration: Env var substitution](/gateway/configuration#env-var-substitution-in-config) for full details.","translated":"详见 [配置:环境变量替换](/gateway/configuration#env-var-substitution-in-config)。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:11:58Z"}
{"cache_key":"08f97e3d7baa10a515db441b79273f697f85c83da040cdf821f9e725243112f2","segment_id":"environment.md:f6b2ffe1d0d5f521","source_path":"environment.md","text_hash":"f6b2ffe1d0d5f521b76cabc67d6e96da2b1170eef8086d530558e9906a7f092d","text":"Models overview","translated":"模型概览","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:17:17Z"}
{"cache_key":"09057abbc867280c96888e1b1eb5d35e4f5b3175c0c5fca9900f147e577fb4b7","segment_id":"index.md:80fc402133201fbe","source_path":"index.md","text_hash":"80fc402133201fbe0e4e9962a9570e741856aa8b0c033f1a20a9bcb06c68e809","text":"Discovery","translated":"发现机制","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:29:24Z"}
{"cache_key":"090f33f5db1fde14d7fc04aaa9febae674e9e6ed0d04ce8f1813dac53ccae3a2","segment_id":"start/wizard.md:ab4386608f0ebc6e","source_path":"start/wizard.md","text_hash":"ab4386608f0ebc6e151eab042c6de71d09863aab6dcb2551665e34210e4a4439","text":"What youll set:","translated":"您需要设置的内容:","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:46:15Z"}
{"cache_key":"09824fcf1352f54ff162268163b8670ead0660d4e0a45d1f236b5b3ef938a56b","segment_id":"index.md:86e2bbbc305c31aa","source_path":"index.md","text_hash":"86e2bbbc305c31aa988751196a1e207da68801a48798c48b90485c11578443a0","text":"Providers and UX:","translated":"提供商 和用户体验:","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:04:39Z"}
{"cache_key":"0a2b53b4943a0ba87fb991fef20f822df6c2fd0584f88d394de35b081daac564","segment_id":"environment.md:668e5590b5bb9990","source_path":"environment.md","text_hash":"668e5590b5bb9990eeb25bf657f7d17281a4c613ee4442036787cd4b2efd22bb","text":"If the config file is missing entirely, step 4 is skipped; shell import still runs if enabled.","translated":"如果配置文件完全缺失,则跳过第 4 步如果已启用shell 导入仍会运行。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:58:00Z"}
@@ -43,6 +52,7 @@
{"cache_key":"0aaaa653a1bad3c2f1d6bbf34819ea4ae8700ea5d6c593937aa6812051809168","segment_id":"environment.md:453c14128fbfb5f6","source_path":"environment.md","text_hash":"453c14128fbfb5f6757511557132a1dbb3bcbf243267630bfec49db8518c7780","text":"Env var substitution in config","translated":"配置中的 环境变量 替换","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:58:16Z"}
{"cache_key":"0b149311bd258e33ab5e06f16483d6b14bfb23bbf8137339bc4cf8d29e2d3d5c","segment_id":"environment.md:453c14128fbfb5f6","source_path":"environment.md","text_hash":"453c14128fbfb5f6757511557132a1dbb3bcbf243267630bfec49db8518c7780","text":"Env var substitution in config","translated":"配置中的环境变量替换","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:11:54Z"}
{"cache_key":"0b68a76b412628864a90e4b194a0db6bcc593e8700ee9228d04b45427a95c7af","segment_id":"environment.md:cf3f9ba035da9f09","source_path":"environment.md","text_hash":"cf3f9ba035da9f09202ba669adca3109148811ef31d484cc2efa1ff50a1621b1","text":" (what the Gateway process already has from the parent shell/daemon).","translated":" Gateway 进程从父 shell/守护进程继承的已有环境变量)。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:57:23Z"}
{"cache_key":"0b6b7380e75d36476a24a56bb3825600832745e76c1a2d862e6631c0aa48c51e","segment_id":"index.md:41dc1288a547d7d1","source_path":"index.md","text_hash":"41dc1288a547d7d155c2d7b831e8cff388e12ab9d77d4c24cd0757ed47e9e209","text":" — Block streaming + Telegram draft streaming details (","translated":" — 块流式传输 + Telegram 草稿流式传输详情(","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:01:36Z"}
{"cache_key":"0bab5344d37eb10f7f0a1105ba4cf723e069867a7f745d016657752c1dc0c21a","segment_id":"environment.md:5105555b1be5f84b","source_path":"environment.md","text_hash":"5105555b1be5f84b47576d6ea432675cef742e63fa52f7b254ef2aa4c90e7cca","text":" (applied only if","translated":" (仅在","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T11:46:04Z"}
{"cache_key":"0bbc0779389fa7b103e39fff721c2df8f37e36a72350175e61b8334f79dd6555","segment_id":"index.md:0b7e778664921066","source_path":"index.md","text_hash":"0b7e77866492106632e98e7718a8e1e89e8cb0ee3f44c1572dfd9e54845023de","text":"/concepts/streaming","translated":"/concepts/streaming","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:30:06Z"}
{"cache_key":"0bda3d8fa9978471f16800fbab17622f054477505f8a680d6165e924184818eb","segment_id":"index.md:3fc5f55ea5862824","source_path":"index.md","text_hash":"3fc5f55ea5862824fc266d26cd39fb5da22cc56670c11905d5743adac10bc9ef","text":"Mattermost Bot (plugin)","translated":"Mattermost 机器人(插件)","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:29:46Z"}
@@ -77,6 +87,7 @@
{"cache_key":"11951539669d912b24dac16f9ed27e1de0a950a3baa481474a65de0ca85fbe7b","segment_id":"start/wizard.md:ec2d0a7d20f3b660","source_path":"start/wizard.md","text_hash":"ec2d0a7d20f3b6602a6593e0abef2337e84ba728ca8f6fef2534dc1e9dbfe06b","text":"Remote mode configures a local client to connect to a Gateway elsewhere.","translated":"远程模式配置本地客户端以连接到其他位置的 Gateway。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:46:13Z"}
{"cache_key":"11a42ddb57b9c1ba4022984efe25b463da52e7b9c5d7ec3a925d7a6d0e5a6c39","segment_id":"index.md:cdb4ee2aea69cc6a","source_path":"index.md","text_hash":"cdb4ee2aea69cc6a83331bbe96dc2caa9a299d21329efb0336fc02a82e1839a8","text":".","translated":".","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:28:19Z"}
{"cache_key":"11a6809809867ab84f2a66da213f7894876530602a0743b37fc93e614c7ccbfe","segment_id":"help/index.md:71095a6d42f5d9c2","source_path":"help/index.md","text_hash":"71095a6d42f5d9c2464a8e3f231fc53636d4ce0f9356b645d245874162ec07e2","text":"Gateway troubleshooting","translated":"Gateway 故障排除","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:39:44Z"}
{"cache_key":"11e66a0f11d149ca8994761cbc3771066650e21d33cb9986d47624a35fb5f177","segment_id":"help/index.md:5c94724fa7810fa9","source_path":"help/index.md","text_hash":"5c94724fa7810fa9902e565cf66c5f5a973074f2961fcd3a40bad4ee4aeca5e0","text":"If you want a quick “get unstuck” flow, start here:","translated":"如果你想快速\"脱困\",从这里开始:","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:21:37Z"}
{"cache_key":"1226fe0b47712f49a01581113142855bc5ae36e3289353b5d592ece5191b0159","segment_id":"start/wizard.md:c90e6f2be18d7e02","source_path":"start/wizard.md","text_hash":"c90e6f2be18d7e02413e18d4174fe7d855c9753005652614556204123b37c96e","text":": browser flow; paste the ","translated":":浏览器流程;粘贴 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:42:18Z"}
{"cache_key":"1249a5c279b0761418bca0826571d62b0526075a0c91018c35002331e3c6d6b5","segment_id":"environment.md:aac7246f5e97142c","source_path":"environment.md","text_hash":"aac7246f5e97142c3f257b7d8b84976f10c29e1b89804bb9d3eb7c43cc03cb8e","text":"Environment variables","translated":"环境变量","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:25:14Z"}
{"cache_key":"124e4ad52161941e1842f43e4f5d0c12d573babaf3f319ec7d5db46ba8ee7e84","segment_id":"index.md:0b60fe04b3c5c3c7","source_path":"index.md","text_hash":"0b60fe04b3c5c3c76371b6eca8b19c8e09a0e54c9010711ff87e782d87d2190b","text":"Android app","translated":"Android 应用","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:32:57Z"}
@@ -104,6 +115,7 @@
{"cache_key":"18bd8d592ca11411d1c02c1a70123dc798352f581db4c9ce297c5ebb04841fa3","segment_id":"index.md:03279877bfe1de07","source_path":"index.md","text_hash":"03279877bfe1de0766393b51e69853dec7e95c287ef887d65d91c8bbe84ff9ff","text":"WebChat + macOS app","translated":"网页聊天 + macOS 应用","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:02:30Z"}
{"cache_key":"190c49164ee5535fac803e9c0f057588d634e056d2c4fc072a0ca26e01ddc391","segment_id":"index.md:7d8b3819c6a9fb72","source_path":"index.md","text_hash":"7d8b3819c6a9fb726f40c191f606079b473f6f72d4080c13bf3b99063a736187","text":"Ops and safety:","translated":"运维和安全:","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:05:19Z"}
{"cache_key":"19207e4ed0ae44f965f33707377a0217c1765cf57b09c0268ee36c10fb108dd9","segment_id":"index.md:c6e91f3b51641b1c","source_path":"index.md","text_hash":"c6e91f3b51641b1c43d297281ee782b40d9b3a0bdd7afc144ba86ba329d5f95f","text":"OpenClaw = CLAW + TARDIS","translated":"OpenClaw = CLAW + TARDIS","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:33:18Z"}
{"cache_key":"19429bac6dc1b8ea7457c6d7eb4bcf0f89cef2a5b2a017e79a0ed5d093e1665a","segment_id":"start/getting-started.md:6b65292dc52408c1","source_path":"start/getting-started.md","text_hash":"6b65292dc52408c15bb07aa90735e215262df697d1a7bd2d907c9d1ff294ed5e","text":"If you dont have a global install yet, run the onboarding step via ","translated":"如果您尚未进行全局安装,请通过以下方式运行上手引导步骤 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:37:47Z"}
{"cache_key":"194e63ecfe45556973c28ccafc39f814f42d2478037734ce44eee72f6fc6fc66","segment_id":"index.md:856302569e24c4d6","source_path":"index.md","text_hash":"856302569e24c4d64997e2ec5c37729f852bcccf333ba1e2f71e189c9d172e6d","text":": SSH tunnel or tailnet/VPN; see ","translated":"SSH 隧道或 Tailnet/VPN请参阅 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:29:21Z"}
{"cache_key":"196942db05e9e40cbdf74a89cdd1be042430343a64ac2185009414f0d092af66","segment_id":"environment.md:cda454f61dfcac70","source_path":"environment.md","text_hash":"cda454f61dfcac7007a9edc538f9f58cf38caa0652e253975979308162bccc53","text":"Gateway configuration","translated":"Gateway 配置","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:13:11Z"}
{"cache_key":"19c0ced45bb35a1d8801864910a9f7bc2c460229fdd97366f546255feeb1db0e","segment_id":"index.md:8816c52bc5877a2b","source_path":"index.md","text_hash":"8816c52bc5877a2b24e3a2f4ae7313d29cf4eba0ca568a36f2d00616cfe721d0","text":"Wizard","translated":"向导","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:59:12Z"}
@@ -150,8 +162,10 @@
{"cache_key":"221e7c2c0fe8b9bb39aa23d66ead440852512864ee62242cc3d9290dbd135860","segment_id":"index.md:9bd86b0bbc71de88","source_path":"index.md","text_hash":"9bd86b0bbc71de88337aa8ca00f0365c1333c43613b77aaa46394c431cb9afd8","text":"Maxim Vovshin","translated":"Maxim Vovshin","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:33:49Z"}
{"cache_key":"2220f5ebb94a086ce480f01165b1993d04e470d58154e2aa482056a2eecbb1f1","segment_id":"help/index.md:3c33340bd23b8db8","source_path":"help/index.md","text_hash":"3c33340bd23b8db89f18fe7d05a954738c0dd5ba9623cf6bdb7bb5d1a3729cfc","text":"FAQ (concepts)","translated":"常见问题(概念)","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:24:59Z"}
{"cache_key":"2229ff2bff7c65fc1a4cd5515373b1b3319f43a26222f43787452e985cf5e4bb","segment_id":"index.md:11d28de5b79e3973","source_path":"index.md","text_hash":"11d28de5b79e3973f6a3e44d08725cdd5852e3e65e2ff188f6708ae9ce776afc","text":"Docs hubs (all pages linked)","translated":"文档中心(所有页面链接)","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:31:49Z"}
{"cache_key":"228b4027bfc7ab84d118c7534132c84e4135f86c319e047f014d862beb938c26","segment_id":"environment.md:a42cc4a7174c83a8","source_path":"environment.md","text_hash":"a42cc4a7174c83a853752b3e74cb001a234f3eca099688fdf0dd2540c60bb1e2","text":" expected keys:","translated":" 预期密钥:","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:26:16Z"}
{"cache_key":"22baac03ae69320ee9635f7e23e85e926ed40c441e97357b30b48e271e88770f","segment_id":"index.md:013e11a23ec9833f","source_path":"index.md","text_hash":"013e11a23ec9833f907b2ead492b0949015e25d10ba92461669609aee559335d","text":"Start here:","translated":"从这里开始:","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:31:47Z"}
{"cache_key":"22bfdd3e9e4f7a5447edf31592e38d663a8907afca5f46061f314b924280a94b","segment_id":"index.md:d53b75d922286041","source_path":"index.md","text_hash":"d53b75d9222860417f783b0829023b450905d982011d35f0e71de8eed93d90fc","text":"New install from zero:","translated":"从零开始全新安装:","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:47:41Z"}
{"cache_key":"22c699e5178ceeaa86c9029a62d9e0cea3b3c6ff75e19666d912f28097ecca91","segment_id":"index.md:5eeecff4ba2df15c","source_path":"index.md","text_hash":"5eeecff4ba2df15c51bcc1ba70a5a2198fbcac141ebe047a2db7acf0e1e83450","text":" — Local UI + menu bar companion for ops and voice wake","translated":" —— 本地界面 + 菜单栏伴侣应用,用于操作和语音唤醒","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:51:05Z"}
{"cache_key":"22c7a06691f087acabe4321804edbb000eaf7520b16060ac2879f19252b639e3","segment_id":"index.md:31365ab9453d6a1e","source_path":"index.md","text_hash":"31365ab9453d6a1ec03731622803d3b44f345b6afad08040d7f3e97290c77913","text":"do nothing","translated":"不做任何操作","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:31:33Z"}
{"cache_key":"22d40e91dde10d2912781df931ab0fac2802d5b81e63fdd93bdb7856c8c43976","segment_id":"environment.md:7175517a370b5cd2","source_path":"environment.md","text_hash":"7175517a370b5cd2e664e3fd29c4ea9db5ce17058eb9772fe090a5485e49dad6","text":" or ","translated":" 或 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:26:00Z"}
{"cache_key":"23004dacbc322d02e170261429793a8b23569f398c4f21352a030b42543cdef9","segment_id":"index.md:6b65292dc52408c1","source_path":"index.md","text_hash":"6b65292dc52408c15bb07aa90735e215262df697d1a7bd2d907c9d1ff294ed5e","text":"If you dont have a global install yet, run the onboarding step via ","translated":"如果您还没有全局安装,请通过以下方式运行 上手引导 步骤 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:51:37Z"}
@@ -474,6 +488,7 @@
{"cache_key":"60cd1a8fee21c221c625fe6961c620592e9f99a88910d9f557d86f92e17d793c","segment_id":"start/wizard.md:1d6bc09c9a9a3dad","source_path":"start/wizard.md","text_hash":"1d6bc09c9a9a3dad8fcbe9ed89a206b2dba3d8cf16046315aee976577d534cae","text":"Downloads the appropriate release asset.","translated":"下载相应的发布资源。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:47:59Z"}
{"cache_key":"60f998f050fe63afd0938f40b2f1cf78a16d5dd9fa6abc631aa8e217ce1e7cc5","segment_id":"index.md:053bc65874ad6098","source_path":"index.md","text_hash":"053bc65874ad6098e58c41c57b378a2f36b0220e5e0b46722245e6c2f796818c","text":"Discord","translated":"Discord","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:53:15Z"}
{"cache_key":"61277a40a0e409e2f324452a28cc35c44e1ac080b4400e7bdaa3c161ce51d545","segment_id":"start/wizard.md:3fcf806de5c2ace5","source_path":"start/wizard.md","text_hash":"3fcf806de5c2ace5327f65078cfb2139aaa8dd33ffdc3b04e9fef6f11778423c","text":"MiniMax M2.1","translated":"MiniMax M2.1","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:42:55Z"}
{"cache_key":"6131873fe6c607965685280107b0527c8bda0c8c322154c415c74adf0b2d6aea","segment_id":"environment.md:cf0923bd0c80e86a","source_path":"environment.md","text_hash":"cf0923bd0c80e86a7aa644d04aa412cbd7baa3273153c40c625ceca9e012bde8","text":" runs your login shell and imports only **missing** expected keys:","translated":" 运行你的登录 shell 并仅导入**缺失的**预期密钥:","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:19:37Z"}
{"cache_key":"613744b9849b1cacbbcdcebd3fcb2637696f177d0364b9e32042a74bf2c1b350","segment_id":"index.md:80fc402133201fbe","source_path":"index.md","text_hash":"80fc402133201fbe0e4e9962a9570e741856aa8b0c033f1a20a9bcb06c68e809","text":"Discovery","translated":"发现","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:49:20Z"}
{"cache_key":"613d01b2aa6e9a9127f428233d5f88e84e2c86b5079776f57becfe4143f86992","segment_id":"start/wizard.md:3ccbb3a92014470f","source_path":"start/wizard.md","text_hash":"3ccbb3a92014470f73c71c81684da45b1e07ee3a49cca372ec678ce89229ea58","text":"Vercel AI Gateway example:","translated":"Vercel AI Gateway 示例:","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:47:26Z"}
{"cache_key":"614a1ff5ae5f98f2f46f1ee6bbb53ace3482d9d15a8842906f26dcbad10c4d71","segment_id":"index.md:084514e91f37c3ce","source_path":"index.md","text_hash":"084514e91f37c3ce85360e26c70b77fdc95f0d3551ce309db96fbcf956a53b01","text":"Dashboard (browser Control UI)","translated":"仪表板(浏览器控制界面)","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:59:30Z"}
@@ -544,6 +559,7 @@
{"cache_key":"6b14f5e839df1e54026ee6d3db5886a6e9360039fd681101a4a9a2b101ff0919","segment_id":"index.md:084514e91f37c3ce","source_path":"index.md","text_hash":"084514e91f37c3ce85360e26c70b77fdc95f0d3551ce309db96fbcf956a53b01","text":"Dashboard (browser Control UI)","translated":"仪表盘(浏览器控制界面)","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:28:21Z"}
{"cache_key":"6b3dbfa396df75c279946f5b8741a67863a0107d3f08c55dc642a8fac173a4c8","segment_id":"index.md:1074116f823ec992","source_path":"index.md","text_hash":"1074116f823ec992e76d7e8be19d3235fec5ddd7020562b06e7242e410174686","text":"Remote use","translated":"远程使用","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:49:11Z"}
{"cache_key":"6b44e5cb8d21527ef6ad754e2792b9416080f2a132c8fd7b6d431fc76113aad9","segment_id":"environment.md:a42cc4a7174c83a8","source_path":"environment.md","text_hash":"a42cc4a7174c83a853752b3e74cb001a234f3eca099688fdf0dd2540c60bb1e2","text":" expected keys:","translated":" 预期的键:","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:22:25Z"}
{"cache_key":"6bf1a3983ec9759b076402ea6998c8207a0b0ef0d87b56ef4945599c9f8bd90a","segment_id":"environment.md:e4255aa4e8f9e525","source_path":"environment.md","text_hash":"e4255aa4e8f9e52571c9bc93336d0774bcd7f017b7b5297fb33b8e1986166f92","text":"), applied only for missing expected keys.","translated":"),仅对缺失的预期密钥应用。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:26:02Z"}
{"cache_key":"6c18bb32586b6c812ebf5323b8ed442c63be7b4014bc62e51f0d7f5eb46d223b","segment_id":"environment.md:582967534d0f909d","source_path":"environment.md","text_hash":"582967534d0f909d196b97f9e6921342777aea87b46fa52df165389db1fb8ccf","text":" in ","translated":" 在 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:40:54Z"}
{"cache_key":"6c1b9632694258c227417b61df6433ac71eca1f2d35ff31cb5e145a7188dacfe","segment_id":"start/getting-started.md:d7849463c3ab6a49","source_path":"start/getting-started.md","text_hash":"d7849463c3ab6a496d77b8e6745d00ad430324bc5ed419a859f7c9e494102d68","text":"Manual run (foreground):","translated":"手动运行(前台):","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:36:51Z"}
{"cache_key":"6c3d2263be9d0d6dd77934bd87f882599e2e9449e67bdee4388f84ab0aa6571b","segment_id":"start/wizard.md:698fdfc9c55bd3e4","source_path":"start/wizard.md","text_hash":"698fdfc9c55bd3e4ed5a9365317ae70aac20783ec38057088da27012a470a901","text":"Gateway port ","translated":"Gateway 端口 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:39:50Z"}
@@ -572,6 +588,7 @@
{"cache_key":"71667555ad1cea654225fec33df1804c97a0b8167affbf3d3c426ccb778e780a","segment_id":"start/wizard.md:82e1216ede141cb1","source_path":"start/wizard.md","text_hash":"82e1216ede141cb1553d20be7356c3f1ab9da9a4a05303cf7cd05ef01142558f","text":"Gateway settings (port/bind/auth/tailscale)","translated":"Gateway 设置(端口/绑定/认证/Tailscale","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:40:23Z"}
{"cache_key":"7170dcd349905701fd3cde7dc5bce0aed2618717e87ffa06e9ab230041f689a1","segment_id":"environment.md:cdb4ee2aea69cc6a","source_path":"environment.md","text_hash":"cdb4ee2aea69cc6a83331bbe96dc2caa9a299d21329efb0336fc02a82e1839a8","text":".","translated":"。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T11:45:26Z"}
{"cache_key":"724a450b6cdfc09dd0fc5acf94bb7f20a45c43e524810239d0e6e7cac65ff74b","segment_id":"index.md:bd293e4db98037bc","source_path":"index.md","text_hash":"bd293e4db98037bc9da5137af50453ac9c81b49e14eb4c47f121b12bed880877","text":" — Direct chats collapse into shared ","translated":" — 直接聊天合并到共享的 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:01:59Z"}
{"cache_key":"726990d1aefefc1ae562bce73f84f1de90c5c6cc094dc9121495e4480aedab92","segment_id":"environment.md:28e19c6e69c7a2aa","source_path":"environment.md","text_hash":"28e19c6e69c7a2aa071951dda3ff0a11ca178e3fb295dae8d6ed7dcc994434a4","text":" for full details.","translated":" 了解完整详情。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:22:42Z"}
{"cache_key":"72d5ce369dd6489f427c02710fae70f6426a51de9441678410a023761cee215b","segment_id":"start/wizard.md:8f7c7d2f15e90b42","source_path":"start/wizard.md","text_hash":"8f7c7d2f15e90b420fb6f2cc7632d7d7a433bc94eeb262d9718286e5ffd9b365","text":"Related docs","translated":"相关文档","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:49:00Z"}
{"cache_key":"730b6369e65b8f27f57a90f6ee355beca28d783793767209a7cfe7beb736769b","segment_id":"start/wizard.md:eda31fe8fb873697","source_path":"start/wizard.md","text_hash":"eda31fe8fb873697fd7d5bfba08f263eaa917808a644bddd2b6d89d3a6b1c868","text":"QuickStart vs Advanced","translated":"快速入门与高级模式","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:39:30Z"}
{"cache_key":"73164a8584f9cc4e546493100199d4ebcbb65ce74c33e21d06da689c6d7b9328","segment_id":"start/wizard.md:ce85fecfbffa2746","source_path":"start/wizard.md","text_hash":"ce85fecfbffa2746f0a9b66464140eb2ed5a085ce85fff062ef0ff8b5686a0a5","text":".\nSessions are stored under ","translated":"下。会话存储在 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:48:54Z"}
@@ -607,6 +624,7 @@
{"cache_key":"77b6a43a45b36b25b51859a5b976fa12609b6d19ed351bc0e84fae2290d32da9","segment_id":"help/index.md:2adc964c084749b1","source_path":"help/index.md","text_hash":"2adc964c084749b1f2d8aef24030988b667dbda2e38a6a1699556c93e07c1cea","text":"Start here","translated":"从这里开始","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:11:12Z"}
{"cache_key":"7806b590e1e2ff8ab2244875f7a2c370ab3b11462fd2061e5f4af9cf72f70d19","segment_id":"start/wizard.md:9c706a2bb9ebcb20","source_path":"start/wizard.md","text_hash":"9c706a2bb9ebcb206633616f2a40867b0c02716657ac4c0e95c7c1939287d3d8","text":"; auth profiles live in ","translated":";认证配置存储在 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:43:31Z"}
{"cache_key":"78161c8de8a14607cd003796d4c4ace7048f9116ecbe036601136d7f0cef4ff3","segment_id":"start/getting-started.md:bfd99edf844f6205","source_path":"start/getting-started.md","text_hash":"bfd99edf844f62050af2f7d37df7cfa7f651b8e1be341eb4f07c3849ca4efc43","text":"Fastest chat: open the Control UI (no channel setup needed). Run ","translated":"最快聊天方式:打开控制界面(无需设置渠道)。运行 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:34:33Z"}
{"cache_key":"78165d4ed88f199c04e34f0686aca8ee87969331cf02c78e26a1851d3673baae","segment_id":"help/index.md:0b554dd0f4b96cff","source_path":"help/index.md","text_hash":"0b554dd0f4b96cff4e1137c5fb22253b12125b6a3dce5d9238c80b20491bcb8e","text":"Help\n\nIf you want a quick “get unstuck” flow, start here:","translated":"# 帮助\n\n如果你想要一个快速的\"脱困\"流程,从这里开始:","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:15:12Z"}
{"cache_key":"785cae01bc172c4c47e2e82cda4c5afd7d37d7069a008e44c8a4176eeacafe67","segment_id":"help/index.md:a8ab86b9313a9236","source_path":"help/index.md","text_hash":"a8ab86b9313a92362150f5e5ba8a19de4ee52f2e3162f9bd2bc6cf128a2fcd18","text":"If youre looking for conceptual questions (not “something","translated":"如果你在寻找概念性问题(不是\"出了什么","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T11:45:00Z"}
{"cache_key":"78ae0fabb1aab02156d5bf1b4e148ba155369b079aa0b733aca5a750a3d0cdc2","segment_id":"index.md:329f3c913c0a1636","source_path":"index.md","text_hash":"329f3c913c0a16363949eb8ee7eb0cda7e81137a3851108019f33e5d18b57d8f","text":"Switching between npm and git installs later is easy: install the other flavor and run ","translated":"之后在 npm 和 git 安装之间切换很简单:安装另一种方式然后运行 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:51:30Z"}
{"cache_key":"791458a3464d7dd0036471e90590958905611942f9f0aefd8917c701e4e587d4","segment_id":"start/wizard.md:0516de0bbbd36c95","source_path":"start/wizard.md","text_hash":"0516de0bbbd36c95c5c45902d43caf2abdab59363114c4d6abae961f6ed1c1cb","text":" imply non-interactive mode. Use ","translated":" 意味着非交互模式。请使用 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:40:50Z"}
@@ -651,6 +669,7 @@
{"cache_key":"7eefff451137a5fd592db6fef6e65447cae69abe23699c34cb838a1c3cc04d73","segment_id":"start/wizard.md:d3745cec7a646b22","source_path":"start/wizard.md","text_hash":"d3745cec7a646b229f6d7123ef3557f68640f35a54a593f1e0e32776da0677c1","text":" (autogenerated, even on loopback)","translated":" (自动生成,即使在回环地址上也是如此)","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:39:58Z"}
{"cache_key":"7f2e9e14503f22acab8659b458900c0864bdc52ee5055d4a3a742508a8e41314","segment_id":"environment.md:45ca56d179d4788c","source_path":"environment.md","text_hash":"45ca56d179d4788c55ba9f7653b376d62e7faa738e92259e3d4f6f5c1b554f28","text":"Related","translated":"相关","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T11:47:13Z"}
{"cache_key":"7f4d30ae34bbfb95b016db35c14a77f46cdda52ff397a69b63ad655c6128f0f6","segment_id":"index.md:30f035b33a6c35d5","source_path":"index.md","text_hash":"30f035b33a6c35d51e09f9241c61061355c872f2fb9a82822cd2f5f443fd4ad4","text":"Group Chat Support","translated":"群聊支持","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:30:31Z"}
{"cache_key":"7f5759f942e4173b7e990de6fbc0eada6e5b6c3106c5aa6fae08456d7b79dcf8","segment_id":"index.md:6b65292dc52408c1","source_path":"index.md","text_hash":"6b65292dc52408c15bb07aa90735e215262df697d1a7bd2d907c9d1ff294ed5e","text":"If you dont have a global install yet, run the onboarding step via ","translated":"如果尚未进行全局安装,请通过以下方式运行上手引导步骤 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:31:19Z"}
{"cache_key":"7f8a0ec6c0614299ed8aca539dde67e208ecc32d4022975fbb37f7930f3f70e5","segment_id":"start/getting-started.md:4cc7ae6d3b7fbaaf","source_path":"start/getting-started.md","text_hash":"4cc7ae6d3b7fbaaf56673ea3268caa38af191a587867ef1090c9f689ecccec96","text":"Headless/server tip: do OAuth on a normal machine first, then copy ","translated":"无头/服务器提示:先在普通机器上完成 OAuth然后复制 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:36:40Z"}
{"cache_key":"7fec8c329b4438aef905e1918364b86faca2a2580bb29eded4850a67ba16109b","segment_id":"environment.md:496aca80e4d8f29f","source_path":"environment.md","text_hash":"496aca80e4d8f29fb8e8cd816c3afb48d3f103970b3a2ee1600c08ca67326dee","text":" block","translated":" 块","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:25:48Z"}
{"cache_key":"8070c35741bdfaa2f8878a7460406a597ccf7fec7994522389adeafea46b6e8e","segment_id":"environment.md:frontmatter:read_when:0","source_path":"environment.md:frontmatter:read_when:0","text_hash":"90fc0487bff88009979cff1061c1a882df8c3b1baa9c43538331d9d5dab15479","text":"You need to know which env vars are loaded, and in what order","translated":"你需要了解加载了哪些环境变量,以及加载的顺序","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T11:45:10Z"}
@@ -662,6 +681,7 @@
{"cache_key":"822efbc5bcf680421493847f6b76e9626f1d8202ff5ff47cd3e141ecdac58a9f","segment_id":"environment.md:496aca80e4d8f29f","source_path":"environment.md","text_hash":"496aca80e4d8f29fb8e8cd816c3afb48d3f103970b3a2ee1600c08ca67326dee","text":" block","translated":" 块","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:16:27Z"}
{"cache_key":"829cc48b5c60f16b09e63437a5de27acc17910473f8e3dfbc505a0d3e3b593c7","segment_id":"start/wizard.md:79a482cf546c23b0","source_path":"start/wizard.md","text_hash":"79a482cf546c23b04cd48a33d4ca8411f62e5b7dc8c3a8f30165e28e747f263a","text":"iMessage","translated":"iMessage","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:44:54Z"}
{"cache_key":"82d122e7cc5c895b61dec28850c3f07a68e69c19f554d9088318f62c6cd30fe1","segment_id":"environment.md:6d28a9f099e563d9","source_path":"environment.md","text_hash":"6d28a9f099e563d9322b5bcdea9ff98af87e9c213c2222462ae738d2fb27ecbe","text":" block\n\nTwo equivalent ways to set inline env vars (both are non-overriding):","translated":" 块\n\n设置内联环境变量的两种等效方式均为非覆盖式","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:16:44Z"}
{"cache_key":"83090d5cbebceddaa2f500bdb4240d4ea9a8ee14da3654f77128a067e4dc220a","segment_id":"environment.md:e4255aa4e8f9e525","source_path":"environment.md","text_hash":"e4255aa4e8f9e52571c9bc93336d0774bcd7f017b7b5297fb33b8e1986166f92","text":"), applied only for missing expected keys.","translated":"),仅对缺失的预期密钥应用。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:12:37Z"}
{"cache_key":"8334186d1a61e931ed7b3905a26e470159f86593819124c5626df7a012733ee9","segment_id":"environment.md:frontmatter:summary","source_path":"environment.md:frontmatter:summary","text_hash":"78351223e7068721146d2de022fdf440c2866b2ee02fbbb50bf64369b999820b","text":"Where OpenClaw loads environment variables and the precedence order","translated":"其中 OpenClaw 加载 环境变量 及优先级顺序","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:56:59Z"}
{"cache_key":"833685db37cf96f2342238018bd6a4a6e7812d1794a7389dc1e349917b140f50","segment_id":"environment.md:668e5590b5bb9990","source_path":"environment.md","text_hash":"668e5590b5bb9990eeb25bf657f7d17281a4c613ee4442036787cd4b2efd22bb","text":"If the config file is missing entirely, step 4 is skipped; shell import still runs if enabled.","translated":"如果配置文件完全缺失,则跳过第 4 步;如果启用了 shell 导入,它仍会运行。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:19:28Z"}
{"cache_key":"834bd8857aa5700b0ec493efb4625ba88e34c885a8254b13f6c44a75589021d2","segment_id":"index.md:9bcda844990ec646","source_path":"index.md","text_hash":"9bcda844990ec646b3b6ee63cbdf10f70b0403727dea3b5ab601ca55e3949db9","text":" for node WebViews; see ","translated":" 用于节点 WebView请参阅 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:29:13Z"}
@@ -675,6 +695,7 @@
{"cache_key":"84c686db4b4fc386bbb4efa35c380073babbc5fb4b2eb1ba3a8213a5f135a5bc","segment_id":"start/getting-started.md:161660030aa6c9e3","source_path":"start/getting-started.md","text_hash":"161660030aa6c9e32470cc1c023dab32dc748d80b0e61882b368cb775d12638e","text":" → ","translated":" → ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:34:27Z"}
{"cache_key":"84e200d4c823802e34a99da4faa8328d0e250aca858b0a32cc08e3ae12e0cc0e","segment_id":"start/wizard.md:e4442451c634e0db","source_path":"start/wizard.md","text_hash":"e4442451c634e0db2db0fae78725becbeafd567302e3ecbfeb5ccdc5887d29be","text":" from GitHub releases:","translated":" (从 GitHub 发布版本):","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:47:56Z"}
{"cache_key":"85040674d9e2db6adb1ebb8c6215e72171d213a9dac8bd3c6bcb438178adc88b","segment_id":"index.md:0a4a282eda1af348","source_path":"index.md","text_hash":"0a4a282eda1af34874b588bce628b76331fbe907de07b57d39afdedccac2ba14","text":" http://127.0.0.1:18789/ (or http://localhost:18789/)","translated":" http://127.0.0.1:18789/(或 http://localhost:18789/","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:28:15Z"}
{"cache_key":"850dacfab0ff7f9fd9498aeac24c0b84c59f266291d504465d7dead52da552bf","segment_id":"index.md:41dc1288a547d7d1","source_path":"index.md","text_hash":"41dc1288a547d7d155c2d7b831e8cff388e12ab9d77d4c24cd0757ed47e9e209","text":" — Block streaming + Telegram draft streaming details (","translated":" — 块流式传输 + Telegram 草稿流式传输详情(","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:30:04Z"}
{"cache_key":"85cb0b7ed6991128b9fe65b7b103c5f32da742641cb24ffc1a3469002a2bcad6","segment_id":"start/getting-started.md:e24d86fa815827a4","source_path":"start/getting-started.md","text_hash":"e24d86fa815827a4dc5b8b22711caaf036427796512a74167ebaf615c495f9f8","text":"Telegram / Discord / others","translated":"Telegram / Discord / 其他","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:37:17Z"}
{"cache_key":"85e39779810391375b7241f2d999fbd5e6b2830ddf226a9ad561132c40d4fd47","segment_id":"start/wizard.md:21b111cbfe6e8fca","source_path":"start/wizard.md","text_hash":"21b111cbfe6e8fca2d181c43f53ad548b22e38aca955b9824706a504b0a07a2d","text":"Default ","translated":"默认 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:43:41Z"}
{"cache_key":"85fdea7998dfe111261588f998c93aceaa9b04ba174bc16bd188e3bbd8f3228a","segment_id":"environment.md:668e5590b5bb9990","source_path":"environment.md","text_hash":"668e5590b5bb9990eeb25bf657f7d17281a4c613ee4442036787cd4b2efd22bb","text":"If the config file is missing entirely, step 4 is skipped; shell import still runs if enabled.","translated":"如果配置文件完全缺失,则跳过第 4 步如果已启用shell 导入仍会运行。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:12:40Z"}
@@ -691,6 +712,7 @@
{"cache_key":"87b42c17fb63bfdcd059198572016f6b8b3cd297aaa991c4c1dea8723a68fbfe","segment_id":"index.md:9abe8e9025013e78","source_path":"index.md","text_hash":"9abe8e9025013e78a6bf2913f8c20ee43134ad001ce29ced89e2af9c07096d8f","text":"Media: images","translated":"媒体:图片","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:32:48Z"}
{"cache_key":"87d80d180c9d4789c20123b3bc177f99c4d00909f70c6fe3c209c078bdcafdce","segment_id":"index.md:1074116f823ec992","source_path":"index.md","text_hash":"1074116f823ec992e76d7e8be19d3235fec5ddd7020562b06e7242e410174686","text":"Remote use","translated":"远程使用","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:00:36Z"}
{"cache_key":"87f8e99a729beb8e55fdef7ca70ebe4b11f4ff1c5dbbfcb3e654429198c6bf0f","segment_id":"help/index.md:729bc562eec2658b","source_path":"help/index.md","text_hash":"729bc562eec2658bd11ffdd522fe5277177dc73e86eaca7baac0b472a4d8f8b2","text":"If youre looking for conceptual questions (not “something broke”):","translated":"如果你在寻找概念性问题(不是\"出了故障\"","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:19:05Z"}
{"cache_key":"8819cee05e67d9206c9adc7cf9539b1586a050f9c259e65a3099184303440591","segment_id":"environment.md:a42cc4a7174c83a8","source_path":"environment.md","text_hash":"a42cc4a7174c83a853752b3e74cb001a234f3eca099688fdf0dd2540c60bb1e2","text":" expected keys:","translated":" 预期密钥:","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:58:11Z"}
{"cache_key":"88ab429b0aa43b0cfc93a1fc0e69576a2acbf64d0cd407fc1028488a0c27c9fc","segment_id":"index.md:fdef9f917ee2f72f","source_path":"index.md","text_hash":"fdef9f917ee2f72fbd5c08b709272d28a2ae7ad8787c7d3b973063f0ebeeff7a","text":" to update the gateway service entrypoint.","translated":" 以更新网关服务入口点。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:03:03Z"}
{"cache_key":"88d02146dbe2246af19afc2deecbb627547528cd1bf8b9839d358e8987a88a99","segment_id":"index.md:9c870aa6e5e93270","source_path":"index.md","text_hash":"9c870aa6e5e93270170d5a81277ad3e623afe8d4efd186d3e28f3d2b646d52e6","text":"How it works","translated":"工作原理","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:59:42Z"}
{"cache_key":"88f63f39528cb8bcb530a350a6b610125dbf6ab7034c2509a772e2ec28ed9476","segment_id":"help/index.md:frontmatter:read_when:1","source_path":"help/index.md:frontmatter:read_when:1","text_hash":"857eafc389d179e83e21e46c10527fec40894fe064c63847ba06b946b7d5eb73","text":"Something broke and you want the fastest path to a fix","translated":"出了问题,你想找到最快的修复方法","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:15:10Z"}
@@ -703,6 +725,7 @@
{"cache_key":"8a81f73e519177081d755623ff45ac47552fa513f5aaf9c77335ce2c329087f3","segment_id":"start/getting-started.md:524bf322c2034388","source_path":"start/getting-started.md","text_hash":"524bf322c2034388f76cd94c1c7834341cedfa09bc4a864676749a08b243416d","text":"model/auth (OAuth recommended)","translated":"模型/认证(推荐使用 OAuth","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:34:53Z"}
{"cache_key":"8a83aabc21a6b84ce7552d72a9bc0a7c2d99864c31350064cbd39564354421f1","segment_id":"index.md:9adcfa4aa10a4e8b","source_path":"index.md","text_hash":"9adcfa4aa10a4e8b991a72ccc45261cd64f296aed5b257e4caf9c87aff1290a0","text":" — Send and receive images, audio, documents","translated":" —— 发送和接收图片、音频、文档","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:50:51Z"}
{"cache_key":"8a984f774ac8874be4797ffddd21cbdddc9379fa6bc51121620fbe9395cd91cf","segment_id":"help/index.md:bfc5930cc2660330","source_path":"help/index.md","text_hash":"bfc5930cc2660330260afd407e98d86adaec0af48dd72b88dc33ef8e9066e2c9","text":"Install sanity (Node/npm/PATH):","translated":"安装完整性检查Node/npm/PATH","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:15:18Z"}
{"cache_key":"8aba2e1efca29d503bd185064c1e676dd87fa34c81fa9bb059ed6300f6bfd517","segment_id":"environment.md:28e19c6e69c7a2aa","source_path":"environment.md","text_hash":"28e19c6e69c7a2aa071951dda3ff0a11ca178e3fb295dae8d6ed7dcc994434a4","text":" for full details.","translated":" 了解完整详情。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:41:35Z"}
{"cache_key":"8ac55f265f3496db43dce513fde21c137826476afcff2ed1b3e86e613ff28b3c","segment_id":"start/wizard.md:44dab6c89cc5e6d9","source_path":"start/wizard.md","text_hash":"44dab6c89cc5e6d9a3112d3cb45c19cd16c3a9963082276015d4b624e5e67782","text":"Some channels are delivered as plugins. When you pick one during onboarding, the wizard\nwill prompt to install it (npm or a local path) before it can be configured.","translated":"部分渠道以插件形式提供。当您在上手引导期间选择某个渠道时,向导会提示先安装它(通过 npm 或本地路径),然后才能进行配置。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:48:57Z"}
{"cache_key":"8b2c90beec3893be65468e57df762fcbc285a9772042200eee3d4bf8f7ff9c0d","segment_id":"index.md:96be070791b7d545","source_path":"index.md","text_hash":"96be070791b7d545dc75084e59059d2170eed247350b351db5330fbd947e4be6","text":"👥 ","translated":"👥 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:30:29Z"}
{"cache_key":"8b921a960a8b92bc6210c2e228fe886cd93000a5a77f1cb5ac97233de2c4f965","segment_id":"index.md:fb87b8dba88b3edc","source_path":"index.md","text_hash":"fb87b8dba88b3edced028edfe2efa5f884ab2639c1b26efa290ccd0469454d25","text":"Slash commands","translated":"斜杠命令","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:04:03Z"}
@@ -784,6 +807,7 @@
{"cache_key":"9a7478d471c30618239146c8b7adbd3669fd552a2fafba13cc6dc8b51c083243","segment_id":"index.md:a194ca16424ddd17","source_path":"index.md","text_hash":"a194ca16424ddd17dacc45f1cbd7d0e41376d8955a7b6d02bc38c295cedd04e4","text":"RPC adapters","translated":"RPC 适配器","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:04:25Z"}
{"cache_key":"9aaaeb76bc162fe216b19290b0978994ad43023335a81224b65bf7e4849ed5b6","segment_id":"index.md:frontmatter:summary","source_path":"index.md:frontmatter:summary","text_hash":"891b2aa093410f546b89f8cf1aa2b477ba958c2c06d2ae772e126d49786df061","text":"Top-level overview of OpenClaw, features, and purpose","translated":"OpenClaw 的顶层概述、功能和用途","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:47:18Z"}
{"cache_key":"9b0b553b6bb64b97bc340190fc4f10febadb5c4542122d2dea4661534f60b8b6","segment_id":"index.md:a10f6ed8c1ddbc10","source_path":"index.md","text_hash":"a10f6ed8c1ddbc10d3528db7f7b6921c1dd5a5e78aa191ff017bf29ce2d26449","text":"⏱️ ","translated":"⏱️ ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:50:04Z"}
{"cache_key":"9b4a9e428618ff38c3d8e54131d987860c0ebbb45007e3493d99964d9cd436a6","segment_id":"index.md:4d705f0fa835fd21","source_path":"index.md","text_hash":"4d705f0fa835fd216c4fd6dea0ee851d33720e23fb714c4c9ea74ac3211fccdc","text":"Discovery + transports","translated":"发现机制 + 传输方式","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:32:28Z"}
{"cache_key":"9bb6f5ad39ff9d7aff3bca1fda6f474e19f25c0ffaaffaf3b19c924234d8c03a","segment_id":"index.md:f0d82ba647b4a33d","source_path":"index.md","text_hash":"f0d82ba647b4a33da3008927253f9bed21e380f54eab0608b1136de4cbff1286","text":"OpenClaw bridges WhatsApp (via WhatsApp Web / Baileys), Telegram (Bot API / grammY), Discord (Bot API / channels.discord.js), and iMessage (imsg CLI) to coding agents like ","translated":"OpenClaw 将 WhatsApp通过 WhatsApp Web / Baileys、TelegramBot API / grammY、DiscordBot API / 渠道.discord.js和 iMessageimsg CLI桥接到编程 智能体,例如 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:47:31Z"}
{"cache_key":"9c03abf2c27129fa2698e7640a7b9add5936e84cf6d779d5f189bf9a27940aa6","segment_id":"index.md:310cc8cec6b20a30","source_path":"index.md","text_hash":"310cc8cec6b20a3003ffab12f5aade078a0e7a7d6a27ff166d62ab4c3a1ee23d","text":"If you ","translated":"如果你 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:03:25Z"}
{"cache_key":"9c11b2ec1c922e332f69000a8a937f0a2318b5356faa6278a7580cc49c3526d5","segment_id":"index.md:e47cdb55779aa06a","source_path":"index.md","text_hash":"e47cdb55779aa06a74ae994c998061bd9b7327f5f171c141caf2cf9f626bfe4b","text":"Peter Steinberger","translated":"Peter Steinberger","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:05:52Z"}
@@ -794,6 +818,7 @@
{"cache_key":"9cbdb7ff14fdd8d015b7bcce3b3c0d48b1711e631ff86cae2c699684f8e4d143","segment_id":"start/wizard.md:c4b2896a2081395e","source_path":"start/wizard.md","text_hash":"c4b2896a2081395e282313d6683f07c81e3339ef8b9d2b5a299ea5b626a0998f","text":").","translated":")。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:41:17Z"}
{"cache_key":"9d44e8f510b7e2cf5ea7b08188a9c606937bc3db8c49e22d903828b34b8b04c1","segment_id":"start/wizard.md:19f53c2ccaf19969","source_path":"start/wizard.md","text_hash":"19f53c2ccaf199696e23d43812941e23fed0625900d2a551533304d6ca1980f6","text":" install or change anything on the remote host.","translated":" 在远程主机上安装或更改任何内容。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:40:40Z"}
{"cache_key":"9d7b3ce341253f712ecd8b4ca661ae0a6d85b1ee8e8ddf00b1ec02ca13d67237","segment_id":"help/index.md:569ca49f4aaf7846","source_path":"help/index.md","text_hash":"569ca49f4aaf7846e952c1d4aeca72febd0b79fa1c4f9db08fd3127551218572","text":"Install","translated":"安装","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:24:41Z"}
{"cache_key":"9d829bdffa4f3aa22d063ea4b6391f8094b8f4db9df8a985430559d4a153e286","segment_id":"index.md:58d30d963f28264b","source_path":"index.md","text_hash":"58d30d963f28264bd9ba0e2d4c07c2c43c0ac1c1609c25b3fccf475eebf41727","text":"Skills config","translated":"技能配置","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:04:19Z"}
{"cache_key":"9db03f9dc7b789dbc3b4115e9b644cd22de2a63adeed02eb3b403a223d96b819","segment_id":"index.md:2b402c90e9b15d9c","source_path":"index.md","text_hash":"2b402c90e9b15d9c3ef65c432c4111108f54ee544cda5424db46f6ac974928e4","text":"🔐 ","translated":"🔐 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:30:14Z"}
{"cache_key":"9e0b7ed9895b612971d582145c837e95bfec8b051c6bccddd008d56dff778711","segment_id":"start/wizard.md:28d03596d24eeb4e","source_path":"start/wizard.md","text_hash":"28d03596d24eeb4eab2d6fe21ca1cb95be7cb1fa6f92933db05e2cc4f4cdfa06","text":"Skip","translated":"跳过","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:43:16Z"}
{"cache_key":"9e3a338fc3d6bce679ff4711d74e67c66877245b6ebd2c2a08f182a3a788dae6","segment_id":"start/getting-started.md:fd82e54418ec23cd","source_path":"start/getting-started.md","text_hash":"fd82e54418ec23cda00219878eaf76c3b37337b3dcb7560a941db6a0d2ec249e","text":": background install (launchd/systemd; WSL2 uses systemd)","translated":"后台安装launchd/systemdWSL2 使用 systemd","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:36:15Z"}
@@ -823,6 +848,7 @@
{"cache_key":"a235aca76de620b9ed0805727dc5f142a660dc6dac3254a01531acad96cb084d","segment_id":"index.md:d53b75d922286041","source_path":"index.md","text_hash":"d53b75d9222860417f783b0829023b450905d982011d35f0e71de8eed93d90fc","text":"New install from zero:","translated":"从零开始全新安装:","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:59:05Z"}
{"cache_key":"a28528856eac855eaf431dc468f5d1a9b3918df6dc73a9bb54c488aa7c23faad","segment_id":"start/getting-started.md:387847437e10c06c","source_path":"start/getting-started.md","text_hash":"387847437e10c06cae87567a6579b38e71849aea9c2355eba4a8d090418360b9","text":"The wizard can write tokens/config for you. If you prefer manual config, start with:","translated":"向导可以为您写入令牌/配置。如果您更喜欢手动配置,请从以下内容开始:","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:37:19Z"}
{"cache_key":"a28d9fd85bfd4afc9a62b3cfe12607c86001b32a9a97d72eeb6cd50993fb51ee","segment_id":"index.md:c6e91f3b51641b1c","source_path":"index.md","text_hash":"c6e91f3b51641b1c43d297281ee782b40d9b3a0bdd7afc144ba86ba329d5f95f","text":"OpenClaw = CLAW + TARDIS","translated":"OpenClaw = CLAW + TARDIS","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:54:04Z"}
{"cache_key":"a29d82b0936a3237f692bb4c86bb8bcc8b1840db6ab6f2922a249fda830bdc5a","segment_id":"index.md:4d705f0fa835fd21","source_path":"index.md","text_hash":"4d705f0fa835fd216c4fd6dea0ee851d33720e23fb714c4c9ea74ac3211fccdc","text":"Discovery + transports","translated":"发现 + 传输","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:04:36Z"}
{"cache_key":"a2c462e51d228b070aba2a14a09d41aa54e0962d795724d5a090c71c7e242dfe","segment_id":"start/getting-started.md:acdd1e734125f341","source_path":"start/getting-started.md","text_hash":"acdd1e734125f341604c0efbabdcc4c4b0597e8f6235d66c2445edd1812838c1","text":"Telegram","translated":"Telegram","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:37:22Z"}
{"cache_key":"a2f08193fbeb8a9400b75d96157bbbf488ab3aa51d50658094d00bb841646217","segment_id":"help/index.md:2adc964c084749b1","source_path":"help/index.md","text_hash":"2adc964c084749b1f2d8aef24030988b667dbda2e38a6a1699556c93e07c1cea","text":"Start here","translated":"从这里开始","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T11:44:37Z"}
{"cache_key":"a32d46351380765e1ec38639781fc9e5abaccdf74240eee7ab685f570551f487","segment_id":"index.md:7d8b3819c6a9fb72","source_path":"index.md","text_hash":"7d8b3819c6a9fb726f40c191f606079b473f6f72d4080c13bf3b99063a736187","text":"Ops and safety:","translated":"运维与安全:","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:33:04Z"}
@@ -832,6 +858,7 @@
{"cache_key":"a3909a297d0e74a4cb418a7a549f495f6eed24048ebf8f12f448eff8d7a20c50","segment_id":"environment.md:1ec31258a6b45ea9","source_path":"environment.md","text_hash":"1ec31258a6b45ea903cd76f5b0190a99ab56afff6241a04f0681eb12b7a02484","text":"Env var equivalents:","translated":"等效的环境变量:","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:26:18Z"}
{"cache_key":"a3e59ee4578bdb5fd68940692f78e9389e163da63e350ba9f0689ffbc980d4a5","segment_id":"environment.md:28b1103adde15a9d","source_path":"environment.md","text_hash":"28b1103adde15a9ddd8fc71f0c57dc155395ade46a0564865ccb5135b01c99b7","text":"OpenClaw pulls environment variables from multiple sources. The rule is **never override existing values**.","translated":"OpenClaw 从多个来源拉取环境变量。规则是**永远不覆盖已有的值**。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:19:23Z"}
{"cache_key":"a4384986e5ce06eca0118051e6a851ac0fd3d922d4d1f31b60000687962a2288","segment_id":"start/wizard.md:ec1a3a5d6d6f0bac","source_path":"start/wizard.md","text_hash":"ec1a3a5d6d6f0baca7805bf1ea17fc7b02042416f02f80bc1970ad8c710abd89","text":"Flow details (local)","translated":"流程详情(本地)","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:40:56Z"}
{"cache_key":"a44af8d86be9e8883c8df3ed68722e659e4d7bb99e2675df13ee0ab386219e51","segment_id":"index.md:22159a426e4f2635","source_path":"index.md","text_hash":"22159a426e4f26356382cc3ac9b2e7af5123c1309250332f5dcbbc6e6f952b0e","text":"Network model","translated":"网络 模型","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:59:51Z"}
{"cache_key":"a46b3daf9b1e1045e72e437a283e8377ec9b4820cde181d05a24a9a582cbf914","segment_id":"start/wizard.md:12754931af777521","source_path":"start/wizard.md","text_hash":"12754931af777521bcb6a904d2a7d342d0d77e6c4f1f2eb1b8b3753d25a1ab4a","text":"If the Control UI assets are missing, the wizard attempts to build them; fallback is ","translated":"如果 Control UI 资源文件缺失,向导会尝试构建它们;后备方案是 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:46:06Z"}
{"cache_key":"a4a009f8c9411234d5dd3ef4a71fdf292ec59e29a2b74d197acea1c789825536","segment_id":"help/index.md:6cb77499abdccd9a","source_path":"help/index.md","text_hash":"6cb77499abdccd9a2dbb7c93a4d31eed01613dda06302933057970df9ecdeb54","text":"Logs:","translated":"日志:","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:24:46Z"}
{"cache_key":"a4b963e5c58f681343b2e7b98ade4df71e3a328906ed382ffc8c0e4853fdf162","segment_id":"environment.md:b1d6b91b67c2afa5","source_path":"environment.md","text_hash":"b1d6b91b67c2afa5e322988d9462638d354ddf8a1ef79dba987f815c22b4baee","text":" at ","translated":" 位于 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:25:39Z"}
@@ -864,6 +891,7 @@
{"cache_key":"a9c30fa450ed436cb03bc256b3075761a9215bd99bcd7bd2891cf15317ffd34f","segment_id":"environment.md:d08a8493f686363a","source_path":"environment.md","text_hash":"d08a8493f686363a78b913d45ebfbd87a3768d1c77b70f23b1fdade3c066e481","text":"Shell env import","translated":"Shell 环境导入","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:16:47Z"}
{"cache_key":"aa80cfc76e76409c5ba7bf331e4fb8aadf72703ead80d203c94e74209da993f9","segment_id":"index.md:310cc8cec6b20a30","source_path":"index.md","text_hash":"310cc8cec6b20a3003ffab12f5aade078a0e7a7d6a27ff166d62ab4c3a1ee23d","text":"If you ","translated":"如果你 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:31:31Z"}
{"cache_key":"aaa5becdcd694b68de2e61f6a13bd932c3f80f8b0b5a959a054a61ad5911beef","segment_id":"index.md:81a1c0449ea684aa","source_path":"index.md","text_hash":"81a1c0449ea684aadad54a7f8575061ddc5bfa713b6ca3eb8a0228843d2a3ea1","text":"Nodes (iOS/Android)","translated":"节点iOS/Android","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:32:22Z"}
{"cache_key":"aab013ce01ee6fc5b450d86a4cb8582865cc8b2e84ef22a6b5e0191462c1ee45","segment_id":"index.md:6b65292dc52408c1","source_path":"index.md","text_hash":"6b65292dc52408c15bb07aa90735e215262df697d1a7bd2d907c9d1ff294ed5e","text":"If you dont have a global install yet, run the onboarding step via ","translated":"如果尚未进行全局安装,请通过以下方式运行 上手引导 步骤 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:03:09Z"}
{"cache_key":"aacffcbc2a97abf1a5eccd00e5893be1125e364251fa27f3e0c88ef2db2b0248","segment_id":"index.md:acdd1e734125f341","source_path":"index.md","text_hash":"acdd1e734125f341604c0efbabdcc4c4b0597e8f6235d66c2445edd1812838c1","text":"Telegram","translated":"Telegram","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:32:36Z"}
{"cache_key":"aad00bc21098071ff9c86ff467cb7f5c65d3467ce4bf7d707f560479783e9eaa","segment_id":"index.md:b79cac926e0b2e34","source_path":"index.md","text_hash":"b79cac926e0b2e347e72cc91d5174037c9e17ae7733fd7bdb570f71b10cd7bfc","text":"Help","translated":"帮助","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:31:51Z"}
{"cache_key":"aae01909516ef373ddb2e4996f9016675f297208f7f075a68490f1f48eb0c87f","segment_id":"environment.md:6a26e1694d9e8520","source_path":"environment.md","text_hash":"6a26e1694d9e852038e5a472ed6b54cc023b4ace8ac10d745cad426d5dc057f3","text":" details.","translated":" 详情。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T11:47:11Z"}
@@ -911,6 +939,7 @@
{"cache_key":"b1a0214973416cbfb4dcac01605c51911f412a6b7d862a6b8aed7db6364bb93a","segment_id":"start/wizard.md:1a0f5fc7ca6e8a74","source_path":"start/wizard.md","text_hash":"1a0f5fc7ca6e8a74bc099d9c397a23564b55eca50c3b2e33c472acb7032a6f3b","text":" (if Minimax chosen)","translated":" (如果选择了 Minimax","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:48:35Z"}
{"cache_key":"b1babe6ce88663854adf02aa4a23f21c9a98e036c72bf36dbe4b518d5d025d8b","segment_id":"environment.md:8d076464a84995bc","source_path":"environment.md","text_hash":"8d076464a84995bc095e934b0aa1e4419372f27cd71d033571e4dbba201ee5d8","text":"You can reference env vars directly in config string values using ","translated":"您可以使用以下方式在配置字符串值中直接引用 环境变量 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:41:25Z"}
{"cache_key":"b1bfed2a2039ffc6f83d8201645caf18d6b942a8e5efbe2a28ca24978f750aa7","segment_id":"index.md:a97c0f391117ef55","source_path":"index.md","text_hash":"a97c0f391117ef554586ed43255ab3ff0e15adcfc1829c62b6d359672c0bec93","text":" — Mention-based by default; owner can toggle ","translated":" — 默认基于提及;所有者可切换 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:02:09Z"}
{"cache_key":"b1d6847512a77312c1152a3f04694cdfc058f6d51d29f421a97d1f7799705076","segment_id":"help/index.md:d5d5bf0c0c86cfaa","source_path":"help/index.md","text_hash":"d5d5bf0c0c86cfaa612b370c3c796bb03e31b285fc928b5a690bfd156d177e88","text":"If you want a quick “get unstuck” flow, start","translated":"如果你想要一个快速的\"摆脱困境\"流程,请从这里开始","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T11:44:31Z"}
{"cache_key":"b1e93b43d06bcf0651c4bee0920f356e1f38bceca29db1936d449b4be99e77d2","segment_id":"index.md:8f6fb4eb7f42c0e2","source_path":"index.md","text_hash":"8f6fb4eb7f42c0e245e29e63f5b82cc3ba19852681d1ed9aed291f59cf75ec0e","text":"Security","translated":"安全","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:53:56Z"}
{"cache_key":"b212246fea49637bc0db899bd39dff2b1762ecf0d8cac3ec6160a8cd4c4da860","segment_id":"start/wizard.md:1f01936efef6e09c","source_path":"start/wizard.md","text_hash":"1f01936efef6e09cd29c9b1a9b6a64c1fcdb35682c9cf25db02dfde331f83fa7","text":" if present or prompts for a key, then saves it to ","translated":" (如果存在)或提示输入密钥,然后保存到 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:42:29Z"}
{"cache_key":"b240cb7927de51aca09fb318798ffd79fe597965722be259f799a2002cbe0f43","segment_id":"start/getting-started.md:4ea5ee68fea05586","source_path":"start/getting-started.md","text_hash":"4ea5ee68fea05586106890ded5733820bb77d919cda27bc4b8139b7cd33b8889","text":" gateway","translated":" Gateway","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:36:02Z"}
@@ -1002,6 +1031,7 @@
{"cache_key":"c2802148a29fff6480dd7c4126df1d7787f83156807ce1f6e0abb05d2e0a7863","segment_id":"index.md:6e0f6eca4ff17d33","source_path":"index.md","text_hash":"6e0f6eca4ff17d3377c1c3e8e1f73457553ad3b9cfcd5e4f2b94cfb1028b6234","text":"iOS app","translated":"iOS 应用","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:53:36Z"}
{"cache_key":"c2acf62bea34b4557cbab8b7ceadd55c5cf37516c124b93afc1b8e9f08d62ab0","segment_id":"index.md:39bbb719fa2b9d22","source_path":"index.md","text_hash":"39bbb719fa2b9d2251039cbf2cd072e1120a414278263e2f11d99af0236c4262","text":"Groups","translated":"群组","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:53:21Z"}
{"cache_key":"c2e74d237df6614199282b8822741be509ff03e31b7319f3184bb2537860e8a9","segment_id":"index.md:bf084dc7b82e1e62","source_path":"index.md","text_hash":"bf084dc7b82e1e62c63727b13451d1eba2269860e27db290d2d5908d7ade0529","text":" — Pairs as a node and exposes Canvas + Chat + Camera","translated":" — 作为节点配对并提供 Canvas + 聊天 + 相机","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:02:43Z"}
{"cache_key":"c2e91312acca3baab311ea42b62c2fcea1bf5ec3fe9f444cc63f3e00c3b1da02","segment_id":"environment.md:7c3c58e5e1838eae","source_path":"environment.md","text_hash":"7c3c58e5e1838eaeec35be812eb7edad1525e370c3420121710cc1d5fb627c1b","text":"), applied only for missing expected keys.\n\nIf the config file is missing entirely, step 4 is skipped; shell import still runs if enabled.","translated":"),仅对缺失的预期密钥应用。\n\n如果配置文件完全不存在则跳过第 4 步如果已启用shell 导入仍会运行。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:16:42Z"}
{"cache_key":"c335a0e455574c0e23a45c10a55511400b6168c38aa7d8e43521b1c8650e58f9","segment_id":"environment.md:frontmatter:read_when:1","source_path":"environment.md:frontmatter:read_when:1","text_hash":"a3a2d99a99de98220c8e0296d6f4e4b2a34024916bd2379d1b3b9179c8fae46f","text":"You are debugging missing API keys in the Gateway","translated":"您正在调试 Gateway 中缺失的 API 密钥","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:40:15Z"}
{"cache_key":"c34f893f16dcd3b37a3752585df805b44212829550f3d82cb5f539fdb50a5a50","segment_id":"environment.md:87e89abb4c1c551f","source_path":"environment.md","text_hash":"87e89abb4c1c551fe08d355d097f18b8de78edca5f556997085681662fce8eed","text":"Config ","translated":"配置 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:25:46Z"}
{"cache_key":"c359a69d5e0e9e6470f36436f1b27a946ef28ef1069e7b7d59e0ea3132f6003c","segment_id":"start/wizard.md:4cd440e57b28aba7","source_path":"start/wizard.md","text_hash":"4cd440e57b28aba7f789ba11d0bb5837f09937ba45bab9a80b9a6a980894250e","text":"Followup reconfiguration:","translated":"后续重新配置:","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:39:15Z"}
@@ -1055,6 +1085,7 @@
{"cache_key":"cc8f5dcfbe51a4638b375d367381be97b79d012b56b2c7eadd2e38d164cdd177","segment_id":"start/wizard.md:e18251a039a6b735","source_path":"start/wizard.md","text_hash":"e18251a039a6b7353675decc475898bfdb91d3bd9d37e83c8447d0359b8711c3","text":"Non-interactive flags: ","translated":"非交互标志: ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:47:05Z"}
{"cache_key":"cc906618700533ea8dd9d752b8e2ef28ffb8707654a557d7cef1b867cdd57f1a","segment_id":"index.md:ceee4f2088b9d5ba","source_path":"index.md","text_hash":"ceee4f2088b9d5ba7d417bac7395003acfbcef576fd4cc1dd3063972f038218a","text":"The name","translated":"名称","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:54:01Z"}
{"cache_key":"cc93bf5458542a509cb8460472bf3269d769fe1cdee6201ab736c4b5460d64d5","segment_id":"start/wizard.md:4bba41aa0148ebb4","source_path":"start/wizard.md","text_hash":"4bba41aa0148ebb49b33763f1b38a983af7c0a4dd22fff07d3cf94fdcb96ecd3","text":"Linux (and Windows via WSL2): systemd user unit","translated":"Linux以及通过 WSL2 的 Windowssystemd 用户单元","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:45:17Z"}
{"cache_key":"ccd10d490dbeb4a1e0c3b7b4ccf7653af6ff78a7d498755c92bf4a6c24b2aacd","segment_id":"environment.md:a42cc4a7174c83a8","source_path":"environment.md","text_hash":"a42cc4a7174c83a853752b3e74cb001a234f3eca099688fdf0dd2540c60bb1e2","text":" expected keys:","translated":" 预期密钥:","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:12:51Z"}
{"cache_key":"cd2d7cce6f1c10e008e8efe49ecf02b6ac401d686667986409f7e6796e9f1140","segment_id":"environment.md:45ca56d179d4788c","source_path":"environment.md","text_hash":"45ca56d179d4788c55ba9f7653b376d62e7faa738e92259e3d4f6f5c1b554f28","text":"Related","translated":"相关内容","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:22:44Z"}
{"cache_key":"cd4cdcf85e185ce70df30cbda64fb2d77baa6a6c989e67cde3f80315c06b3839","segment_id":"index.md:45e6d69dbe995a36","source_path":"index.md","text_hash":"45e6d69dbe995a36f7bc20755eff4eb4d2afaaedbcac4668ab62540c57219f32","text":"macOS app","translated":"macOS 应用","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:53:33Z"}
{"cache_key":"cd82c395857efd6e374fec3ad86de5dd8989415770d38a86d8a1980cd372b7f5","segment_id":"start/wizard.md:c4e77a12a2c0b664","source_path":"start/wizard.md","text_hash":"c4e77a12a2c0b664f398de857da71528f66ffb4a70e65769897dcc7147167b2c","text":" or use allowlists.","translated":" 批准,或使用允许名单。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:45:05Z"}
@@ -1067,6 +1098,7 @@
{"cache_key":"ce3c2713f373fff6ebab9c70141debe3262d0a7ff6214fd146fa277b67c1ab3e","segment_id":"start/wizard.md:bd8a6e0ff884f51d","source_path":"start/wizard.md","text_hash":"bd8a6e0ff884f51d6a4a9b70f4680033876871936c72cf8af5df4e4b2836c75c","text":"Wizard runs a model check and warns if the configured model is unknown or missing auth.","translated":"向导会运行模型检查,如果配置的模型未知或缺少认证则发出警告。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:43:24Z"}
{"cache_key":"ce618de323766f3aa222b534fb69a1502c03699a6b57e801e6f1a1b3c32d3431","segment_id":"index.md:9abe8e9025013e78","source_path":"index.md","text_hash":"9abe8e9025013e78a6bf2913f8c20ee43134ad001ce29ced89e2af9c07096d8f","text":"Media: images","translated":"媒体:图片","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:53:25Z"}
{"cache_key":"ce62c5006939b21f7a2d236f9cdb545ce653778800504e85668fe99075067cbf","segment_id":"environment.md:6db0742daaf9f191","source_path":"environment.md","text_hash":"6db0742daaf9f191ab7816d2c9d317b1ea1693453a8c63b95af8b01477e0f5bb","text":" runs your login shell and imports only ","translated":" 运行你的登录 shell并仅导入 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:12:47Z"}
{"cache_key":"cebc7667fbb15ccecd6359fe5ec38ae1ad00df26f18e56e7debd760a47d30a94","segment_id":"start/getting-started.md:2fa27cf15c3773de","source_path":"start/getting-started.md","text_hash":"2fa27cf15c3773deb54ae880d0f3250d86ef8c316abe07373f5f6a16df7afbed","text":" is also supported.","translated":" 也受支持。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:36:08Z"}
{"cache_key":"cf001b0403d7ae959797460c96aa4da24818c662362595f2da0be349caeb6a09","segment_id":"index.md:cda454f61dfcac70","source_path":"index.md","text_hash":"cda454f61dfcac7007a9edc538f9f58cf38caa0652e253975979308162bccc53","text":"Gateway configuration","translated":"Gateway 配置","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:00:31Z"}
{"cache_key":"cf9fc66b44905a0c47ca04f98d6e6507821789844f1e97ca2026f7df6e5b1451","segment_id":"environment.md:f7e239a42b7cd986","source_path":"environment.md","text_hash":"f7e239a42b7cd986a1558fed234e975ed2e96e9d37cf0a93f381778c461c89dd","text":"OpenClaw pulls environment variables from multiple sources. The rule is ","translated":"OpenClaw 从多个来源拉取 环境变量。规则是 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:57:11Z"}
{"cache_key":"cfc26997d872d590a2aba69f0aba6f704354d3aea9aa3bd433693ca7182cacdc","segment_id":"start/getting-started.md:1093115897879aa3","source_path":"start/getting-started.md","text_hash":"1093115897879aa3ad9511a1dc2850929cfb60ba45ec741605f69f5d20203472","text":"Runtime","translated":"运行时","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:36:17Z"}
@@ -1078,6 +1110,7 @@
{"cache_key":"d0f76abf14b1216bff9974f7e507a3c2a43f331f1ebd805279843692ae78f662","segment_id":"index.md:5cf9ea2e20780551","source_path":"index.md","text_hash":"5cf9ea2e2078055129b38cfbc394142ca6ca41556bd6e31cbd527425647c1d1e","text":"One Gateway per host (recommended)","translated":"每台主机一个 Gateway推荐","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:48:30Z"}
{"cache_key":"d12af03e20c20a4ebdcdbf4c32f52081339c0aa7bd1bb44b311875547bb39918","segment_id":"start/wizard.md:14a01a1b76ad6311","source_path":"start/wizard.md","text_hash":"14a01a1b76ad63111eb126c1d124a893abcb5cc90fe893825a9c96362112ab4f","text":" adds gateway health probes to status output (requires a reachable gateway).","translated":" 将 Gateway 健康探测添加到状态输出中(需要可达的 Gateway。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:45:41Z"}
{"cache_key":"d1818c531bc4e1cca14e64f751cf8698cb0701a745fb3da03b37b4fd7129c18b","segment_id":"start/wizard.md:6d0323ac97e5a313","source_path":"start/wizard.md","text_hash":"6d0323ac97e5a3136bae41278bfd46f5985969ee57dea5f25d7faa78bb01c87e","text":" when model is unset or ","translated":" (当模型未设置或为 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:42:24Z"}
{"cache_key":"d181ecac73ffcad6ec7afe0e692144db4ea470fa5de3a2d218f4b8127ad7d588","segment_id":"environment.md:28e19c6e69c7a2aa","source_path":"environment.md","text_hash":"28e19c6e69c7a2aa071951dda3ff0a11ca178e3fb295dae8d6ed7dcc994434a4","text":" for full details.","translated":" 了解完整详情。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:58:28Z"}
{"cache_key":"d1a349d8c1859f2d1c00367b86704fa95d4168c8615ada60834a6890215d1f58","segment_id":"index.md:3c064c83b8d244fe","source_path":"index.md","text_hash":"3c064c83b8d244fef61e5fd8ce5f070b857a3578a71745e61eea02892788c020","text":" — Anthropic (Claude Pro/Max) + OpenAI (ChatGPT/Codex) via OAuth","translated":" —— 通过 OAuth 支持 AnthropicClaude Pro/Max+ OpenAIChatGPT/Codex","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:50:28Z"}
{"cache_key":"d1d30ee69fb8519a966ebbb5cb51d2be029399b2951ef296b23f96d3fea4bc3a","segment_id":"start/wizard.md:3fad3d2e2c01a9ea","source_path":"start/wizard.md","text_hash":"3fad3d2e2c01a9ea3a66cbcb1b05a0d5982e3665cf0e1ec6dee0e031e83137e1","text":"Reads the available skills and checks requirements.","translated":"读取可用技能并检查依赖条件。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:45:43Z"}
{"cache_key":"d234d82b06f65337a5ab45e775d0f0abda696d4e04e6115c6a042853b3b11ca4","segment_id":"index.md:084514e91f37c3ce","source_path":"index.md","text_hash":"084514e91f37c3ce85360e26c70b77fdc95f0d3551ce309db96fbcf956a53b01","text":"Dashboard (browser Control UI)","translated":"仪表板(浏览器控制界面)","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:48:04Z"}
@@ -1118,6 +1151,7 @@
{"cache_key":"d8fe9f40df201863d43f4937a52bac7d14019fae82150f1191fe4bb66819d827","segment_id":"help/index.md:3c33340bd23b8db8","source_path":"help/index.md","text_hash":"3c33340bd23b8db89f18fe7d05a954738c0dd5ba9623cf6bdb7bb5d1a3729cfc","text":"FAQ (concepts)","translated":"常见问题(概念)","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:11:34Z"}
{"cache_key":"d93001811d4774893fac9a800d8e9c14259b90fc5ed85a3e5e6d381bfb591846","segment_id":"index.md:32ebb1abcc1c601c","source_path":"index.md","text_hash":"32ebb1abcc1c601ceb9c4e3c4faba0caa5b85bb98c4f1e6612c40faa528a91c9","text":" (","translated":" ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:28:10Z"}
{"cache_key":"d952c24b47cb7a9f69823c976f2f5e103fdc731a8bd74cae1436d86f420022df","segment_id":"environment.md:frontmatter:read_when:1","source_path":"environment.md:frontmatter:read_when:1","text_hash":"a3a2d99a99de98220c8e0296d6f4e4b2a34024916bd2379d1b3b9179c8fae46f","text":"You are debugging missing API keys in the Gateway","translated":"你正在调试 Gateway 中缺失的 API 密钥","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:21:50Z"}
{"cache_key":"d963cbde28040dde98de9fd8684bb5552ff2ba0e13e2c9921a8e36d90d7237a4","segment_id":"index.md:58d30d963f28264b","source_path":"index.md","text_hash":"58d30d963f28264bd9ba0e2d4c07c2c43c0ac1c1609c25b3fccf475eebf41727","text":"Skills config","translated":"技能配置","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:32:15Z"}
{"cache_key":"d972ebc19ef87492ca8c11159fd6342cced6b4e19743d79d81ae33fafe35bbd8","segment_id":"environment.md:f7e239a42b7cd986","source_path":"environment.md","text_hash":"f7e239a42b7cd986a1558fed234e975ed2e96e9d37cf0a93f381778c461c89dd","text":"OpenClaw pulls environment variables from multiple sources. The rule is ","translated":"OpenClaw 从多个来源获取环境变量。规则是 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:21:57Z"}
{"cache_key":"d9923f60f9531ccaaefa870fa682febfe862bf9a38ced5baa99ea8637d7fc5ae","segment_id":"start/getting-started.md:63d3b285bad7d501","source_path":"start/getting-started.md","text_hash":"63d3b285bad7d5015cea4d6e62f972e83221dfce48c6919bd536c5e894a6607d","text":" set an API key (wizard can store it for service use). ","translated":" 设置 API 密钥(向导可以将其存储以供服务使用)。 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:36:32Z"}
{"cache_key":"d9b22590788b6c0abf9a15102d23d2aeb6608cf4acc0339e69be4e52ae38af48","segment_id":"index.md:f9b8279bc46e847b","source_path":"index.md","text_hash":"f9b8279bc46e847bfcc47b8701fd5c5dc27baa304d5add8278a7f97925c3ec13","text":"Mattermost (plugin)","translated":"Mattermost插件","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:53:18Z"}
@@ -1133,6 +1167,7 @@
{"cache_key":"dbec24d595565c4c294a91f556c491976ccdeb4f7976d9258e6420af47259608","segment_id":"help/index.md:24669ff48290c187","source_path":"help/index.md","text_hash":"24669ff48290c1875d8067bbd241e8a55444839747bffb8ab99f3a34ef248436","text":"Doctor","translated":"诊断","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:11:29Z"}
{"cache_key":"dbeeb5b2ad003e4152107ceade1290b2001163df5f2fb93a792c8c9d94cec345","segment_id":"start/getting-started.md:922f3f28b57bdd14","source_path":"start/getting-started.md","text_hash":"922f3f28b57bdd146b8892adf494a28a0969d5eaf21333bfdb314db2eb6c8da8","text":"Installer options (install method, non-interactive, from GitHub): ","translated":"安装选项(安装方式、非交互式、从 GitHub 安装): ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:35:48Z"}
{"cache_key":"dbf5bae2a9b91c346475334bdb1294ace20ee07ca1e471c488c5311579ef37ab","segment_id":"index.md:b0d125182029e6c5","source_path":"index.md","text_hash":"b0d125182029e6c500cbcc81011341df77de8fe24d9e80190c32be390c916ec2","text":"🤖 ","translated":"🤖 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:49:58Z"}
{"cache_key":"dc16a7d72c37b5b48ed3034555c195ab7432617c1a8182e92d98e23f1051f615","segment_id":"index.md:f14185309c5ab262","source_path":"index.md","text_hash":"f14185309c5ab26233fde49831f9fc27857a6e7ac200e91dc247ae3e3b74be27","text":"Companion apps:","translated":"伴侣应用:","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:53:30Z"}
{"cache_key":"dc745b075f86ec95e5a22fbb2ba14c5a6f2c00911dfa570cbe2f5123627e887d","segment_id":"environment.md:f15f5f9f4ef4d668","source_path":"environment.md","text_hash":"f15f5f9f4ef4d6688876c894f8eba251ed1db6eaf2209084028d43c9e76a8ba1","text":" (aka ","translated":" (即 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:40:44Z"}
{"cache_key":"dc8c80f84e5339af07824daa81e39f2801c9d6beb851b21e632b3eb6ddf79749","segment_id":"start/wizard.md:4b2a013a2a09958e","source_path":"start/wizard.md","text_hash":"4b2a013a2a09958e251e8998bdfa5fd89cc1c69abb1273fe2c1522cf54363cc6","text":"JVM builds require ","translated":"JVM 构建需要 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:48:09Z"}
{"cache_key":"dcb357452715d4a3fee760c79dfdee6719f235e48d176456a053646ffae10f44","segment_id":"environment.md:d08a8493f686363a","source_path":"environment.md","text_hash":"d08a8493f686363a78b913d45ebfbd87a3768d1c77b70f23b1fdade3c066e481","text":"Shell env import","translated":"Shell 环境导入","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:58:04Z"}
@@ -1182,6 +1217,7 @@
{"cache_key":"e5b4eab0ca38617f4b76c99dc5fa36151812c02576b33f954a56cf5f77703696","segment_id":"index.md:bf0e823c81b87c5d","source_path":"index.md","text_hash":"bf0e823c81b87c5de79676155debf20a29b52d6d7eb7e77deda73a56d0afbaaa","text":"🧠 ","translated":"🧠 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:30:08Z"}
{"cache_key":"e5be378ff2d92da3de35b20680f90f5d1aa0a98ce205139d6fcaeac91ef06f65","segment_id":"index.md:9bcda844990ec646","source_path":"index.md","text_hash":"9bcda844990ec646b3b6ee63cbdf10f70b0403727dea3b5ab601ca55e3949db9","text":" for node WebViews; see ","translated":" 用于节点 WebView参见 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:49:04Z"}
{"cache_key":"e5d655052f08f79672770734c9717dc24a5a9359defba7095dc7a9e2cf9e801b","segment_id":"start/wizard.md:bba52d8bacabbacc","source_path":"start/wizard.md","text_hash":"bba52d8bacabbacc510a1902b4eb35435f691903eb2db22fd110d41eadedec8d","text":" exists, the wizard can reuse it.","translated":" 存在,向导可以复用它。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:42:13Z"}
{"cache_key":"e5febac01358bd99e804e54a33e30d0d88ea12bcab990c3e29c66351fb5a598f","segment_id":"index.md:41dc1288a547d7d1","source_path":"index.md","text_hash":"41dc1288a547d7d155c2d7b831e8cff388e12ab9d77d4c24cd0757ed47e9e209","text":" — Block streaming + Telegram draft streaming details (","translated":" —— 块流式传输 + Telegram 草稿流式传输详情(","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:50:10Z"}
{"cache_key":"e628a7773be8d41e10dc53dcb383a11096e0573ec6b470aa13d2a14adcefb8e7","segment_id":"start/wizard.md:e3ba8a2959965f9c","source_path":"start/wizard.md","text_hash":"e3ba8a2959965f9c8360537e304016b2f75d561bdb03655a42adb02ce75a0e3f","text":"Default workspaces follow ","translated":"默认工作区遵循 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:46:57Z"}
{"cache_key":"e62ed5670f8283396dcc6a81182cda94667ff98973f153e4c86a04db364a4895","segment_id":"start/wizard.md:a8dbd136ed7c8e55","source_path":"start/wizard.md","text_hash":"a8dbd136ed7c8e55f9c0ae6e5acd2576d485f642d964a61f3693afc1c0c4ffdf","text":": uses ","translated":":使用 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:41:50Z"}
{"cache_key":"e66b34ec94f9a9c10b99b098ad8806551356222f1ac50f6fec7d719991faceee","segment_id":"start/wizard.md:c36d819e7bc6d2b7","source_path":"start/wizard.md","text_hash":"c36d819e7bc6d2b7da51394411c733db89c395987885ca6770167a3b9bc45c3c","text":"Use ","translated":"使用 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:46:45Z"}
@@ -1189,6 +1225,7 @@
{"cache_key":"e6b4ca13a3b7e39f521b1aadbb4f54f37875d228cd918c6406bd6519d5c7b6c8","segment_id":"index.md:6638cf2301d3109d","source_path":"index.md","text_hash":"6638cf2301d3109da66a44ee3506fbd35b29773fa4ca33ff35eb838c21609e19","text":"Features (high level)","translated":"功能特性(概览)","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:29:26Z"}
{"cache_key":"e6e2a9985237253e0478229a54f3693bc7b0472bc450d53a4122dc20dfe08b21","segment_id":"environment.md:6863067eb0a2c749","source_path":"environment.md","text_hash":"6863067eb0a2c7499425c6c189b2c88bac55ca754285a6ab1ef37b75b4cfad4d","text":"See ","translated":"参见 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:22:37Z"}
{"cache_key":"e6e456289628d5a4b6cbbc0fbb263d656ba7d49427a2009ce3c5f608b8505ea0","segment_id":"index.md:f0d82ba647b4a33d","source_path":"index.md","text_hash":"f0d82ba647b4a33da3008927253f9bed21e380f54eab0608b1136de4cbff1286","text":"OpenClaw bridges WhatsApp (via WhatsApp Web / Baileys), Telegram (Bot API / grammY), Discord (Bot API / channels.discord.js), and iMessage (imsg CLI) to coding agents like ","translated":"OpenClaw 将 WhatsApp通过 WhatsApp Web / Baileys、TelegramBot API / grammY、DiscordBot API / channels.discord.js和 iMessageimsg CLI桥接到编程 智能体,例如 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:58:56Z"}
{"cache_key":"e6ede2965d77195fa0296a69f8dc8beb3a2fee2b0264180126200d4adbaf4aa3","segment_id":"index.md:f14185309c5ab262","source_path":"index.md","text_hash":"f14185309c5ab26233fde49831f9fc27857a6e7ac200e91dc247ae3e3b74be27","text":"Companion apps:","translated":"伴侣应用:","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:32:51Z"}
{"cache_key":"e723a0b2ab360a74b84f4ccd08fdc4cc1639b85d5178d45d8103a18069bd3d8d","segment_id":"start/getting-started.md:1b59a1d9fa6d392f","source_path":"start/getting-started.md","text_hash":"1b59a1d9fa6d392f1f68642200583ed0f7b372af2fbc7c01d5f7f00463e229de","text":" also bundles A2UI assets; if you need to run just that step, use ","translated":" 也会打包 A2UI 资源;如果您只需要运行该步骤,请使用 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:37:51Z"}
{"cache_key":"e7279b78eeb5dccdf1897af612ce9f34bbae6f6ad7d8a7fed40a48f2f59c2367","segment_id":"environment.md:frontmatter:summary","source_path":"environment.md:frontmatter:summary","text_hash":"78351223e7068721146d2de022fdf440c2866b2ee02fbbb50bf64369b999820b","text":"Where OpenClaw loads environment variables and the precedence order","translated":"OpenClaw 加载环境变量的位置及优先级顺序","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:25:05Z"}
{"cache_key":"e73887cca1549bd1acf945a50dfbd054a3ec1c87741be5a0a4381a4840ce13e5","segment_id":"index.md:1df4f2299f0d9cc4","source_path":"index.md","text_hash":"1df4f2299f0d9cc466fa05abeb2831e76e9f89583228174ffcd9af415fd869fe","text":"Send a test message (requires a running Gateway):","translated":"发送测试消息(需要运行中的 Gateway","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:03:17Z"}
@@ -1198,6 +1235,7 @@
{"cache_key":"e7bc8ffa042426610faa9c40c7191933bfda50deb769ef153580d4ab1c75d679","segment_id":"start/getting-started.md:cdb4ee2aea69cc6a","source_path":"start/getting-started.md","text_hash":"cdb4ee2aea69cc6a83331bbe96dc2caa9a299d21329efb0336fc02a82e1839a8","text":".","translated":"。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:34:45Z"}
{"cache_key":"e8160fc2a7763ac99c0933d4424a99f211b661b0d7649bb1d33f908c3ff5e0d2","segment_id":"start/getting-started.md:75e23f5184b23835","source_path":"start/getting-started.md","text_hash":"75e23f5184b23835efb6fdc64309312d3c9212d10566350b1a08ff7838c79d03","text":"2) Run the onboarding wizard (and install the service)","translated":"2运行上手引导向导并安装服务","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:35:55Z"}
{"cache_key":"e81fa8ea81e681a305d677a823722958c2fdf42c3afbf4149a2d5cdfc4c6e1df","segment_id":"index.md:4eb58187170dc141","source_path":"index.md","text_hash":"4eb58187170dc14198eacb534c8577bef076349c26f2479e1f6a2e31df8eb948","text":" — An AI, probably high on tokens","translated":" — 一个可能被令牌冲昏头脑的 AI","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:06:53Z"}
{"cache_key":"e83550368cc1a10f9407b5e8da39dc639896bb6669eca7e49f6107ff3a3c306c","segment_id":"environment.md:e4255aa4e8f9e525","source_path":"environment.md","text_hash":"e4255aa4e8f9e52571c9bc93336d0774bcd7f017b7b5297fb33b8e1986166f92","text":"), applied only for missing expected keys.","translated":"),仅对缺失的预期密钥应用。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:41:05Z"}
{"cache_key":"e87435d09fd52a520aeae4097eb83a149aeb498192ccfbdd63da8db57571de09","segment_id":"index.md:d08cec54f66c140c","source_path":"index.md","text_hash":"d08cec54f66c140c655a1631f6d629927c7c38b9c8bfa91c875df9bd3ad3c559","text":"OpenClaw assistant setup","translated":"OpenClaw 助手设置","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:32:12Z"}
{"cache_key":"e8a313447619fd5d7895acf1c467e347d47a8c35861910facf5ff08f88a8905e","segment_id":"index.md:5928d14b4d45263d","source_path":"index.md","text_hash":"5928d14b4d45263d4964dfd301c84ed2674ca8b4b698c5efeb88fb86076d2bf9","text":"🎮 ","translated":"🎮 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:29:39Z"}
{"cache_key":"e8bfa9777ff1ca6f2921ef47688f6ddb7d1a68c074dc27c7af195521940fb68f","segment_id":"help/index.md:frontmatter:summary","source_path":"help/index.md:frontmatter:summary","text_hash":"aece82a2d540ab1a9a21c7b038127cae6e9db2149491564bb1856b6f8999f205","text":"Help hub: common fixes, install sanity, and where to look when something breaks","translated":"帮助中心:常见修复方法、安装完整性检查,以及出现问题时的排查指南","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:39:25Z"}
@@ -1219,9 +1257,11 @@
{"cache_key":"eca7489e62538a4b68a7d49f3a67df1c6bad8affc75d6411f68ca1e81bef47b2","segment_id":"environment.md:f6b2ffe1d0d5f521","source_path":"environment.md","text_hash":"f6b2ffe1d0d5f521b76cabc67d6e96da2b1170eef8086d530558e9906a7f092d","text":"Models overview","translated":"模型概览","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:13:17Z"}
{"cache_key":"ecb4df64e132ff6212066948863adabaa06122c77d8971d5c924dc2e744df845","segment_id":"index.md:98a670e2fb754896","source_path":"index.md","text_hash":"98a670e2fb7548964e8b78b90fef47f679580423427bfd15e5869aca9681d0dd","text":"\"We're all just playing with our own prompts.\"","translated":"\"我们都只是在玩弄自己的提示词。\"","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:05:43Z"}
{"cache_key":"ecd894720faa37450014e0fe1630be8382cf6ec23cbb9bfe76bc4125495d8fa5","segment_id":"index.md:9adcfa4aa10a4e8b","source_path":"index.md","text_hash":"9adcfa4aa10a4e8b991a72ccc45261cd64f296aed5b257e4caf9c87aff1290a0","text":" — Send and receive images, audio, documents","translated":" — 收发图片、音频、文档","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:30:38Z"}
{"cache_key":"ed00b197a3002ae69c3929cf870943136f802bf17b2850a71b6091111b76527d","segment_id":"environment.md:28e19c6e69c7a2aa","source_path":"environment.md","text_hash":"28e19c6e69c7a2aa071951dda3ff0a11ca178e3fb295dae8d6ed7dcc994434a4","text":" for full details.","translated":" 了解完整详情。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:26:33Z"}
{"cache_key":"ed10c233aa195883b17061f166f647efac5a27535a85ce4d16fc90d40e138882","segment_id":"help/index.md:8cd501e1124c3047","source_path":"help/index.md","text_hash":"8cd501e1124c30473473c06e536a2d145e2a14a6d7dc1b99028ce818e14442e2","text":"Repairs:","translated":"修复:","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:39:56Z"}
{"cache_key":"ed15427258ffbf85620a0c9c0c42deb7f37be17b7abeff5993a34962964f0e96","segment_id":"index.md:a194ca16424ddd17","source_path":"index.md","text_hash":"a194ca16424ddd17dacc45f1cbd7d0e41376d8955a7b6d02bc38c295cedd04e4","text":"RPC adapters","translated":"RPC 适配器","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:32:19Z"}
{"cache_key":"ed24753e60b54d629cfd978be87185f4772676322534432302319caf28452d29","segment_id":"index.md:ab201ddd7ab330d0","source_path":"index.md","text_hash":"ab201ddd7ab330d04be364c0ac14ce68c52073a0ee8d164a98c3034e91ce1848","text":" from the repo.","translated":" (在仓库目录中执行)。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:31:21Z"}
{"cache_key":"ed366700bbcca6548c3fb1f7dae544b9a9cb0c56d6b36ca8e26c4880bc4e5667","segment_id":"environment.md:28e19c6e69c7a2aa","source_path":"environment.md","text_hash":"28e19c6e69c7a2aa071951dda3ff0a11ca178e3fb295dae8d6ed7dcc994434a4","text":" for full details.","translated":" 了解完整详情。","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:17:08Z"}
{"cache_key":"ed37a2b1a8c3351a6c04bee81df6f507f306be344485e69eb87b3b2451aad89f","segment_id":"help/index.md:d3ef01b4a9c99103","source_path":"help/index.md","text_hash":"d3ef01b4a9c9910364c9b26b2499c8787a0461d2d24ab80376fff736a288b34c","text":"Logging","translated":"日志记录","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:24:47Z"}
{"cache_key":"ee3f1647acf674397ba7f7e1aee0f9972b9830f978b622695d8ab5360de5a496","segment_id":"index.md:255ce77b7a6a015f","source_path":"index.md","text_hash":"255ce77b7a6a015f8595868a524b67c134e8fb405f4584fdac020e57f4ccd5f6","text":"Loopback-first","translated":"回环优先","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:00:01Z"}
{"cache_key":"ee582fba5363de60fb2c00f9238f2ac9ad6dc7615694d8d23d24d88bf7ec13e1","segment_id":"environment.md:582967534d0f909d","source_path":"environment.md","text_hash":"582967534d0f909d196b97f9e6921342777aea87b46fa52df165389db1fb8ccf","text":" in ","translated":" 在 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:16:29Z"}
@@ -1251,6 +1291,7 @@
{"cache_key":"f2a0941718593a4be66a7a033a4117a7b3a502ef64b25fd7d6d3475c77dd5a1a","segment_id":"environment.md:87e89abb4c1c551f","source_path":"environment.md","text_hash":"87e89abb4c1c551fe08d355d097f18b8de78edca5f556997085681662fce8eed","text":"Config ","translated":"配置 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:16:24Z"}
{"cache_key":"f2a0c70d8b9f94722b586320f11c58339d30dd1fe8ff7250a962bb2db84d5ab4","segment_id":"environment.md:ffa63583dfa6706b","source_path":"environment.md","text_hash":"ffa63583dfa6706b87d284b86b0d693a161e4840aad2c5cf6b5d27c3b9621f7d","text":"missing","translated":"缺失的","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:58:09Z"}
{"cache_key":"f2c14989f888bbff9c7330f2d5b3892af3b900910840435595031590dc8248e3","segment_id":"environment.md:frontmatter:read_when:0","source_path":"environment.md:frontmatter:read_when:0","text_hash":"90fc0487bff88009979cff1061c1a882df8c3b1baa9c43538331d9d5dab15479","text":"You need to know which env vars are loaded, and in what order","translated":"你需要了解加载了哪些环境变量,以及它们的加载顺序","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:15:47Z"}
{"cache_key":"f2e6682f149332f775039f6c872837c04dbab51ea935ed4fe0085aa2a75cabe6","segment_id":"environment.md:a42cc4a7174c83a8","source_path":"environment.md","text_hash":"a42cc4a7174c83a853752b3e74cb001a234f3eca099688fdf0dd2540c60bb1e2","text":" expected keys:","translated":" 预期密钥:","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:41:18Z"}
{"cache_key":"f34789e2cb492196e8c057294dd98c5f9d4b8054d548a7b883a47f113efa1277","segment_id":"index.md:31365ab9453d6a1e","source_path":"index.md","text_hash":"31365ab9453d6a1ec03731622803d3b44f345b6afad08040d7f3e97290c77913","text":"do nothing","translated":"不做任何操作","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:51:55Z"}
{"cache_key":"f36f13a67a73f6768bfbf346d552067475ef4f8137e13edfd4f636e1b7ef2ef8","segment_id":"start/getting-started.md:649cfa2f76a80b42","source_path":"start/getting-started.md","text_hash":"649cfa2f76a80b42e1821c89edd348794689409dcdf619dcd10624fb577c676b","text":"not recommended","translated":"不推荐","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:36:21Z"}
{"cache_key":"f3701b1ce8ac7f8931cafd209250aa5ae388ecfdb0154dbbb21c03fd72ce5d08","segment_id":"help/index.md:729bc562eec2658b","source_path":"help/index.md","text_hash":"729bc562eec2658bd11ffdd522fe5277177dc73e86eaca7baac0b472a4d8f8b2","text":"If youre looking for conceptual questions (not “something broke”):","translated":"如果你在寻找概念性问题(不是\"某个东西坏了\"","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:11:29Z"}
@@ -1299,6 +1340,7 @@
{"cache_key":"fab1c40ef11182f7118f5528b5ba6ed5b5c169c37b302382107e3fbab3d200c1","segment_id":"index.md:3d8fed7c358b2ccf","source_path":"index.md","text_hash":"3d8fed7c358b2ccf225ee16857a0bb9b950fd414319749e0f6fff58c99fa5f22","text":"Subscription auth","translated":"订阅认证","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:50:25Z"}
{"cache_key":"fae191ae8b8380df30a34afd63fc9ba9125258cee9f76e625da9a9c41a858973","segment_id":"start/wizard.md:158ac20b77d1dc12","source_path":"start/wizard.md","text_hash":"158ac20b77d1dc1223a47723e75f03b49fe61d0a6d69de4c3bba9fdd4c123c04","text":" only configures the local client to connect to a Gateway elsewhere.\nIt does ","translated":" 仅配置本地客户端以连接到其他位置的 Gateway。它 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:40:36Z"}
{"cache_key":"faf6394b29b7de4f1af4a5c01405a2c33d4a1f8f58691915d75eedd3572b1d49","segment_id":"index.md:a7a19d4f14d001a5","source_path":"index.md","text_hash":"a7a19d4f14d001a56c27f68a13ff267859a407c7a9ab457c0945693c9067dd1c","text":"Configuration (optional)","translated":"配置(可选)","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:03:21Z"}
{"cache_key":"fb2cd6f6a8308f9b9ad6cb30dec3a08de2db675e77bc696aeb2ddb3084c9a6c4","segment_id":"start/wizard.md:58d30d963f28264b","source_path":"start/wizard.md","text_hash":"58d30d963f28264bd9ba0e2d4c07c2c43c0ac1c1609c25b3fccf475eebf41727","text":"Skills config","translated":"技能配置","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:49:20Z"}
{"cache_key":"fc41f7c0ff1d82b20353a8a79f2da756675af014a48e1c36b3e693e2030aca4c","segment_id":"help/index.md:6201111b83a0cb5b","source_path":"help/index.md","text_hash":"6201111b83a0cb5b0922cb37cc442b9a40e24e3b1ce100a4bb204f4c63fd2ac0","text":" and ","translated":" 和 ","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:39:50Z"}
{"cache_key":"fc43ec1fbbcff82d8d617e73687d1fa0c004b3fa731fdb6c9a1b0825ac2df2f5","segment_id":"start/wizard.md:d80c4025fe9728d6","source_path":"start/wizard.md","text_hash":"d80c4025fe9728d67b8330bdbb25a3062c7748ae6779d348b66687d5a796550f","text":"Gateway wizard RPC","translated":"Gateway 向导 RPC","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T13:47:41Z"}
{"cache_key":"fc503e5044847f8c5412b75ba55ec912df5577a3bc37a7a975393684059d9c12","segment_id":"environment.md:61115f6649792387","source_path":"environment.md","text_hash":"61115f664979238731a390e84433a818965b7eaf1d38fa5b4b1507c33ef28c91","text":"Precedence (highest → lowest)","translated":"优先级(从高到低)","provider":"pi","model":"claude-opus-4-5","src_lang":"en","tgt_lang":"zh-CN","updated_at":"2026-02-01T12:16:00Z"}

View File

@@ -1,667 +0,0 @@
(() => {
if (document.getElementById("docs-chat-root")) return;
// Determine if we're on the docs site or embedded elsewhere
const hostname = window.location.hostname;
const isDocsSite = hostname === "localhost" || hostname === "127.0.0.1" ||
hostname.includes("docs.openclaw") || hostname.endsWith(".mintlify.app");
const assetsBase = isDocsSite ? "" : "https://docs.openclaw.ai";
const apiBase = "https://claw-api.openknot.ai/api";
// Load marked for markdown rendering (via CDN)
let markedReady = false;
const loadMarkdownLib = () => {
if (window.marked) {
markedReady = true;
return;
}
const script = document.createElement("script");
script.src = "https://cdn.jsdelivr.net/npm/marked@15.0.6/marked.min.js";
script.onload = () => {
if (window.marked) {
markedReady = true;
}
};
script.onerror = () => console.warn("Failed to load marked library");
document.head.appendChild(script);
};
loadMarkdownLib();
// Markdown renderer with fallback before module loads
const renderMarkdown = (text) => {
if (markedReady && window.marked) {
// Configure marked for security: disable HTML pass-through
const html = window.marked.parse(text, { async: false, gfm: true, breaks: true });
// Open links in new tab by rewriting <a> tags
return html.replace(/<a href="/g, '<a target="_blank" rel="noopener" href="');
}
// Fallback: escape HTML and preserve newlines
return text
.replace(/&/g, "&amp;")
.replace(/</g, "&lt;")
.replace(/>/g, "&gt;")
.replace(/\n/g, "<br>");
};
const style = document.createElement("style");
style.textContent = `
#docs-chat-root { position: fixed; right: 20px; bottom: 20px; z-index: 9999; font-family: var(--font-body, system-ui, -apple-system, sans-serif); }
#docs-chat-root.docs-chat-expanded { right: 0; bottom: 0; top: 0; }
/* Thin scrollbar styling */
#docs-chat-root ::-webkit-scrollbar { width: 6px; height: 6px; }
#docs-chat-root ::-webkit-scrollbar-track { background: transparent; }
#docs-chat-root ::-webkit-scrollbar-thumb { background: var(--docs-chat-panel-border); border-radius: 3px; }
#docs-chat-root ::-webkit-scrollbar-thumb:hover { background: var(--docs-chat-muted); }
#docs-chat-root * { scrollbar-width: thin; scrollbar-color: var(--docs-chat-panel-border) transparent; }
:root {
--docs-chat-accent: var(--accent, #ff7d60);
--docs-chat-text: #1a1a1a;
--docs-chat-muted: #555;
--docs-chat-panel: rgba(255, 255, 255, 0.92);
--docs-chat-panel-border: rgba(0, 0, 0, 0.1);
--docs-chat-surface: rgba(250, 250, 250, 0.95);
--docs-chat-shadow: 0 18px 50px rgba(0,0,0,0.15);
--docs-chat-code-bg: rgba(0, 0, 0, 0.05);
--docs-chat-assistant-bg: #f5f5f5;
}
html[data-theme="dark"] {
--docs-chat-text: #e8e8e8;
--docs-chat-muted: #aaa;
--docs-chat-panel: rgba(28, 28, 30, 0.95);
--docs-chat-panel-border: rgba(255, 255, 255, 0.12);
--docs-chat-surface: rgba(38, 38, 40, 0.95);
--docs-chat-shadow: 0 18px 50px rgba(0,0,0,0.5);
--docs-chat-code-bg: rgba(255, 255, 255, 0.08);
--docs-chat-assistant-bg: #2a2a2c;
}
#docs-chat-button {
display: inline-flex;
align-items: center;
gap: 10px;
background: linear-gradient(140deg, rgba(255,90,54,0.25), rgba(255,90,54,0.06));
color: var(--docs-chat-text);
border: 1px solid rgba(255,90,54,0.4);
border-radius: 999px;
padding: 10px 14px;
cursor: pointer;
box-shadow: 0 8px 30px rgba(255,90,54, 0.08);
backdrop-filter: blur(12px);
-webkit-backdrop-filter: blur(12px);
font-family: var(--font-pixel, var(--font-body, system-ui, sans-serif));
}
#docs-chat-button span { font-weight: 600; letter-spacing: 0.04em; font-size: 14px; }
.docs-chat-logo { width: 20px; height: 20px; }
#docs-chat-panel {
width: min(440px, calc(100vw - 40px));
height: min(696px, calc(100vh - 80px));
background: var(--docs-chat-panel);
color: var(--docs-chat-text);
border-radius: 16px;
border: 1px solid var(--docs-chat-panel-border);
box-shadow: var(--docs-chat-shadow);
display: none;
flex-direction: column;
overflow: hidden;
backdrop-filter: blur(16px);
-webkit-backdrop-filter: blur(16px);
}
#docs-chat-root.docs-chat-expanded #docs-chat-panel {
width: min(512px, 100vw);
height: 100vh;
height: 100dvh;
border-radius: 18px 0 0 18px;
padding-top: env(safe-area-inset-top, 0);
padding-bottom: env(safe-area-inset-bottom, 0);
}
@media (max-width: 520px) {
#docs-chat-root.docs-chat-expanded #docs-chat-panel {
width: 100vw;
border-radius: 0;
}
#docs-chat-root.docs-chat-expanded { right: 0; left: 0; bottom: 0; top: 0; }
}
#docs-chat-header {
padding: 12px 14px;
font-weight: 600;
font-family: var(--font-pixel, var(--font-body, system-ui, sans-serif));
letter-spacing: 0.03em;
border-bottom: 1px solid var(--docs-chat-panel-border);
display: flex;
justify-content: space-between;
align-items: center;
}
#docs-chat-header-title { display: inline-flex; align-items: center; gap: 8px; }
#docs-chat-header-title span { color: var(--docs-chat-text); font-size: 15px; }
#docs-chat-header-actions { display: inline-flex; align-items: center; gap: 6px; }
.docs-chat-icon-button {
border: 1px solid var(--docs-chat-panel-border);
background: transparent;
color: inherit;
border-radius: 8px;
width: 30px;
height: 30px;
cursor: pointer;
font-size: 16px;
line-height: 1;
}
#docs-chat-messages { flex: 1; padding: 12px 14px; overflow: auto; background: transparent; }
#docs-chat-input {
display: flex;
gap: 8px;
padding: 12px 14px;
border-top: 1px solid var(--docs-chat-panel-border);
background: var(--docs-chat-surface);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
}
#docs-chat-input textarea {
flex: 1;
resize: none;
border: 1px solid var(--docs-chat-panel-border);
border-radius: 10px;
padding: 9px 10px;
font-size: 14px;
line-height: 1.5;
font-family: inherit;
color: var(--docs-chat-text);
background: var(--docs-chat-surface);
min-height: 42px;
max-height: 120px;
overflow-y: auto;
}
#docs-chat-input textarea::placeholder { color: var(--docs-chat-muted); }
#docs-chat-send {
background: var(--docs-chat-accent);
color: #fff;
border: none;
border-radius: 10px;
padding: 8px 14px;
cursor: pointer;
font-weight: 600;
font-family: inherit;
font-size: 14px;
transition: opacity 0.15s ease;
}
#docs-chat-send:hover { opacity: 0.9; }
#docs-chat-send:active { opacity: 0.8; }
.docs-chat-bubble {
margin-bottom: 10px;
padding: 10px 14px;
border-radius: 12px;
font-size: 14px;
line-height: 1.6;
max-width: 92%;
}
.docs-chat-user {
background: rgba(255, 125, 96, 0.15);
color: var(--docs-chat-text);
border: 1px solid rgba(255, 125, 96, 0.3);
align-self: flex-end;
white-space: pre-wrap;
margin-left: auto;
}
html[data-theme="dark"] .docs-chat-user {
background: rgba(255, 125, 96, 0.18);
border-color: rgba(255, 125, 96, 0.35);
}
.docs-chat-assistant {
background: var(--docs-chat-assistant-bg);
color: var(--docs-chat-text);
border: 1px solid var(--docs-chat-panel-border);
}
/* Markdown content styling for chat bubbles */
.docs-chat-assistant p { margin: 0 0 10px 0; }
.docs-chat-assistant p:last-child { margin-bottom: 0; }
.docs-chat-assistant code {
background: var(--docs-chat-code-bg);
padding: 2px 6px;
border-radius: 5px;
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
font-size: 0.9em;
}
.docs-chat-assistant pre {
background: var(--docs-chat-code-bg);
padding: 10px 12px;
border-radius: 8px;
overflow-x: auto;
margin: 6px 0;
font-size: 0.9em;
max-width: 100%;
white-space: pre;
word-wrap: normal;
}
.docs-chat-assistant pre::-webkit-scrollbar-thumb { background: transparent; }
.docs-chat-assistant pre:hover::-webkit-scrollbar-thumb { background: var(--docs-chat-panel-border); }
@media (hover: none) {
.docs-chat-assistant pre { -webkit-overflow-scrolling: touch; }
.docs-chat-assistant pre::-webkit-scrollbar-thumb { background: var(--docs-chat-panel-border); }
}
.docs-chat-assistant pre code {
background: transparent;
padding: 0;
font-size: inherit;
white-space: pre;
word-wrap: normal;
display: block;
}
/* Compact single-line code blocks */
.docs-chat-assistant pre.compact {
margin: 4px 0;
padding: 6px 10px;
}
/* Longer code blocks with copy button need extra top padding */
.docs-chat-assistant pre:not(.compact) {
padding-top: 28px;
}
.docs-chat-assistant a {
color: var(--docs-chat-accent);
text-decoration: underline;
text-underline-offset: 2px;
}
.docs-chat-assistant a:hover { opacity: 0.8; }
.docs-chat-assistant ul, .docs-chat-assistant ol {
margin: 8px 0;
padding-left: 18px;
list-style: none;
}
.docs-chat-assistant li {
margin: 4px 0;
position: relative;
padding-left: 14px;
}
.docs-chat-assistant li::before {
content: "•";
position: absolute;
left: 0;
color: var(--docs-chat-muted);
}
.docs-chat-assistant strong { font-weight: 600; }
.docs-chat-assistant em { font-style: italic; }
.docs-chat-assistant h1, .docs-chat-assistant h2, .docs-chat-assistant h3 {
font-weight: 600;
margin: 12px 0 6px 0;
line-height: 1.3;
}
.docs-chat-assistant h1 { font-size: 1.2em; }
.docs-chat-assistant h2 { font-size: 1.1em; }
.docs-chat-assistant h3 { font-size: 1.05em; }
.docs-chat-assistant blockquote {
border-left: 3px solid var(--docs-chat-accent);
margin: 10px 0;
padding: 4px 12px;
color: var(--docs-chat-muted);
background: var(--docs-chat-code-bg);
border-radius: 0 6px 6px 0;
}
.docs-chat-assistant hr {
border: none;
height: 1px;
background: var(--docs-chat-panel-border);
margin: 12px 0;
}
/* Copy buttons */
.docs-chat-assistant { position: relative; padding-top: 28px; }
.docs-chat-copy-response {
position: absolute;
top: 8px;
right: 8px;
background: var(--docs-chat-surface);
border: 1px solid var(--docs-chat-panel-border);
border-radius: 5px;
padding: 4px 8px;
font-size: 11px;
cursor: pointer;
color: var(--docs-chat-muted);
transition: color 0.15s ease, background 0.15s ease;
}
.docs-chat-copy-response:hover {
color: var(--docs-chat-text);
background: var(--docs-chat-code-bg);
}
.docs-chat-assistant pre {
position: relative;
}
.docs-chat-copy-code {
position: absolute;
top: 8px;
right: 8px;
background: var(--docs-chat-surface);
border: 1px solid var(--docs-chat-panel-border);
border-radius: 4px;
padding: 3px 7px;
font-size: 10px;
cursor: pointer;
color: var(--docs-chat-muted);
transition: color 0.15s ease, background 0.15s ease;
z-index: 1;
}
.docs-chat-copy-code:hover {
color: var(--docs-chat-text);
background: var(--docs-chat-code-bg);
}
/* Resize handle - left edge of expanded panel */
#docs-chat-resize-handle {
position: absolute;
left: 0;
top: 0;
bottom: 0;
width: 6px;
cursor: ew-resize;
z-index: 10;
display: none;
}
#docs-chat-root.docs-chat-expanded #docs-chat-resize-handle { display: block; }
#docs-chat-resize-handle::after {
content: "";
position: absolute;
left: 1px;
top: 50%;
transform: translateY(-50%);
width: 4px;
height: 40px;
border-radius: 2px;
background: var(--docs-chat-panel-border);
opacity: 0;
transition: opacity 0.15s ease, background 0.15s ease;
}
#docs-chat-resize-handle:hover::after,
#docs-chat-resize-handle.docs-chat-dragging::after {
opacity: 1;
background: var(--docs-chat-accent);
}
@media (max-width: 520px) {
#docs-chat-resize-handle { display: none !important; }
}
`;
document.head.appendChild(style);
const root = document.createElement("div");
root.id = "docs-chat-root";
const button = document.createElement("button");
button.id = "docs-chat-button";
button.type = "button";
button.innerHTML =
`<img class="docs-chat-logo" src="${assetsBase}/assets/pixel-lobster.svg" alt="OpenClaw">` +
`<span>Ask Molty</span>`;
const panel = document.createElement("div");
panel.id = "docs-chat-panel";
panel.style.display = "none";
// Resize handle for expandable sidebar width (desktop only)
const resizeHandle = document.createElement("div");
resizeHandle.id = "docs-chat-resize-handle";
const header = document.createElement("div");
header.id = "docs-chat-header";
header.innerHTML =
`<div id="docs-chat-header-title">` +
`<img class="docs-chat-logo" src="${assetsBase}/assets/pixel-lobster.svg" alt="OpenClaw">` +
`<span>OpenClaw Docs</span>` +
`</div>` +
`<div id="docs-chat-header-actions"></div>`;
const headerActions = header.querySelector("#docs-chat-header-actions");
const expand = document.createElement("button");
expand.type = "button";
expand.className = "docs-chat-icon-button";
expand.setAttribute("aria-label", "Expand");
expand.textContent = "⤢";
const clear = document.createElement("button");
clear.type = "button";
clear.className = "docs-chat-icon-button";
clear.setAttribute("aria-label", "Clear chat");
clear.textContent = "⌫";
const close = document.createElement("button");
close.type = "button";
close.className = "docs-chat-icon-button";
close.setAttribute("aria-label", "Close");
close.textContent = "×";
headerActions.appendChild(expand);
headerActions.appendChild(clear);
headerActions.appendChild(close);
const messages = document.createElement("div");
messages.id = "docs-chat-messages";
const inputWrap = document.createElement("div");
inputWrap.id = "docs-chat-input";
const textarea = document.createElement("textarea");
textarea.rows = 1;
textarea.placeholder = "Ask about OpenClaw Docs...";
// Auto-expand textarea as user types (up to max-height set in CSS)
const autoExpand = () => {
textarea.style.height = "auto";
textarea.style.height = Math.min(textarea.scrollHeight, 224) + "px";
};
textarea.addEventListener("input", autoExpand);
const send = document.createElement("button");
send.id = "docs-chat-send";
send.type = "button";
send.textContent = "Send";
inputWrap.appendChild(textarea);
inputWrap.appendChild(send);
panel.appendChild(resizeHandle);
panel.appendChild(header);
panel.appendChild(messages);
panel.appendChild(inputWrap);
root.appendChild(button);
root.appendChild(panel);
document.body.appendChild(root);
// Add copy buttons to assistant bubble
const addCopyButtons = (bubble, rawText) => {
// Add copy response button
const copyResponse = document.createElement("button");
copyResponse.className = "docs-chat-copy-response";
copyResponse.textContent = "Copy";
copyResponse.type = "button";
copyResponse.addEventListener("click", async () => {
try {
await navigator.clipboard.writeText(rawText);
copyResponse.textContent = "Copied!";
setTimeout(() => (copyResponse.textContent = "Copy"), 1500);
} catch (e) {
copyResponse.textContent = "Failed";
}
});
bubble.appendChild(copyResponse);
// Add copy buttons to code blocks (skip short/single-line blocks)
bubble.querySelectorAll("pre").forEach((pre) => {
const code = pre.querySelector("code") || pre;
const text = code.textContent || "";
const lineCount = text.split("\n").length;
const isShort = lineCount <= 2 && text.length < 100;
if (isShort) {
pre.classList.add("compact");
return; // Skip copy button for compact blocks
}
const copyCode = document.createElement("button");
copyCode.className = "docs-chat-copy-code";
copyCode.textContent = "Copy";
copyCode.type = "button";
copyCode.addEventListener("click", async (e) => {
e.stopPropagation();
try {
await navigator.clipboard.writeText(text);
copyCode.textContent = "Copied!";
setTimeout(() => (copyCode.textContent = "Copy"), 1500);
} catch (err) {
copyCode.textContent = "Failed";
}
});
pre.appendChild(copyCode);
});
};
const addBubble = (text, role, isMarkdown = false) => {
const bubble = document.createElement("div");
bubble.className =
"docs-chat-bubble " +
(role === "user" ? "docs-chat-user" : "docs-chat-assistant");
if (isMarkdown && role === "assistant") {
bubble.innerHTML = renderMarkdown(text);
} else {
bubble.textContent = text;
}
messages.appendChild(bubble);
messages.scrollTop = messages.scrollHeight;
return bubble;
};
let isExpanded = false;
let customWidth = null; // User-set width via drag
const MIN_WIDTH = 320;
const MAX_WIDTH = 800;
// Drag-to-resize logic
let isDragging = false;
let startX, startWidth;
resizeHandle.addEventListener("mousedown", (e) => {
if (!isExpanded) return;
isDragging = true;
startX = e.clientX;
startWidth = panel.offsetWidth;
resizeHandle.classList.add("docs-chat-dragging");
document.body.style.cursor = "ew-resize";
document.body.style.userSelect = "none";
e.preventDefault();
});
document.addEventListener("mousemove", (e) => {
if (!isDragging) return;
// Panel is on right, so dragging left increases width
const delta = startX - e.clientX;
const newWidth = Math.min(MAX_WIDTH, Math.max(MIN_WIDTH, startWidth + delta));
customWidth = newWidth;
panel.style.width = newWidth + "px";
});
document.addEventListener("mouseup", () => {
if (!isDragging) return;
isDragging = false;
resizeHandle.classList.remove("docs-chat-dragging");
document.body.style.cursor = "";
document.body.style.userSelect = "";
});
const setOpen = (isOpen) => {
panel.style.display = isOpen ? "flex" : "none";
button.style.display = isOpen ? "none" : "inline-flex";
root.classList.toggle("docs-chat-expanded", isOpen && isExpanded);
if (!isOpen) {
panel.style.width = ""; // Reset to CSS default when closed
} else if (isExpanded && customWidth) {
panel.style.width = customWidth + "px";
}
if (isOpen) textarea.focus();
};
const setExpanded = (next) => {
isExpanded = next;
expand.textContent = isExpanded ? "⤡" : "⤢";
expand.setAttribute("aria-label", isExpanded ? "Collapse" : "Expand");
if (panel.style.display !== "none") {
root.classList.toggle("docs-chat-expanded", isExpanded);
if (isExpanded && customWidth) {
panel.style.width = customWidth + "px";
} else if (!isExpanded) {
panel.style.width = ""; // Reset to CSS default
}
}
};
button.addEventListener("click", () => setOpen(true));
expand.addEventListener("click", () => setExpanded(!isExpanded));
clear.addEventListener("click", () => {
messages.innerHTML = "";
});
close.addEventListener("click", () => {
setOpen(false);
root.classList.remove("docs-chat-expanded");
});
const sendMessage = async () => {
const text = textarea.value.trim();
if (!text) return;
textarea.value = "";
textarea.style.height = "auto"; // Reset height after sending
addBubble(text, "user");
const assistantBubble = addBubble("...", "assistant");
assistantBubble.innerHTML = "";
let fullText = "";
try {
const response = await fetch(`${apiBase}/chat`, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ message: text }),
});
// Handle rate limiting
if (response.status === 429) {
const retryAfter = response.headers.get("Retry-After") || "60";
fullText = `You're asking questions too quickly. Please wait ${retryAfter} seconds before trying again.`;
assistantBubble.innerHTML = renderMarkdown(fullText);
addCopyButtons(assistantBubble, fullText);
return;
}
// Handle other errors
if (!response.ok) {
try {
const errorData = await response.json();
fullText = errorData.error || "Something went wrong. Please try again.";
} catch {
fullText = "Something went wrong. Please try again.";
}
assistantBubble.innerHTML = renderMarkdown(fullText);
addCopyButtons(assistantBubble, fullText);
return;
}
if (!response.body) {
fullText = await response.text();
assistantBubble.innerHTML = renderMarkdown(fullText);
addCopyButtons(assistantBubble, fullText);
return;
}
const reader = response.body.getReader();
const decoder = new TextDecoder();
while (true) {
const { value, done } = await reader.read();
if (done) break;
fullText += decoder.decode(value, { stream: true });
// Re-render markdown on each chunk for live preview
assistantBubble.innerHTML = renderMarkdown(fullText);
messages.scrollTop = messages.scrollHeight;
}
// Flush any remaining buffered bytes (partial UTF-8 sequences)
fullText += decoder.decode();
assistantBubble.innerHTML = renderMarkdown(fullText);
// Add copy buttons after streaming completes
addCopyButtons(assistantBubble, fullText);
} catch (err) {
fullText = "Failed to reach docs chat API.";
assistantBubble.innerHTML = renderMarkdown(fullText);
addCopyButtons(assistantBubble, fullText);
}
};
send.addEventListener("click", sendMessage);
textarea.addEventListener("keydown", (event) => {
if (event.key === "Enter" && !event.shiftKey) {
event.preventDefault();
sendMessage();
}
});
})();

View File

@@ -23,7 +23,7 @@ cron is the mechanism.
- Jobs persist under `~/.openclaw/cron/` so restarts dont lose schedules.
- Two execution styles:
- **Main session**: enqueue a system event, then run on the next heartbeat.
- **Isolated**: run a dedicated agent turn in `cron:<jobId>`, with delivery (announce by default or none).
- **Isolated**: run a dedicated agent turn in `cron:<jobId>`, optionally deliver output.
- Wakeups are first-class: a job can request “wake now” vs “next heartbeat”.
## Quick start (actionable)
@@ -53,7 +53,7 @@ openclaw cron add \
--tz "America/Los_Angeles" \
--session isolated \
--message "Summarize overnight updates." \
--announce \
--deliver \
--channel slack \
--to "channel:C1234567890"
```
@@ -86,8 +86,7 @@ Think of a cron job as: **when** to run + **what** to do.
- Main session → `payload.kind = "systemEvent"`
- Isolated session → `payload.kind = "agentTurn"`
Optional: one-shot jobs (`schedule.kind = "at"`) delete after success by default. Set
`deleteAfterRun: false` to keep them (they will disable after success).
Optional: `deleteAfterRun: true` removes successful one-shot jobs from the store.
## Concepts
@@ -97,19 +96,19 @@ A cron job is a stored record with:
- a **schedule** (when it should run),
- a **payload** (what it should do),
- optional **delivery mode** (announce or none).
- optional **delivery** (where output should be sent).
- optional **agent binding** (`agentId`): run the job under a specific agent; if
missing or unknown, the gateway falls back to the default agent.
Jobs are identified by a stable `jobId` (used by CLI/Gateway APIs).
In agent tool calls, `jobId` is canonical; legacy `id` is accepted for compatibility.
One-shot jobs auto-delete after success by default; set `deleteAfterRun: false` to keep them.
Jobs can optionally auto-delete after a successful one-shot run via `deleteAfterRun: true`.
### Schedules
Cron supports three schedule kinds:
- `at`: one-shot timestamp via `schedule.at` (ISO 8601).
- `at`: one-shot timestamp (ms since epoch). Gateway accepts ISO 8601 and coerces to UTC.
- `every`: fixed interval (ms).
- `cron`: 5-field cron expression with optional IANA timezone.
@@ -137,13 +136,9 @@ Key behaviors:
- Prompt is prefixed with `[cron:<jobId> <job name>]` for traceability.
- Each run starts a **fresh session id** (no prior conversation carry-over).
- Default behavior: if `delivery` is omitted, isolated jobs announce a summary (`delivery.mode = "announce"`).
- `delivery.mode` (isolated-only) chooses what happens:
- `announce`: deliver a summary to the target channel and post a brief summary to the main session.
- `none`: internal only (no delivery, no main-session summary).
- `wakeMode` controls when the main-session summary posts:
- `now`: immediate heartbeat.
- `next-heartbeat`: waits for the next scheduled heartbeat.
- A summary is posted to the main session (prefix `Cron`, configurable).
- `wakeMode: "now"` triggers an immediate heartbeat after posting the summary.
- If `payload.deliver: true`, output is delivered to a channel; otherwise it stays internal.
Use isolated jobs for noisy, frequent, or "background chores" that shouldn't spam
your main chat history.
@@ -160,35 +155,16 @@ Common `agentTurn` fields:
- `message`: required text prompt.
- `model` / `thinking`: optional overrides (see below).
- `timeoutSeconds`: optional timeout override.
- `deliver`: `true` to send output to a channel target.
- `channel`: `last` or a specific channel.
- `to`: channel-specific target (phone/chat/channel id).
- `bestEffortDeliver`: avoid failing the job if delivery fails.
Delivery config (isolated jobs only):
Isolation options (only for `session=isolated`):
- `delivery.mode`: `none` | `announce`.
- `delivery.channel`: `last` or a specific channel.
- `delivery.to`: channel-specific target (phone/chat/channel id).
- `delivery.bestEffort`: avoid failing the job if announce delivery fails.
Announce delivery suppresses messaging tool sends for the run; use `delivery.channel`/`delivery.to`
to target the chat instead. When `delivery.mode = "none"`, no summary is posted to the main session.
If `delivery` is omitted for isolated jobs, OpenClaw defaults to `announce`.
#### Announce delivery flow
When `delivery.mode = "announce"`, cron delivers directly via the outbound channel adapters.
The main agent is not spun up to craft or forward the message.
Behavior details:
- Content: delivery uses the isolated run's outbound payloads (text/media) with normal chunking and
channel formatting.
- Heartbeat-only responses (`HEARTBEAT_OK` with no real content) are not delivered.
- If the isolated run already sent a message to the same target via the message tool, delivery is
skipped to avoid duplicates.
- Missing or invalid delivery targets fail the job unless `delivery.bestEffort = true`.
- A short summary is posted to the main session only when `delivery.mode = "announce"`.
- The main-session summary respects `wakeMode`: `now` triggers an immediate heartbeat and
`next-heartbeat` waits for the next scheduled heartbeat.
- `postToMainPrefix` (CLI: `--post-prefix`): prefix for the system event in main.
- `postToMainMode`: `summary` (default) or `full`.
- `postToMainMaxChars`: max chars when `postToMainMode=full` (default 8000).
### Model and thinking overrides
@@ -209,16 +185,19 @@ Resolution priority:
### Delivery (channel + target)
Isolated jobs can deliver output to a channel via the top-level `delivery` config:
Isolated jobs can deliver output to a channel. The job payload can specify:
- `delivery.mode`: `announce` (deliver a summary) or `none`.
- `delivery.channel`: `whatsapp` / `telegram` / `discord` / `slack` / `mattermost` (plugin) / `signal` / `imessage` / `last`.
- `delivery.to`: channel-specific recipient target.
- `channel`: `whatsapp` / `telegram` / `discord` / `slack` / `mattermost` (plugin) / `signal` / `imessage` / `last`
- `to`: channel-specific recipient target
Delivery config is only valid for isolated jobs (`sessionTarget: "isolated"`).
If `channel` or `to` is omitted, cron can fall back to the main sessions “last route”
(the last place the agent replied).
If `delivery.channel` or `delivery.to` is omitted, cron can fall back to the main sessions
“last route” (the last place the agent replied).
Delivery notes:
- If `to` is set, cron auto-delivers the agents final output even if `deliver` is omitted.
- Use `deliver: true` when you want last-route delivery without an explicit `to`.
- Use `deliver: false` to keep output internal even if a `to` is present.
Target format reminders:
@@ -241,8 +220,8 @@ Prefixed targets like `telegram:...` / `telegram:group:...` are also accepted:
## JSON schema for tool calls
Use these shapes when calling Gateway `cron.*` tools directly (agent tool calls or RPC).
CLI flags accept human durations like `20m`, but tool calls should use an ISO 8601 string
for `schedule.at` and milliseconds for `schedule.everyMs`.
CLI flags accept human durations like `20m`, but tool calls use epoch milliseconds for
`atMs` and `everyMs` (ISO timestamps are accepted for `at` times).
### cron.add params
@@ -251,7 +230,7 @@ One-shot, main session job (system event):
```json
{
"name": "Reminder",
"schedule": { "kind": "at", "at": "2026-02-01T16:00:00Z" },
"schedule": { "kind": "at", "atMs": 1738262400000 },
"sessionTarget": "main",
"wakeMode": "now",
"payload": { "kind": "systemEvent", "text": "Reminder text" },
@@ -269,25 +248,22 @@ Recurring, isolated job with delivery:
"wakeMode": "next-heartbeat",
"payload": {
"kind": "agentTurn",
"message": "Summarize overnight updates."
},
"delivery": {
"mode": "announce",
"message": "Summarize overnight updates.",
"deliver": true,
"channel": "slack",
"to": "channel:C1234567890",
"bestEffort": true
}
"bestEffortDeliver": true
},
"isolation": { "postToMainPrefix": "Cron", "postToMainMode": "summary" }
}
```
Notes:
- `schedule.kind`: `at` (`at`), `every` (`everyMs`), or `cron` (`expr`, optional `tz`).
- `schedule.at` accepts ISO 8601 (timezone optional; treated as UTC when omitted).
- `everyMs` is milliseconds.
- `schedule.kind`: `at` (`atMs`), `every` (`everyMs`), or `cron` (`expr`, optional `tz`).
- `atMs` and `everyMs` are epoch milliseconds.
- `sessionTarget` must be `"main"` or `"isolated"` and must match `payload.kind`.
- Optional fields: `agentId`, `description`, `enabled`, `deleteAfterRun` (defaults to true for `at`),
`delivery`.
- Optional fields: `agentId`, `description`, `enabled`, `deleteAfterRun`, `isolation`.
- `wakeMode` defaults to `"next-heartbeat"` when omitted.
### cron.update params
@@ -365,7 +341,7 @@ openclaw cron add \
--wake now
```
Recurring isolated job (announce to WhatsApp):
Recurring isolated job (deliver to WhatsApp):
```bash
openclaw cron add \
@@ -374,7 +350,7 @@ openclaw cron add \
--tz "America/Los_Angeles" \
--session isolated \
--message "Summarize inbox + calendar for today." \
--announce \
--deliver \
--channel whatsapp \
--to "+15551234567"
```
@@ -388,7 +364,7 @@ openclaw cron add \
--tz "America/Los_Angeles" \
--session isolated \
--message "Summarize today; send to the nightly topic." \
--announce \
--deliver \
--channel telegram \
--to "-1001234567890:topic:123"
```
@@ -404,7 +380,7 @@ openclaw cron add \
--message "Weekly deep analysis of project progress." \
--model "opus" \
--thinking high \
--announce \
--deliver \
--channel whatsapp \
--to "+15551234567"
```

View File

@@ -90,8 +90,7 @@ Cron jobs run at **exact times** and can run in isolated sessions without affect
- **Exact timing**: 5-field cron expressions with timezone support.
- **Session isolation**: Runs in `cron:<jobId>` without polluting main history.
- **Model overrides**: Use a cheaper or more powerful model per job.
- **Delivery control**: Isolated jobs default to `announce` (summary); choose `none` as needed.
- **Immediate delivery**: Announce mode posts directly without waiting for heartbeat.
- **Delivery control**: Can deliver directly to a channel; still posts a summary to main by default (configurable).
- **No agent context needed**: Runs even if main session is idle or compacted.
- **One-shot support**: `--at` for precise future timestamps.
@@ -105,12 +104,12 @@ openclaw cron add \
--session isolated \
--message "Generate today's briefing: weather, calendar, top emails, news summary." \
--model opus \
--announce \
--deliver \
--channel whatsapp \
--to "+15551234567"
```
This runs at exactly 7:00 AM New York time, uses Opus for quality, and announces a summary directly to WhatsApp.
This runs at exactly 7:00 AM New York time, uses Opus for quality, and delivers directly to WhatsApp.
### Cron example: One-shot reminder
@@ -174,7 +173,7 @@ The most efficient setup uses **both**:
```bash
# Daily morning briefing at 7am
openclaw cron add --name "Morning brief" --cron "0 7 * * *" --session isolated --message "..." --announce
openclaw cron add --name "Morning brief" --cron "0 7 * * *" --session isolated --message "..." --deliver
# Weekly project review on Mondays at 9am
openclaw cron add --name "Weekly review" --cron "0 9 * * 1" --session isolated --message "..." --model opus
@@ -215,13 +214,13 @@ See [Lobster](/tools/lobster) for full usage and examples.
Both heartbeat and cron can interact with the main session, but differently:
| | Heartbeat | Cron (main) | Cron (isolated) |
| ------- | ------------------------------- | ------------------------ | -------------------------- |
| Session | Main | Main (via system event) | `cron:<jobId>` |
| History | Shared | Shared | Fresh each run |
| Context | Full | Full | None (starts clean) |
| Model | Main session model | Main session model | Can override |
| Output | Delivered if not `HEARTBEAT_OK` | Heartbeat prompt + event | Announce summary (default) |
| | Heartbeat | Cron (main) | Cron (isolated) |
| ------- | ------------------------------- | ------------------------ | ---------------------- |
| Session | Main | Main (via system event) | `cron:<jobId>` |
| History | Shared | Shared | Fresh each run |
| Context | Full | Full | None (starts clean) |
| Model | Main session model | Main session model | Can override |
| Output | Delivered if not `HEARTBEAT_OK` | Heartbeat prompt + event | Summary posted to main |
### When to use main session cron
@@ -246,7 +245,7 @@ Use `--session isolated` when you want:
- A clean slate without prior context
- Different model or thinking settings
- Announce summaries directly to a channel
- Output delivered directly to a channel (summary still posts to main by default)
- History that doesn't clutter main session
```bash
@@ -257,7 +256,7 @@ openclaw cron add \
--message "Weekly codebase analysis..." \
--model opus \
--thinking high \
--announce
--deliver
```
## Cost Considerations

View File

@@ -42,80 +42,6 @@ Status: bundled plugin that talks to the BlueBubbles macOS server over HTTP. **R
4. Point BlueBubbles webhooks to your gateway (example: `https://your-gateway-host:3000/bluebubbles-webhook?password=<password>`).
5. Start the gateway; it will register the webhook handler and start pairing.
## Keeping Messages.app alive (VM / headless setups)
Some macOS VM / always-on setups can end up with Messages.app going “idle” (incoming events stop until the app is opened/foregrounded). A simple workaround is to **poke Messages every 5 minutes** using an AppleScript + LaunchAgent.
### 1) Save the AppleScript
Save this as:
- `~/Scripts/poke-messages.scpt`
Example script (non-interactive; does not steal focus):
```applescript
try
tell application "Messages"
if not running then
launch
end if
-- Touch the scripting interface to keep the process responsive.
set _chatCount to (count of chats)
end tell
on error
-- Ignore transient failures (first-run prompts, locked session, etc).
end try
```
### 2) Install a LaunchAgent
Save this as:
- `~/Library/LaunchAgents/com.user.poke-messages.plist`
```xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.user.poke-messages</string>
<key>ProgramArguments</key>
<array>
<string>/bin/bash</string>
<string>-lc</string>
<string>/usr/bin/osascript &quot;$HOME/Scripts/poke-messages.scpt&quot;</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>StartInterval</key>
<integer>300</integer>
<key>StandardOutPath</key>
<string>/tmp/poke-messages.log</string>
<key>StandardErrorPath</key>
<string>/tmp/poke-messages.err</string>
</dict>
</plist>
```
Notes:
- This runs **every 300 seconds** and **on login**.
- The first run may trigger macOS **Automation** prompts (`osascript` → Messages). Approve them in the same user session that runs the LaunchAgent.
Load it:
```bash
launchctl unload ~/Library/LaunchAgents/com.user.poke-messages.plist 2>/dev/null || true
launchctl load ~/Library/LaunchAgents/com.user.poke-messages.plist
```
## Onboarding
BlueBubbles is available in the interactive setup wizard:

View File

@@ -100,7 +100,7 @@ In **Bot** → **Privileged Gateway Intents**, enable:
- **Message Content Intent** (required to read message text in most guilds; without it youll see “Used disallowed intents” or the bot will connect but not react to messages)
- **Server Members Intent** (recommended; required for some member/user lookups and allowlist matching in guilds)
You usually do **not** need **Presence Intent**. Setting the bot's own presence (`setPresence` action) uses gateway OP3 and does not require this intent; it is only needed if you want to receive presence updates about other guild members.
You usually do **not** need **Presence Intent**.
### 3) Generate an invite URL (OAuth2 URL Generator)
@@ -278,7 +278,6 @@ Outbound Discord API calls retry on rate limits (429) using Discord `retry_after
voiceStatus: true,
events: true,
moderation: false,
presence: false,
},
replyToMode: "off",
dm: {
@@ -354,7 +353,6 @@ ack reaction after the bot replies.
- `channels` (create/edit/delete channels + categories + permissions)
- `roles` (role add/remove, default `false`)
- `moderation` (timeout/kick/ban, default `false`)
- `presence` (bot status/activity, default `false`)
- `execApprovals`: Discord-only exec approval DMs (button UI). Supports `enabled`, `approvers`, `agentFilter`, `sessionFilter`.
Reaction notifications use `guilds.<id>.reactionNotifications`:
@@ -414,7 +412,6 @@ Allowlist notes (PK-enabled):
| events | enabled | List/create scheduled events |
| roles | disabled | Role add/remove |
| moderation | disabled | Timeout/kick/ban |
| presence | disabled | Bot status/activity (setPresence) |
- `replyToMode`: `off` (default), `first`, or `all`. Applies only when the model includes a reply tag.
@@ -463,7 +460,6 @@ The agent can call `discord` with actions like:
- `searchMessages`, `memberInfo`, `roleInfo`, `roleAdd`, `roleRemove`, `emojiList`
- `channelInfo`, `channelList`, `voiceStatus`, `eventList`, `eventCreate`
- `timeout`, `kick`, `ban`
- `setPresence` (bot activity and online status)
Discord message ids are surfaced in the injected context (`[discord message id: …]` and history lines) so the agent can target them.
Emoji can be unicode (e.g., `✅`) or custom emoji syntax like `<:party_blob:1234567890>`.

View File

@@ -1,5 +1,5 @@
---
summary: "Feishu bot overview, features, and configuration"
summary: "Feishu bot support status, features, and configuration"
read_when:
- You want to connect a Feishu/Lark bot
- You are configuring the Feishu channel
@@ -8,7 +8,7 @@ title: Feishu
# Feishu bot
Feishu (Lark) is a team chat platform used by companies for messaging and collaboration. This plugin connects OpenClaw to a Feishu/Lark bot using the platforms WebSocket event subscription so messages can be received without exposing a public webhook URL.
Status: production-ready, supports bot DMs and group chats. Uses WebSocket long connection mode to receive events.
---
@@ -121,7 +121,11 @@ On **Permissions**, click **Batch import** and paste:
"im:message:send_as_bot",
"im:resource"
],
"user": ["aily:file:read", "aily:file:write", "im:chat.access_event.bot_p2p_chat:read"]
"user": [
"aily:file:read",
"aily:file:write",
"im:chat.access_event.bot_p2p_chat:read"
]
}
}
```
@@ -185,11 +189,11 @@ Edit `~/.openclaw/openclaw.json`:
main: {
appId: "cli_xxx",
appSecret: "xxx",
botName: "My AI assistant",
},
},
},
},
botName: "My AI assistant"
}
}
}
}
}
```
@@ -212,11 +216,11 @@ If your tenant is on Lark (international), set the domain to `lark` (or a full d
accounts: {
main: {
appId: "cli_xxx",
appSecret: "xxx",
},
},
},
},
appSecret: "xxx"
}
}
}
}
}
```
@@ -290,10 +294,10 @@ After approval, you can chat normally.
{
channels: {
feishu: {
groupPolicy: "open",
groupPolicy: "open"
// Default requireMention: true
},
},
}
}
}
```
@@ -304,10 +308,10 @@ After approval, you can chat normally.
channels: {
feishu: {
groups: {
oc_xxx: { requireMention: false },
},
},
},
"oc_xxx": { requireMention: false }
}
}
}
}
```
@@ -318,9 +322,9 @@ After approval, you can chat normally.
channels: {
feishu: {
groupPolicy: "allowlist",
groupAllowFrom: ["ou_xxx", "ou_yyy"],
},
},
groupAllowFrom: ["ou_xxx", "ou_yyy"]
}
}
}
```
@@ -362,23 +366,23 @@ openclaw pairing list feishu
## Common commands
| Command | Description |
| --------- | ----------------- |
| `/status` | Show bot status |
| `/reset` | Reset the session |
| `/model` | Show/switch model |
| Command | Description |
|---------|-------------|
| `/status` | Show bot status |
| `/reset` | Reset the session |
| `/model` | Show/switch model |
> Note: Feishu does not support native command menus yet, so commands must be sent as text.
## Gateway management commands
| Command | Description |
| -------------------------- | ----------------------------- |
| `openclaw gateway status` | Show gateway status |
| Command | Description |
|---------|-------------|
| `openclaw gateway status` | Show gateway status |
| `openclaw gateway install` | Install/start gateway service |
| `openclaw gateway stop` | Stop gateway service |
| `openclaw gateway restart` | Restart gateway service |
| `openclaw logs --follow` | Tail gateway logs |
| `openclaw gateway stop` | Stop gateway service |
| `openclaw gateway restart` | Restart gateway service |
| `openclaw logs --follow` | Tail gateway logs |
---
@@ -426,17 +430,17 @@ openclaw pairing list feishu
main: {
appId: "cli_xxx",
appSecret: "xxx",
botName: "Primary bot",
botName: "Primary bot"
},
backup: {
appId: "cli_yyy",
appSecret: "yyy",
botName: "Backup bot",
enabled: false,
},
},
},
},
enabled: false
}
}
}
}
}
```
@@ -457,33 +461,33 @@ Full configuration: [Gateway configuration](/gateway/configuration)
Key options:
| Setting | Description | Default |
| ------------------------------------------------- | ------------------------------- | --------- |
| `channels.feishu.enabled` | Enable/disable channel | `true` |
| `channels.feishu.domain` | API domain (`feishu` or `lark`) | `feishu` |
| `channels.feishu.accounts.<id>.appId` | App ID | - |
| `channels.feishu.accounts.<id>.appSecret` | App Secret | - |
| `channels.feishu.accounts.<id>.domain` | Per-account API domain override | `feishu` |
| `channels.feishu.dmPolicy` | DM policy | `pairing` |
| `channels.feishu.allowFrom` | DM allowlist (open_id list) | - |
| `channels.feishu.groupPolicy` | Group policy | `open` |
| `channels.feishu.groupAllowFrom` | Group allowlist | - |
| `channels.feishu.groups.<chat_id>.requireMention` | Require @mention | `true` |
| `channels.feishu.groups.<chat_id>.enabled` | Enable group | `true` |
| `channels.feishu.textChunkLimit` | Message chunk size | `2000` |
| `channels.feishu.mediaMaxMb` | Media size limit | `30` |
| `channels.feishu.blockStreaming` | Disable streaming | `true` |
| Setting | Description | Default |
|---------|-------------|---------|
| `channels.feishu.enabled` | Enable/disable channel | `true` |
| `channels.feishu.domain` | API domain (`feishu` or `lark`) | `feishu` |
| `channels.feishu.accounts.<id>.appId` | App ID | - |
| `channels.feishu.accounts.<id>.appSecret` | App Secret | - |
| `channels.feishu.accounts.<id>.domain` | Per-account API domain override | `feishu` |
| `channels.feishu.dmPolicy` | DM policy | `pairing` |
| `channels.feishu.allowFrom` | DM allowlist (open_id list) | - |
| `channels.feishu.groupPolicy` | Group policy | `open` |
| `channels.feishu.groupAllowFrom` | Group allowlist | - |
| `channels.feishu.groups.<chat_id>.requireMention` | Require @mention | `true` |
| `channels.feishu.groups.<chat_id>.enabled` | Enable group | `true` |
| `channels.feishu.textChunkLimit` | Message chunk size | `2000` |
| `channels.feishu.mediaMaxMb` | Media size limit | `30` |
| `channels.feishu.blockStreaming` | Disable streaming | `true` |
---
## dmPolicy reference
| Value | Behavior |
| ------------- | --------------------------------------------------------------- |
| `"pairing"` | **Default.** Unknown users get a pairing code; must be approved |
| `"allowlist"` | Only users in `allowFrom` can chat |
| `"open"` | Allow all users (requires `"*"` in allowFrom) |
| `"disabled"` | Disable DMs |
| Value | Behavior |
|-------|----------|
| `"pairing"` | **Default.** Unknown users get a pairing code; must be approved |
| `"allowlist"` | Only users in `allowFrom` can chat |
| `"open"` | Allow all users (requires `"*"` in allowFrom) |
| `"disabled"` | Disable DMs |
---

View File

@@ -1,18 +1,14 @@
---
summary: "Legacy iMessage support via imsg (JSON-RPC over stdio). New setups should use BlueBubbles."
summary: "iMessage support via imsg (JSON-RPC over stdio), setup, and chat_id routing"
read_when:
- Setting up iMessage support
- Debugging iMessage send/receive
title: iMessage
---
# iMessage (legacy: imsg)
# iMessage (imsg)
> **Recommended:** Use [BlueBubbles](/channels/bluebubbles) for new iMessage setups.
>
> The `imsg` channel is a legacy external-CLI integration and may be removed in a future release.
Status: legacy external CLI integration. Gateway spawns `imsg rpc` (JSON-RPC over stdio).
Status: external CLI integration. Gateway spawns `imsg rpc` (JSON-RPC over stdio).
## Quick setup (beginner)

View File

@@ -17,12 +17,11 @@ Text is supported everywhere; media and reactions vary by channel.
- [Telegram](/channels/telegram) — Bot API via grammY; supports groups.
- [Discord](/channels/discord) — Discord Bot API + Gateway; supports servers, channels, and DMs.
- [Slack](/channels/slack) — Bolt SDK; workspace apps.
- [Feishu](/channels/feishu) — Feishu/Lark bot via WebSocket (plugin, installed separately).
- [Google Chat](/channels/googlechat) — Google Chat API app via HTTP webhook.
- [Mattermost](/channels/mattermost) — Bot API + WebSocket; channels, groups, DMs (plugin, installed separately).
- [Signal](/channels/signal) — signal-cli; privacy-focused.
- [BlueBubbles](/channels/bluebubbles) — **Recommended for iMessage**; uses the BlueBubbles macOS server REST API with full feature support (edit, unsend, effects, reactions, group management — edit currently broken on macOS 26 Tahoe).
- [iMessage (legacy)](/channels/imessage) — Legacy macOS integration via imsg CLI (deprecated, use BlueBubbles for new setups).
- [iMessage](/channels/imessage) — macOS only; native integration via imsg (legacy, consider BlueBubbles for new setups).
- [Microsoft Teams](/channels/msteams) — Bot Framework; enterprise support (plugin, installed separately).
- [LINE](/channels/line) — LINE Messaging API bot (plugin, installed separately).
- [Nextcloud Talk](/channels/nextcloud-talk) — Self-hosted chat via Nextcloud Talk (plugin, installed separately).

View File

@@ -148,12 +148,12 @@ Once verified, the bot can decrypt messages in encrypted rooms.
- `openclaw pairing list matrix`
- `openclaw pairing approve matrix <CODE>`
- Public DMs: `channels.matrix.dm.policy="open"` plus `channels.matrix.dm.allowFrom=["*"]`.
- `channels.matrix.dm.allowFrom` accepts full Matrix user IDs (example: `@user:server`). The wizard resolves display names to user IDs when directory search finds a single exact match.
- `channels.matrix.dm.allowFrom` accepts user IDs or display names. The wizard resolves display names to user IDs when directory search is available.
## Rooms (groups)
- Default: `channels.matrix.groupPolicy = "allowlist"` (mention-gated). Use `channels.defaults.groupPolicy` to override the default when unset.
- Allowlist rooms with `channels.matrix.groups` (room IDs or aliases; names are resolved to IDs when directory search finds a single exact match):
- Allowlist rooms with `channels.matrix.groups` (room IDs, aliases, or names):
```json5
{
@@ -172,10 +172,10 @@ Once verified, the bot can decrypt messages in encrypted rooms.
- `requireMention: false` enables auto-reply in that room.
- `groups."*"` can set defaults for mention gating across rooms.
- `groupAllowFrom` restricts which senders can trigger the bot in rooms (full Matrix user IDs).
- Per-room `users` allowlists can further restrict senders inside a specific room (use full Matrix user IDs).
- The configure wizard prompts for room allowlists (room IDs, aliases, or names) and resolves names only on an exact, unique match.
- On startup, OpenClaw resolves room/user names in allowlists to IDs and logs the mapping; unresolved entries are ignored for allowlist matching.
- `groupAllowFrom` restricts which senders can trigger the bot in rooms (optional).
- Per-room `users` allowlists can further restrict senders inside a specific room.
- The configure wizard prompts for room allowlists (room IDs, aliases, or names) and resolves names when possible.
- On startup, OpenClaw resolves room/user names in allowlists to IDs and logs the mapping; unresolved entries are kept as typed.
- Invites are auto-joined by default; control with `channels.matrix.autoJoin` and `channels.matrix.autoJoinAllowlist`.
- To allow **no rooms**, set `channels.matrix.groupPolicy: "disabled"` (or keep an empty allowlist).
- Legacy key: `channels.matrix.rooms` (same shape as `groups`).
@@ -220,9 +220,9 @@ Provider options:
- `channels.matrix.textChunkLimit`: outbound text chunk size (chars).
- `channels.matrix.chunkMode`: `length` (default) or `newline` to split on blank lines (paragraph boundaries) before length chunking.
- `channels.matrix.dm.policy`: `pairing | allowlist | open | disabled` (default: pairing).
- `channels.matrix.dm.allowFrom`: DM allowlist (full Matrix user IDs). `open` requires `"*"`. The wizard resolves names to IDs when possible.
- `channels.matrix.dm.allowFrom`: DM allowlist (user IDs or display names). `open` requires `"*"`. The wizard resolves names to IDs when possible.
- `channels.matrix.groupPolicy`: `allowlist | open | disabled` (default: allowlist).
- `channels.matrix.groupAllowFrom`: allowlisted senders for group messages (full Matrix user IDs).
- `channels.matrix.groupAllowFrom`: allowlisted senders for group messages.
- `channels.matrix.allowlistOnly`: force allowlist rules for DMs + rooms.
- `channels.matrix.groups`: group allowlist + per-room settings map.
- `channels.matrix.rooms`: legacy group allowlist/config.

View File

@@ -72,7 +72,6 @@ Minimal config:
- `openclaw pairing list nextcloud-talk`
- `openclaw pairing approve nextcloud-talk <CODE>`
- Public DMs: `channels.nextcloud-talk.dmPolicy="open"` plus `channels.nextcloud-talk.allowFrom=["*"]`.
- `allowFrom` matches Nextcloud user IDs only; display names are ignored.
## Rooms (groups)

View File

@@ -16,17 +16,12 @@ Related:
Tip: run `openclaw cron --help` for the full command surface.
Note: isolated `cron add` jobs default to `--announce` delivery. Use `--no-deliver` to keep
output internal. `--deliver` remains as a deprecated alias for `--announce`.
Note: one-shot (`--at`) jobs delete after success by default. Use `--keep-after-run` to keep them.
## Common edits
Update delivery settings without changing the message:
```bash
openclaw cron edit <job-id> --announce --channel telegram --to "123456789"
openclaw cron edit <job-id> --deliver --channel telegram --to "123456789"
```
Disable delivery for an isolated job:
@@ -34,9 +29,3 @@ Disable delivery for an isolated job:
```bash
openclaw cron edit <job-id> --no-deliver
```
Announce to a specific channel:
```bash
openclaw cron edit <job-id> --announce --channel slack --to "channel:C1234567890"
```

View File

@@ -303,7 +303,7 @@ Options:
- `--non-interactive`
- `--mode <local|remote>`
- `--flow <quickstart|advanced|manual>` (manual is an alias for advanced)
- `--auth-choice <setup-token|token|chutes|openai-codex|openai-api-key|openrouter-api-key|ai-gateway-api-key|moonshot-api-key|moonshot-api-key-cn|kimi-code-api-key|synthetic-api-key|venice-api-key|gemini-api-key|zai-api-key|apiKey|minimax-api|minimax-api-lightning|opencode-zen|skip>`
- `--auth-choice <setup-token|token|chutes|openai-codex|openai-api-key|openrouter-api-key|ai-gateway-api-key|moonshot-api-key|kimi-code-api-key|synthetic-api-key|venice-api-key|gemini-api-key|zai-api-key|apiKey|minimax-api|minimax-api-lightning|opencode-zen|skip>`
- `--token-provider <id>` (non-interactive; used with `--auth-choice token`)
- `--token <token>` (non-interactive; used with `--auth-choice token`)
- `--token-profile-id <id>` (non-interactive; default: `<provider>:manual`)

View File

@@ -22,5 +22,5 @@ openclaw security audit --deep
openclaw security audit --fix
```
The audit warns when multiple DM senders share the main session and recommends **secure DM mode**: `session.dmScope="per-channel-peer"` (or `per-account-channel-peer` for multi-account channels) for shared inboxes.
The audit warns when multiple DM senders share the main session and recommends `session.dmScope="per-channel-peer"` (or `per-account-channel-peer` for multi-account channels) for shared inboxes.
It also warns when small models (`<=300B`) are used without sandboxing and with web/browser tools enabled.

View File

@@ -3,6 +3,7 @@ summary: "How OpenClaw memory works (workspace files + automatic memory flush)"
read_when:
- You want the memory file layout and workflow
- You want to tune the automatic pre-compaction memory flush
title: "Memory"
---
# Memory
@@ -25,7 +26,7 @@ The default workspace layout uses two memory layers:
- **Only load in the main, private session** (never in group contexts).
These files live under the workspace (`agents.defaults.workspace`, default
`~/clawd`). See [Agent workspace](/concepts/agent-workspace) for the full layout.
`~/.openclaw/workspace`). See [Agent workspace](/concepts/agent-workspace) for the full layout.
## When to write memory
@@ -77,8 +78,9 @@ For the full compaction lifecycle, see
## Vector memory search
OpenClaw can build a small vector index over `MEMORY.md` and `memory/*.md` so
semantic queries can find related notes even when wording differs.
OpenClaw can build a small vector index over `MEMORY.md` and `memory/*.md` (plus
any extra directories or files you opt in) so semantic queries can find related
notes even when wording differs.
Defaults:
@@ -99,123 +101,6 @@ embeddings for memory search. For Gemini, use `GEMINI_API_KEY` or
`models.providers.google.apiKey`. When using a custom OpenAI-compatible endpoint,
set `memorySearch.remote.apiKey` (and optional `memorySearch.remote.headers`).
### QMD backend (experimental)
Set `memory.backend = "qmd"` to swap the built-in SQLite indexer for
[QMD](https://github.com/tobi/qmd): a local-first search sidecar that combines
BM25 + vectors + reranking. Markdown stays the source of truth; OpenClaw shells
out to QMD for retrieval. Key points:
**Prereqs**
- Disabled by default. Opt in per-config (`memory.backend = "qmd"`).
- Install the QMD CLI separately (`bun install -g github.com/tobi/qmd` or grab
a release) and make sure the `qmd` binary is on the gateways `PATH`.
- QMD needs an SQLite build that allows extensions (`brew install sqlite` on
macOS).
- QMD runs fully locally via Bun + `node-llama-cpp` and auto-downloads GGUF
models from HuggingFace on first use (no separate Ollama daemon required).
- The gateway runs QMD in a self-contained XDG home under
`~/.openclaw/agents/<agentId>/qmd/` by setting `XDG_CONFIG_HOME` and
`XDG_CACHE_HOME`.
- OS support: macOS and Linux work out of the box once Bun + SQLite are
installed. Windows is best supported via WSL2.
**How the sidecar runs**
- The gateway writes a self-contained QMD home under
`~/.openclaw/agents/<agentId>/qmd/` (config + cache + sqlite DB).
- Collections are rewritten from `memory.qmd.paths` (plus default workspace
memory files) into `index.yml`, then `qmd update` + `qmd embed` run on boot and
on a configurable interval (`memory.qmd.update.interval`, default 5m).
- Searches run via `qmd query --json`. If QMD fails or the binary is missing,
OpenClaw automatically falls back to the builtin SQLite manager so memory tools
keep working.
- **First search may be slow**: QMD may download local GGUF models (reranker/query
expansion) on the first `qmd query` run.
- OpenClaw sets `XDG_CONFIG_HOME`/`XDG_CACHE_HOME` automatically when it runs QMD.
- If you want to pre-download models manually (and warm the same index OpenClaw
uses), run a one-off query with the agents XDG dirs.
OpenClaws QMD state lives under your **state dir** (defaults to `~/.openclaw`).
You can point `qmd` at the exact same index by exporting the same XDG vars
OpenClaw uses:
```bash
# Pick the same state dir OpenClaw uses
STATE_DIR="${OPENCLAW_STATE_DIR:-$HOME/.openclaw}"
if [ -d "$HOME/.moltbot" ] && [ ! -d "$HOME/.openclaw" ] \
&& [ -z "${OPENCLAW_STATE_DIR:-}" ]; then
STATE_DIR="$HOME/.moltbot"
fi
export XDG_CONFIG_HOME="$STATE_DIR/agents/main/qmd/xdg-config"
export XDG_CACHE_HOME="$STATE_DIR/agents/main/qmd/xdg-cache"
# (Optional) force an index refresh + embeddings
qmd update
qmd embed
# Warm up / trigger first-time model downloads
qmd query "test" -c memory-root --json >/dev/null 2>&1
```
**Config surface (`memory.qmd.*`)**
- `command` (default `qmd`): override the executable path.
- `includeDefaultMemory` (default `true`): auto-index `MEMORY.md` + `memory/**/*.md`.
- `paths[]`: add extra directories/files (`path`, optional `pattern`, optional
stable `name`).
- `sessions`: opt into session JSONL indexing (`enabled`, `retentionDays`,
`exportDir`).
- `update`: controls refresh cadence (`interval`, `debounceMs`, `onBoot`, `embedInterval`).
- `limits`: clamp recall payload (`maxResults`, `maxSnippetChars`,
`maxInjectedChars`, `timeoutMs`).
- `scope`: same schema as [`session.sendPolicy`](/gateway/configuration#session).
Default is DM-only (`deny` all, `allow` direct chats); loosen it to surface QMD
hits in groups/channels.
- Snippets sourced outside the workspace show up as
`qmd/<collection>/<relative-path>` in `memory_search` results; `memory_get`
understands that prefix and reads from the configured QMD collection root.
- When `memory.qmd.sessions.enabled = true`, OpenClaw exports sanitized session
transcripts (User/Assistant turns) into a dedicated QMD collection under
`~/.openclaw/agents/<id>/qmd/sessions/`, so `memory_search` can recall recent
conversations without touching the builtin SQLite index.
- `memory_search` snippets now include a `Source: <path#line>` footer when
`memory.citations` is `auto`/`on`; set `memory.citations = "off"` to keep
the path metadata internal (the agent still receives the path for
`memory_get`, but the snippet text omits the footer and the system prompt
warns the agent not to cite it).
**Example**
```json5
memory: {
backend: "qmd",
citations: "auto",
qmd: {
includeDefaultMemory: true,
update: { interval: "5m", debounceMs: 15000 },
limits: { maxResults: 6, timeoutMs: 4000 },
scope: {
default: "deny",
rules: [{ action: "allow", match: { chatType: "direct" } }]
},
paths: [
{ name: "docs", path: "~/notes", pattern: "**/*.md" }
]
}
}
```
**Citations & fallback**
- `memory.citations` applies regardless of backend (`auto`/`on`/`off`).
- When `qmd` runs, we tag `status().backend = "qmd"` so diagnostics show which
engine served the results. If the QMD subprocess exits or JSON output cant be
parsed, the search manager logs a warning and returns the builtin provider
(existing Markdown embeddings) until QMD recovers.
### Additional memory paths
If you want to index Markdown files outside the default workspace layout, add
@@ -337,14 +222,14 @@ Local mode:
### How the memory tools work
- `memory_search` semantically searches Markdown chunks (~400 token target, 80-token overlap) from `MEMORY.md` + `memory/**/*.md`. It returns snippet text (capped ~700 chars), file path, line range, score, provider/model, and whether we fell back from local → remote embeddings. No full file payload is returned.
- `memory_get` reads a specific memory Markdown file (workspace-relative), optionally from a starting line and for N lines. Paths outside `MEMORY.md` / `memory/` are rejected.
- `memory_get` reads a specific memory Markdown file (workspace-relative), optionally from a starting line and for N lines. Paths outside `MEMORY.md` / `memory/` are allowed only when explicitly listed in `memorySearch.extraPaths`.
- Both tools are enabled only when `memorySearch.enabled` resolves true for the agent.
### What gets indexed (and when)
- File type: Markdown only (`MEMORY.md`, `memory/**/*.md`).
- File type: Markdown only (`MEMORY.md`, `memory/**/*.md`, plus any `.md` files under `memorySearch.extraPaths`).
- Index storage: per-agent SQLite at `~/.openclaw/memory/<agentId>.sqlite` (configurable via `agents.defaults.memorySearch.store.path`, supports `{agentId}` token).
- Freshness: watcher on `MEMORY.md` + `memory/` marks the index dirty (debounce 1.5s). Sync is scheduled on session start, on search, or on an interval and runs asynchronously. Session transcripts use delta thresholds to trigger background sync.
- Freshness: watcher on `MEMORY.md`, `memory/`, and `memorySearch.extraPaths` marks the index dirty (debounce 1.5s). Sync is scheduled on session start, on search, or on an interval and runs asynchronously. Session transcripts use delta thresholds to trigger background sync.
- Reindex triggers: the index stores the embedding **provider/model + endpoint fingerprint + chunking params**. If any of those change, OpenClaw automatically resets and reindexes the entire store.
### Hybrid search (BM25 + vector)

View File

@@ -17,26 +17,6 @@ Use `session.dmScope` to control how **direct messages** are grouped:
- `per-account-channel-peer`: isolate by account + channel + sender (recommended for multi-account inboxes).
Use `session.identityLinks` to map provider-prefixed peer ids to a canonical identity so the same person shares a DM session across channels when using `per-peer`, `per-channel-peer`, or `per-account-channel-peer`.
### Secure DM mode (recommended)
If your agent can receive DMs from **multiple people** (pairing approvals for more than one sender, a DM allowlist with multiple entries, or `dmPolicy: "open"`), enable **secure DM mode** to avoid cross-user context leakage:
```json5
// ~/.openclaw/openclaw.json
{
session: {
// Secure DM mode: isolate DM context per channel + sender.
dmScope: "per-channel-peer",
},
}
```
Notes:
- Default is `dmScope: "main"` for continuity (all DMs share the main session).
- For multi-account inboxes on the same channel, prefer `per-account-channel-peer`.
- If the same person contacts you on multiple channels, use `session.identityLinks` to collapse their DM sessions into one canonical identity.
## Gateway is the source of truth
All session state is **owned by the gateway** (the “master” OpenClaw). UI clients (macOS app, WebChat, etc.) must query the gateway for session lists and token counts instead of reading local files.

File diff suppressed because it is too large Load Diff

View File

@@ -446,32 +446,6 @@ Save to `~/.openclaw/openclaw.json` and you can DM the bot from that number.
}
```
### Secure DM mode (shared inbox / multi-user DMs)
If more than one person can DM your bot (multiple entries in `allowFrom`, pairing approvals for multiple people, or `dmPolicy: "open"`), enable **secure DM mode** so DMs from different senders dont share one context by default:
```json5
{
// Secure DM mode (recommended for multi-user or sensitive DM agents)
session: { dmScope: "per-channel-peer" },
channels: {
// Example: WhatsApp multi-user inbox
whatsapp: {
dmPolicy: "allowlist",
allowFrom: ["+15555550123", "+15555550124"],
},
// Example: Discord multi-user inbox
discord: {
enabled: true,
token: "YOUR_DISCORD_BOT_TOKEN",
dm: { enabled: true, allowFrom: ["alice", "bob"] },
},
},
}
```
### OAuth with API key failover
```json5

View File

@@ -2039,7 +2039,6 @@ of `every`, keep `HEARTBEAT.md` tiny, and/or choose a cheaper `model`.
- `tools.web.search.cacheTtlMinutes` (default 15)
- `tools.web.fetch.enabled` (default true)
- `tools.web.fetch.maxChars` (default 50000)
- `tools.web.fetch.maxCharsCap` (default 50000; clamps maxChars from config/tool calls)
- `tools.web.fetch.timeoutSeconds` (default 30)
- `tools.web.fetch.cacheTtlMinutes` (default 15)
- `tools.web.fetch.userAgent` (optional override)
@@ -2552,9 +2551,7 @@ Notes:
- Set `MOONSHOT_API_KEY` in the environment or use `openclaw onboard --auth-choice moonshot-api-key`.
- Model ref: `moonshot/kimi-k2.5`.
- For the China endpoint, either:
- Run `openclaw onboard --auth-choice moonshot-api-key-cn` (wizard will set `https://api.moonshot.cn/v1`), or
- Manually set `baseUrl: "https://api.moonshot.cn/v1"` in `models.providers.moonshot`.
- Use `https://api.moonshot.cn/v1` if you need the China endpoint.
### Kimi Coding
@@ -2766,7 +2763,6 @@ Fields:
- `per-peer`: isolate DMs by sender id across channels.
- `per-channel-peer`: isolate DMs per channel + sender (recommended for multi-user inboxes).
- `per-account-channel-peer`: isolate DMs per account + channel + sender (recommended for multi-account inboxes).
- Secure DM mode (recommended): set `session.dmScope: "per-channel-peer"` when multiple people can DM the bot (shared inboxes, multi-person allowlists, or `dmPolicy: "open"`).
- `identityLinks`: map canonical ids to provider-prefixed peers so the same person shares a DM session across channels when using `per-peer`, `per-channel-peer`, or `per-account-channel-peer`.
- Example: `alice: ["telegram:123456789", "discord:987654321012345678"]`.
- `reset`: primary reset policy. Defaults to daily resets at 4:00 AM local time on the gateway host.
@@ -2956,7 +2952,6 @@ Control UI base path:
- `gateway.controlUi.basePath` sets the URL prefix where the Control UI is served.
- Examples: `"/ui"`, `"/openclaw"`, `"/apps/openclaw"`.
- Default: root (`/`) (unchanged).
- `gateway.controlUi.root` sets the filesystem root for Control UI assets (default: `dist/control-ui`).
- `gateway.controlUi.allowInsecureAuth` allows token-only auth for the Control UI when
device identity is omitted (typically over HTTP). Default: `false`. Prefer HTTPS
(Tailscale Serve) or `127.0.0.1`.

View File

@@ -205,16 +205,7 @@ By default, OpenClaw routes **all DMs into the main session** so your assistant
}
```
This prevents cross-user context leakage while keeping group chats isolated.
### Secure DM mode (recommended)
Treat the snippet above as **secure DM mode**:
- Default: `session.dmScope: "main"` (all DMs share one session for continuity).
- Secure DM mode: `session.dmScope: "per-channel-peer"` (each channel+sender pair gets an isolated DM context).
If you run multiple accounts on the same channel, use `per-account-channel-peer` instead. If the same person contacts you on multiple channels, use `session.identityLinks` to collapse those DM sessions into one canonical identity. See [Session Management](/concepts/session) and [Configuration](/gateway/configuration).
This prevents cross-user context leakage while keeping group chats isolated. If you run multiple accounts on the same channel, use `per-account-channel-peer` instead. If the same person contacts you on multiple channels, use `session.identityLinks` to collapse those DM sessions into one canonical identity. See [Session Management](/concepts/session) and [Configuration](/gateway/configuration).
## Allowlists (DM + groups) — terminology

File diff suppressed because it is too large Load Diff

View File

@@ -210,8 +210,7 @@ Example:
- [Telegram](/channels/telegram)
- [Discord](/channels/discord)
- [Mattermost (plugin)](/channels/mattermost)
- [BlueBubbles (iMessage)](/channels/bluebubbles)
- [iMessage (legacy)](/channels/imessage)
- [iMessage](/channels/imessage)
- [Groups](/concepts/groups)
- [WhatsApp group messages](/concepts/group-messages)
- [Media: images](/nodes/images)

View File

@@ -79,9 +79,10 @@ Or with pnpm:
```bash
pnpm add -g openclaw@latest
pnpm approve-builds -g # approve openclaw, node-llama-cpp, sharp, etc.
pnpm add -g openclaw@latest # re-run to execute postinstall scripts
```
pnpm requires explicit approval for packages with build scripts. After the first install shows the "Ignored build scripts" warning, run `pnpm approve-builds -g` and select the listed packages.
pnpm requires explicit approval for packages with build scripts. After the first install shows the "Ignored build scripts" warning, run `pnpm approve-builds -g` and select the listed packages, then re-run the install so postinstall scripts execute.
Then:

View File

@@ -29,7 +29,7 @@ Notes:
```
The installer will `git pull --rebase` **only** if the repo is clean.
- For **global installs**, the script uses `npm install -g openclaw@latest` under the hood.
- Legacy note: `clawdbot` remains available as a compatibility shim.
- Legacy note: `openclaw` remains available as a compatibility shim.
## Before you update

View File

@@ -446,10 +446,7 @@ Example voice-call config with ngrok:
"enabled": true,
"config": {
"provider": "twilio",
"tunnel": { "provider": "ngrok" },
"webhookSecurity": {
"allowedHosts": ["example.ngrok.app"]
}
"tunnel": { "provider": "ngrok" }
}
}
}
@@ -457,7 +454,7 @@ Example voice-call config with ngrok:
}
```
The ngrok tunnel runs inside the container and provides a public webhook URL without exposing the Fly app itself. Set `webhookSecurity.allowedHosts` to the public tunnel hostname so forwarded host headers are accepted.
The ngrok tunnel runs inside the container and provides a public webhook URL without exposing the Fly app itself.
### Security benefits

View File

@@ -34,17 +34,17 @@ Notes:
# From repo root; set release IDs so Sparkle feed is enabled.
# APP_BUILD must be numeric + monotonic for Sparkle compare.
BUNDLE_ID=bot.molt.mac \
APP_VERSION=2026.2.3 \
APP_VERSION=2026.2.1 \
APP_BUILD="$(git rev-list --count HEAD)" \
BUILD_CONFIG=release \
SIGN_IDENTITY="Developer ID Application: <Developer Name> (<TEAMID>)" \
scripts/package-mac-app.sh
# Zip for distribution (includes resource forks for Sparkle delta support)
ditto -c -k --sequesterRsrc --keepParent dist/OpenClaw.app dist/OpenClaw-2026.2.3.zip
ditto -c -k --sequesterRsrc --keepParent dist/OpenClaw.app dist/OpenClaw-2026.2.1.zip
# Optional: also build a styled DMG for humans (drag to /Applications)
scripts/create-dmg.sh dist/OpenClaw.app dist/OpenClaw-2026.2.3.dmg
scripts/create-dmg.sh dist/OpenClaw.app dist/OpenClaw-2026.2.1.dmg
# Recommended: build + notarize/staple zip + DMG
# First, create a keychain profile once:
@@ -52,14 +52,14 @@ scripts/create-dmg.sh dist/OpenClaw.app dist/OpenClaw-2026.2.3.dmg
# --apple-id "<apple-id>" --team-id "<team-id>" --password "<app-specific-password>"
NOTARIZE=1 NOTARYTOOL_PROFILE=openclaw-notary \
BUNDLE_ID=bot.molt.mac \
APP_VERSION=2026.2.3 \
APP_VERSION=2026.2.1 \
APP_BUILD="$(git rev-list --count HEAD)" \
BUILD_CONFIG=release \
SIGN_IDENTITY="Developer ID Application: <Developer Name> (<TEAMID>)" \
scripts/package-mac-dist.sh
# Optional: ship dSYM alongside the release
ditto -c -k --keepParent apps/macos/.build/release/OpenClaw.app.dSYM dist/OpenClaw-2026.2.3.dSYM.zip
ditto -c -k --keepParent apps/macos/.build/release/OpenClaw.app.dSYM dist/OpenClaw-2026.2.1.dSYM.zip
```
## Appcast entry
@@ -67,7 +67,7 @@ ditto -c -k --keepParent apps/macos/.build/release/OpenClaw.app.dSYM dist/OpenCl
Use the release note generator so Sparkle renders formatted HTML notes:
```bash
SPARKLE_PRIVATE_KEY_FILE=/path/to/ed25519-private-key scripts/make_appcast.sh dist/OpenClaw-2026.2.3.zip https://raw.githubusercontent.com/openclaw/openclaw/main/appcast.xml
SPARKLE_PRIVATE_KEY_FILE=/path/to/ed25519-private-key scripts/make_appcast.sh dist/OpenClaw-2026.2.1.zip https://raw.githubusercontent.com/openclaw/openclaw/main/appcast.xml
```
Generates HTML release notes from `CHANGELOG.md` (via [`scripts/changelog-to-html.sh`](https://github.com/openclaw/openclaw/blob/main/scripts/changelog-to-html.sh)) and embeds them in the appcast entry.
@@ -75,7 +75,7 @@ Commit the updated `appcast.xml` alongside the release assets (zip + dSYM) when
## Publish & verify
- Upload `OpenClaw-2026.2.3.zip` (and `OpenClaw-2026.2.3.dSYM.zip`) to the GitHub release for tag `v2026.2.3`.
- Upload `OpenClaw-2026.2.1.zip` (and `OpenClaw-2026.2.1.dSYM.zip`) to the GitHub release for tag `v2026.2.1`.
- Ensure the raw appcast URL matches the baked feed: `https://raw.githubusercontent.com/openclaw/openclaw/main/appcast.xml`.
- Sanity checks:
- `curl -I https://raw.githubusercontent.com/openclaw/openclaw/main/appcast.xml` returns 200.

View File

@@ -81,12 +81,6 @@ Set config under `plugins.entries.voice-call.config`:
path: "/voice/webhook",
},
// Webhook security (recommended for tunnels/proxies)
webhookSecurity: {
allowedHosts: ["voice.example.com"],
trustedProxyIPs: ["100.64.0.1"],
},
// Public exposure (pick one)
// publicUrl: "https://example.ngrok.app/voice/webhook",
// tunnel: { provider: "ngrok" },
@@ -117,38 +111,6 @@ Notes:
- `tunnel.allowNgrokFreeTierLoopbackBypass: true` allows Twilio webhooks with invalid signatures **only** when `tunnel.provider="ngrok"` and `serve.bind` is loopback (ngrok local agent). Use for local dev only.
- Ngrok free tier URLs can change or add interstitial behavior; if `publicUrl` drifts, Twilio signatures will fail. For production, prefer a stable domain or Tailscale funnel.
## Webhook Security
When a proxy or tunnel sits in front of the Gateway, the plugin reconstructs the
public URL for signature verification. These options control which forwarded
headers are trusted.
`webhookSecurity.allowedHosts` allowlists hosts from forwarding headers.
`webhookSecurity.trustForwardingHeaders` trusts forwarded headers without an allowlist.
`webhookSecurity.trustedProxyIPs` only trusts forwarded headers when the request
remote IP matches the list.
Example with a stable public host:
```json5
{
plugins: {
entries: {
"voice-call": {
config: {
publicUrl: "https://voice.example.com/voice/webhook",
webhookSecurity: {
allowedHosts: ["voice.example.com"],
},
},
},
},
},
}
```
## TTS for calls
Voice Call uses the core `messages.tts` configuration (OpenAI or ElevenLabs) for

View File

@@ -106,7 +106,6 @@ Current npm plugin list (update as needed):
- @openclaw/bluebubbles
- @openclaw/diagnostics-otel
- @openclaw/discord
- @openclaw/feishu
- @openclaw/lobster
- @openclaw/matrix
- @openclaw/msteams

View File

@@ -1,5 +1,5 @@
---
summary: "RPC adapters for external CLIs (signal-cli, legacy imsg) and gateway patterns"
summary: "RPC adapters for external CLIs (signal-cli, imsg) and gateway patterns"
read_when:
- Adding or changing external CLI integrations
- Debugging RPC adapters (signal-cli, imsg)
@@ -19,11 +19,9 @@ OpenClaw integrates external CLIs via JSON-RPC. Two patterns are used today.
See [Signal](/channels/signal) for setup and endpoints.
## Pattern B: stdio child process (legacy: imsg)
## Pattern B: stdio child process (imsg)
> **Note:** For new iMessage setups, use [BlueBubbles](/channels/bluebubbles) instead.
- OpenClaw spawns `imsg rpc` as a child process (legacy iMessage integration).
- OpenClaw spawns `imsg rpc` as a child process.
- JSON-RPC is line-delimited over stdin/stdout (one JSON object per line).
- No TCP port, no daemon required.
@@ -34,7 +32,7 @@ Core methods used:
- `send`
- `chats.list` (probe/diagnostics)
See [iMessage](/channels/imessage) for legacy setup and addressing (`chat_id` preferred).
See [iMessage](/channels/imessage) for setup and addressing (`chat_id` preferred).
## Adapter guidelines

View File

@@ -11,15 +11,11 @@ title: "Transcript Hygiene"
This document describes **provider-specific fixes** applied to transcripts before a run
(building model context). These are **in-memory** adjustments used to satisfy strict
provider requirements. These hygiene steps do **not** rewrite the stored JSONL transcript
on disk; however, a separate session-file repair pass may rewrite malformed JSONL files
by dropping invalid lines before the session is loaded. When a repair occurs, the original
file is backed up alongside the session file.
provider requirements. They do **not** rewrite the stored JSONL transcript on disk.
Scope includes:
- Tool call id sanitization
- Tool call input validation
- Tool result pairing repair
- Turn validation / ordering
- Thought signature cleanup
@@ -40,11 +36,6 @@ All transcript hygiene is centralized in the embedded runner:
The policy uses `provider`, `modelApi`, and `modelId` to decide what to apply.
Separate from transcript hygiene, session files are repaired (if needed) before load:
- `repairSessionFileIfNeeded` in `src/agents/session-file-repair.ts`
- Called from `run/attempt.ts` and `compact.ts` (embedded runner)
---
## Global rule: image sanitization
@@ -59,19 +50,6 @@ Implementation:
---
## Global rule: malformed tool calls
Assistant tool-call blocks that are missing both `input` and `arguments` are dropped
before model context is built. This prevents provider rejections from partially
persisted tool calls (for example, after a rate limit failure).
Implementation:
- `sanitizeToolCallInputs` in `src/agents/session-transcript-repair.ts`
- Applied in `sanitizeSessionHistory` in `src/agents/pi-embedded-runner/google.ts`
---
## Provider matrix (current behavior)
**OpenAI / OpenAI Codex**

View File

@@ -17,6 +17,11 @@ Use these when a task is clearly tied to a script; otherwise prefer the CLI.
- Prefer CLI surfaces when they exist (example: auth monitoring uses `openclaw models status --check`).
- Assume scripts are hostspecific; read them before running on a new machine.
## Git hooks
- `scripts/setup-git-hooks.js`: best-effort setup for `core.hooksPath` when inside a git repo.
- `scripts/format-staged.js`: pre-commit formatter for staged `src/` and `test/` files.
## Auth monitoring scripts
Auth monitoring scripts are documented here:

View File

@@ -71,8 +71,7 @@ Use these hubs to discover every page, including deep dives and reference docs t
- [Discord](/channels/discord)
- [Mattermost](/channels/mattermost) (plugin)
- [Signal](/channels/signal)
- [BlueBubbles (iMessage)](/channels/bluebubbles)
- [iMessage (legacy)](/channels/imessage)
- [iMessage](/channels/imessage)
- [Location parsing](/channels/location)
- [WebChat](/web/webchat)
- [Webhooks](/automation/webhook)

View File

@@ -80,7 +80,6 @@ Stored under `~/.openclaw/devices/`:
- Telegram: [Telegram](/channels/telegram)
- WhatsApp: [WhatsApp](/channels/whatsapp)
- Signal: [Signal](/channels/signal)
- BlueBubbles (iMessage): [BlueBubbles](/channels/bluebubbles)
- iMessage (legacy): [iMessage](/channels/imessage)
- iMessage: [iMessage](/channels/imessage)
- Discord: [Discord](/channels/discord)
- Slack: [Slack](/channels/slack)

View File

@@ -127,8 +127,7 @@ Tip: `--json` does **not** imply non-interactive mode. Use `--non-interactive` (
- [Google Chat](/channels/googlechat): service account JSON + webhook audience.
- [Mattermost](/channels/mattermost) (plugin): bot token + base URL.
- [Signal](/channels/signal): optional `signal-cli` install + account config.
- [BlueBubbles](/channels/bluebubbles): **recommended for iMessage**; server URL + password + webhook.
- [iMessage](/channels/imessage): legacy `imsg` CLI path + DB access.
- [iMessage](/channels/imessage): local `imsg` CLI path + DB access.
- DM security: default is pairing. First DM sends a code; approve via `openclaw pairing approve <channel> <code>` or use allowlists.
6. **Daemon install**
@@ -330,5 +329,5 @@ will prompt to install it (npm or a local path) before it can be configured.
- macOS app onboarding: [Onboarding](/start/onboarding)
- Config reference: [Gateway configuration](/gateway/configuration)
- Providers: [WhatsApp](/channels/whatsapp), [Telegram](/channels/telegram), [Discord](/channels/discord), [Google Chat](/channels/googlechat), [Signal](/channels/signal), [BlueBubbles](/channels/bluebubbles) (iMessage), [iMessage](/channels/imessage) (legacy)
- Providers: [WhatsApp](/channels/whatsapp), [Telegram](/channels/telegram), [Discord](/channels/discord), [Google Chat](/channels/googlechat), [Signal](/channels/signal), [iMessage](/channels/imessage)
- Skills: [Skills](/tools/skills), [Skills config](/tools/skills-config)

View File

@@ -128,8 +128,6 @@ Shell chaining and redirections are not auto-allowed in allowlist mode.
Shell chaining (`&&`, `||`, `;`) is allowed when every top-level segment satisfies the allowlist
(including safe bins or skill auto-allow). Redirections remain unsupported in allowlist mode.
Command substitution (`$()` / backticks) is rejected during allowlist parsing, including inside
double quotes; use single quotes if you need literal `$()` text.
Default safe bins: `jq`, `grep`, `cut`, `sort`, `uniq`, `head`, `tail`, `tr`, `wc`.

View File

@@ -252,7 +252,6 @@ Core parameters:
Notes:
- Enable via `tools.web.fetch.enabled`.
- `maxChars` is clamped by `tools.web.fetch.maxCharsCap` (default 50000).
- Responses are cached (default 15 min).
- For JS-heavy sites, prefer the browser tool.
- See [Web tools](/tools/web) for setup.

View File

@@ -221,7 +221,6 @@ Fetch a URL and extract readable content.
fetch: {
enabled: true,
maxChars: 50000,
maxCharsCap: 50000,
timeoutSeconds: 30,
cacheTtlMinutes: 15,
maxRedirects: 3,
@@ -253,7 +252,6 @@ Notes:
- Firecrawl requests use bot-circumvention mode and cache results by default.
- `web_fetch` sends a Chrome-like User-Agent and `Accept-Language` by default; override `userAgent` if needed.
- `web_fetch` blocks private/internal hostnames and re-checks redirects (limit with `maxRedirects`).
- `maxChars` is clamped to `tools.web.fetch.maxCharsCap`.
- `web_fetch` is best-effort extraction; some sites will need the browser tool.
- See [Firecrawl](/tools/firecrawl) for key setup and service details.
- Responses are cached (default 15 minutes) to reduce repeated fetches.

View File

@@ -79,11 +79,6 @@ you revoke it with `openclaw devices revoke --device <id> --role <role>`. See
- Logs: live tail of gateway file logs with filter/export (`logs.tail`)
- Update: run a package/git update + restart (`update.run`) with a restart report
Cron jobs panel notes:
- For isolated jobs, delivery defaults to announce summary. You can switch to none if you want internal-only runs.
- Channel/target fields appear when announce is selected.
## Chat behavior
- `chat.send` is **non-blocking**: it acks immediately with `{ runId, status: "started" }` and the response streams via `chat` events.
@@ -202,20 +197,5 @@ Notes:
- `gatewayUrl` is stored in localStorage after load and removed from the URL.
- `token` is stored in localStorage; `password` is kept in memory only.
- Use `wss://` when the Gateway is behind TLS (Tailscale Serve, HTTPS proxy, etc.).
- `gatewayUrl` is only accepted in a top-level window (not embedded) to prevent clickjacking.
- For cross-origin dev setups (e.g. `pnpm ui:dev` to a remote Gateway), add the UI
origin to `gateway.controlUi.allowedOrigins`.
Example:
```json5
{
gateway: {
controlUi: {
allowedOrigins: ["http://localhost:5173"],
},
},
}
```
Remote access setup details: [Remote access](/gateway/remote).

View File

@@ -99,8 +99,6 @@ Open:
- Non-loopback binds still **require** a shared token/password (`gateway.auth` or env).
- The wizard generates a gateway token by default (even on loopback).
- The UI sends `connect.params.auth.token` or `connect.params.auth.password`.
- The Control UI sends anti-clickjacking headers and only accepts same-origin browser
websocket connections unless `gateway.controlUi.allowedOrigins` is set.
- With Serve, Tailscale identity headers can satisfy auth when
`gateway.auth.allowTailscale` is `true` (no token/password required). Set
`gateway.auth.allowTailscale: false` to require explicit credentials. See

View File

@@ -1,59 +0,0 @@
# AGENTS.md - zh-CN 文档翻译工作区
## Read When
- 维护 `docs/zh-CN/**`
- 更新中文翻译流水线glossary/TM/prompt
- 处理中文翻译反馈或回归
## Pipelinedocs-i18n
- 源文档:`docs/**/*.md`
- 目标文档:`docs/zh-CN/**/*.md`
- 术语表:`docs/.i18n/glossary.zh-CN.json`
- 翻译记忆库:`docs/.i18n/zh-CN.tm.jsonl`
- 提示词规则:`scripts/docs-i18n/translator.go`
常用运行方式:
```bash
# 批量doc 模式,可并行)
go run scripts/docs-i18n/main.go -mode doc -parallel 6 docs/**/*.md
# 单文件
go run scripts/docs-i18n/main.go -mode doc docs/channels/matrix.md
# 小范围补丁segment 模式,使用 TM不支持并行
go run scripts/docs-i18n/main.go -mode segment docs/channels/matrix.md
```
注意事项:
- doc 模式用于整页翻译segment 模式用于小范围修补(依赖 TM
- 超大文件若超时,优先做**定点替换**或拆分后再跑。
- 翻译后检查中文引号、CJK-Latin 间距和术语一致性。
## zh-CN 样式规则
- CJK-Latin 间距:遵循 W3C CLREQ`Gateway 网关``Skills 配置`)。
- 中文引号:正文/标题使用 `“”`;代码/CLI/键名保持 ASCII 引号。
- 术语保留英文:`Skills``local loopback``Tailscale`
- 代码块/内联代码:保持原样,不在代码内插入空格或引号替换。
## 关键术语(#6995 修复)
- `Gateway 网关`
- `Skills 配置`
- `沙箱`
- `预期键名`
- `配套应用`
- `分块流式传输`
- `设备发现`
## 反馈与变更记录
- 反馈来源GitHub issue #6995
- 反馈用户:@AaronWander@taiyi747@Explorer1092@rendaoyuan
- 变更要点:更新 prompt 规则、扩充 glossary、清理 TM、批量再生成 + 定点修复
- 参考链接https://github.com/openclaw/openclaw/issues/6995

View File

@@ -5,19 +5,19 @@ read_when:
summary: 监控模型提供商的 OAuth 过期状态
title: 认证监控
x-i18n:
generated_at: "2026-02-03T10:03:53Z"
generated_at: "2026-02-01T19:36:14Z"
model: claude-opus-4-5
provider: pi
source_hash: eef179af9545ed7ab881f3ccbef998869437fb50cdb4088de8da7223b614fa2b
source_path: automation/auth-monitoring.md
workflow: 15
workflow: 14
---
# 认证监控
OpenClaw 通过 `openclaw models status` 提供 OAuth 过期健康状态。请使用该命令进行自动化和告警;脚本是手机工作流程提供的可选附加功能
OpenClaw 通过 `openclaw models status` 暴露 OAuth 过期健康状态。可将其用于自动化和告警;脚本是针对手机工作流的可选补充
## 推荐方式CLI 检查(可移植
## 推荐方式CLI 检查(跨平台通用
```bash
openclaw models status --check
@@ -26,22 +26,22 @@ openclaw models status --check
退出码:
- `0`:正常
- `1`:凭证过期或缺失
- `1`:凭证过期或缺失
- `2`即将过期24 小时内)
此方式适用于 cron/systemd无需额外脚本。
适用于 cron/systemd无需额外脚本。
## 可选脚本(运维 / 手机工作流
## 可选脚本(运维/手机工作流)
这些脚本位于 `scripts/` 目录下,属于**可选**内容。它们假定你可以通过 SSH 访问 Gateway 网关主机,并针对 systemd + Termux 进行了调优。
这些脚本位于 `scripts/` 目录下,属于**可选**。它们假定你可以通过 SSH 访问 Gateway网关主机并针对 systemd + Termux 进行了调优。
- `scripts/claude-auth-status.sh` 现在使用 `openclaw models status --json` 作为数据源(如果 CLI 不可用则回退到直接读取文件),因此请确保 `openclaw`定时器的 `PATH` 中。
- `scripts/claude-auth-status.sh` 现在使用 `openclaw models status --json` 作为数据源(如果 CLI 不可用则回退到直接读取文件),因此请确保定时器中 `openclaw``PATH` 中。
- `scripts/auth-monitor.sh`cron/systemd 定时器目标发送告警ntfy 或手机)。
- `scripts/systemd/openclaw-auth-monitor.{service,timer}`systemd 用户定时器。
- `scripts/claude-auth-status.sh`Claude Code + OpenClaw 认证检查器(完整/json/简洁模式)。
- `scripts/mobile-reauth.sh`:通过 SSH 引导重新认证流程。
- `scripts/termux-quick-auth.sh`:一键小件状态查看 + 打开认证 URL。
- `scripts/termux-auth-widget.sh`:完整的引导式小件流程。
- `scripts/termux-sync-widget.sh`同步 Claude Code 凭证 OpenClaw。
- `scripts/mobile-reauth.sh`:通过 SSH 进行引导重新认证流程。
- `scripts/termux-quick-auth.sh`:一键小件状态查看 + 打开认证 URL。
- `scripts/termux-auth-widget.sh`:完整的引导式小件流程。
- `scripts/termux-sync-widget.sh` Claude Code 凭证同步至 OpenClaw。
如果你不需要手机自动化或 systemd 定时器,可以跳过这些脚本。

View File

@@ -28,7 +28,7 @@ x-i18n:
- 任务持久化存储在 `~/.openclaw/cron/` 下,因此重启不会丢失计划。
- 两种执行方式:
- **主会话**:入队一个系统事件,然后在下一次心跳时运行。
- **隔离式**:在 `cron:<jobId>` 中运行专用智能体轮次,可投递摘要(默认 announce或不投递
- **隔离式**:在 `cron:<jobId>` 中运行专用智能体轮次,可选择投递输出
- 唤醒是一等功能:任务可以请求"立即唤醒"或"下次心跳时"。
## 快速开始(可操作)
@@ -58,7 +58,7 @@ openclaw cron add \
--tz "America/Los_Angeles" \
--session isolated \
--message "Summarize overnight updates." \
--announce \
--deliver \
--channel slack \
--to "channel:C1234567890"
```
@@ -88,8 +88,7 @@ openclaw cron add \
- 主会话 → `payload.kind = "systemEvent"`
- 隔离会话 → `payload.kind = "agentTurn"`
可选:一次性任务(`schedule.kind = "at"`)默认会在成功运行后删除。设置
`deleteAfterRun: false` 可保留它(成功后会禁用)。
可选:`deleteAfterRun: true` 会在一次性任务成功运行后将其从存储中删除。
## 概念
@@ -104,13 +103,13 @@ openclaw cron add \
任务通过稳定的 `jobId` 标识(用于 CLI/Gateway网关 API
在智能体工具调用中,`jobId` 是规范字段;旧版 `id` 仍可兼容使用。
一次性任务默认会在成功运行后自动删除;设置 `deleteAfterRun: false` 可保留它
任务可以通过 `deleteAfterRun: true` 在一次性任务成功运行后自动删除
### 调度计划
定时任务支持三种调度类型:
- `at`:一次性时间戳(ISO 8601 字符串)
- `at`:一次性时间戳(自纪元起的毫秒数。Gateway网关接受 ISO 8601 格式并转换为 UTC
- `every`:固定间隔(毫秒)。
- `cron`5 字段 cron 表达式,可选 IANA 时区。
@@ -135,8 +134,9 @@ Cron 表达式使用 `croner`。如果省略时区,将使用 Gateway网关主
- 提示以 `[cron:<jobId> <任务名称>]` 为前缀,便于追踪。
- 每次运行都会启动一个**全新的会话 ID**(不继承之前的对话)。
- 如果未指定 `delivery`隔离任务会默认以“announce”方式投递摘要
- `delivery.mode` 可选 `announce`(投递摘要)或 `none`(内部运行)
- 摘要会发布到主会话(前缀 `Cron`,可配置)
- `wakeMode: "now"` 在发布摘要后触发立即心跳
- 如果 `payload.deliver: true`,输出会投递到渠道;否则保留在内部。
对于嘈杂、频繁或"后台杂务"类任务,使用隔离任务可以避免污染你的主聊天记录。
@@ -152,6 +152,16 @@ Cron 表达式使用 `croner`。如果省略时区,将使用 Gateway网关主
- `message`:必填文本提示。
- `model` / `thinking`:可选覆盖(见下文)。
- `timeoutSeconds`:可选超时覆盖。
- `deliver`:设为 `true` 以将输出发送到渠道目标。
- `channel``last` 或特定渠道。
- `to`:渠道特定目标(电话/聊天/频道 ID
- `bestEffortDeliver`:投递失败时避免任务失败。
隔离选项(仅适用于 `session=isolated`
- `postToMainPrefix`CLI`--post-prefix`):主会话中系统事件的前缀。
- `postToMainMode``summary`(默认)或 `full`
- `postToMainMaxChars`:当 `postToMainMode=full` 时的最大字符数(默认 8000
### 模型和思维覆盖
@@ -170,16 +180,18 @@ Cron 表达式使用 `croner`。如果省略时区,将使用 Gateway网关主
### 投递(渠道 + 目标)
隔离任务可以通过顶层 `delivery` 配置投递输出
隔离任务可以将输出投递到渠道。任务负载可以指定
- `delivery.mode``announce`(投递摘要)或 `none`
- `delivery.channel``whatsapp` / `telegram` / `discord` / `slack` / `mattermost`(插件)/ `signal` / `imessage` / `last`
- `delivery.to`:渠道特定的接收目标
- `delivery.bestEffort`:投递失败时避免任务失败
- `channel``whatsapp` / `telegram` / `discord` / `slack` / `mattermost`(插件)/ `signal` / `imessage` / `last`
- `to`:渠道特定的接收目标
当启用 announce 投递时,该轮次会抑制消息工具发送;请使用 `delivery.channel`/`delivery.to` 来指定目标
如果省略 `channel``to`,定时任务可以回退到主会话的"最后路由"(智能体最后回复的位置)
如果省略 `delivery.channel``delivery.to`,定时任务会回退到主会话的“最后路由”(智能体最后回复的位置)。
投递说明:
- 如果设置了 `to`,即使省略 `deliver`,定时任务也会自动投递智能体的最终输出。
- 当你需要最后路由投递但不指定明确 `to` 时,使用 `deliver: true`
- 使用 `deliver: false` 即使存在 `to` 也保持输出为内部使用。
目标格式提醒:
@@ -200,7 +212,7 @@ Telegram 通过 `message_thread_id` 支持论坛主题。对于定时任务投
## 工具调用的 JSON 模式
直接调用 Gateway网关 `cron.*` 工具(智能体工具调用或 RPC时使用这些结构。CLI 标志接受人类可读的时间格式如 `20m`,但工具调用应使用 ISO 8601 字符串作为 `schedule.at`,并使用毫秒作为 `schedule.everyMs`
直接调用 Gateway网关 `cron.*` 工具(智能体工具调用或 RPC时使用这些结构。CLI 标志接受人类可读的时间格式如 `20m`,但工具调用`atMs``everyMs` 使用纪元毫秒数(`at` 时间接受 ISO 时间戳)
### cron.add 参数
@@ -209,7 +221,7 @@ Telegram 通过 `message_thread_id` 支持论坛主题。对于定时任务投
```json
{
"name": "Reminder",
"schedule": { "kind": "at", "at": "2026-02-01T16:00:00Z" },
"schedule": { "kind": "at", "atMs": 1738262400000 },
"sessionTarget": "main",
"wakeMode": "now",
"payload": { "kind": "systemEvent", "text": "Reminder text" },
@@ -227,24 +239,22 @@ Telegram 通过 `message_thread_id` 支持论坛主题。对于定时任务投
"wakeMode": "next-heartbeat",
"payload": {
"kind": "agentTurn",
"message": "Summarize overnight updates."
},
"delivery": {
"mode": "announce",
"message": "Summarize overnight updates.",
"deliver": true,
"channel": "slack",
"to": "channel:C1234567890",
"bestEffort": true
}
"bestEffortDeliver": true
},
"isolation": { "postToMainPrefix": "Cron", "postToMainMode": "summary" }
}
```
说明:
- `schedule.kind``at``at`)、`every``everyMs`)或 `cron``expr`,可选 `tz`)。
- `schedule.at` 接受 ISO 8601可省略时区省略时按 UTC 处理)
- `everyMs` 为毫秒数。
- `schedule.kind``at``atMs`)、`every``everyMs`)或 `cron``expr`,可选 `tz`)。
- `atMs``everyMs` 为纪元毫秒数
- `sessionTarget` 必须为 `"main"``"isolated"`,且必须与 `payload.kind` 匹配。
- 可选字段:`agentId``description``enabled``deleteAfterRun``delivery`
- 可选字段:`agentId``description``enabled``deleteAfterRun``isolation`
- `wakeMode` 省略时默认为 `"next-heartbeat"`
### cron.update 参数
@@ -331,7 +341,7 @@ openclaw cron add \
--tz "America/Los_Angeles" \
--session isolated \
--message "Summarize inbox + calendar for today." \
--announce \
--deliver \
--channel whatsapp \
--to "+15551234567"
```
@@ -345,7 +355,7 @@ openclaw cron add \
--tz "America/Los_Angeles" \
--session isolated \
--message "Summarize today; send to the nightly topic." \
--announce \
--deliver \
--channel telegram \
--to "-1001234567890:topic:123"
```
@@ -361,7 +371,7 @@ openclaw cron add \
--message "Weekly deep analysis of project progress." \
--model "opus" \
--thinking high \
--announce \
--deliver \
--channel whatsapp \
--to "+15551234567"
```

View File

@@ -97,7 +97,7 @@ x-i18n:
- **精确定时**:支持带时区的 5 字段 cron 表达式。
- **会话隔离**:在 `cron:<jobId>` 中运行,不会污染主会话历史。
- **模型覆盖**:可按任务使用更便宜或更强大的模型。
- **投递控制**隔离任务默认以 `announce` 投递摘要,可选 `none` 仅内部运行
- **投递控制**可直接投递到渠道;默认仍会向主会话发布摘要(可配置)
- **无需智能体上下文**:即使主会话空闲或已压缩,也能运行。
- **一次性支持**`--at` 用于精确的未来时间戳。
@@ -111,7 +111,7 @@ openclaw cron add \
--session isolated \
--message "Generate today's briefing: weather, calendar, top emails, news summary." \
--model opus \
--announce \
--deliver \
--channel whatsapp \
--to "+15551234567"
```
@@ -180,7 +180,7 @@ openclaw cron add \
```bash
# 每天早上 7 点的早间简报
openclaw cron add --name "Morning brief" --cron "0 7 * * *" --session isolated --message "..." --announce
openclaw cron add --name "Morning brief" --cron "0 7 * * *" --session isolated --message "..." --deliver
# 每周一上午 9 点的项目回顾
openclaw cron add --name "Weekly review" --cron "0 9 * * 1" --session isolated --message "..." --model opus
@@ -219,13 +219,13 @@ Lobster 是用于**多步骤工具管道**的工作流运行时,适用于需
心跳和定时任务都可以与主会话交互,但方式不同:
| | 心跳 | 定时任务(主会话) | 定时任务(隔离式) |
| ------ | ------------------------ | ---------------------- | --------------------- |
| 会话 | 主会话 | 主会话(通过系统事件) | `cron:<jobId>` |
| 历史 | 共享 | 共享 | 每次运行全新 |
| 上下文 | 完整 | 完整 | 无(从零开始) |
| 模型 | 主会话模型 | 主会话模型 | 可覆盖 |
| 输出 | 非 `HEARTBEAT_OK` 时投递 | 心跳提示 + 事件 | announce 摘要(默认) |
| | 心跳 | 定时任务(主会话) | 定时任务(隔离式) |
| ------ | ------------------------ | ---------------------- | ------------------ |
| 会话 | 主会话 | 主会话(通过系统事件) | `cron:<jobId>` |
| 历史 | 共享 | 共享 | 每次运行全新 |
| 上下文 | 完整 | 完整 | 无(从零开始) |
| 模型 | 主会话模型 | 主会话模型 | 可覆盖 |
| 输出 | 非 `HEARTBEAT_OK` 时投递 | 心跳提示 + 事件 | 摘要发布到主会话 |
### 何时使用主会话定时任务
@@ -250,7 +250,7 @@ openclaw cron add \
- 无先前上下文的全新环境
- 不同的模型或思维设置
- 输出可通过 `announce` 直接投递摘要(或用 `none` 仅内部运行
- 输出直接投递到渠道(摘要默认仍会发布到主会话
- 不会把主会话搞得杂乱的历史记录
```bash
@@ -261,7 +261,7 @@ openclaw cron add \
--message "Weekly codebase analysis..." \
--model opus \
--thinking high \
--announce
--deliver
```
## 成本考量

View File

@@ -5,12 +5,12 @@ read_when:
summary: 通过 gogcli 将 Gmail Pub/Sub 推送接入 OpenClaw webhooks
title: Gmail PubSub
x-i18n:
generated_at: "2026-02-03T07:43:25Z"
generated_at: "2026-02-01T19:38:47Z"
model: claude-opus-4-5
provider: pi
source_hash: dfb92133b69177e4e984b7d072f5dc28aa53a9e0cf984a018145ed811aa96195
source_path: automation/gmail-pubsub.md
workflow: 15
workflow: 14
---
# Gmail Pub/Sub -> OpenClaw
@@ -20,11 +20,11 @@ x-i18n:
## 前置条件
- 已安装并登录 `gcloud`[安装指南](https://docs.cloud.google.com/sdk/docs/install-sdk))。
- 已安装 `gog` (gogcli) 并为 Gmail 账户授权[gogcli.sh](https://gogcli.sh/))。
- 已安装 `gog`gogcli)并已授权 Gmail 账[gogcli.sh](https://gogcli.sh/))。
- 已启用 OpenClaw hooks参见 [Webhooks](/automation/webhook))。
- 已登录 `tailscale`[tailscale.com](https://tailscale.com/))。支持的置使用 Tailscale Funnel 作为公共 HTTPS 端点。
其他隧道服务也可以使用,但需要自行配置/不受支持,需要手动接
目前我们支持的是 Tailscale。
- 已登录 `tailscale`[tailscale.com](https://tailscale.com/))。支持的置使用 Tailscale Funnel 作为公共 HTTPS 端点。
其他隧道服务也可以使用,但属于自行配置/不受支持,需要手动接线
目前我们支持的是 Tailscale。
示例 hook 配置(启用 Gmail 预设映射):
@@ -39,7 +39,7 @@ x-i18n:
}
```
将 Gmail 摘要投递到聊天界面,请用设置 `deliver` 以及可选的 `channel`/`to` 的映射覆盖预设
如需将 Gmail 摘要投递到聊天界面,可覆盖预设并设置 `deliver` 以及可选的 `channel`/`to` 的映射:
```json5
{
@@ -65,11 +65,11 @@ x-i18n:
}
```
如果你想使用固定渠道,请设置 `channel` + `to`。否则 `channel: "last"` 会使用上次的投递路由(默认回退到 WhatsApp
如果你想固定渠道,请设置 `channel` + `to`。否则 `channel: "last"` 会使用最后的投递路由(回退到 WhatsApp
为 Gmail 运行强制使用更便宜的模型,在映射中设置 `model``provider/model` 或别名)。如果你强制启用`agents.defaults.models`,请将其包含在
如需为 Gmail 运行强制使用更便宜的模型,在映射中设置 `model``provider/model` 或别名)。如果你设置`agents.defaults.models`,请将其包含在允许列表中
专门为 Gmail hooks 设置默认模型和思级别,在配置中添加 `hooks.gmail.model` / `hooks.gmail.thinking`
如需专门为 Gmail hooks 设置默认模型和思级别,在配置中添加 `hooks.gmail.model` / `hooks.gmail.thinking`
```json5
{
@@ -82,42 +82,42 @@ x-i18n:
}
```
注意事项
说明
- 映射中每个 hook 的 `model`/`thinking` 仍会覆盖这些默认值。
- 映射中每个 hook 的 `model`/`thinking` 仍会覆盖这些默认值。
- 回退顺序:`hooks.gmail.model``agents.defaults.model.fallbacks` → 主模型(认证/速率限制/超时)。
- 如果设置了 `agents.defaults.models`Gmail 模型必须在允许列表中。
- Gmail hook 内容默认使用外部内容安全边界包装。
禁用(危险),请设置 `hooks.gmail.allowUnsafeExternalContent: true`
- Gmail hook 内容默认使用外部内容安全边界进行包装。
如需禁用(危险),请设置 `hooks.gmail.allowUnsafeExternalContent: true`
进一步自定义负载处理,添加 `hooks.mappings` 或在 `hooks.transformsDir` 下添加 JS/TS 转换模块(参见 [Webhooks](/automation/webhook))。
如需进一步自定义负载处理,添加 `hooks.mappings` 或在 `hooks.transformsDir` 下添加 JS/TS 转换模块(参见 [Webhooks](/automation/webhook))。
## 向导(推荐)
使用 OpenClaw 助手将所有内容接入在一起(在 macOS 上通过 brew 安装依赖):
使用 OpenClaw 辅助工具一键完成所有配置(在 macOS 上通过 brew 安装依赖):
```bash
openclaw webhooks gmail setup \
--account openclaw@gmail.com
```
默认置:
默认置:
- 使用 Tailscale Funnel 作为公共推送端点。
-`openclaw webhooks gmail run` 写入 `hooks.gmail` 配置。
- 启用 Gmail hook 预设(`hooks.presets: ["gmail"]`)。
路径说明:当启用 `tailscale.mode`OpenClaw 会自动将 `hooks.gmail.serve.path` 设置为 `/`,并将公共路径保持在 `hooks.gmail.tailscale.path`(默认 `/gmail-pubsub`),因为 Tailscale 在代理前会剥离设置的路径前缀。
如果你需要后端接收带前缀的路径,请将 `hooks.gmail.tailscale.target`(或 `--tailscale-target`)设置为完整 URL`http://127.0.0.1:8788/gmail-pubsub`,并匹配 `hooks.gmail.serve.path`
路径说明:当启用 `tailscale.mode`OpenClaw 会自动将 `hooks.gmail.serve.path` 设置为 `/`,并将公共路径保持在 `hooks.gmail.tailscale.path`(默认 `/gmail-pubsub`),因为 Tailscale 在代理前会去除设置的路径前缀。
如果你需要后端接收带前缀的路径,请将 `hooks.gmail.tailscale.target`(或 `--tailscale-target`)设置为完整 URL`http://127.0.0.1:8788/gmail-pubsub`,并匹配 `hooks.gmail.serve.path`
要自定义端点?使用 `--push-endpoint <url>``--tailscale off`
要自定义端点?使用 `--push-endpoint <url>``--tailscale off`
平台说明:在 macOS 上,向导通过 Homebrew 安装 `gcloud``gogcli``tailscale`;在 Linux 上请先手动安装它们。
Gateway 网关自动启动(推荐):
Gateway网关自动启动推荐
-`hooks.enabled=true` 且设置了 `hooks.gmail.account`Gateway 网关会在启动时运行 `gog gmail watch serve` 并自动续期 watch。
- 设置 `OPENCLAW_SKIP_GMAIL_WATCHER=1` 可退出(如果你自运行守护进程则很有用)。
-`hooks.enabled=true` 且设置了 `hooks.gmail.account`Gateway网关会在启动时运行 `gog gmail watch serve` 并自动续期 watch。
- 设置 `OPENCLAW_SKIP_GMAIL_WATCHER=1` 可退出自动启动(如果你自运行守护进程则很有用)。
- 不要同时运行手动守护进程,否则会遇到 `listen tcp 127.0.0.1:8788: bind: address already in use`
手动守护进程(启动 `gog gmail watch serve` + 自动续期):
@@ -135,7 +135,7 @@ gcloud auth login
gcloud config set project <project-id>
```
注意Gmail watch 要求 Pub/Sub 主题与 OAuth 客户端位于同一项目中。
注意Gmail watch 要求 Pub/Sub 主题位于与 OAuth 客户端相同的项目中。
2. 启用 API
@@ -149,7 +149,7 @@ gcloud services enable gmail.googleapis.com pubsub.googleapis.com
gcloud pubsub topics create gog-gmail-watch
```
4. 允许 Gmail push 发布:
4. 允许 Gmail 推送发布:
```bash
gcloud pubsub topics add-iam-policy-binding gog-gmail-watch \
@@ -168,9 +168,9 @@ gog gmail watch start \
保存输出中的 `history_id`(用于调试)。
## 运行推送处理程序
## 运行推送处理
本地示例(共享 token 认证):
本地示例(共享令牌认证):
```bash
gog gmail watch serve \
@@ -185,17 +185,17 @@ gog gmail watch serve \
--max-bytes 20000
```
注意事项
说明
- `--token` 保护推送端点(`x-gog-token``?token=`)。
- `--hook-url` 指向 OpenClaw `/hooks/gmail`(已映射;隔离运行 + 摘要发送到主线程)。
- `--hook-url` 指向 OpenClaw `/hooks/gmail`(已映射;隔离运行 + 摘要发送到主会话)。
- `--include-body``--max-bytes` 控制发送到 OpenClaw 的正文片段。
推荐:`openclaw webhooks gmail run` 封装了相同的流程并自动续期 watch。
## 暴露处理程序(高级,不受支持)
## 暴露处理(高级,不受支持)
如果你需要非 Tailscale 隧道,请手动接并在推送订阅中使用公共 URL不受支持无保护措施
如果你需要非 Tailscale 隧道,请手动接线并在推送订阅中使用公共 URL不受支持无保护措施
```bash
cloudflared tunnel --url http://127.0.0.1:8788 --no-autoupdate
@@ -217,7 +217,7 @@ gog gmail watch serve --verify-oidc --oidc-email <svc@...>
## 测试
向被监的收件箱发送一条消息
向被监的收件箱发送一封邮件
```bash
gog gmail send \
@@ -227,7 +227,7 @@ gog gmail send \
--body "ping"
```
检查 watch 状态和历史记录
检查 watch 状态和历史:
```bash
gog gmail watch status --account openclaw@gmail.com
@@ -237,8 +237,8 @@ gog gmail history --account openclaw@gmail.com --since <historyId>
## 故障排除
- `Invalid topicName`:项目不匹配(主题不在 OAuth 客户端项目中)。
- `User not authorized`:主题缺少 `roles/pubsub.publisher`
- 空消息Gmail push 仅提供 `historyId`;通过 `gog gmail history` 获取。
- `User not authorized`:主题缺少 `roles/pubsub.publisher` 权限
- 空消息Gmail 推送仅提供 `historyId`;通过 `gog gmail history` 获取详情
## 清理

View File

@@ -1,16 +1,16 @@
---
read_when:
- 添加或修改投票支持
- 调试从 CLI 或 Gateway 网关发送的投票
summary: 通过 Gateway 网关 + CLI 发送投票
- 调试从 CLI 或 Gateway网关发送的投票
summary: 通过 Gateway网关 + CLI 发送投票
title: 投票
x-i18n:
generated_at: "2026-02-03T07:43:12Z"
generated_at: "2026-02-01T19:38:57Z"
model: claude-opus-4-5
provider: pi
source_hash: 760339865d27ec40def7996cac1d294d58ab580748ad6b32cc34d285d0314eaf
source_path: automation/poll.md
workflow: 15
workflow: 14
---
# 投票
@@ -19,7 +19,7 @@ x-i18n:
- WhatsAppWeb 渠道)
- Discord
- MS TeamsAdaptive Cards
- Microsoft TeamsAdaptive Cards
## CLI
@@ -47,30 +47,29 @@ openclaw message poll --channel msteams --target conversation:19:abc@thread.tacv
- `--poll-multi`:允许选择多个选项
- `--poll-duration-hours`:仅限 Discord省略时默认为 24
## Gateway 网关 RPC
## Gateway网关 RPC
方法:`poll`
参数:
- `to`(字符串,必
- `question`(字符串,必
- `options`(字符串数组,必
- `to`(字符串,必
- `question`(字符串,必
- `options`(字符串数组,必
- `maxSelections`(数字,可选)
- `durationHours`(数字,可选)
- `channel`(字符串,可选,默认:`whatsapp`
- `idempotencyKey`(字符串,必
- `idempotencyKey`(字符串,必
## 渠道差异
- WhatsApp2-12 个选项,`maxSelections` 必须在选项数量范围内,忽略 `durationHours`
- Discord2-10 个选项,`durationHours` 限制在 1-768 小时之间(默认 24`maxSelections > 1` 启用多选Discord 不支持严格的选择数量限制。
- MS TeamsAdaptive Card 投票(由 OpenClaw 管理)。原生投票 API`durationHours` 被忽略。
- Discord2-10 个选项,`durationHours` 限制在 1-768 小时(默认 24`maxSelections > 1` 启用多选Discord 不支持严格的选择数量限制。
- Microsoft TeamsAdaptive Card 投票(由 OpenClaw 管理)。没有原生投票 API`durationHours` 被忽略。
## 智能体工具Message
使用 `message` 工具的 `poll` 操作(`to``pollQuestion``pollOption`,可选 `pollMulti``pollDurationHours``channel`)。
注意Discord 没有"恰好选择 N 个"模式;`pollMulti` 映射为多选。
Teams 投票以 Adaptive Cards 形式渲染,需要 Gateway 网关保持在线
以将投票记录到 `~/.openclaw/msteams-polls.json`
注意Discord 没有"精确选择 N 个"模式;`pollMulti` 映射为多选。
Teams 投票以 Adaptive Cards 形式渲染,需要 Gateway网关保持在线以在 `~/.openclaw/msteams-polls.json` 中记录投票结果。

View File

@@ -1,21 +1,21 @@
---
read_when:
- 添加或改 webhook 端点
- 添加或改 webhook 端点
- 将外部系统接入 OpenClaw
summary: 用于唤醒和隔离智能体运行的 Webhook 入口
summary: 用于唤醒和隔离智能体运行的 Webhook 入口
title: Webhooks
x-i18n:
generated_at: "2026-02-03T07:43:23Z"
generated_at: "2026-02-01T19:39:20Z"
model: claude-opus-4-5
provider: pi
source_hash: f26b88864567be82366b1f66a4772ef2813c7846110c62fce6caf7313568265e
source_path: automation/webhook.md
workflow: 15
workflow: 14
---
# Webhooks
Gateway 网关可以暴露一个小型 HTTP webhook 端点用于外部触发。
Gateway网关可以暴露一个小型 HTTP webhook 端点用于外部触发。
## 启用
@@ -29,7 +29,7 @@ Gateway 网关可以暴露一个小型 HTTP webhook 端点用于外部触发。
}
```
注意事项
说明
-`hooks.enabled=true` 时,`hooks.token` 为必填项。
- `hooks.path` 默认为 `/hooks`
@@ -40,7 +40,7 @@ Gateway 网关可以暴露一个小型 HTTP webhook 端点用于外部触发。
- `Authorization: Bearer <token>`(推荐)
- `x-openclaw-token: <token>`
- `?token=<token>`(已弃用;会记录警告日志,将在未来的主要版本中移除)
- `?token=<token>`(已弃用;会记录警告,将在未来的主要版本中移除)
## 端点
@@ -52,13 +52,13 @@ Gateway 网关可以暴露一个小型 HTTP webhook 端点用于外部触发。
{ "text": "System line", "mode": "now" }
```
- `text` **必填**(字符串):事件描述(例如"收到新邮件")。
- `mode` 可选(`now` | `next-heartbeat`):是否立即触发心跳(默认 `now`)或等待下一次定期检查。
- `text` **必填**(字符串):事件描述(例如 "New email received")。
- `mode` 可选(`now` | `next-heartbeat`):是否触发立即心跳(默认 `now`)或等待下一次周期性检查。
效果:
- 为**主**会话入一个系统事件队列
- 如果 `mode=now`则立即触发心跳
- 为**主**会话入一个系统事件
- 如果 `mode=now`,触发立即心跳
### `POST /hooks/agent`
@@ -79,44 +79,44 @@ Gateway 网关可以暴露一个小型 HTTP webhook 端点用于外部触发。
}
```
- `message` **必填**(字符串):智能体处理的提示或消息。
- `name` 可选字符串hook 的可读名称(例如"GitHub"),用作会话摘要的前缀。
- `message` **必填**(字符串):智能体处理的提示或消息。
- `name` 可选字符串hook 的人类可读名称(例如 "GitHub"),用作会话摘要的前缀。
- `sessionKey` 可选(字符串):用于标识智能体会话的键。默认为随机的 `hook:<uuid>`。使用一致的键可以在 hook 上下文中进行多轮对话。
- `wakeMode` 可选(`now` | `next-heartbeat`):是否立即触发心跳(默认 `now`)或等待下一次定期检查。
- `deliver` 可选(布尔值):如果为 `true`,智能体的响应将发送到消息渠道。默认为 `true`。仅为心跳确认的响应会自动跳过。
- `channel` 可选(字符串):用于投递的消息渠道。可选值:`last``whatsapp``telegram``discord``slack``mattermost`(插件)、`signal``imessage``msteams`。默认为 `last`
- `to` 可选(字符串):渠道的接收标识符(例如 WhatsApp/Signal 的电话号码、Telegram 的聊天 ID、Discord/Slack/Mattermost插件的频道 ID、MS Teams 的会话 ID。默认为主会话中的最后一个接收
- `model` 可选(字符串):模型覆盖(例如 `anthropic/claude-3-5-sonnet` 或别名)。如果有限制,必须在允许的模型列表中。
- `thinking` 可选(字符串):思级别覆盖(例如 `low``medium``high`)。
- `wakeMode` 可选(`now` | `next-heartbeat`):是否触发立即心跳(默认 `now`)或等待下一次周期性检查。
- `deliver` 可选(布尔值):如果为 `true`,智能体的回复将发送到消息渠道。默认为 `true`。仅为心跳确认的回复会被自动跳过。
- `channel` 可选(字符串):投递的消息渠道。可选值:`last``whatsapp``telegram``discord``slack``mattermost`(插件)、`signal``imessage``msteams`。默认为 `last`
- `to` 可选(字符串):渠道的接收标识符(例如 WhatsApp/Signal 的电话号码、Telegram 的聊天 ID、Discord/Slack/Mattermost插件的频道 ID、Microsoft Teams 的会话 ID。默认为主会话中的最后一个接收
- `model` 可选(字符串):模型覆盖(例如 `anthropic/claude-3-5-sonnet` 或别名)。如果有模型限制,必须在允许的模型列表中。
- `thinking` 可选(字符串):思级别覆盖(例如 `low``medium``high`)。
- `timeoutSeconds` 可选(数字):智能体运行的最大持续时间(秒)。
效果:
- 运行一**隔离**智能体回合(独立的会话键)
- 始终**主**会话中发布摘要
- 如果 `wakeMode=now`则立即触发心跳
- 运行一**隔离**智能体轮次(使用独立的会话键)
- 始终将摘要发布到**主**会话
- 如果 `wakeMode=now`,触发立即心跳
### `POST /hooks/<name>`(映射)
自定义 hook 名称通过 `hooks.mappings` 解析(见配置)。映射可以将任意请求体转换为 `wake``agent` 操作,支持可选的模板或代码转换。
自定义 hook 名称通过 `hooks.mappings` 解析(见配置)。映射可以将任意请求体转换为 `wake``agent` 操作,支持可选的模板或代码转换。
映射选项(要):
映射选项(要):
- `hooks.presets: ["gmail"]` 启用内置的 Gmail 映射。
- `hooks.mappings` 允许你在配置中定义 `match``action` 和模板。
- `hooks.transformsDir` + `transform.module` 加载 JS/TS 模块用于自定义逻辑。
- `hooks.transformsDir` + `transform.module` 加载 JS/TS 模块以实现自定义逻辑。
- 使用 `match.source` 保持通用的接收端点(基于请求体的路由)。
- TS 转换需要 TS 加载器(例如 `bun``tsx`)或运行时预编译的 `.js`
- 在映射上设置 `deliver: true` + `channel`/`to` 可将回复路由到聊天界面(`channel` 默认为 `last`,回退到 WhatsApp
- `allowUnsafeExternalContent: true` 禁用该 hook 外部内容安全包装(危险;仅用于受信任的内部来源)。
- `openclaw webhooks gmail setup``openclaw webhooks gmail run` 写入 `hooks.gmail` 配置。完整的 Gmail 监听流程请参阅 [Gmail Pub/Sub](/automation/gmail-pubsub)。
- `allowUnsafeExternalContent: true` 该 hook 禁用外部内容安全包装(危险;仅受信任的内部来源)。
- `openclaw webhooks gmail setup``openclaw webhooks gmail run` 写入 `hooks.gmail` 配置。完整的 Gmail watch 流程请参阅 [Gmail Pub/Sub](/automation/gmail-pubsub)。
## 响应
- `200` 用于 `/hooks/wake`
- `202` 用于 `/hooks/agent`(异步运行已启动)
- `401` 认证失败
- `400` 请求体无效
- `400` 无效请求体
- `413` 请求体过大
## 示例
@@ -137,7 +137,7 @@ curl -X POST http://127.0.0.1:18789/hooks/agent \
### 使用不同的模型
智能体请求体(或映射)中添加 `model` 以覆盖该次运行的模型:
agent 请求体(或映射)中添加 `model` 以覆盖该次运行的模型:
```bash
curl -X POST http://127.0.0.1:18789/hooks/agent \
@@ -146,7 +146,7 @@ curl -X POST http://127.0.0.1:18789/hooks/agent \
-d '{"message":"Summarize inbox","name":"Email","model":"openai/gpt-5.2-mini"}'
```
如果你启用`agents.defaults.models` 限制,请确保覆盖的模型包含在其中。
如果你设置`agents.defaults.models`,请确保覆盖的模型包含在其中。
```bash
curl -X POST http://127.0.0.1:18789/hooks/gmail \
@@ -157,7 +157,7 @@ curl -X POST http://127.0.0.1:18789/hooks/gmail \
## 安全
- 将 hook 端点保持在 loopback、tailnet 或受信任的反向代理之后。
- 使用专用的 hook 令牌;不要复用 Gateway 网关认证令牌。
- 将 hook 端点限制在 local loopback、tailnet 或受信任的反向代理之后。
- 使用专用的 hook 令牌;不要复用 Gateway网关认证令牌。
- 避免在 webhook 日志中包含敏感的原始请求体。
- Hook 请求体默认被视为不受信任并使用安全边界包装。如果你必须为特定 hook 禁用此功能,请在该 hook 的映射中设置 `allowUnsafeExternalContent: true`(危险)。
- Hook 请求体默认被视为不受信任的,并使用安全边界进行包装。如果你必须为特定 hook 禁用此功能,请在该 hook 的映射中设置 `allowUnsafeExternalContent: true`(危险)。

View File

@@ -1,23 +1,23 @@
---
read_when:
- 你想在 OpenClaw 中使用 Amazon Bedrock 模型
- 你需要为模型调用置 AWS 凭证/区域
- 你需要为模型调用置 AWS 凭证/区域
summary: 在 OpenClaw 中使用 Amazon BedrockConverse API模型
title: Amazon Bedrock
x-i18n:
generated_at: "2026-02-03T10:04:01Z"
generated_at: "2026-02-01T19:39:40Z"
model: claude-opus-4-5
provider: pi
source_hash: 318f1048451a1910b70522e2f7f9dfc87084de26d9e3938a29d372eed32244a8
source_path: bedrock.md
workflow: 15
workflow: 14
---
# Amazon Bedrock
OpenClaw 可以通过 piai 的 **Bedrock Converse** 流式提供商使用 **Amazon Bedrock** 模型。Bedrock 认证使用 **AWS SDK 默认凭证链**,而非 API 密钥。
## piai 支持的功能
## piai 支持的内容
- 提供商:`amazon-bedrock`
- API`bedrock-converse-stream`
@@ -26,7 +26,7 @@ OpenClaw 可以通过 piai 的 **Bedrock Converse** 流式提供商使用 **A
## 自动模型发现
如果检测到 AWS 凭证OpenClaw 可以自动发现支持**流式传输**和**文本输出**的 Bedrock 模型。发现功能使用 `bedrock:ListFoundationModels`,并会被缓存默认1 小时)。
如果检测到 AWS 凭证OpenClaw 可以自动发现支持**流式传输**和**文本输出**的 Bedrock 模型。发现功能使用 `bedrock:ListFoundationModels`,并带有缓存默认1 小时)。
配置选项位于 `models.bedrockDiscovery` 下:
@@ -45,17 +45,17 @@ OpenClaw 可以通过 piai 的 **Bedrock Converse** 流式提供商使用 **A
}
```
注意事项
说明
- `enabled` 在存在 AWS 凭证时默认为 `true`
- 当 AWS 凭证存在时,`enabled` 默认为 `true`
- `region` 默认为 `AWS_REGION``AWS_DEFAULT_REGION`,然后是 `us-east-1`
- `providerFilter` 匹配 Bedrock 提供商名称(例如 `anthropic`)。
- `refreshInterval` 单位为秒;设置为 `0` 可禁用缓存。
- `defaultContextWindow`(默认:`32000`)和 `defaultMaxTokens`(默认:`4096`)用于发现的模型(如果你知道模型限制可以覆盖这些值)。
- `defaultContextWindow`(默认:`32000`)和 `defaultMaxTokens`(默认:`4096`)用于发现的模型(如果你了解模型限制可以覆盖)。
## 设置(手动)
1. 确保 AWS 凭证在 **Gateway 网关主机**上可用:
1. 确保 AWS 凭证在 **Gateway网关主机**上可用:
```bash
export AWS_ACCESS_KEY_ID="AKIA..."
@@ -102,9 +102,9 @@ export AWS_BEARER_TOKEN_BEDROCK="..."
## EC2 实例角色
在附加了 IAM 角色的 EC2 实例上运行 OpenClaw 时AWS SDK 会自动使用实例元数据服务IMDS进行认证。但是OpenClaw 的凭证检测目前检查环境变量,不检查 IMDS 凭证。
在附加了 IAM 角色的 EC2 实例上运行 OpenClaw 时AWS SDK 会自动使用实例元数据服务IMDS进行认证。但是OpenClaw 的凭证检测目前检查环境变量,不检查 IMDS 凭证。
**解决方法:** 设置 `AWS_PROFILE=default` 以表明 AWS 凭证可用。实际认证仍通过 IMDS 使用实例角色。
**解决方法:** 设置 `AWS_PROFILE=default` 以表明 AWS 凭证可用。实际认证仍通过 IMDS 使用实例角色。
```bash
# 添加到 ~/.bashrc 或你的 shell 配置文件
@@ -118,7 +118,7 @@ EC2 实例角色**所需的 IAM 权限**
- `bedrock:InvokeModelWithResponseStream`
- `bedrock:ListFoundationModels`(用于自动发现)
附加托管策略 `AmazonBedrockFullAccess`
或附加托管策略 `AmazonBedrockFullAccess`
**快速设置:**
@@ -147,11 +147,11 @@ aws ec2 associate-iam-instance-profile \
--instance-id i-xxxxx \
--iam-instance-profile Name=EC2-Bedrock-Access
# 3. 在 EC2 实例上启用发现功能
# 3. 在 EC2 实例上启用发现
openclaw config set models.bedrockDiscovery.enabled true
openclaw config set models.bedrockDiscovery.region us-east-1
# 4. 设置解决方法所需的环境变量
# 4. 设置解决方法的环境变量
echo 'export AWS_PROFILE=default' >> ~/.bashrc
echo 'export AWS_REGION=us-east-1' >> ~/.bashrc
source ~/.bashrc
@@ -160,11 +160,11 @@ source ~/.bashrc
openclaw models list
```
## 注意事项
## 说明
- Bedrock 需要在你的 AWS 账户/区域中启用**模型访问**。
- 自动发现需要 `bedrock:ListFoundationModels` 权限。
- 如果你使用配置文件,请在 Gateway 网关主机上设置 `AWS_PROFILE`
- OpenClaw 按以下顺序获取凭证来源:`AWS_BEARER_TOKEN_BEDROCK`,然后 `AWS_ACCESS_KEY_ID` + `AWS_SECRET_ACCESS_KEY`,然后 `AWS_PROFILE`,最后是默认的 AWS SDK 链。
- 如果你使用配置文件,请在 Gateway网关主机上设置 `AWS_PROFILE`
- OpenClaw 按以下顺序检测凭证来源:`AWS_BEARER_TOKEN_BEDROCK`,然后 `AWS_ACCESS_KEY_ID` + `AWS_SECRET_ACCESS_KEY`,然后 `AWS_PROFILE`,最后是默认的 AWS SDK 链。
- 推理支持取决于模型;请查看 Bedrock 模型卡了解当前功能。
- 如果你更喜欢托管密钥流程,也可以在 Bedrock 前面放置一个 OpenAI 兼容的代理,将其配置为 OpenAI 提供商。
- 如果你偏好托管密钥流程,也可以在 Bedrock 前面放置一个兼容 OpenAI 的代理,将其配置为 OpenAI 提供商。

View File

@@ -2,15 +2,15 @@
read_when:
- 你想使用 Brave Search 进行 web_search
- 你需要 BRAVE_API_KEY 或套餐详情
summary: 用于 web_search Brave Search API 设置
summary: web_search 设置 Brave Search API
title: Brave Search
x-i18n:
generated_at: "2026-02-03T07:43:09Z"
generated_at: "2026-02-01T19:39:45Z"
model: claude-opus-4-5
provider: pi
source_hash: cdcb037b092b8a10609f02acf062b4164cb826ac22bdb3fb2909c842a1405341
source_path: brave-search.md
workflow: 15
workflow: 14
---
# Brave Search API
@@ -19,9 +19,9 @@ OpenClaw 使用 Brave Search 作为 `web_search` 的默认提供商。
## 获取 API 密钥
1. 在 https://brave.com/search/api/ 创建 Brave Search API 账户
1. 在 https://brave.com/search/api/ 创建 Brave Search API 账户
2. 在控制面板中,选择 **Data for Search** 套餐并生成 API 密钥。
3. 将密钥存储在配置中(推荐)或在 Gateway 网关环境中设置 `BRAVE_API_KEY`
3. 将密钥存储在配置中(推荐)或在 Gateway网关环境中设置 `BRAVE_API_KEY`
## 配置示例
@@ -40,9 +40,9 @@ OpenClaw 使用 Brave Search 作为 `web_search` 的默认提供商。
}
```
## 注意事项
## 说明
- Data for AI 套餐与 `web_search` **不**兼容。
- Brave 提供免费层级和付费套餐;请查看 Brave API 门户了解当前限制。
- Brave 提供免费套餐和付费套餐;请查看 Brave API 门户了解当前限制。
请参阅 [Web 工具](/tools/web) 了解完整的 web_search 配置
完整的 web_search 配置请参阅 [Web 工具](/tools/web)。

View File

@@ -3,29 +3,29 @@ read_when:
- 配置广播群组
- 调试 WhatsApp 中的多智能体回复
status: experimental
summary: 向多个智能体广播 WhatsApp 消息
summary: WhatsApp 消息广播给多个智能体
title: 广播群组
x-i18n:
generated_at: "2026-02-03T07:43:43Z"
generated_at: "2026-02-01T19:40:25Z"
model: claude-opus-4-5
provider: pi
source_hash: eaeb4035912c49413e012177cf0bd28b348130d30d3317674418dca728229b70
source_path: broadcast-groups.md
workflow: 15
workflow: 14
---
# 广播群组
**状态:** 实验性功能
**版本:** 2026.1.9 版本新增
**状态:** 实验性
**版本:** 2026.1.9 中添加
## 概述
广播群组允许多个智能体同时处理并响应同一条消息。这使你能够在单个 WhatsApp 群组或私信中创建协同工作的专业智能体团队——全部使用同一个手机号码。
广播群组允许多个智能体同时处理和回复同一条消息。这使你可以创建在单个 WhatsApp 群组或私聊中协同工作的专业智能体团队——全部使用同一个电话号码。
当前范围:**仅限 WhatsApp**web 渠道)。
当前范围:**仅限 WhatsApp**Web 渠道)。
广播群组在渠道白名单和群组激活规则之后进行评估。在 WhatsApp 群组中,这意味着广播在 OpenClaw 正常回复时发生(例如:被提及时,具体取决于你的群组设置)。
广播群组在渠道允许列表和群组激活规则之后进行评估。在 WhatsApp 群组中,这意味着广播发生在 OpenClaw 正常回复的时机(例如:被提及时,取决于你的群组设置)。
## 使用场景
@@ -34,53 +34,53 @@ x-i18n:
部署多个具有原子化、专注职责的智能体:
```
Group: "Development Team"
Agents:
- CodeReviewer (reviews code snippets)
- DocumentationBot (generates docs)
- SecurityAuditor (checks for vulnerabilities)
- TestGenerator (suggests test cases)
群组:"Development Team"
智能体:
- CodeReviewer(审查代码片段)
- DocumentationBot(生成文档)
- SecurityAuditor(检查漏洞)
- TestGenerator(建议测试用例)
```
每个智能体处理相同的消息并提供其专业视角。
每个智能体处理同一条消息并提供其专业视角。
### 2. 多语言支持
```
Group: "International Support"
Agents:
- Agent_EN (responds in English)
- Agent_DE (responds in German)
- Agent_ES (responds in Spanish)
群组:"International Support"
智能体:
- Agent_EN(用英语回复)
- Agent_DE(用德语回复)
- Agent_ES(用西班牙语回复)
```
### 3. 质量保证工作流
```
Group: "Customer Support"
Agents:
- SupportAgent (provides answer)
- QAAgent (reviews quality, only responds if issues found)
群组:"Customer Support"
智能体:
- SupportAgent(提供回答)
- QAAgent(审查质量,仅在发现问题时回复)
```
### 4. 任务自动化
```
Group: "Project Management"
Agents:
- TaskTracker (updates task database)
- TimeLogger (logs time spent)
- ReportGenerator (creates summaries)
群组:"Project Management"
智能体:
- TaskTracker(更新任务数据库)
- TimeLogger(记录时间消耗)
- ReportGenerator(创建摘要)
```
## 配置
### 基本设置
添加一个顶层 `broadcast` 部分(与 `bindings` 同级)。键为 WhatsApp peer id
添加顶层 `broadcast` 部分(与 `bindings` 同级)。键为 WhatsApp peer ID
- 群聊:群组 JID例如 `120363403215116621@g.us`
-E.164 格式电话号码(例如 `+15551234567`
-E.164 格式电话号码(例如 `+15551234567`
```json
{
@@ -90,7 +90,7 @@ Agents:
}
```
**果:** 当 OpenClaw 在此聊天中回复时,运行所有三个智能体。
**果:** 当 OpenClaw 在此聊天中回复时,它会运行所有三个智能体。
### 处理策略
@@ -111,7 +111,7 @@ Agents:
#### 顺序
智能体按顺序处理(后一个等待前一个完成):
智能体按顺序处理(个等待前一个完成):
```json
{
@@ -161,62 +161,62 @@ Agents:
### 消息流程
1. **收消息** 到达 WhatsApp 群组
1. **收消息**,来自 WhatsApp 群组
2. **广播检查**:系统检查 peer ID 是否在 `broadcast`
3. **如果在广播列表中**
- 所有列出的智能体处理该消息
- 每个智能体有自己的会话键和隔离的上下文
- 智能体并行处理(默认)或顺序处理
- 智能体并行(默认)或顺序处理
4. **如果不在广播列表中**
- 应用正常路由(第一个匹配的绑定)
注意:广播群组不会绕过渠道白名单或群组激活规则(提及/命令等)。它们只改变消息符合处理条件时*运行哪些智能体*。
注意:广播群组不会绕过渠道允许列表或群组激活规则(提及/命令等)。它们仅在消息符合处理条件时改变*哪些智能体运行*。
### 会话隔离
广播群组中的每个智能体完全独立维护
广播群组中的每个智能体维护完全独立
- **会话键**`agent:alfred:whatsapp:group:120363...` vs `agent:baerbel:whatsapp:group:120363...`
- **会话键**`agent:alfred:whatsapp:group:120363...` `agent:baerbel:whatsapp:group:120363...`
- **对话历史**(智能体看不到其他智能体的消息)
- **工作空间**(如果配置了则使用独立沙箱)
- **工具访问权限**(不同的允许/拒绝列表)
- **工作**(如果配置了则独立沙箱)
- **工具访问**(不同的允许/拒绝列表)
- **记忆/上下文**(独立的 IDENTITY.md、SOUL.md 等)
- **群组上下文缓冲区**(用于上下文的最近群组消息)按 peer 共享,因此所有广播智能体在触发时看到相同的上下文
- **群组上下文缓冲区**(用于上下文的最近群组消息)按 peer 共享,因此所有广播智能体在触发时看到相同的上下文
允许每个智能体拥有:
使得每个智能体可以拥有:
- 不同的个性
- 不同的工具访问权限(例如只读 vs 读写)
- 不同的模型(例如 opus vs sonnet
- 不同的工具访问权限(例如只读读写)
- 不同的模型(例如 opus sonnet
- 不同的已安装 Skills
### 示例:隔离会话
### 示例:隔离会话
在群组 `120363403215116621@g.us` 中,智能体为 `["alfred", "baerbel"]`
**Alfred 的上下文:**
```
Session: agent:alfred:whatsapp:group:120363403215116621@g.us
History: [user message, alfred's previous responses]
Workspace: /Users/pascal/openclaw-alfred/
Tools: read, write, exec
会话:agent:alfred:whatsapp:group:120363403215116621@g.us
历史:[用户消息alfred 之前的回复]
工作区:/Users/pascal/openclaw-alfred/
工具:readwriteexec
```
**Bärbel 的上下文:**
```
Session: agent:baerbel:whatsapp:group:120363403215116621@g.us
History: [user message, baerbel's previous responses]
Workspace: /Users/pascal/openclaw-baerbel/
Tools: read only
会话:agent:baerbel:whatsapp:group:120363403215116621@g.us
历史:[用户消息baerbel 之前的回复]
工作区:/Users/pascal/openclaw-baerbel/
工具:仅 read
```
## 最佳实践
### 1. 保持智能体专注
每个智能体设计为具有单一、明确的职责:
每个智能体设计单一、明确的职责:
```json
{
@@ -226,12 +226,12 @@ Tools: read only
}
```
**好的做法:** 每个智能体只有一个任务
**不好的做法:** 一个通用的"dev-helper"智能体
**好的做法:** 每个智能体只有一项工作
**不好的做法:** 一个通用的 "dev-helper" 智能体
### 2. 使用描述性名称
明确每个智能体的功能:
每个智能体的功能一目了然
```json
{
@@ -245,16 +245,16 @@ Tools: read only
### 3. 配置不同的工具访问权限
只给智能体提供它们需要的工具:
只给智能体它们需要的工具:
```json
{
"agents": {
"reviewer": {
"tools": { "allow": ["read", "exec"] } // Read-only
"tools": { "allow": ["read", "exec"] } // 只读
},
"fixer": {
"tools": { "allow": ["read", "write", "edit", "exec"] } // Read-write
"tools": { "allow": ["read", "write", "edit", "exec"] } // 读写
}
}
}
@@ -262,19 +262,19 @@ Tools: read only
### 4. 监控性能
有多个智能体时,请考虑:
当智能体数量较多时,请考虑:
- 使用 `"strategy": "parallel"`(默认)以提高速度
- 将广播群组限制在 5-10 个智能体
- 为较简单的智能体使用快的模型
- 为较简单的智能体使用快的模型
### 5. 优雅处理失败
### 5. 优雅处理失败
智能体独立失败。一个智能体的错误不会阻塞其他智能体:
```
Message → [Agent A ✓, Agent B ✗ error, Agent C ✓]
Result: Agent A and C respond, Agent B logs error
消息 → [智能体 A ✓, 智能体 B ✗ 错误, 智能体 C ✓]
结果:智能体 A 和 C 回复,智能体 B 记录错误
```
## 兼容性
@@ -290,7 +290,7 @@ Result: Agent A and C respond, Agent B logs error
### 路由
广播群组与现有路由一起工作:
广播群组与现有路由并行工作:
```json
{
@@ -306,14 +306,14 @@ Result: Agent A and C respond, Agent B logs error
}
```
- `GROUP_A`只有 alfred 响应(正常路由)
- `GROUP_B`agent1 和 agent2 都响应(广播)
- `GROUP_A` alfred 回复(正常路由)
- `GROUP_B`agent1 和 agent2 都回复(广播)
**优先级:** `broadcast` 优先于 `bindings`
## 故障排除
### 智能体不响应
### 智能体没有回复
**检查:**
@@ -327,18 +327,18 @@ Result: Agent A and C respond, Agent B logs error
tail -f ~/.openclaw/logs/gateway.log | grep broadcast
```
### 只有一个智能体响应
### 一个智能体回复
**原因:** Peer ID 可能在 `bindings` 中但不在 `broadcast` 中。
**修复:** 添加到广播配置或从绑定中移除。
**修复:** 添加到广播配置或从 bindings 中移除。
### 性能问题
**如果智能体较多时速度慢:**
**如果智能体较多时速度慢:**
- 减少每个群组的智能体数量
- 使用较轻的模型sonnet 而非 opus
- 使用更轻量的模型sonnet 而非 opus
- 检查沙箱启动时间
## 示例
@@ -380,9 +380,9 @@ tail -f ~/.openclaw/logs/gateway.log | grep broadcast
```
**用户发送:** 代码片段
**响应**
**回复**
- code-formatter"修复缩进并添加了类型提示"
- code-formatter"修复缩进并添加了类型提示"
- security-scanner"⚠️ 第 12 行存在 SQL 注入漏洞"
- test-coverage"覆盖率为 45%,缺少错误情况的测试"
- docs-checker"函数 `process_data` 缺少文档字符串"
@@ -420,7 +420,7 @@ interface OpenClawConfig {
### 字段
- `strategy`(可选):如何处理智能体
- `strategy`(可选):智能体的处理方式
- `"parallel"`(默认):所有智能体同时处理
- `"sequential"`:智能体按数组顺序处理
- `[peerId]`WhatsApp 群组 JID、E.164 号码或其他 peer ID
@@ -428,19 +428,19 @@ interface OpenClawConfig {
## 限制
1. **最大智能体数:** 无硬性限制,但 10 个以上智能体可能会
2. **共享上下文:** 智能体看不到彼此的响应(设计如此)
3. **消息序:** 并行响应可能以任意顺序到达
4. **速率限制:** 所有智能体计入 WhatsApp 速率限制
1. **最大智能体数:** 无硬性限制,但 10 个以上可能会
2. **共享上下文:** 智能体看不到彼此的回复(设计如此)
3. **消息序:** 并行回复可能以任意顺序到达
4. **速率限制:** 所有智能体共同计入 WhatsApp 速率限制
## 未来增强
计划中的功能:
- [ ] 共享上下文模式(智能体可以看到彼此的响应
- [ ] 智能体协调(智能体可以相互发信号
- [ ] 共享上下文模式(智能体可以看到彼此的回复
- [ ] 智能体协调(智能体可以互相通信
- [ ] 动态智能体选择(根据消息内容选择智能体)
- [ ] 智能体优先级(某些智能体先于其他智能体响应
- [ ] 智能体优先级(某些智能体先于其他智能体回复
## 另请参阅

View File

@@ -3,36 +3,36 @@ read_when:
- 设置 BlueBubbles 渠道
- 排查 webhook 配对问题
- 在 macOS 上配置 iMessage
summary: 通过 BlueBubbles macOS 服务器使用 iMessageREST 发送/接收、输入状态、回应、配对、高级操作)。
summary: 通过 BlueBubbles macOS 服务器集成 iMessageREST 发送/接收、输入状态、回应、配对、高级操作)。
title: BlueBubbles
x-i18n:
generated_at: "2026-02-03T10:04:52Z"
generated_at: "2026-02-01T19:41:18Z"
model: claude-opus-4-5
provider: pi
source_hash: 3aae277a8bec479800a7f6268bfbca912c65a4aadc6e513694057fb873597b69
source_hash: ac9a9d71f3bbc661da6cb2897ea32d290bbd16b35925250601cfff53bc85de8c
source_path: channels/bluebubbles.md
workflow: 15
workflow: 14
---
# BlueBubblesmacOS REST
状态:内置插件,通过 HTTP 与 BlueBubbles macOS 服务器通信。由于其更丰富的 API 和更简便的设置,**推荐用于 iMessage 集成**优于旧版 imsg 渠道。
状态:内置插件,通过 HTTP 与 BlueBubbles macOS 服务器通信。**推荐用于 iMessage 集成**因为相比旧版 imsg 渠道,其 API 更丰富且更易于设置
## 概述
- 通过 BlueBubbles 辅助应用在 macOS 上运行([bluebubbles.app](https://bluebubbles.app))。
- 推荐/已测试版本macOS Sequoia (15)。macOS Tahoe (26) 可用;在 Tahoe 上编辑功能目前不可用,群组图标更新可能显示成功但实际未同步。
- 推荐/已测试macOS Sequoia (15)。macOS Tahoe (26) 可用;编辑功能目前在 Tahoe 上不可用,群组图标更新可能报告成功但不会同步。
- OpenClaw 通过其 REST API 与之通信(`GET /api/v1/ping``POST /message/text``POST /chat/:id/*`)。
- 传入消息通过 webhook 到达;发出的回复、输入指示器、已读回执和 tapback 均为 REST 调用。
- 附件和贴纸作为入站媒体被接收(在可能呈现给智能体)。
- 配对/白名单的工作方式与其他渠道相同(`/start/pairing` 等),使用 `channels.bluebubbles.allowFrom` + 配对码。
- 回应作为系统事件呈现,与 Slack/Telegram 类似,智能体可以在回复前"提及"它们。
- 高级功能:编辑、撤回、回复线程、消息效、群组管理。
- 收到的消息通过 webhooks 到达;发出的回复、输入指示器、已读回执和 tapback 回应均为 REST 调用。
- 附件和贴纸作为入站媒体被接收(在可能的情况下呈现给智能体)。
- 配对/允许列表与其他渠道的工作方式相同(`/start/pairing` 等),使用 `channels.bluebubbles.allowFrom` + 配对码。
- 回应作为系统事件呈现,与 Slack/Telegram 相同,因此智能体可以在回复前"提及"它们。
- 高级功能:编辑、撤回、回复线程、消息效、群组管理。
## 快速开始
1. 在你的 Mac 上安装 BlueBubbles 服务器(按照 [bluebubbles.app/install](https://bluebubbles.app/install) 的说明操作)。
2. 在 BlueBubbles 配置中,启用 web API 并设置密码。
2. 在 BlueBubbles 配置中,启用 Web API 并设置密码。
3. 运行 `openclaw onboard` 并选择 BlueBubbles或手动配置
```json5
{
@@ -46,8 +46,8 @@ x-i18n:
},
}
```
4. 将 BlueBubbles webhook 指向你的 Gateway 网关(示例:`https://your-gateway-host:3000/bluebubbles-webhook?password=<password>`)。
5. 启动 Gateway 网关;它将注册 webhook 处理程序并开始配对。
4. 将 BlueBubbles webhooks 指向你的 Gateway网关示例`https://your-gateway-host:3000/bluebubbles-webhook?password=<password>`)。
5. 启动 Gateway网关它将注册 webhook 处理并开始配对。
## 新手引导
@@ -62,8 +62,8 @@ openclaw onboard
- **服务器 URL**必填BlueBubbles 服务器地址(例如 `http://192.168.1.100:1234`
- **密码**(必填):来自 BlueBubbles 服务器设置的 API 密码
- **Webhook 路径**(可选):默认为 `/bluebubbles-webhook`
- **私策略**:配对、白名单、开放或禁用
- **白名单**:电话号码、电子邮件或聊天目标
- **私策略**:配对、允许列表、开放或禁用
- **允许列表**:电话号码、邮箱或聊天目标
你也可以通过 CLI 添加 BlueBubbles
@@ -71,13 +71,13 @@ openclaw onboard
openclaw channels add bluebubbles --http-url http://192.168.1.100:1234 --password <password>
```
## 访问控制(私 + 群组)
## 访问控制(私 + 群组)
- 默认:`channels.bluebubbles.dmPolicy = "pairing"`。
- 未知发送者会收到配对码;在批准之前消息会被忽略(配对码 1 小时后过期)。
- 批准方式
- 未知发送者会收到配对码;消息在批准会被忽略(配对码 1 小时后过期)。
- 通过以下方式批准:
- `openclaw pairing list bluebubbles`
- `openclaw pairing approve bluebubbles <CODE>`
- 配对是默认的令牌交换方式。详情:[配对](/start/pairing)
@@ -92,10 +92,10 @@ openclaw channels add bluebubbles --http-url http://192.168.1.100:1234 --passwor
BlueBubbles 支持群聊的提及门控,与 iMessage/WhatsApp 行为一致:
- 使用 `agents.list[].groupChat.mentionPatterns`(或 `messages.groupChat.mentionPatterns`)检测提及。
- 当群组启用 `requireMention` 时,智能体仅在被提及时响应
- 当群组启用 `requireMention` 时,智能体仅在被提及时回复
- 来自授权发送者的控制命令会绕过提及门控。
群组配置:
群组配置:
```json5
{
@@ -104,8 +104,8 @@ BlueBubbles 支持群聊的提及门控,与 iMessage/WhatsApp 行为一致:
groupPolicy: "allowlist",
groupAllowFrom: ["+15555550123"],
groups: {
"*": { requireMention: true }, // 所有群组的默认设置
"iMessage;-;chat123": { requireMention: false }, // 特定群组的覆盖设置
"*": { requireMention: true }, // 所有群组的默认
"iMessage;-;chat123": { requireMention: false }, // 针对特定群组的覆盖
},
},
},
@@ -115,12 +115,12 @@ BlueBubbles 支持群聊的提及门控,与 iMessage/WhatsApp 行为一致:
### 命令门控
- 控制命令(例如 `/config`、`/model`)需要授权。
- 使用 `allowFrom` 和 `groupAllowFrom` 确定命令授权。
- 授权发送者即使在群组中未提及也可以运行控制命令。
- 使用 `allowFrom` 和 `groupAllowFrom` 确定命令授权。
- 授权发送者即使在群组中未提及也可以运行控制命令。
## 输入状态 + 已读回执
- **输入指示器**:在响应生成前和生成期间自动发送。
- **输入指示器**:在生成回复前和生成过程中自动发送。
- **已读回执**:由 `channels.bluebubbles.sendReadReceipts` 控制(默认:`true`)。
- **输入指示器**OpenClaw 发送输入开始事件BlueBubbles 在发送或超时时自动清除输入状态(通过 DELETE 手动停止不可靠)。
@@ -136,21 +136,21 @@ BlueBubbles 支持群聊的提及门控,与 iMessage/WhatsApp 行为一致:
## 高级操作
BlueBubbles 在配置中启用时支持高级消息操作:
在配置中启用后,BlueBubbles 支持高级消息操作:
```json5
{
channels: {
bluebubbles: {
actions: {
reactions: true, // tapback默认true
edit: true, // 编辑已发送消息macOS 13+macOS 26 Tahoe 上不可用)
reactions: true, // tapback 回应默认true
edit: true, // 编辑已发送消息macOS 13+macOS 26 Tahoe 上不可用)
unsend: true, // 撤回消息macOS 13+
reply: true, // 通过消息 GUID 进行回复线程
sendWithEffect: true, // 消息效slam、loud 等)
reply: true, // 消息 GUID 回复线程
sendWithEffect: true, // 消息slam、loud 等)
renameGroup: true, // 重命名群聊
setGroupIcon: true, // 设置群聊图标/照片(在 macOS 26 Tahoe 上不稳定)
addParticipant: true, // 将参与者添加到群组
setGroupIcon: true, // 设置群聊图标/头像(macOS 26 Tahoe 上不稳定)
addParticipant: true, // 向群组添加参与者
removeParticipant: true, // 从群组移除参与者
leaveGroup: true, // 离开群聊
sendAttachment: true, // 发送附件/媒体
@@ -166,40 +166,40 @@ BlueBubbles 在配置中启用时支持高级消息操作:
- **edit**:编辑已发送的消息(`messageId`、`text`
- **unsend**:撤回消息(`messageId`
- **reply**:回复特定消息(`messageId`、`text`、`to`
- **sendWithEffect** iMessage 效发送(`text`、`to`、`effectId`
- **sendWithEffect**使用 iMessage 效发送(`text`、`to`、`effectId`
- **renameGroup**:重命名群聊(`chatGuid`、`displayName`
- **setGroupIcon**:设置群聊图标/照片`chatGuid`、`media`)— 在 macOS 26 Tahoe 上不稳定API 可能返回成功但图标同步)。
- **addParticipant**将某人添加到群组`chatGuid`、`address`
- **removeParticipant**将某人从群组移除(`chatGuid`、`address`
- **setGroupIcon**:设置群聊图标/头像`chatGuid`、`media`)—在 macOS 26 Tahoe 上不稳定API 可能返回成功但图标不会同步)。
- **addParticipant**向群组添加成员`chatGuid`、`address`
- **removeParticipant**:从群组移除成员`chatGuid`、`address`
- **leaveGroup**:离开群聊(`chatGuid`
- **sendAttachment**:发送媒体/文件(`to`、`buffer`、`filename`、`asVoice`
- 语音备忘录: `asVoice: true` **MP3** 或 **CAF** 音频一起设置,以 iMessage 语音消息形式发送。BlueBubbles 在发送语音备忘录时会将 MP3 转换为 CAF。
- 语音备忘录:设置 `asVoice: true` 并使用 **MP3** 或 **CAF** 音频以 iMessage 语音消息形式发送。BlueBubbles 在发送语音备忘录时会将 MP3 转换为 CAF。
### 消息 ID短格式 vs 完整格式)
### 消息 ID短格式完整格式)
OpenClaw 可能会显示*短*消息 ID例如 `1`、`2`)以节省 token。
OpenClaw 可能会呈现*短*消息 ID例如 `1`、`2`)以节省 token。
- `MessageSid` / `ReplyToId` 可以是短 ID。
- `MessageSidFull` / `ReplyToIdFull` 包含提供商的完整 ID。
- 短 ID 存储在内存中;它们可能在重启或缓存清除后过期。
- 操作接受短或完整的 `messageId`,但如果短 ID 不再可用会报错。
- 操作接受短格式或完整格式的 `messageId`,但如果短 ID 不再可用会报错。
对于持久化自动化和存储,请使用完整 ID
- 模板:`{{MessageSidFull}}`、`{{ReplyToIdFull}}`
- 上下文:入站负载中的 `MessageSidFull` / `ReplyToIdFull`
参见[配置](/gateway/configuration)了解模板变量
模板变量请参阅[配置](/gateway/configuration)。
## 分块流式传输
控制响应是作为单条消息发送还是分块流式传输:
控制回复是作为单条消息发送还是分块流式传输:
```json5
{
channels: {
bluebubbles: {
blockStreaming: true, // 启用分块流式传输(默认关闭
blockStreaming: true, // 启用分块流式传输(默认行为
},
},
}
@@ -209,7 +209,7 @@ OpenClaw 可能会显示*短*消息 ID例如 `1`、`2`)以节省 token。
- 入站附件会被下载并存储在媒体缓存中。
- 媒体上限通过 `channels.bluebubbles.mediaMaxMb` 设置默认8 MB
- 出站文本按 `channels.bluebubbles.textChunkLimit` 分块默认4000 字符)。
- 出站文本按 `channels.bluebubbles.textChunkLimit` 进行分块默认4000 字符)。
## 配置参考
@@ -222,17 +222,17 @@ OpenClaw 可能会显示*短*消息 ID例如 `1`、`2`)以节省 token。
- `channels.bluebubbles.password`API 密码。
- `channels.bluebubbles.webhookPath`Webhook 端点路径(默认:`/bluebubbles-webhook`)。
- `channels.bluebubbles.dmPolicy``pairing | allowlist | open | disabled`(默认:`pairing`)。
- `channels.bluebubbles.allowFrom`:私信白名单(句柄、电子邮件、E.164 号码、`chat_id:*`、`chat_guid:*`)。
- `channels.bluebubbles.allowFrom`:私聊允许列表(句柄、邮箱、E.164 号码、`chat_id:*`、`chat_guid:*`)。
- `channels.bluebubbles.groupPolicy``open | allowlist | disabled`(默认:`allowlist`)。
- `channels.bluebubbles.groupAllowFrom`:群组发送者白名单
- `channels.bluebubbles.groups`群组配置(`requireMention` 等)。
- `channels.bluebubbles.groupAllowFrom`:群组发送者允许列表
- `channels.bluebubbles.groups`群组配置(`requireMention` 等)。
- `channels.bluebubbles.sendReadReceipts`:发送已读回执(默认:`true`)。
- `channels.bluebubbles.blockStreaming`:启用分块流式传输(默认:`false`;流式回复必需)。
- `channels.bluebubbles.textChunkLimit`:出站分块大小(字符默认4000
- `channels.bluebubbles.chunkMode``length`(默认)仅在超过 `textChunkLimit` 时分割;`newline` 在长度分块前先按空行(段落边界)分割。
- `channels.bluebubbles.mediaMaxMb`入站媒体上限MB默认8
- `channels.bluebubbles.historyLimit`上下文的最大群组消息数0 表示禁用)。
- `channels.bluebubbles.dmHistoryLimit`:私历史限制。
- `channels.bluebubbles.blockStreaming`:启用分块流式传输(默认:`true`)。
- `channels.bluebubbles.textChunkLimit`:出站分块大小(字符数,默认4000
- `channels.bluebubbles.chunkMode``length`(默认)仅在超过 `textChunkLimit` 时分割;`newline` 在空行(段落边界)分割,然后再进行长度分块
- `channels.bluebubbles.mediaMaxMb`入站媒体上限MB默认8
- `channels.bluebubbles.historyLimit`用于上下文的最大群组消息数0 表示禁用)。
- `channels.bluebubbles.dmHistoryLimit`:私历史限制。
- `channels.bluebubbles.actions`:启用/禁用特定操作。
- `channels.bluebubbles.accounts`:多账户配置。
@@ -241,31 +241,31 @@ OpenClaw 可能会显示*短*消息 ID例如 `1`、`2`)以节省 token。
- `agents.list[].groupChat.mentionPatterns`(或 `messages.groupChat.mentionPatterns`)。
- `messages.responsePrefix`。
## 地址 / 投递目标
## 寻址/投递目标
优先使用 `chat_guid` 以获得稳定路由:
推荐使用 `chat_guid` 以实现稳定路由:
- `chat_guid:iMessage;-;+15555550123`(群组推荐)
- `chat_guid:iMessage;-;+15555550123`(群组推荐使用
- `chat_id:123`
- `chat_identifier:...`
- 直接句柄:`+15555550123`、`user@example.com`
- 如果直接句柄没有现有的私信聊天OpenClaw 将通过 `POST /api/v1/chat/new` 创建一个。这需要启用 BlueBubbles Private API。
- 如果直接句柄没有现有的私聊会话OpenClaw 将通过 `POST /api/v1/chat/new` 创建一个。这需要启用 BlueBubbles Private API。
## 安全
## 安全
- Webhook 请求通过比较 `guid`/`password` 查询参数或头与 `channels.bluebubbles.password` 进行身份验证。来自 `localhost` 的请求也会被接受。
- 保持 API 密码和 webhook 端点的机密性(将它们视为凭证)。
- localhost 信任意味着同主机的反向代理可能无意绕过密码验证。如果你使用代理 Gateway 网关,请在代理要求身份验证并配置 `gateway.trustedProxies`。参见 [Gateway 网关安全](/gateway/security#reverse-proxy-configuration)。
- 如果将 BlueBubbles 服务器暴露局域网外,请启用 HTTPS + 防火墙规则。
- Webhook 请求通过 `guid`/`password` 查询参数或请求头与 `channels.bluebubbles.password` 比较来进行认证。来自 `localhost` 的请求也会被接受。
- 请保密 API 密码和 webhook 端点(将其视为凭证)。
- localhost 信任意味着同主机的反向代理可能无意绕过密码。如果你 Gateway网关设置了代理,请在代理要求证并配置 `gateway.trustedProxies`。参见 [Gateway网关安全](/gateway/security#reverse-proxy-configuration)。
- 如果将 BlueBubbles 服务器暴露局域网外,请启用 HTTPS + 防火墙规则。
## 故障排除
- 如果输入/已读事件停止工作,请检查 BlueBubbles webhook 日志并验证 Gateway 网关路径是否与 `channels.bluebubbles.webhookPath` 匹配。
- 如果输入/已读事件停止工作,请检查 BlueBubbles webhook 日志并验证 Gateway网关路径是否与 `channels.bluebubbles.webhookPath` 匹配。
- 配对码在一小时后过期;使用 `openclaw pairing list bluebubbles` 和 `openclaw pairing approve bluebubbles <code>`。
- 回应需要 BlueBubbles private API`POST /api/v1/message/react`);确保服务器版本支持它
- 回应功能需要 BlueBubbles private API`POST /api/v1/message/react`确保服务器版本已暴露该接口
- 编辑/撤回需要 macOS 13+ 和兼容的 BlueBubbles 服务器版本。在 macOS 26Tahoe由于 private API 变更,编辑功能目前不可用。
- 在 macOS 26Tahoe群组图标更新可能不稳定API 可能返回成功但新图标同步。
- OpenClaw 会根据 BlueBubbles 服务器的 macOS 版本自动隐藏已知不可用的操作。如果在 macOS 26Tahoe编辑仍然显示,请使用 `channels.bluebubbles.actions.edit=false` 手动禁用。
- 群组图标更新在 macOS 26Tahoe上可能不稳定API 可能返回成功但新图标不会同步。
- OpenClaw 会根据 BlueBubbles 服务器的 macOS 版本自动隐藏已知不可用的操作。如果编辑功能在 macOS 26Tahoe上仍然显示手动通过 `channels.bluebubbles.actions.edit=false` 禁用。
- 查看状态/健康信息:`openclaw status --all` 或 `openclaw status --deep`。
有关通用渠道工作流参考请参阅[渠道](/channels)和[插件](/plugins)指南。
通用渠道工作流参考请参阅[渠道](/channels)和[插件](/plugins)指南。

View File

@@ -1,32 +1,32 @@
---
read_when:
- 开发 Discord 渠道功能
- 开发 Discord 渠道功能
summary: Discord 机器人支持状态、功能和配置
title: Discord
x-i18n:
generated_at: "2026-02-03T07:45:45Z"
generated_at: "2026-02-01T19:19:25Z"
model: claude-opus-4-5
provider: pi
source_hash: 2f0083b55648f9158668b80d078353421e7dc310135fdc43f2d280b242bf8459
source_hash: 44e44e855481a81557d9c205bacaa82efef528f8dba59a2c39c26aeb4f420c62
source_path: channels/discord.md
workflow: 15
workflow: 14
---
# DiscordBot API
状态:已支持通过官方 Discord 机器人网关进行私信和服务器文字频道通信。
状态:已可用于通过官方 Discord 机器人网关进行私信和服务器文字频道通信。
## 快速设置(新手)
1. 创建 Discord 机器人并复制机器人令牌
2. 在 Discord 应用设置中启用 **Message Content Intent**(如果你计划使用允许列表或名称查找,还需启用 **Server Members Intent**)。
3. 为 OpenClaw 设置令牌
1. 创建一个 Discord 机器人并复制机器人 token
2. 在 Discord 应用设置中启用 **Message Content Intent**(如果你计划使用允许列表或名称查找,还需启用 **Server Members Intent**)。
3. 为 OpenClaw 设置 token
- 环境变量:`DISCORD_BOT_TOKEN=...`
- 或配置:`channels.discord.token: "..."`
- 如果两者都设置,配置优先(环境变量回退仅用于默认账户)。
4. 使用消息权限邀请机器人到你的服务器(如果只想使用私信可以创建一个私人服务器)。
5. 启动 Gateway 网关。
6. 私信访问默认采用配对模式;首次联系时批准配对码。
- 如果两者都设置,配置优先(环境变量回退仅用于默认账户)。
4. 邀请机器人到你的服务器并赋予消息权限(如果只想用私信可以创建一个私人服务器)。
5. 启动 Gateway网关。
6. 私信访问默认需要配对;首次联系时批准配对码即可
最小配置:
@@ -44,42 +44,42 @@ x-i18n:
## 目标
- 通过 Discord 私信或服务器频道与 OpenClaw 对话。
- 直接聊天会合并到智能体的主会话(默认 `agent:main:main`);服务器频道保持隔离`agent:<agentId>:discord:channel:<channelId>`(显示名称使用 `discord:<guildSlug>#<channelSlug>`)。
- 群组私信默认被忽略;通过 `channels.discord.dm.groupEnabled` 启用,可选通过 `channels.discord.dm.groupChannels` 进行限制。
- 保持路由确定性:回复始终返回到消息来源的渠道。
- 私聊合并到智能体的主会话(默认 `agent:main:main`);服务器频道`agent:<agentId>:discord:channel:<channelId>` 保持隔离(显示名称使用 `discord:<guildSlug>#<channelSlug>`)。
- 群组私信默认被忽略;通过 `channels.discord.dm.groupEnabled` 启用,可选通过 `channels.discord.dm.groupChannels` 限制。
- 保持路由确定性:回复始终发回消息到达的渠道。
## 工作原理
1. 创建 Discord 应用程序 → Bot启用你需要的意图(私信 + 服务器消息 + 消息内容),获取机器人令牌
2. 使用所需权限邀请机器人到你的服务器,以便在你想使用的地方读取/发送消息。
1. 创建 Discord 应用 → Bot启用所需的 intent(私信 + 服务器消息 + 消息内容),获取机器人 token
2. 邀请机器人到你的服务器,赋予在你需要使用的地方读取/发送消息所需的权限
3. 使用 `channels.discord.token` 配置 OpenClaw或使用 `DISCORD_BOT_TOKEN` 作为回退)。
4. 运行 Gateway 网关;当令牌可用(配置优先,环境变量回退)且 `channels.discord.enabled` 不为 `false` 时,它会自动启动 Discord 渠道。
- 如果你更喜欢使用环境变量,设置 `DISCORD_BOT_TOKEN`(配置块是可选的)。
5. 直接聊天:发送时使用 `user:<id>`(或 `<@id>` 提及);所有对话都进入共享的 `main` 会话。数字 ID 是模糊的,会被拒绝。
6. 服务器频道:发送时使用 `channel:<channelId>`。默认需要提及,可按服务器或按频道设置。
7. 直接聊天:默认通过 `channels.discord.dm.policy` 进行安全保护(默认:`"pairing"`。未知发送者会收到配对码1 小时后过期);通过 `openclaw pairing approve discord <code>` 批准。
4. 运行 Gateway网关 token 可用(配置优先,环境变量回退)且 `channels.discord.enabled` 不为 `false` 时,它会自动启动 Discord 渠道。
- 如果你偏好使用环境变量,设置 `DISCORD_BOT_TOKEN`(配置块是可选的)。
5. 私聊:投递时使用 `user:<id>`(或 `<@id>` 提及);所有回合都进入共享的 `main` 会话。数字 ID 具有歧义性,会被拒绝。
6. 服务器频道:投递时使用 `channel:<channelId>`。默认需要提及,可按服务器或按频道设置。
7. 私聊:默认通过 `channels.discord.dm.policy`(默认:`"pairing"`进行安全保护。未知发送者会收到配对码1 小时后过期);通过 `openclaw pairing approve discord <code>` 批准。
- 要保持旧的"对任何人开放"行为:设置 `channels.discord.dm.policy="open"``channels.discord.dm.allowFrom=["*"]`
-使用硬编码允许列表:设置 `channels.discord.dm.policy="allowlist"` 并在 `channels.discord.dm.allowFrom` 中列出发送者。
-硬性限制允许列表:设置 `channels.discord.dm.policy="allowlist"` 并在 `channels.discord.dm.allowFrom` 中列出发送者。
- 要忽略所有私信:设置 `channels.discord.dm.enabled=false``channels.discord.dm.policy="disabled"`
8. 群组私信默认被忽略;通过 `channels.discord.dm.groupEnabled` 启用,可选通过 `channels.discord.dm.groupChannels` 进行限制。
9. 可选服务器规则:设置 `channels.discord.guilds`,以服务器 ID首选)或 slug 为键,包含每个频道的规则。
10. 可选原生命令:`commands.native` 默认为 `"auto"`Discord/Telegram 开启Slack 关闭)。使用 `channels.discord.commands.native: true|false|"auto"` 覆盖;`false` 会清除之前注册的命令。文本命令由 `commands.text` 控制,必须作为独立的 `/...` 消息发送。使用 `commands.useAccessGroups: false`过命令的访问组检查。
8. 群组私信默认被忽略;通过 `channels.discord.dm.groupEnabled` 启用,可选通过 `channels.discord.dm.groupChannels` 限制。
9. 可选服务器规则:设置 `channels.discord.guilds`,以服务器 ID推荐)或 slug 为键,包含频道的规则。
10. 可选原生命令:`commands.native` 默认为 `"auto"`Discord/Telegram 开启Slack 关闭)。通过 `channels.discord.commands.native: true|false|"auto"` 覆盖;`false` 会清除之前注册的命令。文本命令由 `commands.text` 控制,必须作为独立的 `/...` 消息发送。使用 `commands.useAccessGroups: false`过命令的访问组检查。
- 完整命令列表 + 配置:[斜杠命令](/tools/slash-commands)
11. 可选服务器上下文历史:设置 `channels.discord.historyLimit`(默认 20回退到 `messages.groupChat.historyLimit`)以在回复提及时包含最近 N 条服务器消息作为上下文。设置 `0` 禁用。
12. 表情反应:智能体可以通过 `discord` 工具触发表情反应( `channels.discord.actions.*` 控制)。
- 表情反应移除语义:参见 [/tools/reactions](/tools/reactions)。
- `discord` 工具仅在当前渠道 Discord 时暴露。
13. 原生命令使用隔离的会话键(`agent:<agentId>:discord:slash:<userId>`)而不是共享的 `main` 会话。
11. 可选服务器上下文历史:设置 `channels.discord.historyLimit`(默认 20回退到 `messages.groupChat.historyLimit`)以在回复提及时包含最近 N 条服务器消息作为上下文。设置 `0` 禁用。
12. 应:智能体可以通过 `discord` 工具触发应( `channels.discord.actions.*` 控制)。
- 应移除语义:参见 [/tools/reactions](/tools/reactions)。
- `discord` 工具仅在当前渠道 Discord 时暴露。
13. 原生命令使用隔离的会话键(`agent:<agentId>:discord:slash:<userId>`)而共享的 `main` 会话。
注意:名称 → ID 解析使用服务器成员搜索,需要 Server Members Intent如果机器人无法搜索成员请使用 ID 或 `<@id>` 提及。
注意Slug 为小写空格替换为 `-`。频道名称的 slug 不包含前导 `#`
注意:服务器上下文 `[from:]` 行包含 `author.tag` + `id`,便进行可提及的回复。
注意Slug 为小写空格替换为 `-`。频道名称的 slug 不包含前导 `#`
注意:服务器上下文 `[from:]` 行包含 `author.tag` + `id`便进行可直接 ping 的回复。
## 配置写入
默认情况下,允许 Discord 写入由 `/config set|unset` 触发的配置更新(需要 `commands.config: true`)。
默认情况下Discord 允许通过 `/config set|unset` 触发的配置更新写入(需要 `commands.config: true`)。
禁用方式
通过以下方式禁用:
```json5
{
@@ -91,32 +91,32 @@ x-i18n:
这是在服务器guild频道`#help`)中运行 OpenClaw 的"Discord 开发者门户"设置。
### 1创建 Discord 应用 + 机器人用户
### 1) 创建 Discord 应用 + 机器人用户
1. Discord 开发者门户 → **Applications****New Application**
2. 在你的应用中:
- **Bot** → **Add Bot**
- 复制 **Bot Token**(这是你放入 `DISCORD_BOT_TOKEN`内容
- 复制 **Bot Token**(这是你放入 `DISCORD_BOT_TOKEN`
### 2启用 OpenClaw 需的网关意图
### 2) 启用 OpenClaw 需的网关 intent
Discord 会阻止"特权意图",除非你明确启用它们
Discord 会阻止"特权 intent",除非你明确启用。
**Bot****Privileged Gateway Intents** 中启用:
**Bot****Privileged Gateway Intents**启用:
- **Message Content Intent**(在大多数服务器中读取消息文本所必需;没有它你会看到"Used disallowed intents"或机器人会连接但不响应消息)
- **Server Members Intent**(推荐;服务器中的某些成员/用户查找和允许列表匹配需
- **Server Members Intent**(推荐;某些成员/用户查找和服务器中的允许列表匹配所必需)
通常**不需要** **Presence Intent**
通常**不**需要 **Presence Intent**
### 3生成邀请 URLOAuth2 URL Generator
### 3) 生成邀请 URLOAuth2 URL 生成器
在你的应用中:**OAuth2** → **URL Generator**
**Scopes**
-`bot`
-`applications.commands`(原生命令所需)
-`applications.commands`(原生命令所需)
**Bot Permissions**(最小基线)
@@ -126,27 +126,27 @@ Discord 会阻止"特权意图",除非你明确启用它们。
- ✅ Embed Links
- ✅ Attach Files
- ✅ Add Reactions可选但推荐
- ✅ Use External Emojis / Stickers可选你需要时)
- ✅ Use External Emojis / Stickers可选你需要时)
除非你在调试完全信任机器人,否则避免使用 **Administrator**
除非你在调试完全信任机器人,否则避免使用 **Administrator**
复制生成的 URL打开它选择你的服务器然后安装机器人。
复制生成的 URL打开它选择你的服务器安装机器人。
### 4获取 ID服务器/用户/频道)
### 4) 获取 ID服务器/用户/频道)
Discord 到处使用数字 IDOpenClaw 配置优先使用 ID。
Discord 到处使用数字 IDOpenClaw 配置推荐使用 ID。
1. Discord桌面/网页)→ **用户设置****高级** → 启用 **开发者模式**
2. 右键点击:
- 服务器名称 → **复制服务器 ID**服务器 ID
- 服务器名称 → **复制服务器 ID**guild id
- 频道(例如 `#help`)→ **复制频道 ID**
- 你的用户 → **复制用户 ID**
### 5配置 OpenClaw
### 5) 配置 OpenClaw
#### 令牌
#### Token
通过环境变量设置机器人令牌(服务器上推荐
通过环境变量设置机器人 token推荐用于服务器
- `DISCORD_BOT_TOKEN=...`
@@ -163,7 +163,7 @@ Discord 到处使用数字 IDOpenClaw 配置优先使用 ID。
}
```
多账户支持:使用 `channels.discord.accounts`,每个账户有自己的令牌和可选的 `name`参见 [`gateway/configuration`](/gateway/configuration#telegramaccounts--discordaccounts--slackaccounts--signalaccounts--imessageaccounts) 了解通用模式
多账户支持:使用 `channels.discord.accounts`,每个账户配置独立的 token 和可选的 `name`共享模式请参阅 [`gateway/configuration`](/gateway/configuration#telegramaccounts--discordaccounts--slackaccounts--signalaccounts--imessageaccounts)。
#### 允许列表 + 频道路由
@@ -195,57 +195,52 @@ Discord 到处使用数字 IDOpenClaw 配置优先使用 ID。
}
```
注意:
注意事项
- `requireMention: true` 意味着机器人在被提及时回复(推荐用于共享频道)。
- `agents.list[].groupChat.mentionPatterns`(或 `messages.groupChat.mentionPatterns`)对服务器消息也算作提及。
- `requireMention: true` 表示机器人在被提及时回复(推荐用于共享频道)。
- `agents.list[].groupChat.mentionPatterns`(或 `messages.groupChat.mentionPatterns`)对服务器消息也算作提及。
- 多智能体覆盖:在 `agents.list[].groupChat.mentionPatterns` 上设置每个智能体的模式。
- 如果存在 `channels`,任何未列出的频道默认被拒绝。
- 使用 `"*"` 频道条目所有频道应用默认值;显式频道条目覆盖通配符。
- 话题继承父频道配置(允许列表、`requireMention`、Skills、提示等),除非你显式添加话题频道 ID。
- 机器人发送的消息默认被忽略;设置 `channels.discord.allowBots=true` 允许它们(自己的消息仍被过滤)。
- 警告:如果你允许回复其他机器人(`channels.discord.allowBots=true`),请使用 `requireMention``channels.discord.guilds.*.channels.<id>.users` 允许列表和/或在 `AGENTS.md``SOUL.md` 中设置明确的防护措施来防止机器人之间的回复循环。
- 使用 `"*"` 频道条目来应用所有频道默认值;明确的频道条目覆盖通配符。
- 帖子继承父频道配置(允许列表、`requireMention`、Skills、提示等除非你明确添加帖子频道 ID。
- 机器人发送的消息默认被忽略;设置 `channels.discord.allowBots=true` 允许它们(自己的消息仍被过滤)。
- 警告:如果你允许回复其他机器人(`channels.discord.allowBots=true`),请使用 `requireMention``channels.discord.guilds.*.channels.<id>.users` 允许列表和/或在 `AGENTS.md``SOUL.md` 中设置明确的防护规则来防止机器人之间的回复循环。
### 6验证是否工作
### 6) 验证是否正常工作
1. 启动 Gateway 网关。
2. 在你的服务器频道中发送:`@Krill hello`(或你的机器人名称)。
3. 如果没有应:查看下面的**故障排除**。
1. 启动 Gateway网关。
2. 在你的服务器频道中发送:`@Krill hello`(或你的机器人名称)。
3. 如果没有应:查看下**故障排除**。
### 故障排除
- 首先:运行 `openclaw doctor``openclaw channels status --probe`(可操作的警告 + 快速审计)。
- **"Used disallowed intents"**:在开发者门户中启用 **Message Content Intent**可能还需要 **Server Members Intent**),然后重启 Gateway 网关。
- **机器人连接但从不在服务器频道回复**
- **"Used disallowed intents"**:在开发者门户中启用 **Message Content Intent**以及可能的 **Server Members Intent**),然后重启 Gateway网关。
- **机器人连接但在服务器频道中从不回复**
- 缺少 **Message Content Intent**,或
- 机器人缺少频道权限View/Send/Read History
- 你的配置要提及但你没有提及它,或
- 你的配置要提及但你没有提及它,或
- 你的服务器/频道允许列表拒绝了该频道/用户。
- **`requireMention: false` 但仍然没有回复**
- `channels.discord.groupPolicy` 默认为 **allowlist**;将其设置为 `"open"` 或在 `channels.discord.guilds` 下添加服务器条目(可选`channels.discord.guilds.<id>.channels` 下列出频道以进行限制)。
- 如果你只设置了 `DISCORD_BOT_TOKEN` 从未创建 `channels.discord` 部分,运行时`groupPolicy` 默认`open`。添加 `channels.discord.groupPolicy``channels.defaults.groupPolicy` 或服务器/频道允许列表来锁定它。
- `channels.discord.groupPolicy` 默认为 **allowlist**;将其设置为 `"open"` 或在 `channels.discord.guilds` 下添加服务器条目(可选在 `channels.discord.guilds.<id>.channels` 下列出频道以进行限制)。
- 如果你只设置了 `DISCORD_BOT_TOKEN` 从未创建 `channels.discord` 部分,运行时默认`groupPolicy` `open`。添加 `channels.discord.groupPolicy``channels.defaults.groupPolicy` 或服务器/频道允许列表来锁定它。
- `requireMention` 必须位于 `channels.discord.guilds`(或特定频道)下。顶层的 `channels.discord.requireMention` 会被忽略。
- **权限审计**`channels status --probe`检查数字频道 ID。如果你使用 slug/名称作为 `channels.discord.guilds.*.channels` 键,审计无法验证权限。
- **私信不工作**`channels.discord.dm.enabled=false``channels.discord.dm.policy="disabled"`,或你尚未被批准(`channels.discord.dm.policy="pairing"`)。
- **Discord 中的执行审批**Discord 支持私信中执行审批的**按钮 UI**(允许一次 / 始终允许 / 拒绝)。`/approve <id> ...` 仅用于转发的审批,不会解析 Discord 的按钮提示。如果你看到 `❌ Failed to submit approval: Error: unknown approval id` 或 UI 从未出现,请检查:
- 你的配置中有 `channels.discord.execApprovals.enabled: true`
- 你的 Discord 用户 ID 在 `channels.discord.execApprovals.approvers` 中列出UI 仅发送给审批者)。
- 使用私信提示中的按钮(**Allow once**、**Always allow**、**Deny**)。
- 参见[执行审批](/tools/exec-approvals)和[斜杠命令](/tools/slash-commands)了解更广泛的审批和命令流程。
- **权限审计**`channels status --probe`检查数字频道 ID。如果你使用 slug/名称作为 `channels.discord.guilds.*.channels` 键,审计无法验证权限。
- **私信不工作**`channels.discord.dm.enabled=false``channels.discord.dm.policy="disabled"`,或你尚未被批准(`channels.discord.dm.policy="pairing"`)。
## 功能限制
## 功能限制
- 支持私信和服务器文字频道(话题被视为独立频道;不支持语音)。
- 打字指示尽力发送;消息分块使用 `channels.discord.textChunkLimit`(默认 2000并按行数分割长回复(`channels.discord.maxLinesPerMessage`,默认 17
- 可选换行分块:设置 `channels.discord.chunkMode="newline"` 在空行(段落边界)分割,然后再进行长度分块
- 支持文件上传,最大 `channels.discord.mediaMaxMb`(默认 8 MB
- 默认服务器回复需要提及,以避免嘈杂的机器人。
- 私信和服务器文字频道(帖子被视为独立频道;不支持语音)。
- 输入指示尽力发送;消息分块使用 `channels.discord.textChunkLimit`(默认 2000并按行数分割长回复(`channels.discord.maxLinesPerMessage`,默认 17
- 可选换行分块:设置 `channels.discord.chunkMode="newline"`按长度分块之前按空行(段落边界)分割。
- 支持文件上传,上限为配置的 `channels.discord.mediaMaxMb`(默认 8 MB
- 服务器回复默认需要提及门控,以避免嘈杂的机器人。
- 当消息引用另一条消息时,会注入回复上下文(引用内容 + ID
- 原生回复线程**默认关闭**使用 `channels.discord.replyToMode` 和回复标签启用。
- 原生回复线程**默认关闭**通过 `channels.discord.replyToMode` 和回复标签启用。
## 重试策略
出站 Discord API 调用在速率限制429时使用 Discord `retry_after`(如可用)进行重试,采用指数退避和抖动。通过 `channels.discord.retry` 配置。参见[重试策略](/concepts/retry)。
出站 Discord API 调用在速率限制429时使用 Discord `retry_after`(如可用)进行重试,采用指数退避和抖动。通过 `channels.discord.retry` 配置。参见[重试策略](/concepts/retry)。
## 配置
@@ -316,58 +311,57 @@ Discord 到处使用数字 IDOpenClaw 配置优先使用 ID。
}
```
确认表情反应通过 `messages.ackReaction` + `messages.ackReactionScope` 全局控制。使用 `messages.removeAckAfterReply` 在机器人回复后清除确认表情反应。
确认回应由 `messages.ackReaction` + `messages.ackReactionScope` 全局控制。使用 `messages.removeAckAfterReply` 在机器人回复后清除确认应。
- `dm.enabled`:设置 `false` 忽略所有私信(默认 `true`)。
- `dm.enabled`:设置 `false` 忽略所有私信(默认 `true`)。
- `dm.policy`:私信访问控制(推荐 `pairing`)。`"open"` 需要 `dm.allowFrom=["*"]`
- `dm.allowFrom`:私信允许列表(用户 ID 或名称)。用于 `dm.policy="allowlist"``dm.policy="open"` 验证。向导接受用户名并在机器人可以搜索成员时将其解析为 ID。
- `dm.allowFrom`:私信允许列表(用户 ID 或名称)。用于 `dm.policy="allowlist"``dm.policy="open"` 验证。向导接受用户名并在机器人可以搜索成员时将其解析为 ID。
- `dm.groupEnabled`:启用群组私信(默认 `false`)。
- `dm.groupChannels`:群组私信频道 ID 或 slug 的可选允许列表。
- `groupPolicy`:控制服务器频道处理(`open|disabled|allowlist``allowlist` 需要频道允许列表。
- `guilds`:按服务器规则,以服务器 ID首选)或 slug 为键。
- `guilds."*"`:当没有显式条目时应用的默认服务器设置。
- `groupPolicy`:控制服务器频道处理方式`open|disabled|allowlist``allowlist` 需要频道允许列表。
- `guilds`:按服务器 ID推荐)或 slug 为键的按服务器规则
- `guilds."*"`:当没有明确条目时应用的默认服务器设置。
- `guilds.<id>.slug`:用于显示名称的可选友好 slug。
- `guilds.<id>.users`:可选的服务器用户允许列表ID 或名称)。
- `guilds.<id>.tools`:可选的服务器工具策略覆盖(`allow`/`deny`/`alsoAllow`),在频道覆盖缺失时使用。
- `guilds.<id>.toolsBySender`服务器级别的可选每发送者工具策略覆盖(在频道覆盖缺失时应用;支持 `"*"` 通配符)。
- `guilds.<id>.users`:可选的服务器用户允许列表ID 或名称)。
- `guilds.<id>.tools`:可选的服务器工具策略覆盖(`allow`/`deny`/`alsoAllow`),在频道覆盖缺失时使用。
- `guilds.<id>.toolsBySender`可选的按发送者工具策略覆盖(服务器级别,在频道覆盖缺失时应用;支持 `"*"` 通配符)。
- `guilds.<id>.channels.<channel>.allow`:当 `groupPolicy="allowlist"` 时允许/拒绝频道。
- `guilds.<id>.channels.<channel>.requireMention`:频道的提及限制
- `guilds.<id>.channels.<channel>.tools`:可选的频道工具策略覆盖(`allow`/`deny`/`alsoAllow`)。
- `guilds.<id>.channels.<channel>.toolsBySender`频道内的可选每发送者工具策略覆盖(支持 `"*"` 通配符)。
- `guilds.<id>.channels.<channel>.users`:可选的频道用户允许列表。
- `guilds.<id>.channels.<channel>.requireMention`:频道的提及门控
- `guilds.<id>.channels.<channel>.tools`:可选的频道工具策略覆盖(`allow`/`deny`/`alsoAllow`)。
- `guilds.<id>.channels.<channel>.toolsBySender`可选的频道内按发送者工具策略覆盖(支持 `"*"` 通配符)。
- `guilds.<id>.channels.<channel>.users`:可选的频道用户允许列表。
- `guilds.<id>.channels.<channel>.skills`Skills 过滤器(省略 = 所有 Skills空 = 无)。
- `guilds.<id>.channels.<channel>.systemPrompt`:频道的额外系统提示(与频道主题合)。
- `guilds.<id>.channels.<channel>.enabled`:设置 `false` 禁用频道。
- `guilds.<id>.channels.<channel>.systemPrompt`:频道的额外系统提示(与频道主题合)。
- `guilds.<id>.channels.<channel>.enabled`:设置 `false` 禁用频道。
- `guilds.<id>.channels`:频道规则(键为频道 slug 或 ID
- `guilds.<id>.requireMention`服务器提及要求(可按频道覆盖)。
- `guilds.<id>.reactionNotifications`表情反应系统事件模式(`off``own``all``allowlist`)。
- `textChunkLimit`出站文本块大小字符。默认2000。
- `chunkMode``length`(默认)仅在超过 `textChunkLimit` 时分割;`newline` 在空行(段落边界)分割,然后再进行长度分块
- `guilds.<id>.requireMention`服务器提及要求(可按频道覆盖)。
- `guilds.<id>.reactionNotifications`应系统事件模式(`off``own``all``allowlist`)。
- `textChunkLimit`:出站文本块大小字符。默认2000。
- `chunkMode``length`(默认)仅在超过 `textChunkLimit` 时分割;`newline`按长度分块之前按空行(段落边界)分割。
- `maxLinesPerMessage`每条消息的软最大行数。默认17。
- `mediaMaxMb`:限制保存到磁盘的入站媒体大小。
- `historyLimit`:回复提及时作为上下文包含的最近服务器消息数(默认 20回退到 `messages.groupChat.historyLimit``0` 禁用)。
- `dmHistoryLimit`:私信历史限制(用户轮次)。用户覆盖:`dms["<user_id>"].historyLimit`
- `historyLimit`:回复提及时包含的最近服务器消息数作为上下文(默认 20回退到 `messages.groupChat.historyLimit``0` 禁用)。
- `dmHistoryLimit`:私信历史限制(用户回合数)。用户覆盖:`dms["<user_id>"].historyLimit`
- `retry`:出站 Discord API 调用的重试策略attempts、minDelayMs、maxDelayMs、jitter
- `pluralkit`:解析 PluralKit 代理消息,使系统成员显示为不同的发送者。
- `actions`操作工具门控;省略允许所有(设置 `false` 禁用)。
- `reactions`(涵盖表情反应 + 读取表情反应)
- `actions`操作工具门控;省略允许所有(设置 `false` 禁用)。
- `reactions`(涵盖添加回应 + 读取应)
- `stickers``emojiUploads``stickerUploads``polls``permissions``messages``threads``pins``search`
- `memberInfo``roleInfo``channelInfo``voiceStatus``events`
- `channels`(创建/编辑/删除频道 + 类 + 权限)
- `channels`(创建/编辑/删除频道 + 类 + 权限)
- `roles`(角色添加/移除,默认 `false`
- `moderation`(超时/踢出/封禁,默认 `false`
- `execApprovals`Discord 专用执行审批私信(按钮 UI。支持 `enabled``approvers``agentFilter``sessionFilter`
表情反应通知使用 `guilds.<id>.reactionNotifications`
应通知使用 `guilds.<id>.reactionNotifications`
- `off`:无表情反应事件。
- `own`:机器人自己消息上的表情反应(默认)。
- `all`:所有消息上的所有表情反应。
- `allowlist`:来自 `guilds.<id>.users` 的用户在所有消息上的表情反应(空列表禁用)。
- `off`:无应事件。
- `own`:机器人自己消息上的应(默认)。
- `all`:所有消息上的所有应。
- `allowlist`:来自 `guilds.<id>.users` 的用户在所有消息上的应(空列表禁用)。
### PluralKitPK支持
启用 PK 查找,以便代理消息解析底层系统 + 成员。启用后OpenClaw 使用成员身份进行允许列表匹配,并将发送者标记为 `Member (PK:System)` 以避免意外的 Discord 提及
启用 PK 查找,使代理消息解析底层系统 + 成员。启用后OpenClaw 使用成员身份进行允许列表匹配,并将发送者标记为 `Member (PK:System)` 以避免意外的 Discord ping
```json5
{
@@ -384,85 +378,86 @@ Discord 到处使用数字 IDOpenClaw 配置优先使用 ID。
允许列表注意事项(启用 PK 时):
-`dm.allowFrom``guilds.<id>.users`频道 `users` 中使用 `pk:<memberId>`
- 成员显示名称也名称/slug 匹配。
- 查找使用**原始** Discord 消息 ID代理前的消息因此 PK API 在其 30 分钟窗口内解析它。
- 如果 PK 查找失败(例如没有令牌的私有系统),代理消息被视为机器人消息并被丢弃,除非 `channels.discord.allowBots=true`
-`dm.allowFrom``guilds.<id>.users`频道 `users` 中使用 `pk:<memberId>`
- 成员显示名称也通过名称/slug 匹配。
- 查找使用**原始** Discord 消息 ID代理前的消息因此 PK API 在其 30 分钟窗口内解析它。
- 如果 PK 查找失败(例如没有 token 的私有系统),代理消息被视为机器人消息并被丢弃,除非设置 `channels.discord.allowBots=true`
### 工具操作默认值
| 操作组 | 默认 | 说明 |
| -------------- | ---- | ----------------------------------- |
| reactions | 启用 | 表情反应 + 列出表情反应 + emojiList |
| stickers | 启用 | 发送贴纸 |
| emojiUploads | 启用 | 上传表情 |
| stickerUploads | 启用 | 上传贴纸 |
| polls | 启用 | 创建投票 |
| permissions | 启用 | 频道权限快照 |
| messages | 启用 | 读取/发送/编辑/删除 |
| threads | 启用 | 创建/列出/回复 |
| pins | 启用 | 置顶/取消置顶/列出 |
| search | 启用 | 消息搜索(预览功能) |
| memberInfo | 启用 | 成员信息 |
| roleInfo | 启用 | 角色列表 |
| channelInfo | 启用 | 频道信息 + 列表 |
| channels | 启用 | 频道/类别管理 |
| voiceStatus | 启用 | 语音状态查询 |
| events | 启用 | 列出/创建预定事件 |
| roles | 禁用 | 角色添加/移除 |
| moderation | 禁用 | 超时/踢出/封禁 |
| 操作组 | 默认 | 说明 |
| -------------- | ------ | ------------------------------- |
| reactions | 启用 | 添加回应 + 列出应 + emojiList |
| stickers | 启用 | 发送贴纸 |
| emojiUploads | 启用 | 上传表情 |
| stickerUploads | 启用 | 上传贴纸 |
| polls | 启用 | 创建投票 |
| permissions | 启用 | 频道权限快照 |
| messages | 启用 | 读取/发送/编辑/删除 |
| threads | 启用 | 创建/列出/回复 |
| pins | 启用 | 置顶/取消置顶/列出 |
| search | 启用 | 消息搜索(预览功能) |
| memberInfo | 启用 | 成员信息 |
| roleInfo | 启用 | 角色列表 |
| channelInfo | 启用 | 频道信息 + 列表 |
| channels | 启用 | 频道/分类管理 |
| voiceStatus | 启用 | 语音状态查询 |
| events | 启用 | 列出/创建计划事件 |
| roles | 禁用 | 角色添加/移除 |
| moderation | 禁用 | 超时/踢出/封禁 |
- `replyToMode``off`(默认)、`first``all`。仅在模型包含回复标签时适用
- `replyToMode``off`(默认)、`first``all`。仅在模型输出包含回复标签时生效
## 回复标签
要请求线程回复,模型可以在输出中包含一个标签:
要请求线程回复,模型可以在输出中包含一个标签:
- `[[reply_to_current]]` — 回复触发的 Discord 消息。
- `[[reply_to:<id>]]` — 回复上下文/历史中的特定消息 ID。当前消息 ID 作为 `[message_id: …]` 附加到提示词;历史条目已包含 ID。
- `[[reply_to:<id>]]` — 回复上下文/历史中的特定消息 ID。
当前消息 ID 以 `[message_id: …]` 附加到提示中;历史条目已包含 ID。
行为由 `channels.discord.replyToMode` 控制:
- `off`:忽略标签。
- `first`只有第一个出站块/附件回复。
- `all`:每个出站块/附件都回复。
- `first`第一个出站块/附件作为回复。
- `all`:每个出站块/附件都作为回复。
允许列表匹配注意事项:
- `allowFrom`/`users`/`groupChannels` 接受 ID、名称、标签或 `<@id>` 这样的提及。
- `allowFrom`/`users`/`groupChannels` 接受 ID、名称、标签或 `<@id>` 格式的提及。
- 支持 `discord:`/`user:`(用户)和 `channel:`(群组私信)等前缀。
- 使用 `*` 允许任何发送者/频道。
- 当存在 `guilds.<id>.channels` 时,未列出的频道默认被拒绝。
- 当省略 `guilds.<id>.channels` 时,允许列表中服务器的所有频道都被允许。
- 要**不允许任何频道**,设置 `channels.discord.groupPolicy: "disabled"`(或保持空允许列表)。
- 配置向导接受 `Guild/Channel` 名称(公 + 私有)并在可能时将其解析为 ID。
- 要**不允许任何频道**,设置 `channels.discord.groupPolicy: "disabled"`(或保持空允许列表)。
- 配置向导接受 `Guild/Channel` 名称(公 + 私有)并在可能时将其解析为 ID。
- 启动时OpenClaw 将允许列表中的频道/用户名称解析为 ID当机器人可以搜索成员时并记录映射未解析的条目保持原样。
原生命令注意事项:
- 注册的命令镜像 OpenClaw 的聊天命令。
- 原生命令遵循与私信/服务器消息相同的允许列表(`channels.discord.dm.allowFrom``channels.discord.guilds`频道规则)。
- 斜杠命令可能在 Discord UI 中对未在允许列表中的用户仍然可见OpenClaw 在执行时强制执行允许列表并回复"未授权"。
- 注册的命令 OpenClaw 的聊天命令一致
- 原生命令遵循与私信/服务器消息相同的允许列表(`channels.discord.dm.allowFrom``channels.discord.guilds`频道规则)。
- 斜杠命令在 Discord UI 中可能对不在允许列表中的用户仍然可见OpenClaw 在执行时强制执行允许列表并回复"未授权"。
## 工具操作
智能体可以使用以下操作调用 `discord`
智能体可以调用 `discord` 执行以下操作
- `react` / `reactions`(添加或列出表情反应)
- `react` / `reactions`(添加或列出应)
- `sticker``poll``permissions`
- `readMessages``sendMessage``editMessage``deleteMessage`
- 读取/搜索/置顶工具负载包含规范化的 `timestampMs`UTC 纪元毫秒)和 `timestampUtc` 以及原始 Discord `timestamp`
- 读取/搜索/置顶工具负载包含标准化的 `timestampMs`UTC 纪元毫秒)和 `timestampUtc`,同时保留原始 Discord `timestamp`
- `threadCreate``threadList``threadReply`
- `pinMessage``unpinMessage``listPins`
- `searchMessages``memberInfo``roleInfo``roleAdd``roleRemove``emojiList`
- `channelInfo``channelList``voiceStatus``eventList``eventCreate`
- `timeout``kick``ban`
Discord 消息 ID 在注入的上下文中显示`[discord message id: …]` 和历史行),便智能体可以定位它们。
Discord 消息 ID 在注入的上下文中呈现`[discord message id: …]` 和历史行),便智能体定位它们。
表情可以是 unicode例如 `✅`)或自定义表情语法如 `<:party_blob:1234567890>`
## 安全与运维
- 像对待密码一样对待机器人令牌;在受监督的主机上优先使用 `DISCORD_BOT_TOKEN` 环境变量或锁定配置文件权限。
- 授予机器人所需的权限(通常是读取/发送消息)。
- 如果机器人卡住或受到速率限制,在确认没有其他进程拥有 Discord 会话后重启 Gateway 网关(`openclaw gateway --force`)。
- 将机器人 token 视为密码;在受管主机上推荐使用 `DISCORD_BOT_TOKEN` 环境变量或锁定配置文件权限。
- 授予机器人所需的权限(通常是读取/发送消息)。
- 如果机器人卡住或速率限制,在确认没有其他进程占用 Discord 会话后重启 Gateway网关`openclaw gateway --force`)。

View File

@@ -41,13 +41,11 @@ openclaw onboard
```
向导会引导您完成:
1. 创建飞书应用并获取凭证
2. 配置应用凭证
3. 启动网关
**完成配置后**,您可以使用以下命令检查网关状态:
- `openclaw gateway status` - 查看网关运行状态
- `openclaw logs --follow` - 查看实时日志
@@ -62,7 +60,6 @@ openclaw channels add
然后根据交互式提示选择 Feishu输入 App ID 和 App Secret 即可。
**完成配置后**,您可以使用以下命令管理网关:
- `openclaw gateway status` - 查看网关运行状态
- `openclaw gateway restart` - 重启网关以应用新配置
- `openclaw logs --follow` - 查看实时日志
@@ -83,18 +80,17 @@ Lark国际版请使用 https://open.larksuite.com/app并在配置中设
2. 填写应用名称和描述
3. 选择应用图标
![创建企业自建应用](/images/feishu-step2-create-app.png)
![创建企业自建应用](../images/feishu-step2-create-app.png)
### 3. 获取应用凭证
在应用的 **凭证与基础信息** 页面,复制:
- **App ID**(格式如 `cli_xxx`
- **App Secret**
**重要**:请妥善保管 App Secret不要分享给他人。
![获取应用凭证](/images/feishu-step3-credentials.png)
![获取应用凭证](../images/feishu-step3-credentials.png)
### 4. 配置应用权限
@@ -121,37 +117,38 @@ Lark国际版请使用 https://open.larksuite.com/app并在配置中设
"im:message:send_as_bot",
"im:resource"
],
"user": ["aily:file:read", "aily:file:write", "im:chat.access_event.bot_p2p_chat:read"]
"user": [
"aily:file:read",
"aily:file:write",
"im:chat.access_event.bot_p2p_chat:read"
]
}
}
```
![配置应用权限](/images/feishu-step4-permissions.png)
![配置应用权限](../images/feishu-step4-permissions.png)
### 5. 启用机器人能力
**应用能力** > **机器人** 页面:
1. 开启机器人能力
2. 配置机器人名称
![启用机器人能力](/images/feishu-step5-bot-capability.png)
![启用机器人能力](../images/feishu-step5-bot-capability.png)
### 6. 配置事件订阅
⚠️ **重要提醒**:在配置事件订阅前,请务必确保已完成以下步骤:
1. 运行 `openclaw channels add` 添加了 Feishu 渠道
2. 网关处于启动状态(可通过 `openclaw gateway status` 检查状态)
**事件订阅** 页面:
1. 选择 **使用长连接接收事件**WebSocket 模式)
2. 添加事件:`im.message.receive_v1`(接收消息)
⚠️ **注意**:如果网关未启动或渠道未添加,长连接设置将保存失败。
![配置事件订阅](/images/feishu-step6-event-subscription.png)
![配置事件订阅](../images/feishu-step6-event-subscription.png)
### 7. 发布应用
@@ -187,11 +184,11 @@ openclaw channels add
main: {
appId: "cli_xxx",
appSecret: "xxx",
botName: "我的AI助手",
},
},
},
},
botName: "我的AI助手"
}
}
}
}
}
```
@@ -214,11 +211,11 @@ export FEISHU_APP_SECRET="xxx"
accounts: {
main: {
appId: "cli_xxx",
appSecret: "xxx",
},
},
},
},
appSecret: "xxx"
}
}
}
}
}
```
@@ -272,13 +269,11 @@ openclaw pairing approve feishu <配对码>
### 群组访问
**1. 群组策略**`channels.feishu.groupPolicy`
- `"open"` = 允许群组中所有人(默认)
- `"allowlist"` = 仅允许 `groupAllowFrom` 中的用户
- `"disabled"` = 禁用群组消息
**2. @提及要求**`channels.feishu.groups.<chat_id>.requireMention`
- `true` = 需要 @机器人才响应(默认)
- `false` = 无需 @也响应
@@ -292,10 +287,10 @@ openclaw pairing approve feishu <配对码>
{
channels: {
feishu: {
groupPolicy: "open",
groupPolicy: "open"
// 默认 requireMention: true
},
},
}
}
}
```
@@ -308,10 +303,10 @@ openclaw pairing approve feishu <配对码>
channels: {
feishu: {
groups: {
oc_xxx: { requireMention: false },
},
},
},
"oc_xxx": { requireMention: false }
}
}
}
}
```
@@ -322,9 +317,9 @@ openclaw pairing approve feishu <配对码>
channels: {
feishu: {
groupPolicy: "allowlist",
groupAllowFrom: ["ou_xxx", "ou_yyy"],
},
},
groupAllowFrom: ["ou_xxx", "ou_yyy"]
}
}
}
```
@@ -337,7 +332,6 @@ openclaw pairing approve feishu <配对码>
群组 ID 格式为 `oc_xxx`,可以通过以下方式获取:
**方法一**(推荐):
1. 启动网关并在群组中 @机器人发消息
2. 运行 `openclaw logs --follow` 查看日志中的 `chat_id`
@@ -349,13 +343,11 @@ openclaw pairing approve feishu <配对码>
用户 ID 格式为 `ou_xxx`,可以通过以下方式获取:
**方法一**(推荐):
1. 启动网关并给机器人发消息
2. 运行 `openclaw logs --follow` 查看日志中的 `open_id`
**方法二**
查看配对请求列表,其中包含用户的 Open ID
```bash
openclaw pairing list feishu
```
@@ -364,11 +356,11 @@ openclaw pairing list feishu
## 常用命令
| 命令 | 说明 |
| --------- | -------------- |
| 命令 | 说明 |
|------|------|
| `/status` | 查看机器人状态 |
| `/reset` | 重置对话会话 |
| `/model` | 查看/切换模型 |
| `/reset` | 重置对话会话 |
| `/model` | 查看/切换模型 |
> 注意:飞书目前不支持原生命令菜单,命令需要以文本形式发送。
@@ -376,13 +368,13 @@ openclaw pairing list feishu
在配置和使用飞书渠道时,您可能需要使用以下网关管理命令:
| 命令 | 说明 |
| -------------------------- | ----------------- |
| `openclaw gateway status` | 查看网关运行状态 |
| 命令 | 说明 |
|------|------|
| `openclaw gateway status` | 查看网关运行状态 |
| `openclaw gateway install` | 安装/启动网关服务 |
| `openclaw gateway stop` | 停止网关服务 |
| `openclaw gateway restart` | 重启网关服务 |
| `openclaw logs --follow` | 实时查看日志输出 |
| `openclaw gateway stop` | 停止网关服务 |
| `openclaw gateway restart` | 重启网关服务 |
| `openclaw logs --follow` | 实时查看日志输出 |
---
@@ -432,17 +424,17 @@ openclaw pairing list feishu
main: {
appId: "cli_xxx",
appSecret: "xxx",
botName: "主机器人",
botName: "主机器人"
},
backup: {
appId: "cli_yyy",
appSecret: "yyy",
botName: "备用机器人",
enabled: false, // 暂时禁用
},
},
},
},
enabled: false // 暂时禁用
}
}
}
}
}
```
@@ -463,33 +455,33 @@ openclaw pairing list feishu
主要选项:
| 配置项 | 说明 | 默认值 |
| ------------------------------------------------- | ------------------------------ | --------- |
| `channels.feishu.enabled` | 启用/禁用渠道 | `true` |
| `channels.feishu.domain` | API 域名(`feishu` 或 `lark` | `feishu` |
| `channels.feishu.accounts.<id>.appId` | 应用 App ID | - |
| `channels.feishu.accounts.<id>.appSecret` | 应用 App Secret | - |
| `channels.feishu.accounts.<id>.domain` | 单账号 API 域名覆盖 | `feishu` |
| `channels.feishu.dmPolicy` | 私聊策略 | `pairing` |
| `channels.feishu.allowFrom` | 私聊白名单open_id 列表) | - |
| `channels.feishu.groupPolicy` | 群组策略 | `open` |
| `channels.feishu.groupAllowFrom` | 群组白名单 | - |
| `channels.feishu.groups.<chat_id>.requireMention` | 是否需要 @提及 | `true` |
| `channels.feishu.groups.<chat_id>.enabled` | 是否启用该群组 | `true` |
| `channels.feishu.textChunkLimit` | 消息分块大小 | `2000` |
| `channels.feishu.mediaMaxMb` | 媒体大小限制 | `30` |
| `channels.feishu.blockStreaming` | 禁用流式输出 | `true` |
| 配置项 | 说明 | 默认值 |
|--------|------|--------|
| `channels.feishu.enabled` | 启用/禁用渠道 | `true` |
| `channels.feishu.domain` | API 域名(`feishu` 或 `lark` | `feishu` |
| `channels.feishu.accounts.<id>.appId` | 应用 App ID | - |
| `channels.feishu.accounts.<id>.appSecret` | 应用 App Secret | - |
| `channels.feishu.accounts.<id>.domain` | 单账号 API 域名覆盖 | `feishu` |
| `channels.feishu.dmPolicy` | 私聊策略 | `pairing` |
| `channels.feishu.allowFrom` | 私聊白名单open_id 列表) | - |
| `channels.feishu.groupPolicy` | 群组策略 | `open` |
| `channels.feishu.groupAllowFrom` | 群组白名单 | - |
| `channels.feishu.groups.<chat_id>.requireMention` | 是否需要 @提及 | `true` |
| `channels.feishu.groups.<chat_id>.enabled` | 是否启用该群组 | `true` |
| `channels.feishu.textChunkLimit` | 消息分块大小 | `2000` |
| `channels.feishu.mediaMaxMb` | 媒体大小限制 | `30` |
| `channels.feishu.blockStreaming` | 禁用流式输出 | `true` |
---
## dmPolicy 策略说明
| 值 | 行为 |
| ------------- | -------------------------------------------------- |
| `"pairing"` | **默认**。未知用户收到配对码,管理员批准后才能对话 |
| `"allowlist"` | 仅 `allowFrom` 列表中的用户可对话,其他静默忽略 |
| `"open"` | 允许所有人对话(需在 allowFrom 中加 `"*"` |
| `"disabled"` | 完全禁止私聊 |
| 值 | 行为 |
|----|------|
| `"pairing"` | **默认**。未知用户收到配对码,管理员批准后才能对话 |
| `"allowlist"` | 仅 `allowFrom` 列表中的用户可对话,其他静默忽略 |
| `"open"` | 允许所有人对话(需在 allowFrom 中加 `"*"` |
| `"disabled"` | 完全禁止私聊 |
---

View File

@@ -1,38 +1,38 @@
---
read_when:
- 开发 Google Chat 渠道功能
- 开发 Google Chat 渠道功能
summary: Google Chat 应用支持状态、功能和配置
title: Google Chat
x-i18n:
generated_at: "2026-02-03T07:43:39Z"
generated_at: "2026-02-01T19:20:03Z"
model: claude-opus-4-5
provider: pi
source_hash: 3b2bb116cdd12614c3d5afddd0879e9deb05c3606e3a2385cbc07f23552b357e
source_path: channels/googlechat.md
workflow: 15
workflow: 14
---
# Google ChatChat API
状态:已支持通过 Google Chat API webhooks(仅 HTTP使用私信和空间。
状态:已通过 Google Chat API webhook仅 HTTP私信和空间。
## 快速设置(新手)
1. 创建一个 Google Cloud 项目并启用 **Google Chat API**
- 前往:[Google Chat API Credentials](https://console.cloud.google.com/apis/api/chat.googleapis.com/credentials)
- 如果 API 尚未启用,请启用
2. 创建一个**服务账**
- 前往:[Google Chat API 凭据](https://console.cloud.google.com/apis/api/chat.googleapis.com/credentials)
- 如果尚未启用,请启用该 API
2. 创建**服务账**
- 点击 **Create Credentials** > **Service Account**
- 随意命名(例如 `openclaw-chat`)。
- 权限留空(点击 **Continue**)。
- 有访问权限的主账号留空(点击 **Done**)。
-访问的主体留空(点击 **Done**)。
3. 创建并下载 **JSON 密钥**
- 在服务账列表中,点击刚创建的账号
- 前往 **Keys** 标签页。
- 在服务账列表中,点击刚创建的那个
- 进入 **Keys** 标签页。
- 点击 **Add Key** > **Create new key**
- 选择 **JSON** 并点击 **Create**
4. 将下载的 JSON 文件存储在 Gateway 网关主机上(例如 `~/.openclaw/googlechat-service-account.json`)。
5. 在 [Google Cloud Console Chat Configuration](https://console.cloud.google.com/apis/api/chat.googleapis.com/hangouts-chat) 中创建一个 Google Chat 应用:
4. 将下载的 JSON 文件存储在你的 Gateway网关主机上例如 `~/.openclaw/googlechat-service-account.json`)。
5. 在 [Google Cloud Console Chat 配置](https://console.cloud.google.com/apis/api/chat.googleapis.com/hangouts-chat) 中创建 Google Chat 应用:
- 填写 **Application info**
- **App name**:(例如 `OpenClaw`
- **Avatar URL**:(例如 `https://openclaw.ai/logo.png`
@@ -40,49 +40,49 @@ x-i18n:
- 启用 **Interactive features**
-**Functionality** 下,勾选 **Join spaces and group conversations**
-**Connection settings** 下,选择 **HTTP endpoint URL**
-**Triggers** 下,选择 **Use a common HTTP endpoint URL for all triggers** 并将其设置为你的 Gateway 网关公 URL 后 `/googlechat`
- _提示运行 `openclaw status` 查看你的 Gateway 网关公 URL。_
-**Triggers** 下,选择 **Use a common HTTP endpoint URL for all triggers** 并将其设置为你的 Gateway网关公 URL 后 `/googlechat`
- _提示运行 `openclaw status` 可查找你的 Gateway网关公 URL。_
-**Visibility** 下,勾选 **Make this Chat app available to specific people and groups in &lt;Your Domain&gt;**
- 在文本框中输入你的邮箱地址(例如 `user@example.com`)。
- 点击底部的 **Save**
6. **启用应用状态**
- 保存后,**刷新页面**。
- **App status** 部分(通常在保存后位于顶部或底部附近)。
- **App status** 部分(通常在保存后位于顶部或底部附近)。
- 将状态更改为 **Live - available to users**
- 再次点击 **Save**
7. 使用服务账路径 webhook audience 配置 OpenClaw
7. 使用服务账路径 + webhook audience 配置 OpenClaw
- 环境变量:`GOOGLE_CHAT_SERVICE_ACCOUNT_FILE=/path/to/service-account.json`
- 或配置:`channels.googlechat.serviceAccountFile: "/path/to/service-account.json"`
8. 设置 webhook audience 类型值(与你的 Chat 应用配置匹配)。
9. 启动 Gateway 网关。Google Chat 将向你的 webhook 路径发送 POST 请求。
8. 设置 webhook audience 类型 + 值(与你的 Chat 应用配置匹配)。
9. 启动 Gateway网关。Google Chat 将向你的 webhook 路径发送 POST 请求。
## 添加到 Google Chat
Gateway 网关运行后,且你的邮箱已添加到可见性列表
Gateway网关运行且你的邮箱已添加到可见性列表
1. 前往 [Google Chat](https://chat.google.com/)。
2. 点击 **Direct Messages** 旁边的 **+**(加号)图标。
3. 在搜索栏(通常用于添加联系人的位置)中,输入你在 Google Cloud Console 中配置的 **App name**
- **注意**机器人*不会*出现在"Marketplace"浏览列表中,因为它是私有应用。你必须按名称搜索。
3. 在搜索栏(通常用于添加人员的地方),输入你在 Google Cloud Console 中配置的 **App name**
- **注意**:机器人*不会*出现在"Marketplace"浏览列表中,因为它是私有应用。你必须按名称搜索。
4. 从结果中选择你的机器人。
5. 点击 **Add****Chat** 开始一对一对话。
6. 发送"Hello"来触发助手!
## 公 URL仅 Webhook
## 公 URL仅 Webhook
Google Chat webhooks 需要一个公网 HTTPS 端点。为安全起见,**`/googlechat` 路径暴露到互联网**。将 OpenClaw 仪表板和其他敏感端点保留在你的私有网络上。
Google Chat webhook 需要公共 HTTPS 端点。为安全起见,**`/googlechat` 路径暴露**到互联网。将 OpenClaw 仪表板和其他敏感端点保持在私有网络上。
### 方案 ATailscale Funnel推荐
使用 Tailscale Serve 提供私有仪表板,使用 Funnel 提供公网 webhook 路径。这样可以保持 `/` 私有,同时只暴露 `/googlechat`
使用 Tailscale Serve 用于私有仪表板Funnel 用于公共 webhook 路径。这样 `/` 保持私有,暴露 `/googlechat`
1. **检查你的 Gateway 网关绑定地址:**
1. **检查你的 Gateway网关绑定在哪个地址**
```bash
ss -tlnp | grep 18789
```
记下 IP 地址(例如 `127.0.0.1`、`0.0.0.0` 或你的 Tailscale IP 如 `100.x.x.x`)。
注意 IP 地址(例如 `127.0.0.1`、`0.0.0.0` 或你的 Tailscale IP 如 `100.x.x.x`)。
2. **仅将仪表板暴露给 tailnet端口 8443**
@@ -104,8 +104,8 @@ Google Chat webhooks 需要一个公网 HTTPS 端点。为了安全起见,**
tailscale funnel --bg --set-path /googlechat http://100.106.161.80:18789/googlechat
```
4. **授权节点访问 Funnel**
如果出现提示,请访问输出中显示的授权 URL在你的 tailnet 策略中为此节点启用 Funnel。
4. **为节点授权 Funnel 访问**
如果出现提示,请访问输出中显示的授权 URL在你的 tailnet 策略中为此节点启用 Funnel。
5. **验证配置:**
```bash
@@ -113,19 +113,19 @@ Google Chat webhooks 需要一个公网 HTTPS 端点。为了安全起见,**
tailscale funnel status
```
你的公 webhook URL 将是:
你的公 webhook URL 将是:
`https://<node-name>.<tailnet>.ts.net/googlechat`
你的私有仪表板仅限 tailnet 访问:
`https://<node-name>.<tailnet>.ts.net:8443/`
在 Google Chat 应用配置中使用公 URL不带 `:8443`)。
在 Google Chat 应用配置中使用公 URL不带 `:8443`)。
> 注意:此配置在重启后会保留。如需稍后移除,运行 `tailscale funnel reset` 和 `tailscale serve reset`。
> 注意:此配置在重启后持续有效。要在之后移除,运行 `tailscale funnel reset` 和 `tailscale serve reset`。
### 方案 B反向代理Caddy
如果你使用像 Caddy 这样的反向代理,代理特定路径:
如果你使用像 Caddy 这样的反向代理,代理特定路径:
```caddy
your-domain.com {
@@ -133,31 +133,31 @@ your-domain.com {
}
```
使用此配置,任何发往 `your-domain.com/` 的请求将被忽略或返回 404而 `your-domain.com/googlechat` 安全地路由到 OpenClaw。
使用此配置, `your-domain.com/` 的任何请求将被忽略或返回 404而 `your-domain.com/googlechat` 安全地路由到 OpenClaw。
### 方案 CCloudflare Tunnel
配置你的隧道入口规则,路由 webhook 路径:
配置你的隧道入口规则,路由 webhook 路径:
- **路径**`/googlechat` -> `http://localhost:18789/googlechat`
- **默认规则**HTTP 404未找到
- **默认规则**HTTP 404Not Found
## 工作原理
1. Google Chat 向 Gateway 网关发送 webhook POST 请求。每个请求包含一个 `Authorization: Bearer <token>` 头。
2. OpenClaw 根据配置的 `audienceType` + `audience` 验证令牌
1. Google Chat 向 Gateway网关发送 webhook POST 请求。每个请求包含一个 `Authorization: Bearer <token>` 头。
2. OpenClaw 根据配置的 `audienceType` + `audience` 验证 token
- `audienceType: "app-url"` → audience 是你的 HTTPS webhook URL。
- `audienceType: "project-number"` → audience 是 Cloud 项目编号。
3. 消息按空间路由:
- 私信使用会话键 `agent:<agentId>:googlechat:dm:<spaceId>`。
- 空间使用会话键 `agent:<agentId>:googlechat:group:<spaceId>`。
4. 私信访问默认为配对模式。未知发送者会收到配对码;使用以下命令批准:
4. 私信访问默认需要配对。未知发送者会收到配对码;通过以下方式批准:
- `openclaw pairing approve googlechat <code>`
5. 群组空间默认需要 @提及。如果提及检测需要应用的用户名,请使用 `botUser`。
## 目标标识符
## 目标
使用这些标识符进行消息投递和允许列表:
使用以下标识符进行投递和允许列表:
- 私信:`users/<userId>` 或 `users/<email>`(接受邮箱地址)。
- 空间:`spaces/<spaceId>`。
@@ -173,7 +173,7 @@ your-domain.com {
audienceType: "app-url",
audience: "https://gateway.example.com/googlechat",
webhookPath: "/googlechat",
botUser: "users/1234567890", // 可选;助提及检测
botUser: "users/1234567890", // 可选;助提及检测
dm: {
policy: "pairing",
allowFrom: ["users/1234567890", "name@example.com"],
@@ -197,11 +197,11 @@ your-domain.com {
注意事项:
- 服务账号凭证也可以通过 `serviceAccount`JSON 字符串)内联传递。
- 服务账户凭据也可以通过 `serviceAccount`JSON 字符串)内联传递。
- 如果未设置 `webhookPath`,默认 webhook 路径为 `/googlechat`。
- 当 `actions.reactions` 启用时,可通过 `reactions` 工具和 `channels action` 使用表情回应。
- 当 `actions.reactions` 启用时,可通过 `reactions` 工具和 `channels action` 使用回应功能
- `typingIndicator` 支持 `none`、`message`(默认)和 `reaction`reaction 需要用户 OAuth
- 附件通过 Chat API 下载并存储在媒体管道中(大小 `mediaMaxMb` 限制)。
- 附件通过 Chat API 下载并存储在媒体管道中(大小 `mediaMaxMb` 限制)。
## 故障排除
@@ -213,15 +213,15 @@ your-domain.com {
status code: 405, reason phrase: HTTP error response: HTTP/1.1 405 Method Not Allowed
```
这意味着 webhook 处理程序未注册。常见原因:
这意味着 webhook 处理未注册。常见原因:
1. **渠道未配置**:配置中缺少 `channels.googlechat` 部分。使用以下命令验证:
1. **渠道未配置**:配置中缺少 `channels.googlechat` 部分。通过以下方式验证:
```bash
openclaw config get channels.googlechat
```
如果返回"Config path not found"添加配置(参见[配置要点](#配置要点))。
如果返回"Config path not found",添加配置(参见[配置要点](#配置要点))。
2. **插件未启用**:检查插件状态:
@@ -229,9 +229,9 @@ status code: 405, reason phrase: HTTP error response: HTTP/1.1 405 Method Not Al
openclaw plugins list | grep googlechat
```
如果显示"disabled"在配置中添加 `plugins.entries.googlechat.enabled: true`。
如果显示"disabled",在配置中添加 `plugins.entries.googlechat.enabled: true`。
3. **Gateway 网关未重启**:添加配置后,重启 Gateway 网关:
3. **Gateway网关未重启**:添加配置后,重启 Gateway网关
```bash
openclaw gateway restart
```
@@ -245,13 +245,13 @@ openclaw channels status
### 其他问题
- 检查 `openclaw channels status --probe` 查看认证错误或缺 audience 配置。
- 如果没有收到消息,请确认 Chat 应用的 webhook URL 事件订阅。
- 如果提及门控阻止了回复,将 `botUser` 设置为应用的用户资源名称并验证 `requireMention`。
- 发送测试消息时使用 `openclaw logs --follow` 查看请求是否到达 Gateway 网关。
- 检查 `openclaw channels status --probe` 查看认证错误或缺失的 audience 配置。
- 如果没有消息到达,确认 Chat 应用的 webhook URL + 事件订阅。
- 如果提及门控阻止了回复,将 `botUser` 设置为应用的用户资源名称并验证 `requireMention`。
- 发送测试消息时使用 `openclaw logs --follow` 查看请求是否到达 Gateway网关。
相关文档:
- [Gateway 网关配置](/gateway/configuration)
- [Gateway网关配置](/gateway/configuration)
- [安全](/gateway/security)
- [表情回应](/tools/reactions)
- [回应](/tools/reactions)

View File

@@ -1,38 +1,38 @@
---
read_when:
- 开发 Telegram 或 grammY 相关功能
summary: 通过 grammY 集成 Telegram Bot API,附设置说明
- 开发 Telegram 或 grammY 相关功能
summary: 通过 grammY 集成 Telegram Bot API设置说明
title: grammY
x-i18n:
generated_at: "2026-02-03T10:03:55Z"
generated_at: "2026-02-01T19:20:16Z"
model: claude-opus-4-5
provider: pi
source_hash: ea7ef23e6d77801f4ef5fc56685ef4470f79f5aecab448d644a72cbab53521b7
source_path: channels/grammy.md
workflow: 15
workflow: 14
---
# grammY 集成Telegram Bot API
# 为什么选择 grammY
- 以 TS 为核心的 Bot API 客户端,内置长轮询 + webhook 辅助工具、中间件、错误处理速率限制器。
- 媒体处理辅助工具比手动编写 fetch + FormData 更简洁;支持所有 Bot API 方法。
- 可扩展:通过自定义 fetch 支持代理,可选的会话中间件,类型安全的上下文。
- TypeScript 优先的 Bot API 客户端,内置长轮询 + webhook 辅助工具、中间件、错误处理速率限制器。
- 比手动编写 fetch + FormData 更简洁的媒体辅助工具;支持所有 Bot API 方法。
- 可扩展:通过自定义 fetch 支持代理,会话中间件(可选),类型安全的上下文。
# 我们发布的内容
# 已交付的功能
- **单一客户端路径:** 移除了基于 fetch 的实现grammY 现在是唯一的 Telegram 客户端(发送 + Gateway 网关),默认启用 grammY throttler。
- **Gateway 网关:** `monitorTelegramProvider` 构建 grammY `Bot`,接入 mention/allowlist 网关控制,通过 `getFile`/`download` 下载媒体,并使用 `sendMessage/sendPhoto/sendVideo/sendAudio/sendDocument` 发送回复。通过 `webhookCallback` 支持长轮询或 webhook。
- **单一客户端路径:** 基于 fetch 的实现已移除grammY 现在是唯一的 Telegram 客户端(发送 + Gateway网关默认启用 grammY throttler。
- **Gateway网关** `monitorTelegramProvider` 构建一个 grammY `Bot`,接入提及/允许列表门控、通过 `getFile`/`download` 下载媒体,并通过 `sendMessage/sendPhoto/sendVideo/sendAudio/sendDocument` 投递回复。支持通过 `webhookCallback` 进行长轮询或 webhook。
- **代理:** 可选的 `channels.telegram.proxy` 通过 grammY 的 `client.baseFetch` 使用 `undici.ProxyAgent`
- **Webhook 支持:** `webhook-set.ts` 封装了 `setWebhook/deleteWebhook``webhook.ts` 托管回调支持健康检查优雅关闭。当设置了 `channels.telegram.webhookUrl` + `channels.telegram.webhookSecret`Gateway 网关启用 webhook 模式(否则使用长轮询)。
- **会话:** 私聊折叠到智能体主会话(`agent:<agentId>:<mainKey>`);群组使用 `agent:<agentId>:telegram:group:<chatId>`;回复路由回同一渠道。
- **配置选项:** `channels.telegram.botToken``channels.telegram.dmPolicy``channels.telegram.groups`allowlist + mention 默认值)、`channels.telegram.allowFrom``channels.telegram.groupAllowFrom``channels.telegram.groupPolicy``channels.telegram.mediaMaxMb``channels.telegram.linkPreview``channels.telegram.proxy``channels.telegram.webhookSecret``channels.telegram.webhookUrl`
- **Webhook 支持:** `webhook-set.ts` 封装了 `setWebhook/deleteWebhook``webhook.ts` 托管回调支持健康检查 + 优雅关闭。当设置了 `channels.telegram.webhookUrl` + `channels.telegram.webhookSecret` Gateway网关启用 webhook 模式(否则使用长轮询)。
- **会话:** 私聊合并到智能体主会话(`agent:<agentId>:<mainKey>`);群组使用 `agent:<agentId>:telegram:group:<chatId>`;回复路由回同一渠道。
- **配置选项:** `channels.telegram.botToken``channels.telegram.dmPolicy``channels.telegram.groups`允许列表 + 提及默认值)、`channels.telegram.allowFrom``channels.telegram.groupAllowFrom``channels.telegram.groupPolicy``channels.telegram.mediaMaxMb``channels.telegram.linkPreview``channels.telegram.proxy``channels.telegram.webhookSecret``channels.telegram.webhookUrl`
- **草稿流式传输:** 可选的 `channels.telegram.streamMode` 在私有话题聊天中使用 `sendMessageDraft`Bot API 9.3+)。这与渠道分块流式传输是分开的。
- **测试:** grammY mock 覆盖了私信 + 群组 mention 网关控制和出站发送;欢迎添加更多媒体/webhook 测试用例。
- **测试:** grammY mock 覆盖了私信 + 群组提及门控和出站发送;欢迎更多媒体/webhook 测试用例。
解决问题
讨论问题
- 如果遇到 Bot API 429 错误,考虑使用可选的 grammY 插件throttler
- 添加更多结构化媒体测试(贴纸、语音消息)。
- 使 webhook 监听端口可配置(目前固定为 8787除非通过 Gateway 网关配置)。
- 添加更多结构化媒体测试(贴纸、语音消息)。
- 使 webhook 监听端口可配置(目前固定为 8787除非通过 Gateway网关接入)。

View File

@@ -1,29 +1,29 @@
---
read_when:
- 设置 iMessage 支持
- 调试 iMessage 发送/接
summary: 通过 imsg基于 stdio 的 JSON-RPC实现 iMessage 支持、设置 chat_id 路由
- 调试 iMessage 收
summary: 通过 imsg基于 stdio 的 JSON-RPC实现 iMessage 支持、设置 chat_id 路由
title: iMessage
x-i18n:
generated_at: "2026-02-03T07:44:18Z"
generated_at: "2026-02-01T19:21:07Z"
model: claude-opus-4-5
provider: pi
source_hash: bc19756a42ead80a0845f18c4830c3f1f40948f69b2b016a4026598cfb8fef0d
source_path: channels/imessage.md
workflow: 15
workflow: 14
---
# iMessage (imsg)
# iMessageimsg
状态:外部 CLI 集成。Gateway 网关生成 `imsg rpc`(基于 stdio 的 JSON-RPC
状态:外部 CLI 集成。Gateway网关启动 `imsg rpc`(基于 stdio 的 JSON-RPC
## 快速设置(新手)
1. 确保此 Mac 上已登录"信息"。
1. 确保此 Mac 上"信息"已登录
2. 安装 `imsg`
- `brew install steipete/tap/imsg`
3. 配置 OpenClaw 的 `channels.imessage.cliPath``channels.imessage.dbPath`
4. 启动 Gateway 网关并批准所有 macOS 提示(自动化 + 完全磁盘访问权限)。
4. 启动 Gateway网关并批准所有 macOS 提示(自动化 + 完全磁盘访问权限)。
最小配置:
@@ -39,18 +39,18 @@ x-i18n:
}
```
## 简介
## 它是什么
- 基于 macOS 上 `imsg` 的 iMessage 渠道。
- 确定性路由:回复始终返回到 iMessage。
- macOS 上 `imsg` 支持的 iMessage 渠道。
- 确定性路由:回复始终发回 iMessage。
- 私信共享智能体的主会话;群组是隔离的(`agent:<agentId>:imessage:group:<chat_id>`)。
- 如果多参与者会话`is_group=false` 到达,你仍使用 `channels.imessage.groups` `chat_id` 隔离(参见下方"类群组会话")。
- 如果多参与者线程`is_group=false` 到达,你仍然可以通过 `chat_id` 使用 `channels.imessage.groups` 隔离(参见下方"类群组线程")。
## 配置写入
默认情况下iMessage 允许写入由 `/config set|unset` 触发的配置更新(需要 `commands.config: true`)。
默认情况下iMessage 允许通过 `/config set|unset` 触发的配置更新写入(需要 `commands.config: true`)。
禁用方式
通过以下方式禁用:
```json5
{
@@ -60,31 +60,31 @@ x-i18n:
## 要求
- 已登录"信息"的 macOS
- OpenClaw + `imsg` 完全磁盘访问权限(访问"信息"数据库)。
- macOS 且"信息"已登录。
- OpenClaw + `imsg` 需要完全磁盘访问权限(访问 Messages 数据库)。
- 发送时需要自动化权限。
- `channels.imessage.cliPath` 可以指向任何代理 stdin/stdout 的命令(例如,通过 SSH 连接到另一台 Mac 并运行 `imsg rpc` 的包装脚本)。
## 设置(快速路径)
1. 确保此 Mac 上已登录"信息"。
2. 配置 iMessage 并启动 Gateway 网关。
1. 确保此 Mac 上"信息"已登录
2. 配置 iMessage 并启动 Gateway网关。
### 专用机器人 macOS 用户(用于隔离身份)
如果你希望机器人从**独立的 iMessage 身份**发送(并保持你的个人"信息"整洁),请使用专用 Apple ID + 专用 macOS 用户。
如果你希望机器人从一个**独立的 iMessage 身份**发送消息(并保持你的个人"信息"整洁),请使用专用 Apple ID + 专用 macOS 用户。
1. 创建专用 Apple ID例如`my-cool-bot@icloud.com`)。
- Apple 可能需要电话号码进行验证 / 2FA
2. 创建 macOS 用户(例如:`openclawhome`)并登录。
1. 创建一个专用 Apple ID例如`my-cool-bot@icloud.com`)。
- Apple 可能需要手机号码进行验证/双重认证
2. 创建一个 macOS 用户(例如:`openclawhome`)并登录。
3. 在该 macOS 用户中打开"信息"并使用机器人 Apple ID 登录 iMessage。
4. 启用远程登录(系统设置 → 通用 → 共享 → 远程登录)。
5. 安装 `imsg`
- `brew install steipete/tap/imsg`
6. 设置 SSH 使 `ssh <bot-macos-user>@localhost true` 无需密码即可工作。
7.`channels.imessage.accounts.bot.cliPath` 指向以机器人用户身份运行 `imsg` 的 SSH 包装脚本。
7.`channels.imessage.accounts.bot.cliPath` 指向一个以机器人用户身份运行 `imsg` 的 SSH 包装脚本。
首次运行注意事项:发送/接收可能需要在*机器人 macOS 用户*中进行 GUI 批(自动化 + 完全磁盘访问权限)。如果 `imsg rpc` 看起来卡住或退出,请登录该用户(屏幕共享很有帮助),运行一次 `imsg chats --limit 1` / `imsg send ...`,批准提示,然后重试。
首次运行注意事项:发送/接收可能需要在*机器人 macOS 用户*中进行 GUI 批(自动化 + 完全磁盘访问权限)。如果 `imsg rpc` 看起来卡住或退出,请登录该用户(屏幕共享很有帮助),运行一次 `imsg chats --limit 1` / `imsg send ...`,批准提示,然后重试。
示例包装脚本(`chmod +x`)。将 `<bot-macos-user>` 替换为你的实际 macOS 用户名:
@@ -92,7 +92,7 @@ x-i18n:
#!/usr/bin/env bash
set -euo pipefail
# Run an interactive SSH once first to accept host keys:
# 先运行一次交互式 SSH 以接受主机密钥:
# ssh <bot-macos-user>@localhost true
exec /usr/bin/ssh -o BatchMode=yes -o ConnectTimeout=5 -T <bot-macos-user>@localhost \
"/usr/local/bin/imsg" "$@"
@@ -118,11 +118,11 @@ exec /usr/bin/ssh -o BatchMode=yes -o ConnectTimeout=5 -T <bot-macos-user>@local
}
```
对于单账户设置,使用扁平选项(`channels.imessage.cliPath``channels.imessage.dbPath`)而不是 `accounts` 映射。
对于单账户设置,使用扁平选项(`channels.imessage.cliPath``channels.imessage.dbPath`)而 `accounts` 映射。
### 远程/SSH 变体(可选)
如果你想在另一台 Mac 上使用 iMessage`channels.imessage.cliPath` 设置为通过 SSH 在远程 macOS 主机上运行 `imsg` 的包装脚本。OpenClaw 只需要 stdio。
如果你想在另一台 Mac 上使用 iMessage`channels.imessage.cliPath` 设置为通过 SSH 在远程 macOS 主机上运行 `imsg` 的包装脚本。OpenClaw 只需要 stdio。
示例包装脚本:
@@ -131,36 +131,36 @@ exec /usr/bin/ssh -o BatchMode=yes -o ConnectTimeout=5 -T <bot-macos-user>@local
exec ssh -T gateway-host imsg "$@"
```
**远程附件:**`cliPath` 通过 SSH 指向远程主机时,"信息"数据库中的附件路径引用的是远程机器上的文件。OpenClaw 可以通过设置 `channels.imessage.remoteHost` 自动通过 SCP 获取这些文件:
**远程附件:**`cliPath` 通过 SSH 指向远程主机时,Messages 数据库中的附件路径引用的是远程机器上的文件。OpenClaw 可以通过设置 `channels.imessage.remoteHost` 自动通过 SCP 获取这些文件:
```json5
{
channels: {
imessage: {
cliPath: "~/imsg-ssh", // SSH wrapper to remote Mac
remoteHost: "user@gateway-host", // for SCP file transfer
cliPath: "~/imsg-ssh", // 到远程 Mac 的 SSH 包装脚本
remoteHost: "user@gateway-host", // 用于 SCP 文件传输
includeAttachments: true,
},
},
}
```
如果未设置 `remoteHost`OpenClaw 会尝试通过解析包装脚本中的 SSH 命令自动检测。建议显式配置以提高可靠性。
如果未设置 `remoteHost`OpenClaw 会尝试通过解析包装脚本中的 SSH 命令自动检测。建议显式配置以确保可靠性。
#### 通过 Tailscale 连接远程 Mac示例
如果 Gateway 网关运行在 Linux 主机/虚拟机上但 iMessage 必须运行在 Mac 上Tailscale 是最简单的桥接方Gateway 网关通过 tailnet 与 Mac 通信,通过 SSH 运行 `imsg`,并通过 SCP 获取附件。
如果 Gateway网关运行在 Linux 主机/虚拟机上但 iMessage 必须运行在 Mac 上Tailscale 是最简单的桥接方Gateway网关通过 tailnet 与 Mac 通信,通过 SSH 运行 `imsg`,并通过 SCP 传回附件。
架构:
```
┌──────────────────────────────┐ SSH (imsg rpc) ┌──────────────────────────┐
│ Gateway host (Linux/VM) │──────────────────────────────────▶│ Mac with Messages + imsg │
│ - openclaw gateway │ SCP (attachments) │ - Messages signed in
│ - channels.imessage.cliPath │◀──────────────────────────────────│ - Remote Login enabled
│ Gateway网关主机(Linux/VM │──────────────────────────────────▶│ 装有 Messages + imsg 的 Mac
│ - openclaw gateway │ SCP(附件) │ - Messages 已登录
│ - channels.imessage.cliPath │◀──────────────────────────────────│ - 远程登录已启用
└──────────────────────────────┘ └──────────────────────────┘
│ Tailscale tailnet (hostname or 100.x.y.z)
│ Tailscale tailnet(主机名或 100.x.y.z
user@gateway-host
```
@@ -190,19 +190,19 @@ exec ssh -T bot@mac-mini.tailnet-1234.ts.net imsg "$@"
注意事项:
- 确保 Mac 已登录"信息"并已启用远程登录。
- 确保 Mac 已登录"信息"远程登录已启用
- 使用 SSH 密钥使 `ssh bot@mac-mini.tailnet-1234.ts.net` 无需提示即可工作。
- `remoteHost` 应与 SSH 目标匹配,以便 SCP 可以获取附件。
多账户支持:使用 `channels.imessage.accounts` 配置每个账户可选的 `name`参见 [`gateway/configuration`](/gateway/configuration#telegramaccounts--discordaccounts--slackaccounts--signalaccounts--imessageaccounts) 了解共享模式。不要提交 `~/.openclaw/openclaw.json`(它通常包含令牌)。
多账户支持:使用 `channels.imessage.accounts`每个账户配置独立选项和可选的 `name`共享模式请参阅 [`gateway/configuration`](/gateway/configuration#telegramaccounts--discordaccounts--slackaccounts--signalaccounts--imessageaccounts)。不要提交 `~/.openclaw/openclaw.json`(它通常包含 token)。
## 访问控制(私信 + 群组)
私信:
- 默认:`channels.imessage.dmPolicy = "pairing"`
- 未知发送者会收到配对码;消息在批准会被忽略(配对码 1 小时后过期)。
- 批准方式
- 未知发送者会收到配对码;在批准之前消息会被忽略(配对码 1 小时后过期)。
- 通过以下方式批准:
- `openclaw pairing list imessage`
- `openclaw pairing approve imessage <CODE>`
- 配对是 iMessage 私信的默认令牌交换方式。详情:[配对](/start/pairing)
@@ -210,23 +210,23 @@ exec ssh -T bot@mac-mini.tailnet-1234.ts.net imsg "$@"
群组:
- `channels.imessage.groupPolicy = open | allowlist | disabled`
- 设置 `allowlist` 时,`channels.imessage.groupAllowFrom` 控制谁可以在群组中触发。
- 提及检测使用 `agents.list[].groupChat.mentionPatterns`(或 `messages.groupChat.mentionPatterns`),因为 iMessage 没有原生提及元数据。
- 设置 `allowlist` 时,`channels.imessage.groupAllowFrom` 控制谁可以在群组中触发。
- 提及门控使用 `agents.list[].groupChat.mentionPatterns`(或 `messages.groupChat.mentionPatterns`),因为 iMessage 没有原生提及元数据。
- 多智能体覆盖:在 `agents.list[].groupChat.mentionPatterns` 上设置每个智能体的模式。
## 工作原理(行为)
- `imsg` 流式传输消息事件Gateway 网关将它们规范化为共享渠道信封。
- 回复始终路由回相同的 chat id 或 handle
- `imsg` 流式传输消息事件Gateway网关将其标准化为共享渠道信封。
- 回复始终路由回同一个 chat id 或用户名
## 类群组会话`is_group=false`
## 类群组线程`is_group=false`
些 iMessage 会话可能有多个参与者,但根据"信息"存储聊天标识符的方式,仍以 `is_group=false` 到达。
些 iMessage 线程可能有多个参与者,但由于"信息"存储聊天标识符的方式,仍`is_group=false` 到达。
如果你在 `channels.imessage.groups` 下显式配置了 `chat_id`OpenClaw 会将该会话视为"群组"用于:
如果你在 `channels.imessage.groups` 下显式配置了一个 `chat_id`OpenClaw 会将该线程视为"群组"用于:
- 会话隔离(独立的 `agent:<agentId>:imessage:group:<chat_id>` 会话键)
- 群组允许列表 / 提及检测行为
- 群组允许列表/提及门控行为
示例:
@@ -244,27 +244,27 @@ exec ssh -T bot@mac-mini.tailnet-1234.ts.net imsg "$@"
}
```
当你想为特定会话使用隔离的个性/模型时很有用(参见[多智能体路由](/concepts/multi-agent))。关文件系统隔离,参见[沙箱隔离](/gateway/sandboxing)。
当你想为特定线程使用隔离的个性/模型时很有用(参见[多智能体路由](/concepts/multi-agent))。关文件系统隔离,请参阅[沙箱](/gateway/sandboxing)。
## 媒体 + 限制
- 通过 `channels.imessage.includeAttachments` 可选附件摄取
- 通过 `channels.imessage.mediaMaxMb` 设置媒体上限
- 通过 `channels.imessage.includeAttachments` 可选接收附件。
- 媒体上限通过 `channels.imessage.mediaMaxMb` 设置。
## 限制
- 出站文本按 `channels.imessage.textChunkLimit` 分块(默认 4000
- 可选换行分块:设置 `channels.imessage.chunkMode="newline"` 在长度分块前按空行(段落边界)分割。
- 媒体上传 `channels.imessage.mediaMaxMb` 限制(默认 16
- 可选换行分块:设置 `channels.imessage.chunkMode="newline"`长度分块前按空行(段落边界)分割。
- 媒体上传上限由 `channels.imessage.mediaMaxMb` 限制(默认 16
## 寻址 / 投递目标
优先使用 `chat_id` 进行稳定路由:
推荐使用 `chat_id` 进行稳定路由:
- `chat_id:123`(推荐)
- `chat_guid:...`
- `chat_identifier:...`
- 直接 handle`imessage:+1555` / `sms:+1555` / `user@example.com`
- 直接用户名`imessage:+1555` / `sms:+1555` / `user@example.com`
列出聊天:
@@ -279,22 +279,22 @@ imsg chats --limit 20
提供商选项:
- `channels.imessage.enabled`:启用/禁用渠道启动。
- `channels.imessage.cliPath``imsg` 路径。
- `channels.imessage.dbPath`"信息"数据库路径。
- `channels.imessage.remoteHost`:当 `cliPath` 指向远程 Mac 时用于 SCP 附件传输的 SSH 主机(例如 `user@gateway-host`)。未设置从 SSH 包装脚本自动检测。
- `channels.imessage.cliPath``imsg` 路径。
- `channels.imessage.dbPath`Messages 数据库路径。
- `channels.imessage.remoteHost`:当 `cliPath` 指向远程 Mac 时用于 SCP 附件传输的 SSH 主机(例如 `user@gateway-host`)。未设置从 SSH 包装脚本自动检测。
- `channels.imessage.service``imessage | sms | auto`
- `channels.imessage.region`短信区域。
- `channels.imessage.region`SMS 区域。
- `channels.imessage.dmPolicy``pairing | allowlist | open | disabled`默认pairing
- `channels.imessage.allowFrom`:私信允许列表(handle、邮箱、E.164 号码或 `chat_id:*`)。`open` 需要 `"*"`。iMessage 没有用户名;使用 handle 或聊天目标。
- `channels.imessage.allowFrom`:私信允许列表(用户名、邮箱、E.164 号码或 `chat_id:*`)。`open` 需要 `"*"`。iMessage 没有用户名;使用用户名或聊天目标。
- `channels.imessage.groupPolicy``open | allowlist | disabled`默认allowlist
- `channels.imessage.groupAllowFrom`:群组发送者允许列表。
- `channels.imessage.historyLimit` / `channels.imessage.accounts.*.historyLimit`为上下文包含的最大群组消息数0 禁用)。
- `channels.imessage.dmHistoryLimit`:私信历史限制(用户轮次)。用户覆盖:`channels.imessage.dms["<handle>"].historyLimit`
- `channels.imessage.groups`群组默认值 + 允许列表(使用 `"*"` 作为全局默认值)。
- `channels.imessage.includeAttachments`:将附件摄取到上下文。
- `channels.imessage.historyLimit` / `channels.imessage.accounts.*.historyLimit`包含为上下文的最大群组消息数0 禁用)。
- `channels.imessage.dmHistoryLimit`:私信历史限制(用户回合数)。用户覆盖:`channels.imessage.dms["<handle>"].historyLimit`
- `channels.imessage.groups`群组默认值 + 允许列表(使用 `"*"` 设置全局默认值)。
- `channels.imessage.includeAttachments`:将附件接收到上下文
- `channels.imessage.mediaMaxMb`:入站/出站媒体上限MB
- `channels.imessage.textChunkLimit`:出站分块大小(字符)。
- `channels.imessage.chunkMode``length`(默认)或 `newline`长度分块前按空行(段落边界)分割。
- `channels.imessage.chunkMode``length`(默认)或 `newline`,在按长度分块前按空行(段落边界)分割。
相关全局选项:

View File

@@ -5,49 +5,46 @@ read_when:
summary: OpenClaw 可连接的消息平台
title: 聊天渠道
x-i18n:
generated_at: "2026-02-03T07:43:27Z"
generated_at: "2026-02-01T19:21:22Z"
model: claude-opus-4-5
provider: pi
source_hash: 2632863def6dee97e0fa8b931762f0969174fd4fb22303a00dcd46527fe4a141
source_path: channels/index.md
workflow: 15
workflow: 14
---
# 聊天渠道
OpenClaw 可以在你已经使用的任何聊天应用上与你交流。每个渠道通过 Gateway 网关连接。
所有渠道都支持文本;媒体和表情回应的支持因渠道而异。
OpenClaw 可以在你已经使用的任何聊天应用上与你对话。每个渠道通过 Gateway网关连接。所有渠道都支持文本;媒体和回应功能因渠道而异。
## 支持的渠道
- [WhatsApp](/channels/whatsapp) — 最受欢迎;使用 Baileys需要二维码配对。
- [WhatsApp](/channels/whatsapp) — 最受欢迎;使用 Baileys需要二维码配对。
- [Telegram](/channels/telegram) — 通过 grammY 使用 Bot API支持群组。
- [Discord](/channels/discord) — Discord Bot API + Gateway支持服务器、频道和私信。
- [Discord](/channels/discord) — Discord Bot API + Gateway网关;支持服务器、频道和私信。
- [Slack](/channels/slack) — Bolt SDK工作区应用。
- [飞书](/channels/feishu) — 飞书Lark机器人插件需单独安装
- [Google Chat](/channels/googlechat) — 通过 HTTP webhook 的 Google Chat API 应用。
- [Google Chat](/channels/googlechat) — 通过 HTTP webhook 使用 Google Chat API 应用
- [Mattermost](/channels/mattermost) — Bot API + WebSocket频道、群组、私信插件需单独安装
- [Signal](/channels/signal) — signal-cli注重隐私。
- [BlueBubbles](/channels/bluebubbles) — **推荐用于 iMessage**;使用 BlueBubbles macOS 服务器 REST API功能完整编辑、撤回、特效、回应、群组管理——编辑功能在 macOS 26 Tahoe 上目前不可用)。
- [iMessage(旧版)](/channels/imessage) — 通过 imsg CLI 的旧版 macOS 集成(已弃用,新设置使用 BlueBubbles
- [iMessage](/channels/imessage) — 仅限 macOS通过 imsg 原生集成(旧版,新设置建议使用 BlueBubbles
- [Microsoft Teams](/channels/msteams) — Bot Framework企业支持插件需单独安装
- [LINE](/channels/line) — LINE Messaging API 机器人(插件,需单独安装)。
- [Nextcloud Talk](/channels/nextcloud-talk) — 通过 Nextcloud Talk 的自托管聊天(插件,需单独安装)。
- [Matrix](/channels/matrix) — Matrix 协议(插件,需单独安装)。
- [Nostr](/channels/nostr) — 通过 NIP-04 的去中心化私信(插件,需单独安装)。
- [Tlon](/channels/tlon) — 基于 Urbit 的消息应用(插件,需单独安装)。
- [Tlon](/channels/tlon) — 基于 Urbit 的通讯工具(插件,需单独安装)。
- [Twitch](/channels/twitch) — 通过 IRC 连接的 Twitch 聊天(插件,需单独安装)。
- [Zalo](/channels/zalo) — Zalo Bot API越南流行的消息应用(插件,需单独安装)。
- [Zalo Personal](/channels/zalouser) — 通过二维码登录的 Zalo 个人账(插件,需单独安装)。
- [WebChat](/web/webchat) — 基于 WebSocket 的 Gateway 网关 WebChat 界面
- [Zalo](/channels/zalo) — Zalo Bot API越南流行的通讯工具(插件,需单独安装)。
- [Zalo Personal](/channels/zalouser) — 通过二维码登录的 Zalo 个人账(插件,需单独安装)。
- [WebChat](/web/webchat) — 通过 WebSocket 的 Gateway网关 WebChat UI
## 注意事项
- 渠道可以同时运行;配置多个渠道后OpenClaw 会按聊天进行路由。
- 最快的设置方式通常是 **Telegram**(简单的机器人令牌。WhatsApp 需要二维码配对
并在磁盘上存储更多状态。
- 渠道可以同时运行;配置多个渠道后 OpenClaw 会按聊天路由。
- 最快的设置通常是 **Telegram**(简单的 bot token。WhatsApp 需要二维码配对并在磁盘上存储更多状态。
- 群组行为因渠道而异;参见[群组](/concepts/groups)。
- 为安全起见,私信配对和允许列表会被强制执行;参见[安全](/gateway/security)。
- Telegram 内部机制[grammY 说明](/channels/grammy)。
- 私信配对和允许列表出于安全考虑强制执行;参见[安全](/gateway/security)。
- Telegram 内部实现[grammY 说明](/channels/grammy)。
- 故障排除:[渠道故障排除](/channels/troubleshooting)。
- 模型提供商单独记录;参见[模型提供商](/providers/models)。
- 模型提供商单独文档化;参见[模型提供商](/providers/models)。

View File

@@ -1,26 +1,26 @@
---
read_when:
- 你想将 OpenClaw 连接到 LINE
- 你需要配置 LINE webhook + 凭
-想了解 LINE 特的消息选项
summary: LINE Messaging API 插件的配置、置和使用方法
- 你需要 LINE webhook + 凭据设置
-需要 LINE 特的消息选项
summary: LINE Messaging API 插件置、置和使用
title: LINE
x-i18n:
generated_at: "2026-02-03T07:43:38Z"
generated_at: "2026-02-01T19:21:38Z"
model: claude-opus-4-5
provider: pi
source_hash: 8fbac126786f95b9454f3cc61906c2798393a8d7914e787d3755c020c7ab2da6
source_path: channels/line.md
workflow: 15
workflow: 14
---
# LINE插件
LINE 通过 LINE Messaging API 连接到 OpenClaw。插件作为 webhook 接收器在 Gateway 网关上运行,使用你的 channel access token + channel secret 进行身份验证。
LINE 通过 LINE Messaging API 连接到 OpenClaw。插件作为 Gateway网关上的 webhook 接收器运行,使用你的频道访问 token + 频道密钥进行认证。
状态通过插件支持。支持私信、群聊、媒体、位置、Flex 消息、模板消息和快回复。不支持表情回应和话题回复
状态通过插件支持。支持私信、群聊、媒体、位置、Flex 消息、模板消息和快回复。不支持回应和线程
## 需要安装插件
## 需要插件
安装 LINE 插件:
@@ -34,20 +34,20 @@ openclaw plugins install @openclaw/line
openclaw plugins install ./extensions/line
```
## 配置步骤
## 设置
1. 创建 LINE Developers 账户并打开控制台:
https://developers.line.biz/console/
2. 创建(或选择)一个 Provider 并添加 **Messaging API** 道。
3.道设置中复制 **Channel access token****Channel secret**
2. 创建(或选择)一个 Provider 并添加一个 **Messaging API** 道。
3.道设置中复制 **Channel access token****Channel secret**
4. 在 Messaging API 设置中启用 **Use webhook**
5. 将 webhook URL 设置为你的 Gateway 网关端点(必须使用 HTTPS
5. 将 webhook URL 设置为你的 Gateway网关端点需要 HTTPS
```
https://gateway-host/line/webhook
```
Gateway 网关响应 LINE 的 webhook 验证GET和入站事件POST。如果你需要自定义路径请设置 `channels.line.webhookPath``channels.line.accounts.<id>.webhookPath` 并相应更新 URL。
Gateway网关响应 LINE 的 webhook 验证GET和入站事件POST。如果你需要自定义路径请设置 `channels.line.webhookPath``channels.line.accounts.<id>.webhookPath` 并相应更新 URL。
## 配置
@@ -66,12 +66,12 @@ Gateway 网关会响应 LINE 的 webhook 验证GET和入站事件POST
}
```
环境变量(仅默认账户):
环境变量(仅默认账户):
- `LINE_CHANNEL_ACCESS_TOKEN`
- `LINE_CHANNEL_SECRET`
Token/secret 文件:
Token/密钥文件:
```json5
{
@@ -84,7 +84,7 @@ Token/secret 文件:
}
```
多账户配置
多账户:
```json5
{
@@ -104,7 +104,7 @@ Token/secret 文件:
## 访问控制
私信默认使用配对模式。未知发送者会收到配对码,其消息在获得批准前会被忽略。
私信默认需要配对。未知发送者会收到配对码,在批准之前其消息会被忽略。
```bash
openclaw pairing list line
@@ -114,12 +114,12 @@ openclaw pairing approve line <CODE>
允许列表和策略:
- `channels.line.dmPolicy``pairing | allowlist | open | disabled`
- `channels.line.allowFrom`:私信的允许列表 LINE 用户 ID
- `channels.line.allowFrom`:私信的允许 LINE 用户 ID 列表
- `channels.line.groupPolicy``allowlist | open | disabled`
- `channels.line.groupAllowFrom`:群组的允许列表 LINE 用户 ID
- 群组覆盖:`channels.line.groups.<groupId>.allowFrom`
- `channels.line.groupAllowFrom`:群组的允许 LINE 用户 ID 列表
- 群组覆盖:`channels.line.groups.<groupId>.allowFrom`
LINE ID 区分大小写。有效 ID 格式如下:
LINE ID 区分大小写。有效 ID 格式如下:
- 用户:`U` + 32 位十六进制字符
- 群组:`C` + 32 位十六进制字符
@@ -127,14 +127,14 @@ LINE ID 区分大小写。有效 ID 格式如下:
## 消息行为
- 文本 5000 字符分块。
- Markdown 格式会被除;代码块和表格会尽可能转换为 Flex 卡片。
- 流式响应会被缓冲;智能体处理时,LINE 会收到完整分块并显示加载动画。
- 媒体下载 `channels.line.mediaMaxMb` 限制(默认 10
- 文本 5000 字符分块。
- Markdown 格式会被除;代码块和表格在可能时会转换为 Flex 卡片。
- 流式响应会被缓冲;智能体工作时 LINE 接收完整分块并显示加载动画。
- 媒体下载上限由 `channels.line.mediaMaxMb` 限制(默认 10
## 渠道数据(富消息)
使用 `channelData.line` 发送快回复、位置、Flex 卡片或模板消息。
使用 `channelData.line` 发送快回复、位置、Flex 卡片或模板消息。
```json5
{
@@ -151,7 +151,7 @@ LINE ID 区分大小写。有效 ID 格式如下:
flexMessage: {
altText: "Status card",
contents: {
/* Flex payload */
/* Flex 负载 */
},
},
templateMessage: {
@@ -167,7 +167,7 @@ LINE ID 区分大小写。有效 ID 格式如下:
}
```
LINE 插件还提供 `/card` 命令用于 Flex 消息预设:
LINE 插件还附带一个 `/card` 命令用于 Flex 消息预设:
```
/card info "Welcome" "Thanks for joining!"
@@ -175,6 +175,6 @@ LINE 插件还提供 `/card` 命令用于 Flex 消息预设:
## 故障排除
- **Webhook 验证失败:** 确保 webhook URL 使用 HTTPS 且 `channelSecret` 与 LINE 控制台中的一致
- **没有入站事件:** 确认 webhook 路径与 `channels.line.webhookPath` 匹配且 Gateway 网关可从 LINE 访问。
- **媒体下载错误:** 如果媒体超过默认限制,请提高 `channels.line.mediaMaxMb`
- **Webhook 验证失败:** 确保 webhook URL HTTPS 且 `channelSecret` 与 LINE 控制台匹配
- **没有入站事件:** 确认 webhook 路径与 `channels.line.webhookPath` 匹配且 Gateway网关可从 LINE 访问。
- **媒体下载错误:** 如果媒体超过默认限制,请增大 `channels.line.mediaMaxMb`

View File

@@ -4,25 +4,25 @@ read_when:
summary: Matrix 支持状态、功能和配置
title: Matrix
x-i18n:
generated_at: "2026-02-03T07:44:02Z"
generated_at: "2026-02-01T19:22:24Z"
model: claude-opus-4-5
provider: pi
source_hash: b276b5263593c766e7be6549abbb27927177e7b51cfd297b4825965372513ee4
source_path: channels/matrix.md
workflow: 15
workflow: 14
---
# Matrix插件
Matrix 是一个开放去中心化消息协议。OpenClaw Matrix **用户**身份连接到任主服务器,因此你需要为机器人创建一个 Matrix 账户。登录后你可以直接私信机器人或邀请它加入房间Matrix"群组"。Beeper 也是一个有效的客户端选项,但它需要启用 E2EE
Matrix 是一个开放去中心化消息协议。OpenClaw 作为 Matrix **用户**连接到任主服务器,因此你需要为机器人创建一个 Matrix 账户。登录后你可以直接私信机器人或邀请它加入房间Matrix"群组"。Beeper 也是一个可用的客户端选项,但它需要启用端到端加密
状态:通过插件(@vector-im/matrix-bot-sdk支持。支持私信、房间、话题、媒体、表情回应、投票(发送 + poll-start 为文本)、位置和 E2EE(需要加密支持)。
状态:通过插件支持@vector-im/matrix-bot-sdk。支持私信、房间、线程、媒体、回应、投票(发送 + poll-start 为文本)、位置和端到端加密(需要加密支持)。
## 需要插件
Matrix 作为插件提供,不包含在核心安装中。
Matrix 作为插件发布,不包含在核心安装中。
通过 CLI 安装npm 仓库
通过 CLI 安装npm 注册表
```bash
openclaw plugins install @openclaw/matrix
@@ -34,7 +34,7 @@ openclaw plugins install @openclaw/matrix
openclaw plugins install ./extensions/matrix
```
如果你在配置/新手引导期间选择 Matrix 并检测到 git 检出OpenClaw 自动提供本地安装路径。
如果你在配置/新手引导期间选择 Matrix 并检测到 git 检出OpenClaw 自动提供本地安装路径。
详情:[插件](/plugin)
@@ -46,8 +46,8 @@ openclaw plugins install ./extensions/matrix
2. 在主服务器上创建 Matrix 账户:
- 在 [https://matrix.org/ecosystem/hosting/](https://matrix.org/ecosystem/hosting/) 浏览托管选项
- 或自行托管。
3. 获取机器人账户的访问令牌
- 在你的主服务器上使用 `curl` 调用 Matrix 登录 API
3. 获取机器人账户的访问 token
- 在你的主服务器上使用 Matrix 登录 API 配合 `curl`
```bash
curl --request POST \
@@ -64,18 +64,18 @@ openclaw plugins install ./extensions/matrix
```
- 将 `matrix.example.org` 替换为你的主服务器 URL。
- 或设置 `channels.matrix.userId` + `channels.matrix.password`OpenClaw 调用相同的登录端点,将访问令牌存储在 `~/.openclaw/credentials/matrix/credentials.json`,并在下次启动时重用。
- 或设置 `channels.matrix.userId` + `channels.matrix.password`OpenClaw 调用相同的登录端点,将访问 token 存储在 `~/.openclaw/credentials/matrix/credentials.json`,并在下次启动时重用。
4. 配置凭
4. 配置凭
- 环境变量:`MATRIX_HOMESERVER`、`MATRIX_ACCESS_TOKEN`(或 `MATRIX_USER_ID` + `MATRIX_PASSWORD`
- 或配置:`channels.matrix.*`
- 如果两者都设置,配置优先。
- 使用访问令牌时:用户 ID 通过 `/whoami` 自动获取。
- 设置时,`channels.matrix.userId` 应为完整的 Matrix ID例:`@bot:example.org`)。
5. 重启 Gateway 网关(或完成新手引导)。
6. 从任何 Matrix 客户端Element、Beeper 等;参见 https://matrix.org/ecosystem/clients/与机器人开始私信或邀请它加入房间。Beeper 需要 E2EE,因此请设置 `channels.matrix.encryption: true` 并验证设备。
- 如果两者都设置,配置优先。
- 使用访问 token 时:用户 ID 通过 `/whoami` 自动获取。
- 设置时,`channels.matrix.userId` 应为完整的 Matrix ID`@bot:example.org`)。
5. 重启 Gateway网关或完成新手引导
6. 从任何 Matrix 客户端Element、Beeper 等;参见 https://matrix.org/ecosystem/clients/与机器人开始私信或邀请它加入房间。Beeper 需要端到端加密,因此请设置 `channels.matrix.encryption: true` 并验证设备。
最小配置(访问令牌,用户 ID 自动获取):
最小配置(访问 token,用户 ID 自动获取):
```json5
{
@@ -90,7 +90,7 @@ openclaw plugins install ./extensions/matrix
}
```
E2EE 配置(启用端到端加密):
端到端加密配置(启用端到端加密):
```json5
{
@@ -106,27 +106,27 @@ E2EE 配置(启用端到端加密):
}
```
## 加密(E2EE
## 加密(端到端加密
通过 Rust 加密 SDK **支持**端到端加密
端到端加密通过 Rust 加密 SDK **支持**。
使用 `channels.matrix.encryption: true` 启用:
通过 `channels.matrix.encryption: true` 启用:
- 如果加密模块加载成功,加密房间会自动解密。
- 发送到加密房间时,出站媒体会被加密。
- 首次连接时OpenClaw 会你的其他会话请求设备验证。
- 加密房间发送时,出站媒体会被加密。
- 首次连接时OpenClaw 会你的其他会话请求设备验证。
- 在另一个 Matrix 客户端Element 等)中验证设备以启用密钥共享。
- 如果无法加载加密模块E2EE 将被禁用加密房间无法解密OpenClaw 会记录警告。
- 如果你看到缺少加密模块的错误(例如 `@matrix-org/matrix-sdk-crypto-nodejs-*`),请允许 `@matrix-org/matrix-sdk-crypto-nodejs` 的构建脚本并运行 `pnpm rebuild @matrix-org/matrix-sdk-crypto-nodejs`,或使用 `node node_modules/@matrix-org/matrix-sdk-crypto-nodejs/download-lib.js` 获取二进制文件。
- 如果加密模块无法加载,端到端加密将被禁用加密房间无法解密OpenClaw 会记录警告。
- 如果你看到缺少加密模块的错误(例如 `@matrix-org/matrix-sdk-crypto-nodejs-*`),请允许 `@matrix-org/matrix-sdk-crypto-nodejs` 的构建脚本并运行 `pnpm rebuild @matrix-org/matrix-sdk-crypto-nodejs` 或通过 `node node_modules/@matrix-org/matrix-sdk-crypto-nodejs/download-lib.js` 获取二进制文件。
加密状态按账户 + 访问令牌存储在 `~/.openclaw/matrix/accounts/<account>/<homeserver>__<user>/<token-hash>/crypto/`SQLite 数据库)。同步状态存储在同目录的 `bot-storage.json` 中。如果访问令牌(设备)更改,将创建新的存储,机器人必须重新验证才能访问加密房间。
加密状态按账户 + 访问 token 存储在 `~/.openclaw/matrix/accounts/<account>/<homeserver>__<user>/<token-hash>/crypto/`SQLite 数据库)。同步状态存储在同目录的 `bot-storage.json` 中。如果访问 token设备发生变化创建新的存储,机器人必须重新验证才能加密房间中使用
**设备验证:**
启用 E2EE 时,机器人在启动时你的其他会话请求验证。打开 Element或其他客户端并批准验证请求以建立信任。验证后机器人可以解密加密房间中的消息。
启用端到端加密后,机器人在启动时你的其他会话请求验证。打开 Element或其他客户端并批准验证请求以建立信任。验证完成后,机器人可以解密加密房间中的消息。
## 路由模型
- 回复始终返回到 Matrix。
- 回复始终发回 Matrix。
- 私信共享智能体的主会话;房间映射到群组会话。
## 访问控制(私信)
@@ -136,12 +136,12 @@ E2EE 配置(启用端到端加密):
- `openclaw pairing list matrix`
- `openclaw pairing approve matrix <CODE>`
- 公开私信:`channels.matrix.dm.policy="open"` 加上 `channels.matrix.dm.allowFrom=["*"]`。
- `channels.matrix.dm.allowFrom` 接受完整 Matrix 用户 ID例如 `@user:server`。向导在目录搜索得到唯一精确匹配时将显示名称解析为用户 ID。
- `channels.matrix.dm.allowFrom` 接受用户 ID 或显示名称。向导在目录搜索可用时会将显示名称解析为用户 ID。
## 房间(群组)
- 默认:`channels.matrix.groupPolicy = "allowlist"`(提及门控)。使用 `channels.defaults.groupPolicy` 在未设置时覆盖默认值。
- 使用 `channels.matrix.groups` 配置房间允许列表(房间 ID别名名称仅在目录搜索得到唯一精确匹配时解析为 ID
- 默认:`channels.matrix.groupPolicy = "allowlist"`(提及门控)。使用 `channels.defaults.groupPolicy` 在未设置时覆盖默认值。
- 使用 `channels.matrix.groups` 允许列表中的房间(房间 ID别名名称):
```json5
{
@@ -160,35 +160,35 @@ E2EE 配置(启用端到端加密):
- `requireMention: false` 启用该房间的自动回复。
- `groups."*"` 可以设置跨房间的提及门控默认值。
- `groupAllowFrom` 限制哪些发送者可以在房间中触发机器人(需完整 Matrix 用户 ID)。
- 每个房间的 `users` 允许列表可以进一步限制特定房间内的发送者(需完整 Matrix 用户 ID
- 配置向导会提示输入房间允许列表(房间 ID、别名或名称,仅在精确且唯一匹配时解析名称。
- 启动时OpenClaw 将允许列表中的房间/用户名称解析为 ID 并记录映射;未解析的条目不会参与允许列表匹配
- 默认自动加入邀请;使用 `channels.matrix.autoJoin` 和 `channels.matrix.autoJoinAllowlist` 控制。
- 要**禁止所有房间**,设置 `channels.matrix.groupPolicy: "disabled"`(或保持空的允许列表)。
- 旧版键`channels.matrix.rooms`(与 `groups` 相同的结构)。
- `groupAllowFrom` 限制哪些发送者可以在房间中触发机器人(可选)。
- 房间的 `users` 允许列表可以进一步限制特定房间内的发送者。
- 配置向导会提示输入房间允许列表(房间 ID、别名或名称并在可能时解析名称。
- 启动时OpenClaw 将允许列表中的房间/用户名称解析为 ID 并记录映射;未解析的条目保持原样
- 邀请默认自动加入;通过 `channels.matrix.autoJoin` 和 `channels.matrix.autoJoinAllowlist` 控制。
- 要**不允许任何房间**,设置 `channels.matrix.groupPolicy: "disabled"`(或保持空的允许列表)。
- 旧版键:`channels.matrix.rooms`(与 `groups` 结构相同)。
## 话题
## 线程
- 支持回复话题
- `channels.matrix.threadReplies` 控制回复是否保持在话题中:
- 支持回复线程
- `channels.matrix.threadReplies` 控制回复是否保持在线程中:
- `off`、`inbound`(默认)、`always`
- `channels.matrix.replyToMode` 控制不在话题中回复时的 reply-to 元数据:
- `channels.matrix.replyToMode` 控制不在线程中回复时的 reply-to 元数据:
- `off`(默认)、`first`、`all`
## 功能
| 功能 | 状态 |
| -------- | ------------------------------------------------------ |
| 私信 | ✅ 支持 |
| 房间 | ✅ 支持 |
| 话题 | ✅ 支持 |
| 媒体 | ✅ 支持 |
| E2EE | ✅ 支持(需要加密模块) |
| 表情回应 | ✅ 支持(通过工具发送/读取) |
| 投票 | ✅ 支持发送;入站投票开始转换为文本(响应/结束被忽略) |
| 位置 | ✅ 支持geo URI忽略海拔 |
| 原生命令 | ✅ 支持 |
| 功能 | 状态 |
| ---------- | ---------------------------------------------------------- |
| 私信 | ✅ 支持 |
| 房间 | ✅ 支持 |
| 线程 | ✅ 支持 |
| 媒体 | ✅ 支持 |
| 端到端加密 | ✅ 支持(需要加密模块) |
| 回应 | ✅ 支持(通过工具发送/读取) |
| 投票 | ✅ 支持发送;入站 poll start 转换为文本(响应/结束被忽略) |
| 位置 | ✅ 支持geo URI忽略海拔 |
| 原生命令 | ✅ 支持 |
## 配置参考Matrix
@@ -198,24 +198,24 @@ E2EE 配置(启用端到端加密):
- `channels.matrix.enabled`:启用/禁用渠道启动。
- `channels.matrix.homeserver`:主服务器 URL。
- `channels.matrix.userId`Matrix 用户 ID使用访问令牌时可选)。
- `channels.matrix.accessToken`:访问令牌
- `channels.matrix.password`:登录密码(令牌会被存储)。
- `channels.matrix.userId`Matrix 用户 ID使用访问 token 时可选)。
- `channels.matrix.accessToken`:访问 token
- `channels.matrix.password`:登录密码(token 会被存储)。
- `channels.matrix.deviceName`:设备显示名称。
- `channels.matrix.encryption`:启用 E2EE默认false
- `channels.matrix.encryption`:启用端到端加密默认false
- `channels.matrix.initialSyncLimit`:初始同步限制。
- `channels.matrix.threadReplies``off | inbound | always`默认inbound
- `channels.matrix.textChunkLimit`:出站文本分块大小(字符)。
- `channels.matrix.chunkMode``length`(默认)或 `newline`长度分块前按空行(段落边界)分割。
- `channels.matrix.chunkMode``length`(默认)或 `newline`,在按长度分块前按空行(段落边界)分割。
- `channels.matrix.dm.policy``pairing | allowlist | open | disabled`默认pairing
- `channels.matrix.dm.allowFrom`:私信允许列表(需完整 Matrix 用户 ID。`open` 需要 `"*"`。向导在可能时将名称解析为 ID。
- `channels.matrix.dm.allowFrom`:私信允许列表(用户 ID 或显示名称)。`open` 需要 `"*"`。向导在可能时将名称解析为 ID。
- `channels.matrix.groupPolicy``allowlist | open | disabled`默认allowlist
- `channels.matrix.groupAllowFrom`:群组消息的允许发送者列表(需完整 Matrix 用户 ID
- `channels.matrix.allowlistOnly`:强制私信 + 房间使用允许列表规则。
- `channels.matrix.groups`:群组允许列表 + 每个房间设置映射。
- `channels.matrix.groupAllowFrom`:群组消息的允许发送者列表。
- `channels.matrix.allowlistOnly`:强制私信 + 房间执行允许列表规则。
- `channels.matrix.groups`:群组允许列表 + 房间设置映射。
- `channels.matrix.rooms`:旧版群组允许列表/配置。
- `channels.matrix.replyToMode`话题/标签的 reply-to 模式。
- `channels.matrix.replyToMode`线程/标签的 reply-to 模式。
- `channels.matrix.mediaMaxMb`:入站/出站媒体上限MB
- `channels.matrix.autoJoin`:邀请处理(`always | allowlist | off`默认always
- `channels.matrix.autoJoinAllowlist`:自动加入的允许房间 ID/别名。
- `channels.matrix.actions`每个操作的工具限制reactions/messages/pins/memberInfo/channelInfo
- `channels.matrix.actions`操作的工具门控reactions/messages/pins/memberInfo/channelInfo

View File

@@ -5,23 +5,21 @@ read_when:
summary: Mattermost 机器人设置和 OpenClaw 配置
title: Mattermost
x-i18n:
generated_at: "2026-02-03T07:43:43Z"
generated_at: "2026-02-01T19:22:40Z"
model: claude-opus-4-5
provider: pi
source_hash: 57fabe5eb0efbcb885f4178b317b2fa99a41daf609e3a471de2b44db9def4ad7
source_path: channels/mattermost.md
workflow: 15
workflow: 14
---
# Mattermost插件
状态通过插件支持bot token + WebSocket 事件)。支持频道、群组和私信。
Mattermost 是一个可自托管的团队消息平台;有关产品详情和下载,请访问官方网站
[mattermost.com](https://mattermost.com)。
状态通过插件支持bot token + WebSocket 事件)。支持频道、群组和私信。Mattermost 是一个可自托管的团队消息平台;有关产品详情和下载请访问官方网站 [mattermost.com](https://mattermost.com)。
## 需要插件
Mattermost 以插件形式提供,不包含在核心安装中。
Mattermost 作为插件发布,不包含在核心安装中。
通过 CLI 安装npm 注册表):
@@ -35,16 +33,16 @@ openclaw plugins install @openclaw/mattermost
openclaw plugins install ./extensions/mattermost
```
如果你在配置/新手引导期间选择 Mattermost 并检测到 git 检出OpenClaw 会自动提供本地安装路径。
如果你在配置/新手引导期间选择 Mattermost 并检测到 git 检出OpenClaw 会自动提供本地安装路径。
详情:[插件](/plugin)
## 快速设置
1. 安装 Mattermost 插件。
2. 创建 Mattermost bot 账户并复制 **bot token**
2. 创建一个 Mattermost 机器人账户并复制 **bot token**
3. 复制 Mattermost **基础 URL**(例如 `https://chat.example.com`)。
4. 配置 OpenClaw 并启动 Gateway 网关。
4. 配置 OpenClaw 并启动 Gateway网关。
最小配置:
@@ -63,7 +61,7 @@ openclaw plugins install ./extensions/mattermost
## 环境变量(默认账户)
如果你偏好使用环境变量,请在 Gateway 网关主机上设置:
如果你偏好使用环境变量,请在 Gateway网关主机上设置
- `MATTERMOST_BOT_TOKEN=...`
- `MATTERMOST_URL=https://chat.example.com`
@@ -75,7 +73,7 @@ openclaw plugins install ./extensions/mattermost
Mattermost 自动响应私信。频道行为由 `chatmode` 控制:
- `oncall`(默认):仅在频道中被 @提及时响应
- `onmessage`:响应每条频道消息。
- `onmessage`:响应频道中的每条消息。
- `onchar`:当消息以触发前缀开头时响应。
配置示例:
@@ -93,8 +91,8 @@ Mattermost 自动响应私信。频道行为由 `chatmode` 控制:
注意事项:
- `onchar` 仍会响应显式 @提及
- `channels.mattermost.requireMention` 对旧配置仍然有效,但推荐使用 `chatmode`
- `onchar` 模式仍然响应明确的 @提及
- `channels.mattermost.requireMention` 对旧配置仍然有效,但推荐使用 `chatmode`
## 访问控制(私信)
@@ -106,13 +104,13 @@ Mattermost 自动响应私信。频道行为由 `chatmode` 控制:
## 频道(群组)
- 默认:`channels.mattermost.groupPolicy = "allowlist"`(提及限制)。
- 使用 `channels.mattermost.groupAllowFrom` 将发送者加入允许列表(用户 ID 或 `@username`)。
- 开放频道:`channels.mattermost.groupPolicy="open"`(提及限制)。
- 默认:`channels.mattermost.groupPolicy = "allowlist"`(提及门控)。
- 使用 `channels.mattermost.groupAllowFrom` 允许列表发送者(用户 ID 或 `@username`)。
- 开放频道:`channels.mattermost.groupPolicy="open"`(提及门控)。
## 出站投递目标
`openclaw message send` cron/webhooks 中使用这些目标格式:
`openclaw message send`定时任务/webhook 中使用以下目标格式:
- `channel:<id>` 用于频道
- `user:<id>` 用于私信
@@ -139,6 +137,6 @@ Mattermost 支持在 `channels.mattermost.accounts` 下配置多个账户:
## 故障排除
- 频道中回复:确保 bot 在频道并提及它oncall使用触发前缀onchar或设置 `chatmode: "onmessage"`
- 频道中没有回复:确保机器人已加入频道并提及它oncall 模式使用触发前缀onchar 模式),或设置 `chatmode: "onmessage"`
- 认证错误:检查 bot token、基础 URL 以及账户是否已启用。
- 多账户问题:环境变量仅适用于 `default` 账户。

View File

@@ -1,32 +1,32 @@
---
read_when:
- 开发 MS Teams 渠道功能
- 开发 Microsoft Teams 渠道功能
summary: Microsoft Teams 机器人支持状态、功能和配置
title: Microsoft Teams
x-i18n:
generated_at: "2026-02-03T07:46:52Z"
generated_at: "2026-02-01T19:26:12Z"
model: claude-opus-4-5
provider: pi
source_hash: 2046cb8fa3dd349f4b25a40c013a87188af8f75c1886a782698bff2bb9f70971
source_hash: 3d5641c578086f7569f42276d4ef2462200b9927ca3f505e6ee26806103eaa60
source_path: channels/msteams.md
workflow: 15
workflow: 14
---
# Microsoft Teams插件
> "进入此者,放弃一切希望。"
> "进入此者,放弃一切希望。"
更新时间2026-01-21
状态:支持文本 + 私信附件;频道/群组文件发送需要 `sharePointSiteId` + Graph 权限(参见[在群聊中发送文件](#sending-files-in-group-chats))。投票通过 Adaptive Cards 发送。
状态:支持文本 + 私信附件;频道/群组文件发送需要 `sharePointSiteId` + Graph 权限(参见[在群聊中发送文件](#在群聊中发送文件))。投票通过 Adaptive Cards 发送。
## 需要插件
Microsoft Teams 作为插件提供,不包含在核心安装中。
Microsoft Teams 作为插件发布,不包含在核心安装中。
**破坏性变更2026.1.15** MS Teams 已从核心移出。如果你使用它,必须安装插件。
**破坏性变更2026.1.15** Microsoft Teams 已从核心移出。如果你使用它,必须安装插件。
原因说明:保持核心安装更轻量,并让 MS Teams 依赖项可以独立更新。
原因说明:保持核心安装更轻量,并让 Microsoft Teams 依赖项可以独立更新。
通过 CLI 安装npm 注册表):
@@ -40,18 +40,17 @@ openclaw plugins install @openclaw/msteams
openclaw plugins install ./extensions/msteams
```
如果你在配置/新手引导过程中选择 Teams 并检测到 git 检出,
OpenClaw 将自动提供本地安装路径。
如果你在配置/新手引导期间选择 Teams 并检测到 git 检出,OpenClaw 会自动提供本地安装路径。
详情:[插件](/plugin)
## 快速设置(初学者
## 快速设置(新手
1. 安装 Microsoft Teams 插件。
2. 创建一个 **Azure Bot**App ID + 客户端密钥 + 租户 ID
3. 使用这些凭配置 OpenClaw。
3. 使用这些凭配置 OpenClaw。
4. 通过公共 URL 或隧道暴露 `/api/messages`(默认端口 3978
5. 安装 Teams 应用包并启动 Gateway 网关。
5. 安装 Teams 应用包并启动 Gateway网关。
最小配置:
@@ -69,19 +68,19 @@ OpenClaw 将自动提供本地安装路径。
}
```
注意:群聊默认被阻止(`channels.msteams.groupPolicy: "allowlist"`)。要允许群组回复,请设置 `channels.msteams.groupAllowFrom`(或使用 `groupPolicy: "open"` 允许任何成员,需要提及才能触发)。
注意:群聊默认被阻止(`channels.msteams.groupPolicy: "allowlist"`)。要允许群组回复,请设置 `channels.msteams.groupAllowFrom`(或使用 `groupPolicy: "open"` 允许任何成员,提及门控)。
## 目标
- 通过 Teams 私信、群聊或频道与 OpenClaw 交流
- 保持路由确定性:回复始终返回到消息到达的渠道。
- 默认使用安全的渠道行为(除非另配置,否则需要提及)。
- 通过 Teams 私信、群聊或频道与 OpenClaw 对话
- 保持路由确定性:回复始终发回消息到达的渠道。
- 默认使用安全的渠道行为(除非另配置,否则需要提及)。
## 配置写入
默认情况下Microsoft Teams 允许通过 `/config set|unset` 触发的配置更新写入(需要 `commands.config: true`)。
禁用方式
通过以下方式禁用:
```json5
{
@@ -93,14 +92,14 @@ OpenClaw 将自动提供本地安装路径。
**私信访问**
- 默认:`channels.msteams.dmPolicy = "pairing"`。未知发送者在获得批准之前将被忽略。
- `channels.msteams.allowFrom` 接受 AAD 对象 ID、UPN 或显示名称。当凭允许时,向导通过 Microsoft Graph 将名称解析为 ID。
- 默认:`channels.msteams.dmPolicy = "pairing"`。未知发送者在批准前会被忽略。
- `channels.msteams.allowFrom` 接受 AAD 对象 ID、UPN 或显示名称。当凭允许时,向导通过 Microsoft Graph 将名称解析为 ID。
**群组访问**
- 默认:`channels.msteams.groupPolicy = "allowlist"`(除非添加 `groupAllowFrom`,否则被阻止)。使用 `channels.defaults.groupPolicy` 在未设置时覆盖默认值。
- 默认:`channels.msteams.groupPolicy = "allowlist"`被阻止,除非添加 `groupAllowFrom`)。使用 `channels.defaults.groupPolicy` 在未设置时覆盖默认值。
- `channels.msteams.groupAllowFrom` 控制哪些发送者可以在群聊/频道中触发(回退到 `channels.msteams.allowFrom`)。
- 设置 `groupPolicy: "open"` 允许任何成员(默认仍需提及才能触发)。
- 设置 `groupPolicy: "open"` 允许任何成员(默认仍需提及门控)。
- 要**不允许任何频道**,设置 `channels.msteams.groupPolicy: "disabled"`
示例:
@@ -118,12 +117,11 @@ OpenClaw 将自动提供本地安装路径。
**团队 + 频道允许列表**
- 通过在 `channels.msteams.teams` 下列出团队和频道来限定群组/频道回复范围。
- 通过在 `channels.msteams.teams` 下列出团队和频道来限定群组/频道回复范围。
- 键可以是团队 ID 或名称;频道键可以是会话 ID 或名称。
-`groupPolicy="allowlist"` 且存在团队允许列表时,仅接受列出的团队/频道(需要提及才能触发)。
-`groupPolicy="allowlist"` 且存在团队允许列表时,仅接受列出的团队/频道(提及门控)。
- 配置向导接受 `Team/Channel` 条目并为你存储。
- 启动时OpenClaw 将团队/频道和用户允许列表名称解析为 ID当 Graph 权限允许时)
并记录映射;未解析的条目保持原样。
- 启动时OpenClaw 将团队/频道和用户允许列表名称解析为 ID当 Graph 权限允许时)并记录映射;未解析的条目保持原样。
示例:
@@ -148,10 +146,10 @@ OpenClaw 将自动提供本地安装路径。
1. 安装 Microsoft Teams 插件。
2. 创建一个 **Azure Bot**App ID + 密钥 + 租户 ID
3. 构建一个引用机器人并包含下 RSC 权限的 **Teams 应用包**
4. 将 Teams 应用上传/安装到团队(或用于私信的个人范围)。
5.`~/.openclaw/openclaw.json`(或环境变量)中配置 `msteams` 并启动 Gateway 网关。
6. Gateway 网关默认在 `/api/messages` 上监听 Bot Framework webhook 流量。
3. 构建一个引用机器人并包含下 RSC 权限的 **Teams 应用包**
4. 将 Teams 应用上传/安装到团队(或私人范围用于私信)。
5.`~/.openclaw/openclaw.json`(或环境变量)中配置 `msteams` 并启动 Gateway网关。
6. Gateway网关默认在 `/api/messages` 上监听 Bot Framework webhook 流量。
## Azure Bot 设置(前提条件)
@@ -160,13 +158,13 @@ OpenClaw 将自动提供本地安装路径。
### 步骤 1创建 Azure Bot
1. 前往[创建 Azure Bot](https://portal.azure.com/#create/Microsoft.AzureBot)
2. 填写**基本信息**选项卡
2. 填写 **Basics** 标签页
| 字段 | 值 |
| ------------------ | --------------------------------------------------- |
| **Bot handle** | 你的机器人名称,例如 `openclaw-msteams`(必须唯一) |
| **Subscription** | 选择你的 Azure 订阅 |
| **Resource group** | 新建或使用现有 |
| **Resource group** | 新建或使用现有 |
| **Pricing tier** | **Free** 用于开发/测试 |
| **Type of App** | **Single Tenant**(推荐 - 见下方说明) |
| **Creation type** | **Create new Microsoft App ID** |
@@ -175,22 +173,22 @@ OpenClaw 将自动提供本地安装路径。
3. 点击 **Review + create****Create**(等待约 1-2 分钟)
### 步骤 2获取凭
### 步骤 2获取凭
1. 前往你的 Azure Bot 资源 → **Configuration**
2. 复制 **Microsoft App ID** → 这是你的 `appId`
3. 点击 **Manage Password**前往应用注册
3. 点击 **Manage Password**进入应用注册
4.**Certificates & secrets****New client secret** → 复制 **Value** → 这是你的 `appPassword`
5. 前往 **Overview** → 复制 **Directory (tenant) ID** → 这是你的 `tenantId`
5. 进入 **Overview** → 复制 **Directory (tenant) ID** → 这是你的 `tenantId`
### 步骤 3配置消息端点
1. 在 Azure Bot → **Configuration**
2.**Messaging endpoint** 设置为你的 webhook URL
- 生产环境:`https://your-domain.com/api/messages`
- 本地开发:使用隧道(见下方[本地开发](#local-development-tunneling)
- 本地开发:使用隧道(见下方[本地开发](#本地开发隧道)
### 步骤 4启用 Teams
### 步骤 4启用 Teams
1. 在 Azure Bot → **Channels**
2. 点击 **Microsoft Teams** → Configure → Save
@@ -200,7 +198,7 @@ OpenClaw 将自动提供本地安装路径。
Teams 无法访问 `localhost`。本地开发请使用隧道:
**选项 Angrok**
**方案 Angrok**
```bash
ngrok http 3978
@@ -208,7 +206,7 @@ ngrok http 3978
# 将消息端点设置为https://abc123.ngrok.io/api/messages
```
**选项 BTailscale Funnel**
**方案 BTailscale Funnel**
```bash
tailscale funnel 3978
@@ -217,31 +215,31 @@ tailscale funnel 3978
## Teams 开发者门户(替代方案)
除了手动创建清单 ZIP你可以使用 [Teams 开发者门户](https://dev.teams.microsoft.com/apps)
除了手动创建清单 ZIP,你可以使用 [Teams 开发者门户](https://dev.teams.microsoft.com/apps)
1. 点击 **+ New app**
2. 填写基本信息(名称、描述、开发者信息)
3. 前往 **App features****Bot**
3. 进入 **App features****Bot**
4. 选择 **Enter a bot ID manually** 并粘贴你的 Azure Bot App ID
5. 勾选范围:**Personal**、**Team**、**Group Chat**
6. 点击 **Distribute****Download app package**
7. 在 Teams 中:**Apps** → **Manage your apps****Upload a custom app** → 选择 ZIP
这通常比手动编辑 JSON 清单更容易
这通常比手动编辑 JSON 清单更简单
## 测试机器人
**选项 AAzure Web Chat先验证 webhook**
**方案 AAzure Web Chat先验证 webhook**
1. 在 Azure 门户 → 你的 Azure Bot 资源 → **Test in Web Chat**
2. 发送一条消息 - 你应该看到响应
3. 这确认你的 webhook 端点在 Teams 设置之前正常工作
2. 发送一条消息 - 你应该看到回复
3. 这确认你的 webhook 端点在 Teams 设置之前可以正常工作
**选项 BTeams应用安装后)**
**方案 BTeams安装应用后)**
1. 安装 Teams 应用(载或组织目录)
1. 安装 Teams 应用(旁加载或组织目录)
2. 在 Teams 中找到机器人并发送私信
3. 检查 Gateway 网关日志中的传入活动
3. 检查 Gateway网关日志中的传入活动
## 设置(最小纯文本)
@@ -250,7 +248,7 @@ tailscale funnel 3978
- 从本地检出:`openclaw plugins install ./extensions/msteams`
2. **机器人注册**
- 创建一个 Azure Bot见上)并记录:
- 创建 Azure Bot见上)并记录:
- App ID
- 客户端密钥App password
- 租户 ID单租户
@@ -258,10 +256,10 @@ tailscale funnel 3978
3. **Teams 应用清单**
- 包含一个 `bot` 条目,其中 `botId = <App ID>`
- 范围:`personal``team``groupChat`
- `supportsFiles: true`(个人范围文件处理所需)。
- 添加 RSC 权限(见下)。
- `supportsFiles: true`(个人范围文件处理所需)。
- 添加 RSC 权限(见下)。
- 创建图标:`outline.png`32x32`color.png`192x192
- 将三个文件一起打包:`manifest.json``outline.png``color.png`
- 将三个文件打包在一起`manifest.json``outline.png``color.png`
4. **配置 OpenClaw**
@@ -277,29 +275,29 @@ tailscale funnel 3978
}
```
你也可以使用环境变量替配置键:
你也可以使用环境变量替配置键:
- `MSTEAMS_APP_ID`
- `MSTEAMS_APP_PASSWORD`
- `MSTEAMS_TENANT_ID`
5. **机器人端点**
- 将 Azure Bot Messaging Endpoint 设置为:
- 将 Azure Bot 消息端点设置为:
- `https://<host>:3978/api/messages`(或你选择的路径/端口)。
6. **运行 Gateway 网关**
- 当插件已安装且 `msteams` 配置存在并有凭证Teams 渠道会自动启动。
6. **运行 Gateway网关**
- 当插件已安装且 `msteams` 配置存在凭据Teams 渠道会自动启动。
## 历史上下文
- `channels.msteams.historyLimit` 控制多少条最近的频道/群组消息包含提示中。
- 回退到 `messages.groupChat.historyLimit`。设置 `0` 禁用(默认 50
- 私信历史可通过 `channels.msteams.dmHistoryLimit`(用户轮次)限制。用户覆盖:`channels.msteams.dms["<user_id>"].historyLimit`。
- `channels.msteams.historyLimit` 控制多少条最近的频道/群组消息包含提示中。
- 回退到 `messages.groupChat.historyLimit`。设置 `0` 禁用(默认 50
- 私信历史可通过 `channels.msteams.dmHistoryLimit`(用户回合数)限制。用户覆盖:`channels.msteams.dms["<user_id>"].historyLimit`。
## 当前 Teams RSC 权限(清单)
这些是我们 Teams 应用清单中**现有的 resourceSpecific 权限**。它们仅适用于安装了应用的团队/聊天内部
以下是我们 Teams 应用清单中**现有的 resourceSpecific 权限**。它们仅安装了应用的团队/聊天中适用
**对于频道(团队范围):**
**频道(团队范围):**
- `ChannelMessage.Read.Group`Application- 无需 @提及即可接收所有频道消息
- `ChannelMessage.Send.Group`Application
@@ -309,11 +307,11 @@ tailscale funnel 3978
- `TeamMember.Read.Group`Application
- `TeamSettings.Read.Group`Application
**对于群聊:**
**群聊:**
- `ChatMessage.Read.Chat`Application- 无需 @提及即可接收所有群聊消息
## Teams 清单示例(已脱敏)
## 示例 Teams 清单(已脱敏)
包含必需字段的最小有效示例。请替换 ID 和 URL。
@@ -363,30 +361,30 @@ tailscale funnel 3978
}
```
### 清单注意事项(必字段)
### 清单注意事项(必字段)
- `bots[].botId` **必须**与 Azure Bot App ID 匹配。
- `webApplicationInfo.id` **必须**与 Azure Bot App ID 匹配。
- `bots[].scopes` 必须包含你计划使用的界面`personal`、`team`、`groupChat`)。
- `bots[].supportsFiles: true` 是个人范围文件处理所需的。
- `authorization.permissions.resourceSpecific` 如果你需要频道流量,必须包含频道读取/发送权限。
- `bots[].scopes` 必须包含你计划使用的范围`personal`、`team`、`groupChat`)。
- `bots[].supportsFiles: true` 是个人范围文件处理所需的。
- `authorization.permissions.resourceSpecific` 必须包含频道读取/发送权限(如果你需要频道流量)
### 更新现有应用
要更新已安装的 Teams 应用(例如添加 RSC 权限):
要更新已安装的 Teams 应用(例如添加 RSC 权限):
1. 使用新设置更新你的 `manifest.json`
2. **增 `version` 字段**(例如`1.0.0` → `1.1.0`
1. 使用新设置更新 `manifest.json`
2. **增 `version` 字段**(例如 `1.0.0` → `1.1.0`
3. **重新打包**清单和图标(`manifest.json`、`outline.png`、`color.png`
4. 上传新的 zip
- **选项 ATeams 管理中心):** Teams 管理中心 → Teams apps → Manage apps → 找到你的应用 → Upload new version
- **选项 B载):** 在 Teams 中 → Apps → Manage your apps → Upload a custom app
- **方案 ATeams 管理中心):** Teams 管理中心 → Teams apps → Manage apps → 找到你的应用 → Upload new version
- **方案 B旁加载):** 在 Teams 中 → Apps → Manage your apps → Upload a custom app
5. **对于团队频道:** 在每个团队中重新安装应用以使新权限生效
6. **完全退出并重新启动 Teams**(不仅仅是关闭窗口)以清除缓存的应用元数据
6. **完全退出并重新启动 Teams**(不是关闭窗口)以清除缓存的应用元数据
## 功能:仅 RSC Graph
## 功能:仅 RSC vs Graph
### 仅使用 **Teams RSC**应用已安装,无 Graph API 权限)
### 仅使用 **Teams RSC**(已安装应用,无 Graph API 权限)
可用:
@@ -396,109 +394,108 @@ tailscale funnel 3978
不可用:
- 频道/群组**图片或文件内容**(负载仅包含 HTML 存根)。
- 频道/群组**图片或文件内容**(负载仅包含 HTML 占位符)。
- 下载存储在 SharePoint/OneDrive 中的附件。
- 读取消息历史(超出实时 webhook 事件)。
- 读取消息历史(超出实时 webhook 事件范围)。
### 使用 **Teams RSC + Microsoft Graph Application 权限**
增:
- 下载托管内容(粘贴到消息中的图片)。
- 下载存储在 SharePoint/OneDrive 中的文件附件。
- 通过 Graph 读取频道/聊天消息历史。
### RSC Graph API 对比
### RSC vs Graph API
| 功能 | RSC 权限 | Graph API |
| -------------- | ------------------ | ------------------------- |
| **实时消息** | 是(通过 webhook | 否(仅轮询) |
| **历史消息** | 否 | 是(可查询历史) |
| **设置复杂度** | 仅应用清单 | 需要管理员同意 + 令牌流程 |
| **离线工作** | 否(必须运行) | 是(随时查询) |
| 功能 | RSC 权限 | Graph API |
| -------------- | ------------------ | --------------------------- |
| **实时消息** | 是(通过 webhook | 否(仅轮询) |
| **历史消息** | 否 | 是(可查询历史) |
| **设置复杂度** | 仅应用清单 | 需要管理员同意 + token 流程 |
| **离线可用** | 否(必须运行 | 是(随时查询) |
**结** RSC 用于实时监听Graph API 用于历史访问。要在离线时补上错过的消息,你需要有 `ChannelMessage.Read.All` 的 Graph API需要管理员同意
**结:** RSC 用于实时监听Graph API 用于历史访问。要补上离线期间错过的消息,你需要有 `ChannelMessage.Read.All` 的 Graph API需要管理员同意
## 启用 Graph 的媒体 + 历史(频道所需)
## 启用 Graph 的媒体 + 历史(频道所需)
如果你需要**频道**中的图片/文件或想获取**消息历史**必须启用 Microsoft Graph 权限并授予管理员同意。
如果你需要**频道**中的图片/文件或想获取**消息历史**,必须启用 Microsoft Graph 权限并授予管理员同意。
1. 在 Entra IDAzure AD**App Registration** 中,添加 Microsoft Graph **Application 权限**
1. 在 Entra IDAzure AD**应用注册**中,添加 Microsoft Graph **Application 权限**
- `ChannelMessage.Read.All`(频道附件 + 历史)
- `Chat.Read.All` 或 `ChatMessage.Read.All`(群聊)
2. 为租户**授予管理员同意**。
3. 提升 Teams 应用**清单版本**,重新上传,并**在 Teams 中重新安装应用**。
3. 递增 Teams 应用**清单版本**,重新上传,并在 **Teams 中重新安装应用**。
4. **完全退出并重新启动 Teams** 以清除缓存的应用元数据。
## 已知限制
### Webhook 超时
Teams 通过 HTTP webhook 递消息。如果处理时间过长(例如LLM 响应缓慢),你可能会看到:
Teams 通过 HTTP webhook 递消息。如果处理时间过长(例如 LLM 响应缓慢),你可能会看到:
- Gateway 网关超时
- Gateway网关超时
- Teams 重试消息(导致重复)
- 丢失的回复
- 回复丢失
OpenClaw 通过快速返回并主动发送回复来处理这个问题,但非常慢的响应仍可能导致问题。
OpenClaw 通过快速返回并主动发送回复来处理问题,但非常慢的响应仍可能导致问题。
### 格式
### 格式
Teams markdown 比 Slack 或 Discord 更有限:
- 基本格式有效:**粗体**、_斜体_、`代码`、链接
- 复杂 markdown表格、嵌套列表可能无法正确渲染
- 支持 Adaptive Cards 用于投票和任意卡片发送(见下
- 基本格式有效:**粗体**、_斜体_、`代码`、链接
- 复杂 markdown表格、嵌套列表可能无法正确渲染
- 支持 Adaptive Cards 用于投票和任意卡片发送(见下
## 配置
关键设置(共享渠道模式见 `/gateway/configuration`
关键设置(共享渠道模式请参见 `/gateway/configuration`
- `channels.msteams.enabled`:启用/禁用渠道。
- `channels.msteams.appId`、`channels.msteams.appPassword`、`channels.msteams.tenantId`:机器人凭
- `channels.msteams.appId`、`channels.msteams.appPassword`、`channels.msteams.tenantId`:机器人凭
- `channels.msteams.webhook.port`(默认 `3978`
- `channels.msteams.webhook.path`(默认 `/api/messages`
- `channels.msteams.dmPolicy``pairing | allowlist | open | disabled`默认pairing
- `channels.msteams.allowFrom`私信允许列表AAD 对象 ID、UPN 或显示名称)。当 Graph 访问可用时,向导在设置期间将名称解析为 ID。
- `channels.msteams.textChunkLimit`:出站文本分块大小。
- `channels.msteams.chunkMode``length`(默认)或 `newline`长度分块之前按空行(段落边界)分割。
- `channels.msteams.chunkMode``length`(默认)或 `newline`,在按长度分块之前按空行(段落边界)分割。
- `channels.msteams.mediaAllowHosts`:入站附件主机允许列表(默认为 Microsoft/Teams 域名)。
- `channels.msteams.mediaAuthAllowHosts`:在媒体重试时附加 Authorization 头的允许列表(默认为 Graph + Bot Framework 主机)。
- `channels.msteams.requireMention`:在频道/群组中需要 @提及(默认 true
- `channels.msteams.replyStyle``thread | top-level`(见[回复样式](#reply-style-threads-vs-posts))。
- `channels.msteams.teams.<teamId>.replyStyle`团队覆盖。
- `channels.msteams.teams.<teamId>.requireMention`团队覆盖。
- `channels.msteams.teams.<teamId>.tools`当缺少频道覆盖时使用的默认每团队工具策略覆盖(`allow`/`deny`/`alsoAllow`)。
- `channels.msteams.teams.<teamId>.toolsBySender`默认每团队发送者工具策略覆盖(支持 `"*"` 通配符)。
- `channels.msteams.teams.<teamId>.channels.<conversationId>.replyStyle`频道覆盖。
- `channels.msteams.teams.<teamId>.channels.<conversationId>.requireMention`频道覆盖。
- `channels.msteams.teams.<teamId>.channels.<conversationId>.tools`频道工具策略覆盖(`allow`/`deny`/`alsoAllow`)。
- `channels.msteams.teams.<teamId>.channels.<conversationId>.toolsBySender`频道发送者工具策略覆盖(支持 `"*"` 通配符)。
- `channels.msteams.sharePointSiteId`:用于群聊/频道文件上传的 SharePoint 站点 ID见[在群聊中发送文件](#sending-files-in-group-chats))。
- `channels.msteams.replyStyle``thread | top-level`见[回复样式:线程 vs 帖子](#回复样式线程-vs-帖子))。
- `channels.msteams.teams.<teamId>.replyStyle`团队覆盖。
- `channels.msteams.teams.<teamId>.requireMention`团队覆盖。
- `channels.msteams.teams.<teamId>.tools`按团队默认工具策略覆盖(`allow`/`deny`/`alsoAllow`,在频道覆盖缺失时使用
- `channels.msteams.teams.<teamId>.toolsBySender`团队发送者工具策略覆盖(支持 `"*"` 通配符)。
- `channels.msteams.teams.<teamId>.channels.<conversationId>.replyStyle`频道覆盖。
- `channels.msteams.teams.<teamId>.channels.<conversationId>.requireMention`频道覆盖。
- `channels.msteams.teams.<teamId>.channels.<conversationId>.tools`频道工具策略覆盖(`allow`/`deny`/`alsoAllow`)。
- `channels.msteams.teams.<teamId>.channels.<conversationId>.toolsBySender`频道发送者工具策略覆盖(支持 `"*"` 通配符)。
- `channels.msteams.sharePointSiteId`:用于群聊/频道文件上传的 SharePoint 站点 ID见[在群聊中发送文件](#在群聊中发送文件))。
## 路由会话
## 路由会话
- 会话键遵循标准智能体格式(见 [/concepts/session](/concepts/session)
- 会话键遵循标准智能体格式(见 [/concepts/session](/concepts/session)
- 私信共享主会话(`agent:<agentId>:<mainKey>`)。
- 频道/群组消息使用会话 ID
- `agent:<agentId>:msteams:channel:<conversationId>`
- `agent:<agentId>:msteams:group:<conversationId>`
## 回复样式:话题 vs 帖子
## 回复样式:线程 vs 帖子
Teams 最近在相同的底层数据模型上引入了两种频道 UI 样式:
| 样式 | 描述 | 推荐的 `replyStyle` |
| ----------------------- | ------------------------------ | ------------------- |
| **Posts**(经典) | 消息显示为卡片,下方有话题回复 | `thread`(默认) |
| **Threads**(类 Slack | 消息线性流动,更像 Slack | `top-level` |
| **Posts**(经典) | 消息显示为卡片,下方有线程回复 | `thread`(默认) |
| **Threads**(类 Slack | 消息线性排列,更像 Slack | `top-level` |
**问题:** Teams API 不暴露频道使用 UI 样式。如果你使用错误的 `replyStyle`
**问题:** Teams API 不暴露频道使用哪种 UI 样式。如果你使用错误的 `replyStyle`
- 在 Threads 样式频道中使用 `thread` → 回复嵌套显示很别扭
- 在 Posts 样式频道中使用 `top-level` → 回复显示为独的顶级帖子而不是在话题
- 在 Threads 样式频道中使用 `thread` → 回复嵌套显示不自然
- 在 Posts 样式频道中使用 `top-level` → 回复显示为独的顶级帖子而非在线程
**解决方案:** 根据频道的设置方式为每个频道配置 `replyStyle`
**解决方案:** 根据频道的设置方式频道配置 `replyStyle`
```json
{
@@ -517,43 +514,41 @@ Teams 最近在相同的底层数据模型上引入了两种频道 UI 样式:
}
```
## 附件图片
## 附件图片
**当前限制:**
- **私信:** 图片和文件附件通过 Teams bot file API 工作
- **频道/群组:** 附件存储在 M365 存储SharePoint/OneDrive中。webhook 负载仅包含 HTML 存根,而非实际文件字节。**需要 Graph API 权限**才能下载频道附件。
- **私信:** 图片和文件附件通过 Teams bot 文件 API 可用
- **频道/群组:** 附件存储在 M365 存储SharePoint/OneDrive中。Webhook 负载仅包含 HTML 占位符,而非实际文件字节。**需要 Graph API 权限**才能下载频道附件。
没有 Graph 权限,带图片的频道消息将作为纯文本接收(机器人无法访问图片内容)。
默认情况下OpenClaw 仅从 Microsoft/Teams 主机名下载媒体。使用 `channels.msteams.mediaAllowHosts` 覆盖(使用 `["*"]` 允许任何主机)。
Authorization 头仅附加到 `channels.msteams.mediaAuthAllowHosts` 中的主机(默认为 Graph + Bot Framework 主机)。保持此列表严格(避免多租户后缀)。
没有 Graph 权限时,包含图片的频道消息将作为纯文本接收(机器人无法访问图片内容)。默认情况下OpenClaw 仅从 Microsoft/Teams 主机名下载媒体。通过 `channels.msteams.mediaAllowHosts` 覆盖(使用 `["*"]` 允许任何主机)。
## 在群聊中发送文件
机器人可以使用 FileConsentCard 流程在私信中发送文件(内置)。但是**在群聊/频道中发送文件**需要额外设置:
机器人可以使用 FileConsentCard 流程在私信中发送文件(内置)。然而**在群聊/频道中发送文件**需要额外设置:
| 上下文 | 文件发送方式 | 所需设置 |
| ---------------------- | --------------------------------------- | ------------------------------------ |
| **私信** | FileConsentCard → 用户接受 → 机器人上传 | 开箱即用 |
| **群聊/频道** | 上传到 SharePoint → 享链接 | 需要 `sharePointSiteId` + Graph 权限 |
| **图片(任何上下文** | Base64 编码内联 | 开箱即用 |
| 场景 | 文件发送方式 | 所需设置 |
| -------------------- | --------------------------------------- | ------------------------------------ |
| **私信** | FileConsentCard → 用户接受 → 机器人上传 | 开箱即用 |
| **群聊/频道** | 上传到 SharePoint → 享链接 | 需要 `sharePointSiteId` + Graph 权限 |
| **图片(任何场景** | Base64 编码内联 | 开箱即用 |
### 为什么群聊需要 SharePoint
机器人没有个人 OneDrive 驱动器(`/me/drive` Graph API 端点对应用程序身份不起作用)。要在群聊/频道中发送文件,机器人上传到 **SharePoint 站点**并创建共享链接。
机器人没有个人 OneDrive 驱动器(`/me/drive` Graph API 端点对应用程序标识不可用)。要在群聊/频道中发送文件,机器人上传到 **SharePoint 站点**并创建共享链接。
### 设置
1. **在 Entra IDAzure ADApp Registration 中添加 Graph API 权限**
1. 在 Entra IDAzure AD应用注册中**添加 Graph API 权限**
- `Sites.ReadWrite.All`Application- 上传文件到 SharePoint
- `Chat.Read.All`Application- 可选,启用用户共享链接
- `Chat.Read.All`Application- 可选,启用用户共享链接
2. 为租户**授予管理员同意**。
3. **获取你的 SharePoint 站点 ID**
```bash
# 通过 Graph Explorer 或带有效令牌的 curl
# 通过 Graph Explorer 或使用有效 token 的 curl
curl -H "Authorization: Bearer $TOKEN" \
"https://graph.microsoft.com/v1.0/sites/{hostname}:/{site-path}"
@@ -580,38 +575,38 @@ Authorization 头仅附加到 `channels.msteams.mediaAuthAllowHosts` 中的主
| 权限 | 共享行为 |
| --------------------------------------- | ------------------------------------------ |
| 仅 `Sites.ReadWrite.All` | 组织范围共享链接(组织中任何人都可访问) |
| `Sites.ReadWrite.All` + `Chat.Read.All` | 用户共享链接(仅聊天成员可访问) |
| 仅 `Sites.ReadWrite.All` | 组织范围共享链接(组织中任何人都可访问) |
| `Sites.ReadWrite.All` + `Chat.Read.All` | 用户共享链接(仅聊天成员可访问) |
用户共享更安全,因为只有聊天参与者才能访问文件。如果缺少 `Chat.Read.All` 权限,机器人回退到组织范围共享。
用户共享更安全,因为只有聊天参与者可以访问文件。如果缺少 `Chat.Read.All` 权限,机器人回退到组织范围共享。
### 回退行为
| 场景 | 结果 |
| --------------------------------------- | ------------------------------------------------ |
| 群聊 + 文件 + 已配置 `sharePointSiteId` | 上传到 SharePoint发送共享链接 |
| 群聊 + 文件 + `sharePointSiteId` | 尝试 OneDrive 上传(可能失败),仅发送文本 |
| 个人聊天 + 文件 | FileConsentCard 流程(无需 SharePoint 即可工作 |
| 任何上下文 + 图片 | Base64 编码内联(无需 SharePoint 即可工作 |
| 场景 | 结果 |
| --------------------------------------- | ------------------------------------------ |
| 群聊 + 文件 + 已配置 `sharePointSiteId` | 上传到 SharePoint发送共享链接 |
| 群聊 + 文件 + 未配置 `sharePointSiteId` | 尝试 OneDrive 上传(可能失败),仅发送文本 |
| 个人聊天 + 文件 | FileConsentCard 流程(无需 SharePoint |
| 任何场景 + 图片 | Base64 编码内联(无需 SharePoint |
### 文件存储位置
上传的文件存储在配置 SharePoint 站点默认文档库中的 `/OpenClawShared/` 文件夹
上传的文件存储在配置 SharePoint 站点默认文档库中的 `/OpenClawShared/` 文件夹。
## 投票Adaptive Cards
OpenClaw 将 Teams 投票作为 Adaptive Cards 发送(没有原生 Teams 投票 API
OpenClaw 通过 Adaptive Cards 发送 Teams 投票(没有原生 Teams 投票 API
- CLI`openclaw message poll --channel msteams --target conversation:<id> ...`
- 投票由 Gateway 网关记录在 `~/.openclaw/msteams-polls.json` 中。
- Gateway 网关必须保持在线才能记录投票。
- 投票尚不自动发布结果摘要(如需要请查存储文件)。
- 投票由 Gateway网关记录在 `~/.openclaw/msteams-polls.json` 中。
- Gateway网关必须保持在线记录投票。
- 投票尚不自动发布结果摘要(如需要请查存储文件)。
## Adaptive Cards任意
使用 `message` 工具或 CLI 向 Teams 用户或会话发送任意 Adaptive Card JSON。
`card` 参数接受 Adaptive Card JSON 对象。提供 `card` 时,消息文本是可选的。
`card` 参数接受 Adaptive Card JSON 对象。提供 `card` 时,消息文本是可选的。
**智能体工具:**
@@ -636,11 +631,11 @@ openclaw message send --channel msteams \
--card '{"type":"AdaptiveCard","version":"1.5","body":[{"type":"TextBlock","text":"Hello!"}]}'
```
参见 [Adaptive Cards 文档](https://adaptivecards.io/)了解卡片模式和示例。目标格式详情见下方[目标格式](#target-formats)。
卡片 schema 和示例请参见 [Adaptive Cards 文档](https://adaptivecards.io/)。目标格式详情请参见下方[目标格式](#目标格式)。
## 目标格式
MSTeams 目标使用前缀区分用户和会话:
Microsoft Teams 目标使用前缀区分用户和会话:
| 目标类型 | 格式 | 示例 |
| ----------------- | -------------------------------- | ------------------------------------------------- |
@@ -690,12 +685,12 @@ openclaw message send --channel msteams --target "conversation:19:abc...@thread.
}
```
注意:没有 `user:` 前缀时,名称默认解析为群组/团队。显示名称定位人员时始终使用 `user:`。
注意:不带 `user:` 前缀时,名称默认解析为群组/团队。通过显示名称定位人员时始终使用 `user:`。
## 主动消息
- 主动消息仅在用户交互**之后**才可能,因为我们在那存储会话引用。
- 有关 `dmPolicy` 和允许列表控制,请参见 `/gateway/configuration`。
- 主动消息仅在用户**已交互后**才可能,因为我们在那个时候存储会话引用。
- `dmPolicy` 和允许列表控请参见 `/gateway/configuration`。
## 团队和频道 ID常见陷阱
@@ -719,8 +714,8 @@ https://teams.microsoft.com/l/channel/19%3A15bc...%40thread.tacv2/ChannelName?gr
**用于配置:**
- 团队 ID = `/team/` 后的路径段URL 解码,例如 `19:Bk4j...@thread.tacv2`
- 频道 ID = `/channel/` 后的路径段URL 解码)
- 团队 ID = `/team/` 后的路径段URL 解码,例如 `19:Bk4j...@thread.tacv2`
- 频道 ID = `/channel/` 后的路径段URL 解码
- **忽略** `groupId` 查询参数
## 私有频道
@@ -730,12 +725,12 @@ https://teams.microsoft.com/l/channel/19%3A15bc...%40thread.tacv2/ChannelName?gr
| 功能 | 标准频道 | 私有频道 |
| ------------------- | -------- | ---------------- |
| 机器人安装 | 是 | 有限 |
| 实时消息webhook | 是 | 可能不工作 |
| 实时消息webhook | 是 | 可能不可用 |
| RSC 权限 | 是 | 行为可能不同 |
| @提及 | 是 | 如果机器人可访问 |
| Graph API 历史 | 是 | 是(权限) |
| Graph API 历史 | 是 | 是(需要权限) |
**如果私有频道不工作的变通方**
**私有频道不可用时的变通方**
1. 使用标准频道进行机器人交互
2. 使用私信 - 用户始终可以直接给机器人发消息
@@ -745,31 +740,31 @@ https://teams.microsoft.com/l/channel/19%3A15bc...%40thread.tacv2/ChannelName?gr
### 常见问题
- **频道中图片不显示:** 缺少 Graph 权限或管理员同意。重新安装 Teams 应用并完全退出/重新打开 Teams。
- **频道中响应:** 默认需要提及;设置 `channels.msteams.requireMention=false` 或按团队/频道配置。
- **版本不匹配Teams 仍显示旧清单):** 移除 + 重新添加应用完全退出 Teams 以刷新。
- **来自 webhook 401 Unauthorized** 在没有 Azure JWT 的情况下手动测试时属于预期情况 - 意味着端点可达但认证失败。使用 Azure Web Chat 正确测试。
- **频道中图片不显示:** Graph 权限或管理员同意缺失。重新安装 Teams 应用并完全退出/重新打开 Teams。
- **频道中没有响应:** 默认需要提及;设置 `channels.msteams.requireMention=false` 或按团队/频道配置。
- **版本不匹配Teams 仍显示旧清单):** 移除重新添加应用完全退出 Teams 以刷新。
- **Webhook 返回 401 Unauthorized** 在没有 Azure JWT 的情况下手动测试时这是预期的 - 表示端点可达但认证失败。使用 Azure Web Chat 进行正确测试。
### 清单上传错误
- **"Icon file cannot be empty"** 清单引用的图标文件为 0 字节。创建有效的 PNG 图标(`outline.png` 32x32`color.png` 192x192
- **"webApplicationInfo.Id already in use"** 应用仍安装在另一个团队/聊天中。先找到并卸载它,或等待 5-10 分钟让其传播。
- **上传时"Something went wrong"** 改为通过 https://admin.teams.microsoft.com 上传,打开浏览器 DevToolsF12→ Network 选项卡,检查响应正文中的实际错误。
- **载失败:** 尝试"Upload an app to your org's app catalog"而不是"Upload a custom app" - 这通常可以绕过载限制。
- **"Icon file cannot be empty"** 清单引用了 0 字节的图标文件。创建有效的 PNG 图标(`outline.png` 32x32`color.png` 192x192
- **"webApplicationInfo.Id already in use"** 应用仍安装在其他团队/聊天中。先找到并卸载它,或等待 5-10 分钟传播。
- **上传时显示"Something went wrong"** 改为通过 https://admin.teams.microsoft.com 上传,打开浏览器 DevToolsF12→ Network 标签页,检查响应中的实际错误。
- **旁加载失败:** 尝试"Upload an app to your org's app catalog"而"Upload a custom app" - 这通常可以绕过旁加载限制。
### RSC 权限不工作
### RSC 权限不生效
1. 验证 `webApplicationInfo.id` 与你的机器人 App ID 完全匹配
2. 重新上传应用并在团队/聊天中重新安装
3. 检查你的组织管理员是否阻止了 RSC 权限
4. 确认你使用的是正确的范围:团队使用 `ChannelMessage.Read.Group`群聊使用 `ChatMessage.Read.Chat`
4. 确认你使用正确的范围:`ChannelMessage.Read.Group` 用于团队`ChatMessage.Read.Chat` 用于群聊
## 参考资料
## 参考
- [创建 Azure Bot](https://learn.microsoft.com/en-us/azure/bot-service/bot-service-quickstart-registration) - Azure Bot 设置指南
- [Teams 开发者门户](https://dev.teams.microsoft.com/apps) - 创建/管理 Teams 应用
- [Teams 应用清单模式](https://learn.microsoft.com/en-us/microsoftteams/platform/resources/schema/manifest-schema)
- [Teams 应用清单 schema](https://learn.microsoft.com/en-us/microsoftteams/platform/resources/schema/manifest-schema)
- [使用 RSC 接收频道消息](https://learn.microsoft.com/en-us/microsoftteams/platform/bots/how-to/conversations/channel-messages-with-rsc)
- [RSC 权限参考](https://learn.microsoft.com/en-us/microsoftteams/platform/graph-api/rsc/resource-specific-consent)
- [Teams 机器人文件处理](https://learn.microsoft.com/en-us/microsoftteams/platform/bots/how-to/bots-filesv4)(频道/群组需要 Graph
- [Teams bot 文件处理](https://learn.microsoft.com/en-us/microsoftteams/platform/bots/how-to/bots-filesv4)(频道/群组需要 Graph
- [主动消息](https://learn.microsoft.com/en-us/microsoftteams/platform/bots/how-to/conversations/send-proactive-messages)

View File

@@ -1,54 +1,53 @@
---
read_when:
- 开发 Nextcloud Talk 渠道功能
- 开发 Nextcloud Talk 渠道功能
summary: Nextcloud Talk 支持状态、功能和配置
title: Nextcloud Talk
x-i18n:
generated_at: "2026-02-03T10:04:00Z"
generated_at: "2026-02-01T19:26:32Z"
model: claude-opus-4-5
provider: pi
source_hash: 21b7b9756c4356a76dc0f14c10e44ed74a284cf3badf87e2df75eb88d8a90c31
source_path: channels/nextcloud-talk.md
workflow: 15
workflow: 14
---
# Nextcloud Talk插件
状态通过插件支持webhook 机器人)。支持私信、房间、表情回应和 Markdown 消息。
状态通过插件支持webhook 机器人)。支持私信、房间、回应和 markdown 消息。
## 需要插件
Nextcloud Talk 以插件形式提供,不包含在核心安装中。
Nextcloud Talk 作为插件发布,不包含在核心安装中。
通过 CLI 安装npm 仓库
通过 CLI 安装npm 注册表
```bash
openclaw plugins install @openclaw/nextcloud-talk
```
本地检出安装(从 git 仓库运行时):
本地检出(从 git 仓库运行时):
```bash
openclaw plugins install ./extensions/nextcloud-talk
```
如果你在配置/新手引导过程中选择了 Nextcloud Talk,并且检测到 git 检出,
OpenClaw 将自动提供本地安装路径。
如果你在配置/新手引导期间选择了 Nextcloud Talk检测到 git 检出,OpenClaw 会自动提供本地安装路径。
详情:[插件](/plugin)
## 快速设置(新手)
1. 安装 Nextcloud Talk 插件。
2. 在你的 Nextcloud 服务器上创建机器人:
2. 在你的 Nextcloud 服务器上创建一个机器人:
```bash
./occ talk:bot:install "OpenClaw" "<shared-secret>" "<webhook-url>" --feature reaction
```
3. 在目标房间设置中启用机器人。
3. 在目标房间设置中启用机器人。
4. 配置 OpenClaw
- 配置`channels.nextcloud-talk.baseUrl` + `channels.nextcloud-talk.botSecret`
- 配置:`channels.nextcloud-talk.baseUrl` + `channels.nextcloud-talk.botSecret`
- 或环境变量:`NEXTCLOUD_TALK_BOT_SECRET`(仅默认账户)
5. 重启 Gateway 网关(或完成新手引导)。
5. 重启 Gateway网关或完成新手引导
最小配置:
@@ -67,23 +66,23 @@ OpenClaw 将自动提供本地安装路径。
## 注意事项
- 机器人无法主动发起私信。用户必须先机器人发消息。
- Webhook URL 必须被 Gateway 网关访问;如果在代理后面,请设置 `webhookPublicUrl`。
- 机器人无法主动发起私信。用户必须先机器人发消息。
- Webhook URL 必须被 Gateway网关访问如果在代理后面请设置 `webhookPublicUrl`。
- 机器人 API 不支持媒体上传;媒体以 URL 形式发送。
- Webhook 载荷无法区分私信和房间;设置 `apiUser` + `apiPassword` 以启用房间类型查询(否则私信被视为房间)。
- Webhook 负载不区分私信和房间;设置 `apiUser` + `apiPassword` 以启用房间类型查询(否则私信被视为房间)。
## 访问控制(私信)
- 默认:`channels.nextcloud-talk.dmPolicy = "pairing"`。未知发送者收到配对码。
- 批准方式
- 默认:`channels.nextcloud-talk.dmPolicy = "pairing"`。未知发送者收到配对码。
- 通过以下方式批准:
- `openclaw pairing list nextcloud-talk`
- `openclaw pairing approve nextcloud-talk <CODE>`
- 公开私信:`channels.nextcloud-talk.dmPolicy="open"` 加上 `channels.nextcloud-talk.allowFrom=["*"]`。
## 房间(群组)
- 默认:`channels.nextcloud-talk.groupPolicy = "allowlist"`需要提及触发)。
- 使用 `channels.nextcloud-talk.rooms` 设置房间白名单
- 默认:`channels.nextcloud-talk.groupPolicy = "allowlist"`提及门控)。
- 使用 `channels.nextcloud-talk.rooms` 允许列表中的房间
```json5
{
@@ -97,17 +96,17 @@ OpenClaw 将自动提供本地安装路径。
}
```
- 如需禁止所有房间,保持白名单为空或设置 `channels.nextcloud-talk.groupPolicy="disabled"`。
- 要不允许任何房间,保持允许列表为空或设置 `channels.nextcloud-talk.groupPolicy="disabled"`。
## 功能支持
## 功能
| 功能 | 状态 |
| -------- | ------ |
| 私信 | 支持 |
| 房间 | 支持 |
| 话题 | 不支持 |
| 线程 | 不支持 |
| 媒体 | 仅 URL |
| 表情回应 | 支持 |
| 回应 | 支持 |
| 原生命令 | 不支持 |
## 配置参考Nextcloud Talk
@@ -128,15 +127,15 @@ OpenClaw 将自动提供本地安装路径。
- `channels.nextcloud-talk.webhookPath`webhook 路径(默认:/nextcloud-talk-webhook
- `channels.nextcloud-talk.webhookPublicUrl`:外部可达的 webhook URL。
- `channels.nextcloud-talk.dmPolicy``pairing | allowlist | open | disabled`。
- `channels.nextcloud-talk.allowFrom`:私信白名单(用户 ID。`open` 需要 `"*"`。
- `channels.nextcloud-talk.allowFrom`:私信允许列表(用户 ID。`open` 需要 `"*"`。
- `channels.nextcloud-talk.groupPolicy``allowlist | open | disabled`。
- `channels.nextcloud-talk.groupAllowFrom`:群组白名单(用户 ID
- `channels.nextcloud-talk.rooms`每个房间设置和白名单
- `channels.nextcloud-talk.historyLimit`:群组历史记录限制0 表示禁用)。
- `channels.nextcloud-talk.dmHistoryLimit`:私信历史记录限制0 表示禁用)。
- `channels.nextcloud-talk.dms`每个私信覆盖设置historyLimit
- `channels.nextcloud-talk.textChunkLimit`:出站文本分块大小(字符)。
- `channels.nextcloud-talk.chunkMode``length`(默认)或 `newline`,在长度分块前按空行(段落边界)分割。
- `channels.nextcloud-talk.groupAllowFrom`:群组允许列表(用户 ID
- `channels.nextcloud-talk.rooms`房间设置和允许列表
- `channels.nextcloud-talk.historyLimit`群组历史限制0 禁用)。
- `channels.nextcloud-talk.dmHistoryLimit`私信历史限制0 禁用)。
- `channels.nextcloud-talk.dms`私信覆盖historyLimit
- `channels.nextcloud-talk.textChunkLimit`:出站文本分块大小(字符)。
- `channels.nextcloud-talk.chunkMode``length`(默认)或 `newline`,在长度分块前按空行(段落边界)分割。
- `channels.nextcloud-talk.blockStreaming`:禁用此渠道的分块流式传输。
- `channels.nextcloud-talk.blockStreamingCoalesce`:分块流式传输合并调优。
- `channels.nextcloud-talk.mediaMaxMb`:入站媒体大小上限MB
- `channels.nextcloud-talk.mediaMaxMb`入站媒体上限MB

View File

@@ -1,37 +1,37 @@
---
read_when:
-希望 OpenClaw 通过 Nostr 接收私信
-想让 OpenClaw 通过 Nostr 接收私信
- 你正在设置去中心化消息
summary: 通过 NIP-04 加密消息的 Nostr 私信渠道
title: Nostr
x-i18n:
generated_at: "2026-02-03T07:44:13Z"
generated_at: "2026-02-01T19:26:55Z"
model: claude-opus-4-5
provider: pi
source_hash: 6b9fe4c74bf5e7c0f59bbaa129ec5270fd29a248551a8a9a7dde6cff8fb46111
source_path: channels/nostr.md
workflow: 15
workflow: 14
---
# Nostr
**状态:** 可选插件(默认禁用)。
Nostr 是一个去中心化的社交网络协议。此渠道使 OpenClaw 能够通过 NIP-04 接收和回复加密私信(DMs)。
Nostr 是一个去中心化的社交网络协议。此渠道使 OpenClaw 能够通过 NIP-04 接收和回复加密私信(私信)。
## 安装(按需)
### 新手引导(推荐)
- 新手引导向导(`openclaw onboard`)和 `openclaw channels add` 会列出可选的渠道插件。
- 选择 Nostr 会提示你按需安装插件。
- 选择 Nostr 会提示你按需安装插件。
安装默认
安装默认行为
- **Dev 渠道 + git checkout 可用** 使用本地插件路径。
- **Stable/Beta** 从 npm 下载。
- **开发渠道 + 可用 git 检出** 使用本地插件路径。
- **稳定版/测试版** 从 npm 下载。
你可以随时在提示中覆盖选择。
始终可以在提示中覆盖选择。
### 手动安装
@@ -39,13 +39,13 @@ Nostr 是一个去中心化的社交网络协议。此渠道使 OpenClaw 能够
openclaw plugins install @openclaw/nostr
```
使用本地 checkout(开发工作流):
使用本地检出(开发工作流):
```bash
openclaw plugins install --link <path-to-openclaw>/extensions/nostr
```
安装或启用插件后重启 Gateway 网关。
安装或启用插件后重启 Gateway网关。
## 快速设置
@@ -74,7 +74,7 @@ nak key generate
export NOSTR_PRIVATE_KEY="nsec1..."
```
4. 重启 Gateway 网关。
4. 重启 Gateway网关。
## 配置参考
@@ -90,7 +90,7 @@ export NOSTR_PRIVATE_KEY="nsec1..."
## 个人资料元数据
个人资料数据作为 NIP-01 `kind:0` 事件发布。你可以从控制界面Channels -> Nostr -> Profile管理它或直接在配置中设置。
个人资料数据作为 NIP-01 `kind:0` 事件发布。你可以从控制 UIChannels -> Nostr -> Profile管理它或直接在配置中设置。
示例:
@@ -124,9 +124,9 @@ export NOSTR_PRIVATE_KEY="nsec1..."
### 私信策略
- **pairing**(默认):未知发送者会收到配对码。
- **allowlist**:只有 `allowFrom` 中的公钥可以发私信。
- **open**:公开接收私信(需要 `allowFrom: ["*"]`)。
- **disabled**:忽略接收的私信。
- **allowlist**:只有 `allowFrom` 中的公钥可以发私信。
- **open**:公开入站私信(需要 `allowFrom: ["*"]`)。
- **disabled**:忽略入站私信。
### 允许列表示例
@@ -164,20 +164,20 @@ export NOSTR_PRIVATE_KEY="nsec1..."
}
```
提示
建议
- 使用 2-3 个中继以实现冗余。
- 避免使用过多中继(延迟、重复)。
- 付费中继可以提高可靠性。
- 本地中继适测试(`ws://localhost:7777`)。
- 本地中继适用于测试(`ws://localhost:7777`)。
## 协议支持
| NIP | 状态 | 描述 |
| ------ | ------ | ----------------------------- |
| NIP-01 | 支持 | 基本事件格式 + 个人资料元数据 |
| NIP-04 | 支持 | 加密私信(`kind:4` |
| NIP-17 | 计划中 | 礼物包装私信 |
| NIP-01 | 支持 | 基本事件格式 + 个人资料元数据 |
| NIP-04 | 支持 | 加密私信(`kind:4` |
| NIP-17 | 计划中 | Gift-wrapped 私信 |
| NIP-44 | 计划中 | 版本化加密 |
## 测试
@@ -203,38 +203,38 @@ docker run -p 7777:7777 ghcr.io/hoytech/strfry
### 手动测试
1. 从日志中记下机器人公钥npub
2. 打开 Nostr 客户端Damus、Amethyst 等)。
3. 机器人公钥发送私信
4. 验证响应
2. 打开一个 Nostr 客户端Damus、Amethyst 等)。
3. 私信机器人公钥。
4. 验证回复
## 故障排除
### 收到消息
### 无法收到消息
- 验证私钥是否有效。
- 确保中继 URL 可访问并使用 `wss://`(本地使用 `ws://`)。
- 确认 `enabled` 不是 `false`
- 检查 Gateway 网关日志中的中继连接错误。
- 确保中继 URL 可并使用 `wss://`(本地使用 `ws://`)。
- 确认 `enabled` 未设为 `false`
- 检查 Gateway网关日志中的中继连接错误。
### 未发送响应
### 无法发送回复
- 检查中继是否接受写入。
- 验证出站连接。
- 注意中继速率限制。
### 重复响应
### 重复回复
- 使用多个中继时属于正常现象
- 消息按事件 ID 去重;只有次投递会触发响应
- 使用多个中继时属于预期行为
- 消息按事件 ID 去重;只有第一次投递会触发回复
## 安全
- 切勿提交私钥。
- 绝不提交私钥。
- 使用环境变量存储密钥。
- 生产环境机器人考虑使用 `allowlist`
- 生产机器人考虑使用 `allowlist`
## 限制MVP
- 仅支持私信(不支持群聊)。
- 仅支持私信(群聊)。
- 不支持媒体附件。
- 仅支持 NIP-04计划支持 NIP-17 礼物包装)。
- 仅支持 NIP-04计划支持 NIP-17 gift-wrap)。

View File

@@ -1,29 +1,29 @@
---
read_when:
- 设置 Signal 支持
- 调试 Signal 发送/接
summary: 通过 signal-cliJSON-RPC + SSE支持 Signal设置和号码模型
- 调试 Signal 收
summary: 通过 signal-cliJSON-RPC + SSE实现 Signal 支持、设置和号码模型
title: Signal
x-i18n:
generated_at: "2026-02-03T07:44:15Z"
generated_at: "2026-02-01T19:27:25Z"
model: claude-opus-4-5
provider: pi
source_hash: ca4de8b3685017f54a959e3e2699357ab40b3e4e68574bd7fb5739e4679e7d8a
source_path: channels/signal.md
workflow: 15
workflow: 14
---
# Signal (signal-cli)
# Signalsignal-cli
状态:外部 CLI 集成。Gateway 网关通过 HTTP JSON-RPC + SSE 与 `signal-cli` 通信。
状态:外部 CLI 集成。Gateway网关通过 HTTP JSON-RPC + SSE 与 `signal-cli` 通信。
## 快速设置(初学者
## 快速设置(新手
1. bot 使用**单独的 Signal 号码**(推荐)。
1.机器人使用一个**单独的 Signal 号码**(推荐)。
2. 安装 `signal-cli`(需要 Java
3. 链接 bot 设备并启动守护进程:
3. 链接机器人设备并启动守护进程:
- `signal-cli link -n "OpenClaw"`
4. 配置 OpenClaw 并启动 Gateway 网关。
4. 配置 OpenClaw 并启动 Gateway网关。
最小配置:
@@ -44,14 +44,14 @@ x-i18n:
## 它是什么
- 通过 `signal-cli` 的 Signal 渠道(非嵌入式 libsignal
- 确定性路由:回复始终返回到 Signal。
- 确定性路由:回复始终发回 Signal。
- 私信共享智能体的主会话;群组是隔离的(`agent:<agentId>:signal:group:<groupId>`)。
## 配置写入
默认情况下Signal 允许写入由 `/config set|unset` 触发的配置更新(需要 `commands.config: true`)。
默认情况下Signal 允许通过 `/config set|unset` 触发的配置更新写入(需要 `commands.config: true`)。
禁用方式
通过以下方式禁用:
```json5
{
@@ -61,16 +61,16 @@ x-i18n:
## 号码模型(重要)
- Gateway 网关连接到一个 **Signal 设备**`signal-cli` 账户)。
- 如果你在**个人 Signal 账户**上运行 bot,它会忽略你自己的消息(循环保护)。
- 要实现"我发消息给 bot 然后它回复",请使用**单独的 bot 号码**。
- Gateway网关连接到一个 **Signal 设备**`signal-cli` 账户)。
- 如果你在**个人 Signal 账户**上运行机器人,它会忽略你自己的消息(循环保护)。
- 要实现"我给机器人发消息它回复",请使用一个**单独的机器人号码**。
## 设置(快速路径)
1. 安装 `signal-cli`(需要 Java
2. 链接 bot 账户:
2. 链接机器人账户:
- `signal-cli link -n "OpenClaw"` 然后在 Signal 中扫描二维码。
3. 配置 Signal 并启动 Gateway 网关。
3. 配置 Signal 并启动 Gateway网关。
示例:
@@ -88,11 +88,11 @@ x-i18n:
}
```
多账户支持:使用 `channels.signal.accounts` 配置每个账户可选的 `name`。共享模式请参 [`gateway/configuration`](/gateway/configuration#telegramaccounts--discordaccounts--slackaccounts--signalaccounts--imessageaccounts)。
多账户支持:使用 `channels.signal.accounts`每个账户配置独立选项和可选的 `name`。共享模式请参 [`gateway/configuration`](/gateway/configuration#telegramaccounts--discordaccounts--slackaccounts--signalaccounts--imessageaccounts)。
## 外部守护进程模式httpUrl
如果你想自管理 `signal-cli`JVM 冷启动慢、容器初始化或共享 CPU单独运行守护进程并将 OpenClaw 指向它:
如果你想自管理 `signal-cli`JVM 冷启动慢、容器初始化或共享 CPU可以单独运行守护进程并将 OpenClaw 指向它:
```json5
{
@@ -105,19 +105,19 @@ x-i18n:
}
```
这会跳过自动启动和 OpenClaw 内部的启动等待。对于自动启动时的慢启动,请设置 `channels.signal.startupTimeoutMs`
这会跳过 OpenClaw 内部的自动启动和启动等待。自动启动较慢时,请设置 `channels.signal.startupTimeoutMs`
## 访问控制(私信 + 群组)
私信:
- 默认:`channels.signal.dmPolicy = "pairing"`
- 未知发送者会收到配对码;消息在批准会被忽略(配对码 1 小时后过期)。
- 未知发送者会收到配对码;在批准之前消息会被忽略(配对码 1 小时后过期)。
- 通过以下方式批准:
- `openclaw pairing list signal`
- `openclaw pairing approve signal <CODE>`
- 配对是 Signal 私信的默认令牌交换方式。详情:[配对](/start/pairing)
- UUID 的发送者(来自 `sourceUuid`)在 `channels.signal.allowFrom`存储为 `uuid:<id>`
- 仅 UUID 的发送者(来自 `sourceUuid``uuid:<id>` 形式存储`channels.signal.allowFrom` 中。
群组:
@@ -126,31 +126,31 @@ x-i18n:
## 工作原理(行为)
- `signal-cli` 作为守护进程运行Gateway 网关通过 SSE 读取事件。
- 入站消息被规范化为共享渠道信封。
- 回复始终路由回同一号码或群组。
- `signal-cli` 作为守护进程运行Gateway网关通过 SSE 读取事件。
- 入站消息被标准化为共享渠道信封。
- 回复始终路由回同一号码或群组。
## 媒体 + 限制
- 出站文本按 `channels.signal.textChunkLimit` 分块(默认 4000
- 可选换行分块:设置 `channels.signal.chunkMode="newline"` 在长度分块前按空行(段落边界)分割。
- 可选换行分块:设置 `channels.signal.chunkMode="newline"`长度分块前按空行(段落边界)分割。
- 支持附件(从 `signal-cli` 获取 base64
- 默认媒体上限:`channels.signal.mediaMaxMb`(默认 8
- 使用 `channels.signal.ignoreAttachments` 跳过下载媒体。
- 群组历史上下文使用 `channels.signal.historyLimit`(或 `channels.signal.accounts.*.historyLimit`),回退到 `messages.groupChat.historyLimit`。设置 `0` 禁用(默认 50
- 使用 `channels.signal.ignoreAttachments` 跳过媒体下载
- 群组历史上下文使用 `channels.signal.historyLimit`(或 `channels.signal.accounts.*.historyLimit`),回退到 `messages.groupChat.historyLimit`。设置 `0` 禁用(默认 50
## 输入指示 + 已读回执
## 输入指示 + 已读回执
- **输入指示**OpenClaw 通过 `signal-cli sendTyping` 发送输入信号,并在回复运行时刷新它们
- **输入指示**OpenClaw 通过 `signal-cli sendTyping` 发送输入信号,并在回复运行期间刷新
- **已读回执**:当 `channels.signal.sendReadReceipts` 为 true 时OpenClaw 为允许的私信转发已读回执。
- Signal-cli 不暴露群组的已读回执。
- signal-cli 不暴露群组的已读回执。
## 表情回应message 工具)
## 回应message 工具)
- 使用 `message action=react` 配合 `channel=signal`
- 目标:发送者 E.164 或 UUID使用配对输出中的 `uuid:<id>`;裸 UUID 也可以)。
- `messageId` 是你要回应的消息的 Signal 时间戳。
- 群组表情回应需要 `targetAuthor``targetAuthorUuid`
- 群组回应需要 `targetAuthor``targetAuthorUuid`
示例:
@@ -162,13 +162,13 @@ message action=react channel=signal target=signal:group:<groupId> targetAuthor=u
配置:
- `channels.signal.actions.reactions`:启用/禁用表情回应操作(默认 true
- `channels.signal.actions.reactions`:启用/禁用回应操作(默认 true
- `channels.signal.reactionLevel``off | ack | minimal | extensive`
- `off`/`ack` 禁用智能体表情回应message 工具 `react` 会报错)。
- `minimal`/`extensive` 启用智能体表情回应并设置导级别。
- 账户覆盖:`channels.signal.accounts.<id>.actions.reactions``channels.signal.accounts.<id>.reactionLevel`
- `off`/`ack` 禁用智能体回应message 工具 `react` 会报错)。
- `minimal`/`extensive` 启用智能体回应并设置导级别。
- 账户覆盖:`channels.signal.accounts.<id>.actions.reactions``channels.signal.accounts.<id>.reactionLevel`
## 投递目标CLI/cron
## 投递目标CLI/定时任务
- 私信:`signal:+15551234567`(或纯 E.164)。
- UUID 私信:`uuid:<id>`(或裸 UUID
@@ -182,24 +182,24 @@ message action=react channel=signal target=signal:group:<groupId> targetAuthor=u
提供商选项:
- `channels.signal.enabled`:启用/禁用渠道启动。
- `channels.signal.account`bot 账户的 E.164。
- `channels.signal.account`机器人账户的 E.164。
- `channels.signal.cliPath``signal-cli` 的路径。
- `channels.signal.httpUrl`:完整守护进程 URL覆盖 host/port
- `channels.signal.httpHost``channels.signal.httpPort`:守护进程绑定(默认 127.0.0.1:8080
- `channels.signal.autoStart`:自动启动守护进程(如果未设置 `httpUrl` 默认 true
- `channels.signal.startupTimeoutMs`:启动等待超时毫秒(上限 120000
- `channels.signal.autoStart`:自动启动守护进程(未设置 `httpUrl` 默认 true
- `channels.signal.startupTimeoutMs`:启动等待超时,单位毫秒(上限 120000
- `channels.signal.receiveMode``on-start | manual`
- `channels.signal.ignoreAttachments`:跳过附件下载。
- `channels.signal.ignoreStories`:忽略来自守护进程的动态。
- `channels.signal.sendReadReceipts`:转发已读回执。
- `channels.signal.dmPolicy``pairing | allowlist | open | disabled`默认pairing
- `channels.signal.allowFrom`私信允许列表E.164 或 `uuid:<id>`)。`open` 需要 `"*"`。Signal 没有用户名;使用电话/UUID id
- `channels.signal.allowFrom`私信允许列表E.164 或 `uuid:<id>`)。`open` 需要 `"*"`。Signal 没有用户名;使用电话/UUID 标识
- `channels.signal.groupPolicy``open | allowlist | disabled`默认allowlist
- `channels.signal.groupAllowFrom`:群组发送者允许列表。
- `channels.signal.historyLimit`为上下文包含的最大群组消息数0 禁用)。
- `channels.signal.dmHistoryLimit`:私信历史限制(用户轮次)。用户覆盖:`channels.signal.dms["<phone_or_uuid>"].historyLimit`
- `channels.signal.historyLimit`包含为上下文的最大群组消息数0 禁用)。
- `channels.signal.dmHistoryLimit`:私信历史限制(用户回合数)。用户覆盖:`channels.signal.dms["<phone_or_uuid>"].historyLimit`
- `channels.signal.textChunkLimit`:出站分块大小(字符)。
- `channels.signal.chunkMode``length`(默认)或 `newline`长度分块前按空行(段落边界)分割。
- `channels.signal.chunkMode``length`(默认)或 `newline`,在按长度分块前按空行(段落边界)分割。
- `channels.signal.mediaMaxMb`:入站/出站媒体上限MB
相关全局选项:

View File

@@ -1,14 +1,14 @@
---
read_when: Setting up Slack or debugging Slack socket/HTTP mode
summary: Slack 的 socket 或 HTTP webhook 模式设置
read_when: 设置 Slack 或调试 Slack Socket/HTTP 模式
summary: Slack 的 Socket 或 HTTP webhook 模式设置
title: Slack
x-i18n:
generated_at: "2026-02-03T07:45:49Z"
generated_at: "2026-02-01T19:29:15Z"
model: claude-opus-4-5
provider: pi
source_hash: 703b4b4333bebfef26b64710ba452bdfc3e7d2115048d4e552e8659425b3609b
source_path: channels/slack.md
workflow: 15
workflow: 14
---
# Slack
@@ -19,7 +19,7 @@ x-i18n:
1. 创建一个 Slack 应用并启用 **Socket Mode**
2. 创建一个 **App Token**`xapp-...`)和 **Bot Token**`xoxb-...`)。
3. 为 OpenClaw 设置令牌并启动 Gateway 网关。
3. 为 OpenClaw 设置 token 并启动 Gateway网关。
最小配置:
@@ -37,10 +37,10 @@ x-i18n:
### 设置
1. 在 https://api.slack.com/apps 创建一个 Slack 应用(从头开始)。
2. **Socket Mode** → 开启。然后前往 **Basic Information****App-Level Tokens****Generate Token and Scopes**添加 `connections:write` 权限范围。复制 **App Token**`xapp-...`)。
3. **OAuth & Permissions** → 添加 bot token 权限范围(使用下面的 manifest)。点击 **Install to Workspace**。复制 **Bot User OAuth Token**`xoxb-...`)。
4. 可选:**OAuth & Permissions** → 添加 **User Token Scopes**(参见下面的只读列表)。重新安装应用并复制 **User OAuth Token**`xoxp-...`)。
1. 在 https://api.slack.com/apps 创建 Slack 应用(从头开始)。
2. **Socket Mode** → 开启。然后进入 **Basic Information****App-Level Tokens****Generate Token and Scopes**使用范围 `connections:write`。复制 **App Token**`xapp-...`)。
3. **OAuth & Permissions** → 添加 bot token 范围(使用下方清单)。点击 **Install to Workspace**。复制 **Bot User OAuth Token**`xoxb-...`)。
4. 可选:**OAuth & Permissions** → 添加 **User Token Scopes**(参见下只读列表)。重新安装应用并复制 **User OAuth Token**`xoxp-...`)。
5. **Event Subscriptions** → 启用事件并订阅:
- `message.*`(包括编辑/删除/线程广播)
- `app_mention`
@@ -49,16 +49,16 @@ x-i18n:
- `channel_rename`
- `pin_added``pin_removed`
6. 邀请机器人加入你希望它读取的频道。
7. Slash Commands → 如果你使用 `channels.slack.slashCommand`,创建 `/openclaw`。如果启用原生命令,为每个内置命令添加一个斜杠命令(名称与 `/help` 相同)。除非你设置 `channels.slack.commands.native: true`,否则 Slack 默认关闭原生命令(全局 `commands.native` `"auto"`Slack 保持关闭)。
8. App Home → 启用 **Messages Tab** 以便用户可以私信机器人。
7. Slash Commands → 如果你使用 `channels.slack.slashCommand`,创建 `/openclaw`。如果启用原生命令,为每个内置命令添加一个斜杠命令(名称与 `/help` 列表相同)。Slack 的原生命令默认关闭,除非你设置 `channels.slack.commands.native: true`(全局 `commands.native` `"auto"`Slack 下默认关闭)。
8. App Home → 启用 **Messages Tab** 以便用户可以机器人发私信
使用下面的 manifest 以保持权限范围和事件同步。
使用下方清单以保持范围和事件同步。
多账户支持:使用 `channels.slack.accounts` 配置每个账户的令牌和可选的 `name`参见 [`gateway/configuration`](/gateway/configuration#telegramaccounts--discordaccounts--slackaccounts--signalaccounts--imessageaccounts) 了解共享模式
多账户支持:使用 `channels.slack.accounts`每个账户配置独立 token 和可选的 `name`共享模式请参阅 [`gateway/configuration`](/gateway/configuration#telegramaccounts--discordaccounts--slackaccounts--signalaccounts--imessageaccounts)。
### OpenClaw 配置(最小)
通过环境变量设置令牌(推荐):
通过环境变量设置 token(推荐):
- `SLACK_APP_TOKEN=xapp-...`
- `SLACK_BOT_TOKEN=xoxb-...`
@@ -77,13 +77,13 @@ x-i18n:
}
```
### 用户令牌(可选)
### 用户 token(可选)
OpenClaw 可以使用 Slack 用户令牌`xoxp-...`)进行读取操作(历史记录、置顶、表情回应、表情符号、成员信息)。默认情况下保持只读:当存在用户令牌时,读取优先使用用户令牌,而写入仍使用 bot 令牌,除非你明确选择加入。即使设置了 `userTokenReadOnly: false`,当 bot 令牌可用时写入仍优先使用 bot 令牌
OpenClaw 可以使用 Slack 用户 token`xoxp-...`)进行读取操作(历史记录、置顶、回应、表情、成员信息)。默认保持只读:有用户 token 时读取操作优先使用它,写入仍使用 bot token,除非你明确选择。即使设置了 `userTokenReadOnly: false`,当 bot token 可用时写入操作仍优先使用
用户令牌在配置文件中置(不支持环境变量)。对于多账户设置 `channels.slack.accounts.<id>.userToken`
用户 token 在配置文件中置(不支持环境变量)。多账户设置 `channels.slack.accounts.<id>.userToken`
包含 bot + app + 用户令牌的示例:
同时使用 bot + app + user token 的示例:
```json5
{
@@ -98,7 +98,7 @@ OpenClaw 可以使用 Slack 用户令牌(`xoxp-...`)进行读取操作(历
}
```
明确设置 userTokenReadOnly 的示例(允许用户令牌写入):
显式设置 userTokenReadOnly 的示例(允许用户 token 写入):
```json5
{
@@ -114,27 +114,26 @@ OpenClaw 可以使用 Slack 用户令牌(`xoxp-...`)进行读取操作(历
}
```
#### 令牌使用
#### Token 使用
- 读取操作(历史记录、表情回应列表、置顶列表、表情符号列表、成员信息、搜索)在配置了用户令牌时优先使用用户令牌,否则使用 bot 令牌
- 写入操作(发送/编辑/删除消息、添加/移除表情回应、置顶/取消置顶、文件上传)默认使用 bot 令牌。如果 `userTokenReadOnly: false` 且没有可用的 bot 令牌OpenClaw 回退到用户令牌
- 读取操作(历史记录、回应列表、置顶列表、表情列表、成员信息、搜索)在配置了用户 token 时优先使用,否则使用 bot token
- 写入操作(发送/编辑/删除消息、添加/移除回应、置顶/取消置顶、文件上传)默认使用 bot token。如果 `userTokenReadOnly: false` 且没有 bot token 可用OpenClaw 回退到用户 token
### 历史上下文
- `channels.slack.historyLimit`(或 `channels.slack.accounts.*.historyLimit`)控制多少条最近的频道/群组消息包含提示中。
- 回退到 `messages.groupChat.historyLimit`。设置 `0` 禁用(默认 50
- `channels.slack.historyLimit`(或 `channels.slack.accounts.*.historyLimit`)控制多少条最近的频道/群组消息包含提示中。
- 回退到 `messages.groupChat.historyLimit`。设置 `0` 禁用(默认 50
## HTTP 模式Events API
当你的 Gateway 网关可通过 HTTPS 被 Slack 访问时(服务器部署的典型情况),使用 HTTP webhook 模式。
HTTP 模式使用 Events API + Interactivity + Slash Commands共享一个请求 URL。
当你的 Gateway网关可通过 HTTPS 被 Slack 访问时使用 HTTP webhook 模式适用于服务器部署。HTTP 模式使用 Events API + Interactivity + Slash Commands共享请求 URL
### 设置
1. 创建一个 Slack 应用并**禁用 Socket Mode**(如果你只使用 HTTP 则可选)。
1. 创建 Slack 应用并**禁用 Socket Mode**(如果你只使用 HTTP 则可选)。
2. **Basic Information** → 复制 **Signing Secret**
3. **OAuth & Permissions** → 安装应用并复制 **Bot User OAuth Token**`xoxb-...`)。
4. **Event Subscriptions** → 启用事件并将 **Request URL** 设置为你的 Gateway 网关 webhook 路径(默认 `/slack/events`)。
4. **Event Subscriptions** → 启用事件并将 **Request URL** 设置为你的 Gateway网关 webhook 路径(默认 `/slack/events`)。
5. **Interactivity & Shortcuts** → 启用并设置相同的 **Request URL**
6. **Slash Commands** → 为你的命令设置相同的 **Request URL**
@@ -159,9 +158,9 @@ HTTP 模式使用 Events API + Interactivity + Slash Commands共享一个请
多账户 HTTP 模式:设置 `channels.slack.accounts.<id>.mode = "http"` 并为每个账户提供唯一的 `webhookPath`,以便每个 Slack 应用可以指向自己的 URL。
### Manifest(可选)
### 清单(可选)
使用此 Slack 应用 manifest 快速创建应用(如果需要可以调整名称/命令)。如果你计划配置用户令牌,请包含用户权限范围。
使用此 Slack 应用清单可快速创建应用(根据需要调整名称/命令)。如果你计划配置用户 token,请包含用户范围。
```json
{
@@ -251,23 +250,23 @@ HTTP 模式使用 Events API + Interactivity + Slash Commands共享一个请
}
```
如果启用原生命令,为每个要公开的命令添加一个 `slash_commands` 条目( `/help` 列表匹配)。使用 `channels.slack.commands.native` 覆盖。
如果启用原生命令,为你想暴露的每个命令添加一个 `slash_commands` 条目(匹配 `/help` 列表)。通过 `channels.slack.commands.native` 覆盖。
## 权限范围(当前 vs 可选)
## 范围(当前 vs 可选)
Slack 的 Conversations API 按类型区分的:你只需要你实际接触的会话类型channels、groups、im、mpim权限范围。概参见 https://docs.slack.dev/apis/web-api/using-the-conversations-api/。
Slack 的 Conversations API 按类型设定范围:你只需要你实际使用的会话类型channels、groups、im、mpim对应的范围。概览请参见 https://docs.slack.dev/apis/web-api/using-the-conversations-api/。
### Bot 令牌权限范围(必需)
### Bot token 范围(必需)
- `chat:write`(通过 `chat.postMessage` 发送/更新/删除消息)
https://docs.slack.dev/reference/methods/chat.postMessage
- `im:write`(通过 `conversations.open` 打开私信用于用户私信)
- `im:write`(通过 `conversations.open` 打开用户私信)
https://docs.slack.dev/reference/methods/conversations.open
- `channels:history``groups:history``im:history``mpim:history`
https://docs.slack.dev/reference/methods/conversations.history
- `channels:read``groups:read``im:read``mpim:read`
https://docs.slack.dev/reference/methods/conversations.info
- `users:read`(用户查
- `users:read`(用户查
https://docs.slack.dev/reference/methods/users.info
- `reactions:read``reactions:write``reactions.get` / `reactions.add`
https://docs.slack.dev/reference/methods/reactions.get
@@ -280,9 +279,9 @@ Slack 的 Conversations API 是按类型区分的:你只需要你实际接触
- `files:write`(通过 `files.uploadV2` 上传)
https://docs.slack.dev/messaging/working-with-files/#upload
### 用户令牌权限范围(可选,默认只读)
### 用户 token 范围(可选,默认只读)
如果你配置了 `channels.slack.userToken`,在 **User Token Scopes** 下添加这些。
如果你配置了 `channels.slack.userToken`**User Token Scopes** 下添加这些。
- `channels:history``groups:history``im:history``mpim:history`
- `channels:read``groups:read``im:read``mpim:read`
@@ -292,19 +291,19 @@ Slack 的 Conversations API 是按类型区分的:你只需要你实际接触
- `emoji:read`
- `search:read`
### 目前不需要(但未来可能需要
### 目前不需要(但未来可能)
- `mpim:write`(仅我们添加群组私信打开/私信启动时通过 `conversations.open`
- `groups:write`(仅我们添加私有频道管理时:创建/重命名/邀请/归档)
- `chat:write.public`(仅我们想发布到机器人未加入的频道
- `mpim:write`(仅我们添加群组私信打开/私信开始功能时需要,通过 `conversations.open`
- `groups:write`(仅我们添加私有频道管理时需要:创建/重命名/邀请/归档)
- `chat:write.public`(仅我们想机器人未加入的频道发帖时需要
https://docs.slack.dev/reference/scopes/chat.write.public
- `users:read.email`(仅我们需要从 `users.info` 获取邮箱字段时)
- `users:read.email`(仅我们需要从 `users.info` 获取邮箱字段时需要
https://docs.slack.dev/changelog/2017-04-narrowing-email-access
- `files:read`(仅我们开始列出/读取文件元数据时)
- `files:read`(仅我们开始列出/读取文件元数据时需要
## 配置
Slack 仅使用 Socket Mode无 HTTP webhook 服务器)。提供两个令牌
Slack 仅使用 Socket Mode无 HTTP webhook 服务器)。提供两个 token
```json
{
@@ -353,40 +352,40 @@ Slack 仅使用 Socket Mode无 HTTP webhook 服务器)。提供两个令牌
}
```
令牌也可以通过环境变量提供:
Token 也可以通过环境变量提供:
- `SLACK_BOT_TOKEN`
- `SLACK_APP_TOKEN`
确认表情回应通过 `messages.ackReaction` + `messages.ackReactionScope` 全局控制。使用 `messages.removeAckAfterReply` 在机器人回复后清除确认表情回应。
确认回应由 `messages.ackReaction` + `messages.ackReactionScope` 全局控制。使用 `messages.removeAckAfterReply` 在机器人回复后清除确认回应。
## 限制
- 出站文本按 `channels.slack.textChunkLimit` 分块(默认 4000
- 可选的换行分块:设置 `channels.slack.chunkMode="newline"` 在长度分块之前按空行(段落边界)分割。
- 媒体上传 `channels.slack.mediaMaxMb` 限制(默认 20
- 可选的换行分块:设置 `channels.slack.chunkMode="newline"`长度分块之前按空行(段落边界)分割。
- 媒体上传上限由 `channels.slack.mediaMaxMb` 限制(默认 20
## 回复线程
默认情况下OpenClaw 在主频道回复。使用 `channels.slack.replyToMode` 控制自动线程:
默认情况下OpenClaw 在主频道回复。使用 `channels.slack.replyToMode` 控制自动线程行为
| 模式 | 行为 |
| ------- | -------------------------------------------------------------------------------------------- |
| `off` | **默认。** 在主频道回复。仅触发消息已在线程中时才使用线程。 |
| `first` | 第一条回复进入线程(在触发消息下),后续回复进入主频道。适保持上下文可见同时避免线程乱。 |
| `all` | 所有回复都进入线程。保持对话集中但可能降低可见性。 |
| 模式 | 行为 |
| ------- | ------------------------------------------------------------------------------------------------ |
| `off` | **默认。** 在主频道回复。仅触发消息已在线程中时才在线程中回复。 |
| `first` | 第一条回复进入线程(在触发消息下),后续回复进入主频道。适用于保持上下文可见同时避免线程乱。 |
| `all` | 所有回复都进入线程。保持对话集中但可能降低可见性。 |
该模式适用于自动回复和智能体工具调用(`slack sendMessage`)。
该模式同时适用于自动回复和智能体工具调用(`slack sendMessage`)。
### 按聊天类型线程
### 按聊天类型设置线程
你可以通过设置 `channels.slack.replyToModeByChatType`每种聊天类型配置不同的线程行为:
你可以通过设置 `channels.slack.replyToModeByChatType`不同聊天类型配置不同的线程行为:
```json5
{
channels: {
slack: {
replyToMode: "off", // 频道默认
replyToMode: "off", // 频道默认
replyToModeByChatType: {
direct: "all", // 私信始终使用线程
group: "first", // 群组私信/MPIM 第一条回复使用线程
@@ -400,7 +399,7 @@ Slack 仅使用 Socket Mode无 HTTP webhook 服务器)。提供两个令牌
- `direct`一对一私信Slack `im`
- `group`:群组私信 / MPIMSlack `mpim`
- `channel`:标准频道(公/私有)
- `channel`:标准频道(公/私有)
优先级:
@@ -408,11 +407,11 @@ Slack 仅使用 Socket Mode无 HTTP webhook 服务器)。提供两个令牌
2. `replyToMode`
3. 提供商默认值(`off`
当未设置聊天类型覆盖时,旧版 `channels.slack.dm.replyToMode`作为 `direct` 的回退。
旧版 `channels.slack.dm.replyToMode` 在未设置聊天类型覆盖时仍作为 `direct` 的回退
示例:
私信使用线程:
仅私信使用线程:
```json5
{
@@ -425,7 +424,7 @@ Slack 仅使用 Socket Mode无 HTTP webhook 服务器)。提供两个令牌
}
```
群组私信使用线程但保持频道在根级
群组私信使用线程但频道保持在根级:
```json5
{
@@ -438,7 +437,7 @@ Slack 仅使用 Socket Mode无 HTTP webhook 服务器)。提供两个令牌
}
```
频道使用线程,保持私信在根级
频道使用线程,私信保持在根级:
```json5
{
@@ -453,79 +452,79 @@ Slack 仅使用 Socket Mode无 HTTP webhook 服务器)。提供两个令牌
### 手动线程标签
对于细粒度控制,在智能体响应中使用这些标签:
对于细控制,在智能体回复中使用以下标签:
- `[[reply_to_current]]` — 回复触发消息(开始/继续线程)。
- `[[reply_to:<id>]]` — 回复特定消息 id
- `[[reply_to:<id>]]` — 回复特定消息 ID
## 会话 + 路由
- 私信共享 `main` 会话(与 WhatsApp/Telegram 相同)。
- 私信共享 `main` 会话(与 WhatsApp/Telegram 类似)。
- 频道映射到 `agent:<agentId>:slack:channel:<channelId>` 会话。
- 斜杠命令使用 `agent:<agentId>:slack:slash:<userId>` 会话(前缀可通过 `channels.slack.slashCommand.sessionPrefix` 配置)。
- 如果 Slack 提供 `channel_type`OpenClaw 从频道 ID 前缀(`D``C``G`)推断并默认为 `channel` 以保持会话键稳定。
- 原生命令注册使用 `commands.native`(全局默认 `"auto"` → Slack 关闭),可以使用 `channels.slack.commands.native` 按工作空间覆盖。文本命令需要独立的 `/...` 消息,可以使用 `commands.text: false` 禁用。Slack 斜杠命令在 Slack 应用中管理,不会自动移除。使用 `commands.useAccessGroups: false` 绕过命令的访问组检查。
- 如果 Slack 提供 `channel_type`OpenClaw 从频道 ID 前缀(`D``C``G`)推断并默认为 `channel` 以保持会话键稳定。
- 原生命令注册使用 `commands.native`(全局默认 `"auto"` → Slack 关闭),可通过 `channels.slack.commands.native` 按工作覆盖。文本命令需要独立的 `/...` 消息,可通过 `commands.text: false` 禁用。Slack 斜杠命令在 Slack 应用中管理,不会自动移除。使用 `commands.useAccessGroups: false` 绕过命令的访问组检查。
- 完整命令列表 + 配置:[斜杠命令](/tools/slash-commands)
## 私信安全(配对)
- 默认:`channels.slack.dm.policy="pairing"` — 未知私信发送者会收到配对码1 小时后过期)。
- 通过以下方式批准:`openclaw pairing approve slack <code>`
- 默认:`channels.slack.dm.policy="pairing"` — 未知私信发送者会收到配对码1 小时后过期)。
- 通过 `openclaw pairing approve slack <code>` 批准
- 要允许任何人:设置 `channels.slack.dm.policy="open"``channels.slack.dm.allowFrom=["*"]`
- `channels.slack.dm.allowFrom` 接受用户 ID、@用户名或邮箱在令牌允许时启动时解析)。向导在设置期间接受用户名,并在令牌允许时将其解析为 ID。
- `channels.slack.dm.allowFrom` 接受用户 ID、@用户名或邮箱启动时当 token 允许时解析)。向导在设置期间当 token 允许时接受用户名并将其解析为 ID。
## 群组策略
- `channels.slack.groupPolicy` 控制频道处理(`open|disabled|allowlist`)。
- `allowlist`频道列在 `channels.slack.channels` 中。
- 如果你只设置了 `SLACK_BOT_TOKEN`/`SLACK_APP_TOKEN` 从未创建 `channels.slack` 部分,运行时默认将 `groupPolicy` 设为 `open`。添加 `channels.slack.groupPolicy``channels.defaults.groupPolicy` 或频道白名单来锁定它。
- 配置向导接受 `#channel` 名称并在可能时(公 + 私有)将其解析为 ID;如果存在多个匹配,优先选择活跃频道。
- 启动时OpenClaw 将白名单中的频道/用户名解析为 ID在令牌允许时)并记录映射;未解析的条目按原样保留
- 要**不允许任何频道**,设置 `channels.slack.groupPolicy: "disabled"`(或保留空白名单)。
- `channels.slack.groupPolicy` 控制频道处理方式`open|disabled|allowlist`)。
- `allowlist` 要频道列在 `channels.slack.channels` 中。
- 如果你只设置了 `SLACK_BOT_TOKEN`/`SLACK_APP_TOKEN` 从未创建 `channels.slack` 部分,运行时默认将 `groupPolicy` 设为 `open`。添加 `channels.slack.groupPolicy``channels.defaults.groupPolicy` 或频道允许列表来锁定它。
- 配置向导接受 `#channel` 名称并在可能时将其解析为 ID(公 + 私有);如果存在多个匹配,优先选择活跃频道。
- 启动时OpenClaw 将允许列表中的频道/用户名解析为 ID当 token 允许时)并记录映射;未解析的条目保持原样
- 要**不允许任何频道**,设置 `channels.slack.groupPolicy: "disabled"`(或保持空的允许列表)。
频道选项(`channels.slack.channels.<id>``channels.slack.channels.<name>`
- `allow`:当 `groupPolicy="allowlist"` 时允许/拒绝频道。
- `requireMention`:频道的提及门控。
- `tools`:可选的频道工具策略覆盖(`allow`/`deny`/`alsoAllow`)。
- `toolsBySender`频道内可选的每发送者工具策略覆盖(键为发送者 id/@用户名/邮箱;支持 `"*"` 通配符)。
- `tools`:可选的频道工具策略覆盖(`allow`/`deny`/`alsoAllow`)。
- `toolsBySender`可选的频道内按发送者工具策略覆盖(键为发送者 ID/@用户名/邮箱;支持 `"*"` 通配符)。
- `allowBots`允许此频道中机器人发送的消息默认false
- `users`:可选的频道用户白名单
- `users`:可选的频道用户允许列表
- `skills`Skills 过滤器(省略 = 所有 Skills空 = 无)。
- `systemPrompt`:频道的额外系统提示(与主题/目的合)。
- `enabled`:设置 `false` 禁用频道。
- `systemPrompt`:频道的额外系统提示(与主题/目的合)。
- `enabled`:设置 `false` 禁用频道。
## 投递目标
与 cron/CLI 发送一起使用:
在定时任务/CLI 发送使用:
- `user:<id>` 用于私信
- `channel:<id>` 用于频道
## 工具操作
Slack 工具操作可通过 `channels.slack.actions.*` 进行门控:
Slack 工具操作可通过 `channels.slack.actions.*`
| 操作组 | 默认 | 说明 |
| ---------- | ------ | ----------------------- |
| reactions | 启用 | 表情回应 + 列出表情回应 |
| messages | 启用 | 读取/发送/编辑/删除 |
| pins | 启用 | 置顶/取消置顶/列 |
| memberInfo | 启用 | 成员信息 |
| emojiList | 启用 | 自定义表情符号列表 |
| 操作组 | 默认 | 说明 |
| ---------- | ------ | ------------------- |
| reactions | 启用 | 添加回应 + 列出回应 |
| messages | 启用 | 读取/发送/编辑/删除 |
| pins | 启用 | 置顶/取消置顶/列 |
| memberInfo | 启用 | 成员信息 |
| emojiList | 启用 | 自定义表情列表 |
## 安全说明
## 安全注意事项
- 写入默认使用 bot 令牌,因此状态更改操作保持在应用机器人权限和身份范围内。
- 设置 `userTokenReadOnly: false` 允许在 bot 令牌不可用时使用用户令牌进行写入操作,这意味着操作以安装用户的访问权限运行。将用户令牌视为高权限,并保持操作门控和白名单严格
- 如果你启用用户令牌写入,请确保用户令牌包含你期的写入权限范围(`chat:write``reactions:write``pins:write``files:write`),否则这些操作失败。
- 写入操作默认使用 bot token以便状态变更操作保持在应用机器人权限和身份范围内。
- 设置 `userTokenReadOnly: false` 允许在 bot token 不可用时使用用户 token 进行写入操作,这意味着操作以安装用户的访问权限运行。将用户 token 视为高权限凭据,并严格设置操作门控和允许列表
- 如果你启用用户 token 写入,请确保用户 token 包含你期的写入范围(`chat:write``reactions:write``pins:write``files:write`),否则这些操作失败。
## 说明
## 注意事项
- 提及门控通过 `channels.slack.channels` 控制(将 `requireMention``true``agents.list[].groupChat.mentionPatterns`(或 `messages.groupChat.mentionPatterns`)也算作提及。
- 多智能体覆盖:在 `agents.list[].groupChat.mentionPatterns` 上设置每智能体的模式。
- 表情回应通知遵循 `channels.slack.reactionNotifications``allowlist` 模式下使用 `reactionAllowlist`)。
- 默认忽略机器人发送的消息;通过 `channels.slack.allowBots``channels.slack.channels.<id>.allowBots` 启用。
- 警告:如果你允许回复其他机器人(`channels.slack.allowBots=true``channels.slack.channels.<id>.allowBots=true`),请使用 `requireMention``channels.slack.channels.<id>.users` 白名单和/或在 `AGENTS.md``SOUL.md` 中设置明确的防护措施来防止机器人之间的回复循环。
- 对于 Slack 工具,表情回应移除语义见 [/tools/reactions](/tools/reactions)。
- 附件在允许且在大小限制内时会下载到媒体存储。
- 提及门控通过 `channels.slack.channels` 控制(将 `requireMention` 设为 `true``agents.list[].groupChat.mentionPatterns`(或 `messages.groupChat.mentionPatterns`)也算作提及。
- 多智能体覆盖:在 `agents.list[].groupChat.mentionPatterns` 上设置每智能体的模式。
- 回应通知遵循 `channels.slack.reactionNotifications`(使用 `reactionAllowlist` 配合 `allowlist` 模式)。
- 机器人发送的消息默认被忽略;通过 `channels.slack.allowBots``channels.slack.channels.<id>.allowBots` 启用。
- 警告:如果你允许回复其他机器人(`channels.slack.allowBots=true``channels.slack.channels.<id>.allowBots=true`),请使用 `requireMention``channels.slack.channels.<id>.users` 允许列表和/或在 `AGENTS.md``SOUL.md` 中设置明确的防护规则来防止机器人之间的回复循环。
- Slack 工具回应移除语义请参见 [/tools/reactions](/tools/reactions)。
- 在权限允许且未超过大小限制时,附件会被下载到媒体存储。

View File

@@ -1,30 +1,30 @@
---
read_when:
- 开发 Telegram 功能或 webhook
summary: Telegram 机器人支持状态、功能配置
- 开发 Telegram 功能或 webhook
summary: Telegram 机器人支持状态、功能配置
title: Telegram
x-i18n:
generated_at: "2026-02-03T10:07:32Z"
generated_at: "2026-02-01T19:54:11Z"
model: claude-opus-4-5
provider: pi
source_hash: 65da427e5f2383edb674054f8133a5777b2aae8a7c4bd78defa065124090a19c
source_hash: 63198fce8c29a1020590d6a3ca142314b30c35d50317b878bf1fb1bfd8d54747
source_path: channels/telegram.md
workflow: 15
workflow: 14
---
# TelegramBot API
# Telegram (Bot API)
状态:通过 grammY 支持机器人私信和群组,已可用于生产环境。默认使用长轮询webhook 可选。
状态:通过 grammY 实现的机器人私聊 + 群组功能已可用于生产环境。默认使用长轮询webhook 可选。
## 快速设置(入门
## 快速设置(新手
1. 通过 **@BotFather**[直达链接](https://t.me/BotFather))创建机器人。确认用户名确实是 `@BotFather`,然后复制 token
2. 设置 token
1. 通过 **@BotFather**[直达链接](https://t.me/BotFather))创建机器人。确认用户名确实是 `@BotFather`,然后复制令牌
2. 设置令牌
- 环境变量:`TELEGRAM_BOT_TOKEN=...`
- 或配置:`channels.telegram.botToken: "..."`
- 如果两者都设置了,配置优先(环境变量回退仅适用于默认账户)。
3. 启动 Gateway 网关。
4.访问默认使用配对模式;首次联系时需批准配对码。
3. 启动 Gateway网关。
4.访问默认配对模式;首次联系时需批准配对码。
最小配置:
@@ -40,26 +40,26 @@ x-i18n:
}
```
## 这是什么
## 简介
- 一个由 Gateway 网关拥有的 Telegram Bot API 渠道。
- 确定性路由:回复返回到 Telegram模型不会选择渠道。
-共享智能体的主会话;群组保持隔离(`agent:<agentId>:telegram:group:<chatId>`)。
- 由 Gateway网关管理的 Telegram Bot API 渠道。
- 确定性路由:回复始终发回 Telegram模型不会选择渠道。
-共享智能体的主会话;群组保持隔离(`agent:<agentId>:telegram:group:<chatId>`)。
## 设置(快速路径)
### 1创建机器人 tokenBotFather
### 1创建机器人令牌BotFather
1. 打开 Telegram**@BotFather**[直达链接](https://t.me/BotFather))对话。确认用户名确实是 `@BotFather`
2. 运行 `/newbot`,然后按提示操作(名称 + 以 `bot` 结尾的用户名)。
3. 复制 token 并安全保存。
1. 打开 Telegram**@BotFather**[直达链接](https://t.me/BotFather))对话。确认用户名确实是 `@BotFather`
2. 运行 `/newbot`,然后按提示操作(名称 + 以 `bot` 结尾的用户名)。
3. 复制令牌并安全保存。
可选的 BotFather 设置:
- `/setjoingroups` — 允许/拒绝将机器人添加到群组。
- `/setprivacy` — 控制机器人是否可以看到所有群组消息。
- `/setjoingroups` — 允许/禁止将机器人添加到群组。
- `/setprivacy` — 控制机器人是否看到所有群组消息。
### 2配置 token(环境变量或配置文件
### 2配置令牌(环境变量或配置)
示例:
@@ -79,32 +79,34 @@ x-i18n:
环境变量选项:`TELEGRAM_BOT_TOKEN=...`(适用于默认账户)。
如果环境变量和配置都设置了,配置优先。
多账户支持:使用 `channels.telegram.accounts`,每个账户有独立的 token 和可选的 `name`参见 [`gateway/configuration`](/gateway/configuration#telegramaccounts--discordaccounts--slackaccounts--signalaccounts--imessageaccounts) 了解共享模式。
多账户支持:使用 `channels.telegram.accounts`每个账户设置令牌和可选的 `name`请参阅 [`gateway/configuration`](/gateway/configuration#telegramaccounts--discordaccounts--slackaccounts--signalaccounts--imessageaccounts) 了解通用模式。
3. 启动 Gateway 网关。当 token 解析成功时 Telegram 启动(配置优先,环境变量回退)
4.访问默认为配对模式。机器人首次被联系时批准配对码。
5. 对于群组:添加机器人,决定隐私/管理员行为(见下文),然后设置 `channels.telegram.groups` 来控制提及门控和允许列表
3. 启动 Gateway网关。当令牌被解析后配置优先环境变量回退Telegram 即启动
4.访问默认为配对模式。机器人首次被联系时批准配对码。
5. 对于群组:添加机器人,决定隐私/管理员行为(见下文),然后设置 `channels.telegram.groups` 来控制提及门控 + 白名单
## Token + 隐私 + 权限Telegram 端)
## 令牌 + 隐私 + 权限Telegram 端)
### Token 创建BotFather
### 令牌创建BotFather
- `/newbot` 创建机器人并返回 token(请保密)。
- 如果 token 泄露,通过 @BotFather 撤销/重新生成并更新你的配置。
- `/newbot` 创建机器人并返回令牌(请保密)。
- 如果令牌泄露,通过 @BotFather 撤销/重新生成令牌并更新配置。
### 群组消息可见性(隐私模式)
Telegram 机器人默认启用**隐私模式**,这会限制它们接收哪些群组消息。
如果你的机器人必须看到*所有*群组消息,有两个选项
Telegram 机器人默认启用**隐私模式**,这会限制它们接收到的群组消息。
如果你的机器人必须看到*所有*群组消息,有两种选择
- 使用 `/setprivacy` 禁用隐私模式**或**
- 将机器人添加为群组**管理员**(管理员机器人可以接收所有消息)。
- 使用 `/setprivacy` 禁用隐私模式**或**
- 将机器人为群组**管理员**(管理员机器人可以接收所有消息)。
**注意:** 当你切换隐私模式Telegram 要求将机器人从每个群组中移除并重新添加,更改才能生效。
**注意:** 切换隐私模式Telegram 要求将机器人从每个群组中移除并重新添加,
更改才能生效。
### 群组权限(管理员权限)
管理员状态在群组内设置Telegram UI)。管理员机器人始终接收所有群组消息,因此如果需要完全可见性,请使用管理员身份。
管理员状态在群组内设置Telegram 界面)。管理员机器人始终接收所有
群组消息,因此如果需要完全可见性,请使用管理员身份。
## 工作原理(行为)
@@ -112,31 +114,31 @@ Telegram 机器人默认启用**隐私模式**,这会限制它们接收哪些
- 群组回复默认需要提及(原生 @提及或 `agents.list[].groupChat.mentionPatterns` / `messages.groupChat.mentionPatterns`)。
- 多智能体覆盖:在 `agents.list[].groupChat.mentionPatterns` 上设置每个智能体的模式。
- 回复始终路由回同一个 Telegram 聊天。
- 长轮询使用 grammY runner每个聊天按顺序处理;总体并发受 `agents.defaults.maxConcurrent` 限制。
- 长轮询使用 grammY runner按聊天排序;总体并发受 `agents.defaults.maxConcurrent` 限制。
- Telegram Bot API 不支持已读回执;没有 `sendReadReceipts` 选项。
## 草稿流式传输
OpenClaw 可以在 Telegram 私信中使用 `sendMessageDraft` 流式传输部分回复。
OpenClaw 可以使用 `sendMessageDraft` 在 Telegram 私聊中流式传输部分回复。
要求:
-@BotFather 中为机器人启用线程模式(论坛话题模式)。
- 仅限私聊线程Telegram 在入站消息中包含 `message_thread_id`)。
- `channels.telegram.streamMode` 未设`"off"`(默认:`"partial"``"block"` 启用分块草稿更新)。
-@BotFather 中为机器人启用话题模式(论坛话题模式)。
- 仅限私聊话题Telegram 在入站消息中包含 `message_thread_id`)。
- `channels.telegram.streamMode` 未设为 `"off"`(默认:`"partial"``"block"` 启用分块草稿更新)。
草稿流式传输仅限私信Telegram 在群组或频道中不支持此功能。
草稿流式传输仅适用于私聊Telegram 在群组或频道中不支持此功能。
## 格式化Telegram HTML
- 出站 Telegram 文本使用 `parse_mode: "HTML"`Telegram 支持的标签子集)。
- 类 Markdown 输入被渲染为 **Telegram 安全 HTML**(粗体/斜体/删除线/代码/链接);块级元素被扁平化为带换行/项目符号的文本。
- 类 Markdown 输入被渲染为 **Telegram 安全 HTML**(粗体/斜体/删除线/代码/链接);块级元素被扁平化为带换行/项目符号的文本。
- 来自模型的原始 HTML 会被转义,以避免 Telegram 解析错误。
- 如果 Telegram 拒绝 HTML 负载OpenClaw 会以纯文本重试相同的消息。
- 如果 Telegram 拒绝 HTML 负载OpenClaw 会以纯文本重试同一条消息。
## 命令(原生 + 自定义)
OpenClaw 在启动时向 Telegram 的机器人菜单注册原生命令(如 `/status``/reset``/model`)。
OpenClaw 在启动时原生命令(如 `/status``/reset``/model`注册到 Telegram 的机器人菜单
你可以通过配置向菜单添加自定义命令:
```json5
@@ -144,8 +146,8 @@ OpenClaw 在启动时向 Telegram 的机器人菜单注册原生命令(如 `/s
channels: {
telegram: {
customCommands: [
{ command: "backup", description: "Git 备份" },
{ command: "generate", description: "创建图片" },
{ command: "backup", description: "Git backup" },
{ command: "generate", description: "Create an image" },
],
},
},
@@ -155,29 +157,29 @@ OpenClaw 在启动时向 Telegram 的机器人菜单注册原生命令(如 `/s
## 故障排除
- 日志中出现 `setMyCommands failed` 通常意味着到 `api.telegram.org` 的出站 HTTPS/DNS 被阻止。
- 如果看到 `sendMessage``sendChatAction` 失败,检查 IPv6 路由和 DNS。
- 如果看到 `sendMessage``sendChatAction` 失败,检查 IPv6 路由和 DNS。
更多帮助:[渠道故障排除](/channels/troubleshooting)。
注意:
- 自定义命令**仅菜单条目**;除非你在其他地方处理它们,否则 OpenClaw 不会实现它们。
- 命令名称会被规范化(去除前导 `/`,转为小写),必须匹配 `a-z``0-9``_`1-32 个字符)。
- 自定义命令**不能覆盖原生命令**。冲突会被忽略并记录日志。
- 如果禁用了 `commands.native`,则只注册自定义命令(如果没有则清空)。
- 自定义命令**仅菜单条目**;除非你在其他地方处理它们,否则 OpenClaw 不会实现它们。
- 命令名称会被规范化(去除前导 `/`,转为小写),必须匹配 `a-z``0-9``_`132 个字符)。
- 自定义命令**不能覆盖原生命令**。冲突会被忽略并记录日志。
- 如果 `commands.native` 被禁用,则只注册自定义命令(如果没有自定义命令则清空)。
## 限制
- 出站文本按 `channels.telegram.textChunkLimit` 分块(默认 4000
- 可选的换行分块:设置 `channels.telegram.chunkMode="newline"` 在长度分块之前按空行(段落边界)分割
- 可选的换行分块:设置 `channels.telegram.chunkMode="newline"` 以在空行(段落边界)处拆分,然后再按长度分块
- 媒体下载/上传受 `channels.telegram.mediaMaxMb` 限制(默认 5
- Telegram Bot API 请求在 `channels.telegram.timeoutSeconds` 后超时(通过 grammY 默认 500。设置低的值以避免长时间挂起。
- 群组历史上下文使用 `channels.telegram.historyLimit`(或 `channels.telegram.accounts.*.historyLimit`),回退到 `messages.groupChat.historyLimit`。设 `0` 禁用(默认 50
-历史可以用 `channels.telegram.dmHistoryLimit`(用户轮次)限制。用户覆盖:`channels.telegram.dms["<user_id>"].historyLimit`
- Telegram Bot API 请求在 `channels.telegram.timeoutSeconds` 后超时(通过 grammY 默认 500。设置低的值以避免长时间挂起。
- 群组历史上下文使用 `channels.telegram.historyLimit`(或 `channels.telegram.accounts.*.historyLimit`),回退到 `messages.groupChat.historyLimit`。设 `0` 禁用(默认 50
-历史可通过 `channels.telegram.dmHistoryLimit`(用户轮次)限制。用户覆盖:`channels.telegram.dms["<user_id>"].historyLimit`
## 群组激活模式
默认情况下,机器人只响应群组中的提及(`@botname``agents.list[].groupChat.mentionPatterns` 中的模式)。要更改此行为:
默认情况下,机器人在群组中只响应提及(`@botname``agents.list[].groupChat.mentionPatterns` 中的模式)。要更改此行为:
### 通过配置(推荐)
@@ -186,31 +188,31 @@ OpenClaw 在启动时向 Telegram 的机器人菜单注册原生命令(如 `/s
channels: {
telegram: {
groups: {
"-1001234567890": { requireMention: false }, // 在此群组中始终响应
"-1001234567890": { requireMention: false }, // 在此群组中始终回复
},
},
},
}
```
**重要:** 设置 `channels.telegram.groups` 会创建一个**允许列表** - 只有列出的群组(或 `"*"`)会被接受。
论坛话题继承其父群组配置allowFrom、requireMention、skills、prompts除非你在 `channels.telegram.groups.<groupId>.topics.<topicId>` 下添加每话题覆盖。
**重要:** 设置 `channels.telegram.groups` 会创建一个**白名单** - 只有列出的群组(或 `"*"`)会被接受。
论坛话题继承其父群组配置allowFrom、requireMention、skills、prompts除非你在 `channels.telegram.groups.<groupId>.topics.<topicId>` 下添加每话题覆盖。
允许所有群组始终响应
允许所有群组始终回复
```json5
{
channels: {
telegram: {
groups: {
"*": { requireMention: false }, // 所有群组,始终响应
"*": { requireMention: false }, // 所有群组,始终回复
},
},
},
}
```
保持所有群组仅提及响应(默认行为):
保持所有群组仅提及时回复(默认行为):
```json5
{
@@ -228,26 +230,26 @@ OpenClaw 在启动时向 Telegram 的机器人菜单注册原生命令(如 `/s
在群组中发送:
- `/activation always` - 响应所有消息
- `/activation always` - 回复所有消息
- `/activation mention` - 需要提及(默认)
**注意:** 命令更新会话状态。要在重启后保持持久行为,请使用配置。
**注意:** 命令更新会话状态。要在重启后保持行为,请使用配置。
### 获取群组聊天 ID
将群组中的任消息转发给 Telegram 上的 `@userinfobot``@getidsbot` 以查看聊天 ID负数`-1001234567890`)。
将群组中的任消息转发给 Telegram 上的 `@userinfobot``@getidsbot`,即可看到聊天 ID负数`-1001234567890`)。
**提示:** 要获取你自己的用户 ID机器人,它会回复你的用户 ID配对消息或者在命令启用后使用 `/whoami`
**提示:** 要获取你自己的用户 ID机器人,它会回复你的用户 ID配对消息或者在命令启用后使用 `/whoami`
**隐私注意** `@userinfobot` 是第三方机器人。如果你更倾向于其他方式,将机器人添加到群组,发送一条消息,然后使用 `openclaw logs --follow` 读取 `chat.id`,或使用 Bot API `getUpdates`
**隐私提示** `@userinfobot` 是第三方机器人。如果你更注重隐私,可以将机器人添加到群组,发送一条消息,然后使用 `openclaw logs --follow` 读取 `chat.id`,或使用 Bot API `getUpdates`
## 配置写入
默认情况下Telegram 允许写入由渠道事件或 `/config set|unset` 触发的配置更新。
这发生在以下情况:
以下情况会发生配置写入
- 群组升级为超级群组Telegram 发出 `migrate_to_chat_id`(聊天 ID 更。OpenClaw 可以自动迁移 `channels.telegram.groups`
- 群组升级为超级群组Telegram 发出 `migrate_to_chat_id`(聊天 ID 。OpenClaw 可以自动迁移 `channels.telegram.groups`
- 你在 Telegram 聊天中运行 `/config set``/config unset`(需要 `commands.config: true`)。
禁用方式:
@@ -262,14 +264,14 @@ OpenClaw 在启动时向 Telegram 的机器人菜单注册原生命令(如 `/s
Telegram 论坛话题在每条消息中包含 `message_thread_id`。OpenClaw
-`:topic:<threadId>` 加到 Telegram 群组会话键,使每个话题隔离。
- 发送输入指示器和回复时带 `message_thread_id`使响应保持在话题内。
- 通用话题(线程 id `1`特殊:消息发送省略 `message_thread_id`Telegram 会拒绝),但输入指示器仍包含它。
- 在模板上下文中暴露 `MessageThreadId` + `IsForum` 用于路由/模板。
- 话题特定配置可在 `channels.telegram.groups.<chatId>.topics.<threadId>` 下设置skills、允许列表、自动回复、系统提示、禁用)。
- 话题配置继承群组设置requireMention、允许列表、skills、提示、enabled除非话题覆盖。
-`:topic:<threadId>` 加到 Telegram 群组会话键,使每个话题相互隔离。
- 发送输入指示器和回复时`message_thread_id`确保回复留在话题内。
- 通用话题(thread id `1`比较特殊:消息发送省略 `message_thread_id`Telegram 会拒绝),但输入指示器仍包含它。
- 在模板上下文中暴露 `MessageThreadId` + `IsForum`用于路由/模板。
- 话题配置可在 `channels.telegram.groups.<chatId>.topics.<threadId>` 下设置skills、白名单、自动回复、系统提示、禁用)。
- 话题配置继承群组设置requireMention、白名单、skills、提示、enabled除非话题覆盖。
私聊在某些边缘情况下可能包含 `message_thread_id`。OpenClaw 保持私会话键不变,但在存在线程 id 时仍将其用于回复/草稿流式传输。
私聊在某些边缘情况下可能包含 `message_thread_id`。OpenClaw 保持私会话键不变,但在存在 thread id 时仍将其用于回复/草稿流式传输。
## 内联按钮
@@ -287,7 +289,7 @@ Telegram 支持带回调按钮的内联键盘。
}
```
对于每账户配置:
账户配置:
```json5
{
@@ -308,30 +310,30 @@ Telegram 支持带回调按钮的内联键盘。
作用域:
- `off` — 禁用内联按钮
- `dm` — 仅私(群组目标被阻止)
- `group` — 仅群组(私目标被阻止)
- `all` — 私 + 群组
- `allowlist` — 私 + 群组,但仅限 `allowFrom`/`groupAllowFrom` 允许的发送者(与控制命令规则相同)
- `dm` — 仅私(群组目标被阻止)
- `group` — 仅群组(私目标被阻止)
- `all` — 私 + 群组
- `allowlist` — 私 + 群组,但仅限 `allowFrom`/`groupAllowFrom` 允许的发送者(与控制命令规则相同)
默认:`allowlist`
默认`allowlist`
旧版:`capabilities: ["inlineButtons"]` = `inlineButtons: "all"`
### 发送按钮
使用 `buttons` 参数的消息工具
使用消息工具的 `buttons` 参数:
```json5
{
action: "send",
channel: "telegram",
to: "123456789",
message: "选择一个选项:",
message: "Choose an option:",
buttons: [
[
{ text: "", callback_data: "yes" },
{ text: "", callback_data: "no" },
{ text: "Yes", callback_data: "yes" },
{ text: "No", callback_data: "no" },
],
[{ text: "取消", callback_data: "cancel" }],
[{ text: "Cancel", callback_data: "cancel" }],
],
}
```
@@ -341,75 +343,75 @@ Telegram 支持带回调按钮的内联键盘。
### 配置选项
Telegram 功能可在两个级配置(上面显示的对象形式;旧版字符串数组仍支持):
Telegram 功能可在两个级配置(上面展示了对象形式;旧版字符串数组仍支持):
- `channels.telegram.capabilities`:应用于所有 Telegram 账户的全局默认功能配置,除非被覆盖。
- `channels.telegram.accounts.<account>.capabilities`账户功能,覆盖该特定账户的全局默认值。
- `channels.telegram.capabilities`全局默认功能配置,应用于所有 Telegram 账户,除非被覆盖。
- `channels.telegram.accounts.<account>.capabilities`账户功能配置,覆盖该账户的全局默认值。
当所有 Telegram 机器人/账户应具有相同行为时使用全局设置。当不同机器人需要不同行为时使用账户配置(例如,一个账户只处理私信,而另一个允许在群组中使用)。
当所有 Telegram 机器人/账户应具有相同行为时使用全局设置。当不同机器人需要不同行为时使用账户配置(例如,一个账户只处理私聊,另一个允许在群组中使用)。
## 访问控制(私 + 群组)
## 访问控制(私 + 群组)
### 私访问
### 私访问
- 默认:`channels.telegram.dmPolicy = "pairing"`。未知发送者收到配对码;在批准之前消息被忽略(配对码 1 小时后过期)。
- 默认:`channels.telegram.dmPolicy = "pairing"`。未知发送者收到配对码;消息在批准被忽略(配对码 1 小时后过期)。
- 批准方式:
- `openclaw pairing list telegram`
- `openclaw pairing approve telegram <CODE>`
- 配对是 Telegram 私使用的默认 token 交换。详情:[配对](/start/pairing)
- `channels.telegram.allowFrom` 接受数字用户 ID推荐`@username` 条目。这**不是**机器人用户名;使用人类发送者的 ID。向导接受 `@username` 并在可能时将其解析为数字 ID。
- 配对是 Telegram 私使用的默认令牌交换方式。详情:[配对](/start/pairing)
- `channels.telegram.allowFrom` 接受数字用户 ID推荐`@username` 条目。这**不是**机器人用户名;使用人类发送者的 ID。向导接受 `@username` 并在可能时将其解析为数字 ID。
#### 查找你的 Telegram 用户 ID
更安全(无第三方机器人):
更安全的方式(无第三方机器人):
1. 启动 Gateway 网关并私你的机器人。
1. 启动 Gateway网关并私你的机器人。
2. 运行 `openclaw logs --follow` 并查找 `from.id`
备选(官方 Bot API
替代方式(官方 Bot API
1.你的机器人。
2. 使用你的机器人 token 获取更新并读取 `message.from.id`
1.你的机器人。
2. 使用你的机器人令牌获取更新并读取 `message.from.id`
```bash
curl "https://api.telegram.org/bot<bot_token>/getUpdates"
```
第三方(隐私性较低):
第三方方式(隐私性较低):
- 私 `@userinfobot` 或 `@getidsbot` 并使用返回的用户 id
- 私 `@userinfobot` 或 `@getidsbot` 并使用返回的用户 ID
### 群组访问
两个独立的控制:
**1. 允许哪些群组**(通过 `channels.telegram.groups` 的群组允许列表
**1. 允许哪些群组**(通过 `channels.telegram.groups` 的群组白名单
- `groups` 配置 = 允许所有群组
- 没有 `groups` 配置 = 允许所有群组
- 有 `groups` 配置 = 只允许列出的群组或 `"*"`
- 示例:`"groups": { "-1001234567890": {}, "*": {} }` 允许所有群组
**2. 允许哪些发送者**(通过 `channels.telegram.groupPolicy` 的发送者过滤):
- `"open"` = 允许群组中所有发送者发消息
- `"open"` = 允许群组中所有发送者都可以发消息
- `"allowlist"` = 只有 `channels.telegram.groupAllowFrom` 中的发送者可以发消息
- `"disabled"` = 不接受任何群组消息
默认 `groupPolicy: "allowlist"`(除非添加 `groupAllowFrom` 否则被阻止)。
- `"disabled"` = 完全不接受群组消息
默认 `groupPolicy: "allowlist"`(除非添加 `groupAllowFrom`否则被阻止)。
大多数用户需要:`groupPolicy: "allowlist"` + `groupAllowFrom` + 在 `channels.telegram.groups` 中列出特定群组
## 长轮询 vs webhook
- 默认:长轮询(不需要公 URL
- 默认:长轮询(不需要公 URL
- Webhook 模式:设置 `channels.telegram.webhookUrl` 和 `channels.telegram.webhookSecret`(可选 `channels.telegram.webhookPath`)。
- 本地监听器绑定到 `0.0.0.0:8787`,默认服务 `POST /telegram-webhook`。
- 如果你的公 URL 不同,使用反向代理并将 `channels.telegram.webhookUrl` 指向公端点。
- 本地监听器绑定到 `0.0.0.0:8787`,默认服务 `POST /telegram-webhook`。
- 如果你的公 URL 不同,使用反向代理并将 `channels.telegram.webhookUrl` 指向公端点。
## 回复线程
Telegram 通过标签支持可选的线程回复:
- `[[reply_to_current]]` -- 回复触发消息。
- `[[reply_to:<id>]]` -- 回复特定消息 id
- `[[reply_to:<id>]]` -- 回复特定消息 ID
通过 `channels.telegram.replyToMode` 控制:
@@ -417,16 +419,17 @@ Telegram 通过标签支持可选的线程回复:
## 音频消息(语音 vs 文件)
Telegram 区分**语音备忘录**(圆形气泡)和**音频文件**(元数据卡片)。
OpenClaw 默认使用音频文件以保持向后兼容
Telegram 区分**语音消息**(圆形气泡)和**音频文件**(元数据卡片)。
OpenClaw 默认使用音频文件以保持向后兼容。
要在智能体回复中强制使用语音备忘录气泡,在回复中的任位置包含此标签:
要在智能体回复中强制使用语音消息气泡,在回复中的任位置包含此标签:
- `[[audio_as_voice]]` — 将音频作为语音备忘录而不是文件发送
- `[[audio_as_voice]]` — 以语音消息而非文件形式发送音频
该标签会从发送的文本中除。其他渠道会忽略此标签。
该标签会从发送的文本中除。其他渠道会忽略此标签。
对于消息工具发送,设置 `asVoice: true` 并配合兼容语音的音频 `media` URL(当存在 media 时 `message` 是可选的):
对于消息工具发送,设置 `asVoice: true` 并附带兼容语音的音频 `media` URL
(当有 media 时 `message` 为可选):
```json5
{
@@ -440,34 +443,34 @@ OpenClaw 默认使用音频文件以保持向后兼容性。
## 贴纸
OpenClaw 支持接收和发送 Telegram 贴纸,并有智能缓存功能
OpenClaw 支持接收和发送 Telegram 贴纸,并有智能缓存。
### 接收贴纸
当用户发送贴纸时OpenClaw 根据贴纸类型处理:
当用户发送贴纸时OpenClaw 根据贴纸类型进行处理:
- **静态贴纸WEBP** 下载并通过视觉处理。贴纸在消息内容中显示为 `<media:sticker>` 占位符。
- **动贴纸TGS** 跳过Lottie 格式不支持处理)。
- **视频贴纸WEBM** 跳过(视频格式不支持处理)。
- **静态贴纸WEBP** 下载并通过视觉能力处理。贴纸在消息内容中显示为 `<media:sticker>` 占位符。
- **动贴纸TGS** 跳过(不支持 Lottie 格式处理)。
- **视频贴纸WEBM** 跳过(不支持视频格式处理)。
接收贴纸时可用的模板上下文字段:
- `Sticker` — 包含以下属性的对象:
- `emoji` — 与贴纸关联的表情符号
- `emoji` — 与贴纸关联的表情
- `setName` — 贴纸集名称
- `fileId` — Telegram 文件 ID用于发送相同贴纸)
- `fileId` — Telegram 文件 ID用于发回同一贴纸)
- `fileUniqueId` — 用于缓存查找的稳定 ID
- `cachedDescription` — 可用时的缓存视觉描述
### 贴纸缓存
贴纸通过 AI 的视觉能处理以生成描述。由于相同的贴纸经常重复发送OpenClaw 缓存这些描述以避免冗余的 API 调用。
贴纸通过 AI 的视觉能处理以生成描述。由于相同的贴纸经常重复发送OpenClaw 缓存这些描述以避免冗余的 API 调用。
**工作原理:**
1. **首次遇到:** 贴纸图像被发送给 AI 进行视觉分析。AI 生成描述(例如"一只卡通猫热情地挥手")。
2. **缓存存储:** 描述与贴纸的文件 ID、表情符号和集合名称一起保存。
3. **后续遇到:** 再次看到同贴纸时,直接使用缓存的描述。图像不会发送给 AI。
2. **缓存存储:** 描述与贴纸的文件 ID、表情和集合名称一起保存。
3. **后续遇到:** 再次看到同贴纸时,直接使用缓存的描述,不再将图像发送给 AI。
**缓存位置:** `~/.openclaw/telegram/sticker-cache.json`
@@ -479,22 +482,22 @@ OpenClaw 支持接收和发送 Telegram 贴纸,并具有智能缓存功能。
"fileUniqueId": "AgADBAADb6cxG2Y",
"emoji": "👋",
"setName": "CoolCats",
"description": "一只卡通猫热情地挥手",
"description": "A cartoon cat waving enthusiastically",
"cachedAt": "2026-01-15T10:30:00.000Z"
}
```
**优**
**优**
- 通过避免对同贴纸重复调用视觉 API 来降低 API 成本
- 缓存贴纸响应更快(无视觉处理延迟)
- 基于缓存描述启用贴纸搜索功能
- 通过避免对同贴纸重复调用视觉能力来降低 API 成本
- 缓存贴纸响应速度更快(无视觉处理延迟)
- 支持基于缓存描述贴纸搜索功能
缓存在接收贴纸时自动填充无需手动缓存管理。
缓存在接收贴纸时自动填充无需手动管理。
### 发送贴纸
智能体可以使用 `sticker` 和 `sticker-search` 动作发送和搜索贴纸。这些默认禁用,必须在配置中启用:
智能体可以使用 `sticker` 和 `sticker-search` 动作发送和搜索贴纸。这些功能默认禁用,必须在配置中启用:
```json5
{
@@ -521,24 +524,24 @@ OpenClaw 支持接收和发送 Telegram 贴纸,并具有智能缓存功能。
参数:
- `fileId`(必)— 贴纸的 Telegram 文件 ID。从接收贴纸时的 `Sticker.fileId` 获取,或从 `sticker-search` 结果获取。
- `fileId`(必)— 贴纸的 Telegram 文件 ID。从接收贴纸时的 `Sticker.fileId` 获取,或从 `sticker-search` 结果获取。
- `replyTo`(可选)— 要回复的消息 ID。
- `threadId`(可选)— 论坛话题的消息线程 ID。
**搜索贴纸:**
智能体可以描述、表情符号或集合名称搜索缓存的贴纸:
智能体可以通过描述、表情或集合名称搜索缓存的贴纸:
```json5
{
action: "sticker-search",
channel: "telegram",
query: "猫 挥手",
query: "cat waving",
limit: 5,
}
```
返回缓存中匹配的贴纸:
从缓存返回匹配的贴纸:
```json5
{
@@ -548,14 +551,14 @@ OpenClaw 支持接收和发送 Telegram 贴纸,并具有智能缓存功能。
{
fileId: "CAACAgIAAxkBAAI...",
emoji: "👋",
description: "一只卡通猫热情地挥手",
description: "A cartoon cat waving enthusiastically",
setName: "CoolCats",
},
],
}
```
搜索描述文本、表情符号字符和集合名称之间使用模糊匹配。
搜索使用跨描述文本、表情字符和集合名称模糊匹配。
**带线程的示例:**
@@ -572,72 +575,73 @@ OpenClaw 支持接收和发送 Telegram 贴纸,并具有智能缓存功能。
## 流式传输(草稿)
Telegram 可以在智能体生成响应时流式传输**草稿气泡**。
OpenClaw 使用 Bot API `sendMessageDraft`不是真实消息),然后将最终回复作为普通消息发送。
Telegram 可以在智能体生成回复时流式传输**草稿气泡**。
OpenClaw 使用 Bot API `sendMessageDraft`真实消息),然后将
最终回复作为普通消息发送。
要求Telegram Bot API 9.3+
- **启用话题的私聊**(机器人的论坛话题模式)。
- 入站消息必须包含 `message_thread_id`(私话题线程)。
- 群组/超级群组/频道的流式传输被忽略。
- 入站消息必须包含 `message_thread_id`(私话题线程)。
- 群组/超级群组/频道的流式传输被忽略。
配置:
- `channels.telegram.streamMode: "off" | "partial" | "block"`(默认:`partial`
- `partial`:用最新的流式文本更新草稿气泡。
- `block`:以较大块(分块)更新草稿气泡。
- `block`:以更大的块更新草稿气泡(分块)
- `off`:禁用草稿流式传输。
- 可选(仅用于 `streamMode: "block"`
- 可选(仅用于 `streamMode: "block"`
- `channels.telegram.draftChunk: { minChars?, maxChars?, breakPreference? }`
- 默认值:`minChars: 200`、`maxChars: 800`、`breakPreference: "paragraph"`限制在 `channels.telegram.textChunkLimit` )。
- 默认值:`minChars: 200`、`maxChars: 800`、`breakPreference: "paragraph"` `channels.telegram.textChunkLimit` 限制)。
注意:草稿流式传输与**分块流式传输**(渠道消息)不同。
分块流式传输默认关闭,如果你想要早期 Telegram 消息而不是草稿更新,需要 `channels.telegram.blockStreaming: true`。
分块流式传输默认关闭,如果你想要提前的 Telegram 消息而草稿更新,需要设置 `channels.telegram.blockStreaming: true`。
推理流(仅 Telegram
推理流式传输(仅 Telegram
- `/reasoning stream` 在回复生成时将推理流式传输到草稿气泡中,然后发送不带推理的最终答案。
- 如果 `channels.telegram.streamMode` 为 `off`,推理流被禁用。
- `/reasoning stream` 在回复生成时将推理过程流式传输到草稿气泡中,然后发送不包含推理过程的最终答案。
- 如果 `channels.telegram.streamMode` 为 `off`,推理流式传输将被禁用。
更多上下文:[流式传输 + 分块](/concepts/streaming)。
## 重试策略
出站 Telegram API 调用在遇到临时网络/429 错误时会以指数退避和抖动进行重试。通过 `channels.telegram.retry` 配置。参见[重试策略](/concepts/retry)。
出站 Telegram API 调用在遇到瞬态网络/429 错误时会以指数退避和抖动进行重试。通过 `channels.telegram.retry` 配置。参见[重试策略](/concepts/retry)。
## 智能体工具(消息 + 应)
## 智能体工具(消息 + 表情回应)
- 工具:`telegram`使用 `sendMessage` 动作(`to`、`content`,可选 `mediaUrl`、`replyToMessageId`、`messageThreadId`)。
- 工具:`telegram`使用 `react` 动作(`chatId`、`messageId`、`emoji`)。
- 工具:`telegram`使用 `deleteMessage` 动作(`chatId`、`messageId`)。
- 应移除语义:参见 [/tools/reactions](/tools/reactions)。
- 工具:`telegram``sendMessage` 动作(`to`、`content`,可选 `mediaUrl`、`replyToMessageId`、`messageThreadId`)。
- 工具:`telegram``react` 动作(`chatId`、`messageId`、`emoji`)。
- 工具:`telegram``deleteMessage` 动作(`chatId`、`messageId`)。
- 表情回应移除语义:参见 [/tools/reactions](/tools/reactions)。
- 工具门控:`channels.telegram.actions.reactions`、`channels.telegram.actions.sendMessage`、`channels.telegram.actions.deleteMessage`(默认:启用),以及 `channels.telegram.actions.sticker`(默认:禁用)。
## 应通知
## 表情回应通知
**反应工作原理:**
Telegram 应作为**独的 `message_reaction` 事件**到达,而不是消息负载中的属性。当用户添加应时OpenClaw
**表情回应的工作原理:**
Telegram 表情回应作为**独的 `message_reaction` 事件**到达,而消息负载中的属性。当用户添加表情回应时OpenClaw
1. 从 Telegram API 接收 `message_reaction` 更新
2. 将其转换为**系统事件**,格式为:`"Telegram reaction added: {emoji} by {user} on msg {id}"`
3. 使用与常规消息**相同的会话键**将系统事件入队
4. 当该对话中的下一条消息到达时,系统事件被排出并前置到智能体上下文
3. 使用与常规消息**相同的会话键**将系统事件入队
4. 当该对话中的下一条消息到达时,系统事件被排出并添加到智能体上下文的前面
智能体将应视为对话历史中的**系统通知**,而不是消息元数据。
智能体将表情回应视为对话历史中的**系统通知**,而消息元数据。
**配置:**
- `channels.telegram.reactionNotifications`:控制哪些应触发通知
- `"off"` — 忽略所有
- `"own"` — 当用户对机器人消息做出应时通知(尽力而为;内存中)(默认)
- `"all"` — 通知所有反应
- `channels.telegram.reactionNotifications`:控制哪些表情回应触发通知
- `"off"` — 忽略所有表情回
- `"own"` — 当用户对机器人消息做出表情回应时通知(尽力而为;内存中)(默认)
- `"all"` — 对所有表情回应进行通知
- `channels.telegram.reactionLevel`:控制智能体的应能力
- `"off"` — 智能体不能对消息做出反
- `"ack"` — 机器人发送确认应(处理时显示 👀)(默认)
- `"minimal"` — 智能体可以少量应(指导:每 5-10 次交 1 次)
- `"extensive"` — 智能体可以在适当时自由反
- `channels.telegram.reactionLevel`:控制智能体的表情回应能力
- `"off"` — 智能体不能对消息做表情回
- `"ack"` — 机器人发送确认表情回应(处理时显示 👀)(默认)
- `"minimal"` — 智能体可以少量使用表情回应(指导原则:每 5-10 次交 1 次)
- `"extensive"` — 智能体可以在适当时大量使用表情回
**论坛群组:** 论坛群组中的应包含 `message_thread_id`,使用类似 `agent:main:telegram:group:{chatId}:topic:{threadId}` 的会话键。这确保同一话题中的应和消息保持在一起。
**论坛群组:** 论坛群组中的表情回应包含 `message_thread_id`,使用 `agent:main:telegram:group:{chatId}:topic:{threadId}` 的会话键。这确保同一话题中的表情回应和消息保持在一起。
**示例配置:**
@@ -645,8 +649,8 @@ Telegram 反应作为**单独的 `message_reaction` 事件**到达,而不是
{
channels: {
telegram: {
reactionNotifications: "all", // 查看所有
reactionLevel: "minimal", // 智能体可以少量
reactionNotifications: "all", // 查看所有表情回
reactionLevel: "minimal", // 智能体可以少量使用表情回
},
},
}
@@ -654,51 +658,51 @@ Telegram 反应作为**单独的 `message_reaction` 事件**到达,而不是
**要求:**
- Telegram 机器人必须在 `allowed_updates` 中明确请求 `message_reaction`(由 OpenClaw 自动配置)
- 对于 webhook 模式,应包含在 webhook `allowed_updates` 中
- 对于轮询模式,应包含在 `getUpdates` `allowed_updates` 中
- Telegram 机器人必须在 `allowed_updates` 中显式请求 `message_reaction`(由 OpenClaw 自动配置)
- 对于 webhook 模式,表情回应包含在 webhook `allowed_updates` 中
- 对于轮询模式,表情回应包含在 `getUpdates` `allowed_updates` 中
## 投递目标CLI/cron
## 投递目标CLI/定时任务
- 使用聊天 id`123456789`)或用户名(`@name`)作为目标。
- 使用聊天 ID`123456789`)或用户名(`@name`)作为目标。
- 示例:`openclaw message send --channel telegram --target 123456789 --message "hi"`。
## 故障排除
**机器人不响应群组中的非提及消息:**
**机器人在群组中不响应非提及消息:**
- 如果你设置了 `channels.telegram.groups.*.requireMention=false`Telegram 的 Bot API **隐私模式**必须禁用。
- 如果你设置了 `channels.telegram.groups.*.requireMention=false`Telegram 的 Bot API **隐私模式**必须禁用。
- BotFather`/setprivacy` → **Disable**(然后从群组中移除并重新添加机器人)
- `openclaw channels status` 在配置期望提及群组消息时显示警告。
- `openclaw channels status --probe` 可以额外检查显式数字群组 ID 的成员资格(无法审计通配符 `"*"` 规则)。
- 快速测试:`/activation always`(仅会话级别;使用配置以持久化
- `openclaw channels status` 在配置期望接收非提及群组消息时显示警告。
- `openclaw channels status --probe` 可以额外检查显式数字群组 ID 的成员资格(无法审计通配符 `"*"` 规则)。
- 快速测试:`/activation always`(仅会话级别;持久化请使用配置)
**机器人完全看不到群组消息:**
- 如果设置了 `channels.telegram.groups`,群组必须被列出或使用 `"*"`
- 在 @BotFather 中检查隐私设置 →"Group Privacy"应为 **OFF**
- 验证机器人确实是成员(不仅仅是没有读取权限的管理员)
- 检查 Gateway 网关日志:`openclaw logs --follow`(查找"skipping group message"
- 在 @BotFather 中检查隐私设置 → "Group Privacy" 应为 **OFF**
- 确认机器人确实是成员(而非只是没有读取权限的管理员)
- 检查 Gateway网关日志`openclaw logs --follow`(查找 "skipping group message"
**机器人响应提及但不响应 `/activation always`**
- `/activation` 命令更新会话状态但不持久化到配置
- `/activation` 命令更新会话状态但不持久化到配置
- 要持久化行为,将群组添加到 `channels.telegram.groups` 并设置 `requireMention: false`
**`/status` 这样的命令不起作用**
**`/status` 等命令不工作**
- 确保你的 Telegram 用户 ID 已授权(通过配对或 `channels.telegram.allowFrom`
- 即使在 `groupPolicy: "open"` 的群组中,命令也需要授权
**长轮询在 Node 22+ 上立即中止(通常代理/自定义 fetch 有关**
**长轮询在 Node 22+ 上立即中止(通常涉及代理/自定义 fetch**
- Node 22+ 对 `AbortSignal` 实例更严格;外部信号可立即中止 `fetch` 调用。
- 升级到规范化中止信号的 OpenClaw 构建版本,或在可以升级之前在 Node 20 上运行 Gateway 网关。
- Node 22+ 对 `AbortSignal` 实例更严格;外部信号可能会立即中止 `fetch` 调用。
- 升级到规范化 abort 信号的 OpenClaw 版本,或在 Node 20 上运行 Gateway网关直到可以升级
**机器人启动后静默停止响应(或日志显示 `HttpError: Network request ... failed`**
**机器人启动后静默停止响应(或日志中出现 `HttpError: Network request ... failed`**
- 某些主机先将 `api.telegram.org` 解析为 IPv6。如果你的服务器没有可用的 IPv6 出口grammY 可能会卡在仅 IPv6 的请求上。
- 通过启用 IPv6 出口**或**强制 `api.telegram.org` 使用 IPv4 解析来修复(例如,使用 IPv4 A 记录添加 `/etc/hosts` 条目,或在你的 OS DNS 栈中优先使用 IPv4然后重启 Gateway 网关。
- 某些主机先将 `api.telegram.org` 解析为 IPv6。如果你的服务器没有可用的 IPv6 出口grammY 可能会卡在仅 IPv6 的请求上。
- 修复方法:启用 IPv6 出口**或**强制 `api.telegram.org` 使用 IPv4 解析(例如,使用 IPv4 A 记录添加 `/etc/hosts` 条目,或在操作系统 DNS 栈中优先使用 IPv4然后重启 Gateway网关。
- 快速检查:`dig +short api.telegram.org A` 和 `dig +short api.telegram.org AAAA` 确认 DNS 返回的内容。
## 配置参考Telegram
@@ -708,44 +712,44 @@ Telegram 反应作为**单独的 `message_reaction` 事件**到达,而不是
提供商选项:
- `channels.telegram.enabled`:启用/禁用渠道启动。
- `channels.telegram.botToken`:机器人 tokenBotFather
- `channels.telegram.tokenFile`:从文件路径读取 token
- `channels.telegram.botToken`:机器人令牌BotFather
- `channels.telegram.tokenFile`:从文件路径读取令牌
- `channels.telegram.dmPolicy``pairing | allowlist | open | disabled`默认pairing
- `channels.telegram.allowFrom`:私信允许列表id/用户名)。`open` 需要 `"*"`。
- `channels.telegram.allowFrom`:私聊白名单ID/用户名)。`open` 需要 `"*"`。
- `channels.telegram.groupPolicy``open | allowlist | disabled`默认allowlist
- `channels.telegram.groupAllowFrom`:群组发送者允许列表id/用户名)。
- `channels.telegram.groups`群组默认 + 允许列表(使用 `"*"` 作为全局默认)。
- `channels.telegram.groupAllowFrom`:群组发送者白名单ID/用户名)。
- `channels.telegram.groups`群组默认设置 + 白名单(使用 `"*"` 作为全局默认)。
- `channels.telegram.groups.<id>.requireMention`:提及门控默认值。
- `channels.telegram.groups.<id>.skills`skill 过滤(省略 = 所有 skills空 = 无)。
- `channels.telegram.groups.<id>.allowFrom`群组发送者允许列表覆盖。
- `channels.telegram.groups.<id>.systemPrompt`:群组的额外系统提示。
- `channels.telegram.groups.<id>.enabled`:为 `false` 时禁用群组。
- `channels.telegram.groups.<id>.topics.<threadId>.*`话题覆盖(与群组相同的字段)。
- `channels.telegram.groups.<id>.topics.<threadId>.requireMention`话题提及门控覆盖。
- `channels.telegram.groups.<id>.skills`Skills 过滤(省略 = 所有 Skills空 = 无 Skills)。
- `channels.telegram.groups.<id>.allowFrom`群组发送者白名单覆盖。
- `channels.telegram.groups.<id>.systemPrompt`:群组的额外系统提示
- `channels.telegram.groups.<id>.enabled`为 `false` 时禁用群组。
- `channels.telegram.groups.<id>.topics.<threadId>.*`话题覆盖(与群组字段相同)。
- `channels.telegram.groups.<id>.topics.<threadId>.requireMention`话题提及门控覆盖。
- `channels.telegram.capabilities.inlineButtons``off | dm | group | all | allowlist`默认allowlist
- `channels.telegram.accounts.<account>.capabilities.inlineButtons`账户覆盖。
- `channels.telegram.accounts.<account>.capabilities.inlineButtons`账户覆盖。
- `channels.telegram.replyToMode``off | first | all`(默认:`first`)。
- `channels.telegram.textChunkLimit`:出站分块大小(字符)。
- `channels.telegram.chunkMode``length`(默认)或 `newline` 在长度分块之前按空行(段落边界)分割
- `channels.telegram.textChunkLimit`:出站分块大小(字符)。
- `channels.telegram.chunkMode``length`(默认)或 `newline`,在空行(段落边界)处拆分后再按长度分块
- `channels.telegram.linkPreview`切换出站消息的链接预览默认true
- `channels.telegram.streamMode``off | partial | block`(草稿流式传输)。
- `channels.telegram.mediaMaxMb`:入站/出站媒体上限MB
- `channels.telegram.retry`:出站 Telegram API 调用的重试策略attempts、minDelayMs、maxDelayMs、jitter
- `channels.telegram.network.autoSelectFamily`:覆盖 Node autoSelectFamilytrue=启用false=禁用)。在 Node 22 上默认禁用以避免 Happy Eyeballs 超时。
- `channels.telegram.network.autoSelectFamily`:覆盖 Node autoSelectFamilytrue=启用false=禁用)。在 Node 22 上默认禁用以避免 Happy Eyeballs 超时。
- `channels.telegram.proxy`Bot API 调用的代理 URLSOCKS/HTTP
- `channels.telegram.webhookUrl`:启用 webhook 模式(需要 `channels.telegram.webhookSecret`)。
- `channels.telegram.webhookSecret`webhook 密钥(设置 webhookUrl 时必)。
- `channels.telegram.webhookSecret`webhook 密钥(设置 webhookUrl 时必)。
- `channels.telegram.webhookPath`:本地 webhook 路径(默认 `/telegram-webhook`)。
- `channels.telegram.actions.reactions`门控 Telegram 工具反应
- `channels.telegram.actions.sendMessage`门控 Telegram 工具消息发送。
- `channels.telegram.actions.deleteMessage`门控 Telegram 工具消息删除。
- `channels.telegram.actions.sticker`门控 Telegram 贴纸动作 — 发送和搜索默认false
- `channels.telegram.reactionNotifications``off | own | all` — 控制哪些应触发系统事件(未设置时默认:`own`)。
- `channels.telegram.reactionLevel``off | ack | minimal | extensive` — 控制智能体的应能力(未设置时默认:`minimal`)。
- `channels.telegram.actions.reactions`Telegram 工具表情回应门控
- `channels.telegram.actions.sendMessage`Telegram 工具消息发送门控
- `channels.telegram.actions.deleteMessage`Telegram 工具消息删除门控
- `channels.telegram.actions.sticker`Telegram 贴纸动作门控 — 发送和搜索默认false
- `channels.telegram.reactionNotifications``off | own | all` — 控制哪些表情回应触发系统事件(未设置时默认:`own`)。
- `channels.telegram.reactionLevel``off | ack | minimal | extensive` — 控制智能体的表情回应能力(未设置时默认:`minimal`)。
相关全局选项:
- `agents.list[].groupChat.mentionPatterns`(提及门控模式)。
- `messages.groupChat.mentionPatterns`(全局回退)。
- `commands.native`(默认为 `"auto"` → Telegram/Discord Slack 关闭)、`commands.text`、`commands.useAccessGroups`(命令行为)。使用 `channels.telegram.commands.native` 覆盖。
- `commands.native`(默认为 `"auto"` → Telegram/Discord 启Slack 禁用)、`commands.text`、`commands.useAccessGroups`(命令行为)。通过 `channels.telegram.commands.native` 覆盖。
- `messages.responsePrefix`、`messages.ackReaction`、`messages.ackReactionScope`、`messages.removeAckAfterReply`。

View File

@@ -1,34 +1,36 @@
---
read_when:
- 开发 Tlon/Urbit 渠道功能
- 开发 Tlon/Urbit 渠道功能
summary: Tlon/Urbit 支持状态、功能和配置
title: Tlon
x-i18n:
generated_at: "2026-02-03T07:44:17Z"
generated_at: "2026-02-01T19:58:15Z"
model: claude-opus-4-5
provider: pi
source_hash: 19d7ffe23e82239fd2a2e35913e0d52c809b2c2b939dd39184e6c27a539ed97d
source_path: channels/tlon.md
workflow: 15
workflow: 14
---
# Tlon插件
Tlon 是一个基于 Urbit 构建的去中心化即时通讯工具。OpenClaw 连接到你的 Urbit ship可以响应私信和群聊消息。群组回复默认需要 @ 提及,并可通过允许列表进一步限制。
Tlon 是一个基于 Urbit 构建的去中心化通讯工具。OpenClaw 连接到你的 Urbit ship可以
回复私信和群聊消息。群聊回复默认需要 @ 提及,并可通过白名单进一步限制。
状态:通过插件支持。支持私信、群组提及、话题回复和纯文本媒体回退URL 附加到说明文字)。不支持表情回应、投票和原生媒体上传。
状态:通过插件支持。支持私信、群组提及、线程回复和纯文本媒体回退
URL 附加到标题)。不支持反应、投票和原生媒体上传。
## 需要插件
Tlon 作为插件提供,不包含在核心安装中。
Tlon 以插件形式提供,不包含在核心安装中。
通过 CLI 安装npm 仓库
通过 CLI 安装npm 注册表
```bash
openclaw plugins install @openclaw/tlon
```
本地出(从 git 仓库运行时):
本地出(从 git 仓库运行时):
```bash
openclaw plugins install ./extensions/tlon
@@ -41,8 +43,8 @@ openclaw plugins install ./extensions/tlon
1. 安装 Tlon 插件。
2. 获取你的 ship URL 和登录代码。
3. 配置 `channels.tlon`
4. 重启 Gateway 网关。
5. 私信机器人或在群组道中提及它。
4. 重启 Gateway网关。
5. 机器人发送私信或在群组道中提及它。
最小配置(单账户):
@@ -59,9 +61,9 @@ openclaw plugins install ./extensions/tlon
}
```
## 群组
## 群组
默认启用自动发现。你也可以手动固定道:
默认启用自动发现。你也可以手动固定道:
```json5
{
@@ -87,7 +89,7 @@ openclaw plugins install ./extensions/tlon
## 访问控制
私信允许列表(空 = 允许全部
私信白名单(为空 = 允许所有
```json5
{
@@ -99,7 +101,7 @@ openclaw plugins install ./extensions/tlon
}
```
群组授权(默认受限):
群组授权(默认受限模式
```json5
{
@@ -122,15 +124,15 @@ openclaw plugins install ./extensions/tlon
}
```
## 投递目标CLI/cron
## 投递目标CLI/定时任务
`openclaw message send` cron 投递一起使用:
`openclaw message send`定时投递配合使用:
- 私信:`~sampel-palnet``dm/~sampel-palnet`
- 群组:`chat/~host-ship/channel``group:~host-ship/channel`
## 注意事项
##
-回复需要提及(例如 `~your-bot-ship`)才响应。
- 话题回复:如果入站消息在话题OpenClaw 会在话题内回复。
- 媒体:`sendMedia` 回退为文本 + URL原生上传)。
-回复需要提及(例如 `~your-bot-ship`)才响应。
- 线程回复:如果收到的消息在线程OpenClaw 会在线程内回复。
- 媒体:`sendMedia` 回退为文本 + URL不支持原生上传)。

View File

@@ -1,32 +1,32 @@
---
read_when:
- 为 OpenClaw 设置 Twitch 聊天集成
summary: Twitch 聊天机器人配置设置
summary: Twitch 聊天机器人配置设置
title: Twitch
x-i18n:
generated_at: "2026-02-03T07:44:41Z"
generated_at: "2026-02-01T19:58:38Z"
model: claude-opus-4-5
provider: pi
source_hash: 0dd1c05bef570470d8b82c1f6dee5337e8b76b57269c5cad6aee2e711483f8ba
source_hash: aa7d60444e7f7e5dd7d02ce21527089058e024b8f427aeedf9e200a2818eb007
source_path: channels/twitch.md
workflow: 15
workflow: 14
---
# Twitch插件
通过 IRC 连接支持 Twitch 聊天。OpenClaw 以 Twitch 用户(机器人账)身份连接,在频道中接收和发送消息。
通过 IRC 连接支持 Twitch 聊天。OpenClaw 以 Twitch 用户(机器人账)身份连接,在频道中接收和发送消息。
## 需要插件
Twitch 作为插件发布,未与核心安装捆绑
Twitch 以插件形式提供,未包含在核心安装
通过 CLI 安装npm 注册表):
通过 CLInpm 注册表)安装
```bash
openclaw plugins install @openclaw/twitch
```
本地出(从 git 仓库运行时):
本地出(从 git 仓库运行时):
```bash
openclaw plugins install ./extensions/twitch
@@ -34,19 +34,19 @@ openclaw plugins install ./extensions/twitch
详情:[插件](/plugin)
## 快速设置(新手
## 快速设置(入门
1. 为机器人创建一个专用 Twitch 账(或使用现有账)。
1. 为机器人创建一个专用 Twitch 账(或使用现有账)。
2. 生成凭证:[Twitch Token Generator](https://twitchtokengenerator.com/)
- 选择 **Bot Token**
- 确认已选 `chat:read``chat:write` 权限范围
- 确认已`chat:read``chat:write` 权限范围
- 复制 **Client ID****Access Token**
3. 查找你的 Twitch 用户 IDhttps://www.streamweasels.com/tools/convert-twitch-username-to-user-id/
4. 配置令牌:
- 环境变量:`OPENCLAW_TWITCH_ACCESS_TOKEN=...`(仅限默认账
- 或配置:`channels.twitch.accessToken`
- 如果两者都设置,配置优先(环境变量回退仅适用于默认账)。
5. 启动 Gateway 网关。
- 环境变量:`OPENCLAW_TWITCH_ACCESS_TOKEN=...`(仅限默认账
- 或配置文件`channels.twitch.accessToken`
- 如果两者都设置,配置文件优先(环境变量回退仅适用于默认账)。
5. 启动 Gateway网关。
**⚠️ 重要:** 添加访问控制(`allowFrom``allowedRoles`)以防止未授权用户触发机器人。`requireMention` 默认为 `true`
@@ -57,22 +57,22 @@ openclaw plugins install ./extensions/twitch
channels: {
twitch: {
enabled: true,
username: "openclaw", // 机器人的 Twitch 账
username: "openclaw", // 机器人的 Twitch 账
accessToken: "oauth:abc123...", // OAuth Access Token或使用 OPENCLAW_TWITCH_ACCESS_TOKEN 环境变量)
clientId: "xyz789...", // Token Generator 的 Client ID
channel: "vevisk", // 要加入的 Twitch 频道聊天(必填)
clientId: "xyz789...", // Token Generator 获取的 Client ID
channel: "vevisk", // 要加入的 Twitch 频道聊天(必填)
allowFrom: ["123456789"], // (推荐)仅限你的 Twitch 用户 ID - 从 https://www.streamweasels.com/tools/convert-twitch-username-to-user-id/ 获取
},
},
}
```
## 它是什么
## 工作原理
- 由 Gateway 网关拥有的 Twitch 渠道。
- 确定性路由:回复总是返回到 Twitch。
- 每个账映射到一个隔离的会话键 `agent:<agentId>:twitch:<accountName>`
- `username` 是机器人账户(进行身份验证的账户`channel` 是要加入的聊天室。
- 由 Gateway网关拥有的 Twitch 渠道。
- 确定性路由:回复始终返回到 Twitch。
- 每个账映射到一个隔离的会话键 `agent:<agentId>:twitch:<accountName>`
- `username` 是机器人的账号(用于认证`channel` 是要加入的聊天室。
## 设置(详细)
@@ -81,20 +81,20 @@ openclaw plugins install ./extensions/twitch
使用 [Twitch Token Generator](https://twitchtokengenerator.com/)
- 选择 **Bot Token**
- 确认已选 `chat:read``chat:write` 权限范围
- 确认已`chat:read``chat:write` 权限范围
- 复制 **Client ID****Access Token**
无需手动注册应用。令牌在小时后过期。
无需手动注册应用。令牌在小时后过期。
### 配置机器人
**环境变量(仅限默认账**
**环境变量(仅限默认账**
```bash
OPENCLAW_TWITCH_ACCESS_TOKEN=oauth:abc123...
```
**或配置:**
**或配置文件**
```json5
{
@@ -110,7 +110,7 @@ OPENCLAW_TWITCH_ACCESS_TOKEN=oauth:abc123...
}
```
如果环境变量和配置都设置了,配置优先。
如果环境变量和配置文件都设置了,配置文件优先。
### 访问控制(推荐)
@@ -119,24 +119,23 @@ OPENCLAW_TWITCH_ACCESS_TOKEN=oauth:abc123...
channels: {
twitch: {
allowFrom: ["123456789"], // (推荐)仅限你的 Twitch 用户 ID
allowedRoles: ["moderator"], // 或按角色限制
},
},
}
```
优先使用 `allowFrom` 作为硬性允许列表。如果你想要基于角色的访问控制,请改用 `allowedRoles`
**可用角色:** `"moderator"``"owner"``"vip"``"subscriber"``"all"`
**为什么用用户 ID** 用户名可以更改,允许冒充。用户 ID 是永久的。
**为什么使用用户 ID** 用户名可以更改,存在冒充风险。用户 ID 是永久的。
查找你的 Twitch 用户 IDhttps://www.streamweasels.com/tools/convert-twitch-username-%20to-user-id/(将你的 Twitch 用户名转换为 ID
查找你的 Twitch 用户 IDhttps://www.streamweasels.com/tools/convert-twitch-username-%20to-user-id/(将 Twitch 用户名转换为 ID
## 令牌刷新(可选)
来自 [Twitch Token Generator](https://twitchtokengenerator.com/) 的令牌无法自动刷新 - 过期时需要重新生成。
[Twitch Token Generator](https://twitchtokengenerator.com/) 获取的令牌无法自动刷新——过期后需重新生成。
要实现自动令牌刷新,请在 [Twitch Developer Console](https://dev.twitch.tv/console) 创建你自己的 Twitch 应用并添加到配置中:
如需自动刷新令牌,请在 [Twitch Developer Console](https://dev.twitch.tv/console) 创建你自己的 Twitch 应用并添加到配置中:
```json5
{
@@ -151,11 +150,11 @@ OPENCLAW_TWITCH_ACCESS_TOKEN=oauth:abc123...
机器人会在令牌过期前自动刷新,并记录刷新事件。
## 多账支持
## 多账支持
使用 `channels.twitch.accounts` 配置每个账的令牌。参 [`gateway/configuration`](/gateway/configuration) 了解共享模式。
使用 `channels.twitch.accounts` 配置每个账的令牌。参 [`gateway/configuration`](/gateway/configuration) 了解通用模式。
示例(一个机器人账户在两个频道
示例(一个机器人账号加入两个频道):
```json5
{
@@ -180,7 +179,7 @@ OPENCLAW_TWITCH_ACCESS_TOKEN=oauth:abc123...
}
```
**注意:** 每个账需要自己的令牌(每个频道一个令牌)。
**注意:** 每个账需要自己的令牌(每个频道一个令牌)。
## 访问控制
@@ -200,7 +199,7 @@ OPENCLAW_TWITCH_ACCESS_TOKEN=oauth:abc123...
}
```
### 按用户 ID 允许列表(最安全)
### 按用户 ID 设置允许列表(最安全)
```json5
{
@@ -216,10 +215,9 @@ OPENCLAW_TWITCH_ACCESS_TOKEN=oauth:abc123...
}
```
### 基于角色的访问(替代方案)
### 组合允许列表 + 角色
`allowFrom` 是硬性允许列表。设置后,只允许这些用户 ID。
如果你想要基于角色的访问,请不设置 `allowFrom`,改为配置 `allowedRoles`
`allowFrom` 中的用户可绕过角色检查:
```json5
{
@@ -227,6 +225,7 @@ OPENCLAW_TWITCH_ACCESS_TOKEN=oauth:abc123...
twitch: {
accounts: {
default: {
allowFrom: ["123456789"],
allowedRoles: ["moderator"],
},
},
@@ -264,17 +263,17 @@ openclaw channels status --probe
### 机器人不响应消息
**检查访问控制:** 确保你的用户 ID 在 `allowFrom` 中,或临时移除 `allowFrom`设置 `allowedRoles: ["all"]` 测试。
**检查访问控制:** 临时设置 `allowedRoles: ["all"]` 进行测试。
**检查机器人是否在频道中:** 机器人必须加入 `channel` 中指定的频道。
### 令牌问题
**"Failed to connect"或身份验证错误:**
**"Failed to connect" 或认证错误:**
- 验证 `accessToken` 是 OAuth 访问令牌值(通常以 `oauth:` 前缀开头)
- 检查令牌具有 `chat:read``chat:write` 权限范围
- 如果使用令牌刷新,验证 `clientSecret``refreshToken` 已设置
- 确认 `accessToken` 是 OAuth 访问令牌值(通常以 `oauth:` 前缀开头)
- 检查令牌是否具有 `chat:read``chat:write` 权限范围
- 如果使用令牌刷新,确认已设置 `clientSecret``refreshToken`
### 令牌刷新不工作
@@ -285,36 +284,36 @@ Using env token source for mybot
Access token refreshed for user 123456 (expires in 14400s)
```
如果看到"token refresh disabled (no refresh token)"
如果看到 "token refresh disabled (no refresh token)"
- 确保提供 `clientSecret`
- 确保提供 `refreshToken`
- 确保提供 `clientSecret`
- 确保提供 `refreshToken`
## 配置
**账配置:**
**账配置:**
- `username` - 机器人用户名
- `accessToken` - 具有 `chat:read``chat:write` 权限的 OAuth 访问令牌
- `clientId` - Twitch Client ID来自 Token Generator 或你的应用)
- `channel` - 要加入的频道(必填)
- `enabled` - 启用此账(默认:`true`
- `clientSecret` - 可选:用于自动令牌刷新
- `refreshToken` - 可选:用于自动令牌刷新
- `enabled` - 启用此账(默认:`true`
- `clientSecret` - 可选:用于自动刷新令牌
- `refreshToken` - 可选:用于自动刷新令牌
- `expiresIn` - 令牌过期时间(秒)
- `obtainmentTimestamp` - 令牌获取时间戳
- `allowFrom` - 用户 ID 允许列表
- `allowedRoles` - 基于角色的访问控制(`"moderator" | "owner" | "vip" | "subscriber" | "all"`
- `requireMention` - @提及(默认:`true`
- `requireMention` - 要 @提及(默认:`true`
**提供商选项:**
- `channels.twitch.enabled` - 启用/禁用渠道启动
- `channels.twitch.username` - 机器人用户名(简化单账配置)
- `channels.twitch.accessToken` - OAuth 访问令牌(简化单账配置)
- `channels.twitch.clientId` - Twitch Client ID简化单账配置)
- `channels.twitch.channel` - 要加入的频道(简化单账配置)
- `channels.twitch.accounts.<accountName>` - 多账配置(上所有账字段)
- `channels.twitch.username` - 机器人用户名(简化单账配置)
- `channels.twitch.accessToken` - OAuth 访问令牌(简化单账配置)
- `channels.twitch.clientId` - Twitch Client ID简化单账配置)
- `channels.twitch.channel` - 要加入的频道(简化单账配置)
- `channels.twitch.accounts.<accountName>` - 多账配置(上所有账字段)
完整示例:
@@ -371,15 +370,15 @@ Access token refreshed for user 123456 (expires in 14400s)
## 安全与运维
- **将令牌视为密码** - 永远不要将令牌提交到 git
- **将令牌视为密码** - 切勿将令牌提交到 git
- **使用自动令牌刷新** 用于长时间运行的机器人
- **使用用户 ID 允许列表** 而不是用户名进行访问控制
- **监控日志** 查看令牌刷新事件和连接状态
- **最小化令牌权限范围** - 请求 `chat:read``chat:write`
- **如果卡住**确认没有其他进程拥有会话后重启 Gateway 网关
- **使用用户 ID 允许列表** 而用户名进行访问控制
- **监控日志** 关注令牌刷新事件和连接状态
- **最小化令牌权限范围** - 请求 `chat:read``chat:write`
- **如遇问题**:确认没有其他进程占用会话后重启 Gateway网关
## 限制
- 每条消息 **500 个字符**在单词边界自动分块)
- 分块前会除 Markdown
- 每条消息最多 **500 个字符**词边界自动分块)
- 分块前会除 Markdown 格式
- 无速率限制(使用 Twitch 内置的速率限制)

View File

@@ -4,24 +4,24 @@ read_when:
summary: WhatsApp网页渠道集成登录、收件箱、回复、媒体和运维
title: WhatsApp
x-i18n:
generated_at: "2026-02-03T07:46:24Z"
generated_at: "2026-02-01T20:00:02Z"
model: claude-opus-4-5
provider: pi
source_hash: 44fd88f8e269284999e5a5a52b230edae6e6f978528dd298d6a5603d03c0c38d
source_path: channels/whatsapp.md
workflow: 15
workflow: 14
---
# WhatsApp网页渠道
状态:仅支持通过 Baileys 的 WhatsApp Web。Gateway 网关拥有会话。
状态:仅支持通过 Baileys 的 WhatsApp Web。Gateway网关拥有会话。
## 快速设置(新手
## 快速设置(入门
1. 如果可能,使用**单独的手机号码**(推荐)。
2.`~/.openclaw/openclaw.json` 中配置 WhatsApp。
3. 运行 `openclaw channels login` 扫描二维码(关联设备)。
4. 启动 Gateway 网关。
3. 运行 `openclaw channels login` 扫描二维码(关联设备)。
4. 启动 Gateway网关。
最小配置:
@@ -38,13 +38,13 @@ x-i18n:
## 目标
- 在一个 Gateway 网关进程中支持多个 WhatsApp 账(多账)。
- 个 Gateway网关进程中支持多个 WhatsApp 账(多账)。
- 确定性路由:回复返回到 WhatsApp无模型路由。
- 模型能看到足够的上下文理解引用回复。
- 模型获得足够的上下文理解引用回复。
## 配置写入
默认情况下WhatsApp 允许写入由 `/config set|unset` 触发配置更新(需要 `commands.config: true`)。
默认情况下WhatsApp 允许通过 `/config set|unset` 触发配置更新写入(需要 `commands.config: true`)。
禁用方式:
@@ -54,21 +54,21 @@ x-i18n:
}
```
## 架构(谁拥有什么
## 架构(职责划分
- **Gateway 网关**拥有 Baileys socket 和收件箱循环。
- **CLI / macOS 应用**与 Gateway 网关通信;不直接使用 Baileys。
- 发送出站消息需要**活跃监听器**;否则发送会快速失败。
- **Gateway网关** 拥有 Baileys socket 和收件箱循环。
- **CLI / macOS 应用** 与 Gateway网关通信不直接使用 Baileys。
- **活跃监听器** 是出站发送的必要条件;否则发送会快速失败。
## 获取手机号码(两种模式)
WhatsApp 需要真实手机号码进行验证。VoIP 和虚拟号码通常会被封锁。在 WhatsApp 上运行 OpenClaw 有两种支持的方式:
WhatsApp 需要真实手机号码进行验证。VoIP 和虚拟号码通常会被屏蔽。在 WhatsApp 上运行 OpenClaw 有两种支持的方式:
### 专用号码(推荐)
为 OpenClaw 使用**单独的手机号码**。最佳用户体验,清晰的路由,无自聊天怪异问题。理想设置:**备用/旧 Android 手机 + eSIM**。保持 Wi-Fi 和电连接,通过二维码关联。
为 OpenClaw 使用**单独的手机号码**。最佳用户体验,干净的路由,无自聊天问题。理想设置:**备用/旧 Android 手机 + eSIM**。保持 Wi-Fi 和电连接,通过二维码关联。
**WhatsApp Business** 你可以在同一设备上使用不同号码的 WhatsApp Business。非常适合将个人 WhatsApp 分开——安装 WhatsApp Business 并在那里注册 OpenClaw 号码。
**WhatsApp Business** 你可以在同一设备上使用不同号码的 WhatsApp Business。非常适合将个人 WhatsApp 分开安装 WhatsApp Business 并在其中注册 OpenClaw 号码。
**示例配置(专用号码,单用户允许列表):**
@@ -84,13 +84,13 @@ WhatsApp 需要真实手机号码进行验证。VoIP 和虚拟号码通常会被
```
**配对模式(可选):**
如果你想使用配对而不是允许列表,`channels.whatsapp.dmPolicy` 设置为 `pairing`。未知发送者会收到配对码;使用以下命令批准:
如果你想使用配对而允许列表,将 `channels.whatsapp.dmPolicy` 设置为 `pairing`。未知发送者会收到配对码;通过以下命令批准:
`openclaw pairing approve whatsapp <code>`
### 个人号码(备选方案)
快速备选方案:在**你自己的号码**上运行 OpenClaw。给自己发消息WhatsApp"给自己发消息")进行测试,这样就不会打扰联系人。在设置和实验期间需要在主手机上读验证码。**必须启用自聊天模式。**
当向导询问你的个人 WhatsApp 号码时,输入你将用于发送消息的手机(所有者/发送者),而不是助手号码。
快速备选方案:在**你自己的号码**上运行 OpenClaw。给自己发消息WhatsApp "给自己发消息")进行测试,避免打扰联系人。在设置和实验期间需要在主手机上读验证码。**必须启用自聊天模式。**
当向导询问你的个人 WhatsApp 号码时,输入你将用来发消息的手机(所有者/发送者),而不是助手号码。
**示例配置(个人号码,自聊天):**
@@ -104,65 +104,64 @@ WhatsApp 需要真实手机号码进行验证。VoIP 和虚拟号码通常会被
}
```
当设置了 `identity.name` 时,自聊天回复默认 `[{identity.name}]`(否则为 `[openclaw]`
前提是 `messages.responsePrefix` 未设置。明确设置它可以自定义或禁用
前缀(使用 `""` 来移除)。
当设置了 `messages.responsePrefix` 时,自聊天回复默认使用 `[{identity.name}]`(否则为 `[openclaw]`
如果 `messages.responsePrefix` 未设置,则使用默认值。显式设置可自定义或禁用前缀(使用 `""` 来移除)。
### 号码获取提示
### 号码获取技巧
- **本 eSIM** 来自你所在国家的移动运营商(最可靠)
- **本 eSIM**来自你所在国家的移动运营商(最可靠)
- 奥地利:[hot.at](https://www.hot.at)
- 英国:[giffgaff](https://www.giffgaff.com) — 免费 SIM 卡,无合约
- **预付费 SIM 卡** — 便宜,只需接收一条验证短信
**避免:** TextNow、Google Voice、大多数"免费短信"服务——WhatsApp 会积极封锁这些
**避免使用** TextNow、Google Voice、大多数"免费短信"服务WhatsApp 会积极屏蔽这些号码
**提示:** 该号码只需接收一条验证短信。之后WhatsApp Web 会话通过 `creds.json` 持久
**提示:** 该号码只需接收一条验证短信。之后WhatsApp Web 会话通过 `creds.json` 持久保存
## 为什么不用 Twilio
- 早期 OpenClaw 版本支持 Twilio 的 WhatsApp Business 集成。
- WhatsApp Business 号码不适合个人助手。
- Meta 强制执行 24 小时回复窗口;如果你在过去 24 小时内没有回复,商业号码无法发起新消息。
- 高频或"频繁"使用会触发激进的封,因为商业账不适合发送大量个人助手消息。
- 结果:投递不可靠且频繁被封,因此该支持已被移除
- 高频或"频繁"使用会触发激进的封,因为商业账不适合发送大量个人助手消息。
- 结果:投递不可靠且频繁被封,因此已移除支持
## 登录 + 凭证
- 登录命令:`openclaw channels login`(通过关联设备扫描二维码)。
- 多账登录:`openclaw channels login --account <id>``<id>` = `accountId`)。
- 默认账(省略 `--account` 时):如果存在则为 `default`,否则为第一个配置的账户 id(排序后)。
- 登录命令:`openclaw channels login`(通过关联设备扫描二维码)。
- 多账登录:`openclaw channels login --account <id>``<id>` = `accountId`)。
- 默认账(省略 `--account` 时):如果存在则为 `default`,否则为第一个配置的账号 ID(排序后)。
- 凭证存储在 `~/.openclaw/credentials/whatsapp/<accountId>/creds.json`
- 备份副本 `creds.json.bak`(损坏时恢复)。
- 旧版兼容性:较旧的安装将 Baileys 文件直接存储在 `~/.openclaw/credentials/`
- 登出`openclaw channels logout`(或 `--account <id>`)删除 WhatsApp 认证状态(但保留共享的 `oauth.json`)。
-登出的 socket => 错误提示重新关联。
- 备份副本位于 `creds.json.bak`(损坏时恢复)。
- 旧版兼容:早期安装将 Baileys 文件直接存储在 `~/.openclaw/credentials/`
- 注销`openclaw channels logout`(或 `--account <id>`)删除 WhatsApp 认证状态(但保留共享的 `oauth.json`)。
-注销的 socket => 错误提示重新关联。
## 入站流程(私 + 群
## 入站流程(私 + 群
- WhatsApp 事件来自 `messages.upsert`Baileys
- 收件箱监听器在关闭时分离,以避免在测试/重启累积事件处理器。
- 收件箱监听器在关闭时解除绑定,以避免在测试/重启累积事件处理器。
- 状态/广播聊天被忽略。
- 直接聊天使用 E.164;群使用群组 JID。
- **私策略**`channels.whatsapp.dmPolicy` 控制直接聊天访问(默认:`pairing`)。
- 私聊使用 E.164 格式;群使用群组 JID。
- **私策略**`channels.whatsapp.dmPolicy` 控制私聊访问(默认:`pairing`)。
- 配对:未知发送者会收到配对码(通过 `openclaw pairing approve whatsapp <code>` 批准;码在 1 小时后过期)。
- 开放:需要 `channels.whatsapp.allowFrom` 包含 `"*"`
- 你关联的 WhatsApp 号码隐式信任,因此自消息跳过 `channels.whatsapp.dmPolicy``channels.whatsapp.allowFrom` 检查。
- 你关联的 WhatsApp 号码隐式信任,因此自消息跳过 `channels.whatsapp.dmPolicy``channels.whatsapp.allowFrom` 检查。
### 个人号码模式(备选方案)
如果你在**个人 WhatsApp 号码**上运行 OpenClaw启用 `channels.whatsapp.selfChatMode`(见上面的示例)。
如果你在**个人 WhatsApp 号码**上运行 OpenClaw启用 `channels.whatsapp.selfChatMode`见上方示例配置)。
行为:
- 出站私信永远不会触发配对回复(防止扰联系人)。
- 出站私聊消息不会触发配对回复(防止扰联系人)。
- 入站未知发送者仍遵循 `channels.whatsapp.dmPolicy`
- 自聊天模式allowFrom 包含你的号码)避免自动已读回执并忽略提及 JID。
- 非自聊天私会发送已读回执。
- 非自聊天私会发送已读回执。
## 已读回执
默认情况下Gateway 网关在接受入站 WhatsApp 消息后将其标记为已读(蓝色勾)。
默认情况下Gateway网关在接受入站 WhatsApp 消息后将其标记为已读(蓝色勾)。
全局禁用:
@@ -172,7 +171,7 @@ WhatsApp 需要真实手机号码进行验证。VoIP 和虚拟号码通常会被
}
```
按账禁用:
按账禁用:
```json5
{
@@ -186,31 +185,31 @@ WhatsApp 需要真实手机号码进行验证。VoIP 和虚拟号码通常会被
}
```
意事项
注:
- 自聊天模式始终跳过已读回执。
## WhatsApp 常见问题:发送消息 + 配对
**当我关联 WhatsApp OpenClaw 会给随机联系人发消息吗?**
不会。默认私策略是**配对**,因此未知发送者只会收到配对码,他们的消息**不会被处理**。OpenClaw 只回复收到的聊天,或你明确触发的发送(智能体/CLI
**关联 WhatsApp OpenClaw 会给随机联系人发消息吗?**
不会。默认私策略是**配对**,因此未知发送者只会收到配对码,消息**不会被处理**。OpenClaw 只回复收到的聊天,或你显式触发的发送(智能体/CLI
**WhatsApp 上的配对是如何工作的?**
配对是未知发送者的私门控:
配对是针对未知发送者的私门控:
- 来自新发送者的第一条私信返回一个短码(消息不会被处理)。
- 使用以下命令批准:`openclaw pairing approve whatsapp <code>`使`openclaw pairing list whatsapp` 列出)。
- 新发送者的首条私聊消息会返回一个短码(消息不会被处理)。
- 通过以下命令批准:`openclaw pairing approve whatsapp <code>`(用 `openclaw pairing list whatsapp` 列出)。
- 码在 1 小时后过期;每个渠道的待处理请求上限为 3 个。
**多人可以在一个 WhatsApp 号码上使用不同的 OpenClaw 实例吗?**
可以,通过 `bindings` 将每个发送者路由到不同的智能体peer `kind: "dm"`,发送者 E.164 如 `+15551234567`)。回复仍然来自**同一个 WhatsApp 账**直接聊天会折叠到每个智能体的主会话,因此**每人使用一个智能体**。私访问控制(`dmPolicy`/`allowFrom`每个 WhatsApp 账全局的。参见[多智能体路由](/concepts/multi-agent)。
**多人可以在一个 WhatsApp 号码上使用不同的 OpenClaw 实例吗?**
可以,通过 `bindings` 将每个发送者路由到不同的智能体peer `kind: "dm"`,发送者 E.164 如 `+15551234567`)。回复仍然来自**同一个 WhatsApp 账**且私聊会折叠到每个智能体的主会话,因此请使用**每人一个智能体**。私访问控制(`dmPolicy`/`allowFrom`每个 WhatsApp 账号级别是全局的。参见[多智能体路由](/concepts/multi-agent)。
**为什么向导询问我的手机号码?**
向导使用它来设置你的**允许列表/所有者**,以便允许你自己的私。它不用于自动发送。如果你在个人 WhatsApp 号码上运行,使用相同的号码并启用 `channels.whatsapp.selfChatMode`
**为什么向导询问我的手机号码?**
向导使用它来设置你的**允许列表/所有者**,以便允许你自己的私聊消息。它不用于自动发送。如果你在个人 WhatsApp 号码上运行,使用相同的号码并启用 `channels.whatsapp.selfChatMode`
## 消息规范化(模型看到的内容)
## 消息标准化(模型看到的内容)
- `Body`带有信封的当前消息正文。
- `Body` 是当前消息正文及其信封
- 引用回复上下文**始终附加**
```
[Replying to +1555 id:ABC123]
@@ -220,35 +219,35 @@ WhatsApp 需要真实手机号码进行验证。VoIP 和虚拟号码通常会被
- 回复元数据也会设置:
- `ReplyToId` = stanzaId
- `ReplyToBody` = 引用正文或媒体占位符
- `ReplyToSender` = 已知时为 E.164
- `ReplyToSender` = E.164(已知时)
- 纯媒体入站消息使用占位符:
- `<media:image|video|audio|document|sticker>`
## 群
## 群
- 群映射到 `agent:<agentId>:whatsapp:group:<jid>` 会话。
- 群策略:`channels.whatsapp.groupPolicy = open|disabled|allowlist`(默认 `allowlist`)。
- 群映射到 `agent:<agentId>:whatsapp:group:<jid>` 会话。
- 群策略:`channels.whatsapp.groupPolicy = open|disabled|allowlist`(默认 `allowlist`)。
- 激活模式:
- `mention`(默认):需要 @提及或正则匹配。
- `always`:始终触发。
- `/activation mention|always` 仅限所有者必须作为独立消息发送。
- 所有者 = `channels.whatsapp.allowFrom`如果未设置为自身 E.164)。
- `/activation mention|always` 仅限所有者必须作为独立消息发送。
- 所有者 = `channels.whatsapp.allowFrom`(未设置为自身 E.164)。
- **历史注入**(仅待处理):
- 最近*未处理*的消息(默认 50 条)插入在:
`[Chat messages since your last reply - for context]`(已在会话中的消息不会重新注入)
- 当前消息
`[Chat messages since your last reply - for context]`(已在会话中的消息不会被重复注入)
- 当前消息位于
`[Current message - respond to this]`
- 附加发送者后缀:`[from: Name (+E164)]`
- 群元数据缓存 5 分钟(主题 + 参与者)。
- 发送者后缀附加`[from: Name (+E164)]`
- 群元数据缓存 5 分钟(主题 + 参与者)。
## 回复投递(线程)
- WhatsApp Web 发送标准消息(当前 Gateway 网关无引用回复线程)。
- WhatsApp Web 发送标准消息(当前 Gateway网关无引用回复线程)。
- 此渠道忽略回复标签。
## 确认表情(收到时自动应)
## 确认反应(收到消息时自动应)
WhatsApp 可以在收到传入消息时立即自动发送表情应,在机器人生成回复之前。这为用户提供即时反馈,表明他们的消息已收到。
WhatsApp 可以在收到消息时立即自动发送表情应,在机器人生成回复之前。这为用户提供即时反馈,表明消息已收到。
**配置:**
@@ -266,14 +265,14 @@ WhatsApp 可以在收到传入消息时立即自动发送表情回应,在机
**选项:**
- `emoji`(字符串):用于确认的表情(例如"👀"、"✅"、"📨")。为空或省略 = 功能禁用。
- `direct`(布尔值,默认:`true`):在直接/私信聊天中发送表情回应。
- `emoji`(字符串):用于确认的表情(例如 "👀"、"✅"、"📨")。为空或省略 = 功能禁用。
- `direct`(布尔值,默认:`true`):在私聊/私信 中发送应。
- `group`(字符串,默认:`"mentions"`):群聊行为:
- `"always"`:对所有群消息做出应(即使没有 @提及)
- `"mentions"`:仅在机器人被 @提及时做出
- `"never"`:从不在群中做出
- `"always"`:对所有群消息做出应(即使没有 @提及)
- `"mentions"`:仅在机器人被 @提及时做出
- `"never"`:从不在群中做出
**按账覆盖:**
**按账覆盖:**
```json
{
@@ -293,42 +292,42 @@ WhatsApp 可以在收到传入消息时立即自动发送表情回应,在机
**行为说明:**
- 表情回应在消息收到时**立即**发送,在输入指示器或机器人回复之前。
- 在 `requireMention: false`激活always的群组中`group: "mentions"` 会对所有消息做出应(不仅仅是 @提及)。
- 即发即忘:表情回应失败会被记录但不会阻止机器人回复。
- 群组表情回应会自动包含参与者 JID。
- 反应在收到消息时**立即**发送,在输入指示器或机器人回复之前。
- 在 `requireMention: false`(激活模式always的群组中`group: "mentions"` 会对所有消息做出应(不仅仅是 @提及)。
- 即发即忘:应失败会被记录但不会阻止机器人回复。
- 群聊反应会自动包含参与者 JID。
- WhatsApp 忽略 `messages.ackReaction`;请改用 `channels.whatsapp.ackReaction`。
## 智能体工具(表情回应)
## 智能体工具(应)
- 工具:`whatsapp`带有 `react` 动作(`chatJid`、`messageId`、`emoji`,可选 `remove`)。
- 可选:`participant`(群发送者)、`fromMe`(对自己的消息做出应)、`accountId`(多账)。
- 表情移除语义:参见 [/tools/reactions](/tools/reactions)。
- 工具:`whatsapp`使用 `react` 动作(`chatJid`、`messageId`、`emoji`,可选 `remove`)。
- 可选:`participant`(群发送者)、`fromMe`(对自己的消息做出应)、`accountId`(多账)。
- 反应移除语义:参见 [/tools/reactions](/tools/reactions)。
- 工具门控:`channels.whatsapp.actions.reactions`(默认:启用)。
## 限制
- 出站文本按 `channels.whatsapp.textChunkLimit` 分块(默认 4000
- 可选换行分块:设置 `channels.whatsapp.chunkMode="newline"` 在长度分块之前按空行(段落边界)分割。
- 可选换行分块:设置 `channels.whatsapp.chunkMode="newline"` 在空行(段落边界)分割,再进行长度分块
- 入站媒体保存受 `channels.whatsapp.mediaMaxMb` 限制(默认 50 MB
- 出站媒体项受 `agents.defaults.mediaMaxMb` 限制(默认 5 MB
## 出站发送(文本 + 媒体)
- 使用活跃的网页监听器;如果 Gateway 网关未运行则报错。
- 使用活跃的网页监听器;如果 Gateway网关未运行则报错。
- 文本分块:每条消息最大 4k可通过 `channels.whatsapp.textChunkLimit` 配置,可选 `channels.whatsapp.chunkMode`)。
- 媒体:
- 支持图片/视频/音频/文档。
- 音频作为 PTT 发送;`audio/ogg` => `audio/ogg; codecs=opus`。
- 仅第一个媒体项上添加标题
- 音频 PTT 发送;`audio/ogg` => `audio/ogg; codecs=opus`。
- 仅第一个媒体项带字幕
- 媒体获取支持 HTTP(S) 和本地路径。
- 动 GIFWhatsApp 期望带 `gifPlayback: true` 的 MP4 以实现内联循环。
- 动 GIFWhatsApp 期望带 `gifPlayback: true` 的 MP4 以实现内联循环播放
- CLI`openclaw message send --media <mp4> --gif-playback`
- Gateway 网关:`send` 参数包含 `gifPlayback: true`
- Gateway网关`send` 参数包含 `gifPlayback: true`
## 语音消息PTT 音频)
WhatsApp 将音频作为**语音消息**PTT 气泡)发送。
WhatsApp **语音消息**PTT 气泡)发送音频
- 最佳效果OGG/Opus。OpenClaw 将 `audio/ogg` 重写为 `audio/ogg; codecs=opus`。
- WhatsApp 忽略 `[[audio_as_voice]]`(音频已作为语音消息发送)。
@@ -337,43 +336,43 @@ WhatsApp 将音频作为**语音消息**PTT 气泡)发送。
- 默认出站上限5 MB每个媒体项
- 覆盖:`agents.defaults.mediaMaxMb`。
- 图片自动优化为上限以下的 JPEG调整大小 + 质量扫描)。
- 超大媒体 => 错误;媒体回复降级为文本警告。
- 图片自动优化为 JPEG 以控制在上限内(缩放 + 质量扫描)。
- 超大媒体 => 错误;媒体回复回退为文本警告。
## 心跳
- **Gateway 网关心跳**记录连接健康状态(`web.heartbeatSeconds`,默认 60 秒)。
- **智能体心跳**可按智能体配置(`agents.list[].heartbeat`)或通过
`agents.defaults.heartbeat` 全局配置(当没有设置智能体条目时的降级)。
- 使用配置的心跳提示(默认:`Read HEARTBEAT.md if it exists (workspace context). Follow it strictly. Do not infer or repeat old tasks from prior chats. If nothing needs attention, reply HEARTBEAT_OK.`+ `HEARTBEAT_OK` 跳过行为。
- 投递默认最后使用的渠道(或配置的目标)。
- **Gateway网关心跳** 记录连接健康状态(`web.heartbeatSeconds`,默认 60 秒)。
- **智能体心跳** 可按智能体配置(`agents.list[].heartbeat`)或通过
`agents.defaults.heartbeat` 全局配置(设置智能体条目时的回退)。
- 使用配置的心跳提示(默认:`Read HEARTBEAT.md if it exists (workspace context). Follow it strictly. Do not infer or repeat old tasks from prior chats. If nothing needs attention, reply HEARTBEAT_OK.`+ `HEARTBEAT_OK` 跳过行为。
- 投递默认最后使用的渠道(或配置的目标)。
## 重连行为
- 退避策略:`web.reconnect`
- `initialMs`、`maxMs`、`factor`、`jitter`、`maxAttempts`。
- 如果达到 maxAttempts网页监控停止降级
- 已登出 => 停止并要求重新关联。
- 已注销 => 停止并要求重新关联。
## 配置快速映射
## 配置速查表
- `channels.whatsapp.dmPolicy`(私策略pairing/allowlist/open/disabled
- `channels.whatsapp.selfChatMode`(同手机设置;机器人使用你的个人 WhatsApp 号码)。
- `channels.whatsapp.allowFrom`(私允许列表。WhatsApp 使用 E.164 手机号码(无用户名)。
- `channels.whatsapp.dmPolicy`(私策略pairing/allowlist/open/disabled
- `channels.whatsapp.selfChatMode`(同设置;机器人使用你的个人 WhatsApp 号码)。
- `channels.whatsapp.allowFrom`(私允许列表。WhatsApp 使用 E.164 手机号码(无用户名)。
- `channels.whatsapp.mediaMaxMb`(入站媒体保存上限)。
- `channels.whatsapp.ackReaction`(消息收到时的自动应:`{emoji, direct, group}`)。
- `channels.whatsapp.accounts.<accountId>.*`(按账设置 + 可选 `authDir`)。
- `channels.whatsapp.accounts.<accountId>.mediaMaxMb`(按账入站媒体上限)。
- `channels.whatsapp.accounts.<accountId>.ackReaction`(按账确认应覆盖)。
- `channels.whatsapp.groupAllowFrom`(群发送者允许列表)。
- `channels.whatsapp.groupPolicy`(群策略)。
- `channels.whatsapp.historyLimit` / `channels.whatsapp.accounts.<accountId>.historyLimit`(群历史上下文;`0` 禁用)。
- `channels.whatsapp.dmHistoryLimit`(私历史限制,按用户轮)。按用户覆盖:`channels.whatsapp.dms["<phone>"].historyLimit`。
- `channels.whatsapp.groups`(群允许列表 + 提及门控默认值;使用 `"*"` 允许全部)
- `channels.whatsapp.actions.reactions`门控 WhatsApp 工具表情回应)。
- `channels.whatsapp.ackReaction`(消息收到时的自动应:`{emoji, direct, group}`)。
- `channels.whatsapp.accounts.<accountId>.*`(按账设置 + 可选 `authDir`)。
- `channels.whatsapp.accounts.<accountId>.mediaMaxMb`(按账入站媒体上限)。
- `channels.whatsapp.accounts.<accountId>.ackReaction`(按账确认应覆盖)。
- `channels.whatsapp.groupAllowFrom`(群发送者允许列表)。
- `channels.whatsapp.groupPolicy`(群策略)。
- `channels.whatsapp.historyLimit` / `channels.whatsapp.accounts.<accountId>.historyLimit`(群历史上下文;`0` 禁用)。
- `channels.whatsapp.dmHistoryLimit`(私历史限制,按用户轮)。按用户覆盖:`channels.whatsapp.dms["<phone>"].historyLimit`。
- `channels.whatsapp.groups`(群允许列表 + 提及门控默认值;使用 `"*"` 允许全部)
- `channels.whatsapp.actions.reactions`WhatsApp 工具反应门控)。
- `agents.list[].groupChat.mentionPatterns`(或 `messages.groupChat.mentionPatterns`
- `messages.groupChat.historyLimit`
- `channels.whatsapp.messagePrefix`(入站前缀;按账`channels.whatsapp.accounts.<accountId>.messagePrefix`;已弃用:`messages.messagePrefix`
- `channels.whatsapp.messagePrefix`(入站前缀;按账`channels.whatsapp.accounts.<accountId>.messagePrefix`;已弃用:`messages.messagePrefix`
- `messages.responsePrefix`(出站前缀)
- `agents.defaults.mediaMaxMb`
- `agents.defaults.heartbeat.every`
@@ -391,21 +390,21 @@ WhatsApp 将音频作为**语音消息**PTT 气泡)发送。
- 子系统:`whatsapp/inbound`、`whatsapp/outbound`、`web-heartbeat`、`web-reconnect`。
- 日志文件:`/tmp/openclaw/openclaw-YYYY-MM-DD.log`(可配置)。
- 故障排除指南:[Gateway 网关故障排除](/gateway/troubleshooting)。
- 故障排除指南:[Gateway网关故障排除](/gateway/troubleshooting)。
## 故障排除(快速)
**未关联 / 需要二维码登录**
- 症状:`channels status` 显示 `linked: false` 或警告"Not linked"。
- 修复:在 Gateway 网关主机上运行 `openclaw channels login` 并扫描二维码WhatsApp → 设置 → 关联设备)。
- 症状:`channels status` 显示 `linked: false` 或警告"未关联"。
- 修复:在 Gateway网关主机上运行 `openclaw channels login` 并扫描二维码WhatsApp → 设置 → 关联设备)。
**已关联但断开连接 / 重连循环**
- 症状:`channels status` 显示 `running, disconnected` 或警告"Linked but disconnected"。
- 修复:`openclaw doctor`(或重启 Gateway 网关)。如果问题持续,通过 `channels login` 重新关联并检查 `openclaw logs --follow`。
- 症状:`channels status` 显示 `running, disconnected` 或警告"已关联但断开连接"。
- 修复:`openclaw doctor`(或重启 Gateway网关。如果问题持续通过 `channels login` 重新关联并检查 `openclaw logs --follow`。
**Bun 运行时**
- **不推荐** Bun。WhatsAppBaileys和 Telegram 在 Bun 上不可靠
请使用 **Node** 运行 Gateway 网关。(参见入门指南运行时说明。)
- **不推荐**使用 Bun。WhatsAppBaileys和 Telegram 在 Bun 上不稳定
请使用 **Node** 运行 Gateway网关。参见入门指南运行时说明。

View File

@@ -1,40 +1,40 @@
---
read_when:
- 开发 Zalo 功能或 webhooks
summary: Zalo bot 支持状态、功能和配置
- 处理 Zalo 功能或 webhook
summary: Zalo 机器人支持状态、功能和配置
title: Zalo
x-i18n:
generated_at: "2026-02-03T07:44:44Z"
generated_at: "2026-02-01T19:58:32Z"
model: claude-opus-4-5
provider: pi
source_hash: 0311d932349f96412b712970b5d37329b91929bf3020536edf3ca0ff464373c0
source_path: channels/zalo.md
workflow: 15
workflow: 14
---
# Zalo (Bot API)
状态:实验性。仅支持私信;根据 Zalo 文档,群组即将推出。
状态:实验性。仅支持私信;根据 Zalo 文档,群组功能即将推出。
## 需要插件
Zalo 以插件形式提供,不包含在核心安装中。
- 通过 CLI 安装:`openclaw plugins install @openclaw/zalo`
- 或在新手引导期间选择 **Zalo** 并确认安装提示
- 或在新手引导选择 **Zalo** 并确认安装提示
- 详情:[插件](/plugin)
## 快速设置(初学者
## 快速设置(新手
1. 安装 Zalo 插件:
- 从源码检出:`openclaw plugins install ./extensions/zalo`
- 从 npm已发布):`openclaw plugins install @openclaw/zalo`
- 从源码检出安装`openclaw plugins install ./extensions/zalo`
- 从 npm 安装(如已发布):`openclaw plugins install @openclaw/zalo`
- 或在新手引导中选择 **Zalo** 并确认安装提示
2. 设置 token
2. 设置令牌
- 环境变量:`ZALO_BOT_TOKEN=...`
- 或配置:`channels.zalo.botToken: "..."`
3. 重启 Gateway 网关(或完成新手引导)。
4. 私信访问默认配对模式;首次联系时批准配对码。
3. 重启 Gateway网关或完成新手引导
4. 私信访问默认使用配对模式;首次联系时批准配对码。
最小配置:
@@ -50,25 +50,25 @@ Zalo 以插件形式提供,不包含在核心安装中。
}
```
## 它是什么
## 简介
Zalo 是一款专注于越南市场的即时通讯应用;其 Bot API Gateway 网关可以运行一个用于一对一对话的 bot
它非常适合需要确定性路由回 Zalo 的支持或通知场景。
Zalo 是一款面向越南市场的即时通讯应用;其 Bot API 允许 Gateway网关运行一个用于一对一对话的机器人
它非常适合需要将消息确定性路由回 Zalo 的客服或通知场景。
- 由 Gateway 网关拥有的 Zalo Bot API 渠道。
- 确定性路由:回复返回 Zalo模型不会选择渠道。
- 由 Gateway网关管理的 Zalo Bot API 渠道。
- 确定性路由:回复始终返回 Zalo模型不会选择渠道。
- 私信共享智能体的主会话。
- 群组尚不支持Zalo 文档标注"即将推出")。
## 设置(快速路径)
### 1)创建 bot tokenZalo Bot 平台
### 1) 创建机器人令牌Zalo Bot Platform
1. 前往 **https://bot.zaloplatforms.com** 并登录。
2. 创建新 bot 并配置其设置。
3. 复制 bot token(格式:`12345689:abc-xyz`)。
2. 创建新机器人并配置其设置。
3. 复制机器人令牌(格式:`12345689:abc-xyz`)。
### 2)配置 token(环境变量或配置)
### 2) 配置令牌(环境变量或配置文件
示例:
@@ -86,49 +86,49 @@ Zalo 是一款专注于越南市场的即时通讯应用;其 Bot API 让 Gatew
环境变量选项:`ZALO_BOT_TOKEN=...`(仅适用于默认账户)。
多账户支持:使用 `channels.zalo.accounts` 配置每账户 token 和可选的 `name`
多账户支持:使用 `channels.zalo.accounts`,为每个账户配置令牌和可选的 `name`
3. 重启 Gateway 网关。当 token 被解析环境变量或配置Zalo 启动。
4. 私信访问默认配对模式。当 bot 首次被联系时批准配对码。
3. 重启 Gateway网关。当令牌被解析(通过环境变量或配置Zalo 启动。
4. 私信访问默认使用配对模式。机器人首次被联系时,请批准配对码。
## 工作原理(行为)
- 入站消息被规范化为带有媒体占位符的共享渠道信封
- 回复始终路由回同一 Zalo 聊天。
- 入站消息被标准化为共享渠道信封,并包含媒体占位符
- 回复始终路由回同一 Zalo 聊天。
- 默认使用长轮询;可通过 `channels.zalo.webhookUrl` 启用 webhook 模式。
## 限制
- 出站文本按 2000 字符分块Zalo API 限制)。
- 媒体下载/上传受 `channels.zalo.mediaMaxMb` 限制(默认 5
- 由于 2000 字符限制使流式传输效果不佳,默认阻止流式传输。
- 由于 2000 字符限制导致流式传输意义不大,默认禁用流式传输。
## 访问控制(私信)
### 私信访问
- 默认:`channels.zalo.dmPolicy = "pairing"`。未知发送者会收到配对码;消息在批准前被忽略(配对码 1 小时后过期)。
- 通过以下方式批准:
- 默认:`channels.zalo.dmPolicy = "pairing"`。未知发送者会收到配对码;消息在批准前被忽略(配对码 1 小时后过期)。
- 批准方式
- `openclaw pairing list zalo`
- `openclaw pairing approve zalo <CODE>`
- 配对是默认的令牌交换方式。详情:[配对](/start/pairing)
- `channels.zalo.allowFrom` 接受数字用户 ID用户名查找功能)。
- `channels.zalo.allowFrom` 接受数字用户 ID不支持用户名查找)。
## 长轮询与 webhook
- 默认:长轮询(不需要公共 URL
- 默认:长轮询(无需公网 URL
- Webhook 模式:设置 `channels.zalo.webhookUrl``channels.zalo.webhookSecret`
- Webhook secret 必须为 8-256 个字符。
- Webhook 密钥必须为 8-256 个字符。
- Webhook URL 必须使用 HTTPS。
- Zalo 发送事件时带有 `X-Bot-Api-Secret-Token` 头用于验证。
- Gateway 网关 HTTP 在 `channels.zalo.webhookPath` 处理 webhook 请求(默认为 webhook URL 路径)。
- Zalo 通过 `X-Bot-Api-Secret-Token` 请求头发送事件以进行验证。
- Gateway网关 HTTP 在 `channels.zalo.webhookPath` 处理 webhook 请求(默认为 webhook URL 路径)。
**注意:** 根据 Zalo API 文档getUpdates轮询和 webhook 互斥
**注意:** 根据 Zalo API 文档getUpdates轮询和 webhook 互斥。
## 支持的消息类型
- **文本消息**完全支持2000 字符分块。
- **图片消息**:下载处理入站图片;通过 `sendPhoto` 发送图片。
- **文本消息**:完全支持,2000 字符分块。
- **图片消息**:下载处理入站图片;通过 `sendPhoto` 发送图片。
- **贴纸**:已记录但未完全处理(无智能体响应)。
- **不支持的类型**:已记录(例如来自受保护用户的消息)。
@@ -140,30 +140,30 @@ Zalo 是一款专注于越南市场的即时通讯应用;其 Bot API 让 Gatew
| 群组 | ❌ 即将推出(根据 Zalo 文档) |
| 媒体(图片) | ✅ 支持 |
| 表情回应 | ❌ 不支持 |
| 题 | ❌ 不支持 |
| 题 | ❌ 不支持 |
| 投票 | ❌ 不支持 |
| 原生命令 | ❌ 不支持 |
| 流式传输 | ⚠️ 已阻止2000 字符限制) |
| 流式传输 | ⚠️ 已禁用2000 字符限制) |
## 投递目标CLI/cron
## 投递目标CLI/定时任务
- 使用聊天 id 作为目标。
- 使用聊天 ID 作为目标。
- 示例:`openclaw message send --channel zalo --target 123456789 --message "hi"`
## 故障排除
**Bot 不响应:**
**机器人无响应:**
- 检查 token 是否有效:`openclaw channels status --probe`
- 验证发送者已批准(配对或 allowFrom
- 检查 Gateway 网关日志:`openclaw logs --follow`
- 检查令牌是否有效:`openclaw channels status --probe`
- 验证发送者是否已批准(配对或 allowFrom
- 检查 Gateway网关日志`openclaw logs --follow`
**Webhook 未收到事件:**
- 确保 webhook URL 使用 HTTPS
- 验证 secret token 为 8-256 个字符
- 确认 Gateway 网关 HTTP 端点在配置的路径上可访问
- 检查 getUpdates 轮询未在运行(它们是互斥
- 验证密钥令牌为 8-256 个字符
- 确认 Gateway网关 HTTP 端点在配置的路径上可
- 检查 getUpdates 轮询是否未在运行(两者互斥)
## 配置参考Zalo
@@ -172,25 +172,25 @@ Zalo 是一款专注于越南市场的即时通讯应用;其 Bot API 让 Gatew
提供商选项:
- `channels.zalo.enabled`:启用/禁用渠道启动。
- `channels.zalo.botToken`:来自 Zalo Bot 平台的 bot token
- `channels.zalo.tokenFile`:从文件路径读取 token
- `channels.zalo.botToken`:来自 Zalo Bot Platform 的机器人令牌
- `channels.zalo.tokenFile`:从文件路径读取令牌
- `channels.zalo.dmPolicy``pairing | allowlist | open | disabled`默认pairing
- `channels.zalo.allowFrom`:私信允许列表(用户 ID`open` 需要 `"*"`。向导会询问数字 ID。
- `channels.zalo.mediaMaxMb`:入站/出站媒体上限MB默认 5
- `channels.zalo.allowFrom`:私信允许列表(用户 ID`open` 需要 `"*"`。向导会要求输入数字 ID。
- `channels.zalo.mediaMaxMb`:入站/出站媒体大小上限MB默认 5
- `channels.zalo.webhookUrl`:启用 webhook 模式(需要 HTTPS
- `channels.zalo.webhookSecret`webhook secret8-256 字符)。
- `channels.zalo.webhookPath`Gateway 网关 HTTP 服务器上的 webhook 路径。
- `channels.zalo.webhookSecret`webhook 密钥8-256 字符)。
- `channels.zalo.webhookPath`Gateway网关 HTTP 服务器上的 webhook 路径。
- `channels.zalo.proxy`API 请求的代理 URL。
多账户选项:
- `channels.zalo.accounts.<id>.botToken`:每账户 token
- `channels.zalo.accounts.<id>.tokenFile`:每账户 token 文件。
- `channels.zalo.accounts.<id>.botToken`:每账户的令牌
- `channels.zalo.accounts.<id>.tokenFile`:每账户的令牌文件。
- `channels.zalo.accounts.<id>.name`:显示名称。
- `channels.zalo.accounts.<id>.enabled`:启用/禁用账户。
- `channels.zalo.accounts.<id>.dmPolicy`:每账户私信策略。
- `channels.zalo.accounts.<id>.allowFrom`:每账户允许列表。
- `channels.zalo.accounts.<id>.webhookUrl`:每账户 webhook URL。
- `channels.zalo.accounts.<id>.webhookSecret`:每账户 webhook secret
- `channels.zalo.accounts.<id>.webhookPath`:每账户 webhook 路径。
- `channels.zalo.accounts.<id>.proxy`:每账户代理 URL。
- `channels.zalo.accounts.<id>.dmPolicy`:每账户私信策略。
- `channels.zalo.accounts.<id>.allowFrom`:每账户允许列表。
- `channels.zalo.accounts.<id>.webhookUrl`:每账户 webhook URL。
- `channels.zalo.accounts.<id>.webhookSecret`:每账户 webhook 密钥
- `channels.zalo.accounts.<id>.webhookPath`:每账户 webhook 路径。
- `channels.zalo.accounts.<id>.proxy`:每账户代理 URL。

View File

@@ -1,27 +1,27 @@
---
read_when:
- 为 OpenClaw 设置 Zalo Personal
- 调试 Zalo Personal 登录或消息流
summary: 通过 zca-cliQR 登录)支持 Zalo 个人账户、功能配置
- 调试 Zalo Personal 登录或消息流
summary: 通过 zca-cli二维码登录)支持 Zalo 个人账号,功能配置说明
title: Zalo Personal
x-i18n:
generated_at: "2026-02-03T07:44:34Z"
generated_at: "2026-02-01T19:58:27Z"
model: claude-opus-4-5
provider: pi
source_hash: 2a249728d556e5cc52274627bdaf390fa10e815afa04f4497feb57a2a0cb9261
source_path: channels/zalouser.md
workflow: 15
workflow: 14
---
# Zalo Personal非官方
状态:实验性。此集成通过 `zca-cli` 自动化**个人 Zalo 账**。
状态:实验性。此集成通过 `zca-cli` 自动化操作一个**个人 Zalo 账**。
> **警告:**这是一个非官方集成,可能导致账被暂停/封禁。使用风险自负。
> **警告:** 这是一个非官方集成,可能导致账被暂停封禁。使用风险自负。
## 需要插件
## 需要安装插件
Zalo Personal 作为插件提供,不包含在核心安装中。
Zalo Personal 以插件形式提供,不包含在核心安装中。
- 通过 CLI 安装:`openclaw plugins install @openclaw/zalouser`
- 或从源码检出安装:`openclaw plugins install ./extensions/zalouser`
@@ -29,17 +29,17 @@ Zalo Personal 作为插件提供,不包含在核心安装中。
## 前置条件zca-cli
Gateway 网关机器必须在 `PATH`有可用的 `zca` 二进制文件。
Gateway网关所在机器必须在 `PATH`包含 `zca` 可执行文件。
- 验证:`zca --version`
- 如果缺失,请安装 zca-cli参见 `extensions/zalouser/README.md` 或上游 zca-cli 文档)。
## 快速设置(新手
## 快速设置(入门
1. 安装插件(见上文)。
2. 登录(QR,在 Gateway 网关机器上):
2. 登录(二维码方式,在 Gateway网关机器上操作
- `openclaw channels login --channel zalouser`
- 用 Zalo 手机应用扫描终端中的二维码。
- 使用 Zalo 手机应用扫描终端中的二维码。
3. 启用渠道:
```json5
@@ -53,22 +53,22 @@ Gateway 网关机器必须在 `PATH` 中有可用的 `zca` 二进制文件。
}
```
4. 重启 Gateway 网关(或完成新手引导)。
5. 私信访问默认为配对模式;首次联系时批准配对码。
4. 重启 Gateway网关或完成新手引导
5. 私信访问默认为配对模式;首次联系时批准配对码。
## 这是什么
## 功能说明
- 使用 `zca listen` 接收入站消息。
- 使用 `zca msg ...` 发送回复(文本/媒体/链接)。
- 专为"个人账户"使用场景设计,适用于 Zalo Bot API 不可用的情况
- 专为 Zalo Bot API 不可用时的"个人账号"使用场景设计
## 命名
## 命名说明
渠道 ID 为 `zalouser`,以明确表示这是自动化**个人 Zalo 用户账**(非官方)。我们保留 `zalo` 用于未来可能的官方 Zalo API 集成。
渠道 ID 为 `zalouser`,以明确表示这是**个人 Zalo 用户账**的自动化操作(非官方)。我们 `zalo` 保留给未来可能的官方 Zalo API 集成。
## 查找 ID录)
## 查找 ID通讯录)
使用录 CLI 发现联系人/群组及其 ID
使用通讯录 CLI 发现联系人/群组及其 ID
```bash
openclaw directory self --channel zalouser
@@ -78,13 +78,13 @@ openclaw directory groups list --channel zalouser --query "work"
## 限制
- 出站文本分块为约 2000 字符Zalo 客户端限制)。
- 默认阻止流式传输。
- 出站文本约 2000 字符分块Zalo 客户端限制)。
- 流式传输默认被禁用
## 访问控制(私信)
`channels.zalouser.dmPolicy` 支持:`pairing | allowlist | open | disabled`(默认:`pairing`)。
`channels.zalouser.allowFrom` 接受用户 ID 或名称。向导在可用时通过 `zca friend find` 将名称解析为 ID。
`channels.zalouser.allowFrom` 接受用户 ID 或名称。向导在可用时通过 `zca friend find` 将名称解析为 ID。
通过以下方式批准:
@@ -93,13 +93,13 @@ openclaw directory groups list --channel zalouser --query "work"
## 群组访问(可选)
- 默认:`channels.zalouser.groupPolicy = "open"`(允许群组)。使用 `channels.defaults.groupPolicy` 在未设置时覆盖默认值。
- 通过以下方式限制为允许列表:
- 默认:`channels.zalouser.groupPolicy = "open"`(允许群组)。未设置时使用 `channels.defaults.groupPolicy` 覆盖默认值。
- 通过允许列表进行限制
- `channels.zalouser.groupPolicy = "allowlist"`
- `channels.zalouser.groups`(键为群组 ID 或名称)
- 止所有群组:`channels.zalouser.groupPolicy = "disabled"`
- 配置向导可以提示输入群组允许列表。
- 启动时OpenClaw 将允许列表中的群组/用户名称解析为 ID 并记录映射;未解析的条目保持原样。
- 止所有群组:`channels.zalouser.groupPolicy = "disabled"`
- 配置向导可以提示设置群组允许列表。
- 启动时OpenClaw 将允许列表中的群组/用户名称解析为 ID 并记录映射关系;未解析的条目保持原样。
示例:
@@ -117,9 +117,9 @@ openclaw directory groups list --channel zalouser --query "work"
}
```
## 多账
## 多账
映射到 zca 配置文件。示例:
映射到 zca 配置文件。示例:
```json5
{
@@ -139,9 +139,9 @@ openclaw directory groups list --channel zalouser --query "work"
**找不到 `zca`**
- 安装 zca-cli 并确保它在 Gateway 网关进程的 `PATH` 中。
- 安装 zca-cli 并确保 Gateway网关进程的 `PATH`包含该命令
**登录保持:**
**登录状态无法保持:**
- `openclaw channels status --probe`
- 重新登录:`openclaw channels logout --channel zalouser && openclaw channels login --channel zalouser`

View File

@@ -1,63 +1,63 @@
---
read_when:
- 设置基于 ACP 的 IDE 集成
- 调试到 Gateway 网关的 ACP 会话路由
summary: 运行用于 IDE 集成的 ACP 桥接
- 调试 ACP 会话到 Gateway网关的路由
summary: 运行用于 IDE 集成的 ACP 桥接
title: acp
x-i18n:
generated_at: "2026-02-03T07:44:38Z"
generated_at: "2026-02-01T19:58:33Z"
model: claude-opus-4-5
provider: pi
source_hash: 0c09844297da250bc1a558423e7e534d6b6be9045de12d797c07ecd64a0c63ed
source_path: cli/acp.md
workflow: 15
workflow: 14
---
# acp
运行与 OpenClaw Gateway 网关通信的 ACPAgent Client Protocol桥接
运行与 OpenClaw Gateway网关通信的 ACPAgent Client Protocol桥接。
此命令通过 stdio 使用 ACP 协议与 IDE 通信,并通过 WebSocket 将提示转发到 Gateway 网关。它将 ACP 会话映射到 Gateway 网关会话
此命令通过 stdio 使用 ACP 协议与 IDE 通信,并通过 WebSocket 将提示转发到 Gateway网关。它将 ACP 会话映射到 Gateway网关会话密钥
## 用法
```bash
openclaw acp
# Remote Gateway
# 远程 Gateway网关
openclaw acp --url wss://gateway-host:18789 --token <token>
# Attach to an existing session key
# 附加到现有会话密钥
openclaw acp --session agent:main:main
# Attach by label (must already exist)
# 通过标签附加(必须已存在)
openclaw acp --session-label "support inbox"
# Reset the session key before the first prompt
# 在第一个提示之前重置会话密钥
openclaw acp --session agent:main:main --reset-session
```
## ACP 客户端(调试)
使用内置 ACP 客户端在没有 IDE 的情况下检查桥接器的安装完整性。
它会启动 ACP 桥接器并让你交互式输入提示。
使用内置 ACP 客户端在无需 IDE 的情况下对桥接进行安装完整性检查
它会启动 ACP 桥接并允许你交互式输入提示。
```bash
openclaw acp client
# Point the spawned bridge at a remote Gateway
# 将启动的桥接指向远程 Gateway网关
openclaw acp client --server-args --url wss://gateway-host:18789 --token <token>
# Override the server command (default: openclaw)
# 覆盖服务器命令(默认:openclaw
openclaw acp client --server "node" --server-args openclaw.mjs acp --url ws://127.0.0.1:19001
```
## 如何使用
当 IDE或其他客户端使用 Agent Client Protocol 并且你希望它驱动 OpenClaw Gateway 网关会话时,请使用 ACP。
当 IDE或其他客户端使用 Agent Client Protocol 并且你希望它驱动 OpenClaw Gateway网关会话时请使用 ACP。
1. 确保 Gateway 网关正在运行(本地或远程)。
2. 配置 Gateway 网关目标(配置或标志)。
1. 确保 Gateway网关正在运行本地或远程
2. 配置 Gateway网关目标通过配置文件或标志)。
3. 将你的 IDE 配置为通过 stdio 运行 `openclaw acp`
示例配置(持久化):
@@ -75,9 +75,9 @@ openclaw acp --url wss://gateway-host:18789 --token <token>
## 选择智能体
ACP 不直接选择智能体。它通过 Gateway 网关会话进行路由。
ACP 不直接选择智能体。它通过 Gateway网关会话密钥进行路由。
使用智能体作用域的会话键来定位特定智能体:
使用智能体作用域的会话密钥来指定特定智能体:
```bash
openclaw acp --session agent:main:main
@@ -85,7 +85,7 @@ openclaw acp --session agent:design:main
openclaw acp --session agent:qa:bug-123
```
每个 ACP 会话映射到单个 Gateway 网关会话。一个智能体可以有多个会话;除非你覆盖或标签,否则 ACP 默认使用隔离的 `acp:<uuid>` 会话。
每个 ACP 会话映射到单个 Gateway网关会话密钥。一个智能体可以有多个会话;除非你覆盖密钥或标签,否则 ACP 默认使用隔离的 `acp:<uuid>` 会话。
## Zed 编辑器设置
@@ -104,7 +104,7 @@ openclaw acp --session agent:qa:bug-123
}
```
要定特定的 Gateway 网关或智能体:
定特定的 Gateway网关或智能体
```json
{
@@ -127,18 +127,18 @@ openclaw acp --session agent:qa:bug-123
}
```
在 Zed 中,打开 Agent 面板并选择"OpenClaw ACP"来开始一个会话
在 Zed 中,打开 Agent 面板并选择 "OpenClaw ACP" 来开始一个对话线程
## 会话映射
默认情况下ACP 会话获得一个带有 `acp:` 前缀的隔离 Gateway 网关会话
用已知会话,请传递会话或标签:
默认情况下ACP 会话获得一个带有 `acp:` 前缀的隔离 Gateway网关会话密钥
用已知会话,请传递会话密钥或标签:
- `--session <key>`:使用特定的 Gateway 网关会话
- `--session <key>`:使用特定的 Gateway网关会话密钥
- `--session-label <label>`:通过标签解析现有会话。
- `--reset-session`:为该生成新的会话 ID相同,新对话记录)。
- `--reset-session`:为该密钥生成新的会话 ID相同密钥,新对话记录)。
如果你的 ACP 客户端支持元数据,你可以按会话覆盖:
如果你的 ACP 客户端支持元数据,你可以按会话进行覆盖:
```json
{
@@ -150,19 +150,19 @@ openclaw acp --session agent:qa:bug-123
}
```
[/concepts/session](/concepts/session) 了解更多关于会话键的信息
了解更多关于会话密钥的信息,请参阅 [/concepts/session](/concepts/session)。
## 选项
- `--url <url>`Gateway 网关 WebSocket URL配置后默认 gateway.remote.url
- `--token <token>`Gateway 网关认证令牌。
- `--password <password>`Gateway 网关认证密码。
- `--session <key>`:默认会话
- `--url <url>`Gateway网关 WebSocket URL配置后默认使用 gateway.remote.url
- `--token <token>`Gateway网关认证令牌。
- `--password <password>`Gateway网关认证密码。
- `--session <key>`:默认会话密钥
- `--session-label <label>`:要解析的默认会话标签。
- `--require-existing`:如果会话/标签不存在则失败。
- `--reset-session`:在首次使用前重置会话
- `--require-existing`:如果会话密钥/标签不存在则失败。
- `--reset-session`:在首次使用前重置会话密钥
- `--no-prefix-cwd`:不在提示前添加工作目录前缀。
- `--verbose, -v`向 stderr 输出详细日志
- `--verbose, -v`将详细日志输出到 stderr
### `acp client` 选项

View File

@@ -1,24 +1,25 @@
---
read_when:
- 你想从脚本运行一智能体回合(可选发送回复)
summary: "`openclaw agent` 的 CLI 参考(通过 Gateway 网关发送一智能体回合"
- 你想从脚本运行一智能体轮次(可选择投递回复)
summary: "`openclaw agent` 的 CLI 参考(通过 Gateway网关发送一智能体轮次"
title: agent
x-i18n:
generated_at: "2026-02-03T07:44:38Z"
generated_at: "2026-02-01T19:58:31Z"
model: claude-opus-4-5
provider: pi
source_hash: dcf12fb94e207c68645f58235792596d65afecf8216b8f9ab3acb01e03b50a33
source_path: cli/agent.md
workflow: 15
workflow: 14
---
# `openclaw agent`
通过 Gateway 网关运行智能体回合(使用 `--local` 进行嵌入式运行)。使用 `--agent <id>` 直接指定已配置的智能体。
通过 Gateway网关运行一次智能体轮次(使用 `--local` 进行嵌入式运行)。
使用 `--agent <id>` 直接指定一个已配置的智能体。
相关内容:
- 智能体发送工具:[Agent send](/tools/agent-send)
- 智能体发送工具:[智能体发送](/tools/agent-send)
## 示例

View File

@@ -1,22 +1,22 @@
---
read_when:
- 你想通过 CLI 编辑执行审批
- 你需要管理 Gateway 网关或节点主机上的允许列表
summary: CLI 参考:`openclaw approvals`Gateway 网关或节点主机的执行审批)
- 你需要管理 Gateway网关或节点主机上的允许列表
summary: "`openclaw approvals` 的 CLI 参考(用于 Gateway网关或节点主机的执行审批"
title: approvals
x-i18n:
generated_at: "2026-02-03T10:04:09Z"
generated_at: "2026-02-01T19:58:39Z"
model: claude-opus-4-5
provider: pi
source_hash: 4329cdaaec2c5f5d619415b6431196512d4834dc1ccd7363576f03dd9b845130
source_path: cli/approvals.md
workflow: 15
workflow: 14
---
# `openclaw approvals`
管理**本地主机**、**Gateway 网关主机**或**节点主机**的执行审批。
默认情况下,命令针对磁盘上的本地审批文件。使用 `--gateway` 针对 Gateway 网关,使用 `--node` 针对特定节点。
管理**本地主机**、**Gateway网关主机**或**节点主机**的执行审批。
默认情况下,命令针对磁盘上的本地审批文件。使用 `--gateway` 针对 Gateway网关使用 `--node` 针对特定节点。
相关内容:
@@ -51,7 +51,7 @@ openclaw approvals allowlist remove "~/Projects/**/bin/rg"
## 注意事项
- `--node` 使用与 `openclaw nodes` 相同的解析器id、name、ip 或 id 前缀)。
- `--agent` 默认为 `"*"`表示适用于所有智能体。
- 节点主机必须公 `system.execApprovals.get/set`macOS 应用或无头节点主机)。
- `--node` 使用与 `openclaw nodes` 相同的解析器id、名称、ip 或 id 前缀)。
- `--agent` 默认为 `"*"`适用于所有智能体。
- 节点主机必须公 `system.execApprovals.get/set`macOS 应用或无头节点主机)。
- 审批文件按主机存储在 `~/.openclaw/exec-approvals.json`

View File

@@ -1,35 +1,35 @@
---
read_when:
- 使用 `openclaw browser`要常见任务的示例
- 你想通过 node host 控制在另一台机器上运行的浏览器
- 想使用 Chrome 扩展中继(通过工具栏按钮附加/分离)
- 使用 `openclaw browser`要常见任务的示例
- 想要通过节点主机控制运行在另一台机器上的浏览器
-使用 Chrome 扩展中继(通过工具栏按钮附加/分离)
summary: "`openclaw browser` 的 CLI 参考(配置文件、标签页、操作、扩展中继)"
title: browser
x-i18n:
generated_at: "2026-02-03T07:44:49Z"
generated_at: "2026-02-01T19:58:45Z"
model: claude-opus-4-5
provider: pi
source_hash: af35adfd68726fd519c704d046451effd330458c2b8305e713137fb07b2571fd
source_path: cli/browser.md
workflow: 15
workflow: 14
---
# `openclaw browser`
管理 OpenClaw 的浏览器控制服务器并行浏览器操作(标签页、快照、截图、导航、点击、输入)。
管理 OpenClaw 的浏览器控制服务器并行浏览器操作(标签页、快照、截图、导航、点击、输入)。
相关:
相关内容
- 浏览器工具 + API[浏览器工具](/tools/browser)
- Chrome 扩展中继:[Chrome 扩展](/tools/chrome-extension)
## 用标志
## 用标志
- `--url <gatewayWsUrl>`Gateway 网关 WebSocket URL默认从配置获取)。
- `--token <token>`Gateway 网关令牌(如需要)。
- `--timeout <ms>`:请求超时(毫秒)。
- `--browser-profile <name>`:选择浏览器配置文件(默认从配置获取)。
- `--json`:机器可读输出(在支持的地方)。
- `--url <gatewayWsUrl>`Gateway网关 WebSocket URL默认使用配置值)。
- `--token <token>`Gateway网关令牌如需要
- `--timeout <ms>`:请求超时时间(毫秒)。
- `--browser-profile <name>`:选择浏览器配置文件(默认使用配置值)。
- `--json`:机器可读输出(在支持的情况下)。
## 快速开始(本地)
@@ -42,9 +42,9 @@ openclaw browser --browser-profile openclaw snapshot
## 配置文件
配置文件是命名的浏览器路由配置。实际
配置文件是命名的浏览器路由配置。实际使用中
- `openclaw`:启动/附加到专用的 OpenClaw 管理的 Chrome 实例(隔离的用户数据目录)。
- `openclaw`:启动/附加到一个专用的 OpenClaw 管理的 Chrome 实例(隔离的用户数据目录)。
- `chrome`:通过 Chrome 扩展中继控制你现有的 Chrome 标签页。
```bash
@@ -82,7 +82,7 @@ openclaw browser snapshot
openclaw browser screenshot
```
导航/点击/输入(基于 ref 的 UI 自动化):
导航/点击/输入(基于引用的 UI 自动化):
```bash
openclaw browser navigate https://example.com
@@ -92,7 +92,7 @@ openclaw browser type <ref> "hello"
## Chrome 扩展中继(通过工具栏按钮附加)
此模式智能体控制你手动附加的现有 Chrome 标签页(不会自动附加)。
此模式允许智能体控制你手动附加的现有 Chrome 标签页(不会自动附加)。
将未打包的扩展安装到稳定路径:
@@ -101,14 +101,14 @@ openclaw browser extension install
openclaw browser extension path
```
然后 Chrome → `chrome://extensions` → 启用"开发者模式" → "加载已解压的扩展程序" → 选择打印的文件夹。
然后 Chrome`chrome://extensions` → 启用"开发者模式" → "加载已解压的扩展程序" → 选择打印的文件夹。
完整指南:[Chrome 扩展](/tools/chrome-extension)
## 远程浏览器控制(node host 代理)
## 远程浏览器控制(节点主机代理)
如果 Gateway 网关与浏览器运行在不同的机器上,在有 Chrome/Brave/Edge/Chromium 的机器上运行 **node host**。Gateway 网关会将浏览器操作代理到该节点(无需单独的浏览器控制服务器)。
如果 Gateway网关与浏览器运行在不同的机器上请在安装了 Chrome/Brave/Edge/Chromium 的机器上运行**节点主机**。Gateway网关会将浏览器操作代理到该节点无需单独的浏览器控制服务器
使用 `gateway.nodes.browser.mode` 控制自动路由,使用 `gateway.nodes.browser.node`连接多个节点时固定特定节点。
使用 `gateway.nodes.browser.mode` 控制自动路由,使用 `gateway.nodes.browser.node` 在多个节点连接时固定特定节点。
安全 + 远程设置:[浏览器工具](/tools/browser)、[远程访问](/gateway/remote)、[Tailscale](/gateway/tailscale)、[安全](/gateway/security)
安全 + 远程设置:[浏览器工具](/tools/browser)、[远程访问](/gateway/remote)、[Tailscale](/gateway/tailscale)、[安全](/gateway/security)

Some files were not shown because too many files have changed in this diff Show More