From 149dc7c4e76f2b264cd714c95b3e5ee399db3092 Mon Sep 17 00:00:00 2001 From: Josh Palmer Date: Sun, 1 Feb 2026 22:47:44 +0100 Subject: [PATCH] Docs: add zh-CN translations --- docs/zh-CN/automation/auth-monitoring.md | 47 + docs/zh-CN/automation/cron-jobs.md | 434 +++ docs/zh-CN/automation/cron-vs-heartbeat.md | 286 ++ docs/zh-CN/automation/gmail-pubsub.md | 249 ++ docs/zh-CN/automation/poll.md | 75 + docs/zh-CN/automation/webhook.md | 163 + docs/zh-CN/bedrock.md | 170 + docs/zh-CN/brave-search.md | 48 + docs/zh-CN/broadcast-groups.md | 449 +++ docs/zh-CN/channels/bluebubbles.md | 271 ++ docs/zh-CN/channels/discord.md | 463 +++ docs/zh-CN/channels/googlechat.md | 257 ++ docs/zh-CN/channels/grammy.md | 38 + docs/zh-CN/channels/imessage.md | 302 ++ docs/zh-CN/channels/index.md | 50 + docs/zh-CN/channels/line.md | 180 + docs/zh-CN/channels/location.md | 63 + docs/zh-CN/channels/matrix.md | 221 ++ docs/zh-CN/channels/mattermost.md | 142 + docs/zh-CN/channels/msteams.md | 770 ++++ docs/zh-CN/channels/nextcloud-talk.md | 141 + docs/zh-CN/channels/nostr.md | 240 ++ docs/zh-CN/channels/signal.md | 209 ++ docs/zh-CN/channels/slack.md | 530 +++ docs/zh-CN/channels/telegram.md | 755 ++++ docs/zh-CN/channels/tlon.md | 138 + docs/zh-CN/channels/troubleshooting.md | 36 + docs/zh-CN/channels/twitch.md | 384 ++ docs/zh-CN/channels/whatsapp.md | 410 ++ docs/zh-CN/channels/zalo.md | 196 + docs/zh-CN/channels/zalouser.md | 147 + docs/zh-CN/cli/acp.md | 173 + docs/zh-CN/cli/agent.md | 31 + docs/zh-CN/cli/agents.md | 82 + docs/zh-CN/cli/approvals.md | 57 + docs/zh-CN/cli/browser.md | 114 + docs/zh-CN/cli/channels.md | 86 + docs/zh-CN/cli/config.md | 56 + docs/zh-CN/cli/configure.md | 40 + docs/zh-CN/cli/cron.md | 38 + docs/zh-CN/cli/dashboard.md | 23 + docs/zh-CN/cli/devices.md | 74 + docs/zh-CN/cli/directory.md | 70 + docs/zh-CN/cli/dns.md | 30 + docs/zh-CN/cli/docs.md | 22 + docs/zh-CN/cli/doctor.md | 48 + docs/zh-CN/cli/gateway.md | 206 + docs/zh-CN/cli/health.md | 28 + docs/zh-CN/cli/hooks.md | 310 ++ docs/zh-CN/cli/index.md | 1033 +++++ docs/zh-CN/cli/logs.md | 31 + docs/zh-CN/cli/memory.md | 52 + docs/zh-CN/cli/message.md | 246 ++ docs/zh-CN/cli/models.md | 85 + docs/zh-CN/cli/node.md | 115 + docs/zh-CN/cli/nodes.md | 79 + docs/zh-CN/cli/onboard.md | 36 + docs/zh-CN/cli/pairing.md | 28 + docs/zh-CN/cli/plugins.md | 66 + docs/zh-CN/cli/reset.md | 24 + docs/zh-CN/cli/sandbox.md | 158 + docs/zh-CN/cli/security.md | 33 + docs/zh-CN/cli/sessions.md | 23 + docs/zh-CN/cli/setup.md | 36 + docs/zh-CN/cli/skills.md | 33 + docs/zh-CN/cli/status.md | 33 + docs/zh-CN/cli/system.md | 63 + docs/zh-CN/cli/tui.md | 30 + docs/zh-CN/cli/uninstall.md | 24 + docs/zh-CN/cli/update.md | 101 + docs/zh-CN/cli/voicecall.md | 41 + docs/zh-CN/cli/webhooks.md | 32 + docs/zh-CN/concepts/agent-loop.md | 150 + docs/zh-CN/concepts/agent-workspace.md | 214 ++ docs/zh-CN/concepts/agent.md | 114 + docs/zh-CN/concepts/architecture.md | 123 + docs/zh-CN/concepts/channel-routing.md | 117 + docs/zh-CN/concepts/compaction.md | 67 + docs/zh-CN/concepts/context.md | 168 + docs/zh-CN/concepts/group-messages.md | 91 + docs/zh-CN/concepts/groups.md | 380 ++ docs/zh-CN/concepts/markdown-formatting.md | 117 + docs/zh-CN/concepts/memory.md | 409 ++ docs/zh-CN/concepts/messages.md | 141 + docs/zh-CN/concepts/model-failover.md | 156 + docs/zh-CN/concepts/model-providers.md | 317 ++ docs/zh-CN/concepts/models.md | 196 + docs/zh-CN/concepts/multi-agent.md | 369 ++ docs/zh-CN/concepts/oauth.md | 151 + docs/zh-CN/concepts/presence.md | 99 + docs/zh-CN/concepts/queue.md | 94 + docs/zh-CN/concepts/retry.md | 76 + docs/zh-CN/concepts/session-pruning.md | 129 + docs/zh-CN/concepts/session-tool.md | 200 + docs/zh-CN/concepts/session.md | 166 + docs/zh-CN/concepts/sessions.md | 17 + docs/zh-CN/concepts/streaming.md | 133 + docs/zh-CN/concepts/system-prompt.md | 101 + docs/zh-CN/concepts/timezone.md | 96 + docs/zh-CN/concepts/typebox.md | 284 ++ docs/zh-CN/concepts/typing-indicators.md | 74 + docs/zh-CN/concepts/usage-tracking.md | 42 + docs/zh-CN/date-time.md | 129 + docs/zh-CN/debug/node-issue.md | 90 + docs/zh-CN/debugging.md | 160 + docs/zh-CN/diagnostics/flags.md | 98 + docs/zh-CN/environment.md | 88 + .../experiments/onboarding-config-protocol.md | 47 + .../experiments/plans/cron-add-hardening.md | 70 + .../plans/group-policy-hardening.md | 45 + .../plans/openresponses-gateway.md | 121 + .../experiments/proposals/model-config.md | 42 + docs/zh-CN/experiments/research/memory.md | 235 ++ docs/zh-CN/gateway/authentication.md | 142 + docs/zh-CN/gateway/background-process.md | 100 + docs/zh-CN/gateway/bonjour.md | 160 + docs/zh-CN/gateway/bridge-protocol.md | 84 + docs/zh-CN/gateway/cli-backends.md | 214 ++ docs/zh-CN/gateway/configuration-examples.md | 587 +++ docs/zh-CN/gateway/configuration.md | 3331 +++++++++++++++++ docs/zh-CN/gateway/discovery.md | 123 + docs/zh-CN/gateway/doctor.md | 236 ++ docs/zh-CN/gateway/gateway-lock.md | 41 + docs/zh-CN/gateway/health.md | 42 + docs/zh-CN/gateway/heartbeat.md | 274 ++ docs/zh-CN/gateway/index.md | 328 ++ docs/zh-CN/gateway/local-models.md | 157 + docs/zh-CN/gateway/logging.md | 116 + docs/zh-CN/gateway/multiple-gateways.md | 119 + docs/zh-CN/gateway/openai-http-api.md | 125 + docs/zh-CN/gateway/openresponses-http-api.md | 319 ++ docs/zh-CN/gateway/pairing.md | 99 + docs/zh-CN/gateway/protocol.md | 211 ++ docs/zh-CN/gateway/remote-gateway-readme.md | 164 + docs/zh-CN/gateway/remote.md | 133 + .../sandbox-vs-tool-policy-vs-elevated.md | 135 + docs/zh-CN/gateway/sandboxing.md | 196 + .../gateway/security/formal-verification.md | 169 + docs/zh-CN/gateway/security/index.md | 777 ++++ docs/zh-CN/gateway/tailscale.md | 120 + docs/zh-CN/gateway/tools-invoke-http-api.md | 92 + docs/zh-CN/gateway/troubleshooting.md | 773 ++++ docs/zh-CN/help/faq.md | 2632 +++++++++++++ docs/zh-CN/help/index.md | 28 + docs/zh-CN/help/troubleshooting.md | 104 + docs/zh-CN/hooks.md | 919 +++++ docs/zh-CN/hooks/soul-evil.md | 72 + docs/zh-CN/install/ansible.md | 215 ++ docs/zh-CN/install/bun.md | 65 + docs/zh-CN/install/development-channels.md | 79 + docs/zh-CN/install/docker.md | 461 +++ docs/zh-CN/install/index.md | 193 + docs/zh-CN/install/installer.md | 128 + docs/zh-CN/install/migrating.md | 199 + docs/zh-CN/install/nix.md | 103 + docs/zh-CN/install/node.md | 85 + docs/zh-CN/install/uninstall.md | 135 + docs/zh-CN/install/updating.md | 233 ++ docs/zh-CN/logging.md | 328 ++ docs/zh-CN/multi-agent-sandbox-tools.md | 399 ++ docs/zh-CN/network.md | 59 + docs/zh-CN/nodes/audio.md | 120 + docs/zh-CN/nodes/camera.md | 162 + docs/zh-CN/nodes/images.md | 79 + docs/zh-CN/nodes/index.md | 316 ++ docs/zh-CN/nodes/location-command.md | 120 + docs/zh-CN/nodes/media-understanding.md | 381 ++ docs/zh-CN/nodes/talk.md | 97 + docs/zh-CN/nodes/voicewake.md | 72 + docs/zh-CN/northflank.mdx | 60 + docs/zh-CN/perplexity.md | 84 + docs/zh-CN/pi-dev.md | 77 + docs/zh-CN/pi.md | 607 +++ docs/zh-CN/platforms/android.md | 155 + docs/zh-CN/platforms/digitalocean.md | 269 ++ docs/zh-CN/platforms/exe-dev.md | 127 + docs/zh-CN/platforms/fly.md | 490 +++ docs/zh-CN/platforms/gcp.md | 510 +++ docs/zh-CN/platforms/hetzner.md | 337 ++ docs/zh-CN/platforms/index.md | 60 + docs/zh-CN/platforms/ios.md | 114 + docs/zh-CN/platforms/linux.md | 99 + docs/zh-CN/platforms/mac/bundled-gateway.md | 77 + docs/zh-CN/platforms/mac/canvas.md | 127 + docs/zh-CN/platforms/mac/child-process.md | 62 + docs/zh-CN/platforms/mac/dev-setup.md | 109 + docs/zh-CN/platforms/mac/health.md | 41 + docs/zh-CN/platforms/mac/icon.md | 38 + docs/zh-CN/platforms/mac/logging.md | 64 + docs/zh-CN/platforms/mac/menu-bar.md | 88 + docs/zh-CN/platforms/mac/peekaboo.md | 62 + docs/zh-CN/platforms/mac/permissions.md | 46 + docs/zh-CN/platforms/mac/release.md | 92 + docs/zh-CN/platforms/mac/remote.md | 90 + docs/zh-CN/platforms/mac/signing.md | 54 + docs/zh-CN/platforms/mac/skills.md | 40 + docs/zh-CN/platforms/mac/voice-overlay.md | 67 + docs/zh-CN/platforms/mac/voicewake.md | 74 + docs/zh-CN/platforms/mac/webchat.md | 43 + docs/zh-CN/platforms/mac/xpc.md | 68 + docs/zh-CN/platforms/macos-vm.md | 288 ++ docs/zh-CN/platforms/macos.md | 194 + docs/zh-CN/platforms/oracle.md | 310 ++ docs/zh-CN/platforms/raspberry-pi.md | 365 ++ docs/zh-CN/platforms/windows.md | 156 + docs/zh-CN/plugin.md | 639 ++++ docs/zh-CN/plugins/agent-tools.md | 99 + docs/zh-CN/plugins/manifest.md | 68 + docs/zh-CN/plugins/voice-call.md | 250 ++ docs/zh-CN/plugins/zalouser.md | 88 + docs/zh-CN/prose.md | 141 + docs/zh-CN/providers/anthropic.md | 158 + docs/zh-CN/providers/claude-max-api-proxy.md | 155 + docs/zh-CN/providers/deepgram.md | 97 + docs/zh-CN/providers/github-copilot.md | 67 + docs/zh-CN/providers/glm.md | 39 + docs/zh-CN/providers/index.md | 67 + docs/zh-CN/providers/minimax.md | 206 + docs/zh-CN/providers/models.md | 55 + docs/zh-CN/providers/moonshot.md | 145 + docs/zh-CN/providers/ollama.md | 230 ++ docs/zh-CN/providers/openai.md | 68 + docs/zh-CN/providers/opencode.md | 41 + docs/zh-CN/providers/openrouter.md | 43 + docs/zh-CN/providers/qwen.md | 55 + docs/zh-CN/providers/synthetic.md | 102 + docs/zh-CN/providers/venice.md | 274 ++ docs/zh-CN/providers/vercel-ai-gateway.md | 57 + docs/zh-CN/providers/xiaomi.md | 68 + docs/zh-CN/providers/zai.md | 41 + docs/zh-CN/railway.mdx | 106 + docs/zh-CN/refactor/clawnet.md | 424 +++ docs/zh-CN/refactor/exec-host.md | 323 ++ .../refactor/outbound-session-mirroring.md | 92 + docs/zh-CN/refactor/plugin-sdk.md | 221 ++ docs/zh-CN/refactor/strict-config.md | 100 + docs/zh-CN/reference/AGENTS.default.md | 131 + docs/zh-CN/reference/RELEASING.md | 123 + docs/zh-CN/reference/api-usage-costs.md | 136 + docs/zh-CN/reference/device-models.md | 54 + docs/zh-CN/reference/rpc.md | 48 + .../session-management-compaction.md | 288 ++ docs/zh-CN/reference/templates/AGENTS.dev.md | 89 + docs/zh-CN/reference/templates/AGENTS.md | 225 ++ docs/zh-CN/reference/templates/BOOT.md | 17 + docs/zh-CN/reference/templates/BOOTSTRAP.md | 68 + docs/zh-CN/reference/templates/HEARTBEAT.md | 18 + .../zh-CN/reference/templates/IDENTITY.dev.md | 54 + docs/zh-CN/reference/templates/IDENTITY.md | 35 + docs/zh-CN/reference/templates/SOUL.dev.md | 83 + docs/zh-CN/reference/templates/SOUL.md | 49 + docs/zh-CN/reference/templates/TOOLS.dev.md | 31 + docs/zh-CN/reference/templates/TOOLS.md | 53 + docs/zh-CN/reference/templates/USER.dev.md | 25 + docs/zh-CN/reference/templates/USER.md | 30 + docs/zh-CN/reference/test.md | 57 + docs/zh-CN/reference/transcript-hygiene.md | 109 + docs/zh-CN/render.mdx | 169 + docs/zh-CN/scripts.md | 40 + docs/zh-CN/security/formal-verification.md | 169 + docs/zh-CN/start/hubs.md | 191 + docs/zh-CN/start/lore.md | 226 ++ docs/zh-CN/start/onboarding.md | 105 + docs/zh-CN/start/openclaw.md | 248 ++ docs/zh-CN/start/pairing.md | 90 + docs/zh-CN/start/setup.md | 156 + docs/zh-CN/start/showcase.md | 423 +++ docs/zh-CN/testing.md | 375 ++ docs/zh-CN/token-use.md | 105 + docs/zh-CN/tools/agent-send.md | 60 + docs/zh-CN/tools/apply-patch.md | 57 + .../tools/browser-linux-troubleshooting.md | 146 + docs/zh-CN/tools/browser-login.md | 75 + docs/zh-CN/tools/browser.md | 542 +++ docs/zh-CN/tools/chrome-extension.md | 185 + docs/zh-CN/tools/clawhub.md | 209 ++ docs/zh-CN/tools/creating-skills.md | 61 + docs/zh-CN/tools/elevated.md | 64 + docs/zh-CN/tools/exec-approvals.md | 233 ++ docs/zh-CN/tools/exec.md | 168 + docs/zh-CN/tools/firecrawl.md | 65 + docs/zh-CN/tools/index.md | 513 +++ docs/zh-CN/tools/llm-task.md | 117 + docs/zh-CN/tools/lobster.md | 348 ++ docs/zh-CN/tools/reactions.md | 29 + docs/zh-CN/tools/skills-config.md | 78 + docs/zh-CN/tools/skills.md | 284 ++ docs/zh-CN/tools/slash-commands.md | 205 + docs/zh-CN/tools/subagents.md | 155 + docs/zh-CN/tools/thinking.md | 80 + docs/zh-CN/tools/web.md | 264 ++ docs/zh-CN/tts.md | 380 ++ docs/zh-CN/tui.md | 166 + docs/zh-CN/vps.md | 47 + docs/zh-CN/web/control-ui.md | 203 + docs/zh-CN/web/dashboard.md | 49 + docs/zh-CN/web/index.md | 118 + docs/zh-CN/web/webchat.md | 56 + 298 files changed, 53861 insertions(+) create mode 100644 docs/zh-CN/automation/auth-monitoring.md create mode 100644 docs/zh-CN/automation/cron-jobs.md create mode 100644 docs/zh-CN/automation/cron-vs-heartbeat.md create mode 100644 docs/zh-CN/automation/gmail-pubsub.md create mode 100644 docs/zh-CN/automation/poll.md create mode 100644 docs/zh-CN/automation/webhook.md create mode 100644 docs/zh-CN/bedrock.md create mode 100644 docs/zh-CN/brave-search.md create mode 100644 docs/zh-CN/broadcast-groups.md create mode 100644 docs/zh-CN/channels/bluebubbles.md create mode 100644 docs/zh-CN/channels/discord.md create mode 100644 docs/zh-CN/channels/googlechat.md create mode 100644 docs/zh-CN/channels/grammy.md create mode 100644 docs/zh-CN/channels/imessage.md create mode 100644 docs/zh-CN/channels/index.md create mode 100644 docs/zh-CN/channels/line.md create mode 100644 docs/zh-CN/channels/location.md create mode 100644 docs/zh-CN/channels/matrix.md create mode 100644 docs/zh-CN/channels/mattermost.md create mode 100644 docs/zh-CN/channels/msteams.md create mode 100644 docs/zh-CN/channels/nextcloud-talk.md create mode 100644 docs/zh-CN/channels/nostr.md create mode 100644 docs/zh-CN/channels/signal.md create mode 100644 docs/zh-CN/channels/slack.md create mode 100644 docs/zh-CN/channels/telegram.md create mode 100644 docs/zh-CN/channels/tlon.md create mode 100644 docs/zh-CN/channels/troubleshooting.md create mode 100644 docs/zh-CN/channels/twitch.md create mode 100644 docs/zh-CN/channels/whatsapp.md create mode 100644 docs/zh-CN/channels/zalo.md create mode 100644 docs/zh-CN/channels/zalouser.md create mode 100644 docs/zh-CN/cli/acp.md create mode 100644 docs/zh-CN/cli/agent.md create mode 100644 docs/zh-CN/cli/agents.md create mode 100644 docs/zh-CN/cli/approvals.md create mode 100644 docs/zh-CN/cli/browser.md create mode 100644 docs/zh-CN/cli/channels.md create mode 100644 docs/zh-CN/cli/config.md create mode 100644 docs/zh-CN/cli/configure.md create mode 100644 docs/zh-CN/cli/cron.md create mode 100644 docs/zh-CN/cli/dashboard.md create mode 100644 docs/zh-CN/cli/devices.md create mode 100644 docs/zh-CN/cli/directory.md create mode 100644 docs/zh-CN/cli/dns.md create mode 100644 docs/zh-CN/cli/docs.md create mode 100644 docs/zh-CN/cli/doctor.md create mode 100644 docs/zh-CN/cli/gateway.md create mode 100644 docs/zh-CN/cli/health.md create mode 100644 docs/zh-CN/cli/hooks.md create mode 100644 docs/zh-CN/cli/index.md create mode 100644 docs/zh-CN/cli/logs.md create mode 100644 docs/zh-CN/cli/memory.md create mode 100644 docs/zh-CN/cli/message.md create mode 100644 docs/zh-CN/cli/models.md create mode 100644 docs/zh-CN/cli/node.md create mode 100644 docs/zh-CN/cli/nodes.md create mode 100644 docs/zh-CN/cli/onboard.md create mode 100644 docs/zh-CN/cli/pairing.md create mode 100644 docs/zh-CN/cli/plugins.md create mode 100644 docs/zh-CN/cli/reset.md create mode 100644 docs/zh-CN/cli/sandbox.md create mode 100644 docs/zh-CN/cli/security.md create mode 100644 docs/zh-CN/cli/sessions.md create mode 100644 docs/zh-CN/cli/setup.md create mode 100644 docs/zh-CN/cli/skills.md create mode 100644 docs/zh-CN/cli/status.md create mode 100644 docs/zh-CN/cli/system.md create mode 100644 docs/zh-CN/cli/tui.md create mode 100644 docs/zh-CN/cli/uninstall.md create mode 100644 docs/zh-CN/cli/update.md create mode 100644 docs/zh-CN/cli/voicecall.md create mode 100644 docs/zh-CN/cli/webhooks.md create mode 100644 docs/zh-CN/concepts/agent-loop.md create mode 100644 docs/zh-CN/concepts/agent-workspace.md create mode 100644 docs/zh-CN/concepts/agent.md create mode 100644 docs/zh-CN/concepts/architecture.md create mode 100644 docs/zh-CN/concepts/channel-routing.md create mode 100644 docs/zh-CN/concepts/compaction.md create mode 100644 docs/zh-CN/concepts/context.md create mode 100644 docs/zh-CN/concepts/group-messages.md create mode 100644 docs/zh-CN/concepts/groups.md create mode 100644 docs/zh-CN/concepts/markdown-formatting.md create mode 100644 docs/zh-CN/concepts/memory.md create mode 100644 docs/zh-CN/concepts/messages.md create mode 100644 docs/zh-CN/concepts/model-failover.md create mode 100644 docs/zh-CN/concepts/model-providers.md create mode 100644 docs/zh-CN/concepts/models.md create mode 100644 docs/zh-CN/concepts/multi-agent.md create mode 100644 docs/zh-CN/concepts/oauth.md create mode 100644 docs/zh-CN/concepts/presence.md create mode 100644 docs/zh-CN/concepts/queue.md create mode 100644 docs/zh-CN/concepts/retry.md create mode 100644 docs/zh-CN/concepts/session-pruning.md create mode 100644 docs/zh-CN/concepts/session-tool.md create mode 100644 docs/zh-CN/concepts/session.md create mode 100644 docs/zh-CN/concepts/sessions.md create mode 100644 docs/zh-CN/concepts/streaming.md create mode 100644 docs/zh-CN/concepts/system-prompt.md create mode 100644 docs/zh-CN/concepts/timezone.md create mode 100644 docs/zh-CN/concepts/typebox.md create mode 100644 docs/zh-CN/concepts/typing-indicators.md create mode 100644 docs/zh-CN/concepts/usage-tracking.md create mode 100644 docs/zh-CN/date-time.md create mode 100644 docs/zh-CN/debug/node-issue.md create mode 100644 docs/zh-CN/debugging.md create mode 100644 docs/zh-CN/diagnostics/flags.md create mode 100644 docs/zh-CN/environment.md create mode 100644 docs/zh-CN/experiments/onboarding-config-protocol.md create mode 100644 docs/zh-CN/experiments/plans/cron-add-hardening.md create mode 100644 docs/zh-CN/experiments/plans/group-policy-hardening.md create mode 100644 docs/zh-CN/experiments/plans/openresponses-gateway.md create mode 100644 docs/zh-CN/experiments/proposals/model-config.md create mode 100644 docs/zh-CN/experiments/research/memory.md create mode 100644 docs/zh-CN/gateway/authentication.md create mode 100644 docs/zh-CN/gateway/background-process.md create mode 100644 docs/zh-CN/gateway/bonjour.md create mode 100644 docs/zh-CN/gateway/bridge-protocol.md create mode 100644 docs/zh-CN/gateway/cli-backends.md create mode 100644 docs/zh-CN/gateway/configuration-examples.md create mode 100644 docs/zh-CN/gateway/configuration.md create mode 100644 docs/zh-CN/gateway/discovery.md create mode 100644 docs/zh-CN/gateway/doctor.md create mode 100644 docs/zh-CN/gateway/gateway-lock.md create mode 100644 docs/zh-CN/gateway/health.md create mode 100644 docs/zh-CN/gateway/heartbeat.md create mode 100644 docs/zh-CN/gateway/index.md create mode 100644 docs/zh-CN/gateway/local-models.md create mode 100644 docs/zh-CN/gateway/logging.md create mode 100644 docs/zh-CN/gateway/multiple-gateways.md create mode 100644 docs/zh-CN/gateway/openai-http-api.md create mode 100644 docs/zh-CN/gateway/openresponses-http-api.md create mode 100644 docs/zh-CN/gateway/pairing.md create mode 100644 docs/zh-CN/gateway/protocol.md create mode 100644 docs/zh-CN/gateway/remote-gateway-readme.md create mode 100644 docs/zh-CN/gateway/remote.md create mode 100644 docs/zh-CN/gateway/sandbox-vs-tool-policy-vs-elevated.md create mode 100644 docs/zh-CN/gateway/sandboxing.md create mode 100644 docs/zh-CN/gateway/security/formal-verification.md create mode 100644 docs/zh-CN/gateway/security/index.md create mode 100644 docs/zh-CN/gateway/tailscale.md create mode 100644 docs/zh-CN/gateway/tools-invoke-http-api.md create mode 100644 docs/zh-CN/gateway/troubleshooting.md create mode 100644 docs/zh-CN/help/faq.md create mode 100644 docs/zh-CN/help/index.md create mode 100644 docs/zh-CN/help/troubleshooting.md create mode 100644 docs/zh-CN/hooks.md create mode 100644 docs/zh-CN/hooks/soul-evil.md create mode 100644 docs/zh-CN/install/ansible.md create mode 100644 docs/zh-CN/install/bun.md create mode 100644 docs/zh-CN/install/development-channels.md create mode 100644 docs/zh-CN/install/docker.md create mode 100644 docs/zh-CN/install/index.md create mode 100644 docs/zh-CN/install/installer.md create mode 100644 docs/zh-CN/install/migrating.md create mode 100644 docs/zh-CN/install/nix.md create mode 100644 docs/zh-CN/install/node.md create mode 100644 docs/zh-CN/install/uninstall.md create mode 100644 docs/zh-CN/install/updating.md create mode 100644 docs/zh-CN/logging.md create mode 100644 docs/zh-CN/multi-agent-sandbox-tools.md create mode 100644 docs/zh-CN/network.md create mode 100644 docs/zh-CN/nodes/audio.md create mode 100644 docs/zh-CN/nodes/camera.md create mode 100644 docs/zh-CN/nodes/images.md create mode 100644 docs/zh-CN/nodes/index.md create mode 100644 docs/zh-CN/nodes/location-command.md create mode 100644 docs/zh-CN/nodes/media-understanding.md create mode 100644 docs/zh-CN/nodes/talk.md create mode 100644 docs/zh-CN/nodes/voicewake.md create mode 100644 docs/zh-CN/northflank.mdx create mode 100644 docs/zh-CN/perplexity.md create mode 100644 docs/zh-CN/pi-dev.md create mode 100644 docs/zh-CN/pi.md create mode 100644 docs/zh-CN/platforms/android.md create mode 100644 docs/zh-CN/platforms/digitalocean.md create mode 100644 docs/zh-CN/platforms/exe-dev.md create mode 100644 docs/zh-CN/platforms/fly.md create mode 100644 docs/zh-CN/platforms/gcp.md create mode 100644 docs/zh-CN/platforms/hetzner.md create mode 100644 docs/zh-CN/platforms/index.md create mode 100644 docs/zh-CN/platforms/ios.md create mode 100644 docs/zh-CN/platforms/linux.md create mode 100644 docs/zh-CN/platforms/mac/bundled-gateway.md create mode 100644 docs/zh-CN/platforms/mac/canvas.md create mode 100644 docs/zh-CN/platforms/mac/child-process.md create mode 100644 docs/zh-CN/platforms/mac/dev-setup.md create mode 100644 docs/zh-CN/platforms/mac/health.md create mode 100644 docs/zh-CN/platforms/mac/icon.md create mode 100644 docs/zh-CN/platforms/mac/logging.md create mode 100644 docs/zh-CN/platforms/mac/menu-bar.md create mode 100644 docs/zh-CN/platforms/mac/peekaboo.md create mode 100644 docs/zh-CN/platforms/mac/permissions.md create mode 100644 docs/zh-CN/platforms/mac/release.md create mode 100644 docs/zh-CN/platforms/mac/remote.md create mode 100644 docs/zh-CN/platforms/mac/signing.md create mode 100644 docs/zh-CN/platforms/mac/skills.md create mode 100644 docs/zh-CN/platforms/mac/voice-overlay.md create mode 100644 docs/zh-CN/platforms/mac/voicewake.md create mode 100644 docs/zh-CN/platforms/mac/webchat.md create mode 100644 docs/zh-CN/platforms/mac/xpc.md create mode 100644 docs/zh-CN/platforms/macos-vm.md create mode 100644 docs/zh-CN/platforms/macos.md create mode 100644 docs/zh-CN/platforms/oracle.md create mode 100644 docs/zh-CN/platforms/raspberry-pi.md create mode 100644 docs/zh-CN/platforms/windows.md create mode 100644 docs/zh-CN/plugin.md create mode 100644 docs/zh-CN/plugins/agent-tools.md create mode 100644 docs/zh-CN/plugins/manifest.md create mode 100644 docs/zh-CN/plugins/voice-call.md create mode 100644 docs/zh-CN/plugins/zalouser.md create mode 100644 docs/zh-CN/prose.md create mode 100644 docs/zh-CN/providers/anthropic.md create mode 100644 docs/zh-CN/providers/claude-max-api-proxy.md create mode 100644 docs/zh-CN/providers/deepgram.md create mode 100644 docs/zh-CN/providers/github-copilot.md create mode 100644 docs/zh-CN/providers/glm.md create mode 100644 docs/zh-CN/providers/index.md create mode 100644 docs/zh-CN/providers/minimax.md create mode 100644 docs/zh-CN/providers/models.md create mode 100644 docs/zh-CN/providers/moonshot.md create mode 100644 docs/zh-CN/providers/ollama.md create mode 100644 docs/zh-CN/providers/openai.md create mode 100644 docs/zh-CN/providers/opencode.md create mode 100644 docs/zh-CN/providers/openrouter.md create mode 100644 docs/zh-CN/providers/qwen.md create mode 100644 docs/zh-CN/providers/synthetic.md create mode 100644 docs/zh-CN/providers/venice.md create mode 100644 docs/zh-CN/providers/vercel-ai-gateway.md create mode 100644 docs/zh-CN/providers/xiaomi.md create mode 100644 docs/zh-CN/providers/zai.md create mode 100644 docs/zh-CN/railway.mdx create mode 100644 docs/zh-CN/refactor/clawnet.md create mode 100644 docs/zh-CN/refactor/exec-host.md create mode 100644 docs/zh-CN/refactor/outbound-session-mirroring.md create mode 100644 docs/zh-CN/refactor/plugin-sdk.md create mode 100644 docs/zh-CN/refactor/strict-config.md create mode 100644 docs/zh-CN/reference/AGENTS.default.md create mode 100644 docs/zh-CN/reference/RELEASING.md create mode 100644 docs/zh-CN/reference/api-usage-costs.md create mode 100644 docs/zh-CN/reference/device-models.md create mode 100644 docs/zh-CN/reference/rpc.md create mode 100644 docs/zh-CN/reference/session-management-compaction.md create mode 100644 docs/zh-CN/reference/templates/AGENTS.dev.md create mode 100644 docs/zh-CN/reference/templates/AGENTS.md create mode 100644 docs/zh-CN/reference/templates/BOOT.md create mode 100644 docs/zh-CN/reference/templates/BOOTSTRAP.md create mode 100644 docs/zh-CN/reference/templates/HEARTBEAT.md create mode 100644 docs/zh-CN/reference/templates/IDENTITY.dev.md create mode 100644 docs/zh-CN/reference/templates/IDENTITY.md create mode 100644 docs/zh-CN/reference/templates/SOUL.dev.md create mode 100644 docs/zh-CN/reference/templates/SOUL.md create mode 100644 docs/zh-CN/reference/templates/TOOLS.dev.md create mode 100644 docs/zh-CN/reference/templates/TOOLS.md create mode 100644 docs/zh-CN/reference/templates/USER.dev.md create mode 100644 docs/zh-CN/reference/templates/USER.md create mode 100644 docs/zh-CN/reference/test.md create mode 100644 docs/zh-CN/reference/transcript-hygiene.md create mode 100644 docs/zh-CN/render.mdx create mode 100644 docs/zh-CN/scripts.md create mode 100644 docs/zh-CN/security/formal-verification.md create mode 100644 docs/zh-CN/start/hubs.md create mode 100644 docs/zh-CN/start/lore.md create mode 100644 docs/zh-CN/start/onboarding.md create mode 100644 docs/zh-CN/start/openclaw.md create mode 100644 docs/zh-CN/start/pairing.md create mode 100644 docs/zh-CN/start/setup.md create mode 100644 docs/zh-CN/start/showcase.md create mode 100644 docs/zh-CN/testing.md create mode 100644 docs/zh-CN/token-use.md create mode 100644 docs/zh-CN/tools/agent-send.md create mode 100644 docs/zh-CN/tools/apply-patch.md create mode 100644 docs/zh-CN/tools/browser-linux-troubleshooting.md create mode 100644 docs/zh-CN/tools/browser-login.md create mode 100644 docs/zh-CN/tools/browser.md create mode 100644 docs/zh-CN/tools/chrome-extension.md create mode 100644 docs/zh-CN/tools/clawhub.md create mode 100644 docs/zh-CN/tools/creating-skills.md create mode 100644 docs/zh-CN/tools/elevated.md create mode 100644 docs/zh-CN/tools/exec-approvals.md create mode 100644 docs/zh-CN/tools/exec.md create mode 100644 docs/zh-CN/tools/firecrawl.md create mode 100644 docs/zh-CN/tools/index.md create mode 100644 docs/zh-CN/tools/llm-task.md create mode 100644 docs/zh-CN/tools/lobster.md create mode 100644 docs/zh-CN/tools/reactions.md create mode 100644 docs/zh-CN/tools/skills-config.md create mode 100644 docs/zh-CN/tools/skills.md create mode 100644 docs/zh-CN/tools/slash-commands.md create mode 100644 docs/zh-CN/tools/subagents.md create mode 100644 docs/zh-CN/tools/thinking.md create mode 100644 docs/zh-CN/tools/web.md create mode 100644 docs/zh-CN/tts.md create mode 100644 docs/zh-CN/tui.md create mode 100644 docs/zh-CN/vps.md create mode 100644 docs/zh-CN/web/control-ui.md create mode 100644 docs/zh-CN/web/dashboard.md create mode 100644 docs/zh-CN/web/index.md create mode 100644 docs/zh-CN/web/webchat.md diff --git a/docs/zh-CN/automation/auth-monitoring.md b/docs/zh-CN/automation/auth-monitoring.md new file mode 100644 index 0000000000..1f780e31a7 --- /dev/null +++ b/docs/zh-CN/automation/auth-monitoring.md @@ -0,0 +1,47 @@ +--- +read_when: + - 设置认证过期监控或告警 + - 自动化 Claude Code / Codex OAuth 刷新检查 +summary: 监控模型提供商的 OAuth 过期状态 +title: 认证监控 +x-i18n: + generated_at: "2026-02-01T19:36:14Z" + model: claude-opus-4-5 + provider: pi + source_hash: eef179af9545ed7ab881f3ccbef998869437fb50cdb4088de8da7223b614fa2b + source_path: automation/auth-monitoring.md + workflow: 14 +--- + +# 认证监控 + +OpenClaw 通过 `openclaw models status` 暴露 OAuth 过期健康状态。可将其用于自动化和告警;脚本是针对手机工作流的可选补充。 + +## 推荐方式:CLI 检查(跨平台通用) + +```bash +openclaw models status --check +``` + +退出码: + +- `0`:正常 +- `1`:凭证已过期或缺失 +- `2`:即将过期(24 小时内) + +适用于 cron/systemd,无需额外脚本。 + +## 可选脚本(运维/手机工作流) + +这些脚本位于 `scripts/` 目录下,属于**可选项**。它们假定你可以通过 SSH 访问 Gateway 主机,并针对 systemd + Termux 进行了调优。 + +- `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。 + +如果你不需要手机自动化或 systemd 定时器,可以跳过这些脚本。 diff --git a/docs/zh-CN/automation/cron-jobs.md b/docs/zh-CN/automation/cron-jobs.md new file mode 100644 index 0000000000..73b7f378fa --- /dev/null +++ b/docs/zh-CN/automation/cron-jobs.md @@ -0,0 +1,434 @@ +--- +read_when: + - 调度后台任务或唤醒 + - 配置需要与心跳一起或并行运行的自动化 + - 在心跳和定时任务之间做选择 +summary: Gateway 调度器的定时任务与唤醒 +title: 定时任务 +x-i18n: + generated_at: "2026-02-01T19:37:32Z" + model: claude-opus-4-5 + provider: pi + source_hash: d43268b0029f1b13d0825ddcc9c06a354987ea17ce02f3b5428a9c68bf936676 + source_path: automation/cron-jobs.md + workflow: 14 +--- + +# 定时任务(Gateway 调度器) + +> **定时任务还是心跳?** 请参阅[定时任务与心跳对比](/automation/cron-vs-heartbeat)了解何时使用哪种方式。 + +定时任务是 Gateway 内置的调度器。它持久化任务、在合适的时间唤醒智能体,并可选择将输出发送回聊天。 + +如果你想要 _"每天早上运行"_ 或 _"20 分钟后提醒智能体"_,定时任务就是对应的机制。 + +## 简要概述 + +- 定时任务运行在 **Gateway 内部**(而非模型内部)。 +- 任务持久化存储在 `~/.openclaw/cron/` 下,因此重启不会丢失计划。 +- 两种执行方式: + - **主会话**:入队一个系统事件,然后在下一次心跳时运行。 + - **隔离式**:在 `cron:` 中运行专用智能体轮次,可选择投递输出。 +- 唤醒是一等功能:任务可以请求"立即唤醒"或"下次心跳时"。 + +## 快速开始(可操作) + +创建一个一次性提醒,验证其存在,然后立即运行: + +```bash +openclaw cron add \ + --name "Reminder" \ + --at "2026-02-01T16:00:00Z" \ + --session main \ + --system-event "Reminder: check the cron docs draft" \ + --wake now \ + --delete-after-run + +openclaw cron list +openclaw cron run --force +openclaw cron runs --id +``` + +调度一个带投递功能的周期性隔离任务: + +```bash +openclaw cron add \ + --name "Morning brief" \ + --cron "0 7 * * *" \ + --tz "America/Los_Angeles" \ + --session isolated \ + --message "Summarize overnight updates." \ + --deliver \ + --channel slack \ + --to "channel:C1234567890" +``` + +## 工具调用等价形式(Gateway 定时任务工具) + +有关规范的 JSON 结构和示例,请参阅[工具调用的 JSON 模式](/automation/cron-jobs#json-schema-for-tool-calls)。 + +## 定时任务的存储位置 + +定时任务默认持久化存储在 Gateway 主机的 `~/.openclaw/cron/jobs.json` 中。Gateway 将文件加载到内存中,并在更改时写回,因此仅在 Gateway 停止时手动编辑才是安全的。请优先使用 `openclaw cron add/edit` 或定时任务工具调用 API 进行更改。 + +## 新手友好概述 + +将定时任务理解为:**何时**运行 + **做什么**。 + +1. **选择调度计划** + - 一次性提醒 → `schedule.kind = "at"`(CLI:`--at`) + - 重复任务 → `schedule.kind = "every"` 或 `schedule.kind = "cron"` + - 如果你的 ISO 时间戳省略了时区,将被视为 **UTC**。 + +2. **选择运行位置** + - `sessionTarget: "main"` → 在下一次心跳时使用主会话上下文运行。 + - `sessionTarget: "isolated"` → 在 `cron:` 中运行专用智能体轮次。 + +3. **选择负载** + - 主会话 → `payload.kind = "systemEvent"` + - 隔离会话 → `payload.kind = "agentTurn"` + +可选:`deleteAfterRun: true` 会在一次性任务成功运行后将其从存储中删除。 + +## 概念 + +### 任务 + +定时任务是一条存储记录,包含: + +- 一个**调度计划**(何时运行), +- 一个**负载**(做什么), +- 可选的**投递**(输出发送到哪里)。 +- 可选的**智能体绑定**(`agentId`):在指定智能体下运行任务;如果缺失或未知,Gateway 会回退到默认智能体。 + +任务通过稳定的 `jobId` 标识(用于 CLI/Gateway API)。 +在智能体工具调用中,`jobId` 是规范字段;旧版 `id` 仍可兼容使用。 +任务可以通过 `deleteAfterRun: true` 在一次性任务成功运行后自动删除。 + +### 调度计划 + +定时任务支持三种调度类型: + +- `at`:一次性时间戳(自纪元起的毫秒数)。Gateway 接受 ISO 8601 格式并转换为 UTC。 +- `every`:固定间隔(毫秒)。 +- `cron`:5 字段 cron 表达式,可选 IANA 时区。 + +Cron 表达式使用 `croner`。如果省略时区,将使用 Gateway 主机的本地时区。 + +### 主会话与隔离式执行 + +#### 主会话任务(系统事件) + +主会话任务入队一个系统事件,并可选择唤醒心跳运行器。它们必须使用 `payload.kind = "systemEvent"`。 + +- `wakeMode: "next-heartbeat"`(默认):事件等待下一次计划心跳。 +- `wakeMode: "now"`:事件触发立即心跳运行。 + +当你需要正常的心跳提示 + 主会话上下文时,这是最佳选择。参见[心跳](/gateway/heartbeat)。 + +#### 隔离任务(专用定时会话) + +隔离任务在会话 `cron:` 中运行专用智能体轮次。 + +关键行为: + +- 提示以 `[cron: <任务名称>]` 为前缀,便于追踪。 +- 每次运行都会启动一个**全新的会话 ID**(不继承之前的对话)。 +- 摘要会发布到主会话(前缀 `Cron`,可配置)。 +- `wakeMode: "now"` 在发布摘要后触发立即心跳。 +- 如果 `payload.deliver: true`,输出会投递到渠道;否则保留在内部。 + +对于嘈杂、频繁或"后台杂务"类任务,使用隔离任务可以避免污染你的主聊天记录。 + +### 负载结构(运行内容) + +支持两种负载类型: + +- `systemEvent`:仅限主会话,通过心跳提示路由。 +- `agentTurn`:仅限隔离会话,运行专用智能体轮次。 + +常用 `agentTurn` 字段: + +- `message`:必填文本提示。 +- `model` / `thinking`:可选覆盖(见下文)。 +- `timeoutSeconds`:可选超时覆盖。 +- `deliver`:设为 `true` 以将输出发送到渠道目标。 +- `channel`:`last` 或特定渠道。 +- `to`:渠道特定目标(电话/聊天/频道 ID)。 +- `bestEffortDeliver`:投递失败时避免任务失败。 + +隔离选项(仅适用于 `session=isolated`): + +- `postToMainPrefix`(CLI:`--post-prefix`):主会话中系统事件的前缀。 +- `postToMainMode`:`summary`(默认)或 `full`。 +- `postToMainMaxChars`:当 `postToMainMode=full` 时的最大字符数(默认 8000)。 + +### 模型和思维覆盖 + +隔离任务(`agentTurn`)可以覆盖模型和思维级别: + +- `model`:提供商/模型字符串(例如 `anthropic/claude-sonnet-4-20250514`)或别名(例如 `opus`) +- `thinking`:思维级别(`off`、`minimal`、`low`、`medium`、`high`、`xhigh`;仅限 GPT-5.2 + Codex 模型) + +注意:你也可以在主会话任务上设置 `model`,但这会更改共享的主会话模型。我们建议仅对隔离任务使用模型覆盖,以避免意外的上下文切换。 + +优先级解析顺序: + +1. 任务负载覆盖(最高优先级) +2. 钩子特定默认值(例如 `hooks.gmail.model`) +3. 智能体配置默认值 + +### 投递(渠道 + 目标) + +隔离任务可以将输出投递到渠道。任务负载可以指定: + +- `channel`:`whatsapp` / `telegram` / `discord` / `slack` / `mattermost`(插件)/ `signal` / `imessage` / `last` +- `to`:渠道特定的接收目标 + +如果省略 `channel` 或 `to`,定时任务可以回退到主会话的"最后路由"(智能体最后回复的位置)。 + +投递说明: + +- 如果设置了 `to`,即使省略 `deliver`,定时任务也会自动投递智能体的最终输出。 +- 当你需要最后路由投递但不指定明确 `to` 时,使用 `deliver: true`。 +- 使用 `deliver: false` 即使存在 `to` 也保持输出为内部使用。 + +目标格式提醒: + +- Slack/Discord/Mattermost(插件)目标应使用明确前缀(例如 `channel:`、`user:`)以避免歧义。 +- Telegram 主题应使用 `:topic:` 格式(见下文)。 + +#### Telegram 投递目标(主题/论坛帖子) + +Telegram 通过 `message_thread_id` 支持论坛主题。对于定时任务投递,你可以将主题/帖子编码到 `to` 字段中: + +- `-1001234567890`(仅聊天 ID) +- `-1001234567890:topic:123`(推荐:明确的主题标记) +- `-1001234567890:123`(简写:数字后缀) + +带前缀的目标如 `telegram:...` / `telegram:group:...` 也可接受: + +- `telegram:group:-1001234567890:topic:123` + +## 工具调用的 JSON 模式 + +直接调用 Gateway `cron.*` 工具(智能体工具调用或 RPC)时使用这些结构。CLI 标志接受人类可读的时间格式如 `20m`,但工具调用对 `atMs` 和 `everyMs` 使用纪元毫秒数(`at` 时间接受 ISO 时间戳)。 + +### cron.add 参数 + +一次性主会话任务(系统事件): + +```json +{ + "name": "Reminder", + "schedule": { "kind": "at", "atMs": 1738262400000 }, + "sessionTarget": "main", + "wakeMode": "now", + "payload": { "kind": "systemEvent", "text": "Reminder text" }, + "deleteAfterRun": true +} +``` + +带投递的周期性隔离任务: + +```json +{ + "name": "Morning brief", + "schedule": { "kind": "cron", "expr": "0 7 * * *", "tz": "America/Los_Angeles" }, + "sessionTarget": "isolated", + "wakeMode": "next-heartbeat", + "payload": { + "kind": "agentTurn", + "message": "Summarize overnight updates.", + "deliver": true, + "channel": "slack", + "to": "channel:C1234567890", + "bestEffortDeliver": true + }, + "isolation": { "postToMainPrefix": "Cron", "postToMainMode": "summary" } +} +``` + +说明: + +- `schedule.kind`:`at`(`atMs`)、`every`(`everyMs`)或 `cron`(`expr`,可选 `tz`)。 +- `atMs` 和 `everyMs` 为纪元毫秒数。 +- `sessionTarget` 必须为 `"main"` 或 `"isolated"`,且必须与 `payload.kind` 匹配。 +- 可选字段:`agentId`、`description`、`enabled`、`deleteAfterRun`、`isolation`。 +- `wakeMode` 省略时默认为 `"next-heartbeat"`。 + +### cron.update 参数 + +```json +{ + "jobId": "job-123", + "patch": { + "enabled": false, + "schedule": { "kind": "every", "everyMs": 3600000 } + } +} +``` + +说明: + +- `jobId` 是规范字段;`id` 可兼容使用。 +- 在补丁中使用 `agentId: null` 可清除智能体绑定。 + +### cron.run 和 cron.remove 参数 + +```json +{ "jobId": "job-123", "mode": "force" } +``` + +```json +{ "jobId": "job-123" } +``` + +## 存储与历史 + +- 任务存储:`~/.openclaw/cron/jobs.json`(Gateway 管理的 JSON)。 +- 运行历史:`~/.openclaw/cron/runs/.jsonl`(JSONL,自动清理)。 +- 覆盖存储路径:配置中的 `cron.store`。 + +## 配置 + +```json5 +{ + cron: { + enabled: true, // 默认 true + store: "~/.openclaw/cron/jobs.json", + maxConcurrentRuns: 1, // 默认 1 + }, +} +``` + +完全禁用定时任务: + +- `cron.enabled: false`(配置) +- `OPENCLAW_SKIP_CRON=1`(环境变量) + +## CLI 快速开始 + +一次性提醒(UTC ISO,成功后自动删除): + +```bash +openclaw cron add \ + --name "Send reminder" \ + --at "2026-01-12T18:00:00Z" \ + --session main \ + --system-event "Reminder: submit expense report." \ + --wake now \ + --delete-after-run +``` + +一次性提醒(主会话,立即唤醒): + +```bash +openclaw cron add \ + --name "Calendar check" \ + --at "20m" \ + --session main \ + --system-event "Next heartbeat: check calendar." \ + --wake now +``` + +周期性隔离任务(投递到 WhatsApp): + +```bash +openclaw cron add \ + --name "Morning status" \ + --cron "0 7 * * *" \ + --tz "America/Los_Angeles" \ + --session isolated \ + --message "Summarize inbox + calendar for today." \ + --deliver \ + --channel whatsapp \ + --to "+15551234567" +``` + +周期性隔离任务(投递到 Telegram 主题): + +```bash +openclaw cron add \ + --name "Nightly summary (topic)" \ + --cron "0 22 * * *" \ + --tz "America/Los_Angeles" \ + --session isolated \ + --message "Summarize today; send to the nightly topic." \ + --deliver \ + --channel telegram \ + --to "-1001234567890:topic:123" +``` + +带模型和思维覆盖的隔离任务: + +```bash +openclaw cron add \ + --name "Deep analysis" \ + --cron "0 6 * * 1" \ + --tz "America/Los_Angeles" \ + --session isolated \ + --message "Weekly deep analysis of project progress." \ + --model "opus" \ + --thinking high \ + --deliver \ + --channel whatsapp \ + --to "+15551234567" +``` + +智能体选择(多智能体配置): + +```bash +# 将任务绑定到智能体 "ops"(如果该智能体不存在则回退到默认智能体) +openclaw cron add --name "Ops sweep" --cron "0 6 * * *" --session isolated --message "Check ops queue" --agent ops + +# 切换或清除现有任务的智能体 +openclaw cron edit --agent ops +openclaw cron edit --clear-agent +``` + +手动运行(调试): + +```bash +openclaw cron run --force +``` + +编辑现有任务(补丁字段): + +```bash +openclaw cron edit \ + --message "Updated prompt" \ + --model "opus" \ + --thinking low +``` + +运行历史: + +```bash +openclaw cron runs --id --limit 50 +``` + +不创建任务直接发送系统事件: + +```bash +openclaw system event --mode now --text "Next heartbeat: check battery." +``` + +## Gateway API 接口 + +- `cron.list`、`cron.status`、`cron.add`、`cron.update`、`cron.remove` +- `cron.run`(强制或到期)、`cron.runs` + 如需不创建任务直接发送系统事件,请使用 [`openclaw system event`](/cli/system)。 + +## 故障排除 + +### "没有任何任务运行" + +- 检查定时任务是否已启用:`cron.enabled` 和 `OPENCLAW_SKIP_CRON`。 +- 检查 Gateway 是否持续运行(定时任务运行在 Gateway 进程内部)。 +- 对于 `cron` 调度:确认时区(`--tz`)与主机时区的关系。 + +### Telegram 投递到了错误的位置 + +- 对于论坛主题,使用 `-100…:topic:` 以确保明确无歧义。 +- 如果你在日志或存储的"最后路由"目标中看到 `telegram:...` 前缀,这是正常的;定时任务投递接受这些前缀并仍能正确解析主题 ID。 diff --git a/docs/zh-CN/automation/cron-vs-heartbeat.md b/docs/zh-CN/automation/cron-vs-heartbeat.md new file mode 100644 index 0000000000..73f3bdcd18 --- /dev/null +++ b/docs/zh-CN/automation/cron-vs-heartbeat.md @@ -0,0 +1,286 @@ +--- +read_when: + - 决定如何调度周期性任务 + - 设置后台监控或通知 + - 优化定期检查的 token 用量 +summary: 选择心跳还是定时任务进行自动化的指南 +title: 定时任务与心跳对比 +x-i18n: + generated_at: "2026-02-01T19:38:18Z" + model: claude-opus-4-5 + provider: pi + source_hash: 5f71a63181baa41b1c307eb7bfac561df7943d4627077dfa2861eb9f76ab086b + source_path: automation/cron-vs-heartbeat.md + workflow: 14 +--- + +# 定时任务与心跳:何时使用哪种方式 + +心跳和定时任务都可以按计划运行任务。本指南帮助你根据使用场景选择合适的机制。 + +## 快速决策指南 + +| 使用场景 | 推荐方式 | 原因 | +| ------------------------- | -------------------------- | ---------------------------------------- | +| 每 30 分钟检查收件箱 | 心跳 | 可与其他检查批量处理,具备上下文感知能力 | +| 每天上午 9 点准时发送报告 | 定时任务(隔离式) | 需要精确定时 | +| 监控日历中即将到来的事件 | 心跳 | 天然适合周期性感知 | +| 运行每周深度分析 | 定时任务(隔离式) | 独立任务,可使用不同模型 | +| 20 分钟后提醒我 | 定时任务(主会话,`--at`) | 精确定时的一次性任务 | +| 后台项目健康检查 | 心跳 | 搭载在现有周期上 | + +## 心跳:周期性感知 + +心跳在**主会话**中以固定间隔运行(默认:30 分钟)。它的设计目的是让智能体检查各种事项并呈现重要信息。 + +### 何时使用心跳 + +- **多个周期性检查**:与其设置 5 个独立的定时任务分别检查收件箱、日历、天气、通知和项目状态,不如用一次心跳批量处理所有内容。 +- **上下文感知决策**:智能体拥有完整的主会话上下文,因此可以智能判断哪些紧急、哪些可以等待。 +- **对话连续性**:心跳运行共享同一会话,因此智能体记得最近的对话,可以自然地进行后续跟进。 +- **低开销监控**:一次心跳替代多个小型轮询任务。 + +### 心跳优势 + +- **批量处理多项检查**:一次智能体轮次可以同时审查收件箱、日历和通知。 +- **减少 API 调用**:一次心跳比 5 个隔离式定时任务更经济。 +- **上下文感知**:智能体了解你一直在做什么,可以据此排定优先级。 +- **智能抑制**:如果没有需要关注的事项,智能体回复 `HEARTBEAT_OK`,不会投递任何消息。 +- **自然定时**:会根据队列负载略有漂移,但对大多数监控来说没有问题。 + +### 心跳示例:HEARTBEAT.md 检查清单 + +```md +# Heartbeat checklist + +- Check email for urgent messages +- Review calendar for events in next 2 hours +- If a background task finished, summarize results +- If idle for 8+ hours, send a brief check-in +``` + +智能体在每次心跳时读取此清单,并在一次轮次中处理所有项目。 + +### 配置心跳 + +```json5 +{ + agents: { + defaults: { + heartbeat: { + every: "30m", // 间隔 + target: "last", // 告警投递目标 + activeHours: { start: "08:00", end: "22:00" }, // 可选 + }, + }, + }, +} +``` + +完整配置请参阅[心跳](/gateway/heartbeat)。 + +## 定时任务:精确调度 + +定时任务在**精确时间**运行,可以在隔离会话中运行而不影响主会话上下文。 + +### 何时使用定时任务 + +- **需要精确定时**:"每周一上午 9:00 发送"(而不是"大约 9 点左右")。 +- **独立任务**:不需要对话上下文的任务。 +- **不同的模型/思维级别**:需要更强大模型的深度分析。 +- **一次性提醒**:使用 `--at` 实现"20 分钟后提醒我"。 +- **嘈杂/频繁的任务**:会把主会话历史搞得杂乱的任务。 +- **外部触发器**:无论智能体是否处于活跃状态都应独立运行的任务。 + +### 定时任务优势 + +- **精确定时**:支持带时区的 5 字段 cron 表达式。 +- **会话隔离**:在 `cron:` 中运行,不会污染主会话历史。 +- **模型覆盖**:可按任务使用更便宜或更强大的模型。 +- **投递控制**:可直接投递到渠道;默认仍会向主会话发布摘要(可配置)。 +- **无需智能体上下文**:即使主会话空闲或已压缩,也能运行。 +- **一次性支持**:`--at` 用于精确的未来时间戳。 + +### 定时任务示例:每日早间简报 + +```bash +openclaw cron add \ + --name "Morning briefing" \ + --cron "0 7 * * *" \ + --tz "America/New_York" \ + --session isolated \ + --message "Generate today's briefing: weather, calendar, top emails, news summary." \ + --model opus \ + --deliver \ + --channel whatsapp \ + --to "+15551234567" +``` + +这会在纽约时间每天早上 7:00 准时运行,使用 Opus 保证质量,并直接投递到 WhatsApp。 + +### 定时任务示例:一次性提醒 + +```bash +openclaw cron add \ + --name "Meeting reminder" \ + --at "20m" \ + --session main \ + --system-event "Reminder: standup meeting starts in 10 minutes." \ + --wake now \ + --delete-after-run +``` + +完整 CLI 参考请参阅[定时任务](/automation/cron-jobs)。 + +## 决策流程图 + +``` +任务是否需要在精确时间运行? + 是 -> 使用定时任务 + 否 -> 继续... + +任务是否需要与主会话隔离? + 是 -> 使用定时任务(隔离式) + 否 -> 继续... + +此任务能否与其他周期性检查批量处理? + 是 -> 使用心跳(添加到 HEARTBEAT.md) + 否 -> 使用定时任务 + +这是一次性提醒吗? + 是 -> 使用定时任务配合 --at + 否 -> 继续... + +是否需要不同的模型或思维级别? + 是 -> 使用定时任务(隔离式)配合 --model/--thinking + 否 -> 使用心跳 +``` + +## 组合使用 + +最高效的配置是**两者结合**: + +1. **心跳**处理常规监控(收件箱、日历、通知),每 30 分钟批量处理一次。 +2. **定时任务**处理精确调度(每日报告、每周回顾)和一次性提醒。 + +### 示例:高效自动化配置 + +**HEARTBEAT.md**(每 30 分钟检查一次): + +```md +# Heartbeat checklist + +- Scan inbox for urgent emails +- Check calendar for events in next 2h +- Review any pending tasks +- Light check-in if quiet for 8+ hours +``` + +**定时任务**(精确定时): + +```bash +# 每天早上 7 点的早间简报 +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 + +# 一次性提醒 +openclaw cron add --name "Call back" --at "2h" --session main --system-event "Call back the client" --wake now +``` + +## Lobster:带审批的确定性工作流 + +Lobster 是用于**多步骤工具管道**的工作流运行时,适用于需要确定性执行和明确审批的场景。当任务不只是单次智能体轮次,且你需要可恢复的带人工检查点的工作流时,使用它。 + +### 何时适合使用 Lobster + +- **多步骤自动化**:你需要一个固定的工具调用管道,而不是一次性提示。 +- **审批关卡**:副作用应暂停直到你批准,然后继续执行。 +- **可恢复运行**:继续暂停的工作流而无需重新运行之前的步骤。 + +### 如何与心跳和定时任务配合 + +- **心跳/定时任务**决定*何时*运行。 +- **Lobster** 定义运行开始后*执行哪些步骤*。 + +对于计划性工作流,使用定时任务或心跳触发一次调用 Lobster 的智能体轮次。对于临时工作流,直接调用 Lobster。 + +### 操作说明(来自代码) + +- Lobster 以**本地子进程**(`lobster` CLI)在工具模式下运行,并返回 **JSON 信封**。 +- 如果工具返回 `needs_approval`,你需要使用 `resumeToken` 和 `approve` 标志来恢复。 +- 该工具是**可选插件**;建议通过 `tools.alsoAllow: ["lobster"]` 附加启用。 +- 如果传入 `lobsterPath`,必须是**绝对路径**。 + +完整用法和示例请参阅 [Lobster](/tools/lobster)。 + +## 主会话与隔离会话 + +心跳和定时任务都可以与主会话交互,但方式不同: + +| | 心跳 | 定时任务(主会话) | 定时任务(隔离式) | +| ------ | ------------------------ | ---------------------- | ------------------ | +| 会话 | 主会话 | 主会话(通过系统事件) | `cron:` | +| 历史 | 共享 | 共享 | 每次运行全新 | +| 上下文 | 完整 | 完整 | 无(从零开始) | +| 模型 | 主会话模型 | 主会话模型 | 可覆盖 | +| 输出 | 非 `HEARTBEAT_OK` 时投递 | 心跳提示 + 事件 | 摘要发布到主会话 | + +### 何时使用主会话定时任务 + +当你需要以下场景时,使用 `--session main` 配合 `--system-event`: + +- 提醒/事件出现在主会话上下文中 +- 智能体在下一次心跳时带着完整上下文处理它 +- 不需要单独的隔离运行 + +```bash +openclaw cron add \ + --name "Check project" \ + --every "4h" \ + --session main \ + --system-event "Time for a project health check" \ + --wake now +``` + +### 何时使用隔离式定时任务 + +当你需要以下场景时,使用 `--session isolated`: + +- 无先前上下文的全新环境 +- 不同的模型或思维设置 +- 输出直接投递到渠道(摘要默认仍会发布到主会话) +- 不会把主会话搞得杂乱的历史记录 + +```bash +openclaw cron add \ + --name "Deep analysis" \ + --cron "0 6 * * 0" \ + --session isolated \ + --message "Weekly codebase analysis..." \ + --model opus \ + --thinking high \ + --deliver +``` + +## 成本考量 + +| 机制 | 成本特征 | +| ------------------ | ---------------------------------------------- | +| 心跳 | 每 N 分钟一次轮次;随 HEARTBEAT.md 大小扩展 | +| 定时任务(主会话) | 将事件添加到下一次心跳(无隔离轮次) | +| 定时任务(隔离式) | 每个任务一次完整智能体轮次;可使用更便宜的模型 | + +**建议**: + +- 保持 `HEARTBEAT.md` 精简以减少 token 开销。 +- 将类似的检查批量放入心跳,而不是创建多个定时任务。 +- 如果只需要内部处理,在心跳上使用 `target: "none"`。 +- 对常规任务使用隔离式定时任务配合更便宜的模型。 + +## 相关内容 + +- [心跳](/gateway/heartbeat) - 完整的心跳配置 +- [定时任务](/automation/cron-jobs) - 完整的定时任务 CLI 和 API 参考 +- [系统](/cli/system) - 系统事件 + 心跳控制 diff --git a/docs/zh-CN/automation/gmail-pubsub.md b/docs/zh-CN/automation/gmail-pubsub.md new file mode 100644 index 0000000000..041ab6d71f --- /dev/null +++ b/docs/zh-CN/automation/gmail-pubsub.md @@ -0,0 +1,249 @@ +--- +read_when: + - 将 Gmail 收件箱触发器接入 OpenClaw + - 为智能体唤醒设置 Pub/Sub 推送 +summary: 通过 gogcli 将 Gmail Pub/Sub 推送接入 OpenClaw webhooks +title: Gmail PubSub +x-i18n: + generated_at: "2026-02-01T19:38:47Z" + model: claude-opus-4-5 + provider: pi + source_hash: dfb92133b69177e4e984b7d072f5dc28aa53a9e0cf984a018145ed811aa96195 + source_path: automation/gmail-pubsub.md + workflow: 14 +--- + +# Gmail Pub/Sub -> OpenClaw + +目标:Gmail watch -> Pub/Sub 推送 -> `gog gmail watch serve` -> OpenClaw webhook。 + +## 前置条件 + +- 已安装并登录 `gcloud`([安装指南](https://docs.cloud.google.com/sdk/docs/install-sdk))。 +- 已安装 `gog`(gogcli)并已授权 Gmail 账号([gogcli.sh](https://gogcli.sh/))。 +- 已启用 OpenClaw hooks(参见 [Webhooks](/automation/webhook))。 +- 已登录 `tailscale`([tailscale.com](https://tailscale.com/))。支持的配置使用 Tailscale Funnel 作为公共 HTTPS 端点。 + 其他隧道服务也可以使用,但属于自行配置/不受支持,需要手动接线。 + 目前我们支持的是 Tailscale。 + +示例 hook 配置(启用 Gmail 预设映射): + +```json5 +{ + hooks: { + enabled: true, + token: "OPENCLAW_HOOK_TOKEN", + path: "/hooks", + presets: ["gmail"], + }, +} +``` + +如需将 Gmail 摘要投递到聊天界面,可覆盖预设并设置带 `deliver` 以及可选的 `channel`/`to` 的映射: + +```json5 +{ + hooks: { + enabled: true, + token: "OPENCLAW_HOOK_TOKEN", + presets: ["gmail"], + mappings: [ + { + match: { path: "gmail" }, + action: "agent", + wakeMode: "now", + name: "Gmail", + sessionKey: "hook:gmail:{{messages[0].id}}", + messageTemplate: "New email from {{messages[0].from}}\nSubject: {{messages[0].subject}}\n{{messages[0].snippet}}\n{{messages[0].body}}", + model: "openai/gpt-5.2-mini", + deliver: true, + channel: "last", + // to: "+15551234567" + }, + ], + }, +} +``` + +如果你想要固定渠道,请设置 `channel` + `to`。否则 `channel: "last"` 会使用最后的投递路由(回退到 WhatsApp)。 + +如需为 Gmail 运行强制使用更便宜的模型,在映射中设置 `model`(`provider/model` 或别名)。如果你设置了 `agents.defaults.models`,请将其包含在允许列表中。 + +如需专门为 Gmail hooks 设置默认模型和思维级别,在配置中添加 `hooks.gmail.model` / `hooks.gmail.thinking`: + +```json5 +{ + hooks: { + gmail: { + model: "openrouter/meta-llama/llama-3.3-70b-instruct:free", + thinking: "off", + }, + }, +} +``` + +说明: + +- 映射中每个 hook 的 `model`/`thinking` 仍会覆盖这些默认值。 +- 回退顺序:`hooks.gmail.model` → `agents.defaults.model.fallbacks` → 主模型(认证/速率限制/超时)。 +- 如果设置了 `agents.defaults.models`,Gmail 模型必须在允许列表中。 +- Gmail hook 内容默认使用外部内容安全边界进行包装。 + 如需禁用(危险),请设置 `hooks.gmail.allowUnsafeExternalContent: true`。 + +如需进一步自定义负载处理,可添加 `hooks.mappings` 或在 `hooks.transformsDir` 下添加 JS/TS 转换模块(参见 [Webhooks](/automation/webhook))。 + +## 向导(推荐) + +使用 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`。 + +需要自定义端点?使用 `--push-endpoint ` 或 `--tailscale off`。 + +平台说明:在 macOS 上,向导通过 Homebrew 安装 `gcloud`、`gogcli` 和 `tailscale`;在 Linux 上请先手动安装它们。 + +Gateway 自动启动(推荐): + +- 当 `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` + 自动续期): + +```bash +openclaw webhooks gmail run +``` + +## 一次性设置 + +1. 选择**拥有 `gog` 使用的 OAuth 客户端**的 GCP 项目。 + +```bash +gcloud auth login +gcloud config set project +``` + +注意:Gmail watch 要求 Pub/Sub 主题位于与 OAuth 客户端相同的项目中。 + +2. 启用 API: + +```bash +gcloud services enable gmail.googleapis.com pubsub.googleapis.com +``` + +3. 创建主题: + +```bash +gcloud pubsub topics create gog-gmail-watch +``` + +4. 允许 Gmail 推送发布: + +```bash +gcloud pubsub topics add-iam-policy-binding gog-gmail-watch \ + --member=serviceAccount:gmail-api-push@system.gserviceaccount.com \ + --role=roles/pubsub.publisher +``` + +## 启动 watch + +```bash +gog gmail watch start \ + --account openclaw@gmail.com \ + --label INBOX \ + --topic projects//topics/gog-gmail-watch +``` + +保存输出中的 `history_id`(用于调试)。 + +## 运行推送处理器 + +本地示例(共享令牌认证): + +```bash +gog gmail watch serve \ + --account openclaw@gmail.com \ + --bind 127.0.0.1 \ + --port 8788 \ + --path /gmail-pubsub \ + --token \ + --hook-url http://127.0.0.1:18789/hooks/gmail \ + --hook-token OPENCLAW_HOOK_TOKEN \ + --include-body \ + --max-bytes 20000 +``` + +说明: + +- `--token` 保护推送端点(`x-gog-token` 或 `?token=`)。 +- `--hook-url` 指向 OpenClaw `/hooks/gmail`(已映射;隔离运行 + 摘要发送到主会话)。 +- `--include-body` 和 `--max-bytes` 控制发送到 OpenClaw 的正文片段。 + +推荐:`openclaw webhooks gmail run` 封装了相同的流程并自动续期 watch。 + +## 暴露处理器(高级,不受支持) + +如果你需要非 Tailscale 隧道,请手动接线并在推送订阅中使用公共 URL(不受支持,无保护措施): + +```bash +cloudflared tunnel --url http://127.0.0.1:8788 --no-autoupdate +``` + +使用生成的 URL 作为推送端点: + +```bash +gcloud pubsub subscriptions create gog-gmail-watch-push \ + --topic gog-gmail-watch \ + --push-endpoint "https:///gmail-pubsub?token=" +``` + +生产环境:使用稳定的 HTTPS 端点并配置 Pub/Sub OIDC JWT,然后运行: + +```bash +gog gmail watch serve --verify-oidc --oidc-email +``` + +## 测试 + +向被监控的收件箱发送一封邮件: + +```bash +gog gmail send \ + --account openclaw@gmail.com \ + --to openclaw@gmail.com \ + --subject "watch test" \ + --body "ping" +``` + +检查 watch 状态和历史: + +```bash +gog gmail watch status --account openclaw@gmail.com +gog gmail history --account openclaw@gmail.com --since +``` + +## 故障排除 + +- `Invalid topicName`:项目不匹配(主题不在 OAuth 客户端项目中)。 +- `User not authorized`:主题缺少 `roles/pubsub.publisher` 权限。 +- 空消息:Gmail 推送仅提供 `historyId`;通过 `gog gmail history` 获取详情。 + +## 清理 + +```bash +gog gmail watch stop --account openclaw@gmail.com +gcloud pubsub subscriptions delete gog-gmail-watch-push +gcloud pubsub topics delete gog-gmail-watch +``` diff --git a/docs/zh-CN/automation/poll.md b/docs/zh-CN/automation/poll.md new file mode 100644 index 0000000000..33e68ba5a4 --- /dev/null +++ b/docs/zh-CN/automation/poll.md @@ -0,0 +1,75 @@ +--- +read_when: + - 添加或修改投票支持 + - 调试从 CLI 或 Gateway 发送的投票 +summary: 通过 Gateway + CLI 发送投票 +title: 投票 +x-i18n: + generated_at: "2026-02-01T19:38:57Z" + model: claude-opus-4-5 + provider: pi + source_hash: 760339865d27ec40def7996cac1d294d58ab580748ad6b32cc34d285d0314eaf + source_path: automation/poll.md + workflow: 14 +--- + +# 投票 + +## 支持的渠道 + +- WhatsApp(Web 渠道) +- Discord +- Microsoft Teams(Adaptive Cards) + +## CLI + +```bash +# WhatsApp +openclaw message poll --target +15555550123 \ + --poll-question "Lunch today?" --poll-option "Yes" --poll-option "No" --poll-option "Maybe" +openclaw message poll --target 123456789@g.us \ + --poll-question "Meeting time?" --poll-option "10am" --poll-option "2pm" --poll-option "4pm" --poll-multi + +# Discord +openclaw message poll --channel discord --target channel:123456789 \ + --poll-question "Snack?" --poll-option "Pizza" --poll-option "Sushi" +openclaw message poll --channel discord --target channel:123456789 \ + --poll-question "Plan?" --poll-option "A" --poll-option "B" --poll-duration-hours 48 + +# MS Teams +openclaw message poll --channel msteams --target conversation:19:abc@thread.tacv2 \ + --poll-question "Lunch?" --poll-option "Pizza" --poll-option "Sushi" +``` + +选项: + +- `--channel`:`whatsapp`(默认)、`discord` 或 `msteams` +- `--poll-multi`:允许选择多个选项 +- `--poll-duration-hours`:仅限 Discord(省略时默认为 24) + +## Gateway RPC + +方法:`poll` + +参数: + +- `to`(字符串,必填) +- `question`(字符串,必填) +- `options`(字符串数组,必填) +- `maxSelections`(数字,可选) +- `durationHours`(数字,可选) +- `channel`(字符串,可选,默认:`whatsapp`) +- `idempotencyKey`(字符串,必填) + +## 渠道差异 + +- WhatsApp:2-12 个选项,`maxSelections` 必须在选项数量范围内,忽略 `durationHours`。 +- Discord:2-10 个选项,`durationHours` 限制在 1-768 小时(默认 24)。`maxSelections > 1` 启用多选;Discord 不支持严格的选择数量限制。 +- Microsoft Teams:Adaptive Card 投票(由 OpenClaw 管理)。没有原生投票 API;`durationHours` 被忽略。 + +## 智能体工具(Message) + +使用 `message` 工具的 `poll` 操作(`to`、`pollQuestion`、`pollOption`,可选 `pollMulti`、`pollDurationHours`、`channel`)。 + +注意:Discord 没有"精确选择 N 个"模式;`pollMulti` 映射为多选。 +Teams 投票以 Adaptive Cards 形式渲染,需要 Gateway 保持在线以在 `~/.openclaw/msteams-polls.json` 中记录投票结果。 diff --git a/docs/zh-CN/automation/webhook.md b/docs/zh-CN/automation/webhook.md new file mode 100644 index 0000000000..d06bc70d8f --- /dev/null +++ b/docs/zh-CN/automation/webhook.md @@ -0,0 +1,163 @@ +--- +read_when: + - 添加或修改 webhook 端点 + - 将外部系统接入 OpenClaw +summary: 用于唤醒和隔离式智能体运行的 Webhook 入口 +title: Webhooks +x-i18n: + generated_at: "2026-02-01T19:39:20Z" + model: claude-opus-4-5 + provider: pi + source_hash: f26b88864567be82366b1f66a4772ef2813c7846110c62fce6caf7313568265e + source_path: automation/webhook.md + workflow: 14 +--- + +# Webhooks + +Gateway 可以暴露一个小型 HTTP webhook 端点用于外部触发。 + +## 启用 + +```json5 +{ + hooks: { + enabled: true, + token: "shared-secret", + path: "/hooks", + }, +} +``` + +说明: + +- 当 `hooks.enabled=true` 时,`hooks.token` 为必填项。 +- `hooks.path` 默认为 `/hooks`。 + +## 认证 + +每个请求必须包含 hook 令牌。推荐使用请求头: + +- `Authorization: Bearer `(推荐) +- `x-openclaw-token: ` +- `?token=`(已弃用;会记录警告,将在未来的主要版本中移除) + +## 端点 + +### `POST /hooks/wake` + +请求体: + +```json +{ "text": "System line", "mode": "now" } +``` + +- `text` **必填**(字符串):事件描述(例如 "New email received")。 +- `mode` 可选(`now` | `next-heartbeat`):是否触发立即心跳(默认 `now`)或等待下一次周期性检查。 + +效果: + +- 为**主**会话入队一个系统事件 +- 如果 `mode=now`,触发立即心跳 + +### `POST /hooks/agent` + +请求体: + +```json +{ + "message": "Run this", + "name": "Email", + "sessionKey": "hook:email:msg-123", + "wakeMode": "now", + "deliver": true, + "channel": "last", + "to": "+15551234567", + "model": "openai/gpt-5.2-mini", + "thinking": "low", + "timeoutSeconds": 120 +} +``` + +- `message` **必填**(字符串):智能体处理的提示或消息。 +- `name` 可选(字符串):hook 的人类可读名称(例如 "GitHub"),用作会话摘要的前缀。 +- `sessionKey` 可选(字符串):用于标识智能体会话的键。默认为随机的 `hook:`。使用一致的键可以在 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、Microsoft Teams 的会话 ID)。默认为主会话中的最后一个接收方。 +- `model` 可选(字符串):模型覆盖(例如 `anthropic/claude-3-5-sonnet` 或别名)。如果有模型限制,必须在允许的模型列表中。 +- `thinking` 可选(字符串):思维级别覆盖(例如 `low`、`medium`、`high`)。 +- `timeoutSeconds` 可选(数字):智能体运行的最大持续时间(秒)。 + +效果: + +- 运行一次**隔离式**智能体轮次(使用独立的会话键) +- 始终将摘要发布到**主**会话 +- 如果 `wakeMode=now`,触发立即心跳 + +### `POST /hooks/`(映射) + +自定义 hook 名称通过 `hooks.mappings` 解析(参见配置)。映射可以将任意请求体转换为 `wake` 或 `agent` 操作,并支持可选的模板或代码转换。 + +映射选项(概要): + +- `hooks.presets: ["gmail"]` 启用内置的 Gmail 映射。 +- `hooks.mappings` 允许你在配置中定义 `match`、`action` 和模板。 +- `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 watch 流程请参阅 [Gmail Pub/Sub](/automation/gmail-pubsub)。 + +## 响应 + +- `200` 用于 `/hooks/wake` +- `202` 用于 `/hooks/agent`(异步运行已启动) +- `401` 认证失败 +- `400` 无效请求体 +- `413` 请求体过大 + +## 示例 + +```bash +curl -X POST http://127.0.0.1:18789/hooks/wake \ + -H 'Authorization: Bearer SECRET' \ + -H 'Content-Type: application/json' \ + -d '{"text":"New email received","mode":"now"}' +``` + +```bash +curl -X POST http://127.0.0.1:18789/hooks/agent \ + -H 'x-openclaw-token: SECRET' \ + -H 'Content-Type: application/json' \ + -d '{"message":"Summarize inbox","name":"Email","wakeMode":"next-heartbeat"}' +``` + +### 使用不同的模型 + +在 agent 请求体(或映射)中添加 `model` 以覆盖该次运行的模型: + +```bash +curl -X POST http://127.0.0.1:18789/hooks/agent \ + -H 'x-openclaw-token: SECRET' \ + -H 'Content-Type: application/json' \ + -d '{"message":"Summarize inbox","name":"Email","model":"openai/gpt-5.2-mini"}' +``` + +如果你设置了 `agents.defaults.models`,请确保覆盖的模型包含在其中。 + +```bash +curl -X POST http://127.0.0.1:18789/hooks/gmail \ + -H 'Authorization: Bearer SECRET' \ + -H 'Content-Type: application/json' \ + -d '{"source":"gmail","messages":[{"from":"Ada","subject":"Hello","snippet":"Hi"}]}' +``` + +## 安全 + +- 将 hook 端点限制在回环地址、tailnet 或受信任的反向代理之后。 +- 使用专用的 hook 令牌;不要复用 Gateway 认证令牌。 +- 避免在 webhook 日志中包含敏感的原始请求体。 +- Hook 请求体默认被视为不受信任的,并使用安全边界进行包装。如果你必须为特定 hook 禁用此功能,请在该 hook 的映射中设置 `allowUnsafeExternalContent: true`(危险)。 diff --git a/docs/zh-CN/bedrock.md b/docs/zh-CN/bedrock.md new file mode 100644 index 0000000000..823252ef97 --- /dev/null +++ b/docs/zh-CN/bedrock.md @@ -0,0 +1,170 @@ +--- +read_when: + - 你想在 OpenClaw 中使用 Amazon Bedrock 模型 + - 你需要为模型调用设置 AWS 凭证/区域 +summary: 在 OpenClaw 中使用 Amazon Bedrock(Converse API)模型 +title: Amazon Bedrock +x-i18n: + generated_at: "2026-02-01T19:39:40Z" + model: claude-opus-4-5 + provider: pi + source_hash: 318f1048451a1910b70522e2f7f9dfc87084de26d9e3938a29d372eed32244a8 + source_path: bedrock.md + workflow: 14 +--- + +# Amazon Bedrock + +OpenClaw 可以通过 pi‑ai 的 **Bedrock Converse** 流式提供商使用 **Amazon Bedrock** 模型。Bedrock 认证使用 **AWS SDK 默认凭证链**,而非 API 密钥。 + +## pi‑ai 支持的内容 + +- 提供商:`amazon-bedrock` +- API:`bedrock-converse-stream` +- 认证:AWS 凭证(环境变量、共享配置或实例角色) +- 区域:`AWS_REGION` 或 `AWS_DEFAULT_REGION`(默认:`us-east-1`) + +## 自动模型发现 + +如果检测到 AWS 凭证,OpenClaw 可以自动发现支持**流式传输**和**文本输出**的 Bedrock 模型。发现功能使用 `bedrock:ListFoundationModels`,并带有缓存(默认:1 小时)。 + +配置选项位于 `models.bedrockDiscovery` 下: + +```json5 +{ + models: { + bedrockDiscovery: { + enabled: true, + region: "us-east-1", + providerFilter: ["anthropic", "amazon"], + refreshInterval: 3600, + defaultContextWindow: 32000, + defaultMaxTokens: 4096, + }, + }, +} +``` + +说明: + +- 当 AWS 凭证存在时,`enabled` 默认为 `true`。 +- `region` 默认为 `AWS_REGION` 或 `AWS_DEFAULT_REGION`,然后是 `us-east-1`。 +- `providerFilter` 匹配 Bedrock 提供商名称(例如 `anthropic`)。 +- `refreshInterval` 单位为秒;设置为 `0` 可禁用缓存。 +- `defaultContextWindow`(默认:`32000`)和 `defaultMaxTokens`(默认:`4096`)用于发现的模型(如果你了解模型限制可以覆盖)。 + +## 设置(手动) + +1. 确保 AWS 凭证在 **Gateway 主机**上可用: + +```bash +export AWS_ACCESS_KEY_ID="AKIA..." +export AWS_SECRET_ACCESS_KEY="..." +export AWS_REGION="us-east-1" +# 可选: +export AWS_SESSION_TOKEN="..." +export AWS_PROFILE="your-profile" +# 可选(Bedrock API 密钥/Bearer 令牌): +export AWS_BEARER_TOKEN_BEDROCK="..." +``` + +2. 在配置中添加 Bedrock 提供商和模型(无需 `apiKey`): + +```json5 +{ + models: { + providers: { + "amazon-bedrock": { + baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com", + api: "bedrock-converse-stream", + auth: "aws-sdk", + models: [ + { + id: "anthropic.claude-opus-4-5-20251101-v1:0", + name: "Claude Opus 4.5 (Bedrock)", + reasoning: true, + input: ["text", "image"], + cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, + contextWindow: 200000, + maxTokens: 8192, + }, + ], + }, + }, + }, + agents: { + defaults: { + model: { primary: "amazon-bedrock/anthropic.claude-opus-4-5-20251101-v1:0" }, + }, + }, +} +``` + +## EC2 实例角色 + +在附加了 IAM 角色的 EC2 实例上运行 OpenClaw 时,AWS SDK 会自动使用实例元数据服务(IMDS)进行认证。但是,OpenClaw 的凭证检测目前仅检查环境变量,不检查 IMDS 凭证。 + +**解决方法:** 设置 `AWS_PROFILE=default` 以表明 AWS 凭证可用。实际认证仍通过 IMDS 使用实例角色。 + +```bash +# 添加到 ~/.bashrc 或你的 shell 配置文件 +export AWS_PROFILE=default +export AWS_REGION=us-east-1 +``` + +EC2 实例角色**所需的 IAM 权限**: + +- `bedrock:InvokeModel` +- `bedrock:InvokeModelWithResponseStream` +- `bedrock:ListFoundationModels`(用于自动发现) + +或附加托管策略 `AmazonBedrockFullAccess`。 + +**快速设置:** + +```bash +# 1. 创建 IAM 角色和实例配置文件 +aws iam create-role --role-name EC2-Bedrock-Access \ + --assume-role-policy-document '{ + "Version": "2012-10-17", + "Statement": [{ + "Effect": "Allow", + "Principal": {"Service": "ec2.amazonaws.com"}, + "Action": "sts:AssumeRole" + }] + }' + +aws iam attach-role-policy --role-name EC2-Bedrock-Access \ + --policy-arn arn:aws:iam::aws:policy/AmazonBedrockFullAccess + +aws iam create-instance-profile --instance-profile-name EC2-Bedrock-Access +aws iam add-role-to-instance-profile \ + --instance-profile-name EC2-Bedrock-Access \ + --role-name EC2-Bedrock-Access + +# 2. 附加到你的 EC2 实例 +aws ec2 associate-iam-instance-profile \ + --instance-id i-xxxxx \ + --iam-instance-profile Name=EC2-Bedrock-Access + +# 3. 在 EC2 实例上启用发现 +openclaw config set models.bedrockDiscovery.enabled true +openclaw config set models.bedrockDiscovery.region us-east-1 + +# 4. 设置解决方法的环境变量 +echo 'export AWS_PROFILE=default' >> ~/.bashrc +echo 'export AWS_REGION=us-east-1' >> ~/.bashrc +source ~/.bashrc + +# 5. 验证模型已被发现 +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 链。 +- 推理支持取决于模型;请查看 Bedrock 模型卡了解当前功能。 +- 如果你偏好托管密钥流程,也可以在 Bedrock 前面放置一个兼容 OpenAI 的代理,将其配置为 OpenAI 提供商。 diff --git a/docs/zh-CN/brave-search.md b/docs/zh-CN/brave-search.md new file mode 100644 index 0000000000..80d7521c37 --- /dev/null +++ b/docs/zh-CN/brave-search.md @@ -0,0 +1,48 @@ +--- +read_when: + - 你想使用 Brave Search 进行 web_search + - 你需要 BRAVE_API_KEY 或套餐详情 +summary: 为 web_search 设置 Brave Search API +title: Brave Search +x-i18n: + generated_at: "2026-02-01T19:39:45Z" + model: claude-opus-4-5 + provider: pi + source_hash: cdcb037b092b8a10609f02acf062b4164cb826ac22bdb3fb2909c842a1405341 + source_path: brave-search.md + workflow: 14 +--- + +# Brave Search API + +OpenClaw 使用 Brave Search 作为 `web_search` 的默认提供商。 + +## 获取 API 密钥 + +1. 在 https://brave.com/search/api/ 创建 Brave Search API 账户。 +2. 在控制面板中,选择 **Data for Search** 套餐并生成 API 密钥。 +3. 将密钥存储在配置中(推荐)或在 Gateway 环境中设置 `BRAVE_API_KEY`。 + +## 配置示例 + +```json5 +{ + tools: { + web: { + search: { + provider: "brave", + apiKey: "BRAVE_API_KEY_HERE", + maxResults: 5, + timeoutSeconds: 30, + }, + }, + }, +} +``` + +## 说明 + +- Data for AI 套餐与 `web_search` **不**兼容。 +- Brave 提供免费套餐和付费套餐;请查看 Brave API 门户了解当前限制。 + +完整的 web_search 配置请参阅 [Web 工具](/tools/web)。 diff --git a/docs/zh-CN/broadcast-groups.md b/docs/zh-CN/broadcast-groups.md new file mode 100644 index 0000000000..d5c9320ff4 --- /dev/null +++ b/docs/zh-CN/broadcast-groups.md @@ -0,0 +1,449 @@ +--- +read_when: + - 配置广播群组 + - 调试 WhatsApp 中的多智能体回复 +status: experimental +summary: 将 WhatsApp 消息广播给多个智能体 +title: 广播群组 +x-i18n: + generated_at: "2026-02-01T19:40:25Z" + model: claude-opus-4-5 + provider: pi + source_hash: eaeb4035912c49413e012177cf0bd28b348130d30d3317674418dca728229b70 + source_path: broadcast-groups.md + workflow: 14 +--- + +# 广播群组 + +**状态:** 实验性 +**版本:** 在 2026.1.9 中添加 + +## 概述 + +广播群组允许多个智能体同时处理和回复同一条消息。这使你可以创建在单个 WhatsApp 群组或私聊中协同工作的专业智能体团队——全部使用同一个电话号码。 + +当前范围:**仅限 WhatsApp**(Web 渠道)。 + +广播群组在渠道允许列表和群组激活规则之后进行评估。在 WhatsApp 群组中,这意味着广播发生在 OpenClaw 正常回复的时机(例如:被提及时,取决于你的群组设置)。 + +## 使用场景 + +### 1. 专业智能体团队 + +部署多个具有原子化、专注职责的智能体: + +``` +群组:"Development Team" +智能体: + - CodeReviewer(审查代码片段) + - DocumentationBot(生成文档) + - SecurityAuditor(检查漏洞) + - TestGenerator(建议测试用例) +``` + +每个智能体处理同一条消息并提供其专业视角。 + +### 2. 多语言支持 + +``` +群组:"International Support" +智能体: + - Agent_EN(用英语回复) + - Agent_DE(用德语回复) + - Agent_ES(用西班牙语回复) +``` + +### 3. 质量保证工作流 + +``` +群组:"Customer Support" +智能体: + - SupportAgent(提供回答) + - QAAgent(审查质量,仅在发现问题时回复) +``` + +### 4. 任务自动化 + +``` +群组:"Project Management" +智能体: + - TaskTracker(更新任务数据库) + - TimeLogger(记录时间消耗) + - ReportGenerator(创建摘要) +``` + +## 配置 + +### 基本设置 + +添加顶层 `broadcast` 部分(与 `bindings` 同级)。键为 WhatsApp peer ID: + +- 群聊:群组 JID(例如 `120363403215116621@g.us`) +- 私聊:E.164 格式电话号码(例如 `+15551234567`) + +```json +{ + "broadcast": { + "120363403215116621@g.us": ["alfred", "baerbel", "assistant3"] + } +} +``` + +**效果:** 当 OpenClaw 在此聊天中回复时,它会运行所有三个智能体。 + +### 处理策略 + +控制智能体如何处理消息: + +#### 并行(默认) + +所有智能体同时处理: + +```json +{ + "broadcast": { + "strategy": "parallel", + "120363403215116621@g.us": ["alfred", "baerbel"] + } +} +``` + +#### 顺序 + +智能体按顺序处理(每个等待前一个完成): + +```json +{ + "broadcast": { + "strategy": "sequential", + "120363403215116621@g.us": ["alfred", "baerbel"] + } +} +``` + +### 完整示例 + +```json +{ + "agents": { + "list": [ + { + "id": "code-reviewer", + "name": "Code Reviewer", + "workspace": "/path/to/code-reviewer", + "sandbox": { "mode": "all" } + }, + { + "id": "security-auditor", + "name": "Security Auditor", + "workspace": "/path/to/security-auditor", + "sandbox": { "mode": "all" } + }, + { + "id": "docs-generator", + "name": "Documentation Generator", + "workspace": "/path/to/docs-generator", + "sandbox": { "mode": "all" } + } + ] + }, + "broadcast": { + "strategy": "parallel", + "120363403215116621@g.us": ["code-reviewer", "security-auditor", "docs-generator"], + "120363424282127706@g.us": ["support-en", "support-de"], + "+15555550123": ["assistant", "logger"] + } +} +``` + +## 工作原理 + +### 消息流程 + +1. **收到消息**,来自 WhatsApp 群组 +2. **广播检查**:系统检查 peer ID 是否在 `broadcast` 中 +3. **如果在广播列表中**: + - 所有列出的智能体处理该消息 + - 每个智能体有自己的会话键和隔离的上下文 + - 智能体并行(默认)或顺序处理 +4. **如果不在广播列表中**: + - 应用正常路由(第一个匹配的绑定) + +注意:广播群组不会绕过渠道允许列表或群组激活规则(提及/命令等)。它们仅在消息符合处理条件时改变*哪些智能体运行*。 + +### 会话隔离 + +广播群组中的每个智能体维护完全独立的: + +- **会话键**(`agent:alfred:whatsapp:group:120363...` 与 `agent:baerbel:whatsapp:group:120363...`) +- **对话历史**(智能体看不到其他智能体的消息) +- **工作区**(如果配置了则为独立沙箱) +- **工具访问**(不同的允许/拒绝列表) +- **记忆/上下文**(独立的 IDENTITY.md、SOUL.md 等) +- **群组上下文缓冲区**(用于上下文的最近群组消息)按 peer 共享,因此所有广播智能体在触发时看到相同的上下文 + +这使得每个智能体可以拥有: + +- 不同的个性 +- 不同的工具访问权限(例如只读与读写) +- 不同的模型(例如 opus 与 sonnet) +- 不同的已安装技能 + +### 示例:隔离会话 + +在群组 `120363403215116621@g.us` 中,智能体为 `["alfred", "baerbel"]`: + +**Alfred 的上下文:** + +``` +会话:agent:alfred:whatsapp:group:120363403215116621@g.us +历史:[用户消息,alfred 之前的回复] +工作区:/Users/pascal/openclaw-alfred/ +工具:read、write、exec +``` + +**Bärbel 的上下文:** + +``` +会话:agent:baerbel:whatsapp:group:120363403215116621@g.us +历史:[用户消息,baerbel 之前的回复] +工作区:/Users/pascal/openclaw-baerbel/ +工具:仅 read +``` + +## 最佳实践 + +### 1. 保持智能体专注 + +为每个智能体设计单一、明确的职责: + +```json +{ + "broadcast": { + "DEV_GROUP": ["formatter", "linter", "tester"] + } +} +``` + +✅ **好的做法:** 每个智能体只有一项工作 +❌ **不好的做法:** 一个通用的 "dev-helper" 智能体 + +### 2. 使用描述性名称 + +让每个智能体的功能一目了然: + +```json +{ + "agents": { + "security-scanner": { "name": "Security Scanner" }, + "code-formatter": { "name": "Code Formatter" }, + "test-generator": { "name": "Test Generator" } + } +} +``` + +### 3. 配置不同的工具访问权限 + +只给智能体它们需要的工具: + +```json +{ + "agents": { + "reviewer": { + "tools": { "allow": ["read", "exec"] } // 只读 + }, + "fixer": { + "tools": { "allow": ["read", "write", "edit", "exec"] } // 读写 + } + } +} +``` + +### 4. 监控性能 + +当智能体数量较多时,请考虑: + +- 使用 `"strategy": "parallel"`(默认)以提高速度 +- 将广播群组限制在 5-10 个智能体 +- 为较简单的智能体使用更快的模型 + +### 5. 优雅处理失败 + +智能体独立失败。一个智能体的错误不会阻塞其他智能体: + +``` +消息 → [智能体 A ✓, 智能体 B ✗ 错误, 智能体 C ✓] +结果:智能体 A 和 C 回复,智能体 B 记录错误 +``` + +## 兼容性 + +### 提供商 + +广播群组目前支持: + +- ✅ WhatsApp(已实现) +- 🚧 Telegram(计划中) +- 🚧 Discord(计划中) +- 🚧 Slack(计划中) + +### 路由 + +广播群组与现有路由并行工作: + +```json +{ + "bindings": [ + { + "match": { "channel": "whatsapp", "peer": { "kind": "group", "id": "GROUP_A" } }, + "agentId": "alfred" + } + ], + "broadcast": { + "GROUP_B": ["agent1", "agent2"] + } +} +``` + +- `GROUP_A`:仅 alfred 回复(正常路由) +- `GROUP_B`:agent1 和 agent2 都回复(广播) + +**优先级:** `broadcast` 优先于 `bindings`。 + +## 故障排除 + +### 智能体没有回复 + +**检查:** + +1. 智能体 ID 存在于 `agents.list` 中 +2. Peer ID 格式正确(例如 `120363403215116621@g.us`) +3. 智能体不在拒绝列表中 + +**调试:** + +```bash +tail -f ~/.openclaw/logs/gateway.log | grep broadcast +``` + +### 仅一个智能体回复 + +**原因:** Peer ID 可能在 `bindings` 中但不在 `broadcast` 中。 + +**修复:** 添加到广播配置中或从 bindings 中移除。 + +### 性能问题 + +**如果智能体较多时速度慢:** + +- 减少每个群组的智能体数量 +- 使用更轻量的模型(sonnet 而非 opus) +- 检查沙箱启动时间 + +## 示例 + +### 示例 1:代码审查团队 + +```json +{ + "broadcast": { + "strategy": "parallel", + "120363403215116621@g.us": [ + "code-formatter", + "security-scanner", + "test-coverage", + "docs-checker" + ] + }, + "agents": { + "list": [ + { + "id": "code-formatter", + "workspace": "~/agents/formatter", + "tools": { "allow": ["read", "write"] } + }, + { + "id": "security-scanner", + "workspace": "~/agents/security", + "tools": { "allow": ["read", "exec"] } + }, + { + "id": "test-coverage", + "workspace": "~/agents/testing", + "tools": { "allow": ["read", "exec"] } + }, + { "id": "docs-checker", "workspace": "~/agents/docs", "tools": { "allow": ["read"] } } + ] + } +} +``` + +**用户发送:** 代码片段 +**回复:** + +- code-formatter:"已修复缩进并添加了类型提示" +- security-scanner:"⚠️ 第 12 行存在 SQL 注入漏洞" +- test-coverage:"覆盖率为 45%,缺少错误情况的测试" +- docs-checker:"函数 `process_data` 缺少文档字符串" + +### 示例 2:多语言支持 + +```json +{ + "broadcast": { + "strategy": "sequential", + "+15555550123": ["detect-language", "translator-en", "translator-de"] + }, + "agents": { + "list": [ + { "id": "detect-language", "workspace": "~/agents/lang-detect" }, + { "id": "translator-en", "workspace": "~/agents/translate-en" }, + { "id": "translator-de", "workspace": "~/agents/translate-de" } + ] + } +} +``` + +## API 参考 + +### 配置模式 + +```typescript +interface OpenClawConfig { + broadcast?: { + strategy?: "parallel" | "sequential"; + [peerId: string]: string[]; + }; +} +``` + +### 字段 + +- `strategy`(可选):智能体的处理方式 + - `"parallel"`(默认):所有智能体同时处理 + - `"sequential"`:智能体按数组顺序处理 +- `[peerId]`:WhatsApp 群组 JID、E.164 号码或其他 peer ID + - 值:应处理消息的智能体 ID 数组 + +## 限制 + +1. **最大智能体数:** 无硬性限制,但 10 个以上可能会变慢 +2. **共享上下文:** 智能体看不到彼此的回复(设计如此) +3. **消息排序:** 并行回复可能以任意顺序到达 +4. **速率限制:** 所有智能体共同计入 WhatsApp 速率限制 + +## 未来增强 + +计划中的功能: + +- [ ] 共享上下文模式(智能体可以看到彼此的回复) +- [ ] 智能体协调(智能体可以互相通信) +- [ ] 动态智能体选择(根据消息内容选择智能体) +- [ ] 智能体优先级(某些智能体先于其他智能体回复) + +## 另请参阅 + +- [多智能体配置](/multi-agent-sandbox-tools) +- [路由配置](/concepts/channel-routing) +- [会话管理](/concepts/sessions) diff --git a/docs/zh-CN/channels/bluebubbles.md b/docs/zh-CN/channels/bluebubbles.md new file mode 100644 index 0000000000..8fa0ace905 --- /dev/null +++ b/docs/zh-CN/channels/bluebubbles.md @@ -0,0 +1,271 @@ +--- +read_when: + - 设置 BlueBubbles 渠道 + - 排查 webhook 配对问题 + - 在 macOS 上配置 iMessage +summary: 通过 BlueBubbles macOS 服务器集成 iMessage(REST 发送/接收、输入状态、回应、配对、高级操作)。 +title: BlueBubbles +x-i18n: + generated_at: "2026-02-01T19:41:18Z" + model: claude-opus-4-5 + provider: pi + source_hash: ac9a9d71f3bbc661da6cb2897ea32d290bbd16b35925250601cfff53bc85de8c + source_path: channels/bluebubbles.md + workflow: 14 +--- + +# BlueBubbles(macOS REST) + +状态:内置插件,通过 HTTP 与 BlueBubbles macOS 服务器通信。**推荐用于 iMessage 集成**,因为相比旧版 imsg 渠道,其 API 更丰富且更易于设置。 + +## 概述 + +- 通过 BlueBubbles 辅助应用在 macOS 上运行([bluebubbles.app](https://bluebubbles.app))。 +- 推荐/已测试:macOS Sequoia (15)。macOS Tahoe (26) 可用;编辑功能目前在 Tahoe 上不可用,群组图标更新可能报告成功但不会同步。 +- OpenClaw 通过其 REST API 与之通信(`GET /api/v1/ping`、`POST /message/text`、`POST /chat/:id/*`)。 +- 收到的消息通过 webhooks 到达;发出的回复、输入指示器、已读回执和 tapback 回应均为 REST 调用。 +- 附件和贴纸作为入站媒体被接收(在可能的情况下呈现给智能体)。 +- 配对/允许列表与其他渠道的工作方式相同(`/start/pairing` 等),使用 `channels.bluebubbles.allowFrom` + 配对码。 +- 回应作为系统事件呈现,与 Slack/Telegram 相同,因此智能体可以在回复前"提及"它们。 +- 高级功能:编辑、撤回、回复线程、消息特效、群组管理。 + +## 快速开始 + +1. 在你的 Mac 上安装 BlueBubbles 服务器(按照 [bluebubbles.app/install](https://bluebubbles.app/install) 的说明操作)。 +2. 在 BlueBubbles 配置中,启用 Web API 并设置密码。 +3. 运行 `openclaw onboard` 并选择 BlueBubbles,或手动配置: + ```json5 + { + channels: { + bluebubbles: { + enabled: true, + serverUrl: "http://192.168.1.100:1234", + password: "example-password", + webhookPath: "/bluebubbles-webhook", + }, + }, + } + ``` +4. 将 BlueBubbles webhooks 指向你的 Gateway(示例:`https://your-gateway-host:3000/bluebubbles-webhook?password=`)。 +5. 启动 Gateway;它将注册 webhook 处理器并开始配对。 + +## 上手引导 + +BlueBubbles 可在交互式设置向导中使用: + +``` +openclaw onboard +``` + +向导会提示输入: + +- **服务器 URL**(必填):BlueBubbles 服务器地址(例如 `http://192.168.1.100:1234`) +- **密码**(必填):来自 BlueBubbles 服务器设置的 API 密码 +- **Webhook 路径**(可选):默认为 `/bluebubbles-webhook` +- **私聊策略**:配对、允许列表、开放或禁用 +- **允许列表**:电话号码、邮箱或聊天目标 + +你也可以通过 CLI 添加 BlueBubbles: + +``` +openclaw channels add bluebubbles --http-url http://192.168.1.100:1234 --password +``` + +## 访问控制(私聊 + 群组) + +私聊: + +- 默认:`channels.bluebubbles.dmPolicy = "pairing"`。 +- 未知发送者会收到配对码;消息在批准前会被忽略(配对码 1 小时后过期)。 +- 通过以下方式批准: + - `openclaw pairing list bluebubbles` + - `openclaw pairing approve bluebubbles ` +- 配对是默认的令牌交换方式。详情:[配对](/start/pairing) + +群组: + +- `channels.bluebubbles.groupPolicy = open | allowlist | disabled`(默认:`allowlist`)。 +- 当设置为 `allowlist` 时,`channels.bluebubbles.groupAllowFrom` 控制谁可以在群组中触发。 + +### 提及门控(群组) + +BlueBubbles 支持群聊的提及门控,与 iMessage/WhatsApp 行为一致: + +- 使用 `agents.list[].groupChat.mentionPatterns`(或 `messages.groupChat.mentionPatterns`)检测提及。 +- 当群组启用 `requireMention` 时,智能体仅在被提及时回复。 +- 来自授权发送者的控制命令会绕过提及门控。 + +按群组配置: + +```json5 +{ + channels: { + bluebubbles: { + groupPolicy: "allowlist", + groupAllowFrom: ["+15555550123"], + groups: { + "*": { requireMention: true }, // 所有群组的默认值 + "iMessage;-;chat123": { requireMention: false }, // 针对特定群组的覆盖 + }, + }, + }, +} +``` + +### 命令门控 + +- 控制命令(例如 `/config`、`/model`)需要授权。 +- 使用 `allowFrom` 和 `groupAllowFrom` 来确定命令授权。 +- 授权发送者即使在群组中未提及也可以运行控制命令。 + +## 输入状态 + 已读回执 + +- **输入指示器**:在生成回复前和生成过程中自动发送。 +- **已读回执**:由 `channels.bluebubbles.sendReadReceipts` 控制(默认:`true`)。 +- **输入指示器**:OpenClaw 发送输入开始事件;BlueBubbles 在发送或超时时自动清除输入状态(通过 DELETE 手动停止不可靠)。 + +```json5 +{ + channels: { + bluebubbles: { + sendReadReceipts: false, // 禁用已读回执 + }, + }, +} +``` + +## 高级操作 + +在配置中启用后,BlueBubbles 支持高级消息操作: + +```json5 +{ + channels: { + bluebubbles: { + actions: { + reactions: true, // tapback 回应(默认:true) + edit: true, // 编辑已发送消息(macOS 13+,macOS 26 Tahoe 上不可用) + unsend: true, // 撤回消息(macOS 13+) + reply: true, // 按消息 GUID 回复线程 + sendWithEffect: true, // 消息特效(slam、loud 等) + renameGroup: true, // 重命名群聊 + setGroupIcon: true, // 设置群聊图标/头像(macOS 26 Tahoe 上不稳定) + addParticipant: true, // 向群组添加参与者 + removeParticipant: true, // 从群组移除参与者 + leaveGroup: true, // 离开群聊 + sendAttachment: true, // 发送附件/媒体 + }, + }, + }, +} +``` + +可用操作: + +- **react**:添加/移除 tapback 回应(`messageId`、`emoji`、`remove`) +- **edit**:编辑已发送的消息(`messageId`、`text`) +- **unsend**:撤回消息(`messageId`) +- **reply**:回复特定消息(`messageId`、`text`、`to`) +- **sendWithEffect**:使用 iMessage 特效发送(`text`、`to`、`effectId`) +- **renameGroup**:重命名群聊(`chatGuid`、`displayName`) +- **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。 + +### 消息 ID(短格式与完整格式) + +OpenClaw 可能会呈现*短*消息 ID(例如 `1`、`2`)以节省 token。 + +- `MessageSid` / `ReplyToId` 可以是短 ID。 +- `MessageSidFull` / `ReplyToIdFull` 包含提供商的完整 ID。 +- 短 ID 存储在内存中;它们可能在重启或缓存清除后过期。 +- 操作接受短格式或完整格式的 `messageId`,但如果短 ID 不再可用则会报错。 + +对于持久化自动化和存储,请使用完整 ID: + +- 模板:`{{MessageSidFull}}`、`{{ReplyToIdFull}}` +- 上下文:入站负载中的 `MessageSidFull` / `ReplyToIdFull` + +模板变量请参阅[配置](/gateway/configuration)。 + +## 分块流式传输 + +控制回复是作为单条消息发送还是分块流式传输: + +```json5 +{ + channels: { + bluebubbles: { + blockStreaming: true, // 启用分块流式传输(默认行为) + }, + }, +} +``` + +## 媒体 + 限制 + +- 入站附件会被下载并存储在媒体缓存中。 +- 媒体上限通过 `channels.bluebubbles.mediaMaxMb` 设置(默认:8 MB)。 +- 出站文本按 `channels.bluebubbles.textChunkLimit` 进行分块(默认:4000 字符)。 + +## 配置参考 + +完整配置:[配置](/gateway/configuration) + +提供商选项: + +- `channels.bluebubbles.enabled`:启用/禁用渠道。 +- `channels.bluebubbles.serverUrl`:BlueBubbles REST API 基础 URL。 +- `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.groupPolicy`:`open | allowlist | disabled`(默认:`allowlist`)。 +- `channels.bluebubbles.groupAllowFrom`:群组发送者允许列表。 +- `channels.bluebubbles.groups`:按群组配置(`requireMention` 等)。 +- `channels.bluebubbles.sendReadReceipts`:发送已读回执(默认:`true`)。 +- `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`:多账户配置。 + +相关全局选项: + +- `agents.list[].groupChat.mentionPatterns`(或 `messages.groupChat.mentionPatterns`)。 +- `messages.responsePrefix`。 + +## 寻址/投递目标 + +推荐使用 `chat_guid` 以实现稳定路由: + +- `chat_guid:iMessage;-;+15555550123`(群组推荐使用) +- `chat_id:123` +- `chat_identifier:...` +- 直接句柄:`+15555550123`、`user@example.com` + - 如果直接句柄没有现有的私聊会话,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 + 防火墙规则。 + +## 故障排除 + +- 如果输入/已读事件停止工作,请检查 BlueBubbles webhook 日志并验证 Gateway 路径是否与 `channels.bluebubbles.webhookPath` 匹配。 +- 配对码在一小时后过期;使用 `openclaw pairing list bluebubbles` 和 `openclaw pairing approve bluebubbles `。 +- 回应功能需要 BlueBubbles private API(`POST /api/v1/message/react`);请确保服务器版本已暴露该接口。 +- 编辑/撤回需要 macOS 13+ 和兼容的 BlueBubbles 服务器版本。在 macOS 26(Tahoe)上,由于 private API 变更,编辑功能目前不可用。 +- 群组图标更新在 macOS 26(Tahoe)上可能不稳定:API 可能返回成功但新图标不会同步。 +- OpenClaw 会根据 BlueBubbles 服务器的 macOS 版本自动隐藏已知不可用的操作。如果编辑功能在 macOS 26(Tahoe)上仍然显示,请手动通过 `channels.bluebubbles.actions.edit=false` 禁用。 +- 查看状态/健康信息:`openclaw status --all` 或 `openclaw status --deep`。 + +通用渠道工作流参考请参阅[渠道](/channels)和[插件](/plugins)指南。 diff --git a/docs/zh-CN/channels/discord.md b/docs/zh-CN/channels/discord.md new file mode 100644 index 0000000000..ccc686d866 --- /dev/null +++ b/docs/zh-CN/channels/discord.md @@ -0,0 +1,463 @@ +--- +read_when: + - 开发 Discord 渠道功能 +summary: Discord 机器人支持状态、功能和配置 +title: Discord +x-i18n: + generated_at: "2026-02-01T19:19:25Z" + model: claude-opus-4-5 + provider: pi + source_hash: 44e44e855481a81557d9c205bacaa82efef528f8dba59a2c39c26aeb4f420c62 + source_path: channels/discord.md + workflow: 14 +--- + +# Discord(Bot API) + +状态:已可用于通过官方 Discord 机器人网关进行私信和服务器文字频道通信。 + +## 快速设置(新手) + +1. 创建一个 Discord 机器人并复制机器人 token。 +2. 在 Discord 应用设置中,启用 **Message Content Intent**(如果你计划使用允许列表或名称查找,还需启用 **Server Members Intent**)。 +3. 为 OpenClaw 设置 token: + - 环境变量:`DISCORD_BOT_TOKEN=...` + - 或配置:`channels.discord.token: "..."`。 + - 如果两者都设置了,配置优先(环境变量回退仅用于默认账户)。 +4. 邀请机器人到你的服务器并赋予消息权限(如果只想用私信可以创建一个私人服务器)。 +5. 启动 Gateway。 +6. 私信访问默认需要配对;首次联系时批准配对码即可。 + +最小配置: + +```json5 +{ + channels: { + discord: { + enabled: true, + token: "YOUR_BOT_TOKEN", + }, + }, +} +``` + +## 目标 + +- 通过 Discord 私信或服务器频道与 OpenClaw 对话。 +- 私聊合并到智能体的主会话(默认 `agent:main:main`);服务器频道作为 `agent::discord:channel:` 保持隔离(显示名称使用 `discord:#`)。 +- 群组私信默认被忽略;通过 `channels.discord.dm.groupEnabled` 启用,可选通过 `channels.discord.dm.groupChannels` 限制。 +- 保持路由确定性:回复始终发回消息到达的渠道。 + +## 工作原理 + +1. 创建 Discord 应用 → Bot,启用所需的 intent(私信 + 服务器消息 + 消息内容),获取机器人 token。 +2. 邀请机器人到你的服务器,赋予在你需要使用的地方读取/发送消息所需的权限。 +3. 使用 `channels.discord.token` 配置 OpenClaw(或使用 `DISCORD_BOT_TOKEN` 作为回退)。 +4. 运行 Gateway;当 token 可用(配置优先,环境变量回退)且 `channels.discord.enabled` 不为 `false` 时,它会自动启动 Discord 渠道。 + - 如果你偏好使用环境变量,设置 `DISCORD_BOT_TOKEN`(配置块是可选的)。 +5. 私聊:投递时使用 `user:`(或 `<@id>` 提及);所有回合都进入共享的 `main` 会话。裸数字 ID 具有歧义性,会被拒绝。 +6. 服务器频道:投递时使用 `channel:`。默认需要提及,可按服务器或按频道设置。 +7. 私聊:默认通过 `channels.discord.dm.policy`(默认:`"pairing"`)进行安全保护。未知发送者会收到配对码(1 小时后过期);通过 `openclaw pairing approve discord ` 批准。 + - 要保持旧的"对任何人开放"行为:设置 `channels.discord.dm.policy="open"` 和 `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` 可绕过命令的访问组检查。 + - 完整命令列表 + 配置:[斜杠命令](/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::discord:slash:`)而非共享的 `main` 会话。 + +注意:名称 → ID 解析使用服务器成员搜索,需要 Server Members Intent;如果机器人无法搜索成员,请使用 ID 或 `<@id>` 提及。 +注意:Slug 为小写且空格替换为 `-`。频道名称的 slug 不包含前导 `#`。 +注意:服务器上下文 `[from:]` 行包含 `author.tag` + `id`,方便进行可直接 ping 的回复。 + +## 配置写入 + +默认情况下,Discord 允许通过 `/config set|unset` 触发的配置更新写入(需要 `commands.config: true`)。 + +通过以下方式禁用: + +```json5 +{ + channels: { discord: { configWrites: false } }, +} +``` + +## 如何创建自己的机器人 + +这是在服务器(guild)频道(如 `#help`)中运行 OpenClaw 的"Discord 开发者门户"设置。 + +### 1) 创建 Discord 应用 + 机器人用户 + +1. Discord 开发者门户 → **Applications** → **New Application** +2. 在你的应用中: + - **Bot** → **Add Bot** + - 复制 **Bot Token**(这就是你放入 `DISCORD_BOT_TOKEN` 的值) + +### 2) 启用 OpenClaw 所需的网关 intent + +Discord 会阻止"特权 intent",除非你明确启用。 + +在 **Bot** → **Privileged Gateway Intents** 中,启用: + +- **Message Content Intent**(在大多数服务器中读取消息文本所必需;没有它你会看到"Used disallowed intents"或机器人会连接但不响应消息) +- **Server Members Intent**(推荐;某些成员/用户查找和服务器中的允许列表匹配所必需) + +通常你**不**需要 **Presence Intent**。 + +### 3) 生成邀请 URL(OAuth2 URL 生成器) + +在你的应用中:**OAuth2** → **URL Generator** + +**Scopes** + +- ✅ `bot` +- ✅ `applications.commands`(原生命令所必需) + +**Bot Permissions**(最小基线) + +- ✅ View Channels +- ✅ Send Messages +- ✅ Read Message History +- ✅ Embed Links +- ✅ Attach Files +- ✅ Add Reactions(可选但推荐) +- ✅ Use External Emojis / Stickers(可选;仅在你需要时) + +除非你在调试且完全信任机器人,否则避免使用 **Administrator**。 + +复制生成的 URL,打开它,选择你的服务器,安装机器人。 + +### 4) 获取 ID(服务器/用户/频道) + +Discord 到处使用数字 ID;OpenClaw 配置推荐使用 ID。 + +1. Discord(桌面/网页)→ **用户设置** → **高级** → 启用 **开发者模式** +2. 右键点击: + - 服务器名称 → **复制服务器 ID**(guild id) + - 频道(例如 `#help`)→ **复制频道 ID** + - 你的用户 → **复制用户 ID** + +### 5) 配置 OpenClaw + +#### Token + +通过环境变量设置机器人 token(推荐用于服务器): + +- `DISCORD_BOT_TOKEN=...` + +或通过配置: + +```json5 +{ + channels: { + discord: { + enabled: true, + token: "YOUR_BOT_TOKEN", + }, + }, +} +``` + +多账户支持:使用 `channels.discord.accounts`,每个账户配置独立的 token 和可选的 `name`。共享模式请参阅 [`gateway/configuration`](/gateway/configuration#telegramaccounts--discordaccounts--slackaccounts--signalaccounts--imessageaccounts)。 + +#### 允许列表 + 频道路由 + +示例"单服务器,只允许我,只允许 #help": + +```json5 +{ + channels: { + discord: { + enabled: true, + dm: { enabled: false }, + guilds: { + YOUR_GUILD_ID: { + users: ["YOUR_USER_ID"], + requireMention: true, + channels: { + help: { allow: true, requireMention: true }, + }, + }, + }, + retry: { + attempts: 3, + minDelayMs: 500, + maxDelayMs: 30000, + jitter: 0.1, + }, + }, + }, +} +``` + +注意事项: + +- `requireMention: true` 表示机器人仅在被提及时回复(推荐用于共享频道)。 +- `agents.list[].groupChat.mentionPatterns`(或 `messages.groupChat.mentionPatterns`)对服务器消息也算作提及。 +- 多智能体覆盖:在 `agents.list[].groupChat.mentionPatterns` 上设置每个智能体的模式。 +- 如果存在 `channels`,任何未列出的频道默认被拒绝。 +- 使用 `"*"` 频道条目来应用所有频道的默认值;明确的频道条目会覆盖通配符。 +- 帖子继承父频道配置(允许列表、`requireMention`、技能、提示等),除非你明确添加帖子频道 ID。 +- 机器人发送的消息默认被忽略;设置 `channels.discord.allowBots=true` 可允许它们(自己的消息仍然被过滤)。 +- 警告:如果你允许回复其他机器人(`channels.discord.allowBots=true`),请使用 `requireMention`、`channels.discord.guilds.*.channels..users` 允许列表和/或在 `AGENTS.md` 和 `SOUL.md` 中设置明确的防护规则来防止机器人之间的回复循环。 + +### 6) 验证是否正常工作 + +1. 启动 Gateway。 +2. 在你的服务器频道中,发送:`@Krill hello`(或你的机器人名称)。 +3. 如果没有响应:查看下方**故障排除**。 + +### 故障排除 + +- 首先:运行 `openclaw doctor` 和 `openclaw channels status --probe`(可操作的警告 + 快速审计)。 +- **"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..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"`)。 + +## 功能与限制 + +- 私信和服务器文字频道(帖子被视为独立频道;不支持语音)。 +- 输入指示尽力发送;消息分块使用 `channels.discord.textChunkLimit`(默认 2000)并按行数分割较长回复(`channels.discord.maxLinesPerMessage`,默认 17)。 +- 可选的换行分块:设置 `channels.discord.chunkMode="newline"` 在按长度分块之前按空行(段落边界)分割。 +- 支持文件上传,上限为配置的 `channels.discord.mediaMaxMb`(默认 8 MB)。 +- 服务器回复默认需要提及门控,以避免嘈杂的机器人。 +- 当消息引用另一条消息时,会注入回复上下文(引用内容 + ID)。 +- 原生回复线程**默认关闭**;通过 `channels.discord.replyToMode` 和回复标签启用。 + +## 重试策略 + +出站 Discord API 调用在速率限制(429)时使用 Discord 的 `retry_after`(如可用)进行重试,采用指数退避和抖动。通过 `channels.discord.retry` 配置。参见[重试策略](/concepts/retry)。 + +## 配置 + +```json5 +{ + channels: { + discord: { + enabled: true, + token: "abc.123", + groupPolicy: "allowlist", + guilds: { + "*": { + channels: { + general: { allow: true }, + }, + }, + }, + mediaMaxMb: 8, + actions: { + reactions: true, + stickers: true, + emojiUploads: true, + stickerUploads: true, + polls: true, + permissions: true, + messages: true, + threads: true, + pins: true, + search: true, + memberInfo: true, + roleInfo: true, + roles: false, + channelInfo: true, + channels: true, + voiceStatus: true, + events: true, + moderation: false, + }, + replyToMode: "off", + dm: { + enabled: true, + policy: "pairing", // pairing | allowlist | open | disabled + allowFrom: ["123456789012345678", "steipete"], + groupEnabled: false, + groupChannels: ["openclaw-dm"], + }, + guilds: { + "*": { requireMention: true }, + "123456789012345678": { + slug: "friends-of-openclaw", + requireMention: false, + reactionNotifications: "own", + users: ["987654321098765432", "steipete"], + channels: { + general: { allow: true }, + help: { + allow: true, + requireMention: true, + users: ["987654321098765432"], + skills: ["search", "docs"], + systemPrompt: "Keep answers short.", + }, + }, + }, + }, + }, + }, +} +``` + +确认回应由 `messages.ackReaction` + `messages.ackReactionScope` 全局控制。使用 `messages.removeAckAfterReply` 在机器人回复后清除确认回应。 + +- `dm.enabled`:设置 `false` 可忽略所有私信(默认 `true`)。 +- `dm.policy`:私信访问控制(推荐 `pairing`)。`"open"` 需要 `dm.allowFrom=["*"]`。 +- `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."*"`:当没有明确条目时应用的默认按服务器设置。 +- `guilds..slug`:用于显示名称的可选友好 slug。 +- `guilds..users`:可选的按服务器用户允许列表(ID 或名称)。 +- `guilds..tools`:可选的按服务器工具策略覆盖(`allow`/`deny`/`alsoAllow`),在频道覆盖缺失时使用。 +- `guilds..toolsBySender`:可选的按发送者工具策略覆盖(服务器级别,在频道覆盖缺失时应用;支持 `"*"` 通配符)。 +- `guilds..channels..allow`:当 `groupPolicy="allowlist"` 时允许/拒绝频道。 +- `guilds..channels..requireMention`:频道的提及门控。 +- `guilds..channels..tools`:可选的按频道工具策略覆盖(`allow`/`deny`/`alsoAllow`)。 +- `guilds..channels..toolsBySender`:可选的频道内按发送者工具策略覆盖(支持 `"*"` 通配符)。 +- `guilds..channels..users`:可选的按频道用户允许列表。 +- `guilds..channels..skills`:技能过滤器(省略 = 所有技能,空 = 无)。 +- `guilds..channels..systemPrompt`:频道的额外系统提示(与频道主题合并)。 +- `guilds..channels..enabled`:设置 `false` 可禁用频道。 +- `guilds..channels`:频道规则(键为频道 slug 或 ID)。 +- `guilds..requireMention`:按服务器的提及要求(可按频道覆盖)。 +- `guilds..reactionNotifications`:回应系统事件模式(`off`、`own`、`all`、`allowlist`)。 +- `textChunkLimit`:出站文本分块大小(字符)。默认:2000。 +- `chunkMode`:`length`(默认)仅在超过 `textChunkLimit` 时分割;`newline` 在按长度分块之前按空行(段落边界)分割。 +- `maxLinesPerMessage`:每条消息的软最大行数。默认:17。 +- `mediaMaxMb`:限制保存到磁盘的入站媒体大小。 +- `historyLimit`:回复提及时包含的最近服务器消息数作为上下文(默认 20;回退到 `messages.groupChat.historyLimit`;`0` 禁用)。 +- `dmHistoryLimit`:私信历史限制(用户回合数)。按用户覆盖:`dms[""].historyLimit`。 +- `retry`:出站 Discord API 调用的重试策略(attempts、minDelayMs、maxDelayMs、jitter)。 +- `pluralkit`:解析 PluralKit 代理消息,使系统成员显示为不同的发送者。 +- `actions`:按操作的工具门控;省略则允许所有(设置 `false` 可禁用)。 + - `reactions`(涵盖添加回应 + 读取回应) + - `stickers`、`emojiUploads`、`stickerUploads`、`polls`、`permissions`、`messages`、`threads`、`pins`、`search` + - `memberInfo`、`roleInfo`、`channelInfo`、`voiceStatus`、`events` + - `channels`(创建/编辑/删除频道 + 分类 + 权限) + - `roles`(角色添加/移除,默认 `false`) + - `moderation`(超时/踢出/封禁,默认 `false`) + +回应通知使用 `guilds..reactionNotifications`: + +- `off`:无回应事件。 +- `own`:机器人自己消息上的回应(默认)。 +- `all`:所有消息上的所有回应。 +- `allowlist`:来自 `guilds..users` 的用户在所有消息上的回应(空列表则禁用)。 + +### PluralKit(PK)支持 + +启用 PK 查找,使代理消息解析为底层的系统 + 成员。启用后,OpenClaw 使用成员身份进行允许列表匹配,并将发送者标记为 `Member (PK:System)` 以避免意外的 Discord ping。 + +```json5 +{ + channels: { + discord: { + pluralkit: { + enabled: true, + token: "pk_live_...", // 可选;私有系统需要 + }, + }, + }, +} +``` + +允许列表注意事项(启用 PK 时): + +- 在 `dm.allowFrom`、`guilds..users` 或按频道的 `users` 中使用 `pk:`。 +- 成员显示名称也通过名称/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 | 禁用 | 超时/踢出/封禁 | + +- `replyToMode`:`off`(默认)、`first` 或 `all`。仅在模型输出包含回复标签时生效。 + +## 回复标签 + +要请求线程回复,模型可以在输出中包含一个标签: + +- `[[reply_to_current]]` — 回复触发的 Discord 消息。 +- `[[reply_to:]]` — 回复上下文/历史中的特定消息 ID。 + 当前消息 ID 以 `[message_id: …]` 附加到提示中;历史条目已包含 ID。 + +行为由 `channels.discord.replyToMode` 控制: + +- `off`:忽略标签。 +- `first`:仅第一个出站分块/附件作为回复。 +- `all`:每个出站分块/附件都作为回复。 + +允许列表匹配注意事项: + +- `allowFrom`/`users`/`groupChannels` 接受 ID、名称、标签或 `<@id>` 格式的提及。 +- 支持 `discord:`/`user:`(用户)和 `channel:`(群组私信)等前缀。 +- 使用 `*` 允许任何发送者/频道。 +- 当存在 `guilds..channels` 时,未列出的频道默认被拒绝。 +- 当省略 `guilds..channels` 时,允许列表中服务器的所有频道都被允许。 +- 要**不允许任何频道**,设置 `channels.discord.groupPolicy: "disabled"`(或保持空的允许列表)。 +- 配置向导接受 `Guild/Channel` 名称(公共 + 私有)并在可能时将其解析为 ID。 +- 启动时,OpenClaw 将允许列表中的频道/用户名称解析为 ID(当机器人可以搜索成员时)并记录映射;未解析的条目保持原样。 + +原生命令注意事项: + +- 注册的命令与 OpenClaw 的聊天命令一致。 +- 原生命令遵循与私信/服务器消息相同的允许列表(`channels.discord.dm.allowFrom`、`channels.discord.guilds`、按频道规则)。 +- 斜杠命令在 Discord UI 中可能对不在允许列表中的用户仍然可见;OpenClaw 在执行时强制执行允许列表并回复"未授权"。 + +## 工具操作 + +智能体可以调用 `discord` 执行以下操作: + +- `react` / `reactions`(添加或列出回应) +- `sticker`、`poll`、`permissions` +- `readMessages`、`sendMessage`、`editMessage`、`deleteMessage` +- 读取/搜索/置顶工具的负载包含标准化的 `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: …]` 和历史行),方便智能体定位它们。 +表情可以是 unicode(例如 `✅`)或自定义表情语法如 `<:party_blob:1234567890>`。 + +## 安全与运维 + +- 将机器人 token 视为密码;在受管主机上推荐使用 `DISCORD_BOT_TOKEN` 环境变量或锁定配置文件权限。 +- 仅授予机器人所需的权限(通常是读取/发送消息)。 +- 如果机器人卡住或被速率限制,在确认没有其他进程占用 Discord 会话后重启 Gateway(`openclaw gateway --force`)。 diff --git a/docs/zh-CN/channels/googlechat.md b/docs/zh-CN/channels/googlechat.md new file mode 100644 index 0000000000..24eebf9926 --- /dev/null +++ b/docs/zh-CN/channels/googlechat.md @@ -0,0 +1,257 @@ +--- +read_when: + - 开发 Google Chat 渠道功能 +summary: Google Chat 应用支持状态、功能和配置 +title: Google Chat +x-i18n: + generated_at: "2026-02-01T19:20:03Z" + model: claude-opus-4-5 + provider: pi + source_hash: 3b2bb116cdd12614c3d5afddd0879e9deb05c3606e3a2385cbc07f23552b357e + source_path: channels/googlechat.md + workflow: 14 +--- + +# Google Chat(Chat API) + +状态:已可通过 Google Chat API webhook(仅 HTTP)用于私信和空间。 + +## 快速设置(新手) + +1. 创建一个 Google Cloud 项目并启用 **Google Chat API**。 + - 前往:[Google Chat API 凭据](https://console.cloud.google.com/apis/api/chat.googleapis.com/credentials) + - 如果尚未启用,请启用该 API。 +2. 创建**服务账户**: + - 点击 **Create Credentials** > **Service Account**。 + - 随意命名(例如 `openclaw-chat`)。 + - 权限留空(点击 **Continue**)。 + - 有权访问的主体留空(点击 **Done**)。 +3. 创建并下载 **JSON 密钥**: + - 在服务账户列表中,点击你刚创建的那个。 + - 进入 **Keys** 标签页。 + - 点击 **Add Key** > **Create new key**。 + - 选择 **JSON** 并点击 **Create**。 +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`) + - **Description**:(例如 `Personal AI Assistant`) + - 启用 **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。_ + - 在 **Visibility** 下,勾选 **Make this Chat app available to specific people and groups in <Your Domain>**。 + - 在文本框中输入你的邮箱地址(例如 `user@example.com`)。 + - 点击底部的 **Save**。 +6. **启用应用状态**: + - 保存后,**刷新页面**。 + - 查找 **App status** 部分(通常在保存后位于顶部或底部附近)。 + - 将状态更改为 **Live - available to users**。 + - 再次点击 **Save**。 +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 请求。 + +## 添加到 Google Chat + +Gateway 运行且你的邮箱已添加到可见性列表后: + +1. 前往 [Google Chat](https://chat.google.com/)。 +2. 点击 **Direct Messages** 旁边的 **+**(加号)图标。 +3. 在搜索栏中(通常用于添加人员的地方),输入你在 Google Cloud Console 中配置的 **App name**。 + - **注意**:机器人*不会*出现在"Marketplace"浏览列表中,因为它是私有应用。你必须按名称搜索。 +4. 从结果中选择你的机器人。 +5. 点击 **Add** 或 **Chat** 开始一对一对话。 +6. 发送"Hello"来触发助手! + +## 公共 URL(仅 Webhook) + +Google Chat webhook 需要公共 HTTPS 端点。为安全起见,**仅将 `/googlechat` 路径暴露**到互联网。将 OpenClaw 仪表板和其他敏感端点保持在私有网络上。 + +### 方案 A:Tailscale Funnel(推荐) + +使用 Tailscale Serve 用于私有仪表板,Funnel 用于公共 webhook 路径。这样 `/` 保持私有,仅暴露 `/googlechat`。 + +1. **检查你的 Gateway 绑定在哪个地址上:** + + ```bash + ss -tlnp | grep 18789 + ``` + + 注意 IP 地址(例如 `127.0.0.1`、`0.0.0.0` 或你的 Tailscale IP 如 `100.x.x.x`)。 + +2. **仅将仪表板暴露给 tailnet(端口 8443):** + + ```bash + # 如果绑定到 localhost(127.0.0.1 或 0.0.0.0): + tailscale serve --bg --https 8443 http://127.0.0.1:18789 + + # 如果仅绑定到 Tailscale IP(例如 100.106.161.80): + tailscale serve --bg --https 8443 http://100.106.161.80:18789 + ``` + +3. **仅公开暴露 webhook 路径:** + + ```bash + # 如果绑定到 localhost(127.0.0.1 或 0.0.0.0): + tailscale funnel --bg --set-path /googlechat http://127.0.0.1:18789/googlechat + + # 如果仅绑定到 Tailscale IP(例如 100.106.161.80): + tailscale funnel --bg --set-path /googlechat http://100.106.161.80:18789/googlechat + ``` + +4. **为节点授权 Funnel 访问:** + 如果出现提示,请访问输出中显示的授权 URL,在你的 tailnet 策略中为此节点启用 Funnel。 + +5. **验证配置:** + ```bash + tailscale serve status + tailscale funnel status + ``` + +你的公共 webhook URL 将是: +`https://..ts.net/googlechat` + +你的私有仪表板仅限 tailnet 访问: +`https://..ts.net:8443/` + +在 Google Chat 应用配置中使用公共 URL(不带 `:8443`)。 + +> 注意:此配置在重启后持续有效。要在之后移除,运行 `tailscale funnel reset` 和 `tailscale serve reset`。 + +### 方案 B:反向代理(Caddy) + +如果你使用像 Caddy 这样的反向代理,仅代理特定路径: + +```caddy +your-domain.com { + reverse_proxy /googlechat* localhost:18789 +} +``` + +使用此配置,对 `your-domain.com/` 的任何请求将被忽略或返回 404,而 `your-domain.com/googlechat` 安全地路由到 OpenClaw。 + +### 方案 C:Cloudflare Tunnel + +配置你的隧道入口规则,仅路由 webhook 路径: + +- **路径**:`/googlechat` -> `http://localhost:18789/googlechat` +- **默认规则**:HTTP 404(Not Found) + +## 工作原理 + +1. Google Chat 向 Gateway 发送 webhook POST 请求。每个请求包含一个 `Authorization: Bearer ` 头。 +2. OpenClaw 根据配置的 `audienceType` + `audience` 验证 token: + - `audienceType: "app-url"` → audience 是你的 HTTPS webhook URL。 + - `audienceType: "project-number"` → audience 是 Cloud 项目编号。 +3. 消息按空间路由: + - 私信使用会话键 `agent::googlechat:dm:`。 + - 空间使用会话键 `agent::googlechat:group:`。 +4. 私信访问默认需要配对。未知发送者会收到配对码;通过以下方式批准: + - `openclaw pairing approve googlechat ` +5. 群组空间默认需要 @提及。如果提及检测需要应用的用户名,请使用 `botUser`。 + +## 目标 + +使用以下标识符进行投递和允许列表: + +- 私信:`users/` 或 `users/`(接受邮箱地址)。 +- 空间:`spaces/`。 + +## 配置要点 + +```json5 +{ + channels: { + googlechat: { + enabled: true, + serviceAccountFile: "/path/to/service-account.json", + audienceType: "app-url", + audience: "https://gateway.example.com/googlechat", + webhookPath: "/googlechat", + botUser: "users/1234567890", // 可选;辅助提及检测 + dm: { + policy: "pairing", + allowFrom: ["users/1234567890", "name@example.com"], + }, + groupPolicy: "allowlist", + groups: { + "spaces/AAAA": { + allow: true, + requireMention: true, + users: ["users/1234567890"], + systemPrompt: "Short answers only.", + }, + }, + actions: { reactions: true }, + typingIndicator: "message", + mediaMaxMb: 20, + }, + }, +} +``` + +注意事项: + +- 服务账户凭据也可以通过 `serviceAccount`(JSON 字符串)内联传递。 +- 如果未设置 `webhookPath`,默认 webhook 路径为 `/googlechat`。 +- 当 `actions.reactions` 启用时,可通过 `reactions` 工具和 `channels action` 使用回应功能。 +- `typingIndicator` 支持 `none`、`message`(默认)和 `reaction`(reaction 需要用户 OAuth)。 +- 附件通过 Chat API 下载并存储在媒体管道中(大小由 `mediaMaxMb` 限制)。 + +## 故障排除 + +### 405 Method Not Allowed + +如果 Google Cloud Logs Explorer 显示如下错误: + +``` +status code: 405, reason phrase: HTTP error response: HTTP/1.1 405 Method Not Allowed +``` + +这意味着 webhook 处理器未注册。常见原因: + +1. **渠道未配置**:配置中缺少 `channels.googlechat` 部分。通过以下方式验证: + + ```bash + openclaw config get channels.googlechat + ``` + + 如果返回"Config path not found",添加配置(参见[配置要点](#配置要点))。 + +2. **插件未启用**:检查插件状态: + + ```bash + openclaw plugins list | grep googlechat + ``` + + 如果显示"disabled",在配置中添加 `plugins.entries.googlechat.enabled: true`。 + +3. **Gateway 未重启**:添加配置后,重启 Gateway: + ```bash + openclaw gateway restart + ``` + +验证渠道是否正在运行: + +```bash +openclaw channels status +# 应显示:Google Chat default: enabled, configured, ... +``` + +### 其他问题 + +- 检查 `openclaw channels status --probe` 查看认证错误或缺失的 audience 配置。 +- 如果没有消息到达,确认 Chat 应用的 webhook URL + 事件订阅。 +- 如果提及门控阻止了回复,将 `botUser` 设置为应用的用户资源名称并验证 `requireMention`。 +- 发送测试消息时使用 `openclaw logs --follow` 查看请求是否到达 Gateway。 + +相关文档: + +- [Gateway 配置](/gateway/configuration) +- [安全](/gateway/security) +- [回应](/tools/reactions) diff --git a/docs/zh-CN/channels/grammy.md b/docs/zh-CN/channels/grammy.md new file mode 100644 index 0000000000..f381e21bc7 --- /dev/null +++ b/docs/zh-CN/channels/grammy.md @@ -0,0 +1,38 @@ +--- +read_when: + - 开发 Telegram 或 grammY 相关功能 +summary: 通过 grammY 集成 Telegram Bot API 及设置说明 +title: grammY +x-i18n: + generated_at: "2026-02-01T19:20:16Z" + model: claude-opus-4-5 + provider: pi + source_hash: ea7ef23e6d77801f4ef5fc56685ef4470f79f5aecab448d644a72cbab53521b7 + source_path: channels/grammy.md + workflow: 14 +--- + +# grammY 集成(Telegram Bot API) + +# 为什么选择 grammY + +- TypeScript 优先的 Bot API 客户端,内置长轮询 + webhook 辅助工具、中间件、错误处理、速率限制器。 +- 比手动编写 fetch + FormData 更简洁的媒体辅助工具;支持所有 Bot API 方法。 +- 可扩展:通过自定义 fetch 支持代理,会话中间件(可选),类型安全的上下文。 + +# 已交付的功能 + +- **单一客户端路径:** 基于 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::`);群组使用 `agent::telegram:group:`;回复路由回同一渠道。 +- **配置选项:** `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 覆盖了私信 + 群组提及门控和出站发送;欢迎更多媒体/webhook 测试用例。 + +待讨论问题 + +- 如果遇到 Bot API 429 错误,考虑使用可选的 grammY 插件(throttler)。 +- 添加更多结构化的媒体测试(贴纸、语音消息)。 +- 使 webhook 监听端口可配置(目前固定为 8787,除非通过 Gateway 接入)。 diff --git a/docs/zh-CN/channels/imessage.md b/docs/zh-CN/channels/imessage.md new file mode 100644 index 0000000000..fd57ae85b7 --- /dev/null +++ b/docs/zh-CN/channels/imessage.md @@ -0,0 +1,302 @@ +--- +read_when: + - 设置 iMessage 支持 + - 调试 iMessage 收发 +summary: 通过 imsg(基于 stdio 的 JSON-RPC)实现 iMessage 支持、设置和 chat_id 路由 +title: iMessage +x-i18n: + generated_at: "2026-02-01T19:21:07Z" + model: claude-opus-4-5 + provider: pi + source_hash: bc19756a42ead80a0845f18c4830c3f1f40948f69b2b016a4026598cfb8fef0d + source_path: channels/imessage.md + workflow: 14 +--- + +# iMessage(imsg) + +状态:外部 CLI 集成。Gateway 启动 `imsg rpc`(基于 stdio 的 JSON-RPC)。 + +## 快速设置(新手) + +1. 确保此 Mac 上的"信息"已登录。 +2. 安装 `imsg`: + - `brew install steipete/tap/imsg` +3. 配置 OpenClaw 的 `channels.imessage.cliPath` 和 `channels.imessage.dbPath`。 +4. 启动 Gateway 并批准所有 macOS 提示(自动化 + 完全磁盘访问权限)。 + +最小配置: + +```json5 +{ + channels: { + imessage: { + enabled: true, + cliPath: "/usr/local/bin/imsg", + dbPath: "/Users//Library/Messages/chat.db", + }, + }, +} +``` + +## 它是什么 + +- 在 macOS 上由 `imsg` 支持的 iMessage 渠道。 +- 确定性路由:回复始终发回 iMessage。 +- 私信共享智能体的主会话;群组是隔离的(`agent::imessage:group:`)。 +- 如果多参与者线程以 `is_group=false` 到达,你仍然可以通过 `chat_id` 使用 `channels.imessage.groups` 来隔离它(参见下方"类群组线程")。 + +## 配置写入 + +默认情况下,iMessage 允许通过 `/config set|unset` 触发的配置更新写入(需要 `commands.config: true`)。 + +通过以下方式禁用: + +```json5 +{ + channels: { imessage: { configWrites: false } }, +} +``` + +## 要求 + +- macOS 且"信息"已登录。 +- OpenClaw + `imsg` 需要完全磁盘访问权限(访问 Messages 数据库)。 +- 发送时需要自动化权限。 +- `channels.imessage.cliPath` 可以指向任何代理 stdin/stdout 的命令(例如,通过 SSH 连接到另一台 Mac 并运行 `imsg rpc` 的包装脚本)。 + +## 设置(快速路径) + +1. 确保此 Mac 上的"信息"已登录。 +2. 配置 iMessage 并启动 Gateway。 + +### 专用机器人 macOS 用户(用于隔离身份) + +如果你希望机器人从一个**独立的 iMessage 身份**发送消息(并保持你的个人"信息"整洁),请使用专用的 Apple ID + 专用的 macOS 用户。 + +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 @localhost true` 无需密码即可工作。 +7. 将 `channels.imessage.accounts.bot.cliPath` 指向一个以机器人用户身份运行 `imsg` 的 SSH 包装脚本。 + +首次运行注意事项:发送/接收可能需要在*机器人 macOS 用户*中进行 GUI 审批(自动化 + 完全磁盘访问权限)。如果 `imsg rpc` 看起来卡住或退出,请登录该用户(屏幕共享很有帮助),运行一次 `imsg chats --limit 1` / `imsg send ...`,批准提示,然后重试。 + +示例包装脚本(`chmod +x`)。将 `` 替换为你的实际 macOS 用户名: + +```bash +#!/usr/bin/env bash +set -euo pipefail + +# 先运行一次交互式 SSH 以接受主机密钥: +# ssh @localhost true +exec /usr/bin/ssh -o BatchMode=yes -o ConnectTimeout=5 -T @localhost \ + "/usr/local/bin/imsg" "$@" +``` + +示例配置: + +```json5 +{ + channels: { + imessage: { + enabled: true, + accounts: { + bot: { + name: "Bot", + enabled: true, + cliPath: "/path/to/imsg-bot", + dbPath: "/Users//Library/Messages/chat.db", + }, + }, + }, + }, +} +``` + +对于单账户设置,使用扁平选项(`channels.imessage.cliPath`、`channels.imessage.dbPath`)而非 `accounts` 映射。 + +### 远程/SSH 变体(可选) + +如果你想在另一台 Mac 上使用 iMessage,将 `channels.imessage.cliPath` 设置为通过 SSH 在远程 macOS 主机上运行 `imsg` 的包装脚本。OpenClaw 只需要 stdio。 + +示例包装脚本: + +```bash +#!/usr/bin/env bash +exec ssh -T gateway-host imsg "$@" +``` + +**远程附件:** 当 `cliPath` 通过 SSH 指向远程主机时,Messages 数据库中的附件路径引用的是远程机器上的文件。OpenClaw 可以通过设置 `channels.imessage.remoteHost` 自动通过 SCP 获取这些文件: + +```json5 +{ + channels: { + imessage: { + cliPath: "~/imsg-ssh", // 到远程 Mac 的 SSH 包装脚本 + remoteHost: "user@gateway-host", // 用于 SCP 文件传输 + includeAttachments: true, + }, + }, +} +``` + +如果未设置 `remoteHost`,OpenClaw 会尝试通过解析你包装脚本中的 SSH 命令来自动检测。建议显式配置以确保可靠性。 + +#### 通过 Tailscale 连接远程 Mac(示例) + +如果 Gateway 运行在 Linux 主机/虚拟机上但 iMessage 必须运行在 Mac 上,Tailscale 是最简单的桥接方案:Gateway 通过 tailnet 与 Mac 通信,通过 SSH 运行 `imsg`,并通过 SCP 传回附件。 + +架构: + +``` +┌──────────────────────────────┐ SSH (imsg rpc) ┌──────────────────────────┐ +│ Gateway 主机(Linux/VM) │──────────────────────────────────▶│ 装有 Messages + imsg 的 Mac │ +│ - openclaw gateway │ SCP(附件) │ - Messages 已登录 │ +│ - channels.imessage.cliPath │◀──────────────────────────────────│ - 远程登录已启用 │ +└──────────────────────────────┘ └──────────────────────────┘ + ▲ + │ Tailscale tailnet(主机名或 100.x.y.z) + ▼ + user@gateway-host +``` + +具体配置示例(Tailscale 主机名): + +```json5 +{ + channels: { + imessage: { + enabled: true, + cliPath: "~/.openclaw/scripts/imsg-ssh", + remoteHost: "bot@mac-mini.tailnet-1234.ts.net", + includeAttachments: true, + dbPath: "/Users/bot/Library/Messages/chat.db", + }, + }, +} +``` + +示例包装脚本(`~/.openclaw/scripts/imsg-ssh`): + +```bash +#!/usr/bin/env bash +exec ssh -T bot@mac-mini.tailnet-1234.ts.net imsg "$@" +``` + +注意事项: + +- 确保 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`(它通常包含 token)。 + +## 访问控制(私信 + 群组) + +私信: + +- 默认:`channels.imessage.dmPolicy = "pairing"`。 +- 未知发送者会收到配对码;在批准之前消息会被忽略(配对码 1 小时后过期)。 +- 通过以下方式批准: + - `openclaw pairing list imessage` + - `openclaw pairing approve imessage ` +- 配对是 iMessage 私信的默认令牌交换方式。详情:[配对](/start/pairing) + +群组: + +- `channels.imessage.groupPolicy = open | allowlist | disabled`。 +- 当设置为 `allowlist` 时,`channels.imessage.groupAllowFrom` 控制谁可以在群组中触发。 +- 提及门控使用 `agents.list[].groupChat.mentionPatterns`(或 `messages.groupChat.mentionPatterns`),因为 iMessage 没有原生提及元数据。 +- 多智能体覆盖:在 `agents.list[].groupChat.mentionPatterns` 上设置每个智能体的模式。 + +## 工作原理(行为) + +- `imsg` 流式传输消息事件;Gateway 将其标准化为共享的渠道信封。 +- 回复始终路由回同一个 chat id 或用户名。 + +## 类群组线程(`is_group=false`) + +一些 iMessage 线程可能有多个参与者,但由于"信息"存储聊天标识符的方式,仍然以 `is_group=false` 到达。 + +如果你在 `channels.imessage.groups` 下显式配置了一个 `chat_id`,OpenClaw 会将该线程视为"群组",用于: + +- 会话隔离(独立的 `agent::imessage:group:` 会话键) +- 群组允许列表/提及门控行为 + +示例: + +```json5 +{ + channels: { + imessage: { + groupPolicy: "allowlist", + groupAllowFrom: ["+15555550123"], + groups: { + "42": { requireMention: false }, + }, + }, + }, +} +``` + +当你想为特定线程使用隔离的个性/模型时很有用(参见[多智能体路由](/concepts/multi-agent))。有关文件系统隔离,请参阅[沙箱](/gateway/sandboxing)。 + +## 媒体 + 限制 + +- 通过 `channels.imessage.includeAttachments` 可选接收附件。 +- 媒体上限通过 `channels.imessage.mediaMaxMb` 设置。 + +## 限制 + +- 出站文本按 `channels.imessage.textChunkLimit` 分块(默认 4000)。 +- 可选的换行分块:设置 `channels.imessage.chunkMode="newline"` 在按长度分块之前按空行(段落边界)分割。 +- 媒体上传上限由 `channels.imessage.mediaMaxMb` 限制(默认 16)。 + +## 寻址 / 投递目标 + +推荐使用 `chat_id` 进行稳定路由: + +- `chat_id:123`(推荐) +- `chat_guid:...` +- `chat_identifier:...` +- 直接用户名:`imessage:+1555` / `sms:+1555` / `user@example.com` + +列出聊天: + +``` +imsg chats --limit 20 +``` + +## 配置参考(iMessage) + +完整配置:[配置](/gateway/configuration) + +提供商选项: + +- `channels.imessage.enabled`:启用/禁用渠道启动。 +- `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`:SMS 区域。 +- `channels.imessage.dmPolicy`:`pairing | allowlist | open | disabled`(默认:pairing)。 +- `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[""].historyLimit`。 +- `channels.imessage.groups`:按群组默认值 + 允许列表(使用 `"*"` 设置全局默认值)。 +- `channels.imessage.includeAttachments`:将附件接收到上下文中。 +- `channels.imessage.mediaMaxMb`:入站/出站媒体上限(MB)。 +- `channels.imessage.textChunkLimit`:出站分块大小(字符)。 +- `channels.imessage.chunkMode`:`length`(默认)或 `newline`,在按长度分块之前按空行(段落边界)分割。 + +相关全局选项: + +- `agents.list[].groupChat.mentionPatterns`(或 `messages.groupChat.mentionPatterns`)。 +- `messages.responsePrefix`。 diff --git a/docs/zh-CN/channels/index.md b/docs/zh-CN/channels/index.md new file mode 100644 index 0000000000..559c52d228 --- /dev/null +++ b/docs/zh-CN/channels/index.md @@ -0,0 +1,50 @@ +--- +read_when: + - 你想为 OpenClaw 选择一个聊天渠道 + - 你需要快速了解支持的消息平台 +summary: OpenClaw 可连接的消息平台 +title: 聊天渠道 +x-i18n: + generated_at: "2026-02-01T19:21:22Z" + model: claude-opus-4-5 + provider: pi + source_hash: 2632863def6dee97e0fa8b931762f0969174fd4fb22303a00dcd46527fe4a141 + source_path: channels/index.md + workflow: 14 +--- + +# 聊天渠道 + +OpenClaw 可以在你已经使用的任何聊天应用上与你对话。每个渠道通过 Gateway 连接。所有渠道都支持文本;媒体和回应功能因渠道而异。 + +## 支持的渠道 + +- [WhatsApp](/channels/whatsapp) — 最受欢迎;使用 Baileys 并需要二维码配对。 +- [Telegram](/channels/telegram) — 通过 grammY 使用 Bot API;支持群组。 +- [Discord](/channels/discord) — Discord Bot API + Gateway;支持服务器、频道和私信。 +- [Slack](/channels/slack) — Bolt SDK;工作区应用。 +- [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) — 仅限 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 的通讯工具(插件,需单独安装)。 +- [Twitch](/channels/twitch) — 通过 IRC 连接的 Twitch 聊天(插件,需单独安装)。 +- [Zalo](/channels/zalo) — Zalo Bot API;越南流行的通讯工具(插件,需单独安装)。 +- [Zalo Personal](/channels/zalouser) — 通过二维码登录的 Zalo 个人账户(插件,需单独安装)。 +- [WebChat](/web/webchat) — 通过 WebSocket 的 Gateway WebChat UI。 + +## 注意事项 + +- 渠道可以同时运行;配置多个渠道后 OpenClaw 会按聊天路由。 +- 最快的设置通常是 **Telegram**(简单的 bot token)。WhatsApp 需要二维码配对并在磁盘上存储更多状态。 +- 群组行为因渠道而异;参见[群组](/concepts/groups)。 +- 私信配对和允许列表出于安全考虑强制执行;参见[安全](/gateway/security)。 +- Telegram 内部实现:[grammY 说明](/channels/grammy)。 +- 故障排除:[渠道故障排除](/channels/troubleshooting)。 +- 模型提供商单独文档化;参见[模型提供商](/providers/models)。 diff --git a/docs/zh-CN/channels/line.md b/docs/zh-CN/channels/line.md new file mode 100644 index 0000000000..aab4745d53 --- /dev/null +++ b/docs/zh-CN/channels/line.md @@ -0,0 +1,180 @@ +--- +read_when: + - 你想将 OpenClaw 连接到 LINE + - 你需要 LINE webhook + 凭据设置 + - 你需要 LINE 特定的消息选项 +summary: LINE Messaging API 插件设置、配置和使用 +title: LINE +x-i18n: + generated_at: "2026-02-01T19:21:38Z" + model: claude-opus-4-5 + provider: pi + source_hash: 8fbac126786f95b9454f3cc61906c2798393a8d7914e787d3755c020c7ab2da6 + source_path: channels/line.md + workflow: 14 +--- + +# LINE(插件) + +LINE 通过 LINE Messaging API 连接到 OpenClaw。插件作为 Gateway 上的 webhook 接收器运行,使用你的频道访问 token + 频道密钥进行认证。 + +状态:通过插件支持。支持私信、群聊、媒体、位置、Flex 消息、模板消息和快速回复。不支持回应和线程。 + +## 需要插件 + +安装 LINE 插件: + +```bash +openclaw plugins install @openclaw/line +``` + +本地检出(从 git 仓库运行时): + +```bash +openclaw plugins install ./extensions/line +``` + +## 设置 + +1. 创建 LINE Developers 账户并打开控制台: + https://developers.line.biz/console/ +2. 创建(或选择)一个 Provider 并添加一个 **Messaging API** 频道。 +3. 从频道设置中复制 **Channel access token** 和 **Channel secret**。 +4. 在 Messaging API 设置中启用 **Use webhook**。 +5. 将 webhook URL 设置为你的 Gateway 端点(需要 HTTPS): + +``` +https://gateway-host/line/webhook +``` + +Gateway 响应 LINE 的 webhook 验证(GET)和入站事件(POST)。如果你需要自定义路径,请设置 `channels.line.webhookPath` 或 `channels.line.accounts..webhookPath` 并相应更新 URL。 + +## 配置 + +最小配置: + +```json5 +{ + channels: { + line: { + enabled: true, + channelAccessToken: "LINE_CHANNEL_ACCESS_TOKEN", + channelSecret: "LINE_CHANNEL_SECRET", + dmPolicy: "pairing", + }, + }, +} +``` + +环境变量(仅默认账户): + +- `LINE_CHANNEL_ACCESS_TOKEN` +- `LINE_CHANNEL_SECRET` + +Token/密钥文件: + +```json5 +{ + channels: { + line: { + tokenFile: "/path/to/line-token.txt", + secretFile: "/path/to/line-secret.txt", + }, + }, +} +``` + +多账户: + +```json5 +{ + channels: { + line: { + accounts: { + marketing: { + channelAccessToken: "...", + channelSecret: "...", + webhookPath: "/line/marketing", + }, + }, + }, + }, +} +``` + +## 访问控制 + +私信默认需要配对。未知发送者会收到配对码,在批准之前其消息会被忽略。 + +```bash +openclaw pairing list line +openclaw pairing approve line +``` + +允许列表和策略: + +- `channels.line.dmPolicy`:`pairing | allowlist | open | disabled` +- `channels.line.allowFrom`:私信的允许 LINE 用户 ID 列表 +- `channels.line.groupPolicy`:`allowlist | open | disabled` +- `channels.line.groupAllowFrom`:群组的允许 LINE 用户 ID 列表 +- 按群组覆盖:`channels.line.groups..allowFrom` + +LINE ID 区分大小写。有效的 ID 格式如下: + +- 用户:`U` + 32 位十六进制字符 +- 群组:`C` + 32 位十六进制字符 +- 房间:`R` + 32 位十六进制字符 + +## 消息行为 + +- 文本在 5000 字符处分块。 +- Markdown 格式会被去除;代码块和表格在可能时会转换为 Flex 卡片。 +- 流式响应会被缓冲;智能体工作时 LINE 接收完整分块并显示加载动画。 +- 媒体下载上限由 `channels.line.mediaMaxMb` 限制(默认 10)。 + +## 渠道数据(富消息) + +使用 `channelData.line` 发送快速回复、位置、Flex 卡片或模板消息。 + +```json5 +{ + text: "Here you go", + channelData: { + line: { + quickReplies: ["Status", "Help"], + location: { + title: "Office", + address: "123 Main St", + latitude: 35.681236, + longitude: 139.767125, + }, + flexMessage: { + altText: "Status card", + contents: { + /* Flex 负载 */ + }, + }, + templateMessage: { + type: "confirm", + text: "Proceed?", + confirmLabel: "Yes", + confirmData: "yes", + cancelLabel: "No", + cancelData: "no", + }, + }, + }, +} +``` + +LINE 插件还附带一个 `/card` 命令用于 Flex 消息预设: + +``` +/card info "Welcome" "Thanks for joining!" +``` + +## 故障排除 + +- **Webhook 验证失败:** 确保 webhook URL 为 HTTPS 且 `channelSecret` 与 LINE 控制台匹配。 +- **没有入站事件:** 确认 webhook 路径与 `channels.line.webhookPath` 匹配且 Gateway 可从 LINE 访问。 +- **媒体下载错误:** 如果媒体超过默认限制,请增大 `channels.line.mediaMaxMb`。 diff --git a/docs/zh-CN/channels/location.md b/docs/zh-CN/channels/location.md new file mode 100644 index 0000000000..2b040bbc5b --- /dev/null +++ b/docs/zh-CN/channels/location.md @@ -0,0 +1,63 @@ +--- +read_when: + - 添加或修改渠道位置解析 + - 在智能体提示或工具中使用位置上下文字段 +summary: 入站渠道位置解析(Telegram + WhatsApp)及上下文字段 +title: 渠道位置解析 +x-i18n: + generated_at: "2026-02-01T19:21:46Z" + model: claude-opus-4-5 + provider: pi + source_hash: 5602ef105c3da7e47497bfed8fc343dd8d7f3c019ff7e423a08b25092c5a1837 + source_path: channels/location.md + workflow: 14 +--- + +# 渠道位置解析 + +OpenClaw 将聊天渠道中分享的位置标准化为: + +- 附加到入站消息体的可读文本,以及 +- 自动回复上下文负载中的结构化字段。 + +目前支持: + +- **Telegram**(位置图钉 + 地点 + 实时位置) +- **WhatsApp**(locationMessage + liveLocationMessage) +- **Matrix**(`m.location` 配合 `geo_uri`) + +## 文本格式 + +位置以友好的行格式呈现,不带括号: + +- 图钉: + - `📍 48.858844, 2.294351 ±12m` +- 命名地点: + - `📍 Eiffel Tower — Champ de Mars, Paris (48.858844, 2.294351 ±12m)` +- 实时分享: + - `🛰 Live location: 48.858844, 2.294351 ±12m` + +如果渠道包含标题/评论,会附加在下一行: + +``` +📍 48.858844, 2.294351 ±12m +Meet here +``` + +## 上下文字段 + +当存在位置信息时,以下字段会被添加到 `ctx` 中: + +- `LocationLat`(数字) +- `LocationLon`(数字) +- `LocationAccuracy`(数字,米;可选) +- `LocationName`(字符串;可选) +- `LocationAddress`(字符串;可选) +- `LocationSource`(`pin | place | live`) +- `LocationIsLive`(布尔值) + +## 渠道说明 + +- **Telegram**:地点映射到 `LocationName/LocationAddress`;实时位置使用 `live_period`。 +- **WhatsApp**:`locationMessage.comment` 和 `liveLocationMessage.caption` 作为标题行附加。 +- **Matrix**:`geo_uri` 解析为图钉位置;忽略海拔高度,`LocationIsLive` 始终为 false。 diff --git a/docs/zh-CN/channels/matrix.md b/docs/zh-CN/channels/matrix.md new file mode 100644 index 0000000000..8aff83703a --- /dev/null +++ b/docs/zh-CN/channels/matrix.md @@ -0,0 +1,221 @@ +--- +read_when: + - 开发 Matrix 渠道功能 +summary: Matrix 支持状态、功能和配置 +title: Matrix +x-i18n: + generated_at: "2026-02-01T19:22:24Z" + model: claude-opus-4-5 + provider: pi + source_hash: b276b5263593c766e7be6549abbb27927177e7b51cfd297b4825965372513ee4 + source_path: channels/matrix.md + workflow: 14 +--- + +# Matrix(插件) + +Matrix 是一个开放、去中心化的消息协议。OpenClaw 作为 Matrix **用户**连接到任何主服务器,因此你需要为机器人创建一个 Matrix 账户。登录后,你可以直接私信机器人或邀请它加入房间(Matrix 的"群组")。Beeper 也是一个可用的客户端选项,但它需要启用端到端加密。 + +状态:通过插件支持(@vector-im/matrix-bot-sdk)。支持私信、房间、线程、媒体、回应、投票(发送 + poll-start 转为文本)、位置和端到端加密(需要加密支持)。 + +## 需要插件 + +Matrix 作为插件发布,不包含在核心安装中。 + +通过 CLI 安装(npm 注册表): + +```bash +openclaw plugins install @openclaw/matrix +``` + +本地检出(从 git 仓库运行时): + +```bash +openclaw plugins install ./extensions/matrix +``` + +如果你在配置/上手引导期间选择了 Matrix 并检测到 git 检出,OpenClaw 会自动提供本地安装路径。 + +详情:[插件](/plugin) + +## 设置 + +1. 安装 Matrix 插件: + - 从 npm:`openclaw plugins install @openclaw/matrix` + - 从本地检出:`openclaw plugins install ./extensions/matrix` +2. 在主服务器上创建 Matrix 账户: + - 在 [https://matrix.org/ecosystem/hosting/](https://matrix.org/ecosystem/hosting/) 浏览托管选项 + - 或自行托管。 +3. 获取机器人账户的访问 token: + - 在你的主服务器上使用 Matrix 登录 API 配合 `curl`: + + ```bash + curl --request POST \ + --url https://matrix.example.org/_matrix/client/v3/login \ + --header 'Content-Type: application/json' \ + --data '{ + "type": "m.login.password", + "identifier": { + "type": "m.id.user", + "user": "your-user-name" + }, + "password": "your-password" + }' + ``` + + - 将 `matrix.example.org` 替换为你的主服务器 URL。 + - 或设置 `channels.matrix.userId` + `channels.matrix.password`:OpenClaw 调用相同的登录端点,将访问 token 存储在 `~/.openclaw/credentials/matrix/credentials.json` 中,并在下次启动时重用。 + +4. 配置凭据: + - 环境变量:`MATRIX_HOMESERVER`、`MATRIX_ACCESS_TOKEN`(或 `MATRIX_USER_ID` + `MATRIX_PASSWORD`) + - 或配置:`channels.matrix.*` + - 如果两者都设置了,配置优先。 + - 使用访问 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` 并验证设备。 + +最小配置(访问 token,用户 ID 自动获取): + +```json5 +{ + channels: { + matrix: { + enabled: true, + homeserver: "https://matrix.example.org", + accessToken: "syt_***", + dm: { policy: "pairing" }, + }, + }, +} +``` + +端到端加密配置(启用端到端加密): + +```json5 +{ + channels: { + matrix: { + enabled: true, + homeserver: "https://matrix.example.org", + accessToken: "syt_***", + encryption: true, + dm: { policy: "pairing" }, + }, + }, +} +``` + +## 加密(端到端加密) + +端到端加密通过 Rust 加密 SDK **支持**。 + +通过 `channels.matrix.encryption: true` 启用: + +- 如果加密模块加载成功,加密房间会自动解密。 +- 向加密房间发送时,出站媒体会被加密。 +- 首次连接时,OpenClaw 会从你的其他会话请求设备验证。 +- 在另一个 Matrix 客户端(Element 等)中验证设备以启用密钥共享。 +- 如果加密模块无法加载,端到端加密将被禁用且加密房间无法解密;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` 获取二进制文件。 + +加密状态按账户 + 访问 token 存储在 `~/.openclaw/matrix/accounts//__//crypto/`(SQLite 数据库)。同步状态存储在同一目录下的 `bot-storage.json` 中。如果访问 token(设备)发生变化,会创建新的存储,机器人必须重新验证才能在加密房间中使用。 + +**设备验证:** +启用端到端加密后,机器人会在启动时从你的其他会话请求验证。打开 Element(或其他客户端)并批准验证请求以建立信任。验证完成后,机器人可以解密加密房间中的消息。 + +## 路由模型 + +- 回复始终发回 Matrix。 +- 私信共享智能体的主会话;房间映射到群组会话。 + +## 访问控制(私信) + +- 默认:`channels.matrix.dm.policy = "pairing"`。未知发送者会收到配对码。 +- 通过以下方式批准: + - `openclaw pairing list matrix` + - `openclaw pairing approve matrix ` +- 公开私信:`channels.matrix.dm.policy="open"` 加上 `channels.matrix.dm.allowFrom=["*"]`。 +- `channels.matrix.dm.allowFrom` 接受用户 ID 或显示名称。向导在目录搜索可用时会将显示名称解析为用户 ID。 + +## 房间(群组) + +- 默认:`channels.matrix.groupPolicy = "allowlist"`(提及门控)。使用 `channels.defaults.groupPolicy` 可在未设置时覆盖默认值。 +- 使用 `channels.matrix.groups` 允许列表中的房间(房间 ID、别名或名称): + +```json5 +{ + channels: { + matrix: { + groupPolicy: "allowlist", + groups: { + "!roomId:example.org": { allow: true }, + "#alias:example.org": { allow: true }, + }, + groupAllowFrom: ["@owner:example.org"], + }, + }, +} +``` + +- `requireMention: false` 启用该房间的自动回复。 +- `groups."*"` 可以设置跨房间的提及门控默认值。 +- `groupAllowFrom` 限制哪些发送者可以在房间中触发机器人(可选)。 +- 按房间的 `users` 允许列表可以进一步限制特定房间内的发送者。 +- 配置向导会提示输入房间允许列表(房间 ID、别名或名称)并在可能时解析名称。 +- 启动时,OpenClaw 将允许列表中的房间/用户名称解析为 ID 并记录映射;未解析的条目保持原样。 +- 邀请默认自动加入;通过 `channels.matrix.autoJoin` 和 `channels.matrix.autoJoinAllowlist` 控制。 +- 要**不允许任何房间**,设置 `channels.matrix.groupPolicy: "disabled"`(或保持空的允许列表)。 +- 旧版键:`channels.matrix.rooms`(与 `groups` 结构相同)。 + +## 线程 + +- 支持回复线程。 +- `channels.matrix.threadReplies` 控制回复是否保持在线程中: + - `off`、`inbound`(默认)、`always` +- `channels.matrix.replyToMode` 控制不在线程中回复时的 reply-to 元数据: + - `off`(默认)、`first`、`all` + +## 功能 + +| 功能 | 状态 | +| ---------- | ---------------------------------------------------------- | +| 私信 | ✅ 支持 | +| 房间 | ✅ 支持 | +| 线程 | ✅ 支持 | +| 媒体 | ✅ 支持 | +| 端到端加密 | ✅ 支持(需要加密模块) | +| 回应 | ✅ 支持(通过工具发送/读取) | +| 投票 | ✅ 支持发送;入站 poll start 转换为文本(响应/结束被忽略) | +| 位置 | ✅ 支持(geo URI;忽略海拔) | +| 原生命令 | ✅ 支持 | + +## 配置参考(Matrix) + +完整配置:[配置](/gateway/configuration) + +提供商选项: + +- `channels.matrix.enabled`:启用/禁用渠道启动。 +- `channels.matrix.homeserver`:主服务器 URL。 +- `channels.matrix.userId`:Matrix 用户 ID(使用访问 token 时可选)。 +- `channels.matrix.accessToken`:访问 token。 +- `channels.matrix.password`:登录密码(token 会被存储)。 +- `channels.matrix.deviceName`:设备显示名称。 +- `channels.matrix.encryption`:启用端到端加密(默认:false)。 +- `channels.matrix.initialSyncLimit`:初始同步限制。 +- `channels.matrix.threadReplies`:`off | inbound | always`(默认:inbound)。 +- `channels.matrix.textChunkLimit`:出站文本分块大小(字符)。 +- `channels.matrix.chunkMode`:`length`(默认)或 `newline`,在按长度分块之前按空行(段落边界)分割。 +- `channels.matrix.dm.policy`:`pairing | allowlist | open | disabled`(默认:pairing)。 +- `channels.matrix.dm.allowFrom`:私信允许列表(用户 ID 或显示名称)。`open` 需要 `"*"`。向导在可能时将名称解析为 ID。 +- `channels.matrix.groupPolicy`:`allowlist | open | disabled`(默认:allowlist)。 +- `channels.matrix.groupAllowFrom`:群组消息的允许发送者列表。 +- `channels.matrix.allowlistOnly`:强制对私信 + 房间执行允许列表规则。 +- `channels.matrix.groups`:群组允许列表 + 按房间设置映射。 +- `channels.matrix.rooms`:旧版群组允许列表/配置。 +- `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)。 diff --git a/docs/zh-CN/channels/mattermost.md b/docs/zh-CN/channels/mattermost.md new file mode 100644 index 0000000000..1842da6ad0 --- /dev/null +++ b/docs/zh-CN/channels/mattermost.md @@ -0,0 +1,142 @@ +--- +read_when: + - 设置 Mattermost + - 调试 Mattermost 路由 +summary: Mattermost 机器人设置和 OpenClaw 配置 +title: Mattermost +x-i18n: + generated_at: "2026-02-01T19:22:40Z" + model: claude-opus-4-5 + provider: pi + source_hash: 57fabe5eb0efbcb885f4178b317b2fa99a41daf609e3a471de2b44db9def4ad7 + source_path: channels/mattermost.md + workflow: 14 +--- + +# Mattermost(插件) + +状态:通过插件支持(bot token + WebSocket 事件)。支持频道、群组和私信。Mattermost 是一个可自托管的团队消息平台;有关产品详情和下载请访问官方网站 [mattermost.com](https://mattermost.com)。 + +## 需要插件 + +Mattermost 作为插件发布,不包含在核心安装中。 + +通过 CLI 安装(npm 注册表): + +```bash +openclaw plugins install @openclaw/mattermost +``` + +本地检出(从 git 仓库运行时): + +```bash +openclaw plugins install ./extensions/mattermost +``` + +如果你在配置/上手引导期间选择了 Mattermost 并检测到 git 检出,OpenClaw 会自动提供本地安装路径。 + +详情:[插件](/plugin) + +## 快速设置 + +1. 安装 Mattermost 插件。 +2. 创建一个 Mattermost 机器人账户并复制 **bot token**。 +3. 复制 Mattermost **基础 URL**(例如 `https://chat.example.com`)。 +4. 配置 OpenClaw 并启动 Gateway。 + +最小配置: + +```json5 +{ + channels: { + mattermost: { + enabled: true, + botToken: "mm-token", + baseUrl: "https://chat.example.com", + dmPolicy: "pairing", + }, + }, +} +``` + +## 环境变量(默认账户) + +如果你偏好使用环境变量,请在 Gateway 主机上设置: + +- `MATTERMOST_BOT_TOKEN=...` +- `MATTERMOST_URL=https://chat.example.com` + +环境变量仅适用于**默认**账户(`default`)。其他账户必须使用配置值。 + +## 聊天模式 + +Mattermost 自动响应私信。频道行为由 `chatmode` 控制: + +- `oncall`(默认):仅在频道中被 @提及时响应。 +- `onmessage`:响应频道中的每条消息。 +- `onchar`:当消息以触发前缀开头时响应。 + +配置示例: + +```json5 +{ + channels: { + mattermost: { + chatmode: "onchar", + oncharPrefixes: [">", "!"], + }, + }, +} +``` + +注意事项: + +- `onchar` 模式仍然响应明确的 @提及。 +- `channels.mattermost.requireMention` 对旧版配置仍然有效,但推荐使用 `chatmode`。 + +## 访问控制(私信) + +- 默认:`channels.mattermost.dmPolicy = "pairing"`(未知发送者会收到配对码)。 +- 通过以下方式批准: + - `openclaw pairing list mattermost` + - `openclaw pairing approve mattermost ` +- 公开私信:`channels.mattermost.dmPolicy="open"` 加上 `channels.mattermost.allowFrom=["*"]`。 + +## 频道(群组) + +- 默认:`channels.mattermost.groupPolicy = "allowlist"`(提及门控)。 +- 使用 `channels.mattermost.groupAllowFrom` 允许列表发送者(用户 ID 或 `@username`)。 +- 开放频道:`channels.mattermost.groupPolicy="open"`(提及门控)。 + +## 出站投递目标 + +在 `openclaw message send` 或定时任务/webhook 中使用以下目标格式: + +- `channel:` 用于频道 +- `user:` 用于私信 +- `@username` 用于私信(通过 Mattermost API 解析) + +裸 ID 被视为频道。 + +## 多账户 + +Mattermost 支持在 `channels.mattermost.accounts` 下配置多个账户: + +```json5 +{ + channels: { + mattermost: { + accounts: { + default: { name: "Primary", botToken: "mm-token", baseUrl: "https://chat.example.com" }, + alerts: { name: "Alerts", botToken: "mm-token-2", baseUrl: "https://alerts.example.com" }, + }, + }, + }, +} +``` + +## 故障排除 + +- 频道中没有回复:确保机器人已加入频道并提及它(oncall 模式),使用触发前缀(onchar 模式),或设置 `chatmode: "onmessage"`。 +- 认证错误:检查 bot token、基础 URL 以及账户是否已启用。 +- 多账户问题:环境变量仅适用于 `default` 账户。 diff --git a/docs/zh-CN/channels/msteams.md b/docs/zh-CN/channels/msteams.md new file mode 100644 index 0000000000..f1813fffae --- /dev/null +++ b/docs/zh-CN/channels/msteams.md @@ -0,0 +1,770 @@ +--- +read_when: + - 开发 Microsoft Teams 渠道功能 +summary: Microsoft Teams 机器人支持状态、功能和配置 +title: Microsoft Teams +x-i18n: + generated_at: "2026-02-01T19:26:12Z" + model: claude-opus-4-5 + provider: pi + source_hash: 3d5641c578086f7569f42276d4ef2462200b9927ca3f505e6ee26806103eaa60 + source_path: channels/msteams.md + workflow: 14 +--- + +# Microsoft Teams(插件) + +> "进入此处者,放弃一切希望。" + +更新时间:2026-01-21 + +状态:支持文本 + 私信附件;频道/群组文件发送需要 `sharePointSiteId` + Graph 权限(参见[在群聊中发送文件](#在群聊中发送文件))。投票通过 Adaptive Cards 发送。 + +## 需要插件 + +Microsoft Teams 作为插件发布,不包含在核心安装中。 + +**破坏性变更(2026.1.15):** Microsoft Teams 已从核心中移出。如果你使用它,必须安装插件。 + +原因说明:保持核心安装更轻量,并让 Microsoft Teams 依赖项可以独立更新。 + +通过 CLI 安装(npm 注册表): + +```bash +openclaw plugins install @openclaw/msteams +``` + +本地检出(从 git 仓库运行时): + +```bash +openclaw plugins install ./extensions/msteams +``` + +如果你在配置/上手引导期间选择了 Teams 并检测到 git 检出,OpenClaw 会自动提供本地安装路径。 + +详情:[插件](/plugin) + +## 快速设置(新手) + +1. 安装 Microsoft Teams 插件。 +2. 创建一个 **Azure Bot**(App ID + 客户端密钥 + 租户 ID)。 +3. 使用这些凭据配置 OpenClaw。 +4. 通过公共 URL 或隧道暴露 `/api/messages`(默认端口 3978)。 +5. 安装 Teams 应用包并启动 Gateway。 + +最小配置: + +```json5 +{ + channels: { + msteams: { + enabled: true, + appId: "", + appPassword: "", + tenantId: "", + webhook: { port: 3978, path: "/api/messages" }, + }, + }, +} +``` + +注意:群聊默认被阻止(`channels.msteams.groupPolicy: "allowlist"`)。要允许群组回复,请设置 `channels.msteams.groupAllowFrom`(或使用 `groupPolicy: "open"` 允许任何成员,提及门控)。 + +## 目标 + +- 通过 Teams 私信、群聊或频道与 OpenClaw 对话。 +- 保持路由确定性:回复始终发回消息到达的渠道。 +- 默认使用安全的渠道行为(除非另行配置,否则需要提及)。 + +## 配置写入 + +默认情况下,Microsoft Teams 允许通过 `/config set|unset` 触发的配置更新写入(需要 `commands.config: true`)。 + +通过以下方式禁用: + +```json5 +{ + channels: { msteams: { configWrites: false } }, +} +``` + +## 访问控制(私信 + 群组) + +**私信访问** + +- 默认:`channels.msteams.dmPolicy = "pairing"`。未知发送者在批准前会被忽略。 +- `channels.msteams.allowFrom` 接受 AAD 对象 ID、UPN 或显示名称。当凭据允许时,向导通过 Microsoft Graph 将名称解析为 ID。 + +**群组访问** + +- 默认:`channels.msteams.groupPolicy = "allowlist"`(被阻止,除非你添加 `groupAllowFrom`)。使用 `channels.defaults.groupPolicy` 可在未设置时覆盖默认值。 +- `channels.msteams.groupAllowFrom` 控制哪些发送者可以在群聊/频道中触发(回退到 `channels.msteams.allowFrom`)。 +- 设置 `groupPolicy: "open"` 可允许任何成员(默认仍需提及门控)。 +- 要**不允许任何频道**,设置 `channels.msteams.groupPolicy: "disabled"`。 + +示例: + +```json5 +{ + channels: { + msteams: { + groupPolicy: "allowlist", + groupAllowFrom: ["user@org.com"], + }, + }, +} +``` + +**团队 + 频道允许列表** + +- 通过在 `channels.msteams.teams` 下列出团队和频道来限定群组/频道回复范围。 +- 键可以是团队 ID 或名称;频道键可以是会话 ID 或名称。 +- 当 `groupPolicy="allowlist"` 且存在团队允许列表时,仅接受列出的团队/频道(提及门控)。 +- 配置向导接受 `Team/Channel` 条目并为你存储。 +- 启动时,OpenClaw 将团队/频道和用户允许列表名称解析为 ID(当 Graph 权限允许时)并记录映射;未解析的条目保持原样。 + +示例: + +```json5 +{ + channels: { + msteams: { + groupPolicy: "allowlist", + teams: { + "My Team": { + channels: { + General: { requireMention: true }, + }, + }, + }, + }, + }, +} +``` + +## 工作原理 + +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 流量。 + +## Azure Bot 设置(前提条件) + +在配置 OpenClaw 之前,你需要创建一个 Azure Bot 资源。 + +### 步骤 1:创建 Azure Bot + +1. 前往[创建 Azure Bot](https://portal.azure.com/#create/Microsoft.AzureBot) +2. 填写 **Basics** 标签页: + + | 字段 | 值 | + | ------------------ | --------------------------------------------------- | + | **Bot handle** | 你的机器人名称,例如 `openclaw-msteams`(必须唯一) | + | **Subscription** | 选择你的 Azure 订阅 | + | **Resource group** | 新建或使用现有的 | + | **Pricing tier** | **Free** 用于开发/测试 | + | **Type of App** | **Single Tenant**(推荐 - 见下方说明) | + | **Creation type** | **Create new Microsoft App ID** | + +> **弃用通知:** 2025-07-31 之后已弃用创建新的多租户机器人。新机器人请使用 **Single Tenant**。 + +3. 点击 **Review + create** → **Create**(等待约 1-2 分钟) + +### 步骤 2:获取凭据 + +1. 前往你的 Azure Bot 资源 → **Configuration** +2. 复制 **Microsoft App ID** → 这是你的 `appId` +3. 点击 **Manage Password** → 进入应用注册 +4. 在 **Certificates & secrets** → **New client secret** → 复制 **Value** → 这是你的 `appPassword` +5. 进入 **Overview** → 复制 **Directory (tenant) ID** → 这是你的 `tenantId` + +### 步骤 3:配置消息端点 + +1. 在 Azure Bot → **Configuration** +2. 将 **Messaging endpoint** 设置为你的 webhook URL: + - 生产环境:`https://your-domain.com/api/messages` + - 本地开发:使用隧道(参见下方[本地开发](#本地开发隧道)) + +### 步骤 4:启用 Teams 频道 + +1. 在 Azure Bot → **Channels** +2. 点击 **Microsoft Teams** → Configure → Save +3. 接受服务条款 + +## 本地开发(隧道) + +Teams 无法访问 `localhost`。本地开发请使用隧道: + +**方案 A:ngrok** + +```bash +ngrok http 3978 +# 复制 https URL,例如 https://abc123.ngrok.io +# 将消息端点设置为:https://abc123.ngrok.io/api/messages +``` + +**方案 B:Tailscale Funnel** + +```bash +tailscale funnel 3978 +# 使用你的 Tailscale funnel URL 作为消息端点 +``` + +## Teams 开发者门户(替代方案) + +除了手动创建清单 ZIP 外,你可以使用 [Teams 开发者门户](https://dev.teams.microsoft.com/apps): + +1. 点击 **+ New app** +2. 填写基本信息(名称、描述、开发者信息) +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 清单更简单。 + +## 测试机器人 + +**方案 A:Azure Web Chat(先验证 webhook)** + +1. 在 Azure 门户 → 你的 Azure Bot 资源 → **Test in Web Chat** +2. 发送一条消息 - 你应该看到回复 +3. 这确认了你的 webhook 端点在 Teams 设置之前可以正常工作 + +**方案 B:Teams(安装应用后)** + +1. 安装 Teams 应用(旁加载或组织目录) +2. 在 Teams 中找到机器人并发送私信 +3. 检查 Gateway 日志中的传入活动 + +## 设置(最小纯文本) + +1. **安装 Microsoft Teams 插件** + - 从 npm:`openclaw plugins install @openclaw/msteams` + - 从本地检出:`openclaw plugins install ./extensions/msteams` + +2. **机器人注册** + - 创建 Azure Bot(见上方)并记录: + - App ID + - 客户端密钥(App password) + - 租户 ID(单租户) + +3. **Teams 应用清单** + - 包含一个 `bot` 条目,其中 `botId = `。 + - 范围:`personal`、`team`、`groupChat`。 + - `supportsFiles: true`(个人范围文件处理所必需)。 + - 添加 RSC 权限(见下方)。 + - 创建图标:`outline.png`(32x32)和 `color.png`(192x192)。 + - 将三个文件打包在一起:`manifest.json`、`outline.png`、`color.png`。 + +4. **配置 OpenClaw** + + ```json + { + "msteams": { + "enabled": true, + "appId": "", + "appPassword": "", + "tenantId": "", + "webhook": { "port": 3978, "path": "/api/messages" } + } + } + ``` + + 你也可以使用环境变量替代配置键: + - `MSTEAMS_APP_ID` + - `MSTEAMS_APP_PASSWORD` + - `MSTEAMS_TENANT_ID` + +5. **机器人端点** + - 将 Azure Bot 消息端点设置为: + - `https://:3978/api/messages`(或你选择的路径/端口)。 + +6. **运行 Gateway** + - 当插件已安装且 `msteams` 配置存在凭据时,Teams 渠道会自动启动。 + +## 历史上下文 + +- `channels.msteams.historyLimit` 控制多少条最近的频道/群组消息被包含在提示中。 +- 回退到 `messages.groupChat.historyLimit`。设置 `0` 可禁用(默认 50)。 +- 私信历史可通过 `channels.msteams.dmHistoryLimit`(用户回合数)限制。按用户覆盖:`channels.msteams.dms[""].historyLimit`。 + +## 当前 Teams RSC 权限(清单) + +以下是我们 Teams 应用清单中**现有的 resourceSpecific 权限**。它们仅在安装了应用的团队/聊天中适用。 + +**频道(团队范围):** + +- `ChannelMessage.Read.Group`(Application)- 无需 @提及即可接收所有频道消息 +- `ChannelMessage.Send.Group`(Application) +- `Member.Read.Group`(Application) +- `Owner.Read.Group`(Application) +- `ChannelSettings.Read.Group`(Application) +- `TeamMember.Read.Group`(Application) +- `TeamSettings.Read.Group`(Application) + +**群聊:** + +- `ChatMessage.Read.Chat`(Application)- 无需 @提及即可接收所有群聊消息 + +## 示例 Teams 清单(已脱敏) + +包含必需字段的最小有效示例。请替换 ID 和 URL。 + +```json +{ + "$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.23/MicrosoftTeams.schema.json", + "manifestVersion": "1.23", + "version": "1.0.0", + "id": "00000000-0000-0000-0000-000000000000", + "name": { "short": "OpenClaw" }, + "developer": { + "name": "Your Org", + "websiteUrl": "https://example.com", + "privacyUrl": "https://example.com/privacy", + "termsOfUseUrl": "https://example.com/terms" + }, + "description": { "short": "OpenClaw in Teams", "full": "OpenClaw in Teams" }, + "icons": { "outline": "outline.png", "color": "color.png" }, + "accentColor": "#5B6DEF", + "bots": [ + { + "botId": "11111111-1111-1111-1111-111111111111", + "scopes": ["personal", "team", "groupChat"], + "isNotificationOnly": false, + "supportsCalling": false, + "supportsVideo": false, + "supportsFiles": true + } + ], + "webApplicationInfo": { + "id": "11111111-1111-1111-1111-111111111111" + }, + "authorization": { + "permissions": { + "resourceSpecific": [ + { "name": "ChannelMessage.Read.Group", "type": "Application" }, + { "name": "ChannelMessage.Send.Group", "type": "Application" }, + { "name": "Member.Read.Group", "type": "Application" }, + { "name": "Owner.Read.Group", "type": "Application" }, + { "name": "ChannelSettings.Read.Group", "type": "Application" }, + { "name": "TeamMember.Read.Group", "type": "Application" }, + { "name": "TeamSettings.Read.Group", "type": "Application" }, + { "name": "ChatMessage.Read.Chat", "type": "Application" } + ] + } + } +} +``` + +### 清单注意事项(必需字段) + +- `bots[].botId` **必须**与 Azure Bot App ID 匹配。 +- `webApplicationInfo.id` **必须**与 Azure Bot App ID 匹配。 +- `bots[].scopes` 必须包含你计划使用的范围(`personal`、`team`、`groupChat`)。 +- `bots[].supportsFiles: true` 是个人范围文件处理所必需的。 +- `authorization.permissions.resourceSpecific` 必须包含频道读取/发送权限(如果你需要频道流量)。 + +### 更新现有应用 + +要更新已安装的 Teams 应用(例如添加 RSC 权限): + +1. 使用新设置更新 `manifest.json` +2. **递增 `version` 字段**(例如 `1.0.0` → `1.1.0`) +3. **重新打包**清单和图标(`manifest.json`、`outline.png`、`color.png`) +4. 上传新的 zip: + - **方案 A(Teams 管理中心):** Teams 管理中心 → Teams apps → Manage apps → 找到你的应用 → Upload new version + - **方案 B(旁加载):** 在 Teams 中 → Apps → Manage your apps → Upload a custom app +5. **对于团队频道:** 在每个团队中重新安装应用以使新权限生效 +6. **完全退出并重新启动 Teams**(不只是关闭窗口)以清除缓存的应用元数据 + +## 功能:仅 RSC vs Graph + +### 仅使用 **Teams RSC**(已安装应用,无 Graph API 权限) + +可用: + +- 读取频道消息**文本**内容。 +- 发送频道消息**文本**内容。 +- 接收**个人(私信)**文件附件。 + +不可用: + +- 频道/群组**图片或文件内容**(负载仅包含 HTML 占位符)。 +- 下载存储在 SharePoint/OneDrive 中的附件。 +- 读取消息历史(超出实时 webhook 事件范围)。 + +### 使用 **Teams RSC + Microsoft Graph Application 权限** + +新增: + +- 下载托管内容(粘贴到消息中的图片)。 +- 下载存储在 SharePoint/OneDrive 中的文件附件。 +- 通过 Graph 读取频道/聊天消息历史。 + +### RSC vs Graph API + +| 功能 | RSC 权限 | Graph API | +| -------------- | ------------------ | --------------------------- | +| **实时消息** | 是(通过 webhook) | 否(仅轮询) | +| **历史消息** | 否 | 是(可查询历史) | +| **设置复杂度** | 仅需应用清单 | 需要管理员同意 + token 流程 | +| **离线可用** | 否(必须运行中) | 是(可随时查询) | + +**总结:** RSC 用于实时监听;Graph API 用于历史访问。要补上离线期间错过的消息,你需要具有 `ChannelMessage.Read.All` 的 Graph API(需要管理员同意)。 + +## 启用 Graph 的媒体 + 历史(频道所必需) + +如果你需要**频道**中的图片/文件或想获取**消息历史**,必须启用 Microsoft Graph 权限并授予管理员同意。 + +1. 在 Entra ID(Azure AD)**应用注册**中,添加 Microsoft Graph **Application 权限**: + - `ChannelMessage.Read.All`(频道附件 + 历史) + - `Chat.Read.All` 或 `ChatMessage.Read.All`(群聊) +2. 为租户**授予管理员同意**。 +3. 递增 Teams 应用**清单版本**,重新上传,并在 **Teams 中重新安装应用**。 +4. **完全退出并重新启动 Teams** 以清除缓存的应用元数据。 + +## 已知限制 + +### Webhook 超时 + +Teams 通过 HTTP webhook 投递消息。如果处理时间过长(例如 LLM 响应缓慢),你可能会看到: + +- Gateway 超时 +- Teams 重试消息(导致重复) +- 回复丢失 + +OpenClaw 通过快速返回并主动发送回复来处理此问题,但非常慢的响应仍可能导致问题。 + +### 格式 + +Teams markdown 比 Slack 或 Discord 更有限: + +- 基本格式有效:**粗体**、_斜体_、`代码`、链接 +- 复杂 markdown(表格、嵌套列表)可能无法正确渲染 +- 支持 Adaptive Cards 用于投票和任意卡片发送(见下方) + +## 配置 + +关键设置(共享渠道模式请参见 `/gateway/configuration`): + +- `channels.msteams.enabled`:启用/禁用渠道。 +- `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.mediaAllowHosts`:入站附件主机允许列表(默认为 Microsoft/Teams 域名)。 +- `channels.msteams.requireMention`:在频道/群组中需要 @提及(默认 true)。 +- `channels.msteams.replyStyle`:`thread | top-level`(参见[回复样式:线程 vs 帖子](#回复样式线程-vs-帖子))。 +- `channels.msteams.teams..replyStyle`:按团队覆盖。 +- `channels.msteams.teams..requireMention`:按团队覆盖。 +- `channels.msteams.teams..tools`:按团队默认工具策略覆盖(`allow`/`deny`/`alsoAllow`),在频道覆盖缺失时使用。 +- `channels.msteams.teams..toolsBySender`:按团队按发送者工具策略覆盖(支持 `"*"` 通配符)。 +- `channels.msteams.teams..channels..replyStyle`:按频道覆盖。 +- `channels.msteams.teams..channels..requireMention`:按频道覆盖。 +- `channels.msteams.teams..channels..tools`:按频道工具策略覆盖(`allow`/`deny`/`alsoAllow`)。 +- `channels.msteams.teams..channels..toolsBySender`:按频道按发送者工具策略覆盖(支持 `"*"` 通配符)。 +- `channels.msteams.sharePointSiteId`:用于群聊/频道文件上传的 SharePoint 站点 ID(参见[在群聊中发送文件](#在群聊中发送文件))。 + +## 路由与会话 + +- 会话键遵循标准智能体格式(参见 [/concepts/session](/concepts/session)): + - 私信共享主会话(`agent::`)。 + - 频道/群组消息使用会话 ID: + - `agent::msteams:channel:` + - `agent::msteams:group:` + +## 回复样式:线程 vs 帖子 + +Teams 最近在相同的底层数据模型上引入了两种频道 UI 样式: + +| 样式 | 描述 | 推荐的 `replyStyle` | +| ----------------------- | ------------------------------ | ------------------- | +| **Posts**(经典) | 消息显示为卡片,下方有线程回复 | `thread`(默认) | +| **Threads**(类 Slack) | 消息线性排列,更像 Slack | `top-level` | + +**问题:** Teams API 不暴露频道使用哪种 UI 样式。如果你使用了错误的 `replyStyle`: + +- 在 Threads 样式的频道中使用 `thread` → 回复嵌套显示不自然 +- 在 Posts 样式的频道中使用 `top-level` → 回复显示为独立的顶级帖子而非在线程中 + +**解决方案:** 根据频道的设置方式按频道配置 `replyStyle`: + +```json +{ + "msteams": { + "replyStyle": "thread", + "teams": { + "19:abc...@thread.tacv2": { + "channels": { + "19:xyz...@thread.tacv2": { + "replyStyle": "top-level" + } + } + } + } + } +} +``` + +## 附件与图片 + +**当前限制:** + +- **私信:** 图片和文件附件通过 Teams bot 文件 API 可用。 +- **频道/群组:** 附件存储在 M365 存储(SharePoint/OneDrive)中。Webhook 负载仅包含 HTML 占位符,而非实际文件字节。**需要 Graph API 权限**才能下载频道附件。 + +没有 Graph 权限时,包含图片的频道消息将仅作为纯文本接收(机器人无法访问图片内容)。默认情况下,OpenClaw 仅从 Microsoft/Teams 主机名下载媒体。通过 `channels.msteams.mediaAllowHosts` 覆盖(使用 `["*"]` 允许任何主机)。 + +## 在群聊中发送文件 + +机器人可以使用 FileConsentCard 流程在私信中发送文件(内置)。然而,**在群聊/频道中发送文件**需要额外设置: + +| 场景 | 文件发送方式 | 所需设置 | +| -------------------- | --------------------------------------- | ------------------------------------ | +| **私信** | FileConsentCard → 用户接受 → 机器人上传 | 开箱即用 | +| **群聊/频道** | 上传到 SharePoint → 分享链接 | 需要 `sharePointSiteId` + Graph 权限 | +| **图片(任何场景)** | Base64 编码内联 | 开箱即用 | + +### 为什么群聊需要 SharePoint + +机器人没有个人 OneDrive 驱动器(`/me/drive` Graph API 端点对应用程序标识不可用)。要在群聊/频道中发送文件,机器人上传到 **SharePoint 站点**并创建共享链接。 + +### 设置 + +1. 在 Entra ID(Azure AD)→ 应用注册中**添加 Graph API 权限**: + - `Sites.ReadWrite.All`(Application)- 上传文件到 SharePoint + - `Chat.Read.All`(Application)- 可选,启用按用户共享链接 + +2. 为租户**授予管理员同意**。 + +3. **获取你的 SharePoint 站点 ID:** + + ```bash + # 通过 Graph Explorer 或使用有效 token 的 curl: + curl -H "Authorization: Bearer $TOKEN" \ + "https://graph.microsoft.com/v1.0/sites/{hostname}:/{site-path}" + + # 示例:对于 "contoso.sharepoint.com/sites/BotFiles" 的站点 + curl -H "Authorization: Bearer $TOKEN" \ + "https://graph.microsoft.com/v1.0/sites/contoso.sharepoint.com:/sites/BotFiles" + + # 响应包含:"id": "contoso.sharepoint.com,guid1,guid2" + ``` + +4. **配置 OpenClaw:** + ```json5 + { + channels: { + msteams: { + // ... 其他配置 ... + sharePointSiteId: "contoso.sharepoint.com,guid1,guid2", + }, + }, + } + ``` + +### 共享行为 + +| 权限 | 共享行为 | +| --------------------------------------- | ------------------------------------------ | +| 仅 `Sites.ReadWrite.All` | 组织范围共享链接(组织中的任何人都可访问) | +| `Sites.ReadWrite.All` + `Chat.Read.All` | 按用户共享链接(仅聊天成员可访问) | + +按用户共享更安全,因为只有聊天参与者可以访问文件。如果缺少 `Chat.Read.All` 权限,机器人回退到组织范围共享。 + +### 回退行为 + +| 场景 | 结果 | +| --------------------------------------- | ------------------------------------------ | +| 群聊 + 文件 + 已配置 `sharePointSiteId` | 上传到 SharePoint,发送共享链接 | +| 群聊 + 文件 + 未配置 `sharePointSiteId` | 尝试 OneDrive 上传(可能失败),仅发送文本 | +| 个人聊天 + 文件 | FileConsentCard 流程(无需 SharePoint) | +| 任何场景 + 图片 | Base64 编码内联(无需 SharePoint) | + +### 文件存储位置 + +上传的文件存储在已配置 SharePoint 站点默认文档库中的 `/OpenClawShared/` 文件夹。 + +## 投票(Adaptive Cards) + +OpenClaw 通过 Adaptive Cards 发送 Teams 投票(没有原生 Teams 投票 API)。 + +- CLI:`openclaw message poll --channel msteams --target conversation: ...` +- 投票由 Gateway 记录在 `~/.openclaw/msteams-polls.json` 中。 +- Gateway 必须保持在线以记录投票。 +- 投票尚不会自动发布结果摘要(如需要请查看存储文件)。 + +## Adaptive Cards(任意) + +使用 `message` 工具或 CLI 向 Teams 用户或会话发送任意 Adaptive Card JSON。 + +`card` 参数接受 Adaptive Card JSON 对象。提供 `card` 时,消息文本是可选的。 + +**智能体工具:** + +```json +{ + "action": "send", + "channel": "msteams", + "target": "user:", + "card": { + "type": "AdaptiveCard", + "version": "1.5", + "body": [{ "type": "TextBlock", "text": "Hello!" }] + } +} +``` + +**CLI:** + +```bash +openclaw message send --channel msteams \ + --target "conversation:19:abc...@thread.tacv2" \ + --card '{"type":"AdaptiveCard","version":"1.5","body":[{"type":"TextBlock","text":"Hello!"}]}' +``` + +卡片 schema 和示例请参见 [Adaptive Cards 文档](https://adaptivecards.io/)。目标格式详情请参见下方[目标格式](#目标格式)。 + +## 目标格式 + +Microsoft Teams 目标使用前缀区分用户和会话: + +| 目标类型 | 格式 | 示例 | +| ----------------- | -------------------------------- | ------------------------------------------------- | +| 用户(按 ID) | `user:` | `user:40a1a0ed-4ff2-4164-a219-55518990c197` | +| 用户(按名称) | `user:` | `user:John Smith`(需要 Graph API) | +| 群组/频道 | `conversation:` | `conversation:19:abc123...@thread.tacv2` | +| 群组/频道(原始) | `` | `19:abc123...@thread.tacv2`(如果包含 `@thread`) | + +**CLI 示例:** + +```bash +# 按 ID 发送给用户 +openclaw message send --channel msteams --target "user:40a1a0ed-..." --message "Hello" + +# 按显示名称发送给用户(触发 Graph API 查找) +openclaw message send --channel msteams --target "user:John Smith" --message "Hello" + +# 发送到群聊或频道 +openclaw message send --channel msteams --target "conversation:19:abc...@thread.tacv2" --message "Hello" + +# 向会话发送 Adaptive Card +openclaw message send --channel msteams --target "conversation:19:abc...@thread.tacv2" \ + --card '{"type":"AdaptiveCard","version":"1.5","body":[{"type":"TextBlock","text":"Hello"}]}' +``` + +**智能体工具示例:** + +```json +{ + "action": "send", + "channel": "msteams", + "target": "user:John Smith", + "message": "Hello!" +} +``` + +```json +{ + "action": "send", + "channel": "msteams", + "target": "conversation:19:abc...@thread.tacv2", + "card": { + "type": "AdaptiveCard", + "version": "1.5", + "body": [{ "type": "TextBlock", "text": "Hello" }] + } +} +``` + +注意:不带 `user:` 前缀时,名称默认解析为群组/团队。通过显示名称定位人员时请始终使用 `user:`。 + +## 主动消息 + +- 主动消息仅在用户**已交互后**才可能,因为我们在那个时候存储会话引用。 +- `dmPolicy` 和允许列表门控请参见 `/gateway/configuration`。 + +## 团队和频道 ID(常见陷阱) + +Teams URL 中的 `groupId` 查询参数**不是**用于配置的团队 ID。请从 URL 路径中提取 ID: + +**团队 URL:** + +``` +https://teams.microsoft.com/l/team/19%3ABk4j...%40thread.tacv2/conversations?groupId=... + └────────────────────────────┘ + 团队 ID(URL 解码此部分) +``` + +**频道 URL:** + +``` +https://teams.microsoft.com/l/channel/19%3A15bc...%40thread.tacv2/ChannelName?groupId=... + └─────────────────────────┘ + 频道 ID(URL 解码此部分) +``` + +**用于配置:** + +- 团队 ID = `/team/` 后的路径段(URL 解码后,例如 `19:Bk4j...@thread.tacv2`) +- 频道 ID = `/channel/` 后的路径段(URL 解码后) +- **忽略** `groupId` 查询参数 + +## 私有频道 + +机器人在私有频道中的支持有限: + +| 功能 | 标准频道 | 私有频道 | +| ------------------- | -------- | ---------------- | +| 机器人安装 | 是 | 有限 | +| 实时消息(webhook) | 是 | 可能不可用 | +| RSC 权限 | 是 | 行为可能不同 | +| @提及 | 是 | 如果机器人可访问 | +| Graph API 历史 | 是 | 是(需要权限) | + +**私有频道不可用时的变通方案:** + +1. 使用标准频道进行机器人交互 +2. 使用私信 - 用户始终可以直接给机器人发消息 +3. 使用 Graph API 进行历史访问(需要 `ChannelMessage.Read.All`) + +## 故障排除 + +### 常见问题 + +- **频道中图片不显示:** 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 上传,打开浏览器 DevTools(F12)→ Network 标签页,检查响应体中的实际错误。 +- **旁加载失败:** 尝试"Upload an app to your org's app catalog"而非"Upload a custom app" - 这通常可以绕过旁加载限制。 + +### RSC 权限不生效 + +1. 验证 `webApplicationInfo.id` 与你的机器人 App ID 完全匹配 +2. 重新上传应用并在团队/聊天中重新安装 +3. 检查你的组织管理员是否阻止了 RSC 权限 +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 应用清单 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 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) diff --git a/docs/zh-CN/channels/nextcloud-talk.md b/docs/zh-CN/channels/nextcloud-talk.md new file mode 100644 index 0000000000..57037bd33f --- /dev/null +++ b/docs/zh-CN/channels/nextcloud-talk.md @@ -0,0 +1,141 @@ +--- +read_when: + - 开发 Nextcloud Talk 渠道功能 +summary: Nextcloud Talk 支持状态、功能和配置 +title: Nextcloud Talk +x-i18n: + generated_at: "2026-02-01T19:26:32Z" + model: claude-opus-4-5 + provider: pi + source_hash: 21b7b9756c4356a76dc0f14c10e44ed74a284cf3badf87e2df75eb88d8a90c31 + source_path: channels/nextcloud-talk.md + workflow: 14 +--- + +# Nextcloud Talk(插件) + +状态:通过插件支持(webhook 机器人)。支持私信、房间、回应和 markdown 消息。 + +## 需要插件 + +Nextcloud Talk 作为插件发布,不包含在核心安装中。 + +通过 CLI 安装(npm 注册表): + +```bash +openclaw plugins install @openclaw/nextcloud-talk +``` + +本地检出(从 git 仓库运行时): + +```bash +openclaw plugins install ./extensions/nextcloud-talk +``` + +如果你在配置/上手引导期间选择了 Nextcloud Talk 并检测到 git 检出,OpenClaw 会自动提供本地安装路径。 + +详情:[插件](/plugin) + +## 快速设置(新手) + +1. 安装 Nextcloud Talk 插件。 +2. 在你的 Nextcloud 服务器上创建一个机器人: + ```bash + ./occ talk:bot:install "OpenClaw" "" "" --feature reaction + ``` +3. 在目标房间设置中启用该机器人。 +4. 配置 OpenClaw: + - 配置:`channels.nextcloud-talk.baseUrl` + `channels.nextcloud-talk.botSecret` + - 或环境变量:`NEXTCLOUD_TALK_BOT_SECRET`(仅默认账户) +5. 重启 Gateway(或完成上手引导)。 + +最小配置: + +```json5 +{ + channels: { + "nextcloud-talk": { + enabled: true, + baseUrl: "https://cloud.example.com", + botSecret: "shared-secret", + dmPolicy: "pairing", + }, + }, +} +``` + +## 注意事项 + +- 机器人无法主动发起私信。用户必须先给机器人发消息。 +- Webhook URL 必须能被 Gateway 访问;如果在代理后面,请设置 `webhookPublicUrl`。 +- 机器人 API 不支持媒体上传;媒体以 URL 形式发送。 +- Webhook 负载不区分私信和房间;设置 `apiUser` + `apiPassword` 以启用房间类型查询(否则私信会被视为房间)。 + +## 访问控制(私信) + +- 默认:`channels.nextcloud-talk.dmPolicy = "pairing"`。未知发送者会收到配对码。 +- 通过以下方式批准: + - `openclaw pairing list nextcloud-talk` + - `openclaw pairing approve nextcloud-talk ` +- 公开私信:`channels.nextcloud-talk.dmPolicy="open"` 加上 `channels.nextcloud-talk.allowFrom=["*"]`。 + +## 房间(群组) + +- 默认:`channels.nextcloud-talk.groupPolicy = "allowlist"`(提及门控)。 +- 使用 `channels.nextcloud-talk.rooms` 允许列表中的房间: + +```json5 +{ + channels: { + "nextcloud-talk": { + rooms: { + "room-token": { requireMention: true }, + }, + }, + }, +} +``` + +- 要不允许任何房间,保持允许列表为空或设置 `channels.nextcloud-talk.groupPolicy="disabled"`。 + +## 功能 + +| 功能 | 状态 | +| -------- | ------ | +| 私信 | 支持 | +| 房间 | 支持 | +| 线程 | 不支持 | +| 媒体 | 仅 URL | +| 回应 | 支持 | +| 原生命令 | 不支持 | + +## 配置参考(Nextcloud Talk) + +完整配置:[配置](/gateway/configuration) + +提供商选项: + +- `channels.nextcloud-talk.enabled`:启用/禁用渠道启动。 +- `channels.nextcloud-talk.baseUrl`:Nextcloud 实例 URL。 +- `channels.nextcloud-talk.botSecret`:机器人共享密钥。 +- `channels.nextcloud-talk.botSecretFile`:密钥文件路径。 +- `channels.nextcloud-talk.apiUser`:用于房间查询的 API 用户(私信检测)。 +- `channels.nextcloud-talk.apiPassword`:用于房间查询的 API/应用密码。 +- `channels.nextcloud-talk.apiPasswordFile`:API 密码文件路径。 +- `channels.nextcloud-talk.webhookPort`:webhook 监听端口(默认:8788)。 +- `channels.nextcloud-talk.webhookHost`:webhook 主机(默认:0.0.0.0)。 +- `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.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.blockStreaming`:禁用此渠道的分块流式传输。 +- `channels.nextcloud-talk.blockStreamingCoalesce`:分块流式传输合并调优。 +- `channels.nextcloud-talk.mediaMaxMb`:入站媒体上限(MB)。 diff --git a/docs/zh-CN/channels/nostr.md b/docs/zh-CN/channels/nostr.md new file mode 100644 index 0000000000..c052025738 --- /dev/null +++ b/docs/zh-CN/channels/nostr.md @@ -0,0 +1,240 @@ +--- +read_when: + - 你想让 OpenClaw 通过 Nostr 接收私信 + - 你正在设置去中心化消息 +summary: 通过 NIP-04 加密消息的 Nostr 私信渠道 +title: Nostr +x-i18n: + generated_at: "2026-02-01T19:26:55Z" + model: claude-opus-4-5 + provider: pi + source_hash: 6b9fe4c74bf5e7c0f59bbaa129ec5270fd29a248551a8a9a7dde6cff8fb46111 + source_path: channels/nostr.md + workflow: 14 +--- + +# Nostr + +**状态:** 可选插件(默认禁用)。 + +Nostr 是一个去中心化的社交网络协议。此渠道使 OpenClaw 能够通过 NIP-04 接收和回复加密私信(DM)。 + +## 安装(按需) + +### 上手引导(推荐) + +- 上手引导向导(`openclaw onboard`)和 `openclaw channels add` 会列出可选的渠道插件。 +- 选择 Nostr 时会提示你按需安装插件。 + +安装默认行为: + +- **开发渠道 + 可用 git 检出:** 使用本地插件路径。 +- **稳定版/测试版:** 从 npm 下载。 + +你始终可以在提示中覆盖此选择。 + +### 手动安装 + +```bash +openclaw plugins install @openclaw/nostr +``` + +使用本地检出(开发工作流): + +```bash +openclaw plugins install --link /extensions/nostr +``` + +安装或启用插件后请重启 Gateway。 + +## 快速设置 + +1. 生成 Nostr 密钥对(如需要): + +```bash +# 使用 nak +nak key generate +``` + +2. 添加到配置: + +```json +{ + "channels": { + "nostr": { + "privateKey": "${NOSTR_PRIVATE_KEY}" + } + } +} +``` + +3. 导出密钥: + +```bash +export NOSTR_PRIVATE_KEY="nsec1..." +``` + +4. 重启 Gateway。 + +## 配置参考 + +| 键 | 类型 | 默认值 | 描述 | +| ------------ | -------- | ------------------------------------------- | --------------------------- | +| `privateKey` | string | 必填 | `nsec` 或十六进制格式的私钥 | +| `relays` | string[] | `['wss://relay.damus.io', 'wss://nos.lol']` | 中继 URL(WebSocket) | +| `dmPolicy` | string | `pairing` | 私信访问策略 | +| `allowFrom` | string[] | `[]` | 允许的发送者公钥 | +| `enabled` | boolean | `true` | 启用/禁用渠道 | +| `name` | string | - | 显示名称 | +| `profile` | object | - | NIP-01 个人资料元数据 | + +## 个人资料元数据 + +个人资料数据作为 NIP-01 `kind:0` 事件发布。你可以从控制 UI(Channels -> Nostr -> Profile)管理它,或直接在配置中设置。 + +示例: + +```json +{ + "channels": { + "nostr": { + "privateKey": "${NOSTR_PRIVATE_KEY}", + "profile": { + "name": "openclaw", + "displayName": "OpenClaw", + "about": "Personal assistant DM bot", + "picture": "https://example.com/avatar.png", + "banner": "https://example.com/banner.png", + "website": "https://example.com", + "nip05": "openclaw@example.com", + "lud16": "openclaw@example.com" + } + } + } +} +``` + +注意事项: + +- 个人资料 URL 必须使用 `https://`。 +- 从中继导入会合并字段并保留本地覆盖。 + +## 访问控制 + +### 私信策略 + +- **pairing**(默认):未知发送者会收到配对码。 +- **allowlist**:只有 `allowFrom` 中的公钥可以发私信。 +- **open**:公开入站私信(需要 `allowFrom: ["*"]`)。 +- **disabled**:忽略入站私信。 + +### 允许列表示例 + +```json +{ + "channels": { + "nostr": { + "privateKey": "${NOSTR_PRIVATE_KEY}", + "dmPolicy": "allowlist", + "allowFrom": ["npub1abc...", "npub1xyz..."] + } + } +} +``` + +## 密钥格式 + +接受的格式: + +- **私钥:** `nsec...` 或 64 字符十六进制 +- **公钥(`allowFrom`):** `npub...` 或十六进制 + +## 中继 + +默认值:`relay.damus.io` 和 `nos.lol`。 + +```json +{ + "channels": { + "nostr": { + "privateKey": "${NOSTR_PRIVATE_KEY}", + "relays": ["wss://relay.damus.io", "wss://relay.primal.net", "wss://nostr.wine"] + } + } +} +``` + +建议: + +- 使用 2-3 个中继以实现冗余。 +- 避免使用过多中继(延迟、重复)。 +- 付费中继可以提高可靠性。 +- 本地中继适用于测试(`ws://localhost:7777`)。 + +## 协议支持 + +| NIP | 状态 | 描述 | +| ------ | ------ | ----------------------------- | +| NIP-01 | 支持 | 基本事件格式 + 个人资料元数据 | +| NIP-04 | 支持 | 加密私信(`kind:4`) | +| NIP-17 | 计划中 | Gift-wrapped 私信 | +| NIP-44 | 计划中 | 版本化加密 | + +## 测试 + +### 本地中继 + +```bash +# 启动 strfry +docker run -p 7777:7777 ghcr.io/hoytech/strfry +``` + +```json +{ + "channels": { + "nostr": { + "privateKey": "${NOSTR_PRIVATE_KEY}", + "relays": ["ws://localhost:7777"] + } + } +} +``` + +### 手动测试 + +1. 从日志中记下机器人公钥(npub)。 +2. 打开一个 Nostr 客户端(Damus、Amethyst 等)。 +3. 私信机器人公钥。 +4. 验证回复。 + +## 故障排除 + +### 无法收到消息 + +- 验证私钥是否有效。 +- 确保中继 URL 可达并使用 `wss://`(本地使用 `ws://`)。 +- 确认 `enabled` 未设为 `false`。 +- 检查 Gateway 日志中的中继连接错误。 + +### 无法发送回复 + +- 检查中继是否接受写入。 +- 验证出站连接。 +- 注意中继速率限制。 + +### 重复回复 + +- 使用多个中继时属于预期行为。 +- 消息按事件 ID 去重;只有第一次投递会触发回复。 + +## 安全 + +- 绝不提交私钥。 +- 使用环境变量存储密钥。 +- 生产机器人请考虑使用 `allowlist`。 + +## 限制(MVP) + +- 仅支持私信(无群聊)。 +- 不支持媒体附件。 +- 仅支持 NIP-04(计划支持 NIP-17 gift-wrap)。 diff --git a/docs/zh-CN/channels/signal.md b/docs/zh-CN/channels/signal.md new file mode 100644 index 0000000000..92d6712524 --- /dev/null +++ b/docs/zh-CN/channels/signal.md @@ -0,0 +1,209 @@ +--- +read_when: + - 设置 Signal 支持 + - 调试 Signal 收发 +summary: 通过 signal-cli(JSON-RPC + SSE)实现 Signal 支持、设置和号码模型 +title: Signal +x-i18n: + generated_at: "2026-02-01T19:27:25Z" + model: claude-opus-4-5 + provider: pi + source_hash: ca4de8b3685017f54a959e3e2699357ab40b3e4e68574bd7fb5739e4679e7d8a + source_path: channels/signal.md + workflow: 14 +--- + +# Signal(signal-cli) + +状态:外部 CLI 集成。Gateway 通过 HTTP JSON-RPC + SSE 与 `signal-cli` 通信。 + +## 快速设置(新手) + +1. 为机器人使用一个**单独的 Signal 号码**(推荐)。 +2. 安装 `signal-cli`(需要 Java)。 +3. 链接机器人设备并启动守护进程: + - `signal-cli link -n "OpenClaw"` +4. 配置 OpenClaw 并启动 Gateway。 + +最小配置: + +```json5 +{ + channels: { + signal: { + enabled: true, + account: "+15551234567", + cliPath: "signal-cli", + dmPolicy: "pairing", + allowFrom: ["+15557654321"], + }, + }, +} +``` + +## 它是什么 + +- 通过 `signal-cli` 的 Signal 渠道(非嵌入式 libsignal)。 +- 确定性路由:回复始终发回 Signal。 +- 私信共享智能体的主会话;群组是隔离的(`agent::signal:group:`)。 + +## 配置写入 + +默认情况下,Signal 允许通过 `/config set|unset` 触发的配置更新写入(需要 `commands.config: true`)。 + +通过以下方式禁用: + +```json5 +{ + channels: { signal: { configWrites: false } }, +} +``` + +## 号码模型(重要) + +- Gateway 连接到一个 **Signal 设备**(`signal-cli` 账户)。 +- 如果你在**个人 Signal 账户**上运行机器人,它会忽略你自己的消息(循环保护)。 +- 要实现"我给机器人发消息它回复我",请使用一个**单独的机器人号码**。 + +## 设置(快速路径) + +1. 安装 `signal-cli`(需要 Java)。 +2. 链接机器人账户: + - `signal-cli link -n "OpenClaw"` 然后在 Signal 中扫描二维码。 +3. 配置 Signal 并启动 Gateway。 + +示例: + +```json5 +{ + channels: { + signal: { + enabled: true, + account: "+15551234567", + cliPath: "signal-cli", + dmPolicy: "pairing", + allowFrom: ["+15557654321"], + }, + }, +} +``` + +多账户支持:使用 `channels.signal.accounts`,每个账户配置独立选项和可选的 `name`。共享模式请参阅 [`gateway/configuration`](/gateway/configuration#telegramaccounts--discordaccounts--slackaccounts--signalaccounts--imessageaccounts)。 + +## 外部守护进程模式(httpUrl) + +如果你想自行管理 `signal-cli`(JVM 冷启动慢、容器初始化或共享 CPU),可以单独运行守护进程并将 OpenClaw 指向它: + +```json5 +{ + channels: { + signal: { + httpUrl: "http://127.0.0.1:8080", + autoStart: false, + }, + }, +} +``` + +这会跳过 OpenClaw 内部的自动启动和启动等待。当自动启动较慢时,请设置 `channels.signal.startupTimeoutMs`。 + +## 访问控制(私信 + 群组) + +私信: + +- 默认:`channels.signal.dmPolicy = "pairing"`。 +- 未知发送者会收到配对码;在批准之前消息会被忽略(配对码 1 小时后过期)。 +- 通过以下方式批准: + - `openclaw pairing list signal` + - `openclaw pairing approve signal ` +- 配对是 Signal 私信的默认令牌交换方式。详情:[配对](/start/pairing) +- 仅 UUID 的发送者(来自 `sourceUuid`)以 `uuid:` 形式存储在 `channels.signal.allowFrom` 中。 + +群组: + +- `channels.signal.groupPolicy = open | allowlist | disabled`。 +- 当设置为 `allowlist` 时,`channels.signal.groupAllowFrom` 控制谁可以在群组中触发。 + +## 工作原理(行为) + +- `signal-cli` 作为守护进程运行;Gateway 通过 SSE 读取事件。 +- 入站消息被标准化为共享的渠道信封。 +- 回复始终路由回同一个号码或群组。 + +## 媒体 + 限制 + +- 出站文本按 `channels.signal.textChunkLimit` 分块(默认 4000)。 +- 可选的换行分块:设置 `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)。 + +## 输入指示 + 已读回执 + +- **输入指示**:OpenClaw 通过 `signal-cli sendTyping` 发送输入信号,并在回复运行期间刷新。 +- **已读回执**:当 `channels.signal.sendReadReceipts` 为 true 时,OpenClaw 为允许的私信转发已读回执。 +- signal-cli 不暴露群组的已读回执。 + +## 回应(message 工具) + +- 使用 `message action=react` 配合 `channel=signal`。 +- 目标:发送者 E.164 或 UUID(使用配对输出中的 `uuid:`;裸 UUID 也可以)。 +- `messageId` 是你要回应的消息的 Signal 时间戳。 +- 群组回应需要 `targetAuthor` 或 `targetAuthorUuid`。 + +示例: + +``` +message action=react channel=signal target=uuid:123e4567-e89b-12d3-a456-426614174000 messageId=1737630212345 emoji=🔥 +message action=react channel=signal target=+15551234567 messageId=1737630212345 emoji=🔥 remove=true +message action=react channel=signal target=signal:group: targetAuthor=uuid: messageId=1737630212345 emoji=✅ +``` + +配置: + +- `channels.signal.actions.reactions`:启用/禁用回应操作(默认 true)。 +- `channels.signal.reactionLevel`:`off | ack | minimal | extensive`。 + - `off`/`ack` 禁用智能体回应(message 工具 `react` 会报错)。 + - `minimal`/`extensive` 启用智能体回应并设置引导级别。 +- 按账户覆盖:`channels.signal.accounts..actions.reactions`、`channels.signal.accounts..reactionLevel`。 + +## 投递目标(CLI/定时任务) + +- 私信:`signal:+15551234567`(或纯 E.164)。 +- UUID 私信:`uuid:`(或裸 UUID)。 +- 群组:`signal:group:`。 +- 用户名:`username:`(如果你的 Signal 账户支持)。 + +## 配置参考(Signal) + +完整配置:[配置](/gateway/configuration) + +提供商选项: + +- `channels.signal.enabled`:启用/禁用渠道启动。 +- `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.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:`)。`open` 需要 `"*"`。Signal 没有用户名;使用电话/UUID 标识。 +- `channels.signal.groupPolicy`:`open | allowlist | disabled`(默认:allowlist)。 +- `channels.signal.groupAllowFrom`:群组发送者允许列表。 +- `channels.signal.historyLimit`:包含为上下文的最大群组消息数(0 禁用)。 +- `channels.signal.dmHistoryLimit`:私信历史限制(用户回合数)。按用户覆盖:`channels.signal.dms[""].historyLimit`。 +- `channels.signal.textChunkLimit`:出站分块大小(字符)。 +- `channels.signal.chunkMode`:`length`(默认)或 `newline`,在按长度分块之前按空行(段落边界)分割。 +- `channels.signal.mediaMaxMb`:入站/出站媒体上限(MB)。 + +相关全局选项: + +- `agents.list[].groupChat.mentionPatterns`(Signal 不支持原生提及)。 +- `messages.groupChat.mentionPatterns`(全局回退)。 +- `messages.responsePrefix`。 diff --git a/docs/zh-CN/channels/slack.md b/docs/zh-CN/channels/slack.md new file mode 100644 index 0000000000..0eba79c001 --- /dev/null +++ b/docs/zh-CN/channels/slack.md @@ -0,0 +1,530 @@ +--- +read_when: 设置 Slack 或调试 Slack Socket/HTTP 模式 +summary: Slack 的 Socket 或 HTTP webhook 模式设置 +title: Slack +x-i18n: + generated_at: "2026-02-01T19:29:15Z" + model: claude-opus-4-5 + provider: pi + source_hash: 703b4b4333bebfef26b64710ba452bdfc3e7d2115048d4e552e8659425b3609b + source_path: channels/slack.md + workflow: 14 +--- + +# Slack + +## Socket 模式(默认) + +### 快速设置(新手) + +1. 创建一个 Slack 应用并启用 **Socket Mode**。 +2. 创建一个 **App Token**(`xapp-...`)和 **Bot Token**(`xoxb-...`)。 +3. 为 OpenClaw 设置 token 并启动 Gateway。 + +最小配置: + +```json5 +{ + channels: { + slack: { + enabled: true, + appToken: "xapp-...", + botToken: "xoxb-...", + }, + }, +} +``` + +### 设置 + +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` + - `reaction_added`、`reaction_removed` + - `member_joined_channel`、`member_left_channel` + - `channel_rename` + - `pin_added`、`pin_removed` +6. 邀请机器人加入你希望它读取的频道。 +7. Slash Commands → 如果你使用 `channels.slack.slashCommand`,创建 `/openclaw`。如果你启用原生命令,为每个内置命令添加一个斜杠命令(名称与 `/help` 列表相同)。Slack 的原生命令默认关闭,除非你设置 `channels.slack.commands.native: true`(全局 `commands.native` 为 `"auto"`,Slack 下默认关闭)。 +8. App Home → 启用 **Messages Tab** 以便用户可以给机器人发私信。 + +使用下方清单以保持范围和事件同步。 + +多账户支持:使用 `channels.slack.accounts`,每个账户配置独立 token 和可选的 `name`。共享模式请参阅 [`gateway/configuration`](/gateway/configuration#telegramaccounts--discordaccounts--slackaccounts--signalaccounts--imessageaccounts)。 + +### OpenClaw 配置(最小) + +通过环境变量设置 token(推荐): + +- `SLACK_APP_TOKEN=xapp-...` +- `SLACK_BOT_TOKEN=xoxb-...` + +或通过配置: + +```json5 +{ + channels: { + slack: { + enabled: true, + appToken: "xapp-...", + botToken: "xoxb-...", + }, + }, +} +``` + +### 用户 token(可选) + +OpenClaw 可以使用 Slack 用户 token(`xoxp-...`)进行读取操作(历史记录、置顶、回应、表情、成员信息)。默认保持只读:有用户 token 时读取操作优先使用它,写入仍使用 bot token,除非你明确选择。即使设置了 `userTokenReadOnly: false`,当 bot token 可用时写入操作仍优先使用它。 + +用户 token 在配置文件中设置(不支持环境变量)。多账户时设置 `channels.slack.accounts..userToken`。 + +同时使用 bot + app + user token 的示例: + +```json5 +{ + channels: { + slack: { + enabled: true, + appToken: "xapp-...", + botToken: "xoxb-...", + userToken: "xoxp-...", + }, + }, +} +``` + +显式设置 userTokenReadOnly 的示例(允许用户 token 写入): + +```json5 +{ + channels: { + slack: { + enabled: true, + appToken: "xapp-...", + botToken: "xoxb-...", + userToken: "xoxp-...", + userTokenReadOnly: false, + }, + }, +} +``` + +#### Token 使用 + +- 读取操作(历史记录、回应列表、置顶列表、表情列表、成员信息、搜索)在配置了用户 token 时优先使用,否则使用 bot token。 +- 写入操作(发送/编辑/删除消息、添加/移除回应、置顶/取消置顶、文件上传)默认使用 bot token。如果 `userTokenReadOnly: false` 且没有 bot token 可用,OpenClaw 回退到用户 token。 + +### 历史上下文 + +- `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。 + +### 设置 + +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`)。 +5. **Interactivity & Shortcuts** → 启用并设置相同的 **Request URL**。 +6. **Slash Commands** → 为你的命令设置相同的 **Request URL**。 + +示例请求 URL: +`https://gateway-host/slack/events` + +### OpenClaw 配置(最小) + +```json5 +{ + channels: { + slack: { + enabled: true, + mode: "http", + botToken: "xoxb-...", + signingSecret: "your-signing-secret", + webhookPath: "/slack/events", + }, + }, +} +``` + +多账户 HTTP 模式:设置 `channels.slack.accounts..mode = "http"` 并为每个账户提供唯一的 `webhookPath`,以便每个 Slack 应用可以指向自己的 URL。 + +### 清单(可选) + +使用此 Slack 应用清单可快速创建应用(根据需要调整名称/命令)。如果你计划配置用户 token,请包含用户范围。 + +```json +{ + "display_information": { + "name": "OpenClaw", + "description": "Slack connector for OpenClaw" + }, + "features": { + "bot_user": { + "display_name": "OpenClaw", + "always_online": false + }, + "app_home": { + "messages_tab_enabled": true, + "messages_tab_read_only_enabled": false + }, + "slash_commands": [ + { + "command": "/openclaw", + "description": "Send a message to OpenClaw", + "should_escape": false + } + ] + }, + "oauth_config": { + "scopes": { + "bot": [ + "chat:write", + "channels:history", + "channels:read", + "groups:history", + "groups:read", + "groups:write", + "im:history", + "im:read", + "im:write", + "mpim:history", + "mpim:read", + "mpim:write", + "users:read", + "app_mentions:read", + "reactions:read", + "reactions:write", + "pins:read", + "pins:write", + "emoji:read", + "commands", + "files:read", + "files:write" + ], + "user": [ + "channels:history", + "channels:read", + "groups:history", + "groups:read", + "im:history", + "im:read", + "mpim:history", + "mpim:read", + "users:read", + "reactions:read", + "pins:read", + "emoji:read", + "search:read" + ] + } + }, + "settings": { + "socket_mode_enabled": true, + "event_subscriptions": { + "bot_events": [ + "app_mention", + "message.channels", + "message.groups", + "message.im", + "message.mpim", + "reaction_added", + "reaction_removed", + "member_joined_channel", + "member_left_channel", + "channel_rename", + "pin_added", + "pin_removed" + ] + } + } +} +``` + +如果你启用原生命令,为你想暴露的每个命令添加一个 `slash_commands` 条目(匹配 `/help` 列表)。通过 `channels.slack.commands.native` 覆盖。 + +## 范围(当前 vs 可选) + +Slack 的 Conversations API 按类型设定范围:你只需要你实际使用的会话类型(channels、groups、im、mpim)对应的范围。概览请参见 https://docs.slack.dev/apis/web-api/using-the-conversations-api/。 + +### Bot token 范围(必需) + +- `chat:write`(通过 `chat.postMessage` 发送/更新/删除消息) + https://docs.slack.dev/reference/methods/chat.postMessage +- `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`(用户查找) + https://docs.slack.dev/reference/methods/users.info +- `reactions:read`、`reactions:write`(`reactions.get` / `reactions.add`) + https://docs.slack.dev/reference/methods/reactions.get + https://docs.slack.dev/reference/methods/reactions.add +- `pins:read`、`pins:write`(`pins.list` / `pins.add` / `pins.remove`) + https://docs.slack.dev/reference/scopes/pins.read + https://docs.slack.dev/reference/scopes/pins.write +- `emoji:read`(`emoji.list`) + https://docs.slack.dev/reference/scopes/emoji.read +- `files:write`(通过 `files.uploadV2` 上传) + https://docs.slack.dev/messaging/working-with-files/#upload + +### 用户 token 范围(可选,默认只读) + +如果你配置了 `channels.slack.userToken`,请在 **User Token Scopes** 下添加这些。 + +- `channels:history`、`groups:history`、`im:history`、`mpim:history` +- `channels:read`、`groups:read`、`im:read`、`mpim:read` +- `users:read` +- `reactions:read` +- `pins:read` +- `emoji:read` +- `search:read` + +### 目前不需要(但未来可能) + +- `mpim:write`(仅在我们添加群组私信打开/私信开始功能时需要,通过 `conversations.open`) +- `groups:write`(仅在我们添加私有频道管理时需要:创建/重命名/邀请/归档) +- `chat:write.public`(仅在我们想向机器人未加入的频道发帖时需要) + https://docs.slack.dev/reference/scopes/chat.write.public +- `users:read.email`(仅在我们需要从 `users.info` 获取邮箱字段时需要) + https://docs.slack.dev/changelog/2017-04-narrowing-email-access +- `files:read`(仅在我们开始列出/读取文件元数据时需要) + +## 配置 + +Slack 仅使用 Socket Mode(无 HTTP webhook 服务器)。提供两个 token: + +```json +{ + "slack": { + "enabled": true, + "botToken": "xoxb-...", + "appToken": "xapp-...", + "groupPolicy": "allowlist", + "dm": { + "enabled": true, + "policy": "pairing", + "allowFrom": ["U123", "U456", "*"], + "groupEnabled": false, + "groupChannels": ["G123"], + "replyToMode": "all" + }, + "channels": { + "C123": { "allow": true, "requireMention": true }, + "#general": { + "allow": true, + "requireMention": true, + "users": ["U123"], + "skills": ["search", "docs"], + "systemPrompt": "Keep answers short." + } + }, + "reactionNotifications": "own", + "reactionAllowlist": ["U123"], + "replyToMode": "off", + "actions": { + "reactions": true, + "messages": true, + "pins": true, + "memberInfo": true, + "emojiList": true + }, + "slashCommand": { + "enabled": true, + "name": "openclaw", + "sessionPrefix": "slack:slash", + "ephemeral": true + }, + "textChunkLimit": 4000, + "mediaMaxMb": 20 + } +} +``` + +Token 也可以通过环境变量提供: + +- `SLACK_BOT_TOKEN` +- `SLACK_APP_TOKEN` + +确认回应由 `messages.ackReaction` + `messages.ackReactionScope` 全局控制。使用 `messages.removeAckAfterReply` 在机器人回复后清除确认回应。 + +## 限制 + +- 出站文本按 `channels.slack.textChunkLimit` 分块(默认 4000)。 +- 可选的换行分块:设置 `channels.slack.chunkMode="newline"` 在按长度分块之前按空行(段落边界)分割。 +- 媒体上传上限由 `channels.slack.mediaMaxMb` 限制(默认 20)。 + +## 回复线程 + +默认情况下,OpenClaw 在主频道中回复。使用 `channels.slack.replyToMode` 控制自动线程行为: + +| 模式 | 行为 | +| ------- | ------------------------------------------------------------------------------------------------ | +| `off` | **默认。** 在主频道回复。仅在触发消息已在线程中时才在线程中回复。 | +| `first` | 第一条回复进入线程(在触发消息下方),后续回复进入主频道。适用于保持上下文可见同时避免线程杂乱。 | +| `all` | 所有回复都进入线程。保持对话集中但可能降低可见性。 | + +该模式同时适用于自动回复和智能体工具调用(`slack sendMessage`)。 + +### 按聊天类型设置线程 + +你可以通过设置 `channels.slack.replyToModeByChatType` 为不同聊天类型配置不同的线程行为: + +```json5 +{ + channels: { + slack: { + replyToMode: "off", // 频道默认 + replyToModeByChatType: { + direct: "all", // 私信始终使用线程 + group: "first", // 群组私信/MPIM 第一条回复使用线程 + }, + }, + }, +} +``` + +支持的聊天类型: + +- `direct`:一对一私信(Slack `im`) +- `group`:群组私信 / MPIM(Slack `mpim`) +- `channel`:标准频道(公共/私有) + +优先级: + +1. `replyToModeByChatType.` +2. `replyToMode` +3. 提供商默认值(`off`) + +旧版 `channels.slack.dm.replyToMode` 在未设置聊天类型覆盖时仍作为 `direct` 的回退值。 + +示例: + +仅私信使用线程: + +```json5 +{ + channels: { + slack: { + replyToMode: "off", + replyToModeByChatType: { direct: "all" }, + }, + }, +} +``` + +群组私信使用线程但频道保持在根级: + +```json5 +{ + channels: { + slack: { + replyToMode: "off", + replyToModeByChatType: { group: "first" }, + }, + }, +} +``` + +频道使用线程,私信保持在根级: + +```json5 +{ + channels: { + slack: { + replyToMode: "first", + replyToModeByChatType: { direct: "off", group: "off" }, + }, + }, +} +``` + +### 手动线程标签 + +对于精细控制,在智能体回复中使用以下标签: + +- `[[reply_to_current]]` — 回复触发消息(开始/继续线程)。 +- `[[reply_to:]]` — 回复特定消息 ID。 + +## 会话 + 路由 + +- 私信共享 `main` 会话(与 WhatsApp/Telegram 类似)。 +- 频道映射到 `agent::slack:channel:` 会话。 +- 斜杠命令使用 `agent::slack:slash:` 会话(前缀可通过 `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` 可绕过命令的访问组检查。 +- 完整命令列表 + 配置:[斜杠命令](/tools/slash-commands) + +## 私信安全(配对) + +- 默认:`channels.slack.dm.policy="pairing"` — 未知私信发送者会收到配对码(1 小时后过期)。 +- 通过 `openclaw pairing approve slack ` 批准。 +- 要允许任何人:设置 `channels.slack.dm.policy="open"` 和 `channels.slack.dm.allowFrom=["*"]`。 +- `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(当 token 允许时)并记录映射;未解析的条目保持原样。 +- 要**不允许任何频道**,设置 `channels.slack.groupPolicy: "disabled"`(或保持空的允许列表)。 + +频道选项(`channels.slack.channels.` 或 `channels.slack.channels.`): + +- `allow`:当 `groupPolicy="allowlist"` 时允许/拒绝频道。 +- `requireMention`:频道的提及门控。 +- `tools`:可选的按频道工具策略覆盖(`allow`/`deny`/`alsoAllow`)。 +- `toolsBySender`:可选的频道内按发送者工具策略覆盖(键为发送者 ID/@用户名/邮箱;支持 `"*"` 通配符)。 +- `allowBots`:允许此频道中机器人发送的消息(默认:false)。 +- `users`:可选的按频道用户允许列表。 +- `skills`:技能过滤器(省略 = 所有技能,空 = 无)。 +- `systemPrompt`:频道的额外系统提示(与主题/目的合并)。 +- `enabled`:设置 `false` 可禁用频道。 + +## 投递目标 + +在定时任务/CLI 发送中使用: + +- `user:` 用于私信 +- `channel:` 用于频道 + +## 工具操作 + +Slack 工具操作可通过 `channels.slack.actions.*` 控制: + +| 操作组 | 默认值 | 说明 | +| ---------- | ------ | ------------------- | +| reactions | 启用 | 添加回应 + 列出回应 | +| messages | 启用 | 读取/发送/编辑/删除 | +| pins | 启用 | 置顶/取消置顶/列出 | +| memberInfo | 启用 | 成员信息 | +| emojiList | 启用 | 自定义表情列表 | + +## 安全注意事项 + +- 写入操作默认使用 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`(使用 `reactionAllowlist` 配合 `allowlist` 模式)。 +- 机器人发送的消息默认被忽略;通过 `channels.slack.allowBots` 或 `channels.slack.channels..allowBots` 启用。 +- 警告:如果你允许回复其他机器人(`channels.slack.allowBots=true` 或 `channels.slack.channels..allowBots=true`),请使用 `requireMention`、`channels.slack.channels..users` 允许列表和/或在 `AGENTS.md` 和 `SOUL.md` 中设置明确的防护规则来防止机器人之间的回复循环。 +- Slack 工具的回应移除语义请参见 [/tools/reactions](/tools/reactions)。 +- 在权限允许且未超过大小限制时,附件会被下载到媒体存储。 diff --git a/docs/zh-CN/channels/telegram.md b/docs/zh-CN/channels/telegram.md new file mode 100644 index 0000000000..4195d85144 --- /dev/null +++ b/docs/zh-CN/channels/telegram.md @@ -0,0 +1,755 @@ +--- +read_when: + - 开发 Telegram 功能或 webhook 时 +summary: Telegram 机器人支持状态、功能与配置 +title: Telegram +x-i18n: + generated_at: "2026-02-01T19:54:11Z" + model: claude-opus-4-5 + provider: pi + source_hash: 63198fce8c29a1020590d6a3ca142314b30c35d50317b878bf1fb1bfd8d54747 + source_path: channels/telegram.md + workflow: 14 +--- + +# Telegram (Bot API) + +状态:通过 grammY 实现的机器人私聊 + 群组功能已可用于生产环境。默认使用长轮询;webhook 可选。 + +## 快速设置(新手) + +1. 通过 **@BotFather**([直达链接](https://t.me/BotFather))创建机器人。确认用户名确实是 `@BotFather`,然后复制令牌。 +2. 设置令牌: + - 环境变量:`TELEGRAM_BOT_TOKEN=...` + - 或配置:`channels.telegram.botToken: "..."`。 + - 如果两者都设置了,配置优先(环境变量回退仅适用于默认账户)。 +3. 启动 Gateway。 +4. 私聊访问默认为配对模式;首次联系时需批准配对码。 + +最小配置: + +```json5 +{ + channels: { + telegram: { + enabled: true, + botToken: "123:abc", + dmPolicy: "pairing", + }, + }, +} +``` + +## 简介 + +- 由 Gateway 管理的 Telegram Bot API 渠道。 +- 确定性路由:回复始终发回 Telegram;模型不会选择渠道。 +- 私聊共享智能体的主会话;群组保持隔离(`agent::telegram:group:`)。 + +## 设置(快速路径) + +### 1)创建机器人令牌(BotFather) + +1. 打开 Telegram,与 **@BotFather**([直达链接](https://t.me/BotFather))对话。确认用户名确实是 `@BotFather`。 +2. 运行 `/newbot`,然后按提示操作(名称 + 以 `bot` 结尾的用户名)。 +3. 复制令牌并安全保存。 + +可选的 BotFather 设置: + +- `/setjoingroups` — 允许/禁止将机器人添加到群组。 +- `/setprivacy` — 控制机器人是否能看到所有群组消息。 + +### 2)配置令牌(环境变量或配置) + +示例: + +```json5 +{ + channels: { + telegram: { + enabled: true, + botToken: "123:abc", + dmPolicy: "pairing", + groups: { "*": { requireMention: true } }, + }, + }, +} +``` + +环境变量选项:`TELEGRAM_BOT_TOKEN=...`(适用于默认账户)。 +如果环境变量和配置都设置了,配置优先。 + +多账户支持:使用 `channels.telegram.accounts`,为每个账户设置令牌和可选的 `name`。请参阅 [`gateway/configuration`](/gateway/configuration#telegramaccounts--discordaccounts--slackaccounts--signalaccounts--imessageaccounts) 了解通用模式。 + +3. 启动 Gateway。当令牌被解析后(配置优先,环境变量回退),Telegram 即启动。 +4. 私聊访问默认为配对模式。机器人首次被联系时需批准配对码。 +5. 对于群组:添加机器人,决定隐私/管理员行为(见下文),然后设置 `channels.telegram.groups` 来控制提及门控 + 白名单。 + +## 令牌 + 隐私 + 权限(Telegram 端) + +### 令牌创建(BotFather) + +- `/newbot` 创建机器人并返回令牌(请保密)。 +- 如果令牌泄露,通过 @BotFather 撤销/重新生成令牌并更新配置。 + +### 群组消息可见性(隐私模式) + +Telegram 机器人默认启用**隐私模式**,这会限制它们能接收到的群组消息。 +如果你的机器人必须看到*所有*群组消息,有两种选择: + +- 使用 `/setprivacy` 禁用隐私模式,**或者** +- 将机器人设为群组**管理员**(管理员机器人可以接收所有消息)。 + +**注意:** 切换隐私模式后,Telegram 要求将机器人从每个群组中移除并重新添加, +更改才能生效。 + +### 群组权限(管理员权限) + +管理员状态在群组内设置(Telegram 界面)。管理员机器人始终能接收所有 +群组消息,因此如果需要完全可见性,请使用管理员身份。 + +## 工作原理(行为) + +- 入站消息被规范化为共享渠道信封,包含回复上下文和媒体占位符。 +- 群组回复默认需要提及(原生 @提及或 `agents.list[].groupChat.mentionPatterns` / `messages.groupChat.mentionPatterns`)。 +- 多智能体覆盖:在 `agents.list[].groupChat.mentionPatterns` 上设置每个智能体的模式。 +- 回复始终路由回同一个 Telegram 聊天。 +- 长轮询使用 grammY runner,按聊天排序;总体并发受 `agents.defaults.maxConcurrent` 限制。 +- Telegram Bot API 不支持已读回执;没有 `sendReadReceipts` 选项。 + +## 草稿流式传输 + +OpenClaw 可以使用 `sendMessageDraft` 在 Telegram 私聊中流式传输部分回复。 + +要求: + +- 在 @BotFather 中为机器人启用话题模式(论坛话题模式)。 +- 仅限私聊话题(Telegram 在入站消息中包含 `message_thread_id`)。 +- `channels.telegram.streamMode` 未设为 `"off"`(默认:`"partial"`,`"block"` 启用分块草稿更新)。 + +草稿流式传输仅适用于私聊;Telegram 在群组或频道中不支持此功能。 + +## 格式化(Telegram HTML) + +- 出站 Telegram 文本使用 `parse_mode: "HTML"`(Telegram 支持的标签子集)。 +- 类 Markdown 输入被渲染为 **Telegram 安全的 HTML**(粗体/斜体/删除线/代码/链接);块级元素被扁平化为带换行符/项目符号的文本。 +- 来自模型的原始 HTML 会被转义,以避免 Telegram 解析错误。 +- 如果 Telegram 拒绝 HTML 负载,OpenClaw 会以纯文本重试同一条消息。 + +## 命令(原生 + 自定义) + +OpenClaw 在启动时将原生命令(如 `/status`、`/reset`、`/model`)注册到 Telegram 的机器人菜单。 +你可以通过配置向菜单添加自定义命令: + +```json5 +{ + channels: { + telegram: { + customCommands: [ + { command: "backup", description: "Git backup" }, + { command: "generate", description: "Create an image" }, + ], + }, + }, +} +``` + +## 故障排除 + +- 日志中出现 `setMyCommands failed` 通常意味着到 `api.telegram.org` 的出站 HTTPS/DNS 被阻止。 +- 如果看到 `sendMessage` 或 `sendChatAction` 失败,请检查 IPv6 路由和 DNS。 + +更多帮助:[渠道故障排除](/channels/troubleshooting)。 + +注意: + +- 自定义命令**仅为菜单条目**;除非你在其他地方处理它们,否则 OpenClaw 不会实现它们。 +- 命令名称会被规范化(去除前导 `/`,转为小写),且必须匹配 `a-z`、`0-9`、`_`(1–32 个字符)。 +- 自定义命令**不能覆盖原生命令**。冲突会被忽略并记录到日志。 +- 如果 `commands.native` 被禁用,则只注册自定义命令(如果没有自定义命令则清空)。 + +## 限制 + +- 出站文本按 `channels.telegram.textChunkLimit` 分块(默认 4000)。 +- 可选的换行分块:设置 `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[""].historyLimit`。 + +## 群组激活模式 + +默认情况下,机器人在群组中只响应提及(`@botname` 或 `agents.list[].groupChat.mentionPatterns` 中的模式)。要更改此行为: + +### 通过配置(推荐) + +```json5 +{ + channels: { + telegram: { + groups: { + "-1001234567890": { requireMention: false }, // 在此群组中始终回复 + }, + }, + }, +} +``` + +**重要:** 设置 `channels.telegram.groups` 会创建一个**白名单** - 只有列出的群组(或 `"*"`)会被接受。 +论坛话题继承其父群组配置(allowFrom、requireMention、skills、prompts),除非你在 `channels.telegram.groups..topics.` 下添加每个话题的覆盖。 + +允许所有群组且始终回复: + +```json5 +{ + channels: { + telegram: { + groups: { + "*": { requireMention: false }, // 所有群组,始终回复 + }, + }, + }, +} +``` + +保持所有群组仅提及时回复(默认行为): + +```json5 +{ + channels: { + telegram: { + groups: { + "*": { requireMention: true }, // 或完全省略 groups + }, + }, + }, +} +``` + +### 通过命令(会话级别) + +在群组中发送: + +- `/activation always` - 回复所有消息 +- `/activation mention` - 需要提及(默认) + +**注意:** 命令仅更新会话状态。要在重启后保持行为,请使用配置。 + +### 获取群组聊天 ID + +将群组中的任意消息转发给 Telegram 上的 `@userinfobot` 或 `@getidsbot`,即可看到聊天 ID(负数,如 `-1001234567890`)。 + +**提示:** 要获取你自己的用户 ID,私聊机器人,它会回复你的用户 ID(配对消息),或者在命令启用后使用 `/whoami`。 + +**隐私提示:** `@userinfobot` 是第三方机器人。如果你更注重隐私,可以将机器人添加到群组,发送一条消息,然后使用 `openclaw logs --follow` 读取 `chat.id`,或使用 Bot API 的 `getUpdates`。 + +## 配置写入 + +默认情况下,Telegram 允许写入由渠道事件或 `/config set|unset` 触发的配置更新。 + +以下情况会发生配置写入: + +- 群组升级为超级群组时,Telegram 发出 `migrate_to_chat_id`(聊天 ID 变更)。OpenClaw 可以自动迁移 `channels.telegram.groups`。 +- 你在 Telegram 聊天中运行 `/config set` 或 `/config unset`(需要 `commands.config: true`)。 + +禁用方式: + +```json5 +{ + channels: { telegram: { configWrites: false } }, +} +``` + +## 话题(论坛超级群组) + +Telegram 论坛话题在每条消息中包含 `message_thread_id`。OpenClaw: + +- 将 `:topic:` 追加到 Telegram 群组会话键,使每个话题相互隔离。 +- 发送输入指示器和回复时携带 `message_thread_id`,确保回复留在话题内。 +- 通用话题(thread id `1`)比较特殊:消息发送时省略 `message_thread_id`(Telegram 会拒绝),但输入指示器仍包含它。 +- 在模板上下文中暴露 `MessageThreadId` + `IsForum`,用于路由/模板。 +- 话题级配置可在 `channels.telegram.groups..topics.` 下设置(skills、白名单、自动回复、系统提示词、禁用)。 +- 话题配置继承群组设置(requireMention、白名单、skills、提示词、enabled),除非按话题覆盖。 + +私聊在某些边缘情况下可能包含 `message_thread_id`。OpenClaw 保持私聊会话键不变,但在存在 thread id 时仍将其用于回复/草稿流式传输。 + +## 内联按钮 + +Telegram 支持带回调按钮的内联键盘。 + +```json5 +{ + channels: { + telegram: { + capabilities: { + inlineButtons: "allowlist", + }, + }, + }, +} +``` + +按账户配置: + +```json5 +{ + channels: { + telegram: { + accounts: { + main: { + capabilities: { + inlineButtons: "allowlist", + }, + }, + }, + }, + }, +} +``` + +作用域: + +- `off` — 禁用内联按钮 +- `dm` — 仅私聊(群组目标被阻止) +- `group` — 仅群组(私聊目标被阻止) +- `all` — 私聊 + 群组 +- `allowlist` — 私聊 + 群组,但仅限 `allowFrom`/`groupAllowFrom` 允许的发送者(与控制命令规则相同) + +默认值:`allowlist`。 +旧版:`capabilities: ["inlineButtons"]` = `inlineButtons: "all"`。 + +### 发送按钮 + +使用消息工具的 `buttons` 参数: + +```json5 +{ + action: "send", + channel: "telegram", + to: "123456789", + message: "Choose an option:", + buttons: [ + [ + { text: "Yes", callback_data: "yes" }, + { text: "No", callback_data: "no" }, + ], + [{ text: "Cancel", callback_data: "cancel" }], + ], +} +``` + +当用户点击按钮时,回调数据会以以下格式作为消息发送回智能体: +`callback_data: value` + +### 配置选项 + +Telegram 功能可在两个层级配置(上面展示了对象形式;旧版字符串数组仍受支持): + +- `channels.telegram.capabilities`:全局默认功能配置,应用于所有 Telegram 账户,除非被覆盖。 +- `channels.telegram.accounts..capabilities`:按账户的功能配置,覆盖该账户的全局默认值。 + +当所有 Telegram 机器人/账户应具有相同行为时,使用全局设置。当不同机器人需要不同行为时,使用按账户配置(例如,一个账户只处理私聊,另一个允许在群组中使用)。 + +## 访问控制(私聊 + 群组) + +### 私聊访问 + +- 默认:`channels.telegram.dmPolicy = "pairing"`。未知发送者会收到配对码;消息在批准前被忽略(配对码 1 小时后过期)。 +- 批准方式: + - `openclaw pairing list telegram` + - `openclaw pairing approve telegram ` +- 配对是 Telegram 私聊使用的默认令牌交换方式。详情:[配对](/start/pairing) +- `channels.telegram.allowFrom` 接受数字用户 ID(推荐)或 `@username` 条目。这**不是**机器人用户名;请使用人类发送者的 ID。向导接受 `@username` 并在可能时将其解析为数字 ID。 + +#### 查找你的 Telegram 用户 ID + +更安全的方式(无需第三方机器人): + +1. 启动 Gateway 并私聊你的机器人。 +2. 运行 `openclaw logs --follow` 并查找 `from.id`。 + +替代方式(官方 Bot API): + +1. 私聊你的机器人。 +2. 使用你的机器人令牌获取更新,并读取 `message.from.id`: + ```bash + curl "https://api.telegram.org/bot/getUpdates" + ``` + +第三方方式(隐私性较低): + +- 私聊 `@userinfobot` 或 `@getidsbot` 并使用返回的用户 ID。 + +### 群组访问 + +两个独立的控制: + +**1. 允许哪些群组**(通过 `channels.telegram.groups` 的群组白名单): + +- 没有 `groups` 配置 = 允许所有群组 +- 有 `groups` 配置 = 只允许列出的群组或 `"*"` +- 示例:`"groups": { "-1001234567890": {}, "*": {} }` 允许所有群组 + +**2. 允许哪些发送者**(通过 `channels.telegram.groupPolicy` 的发送者过滤): + +- `"open"` = 允许的群组中所有发送者都可以发消息 +- `"allowlist"` = 只有 `channels.telegram.groupAllowFrom` 中的发送者可以发消息 +- `"disabled"` = 完全不接受群组消息 + 默认为 `groupPolicy: "allowlist"`(除非添加 `groupAllowFrom`,否则被阻止)。 + +大多数用户需要:`groupPolicy: "allowlist"` + `groupAllowFrom` + 在 `channels.telegram.groups` 中列出特定群组 + +## 长轮询 vs webhook + +- 默认:长轮询(不需要公网 URL)。 +- Webhook 模式:设置 `channels.telegram.webhookUrl` 和 `channels.telegram.webhookSecret`(可选 `channels.telegram.webhookPath`)。 + - 本地监听器绑定到 `0.0.0.0:8787`,默认服务 `POST /telegram-webhook`。 + - 如果你的公网 URL 不同,请使用反向代理并将 `channels.telegram.webhookUrl` 指向公网端点。 + +## 回复线程 + +Telegram 通过标签支持可选的线程回复: + +- `[[reply_to_current]]` -- 回复触发消息。 +- `[[reply_to:]]` -- 回复特定消息 ID。 + +通过 `channels.telegram.replyToMode` 控制: + +- `first`(默认)、`all`、`off`。 + +## 音频消息(语音 vs 文件) + +Telegram 区分**语音消息**(圆形气泡)和**音频文件**(元数据卡片)。 +OpenClaw 默认使用音频文件以保持向后兼容。 + +要在智能体回复中强制使用语音消息气泡,在回复中的任意位置包含此标签: + +- `[[audio_as_voice]]` — 以语音消息而非文件形式发送音频。 + +该标签会从发送的文本中移除。其他渠道会忽略此标签。 + +对于消息工具发送,设置 `asVoice: true` 并附带兼容语音的音频 `media` URL +(当有 media 时 `message` 为可选): + +```json5 +{ + action: "send", + channel: "telegram", + to: "123456789", + media: "https://example.com/voice.ogg", + asVoice: true, +} +``` + +## 贴纸 + +OpenClaw 支持接收和发送 Telegram 贴纸,并带有智能缓存。 + +### 接收贴纸 + +当用户发送贴纸时,OpenClaw 根据贴纸类型进行处理: + +- **静态贴纸(WEBP):** 下载并通过视觉能力处理。贴纸在消息内容中显示为 `` 占位符。 +- **动态贴纸(TGS):** 跳过(不支持 Lottie 格式处理)。 +- **视频贴纸(WEBM):** 跳过(不支持视频格式处理)。 + +接收贴纸时可用的模板上下文字段: + +- `Sticker` — 包含以下属性的对象: + - `emoji` — 与贴纸关联的表情 + - `setName` — 贴纸集名称 + - `fileId` — Telegram 文件 ID(可用于发回同一贴纸) + - `fileUniqueId` — 用于缓存查找的稳定 ID + - `cachedDescription` — 可用时的缓存视觉描述 + +### 贴纸缓存 + +贴纸通过 AI 的视觉能力处理以生成描述。由于相同的贴纸经常被重复发送,OpenClaw 会缓存这些描述以避免冗余的 API 调用。 + +**工作原理:** + +1. **首次遇到:** 贴纸图像被发送给 AI 进行视觉分析。AI 生成描述(例如"一只卡通猫热情地挥手")。 +2. **缓存存储:** 描述与贴纸的文件 ID、表情和集合名称一起保存。 +3. **后续遇到:** 再次看到同一贴纸时,直接使用缓存的描述,不再将图像发送给 AI。 + +**缓存位置:** `~/.openclaw/telegram/sticker-cache.json` + +**缓存条目格式:** + +```json +{ + "fileId": "CAACAgIAAxkBAAI...", + "fileUniqueId": "AgADBAADb6cxG2Y", + "emoji": "👋", + "setName": "CoolCats", + "description": "A cartoon cat waving enthusiastically", + "cachedAt": "2026-01-15T10:30:00.000Z" +} +``` + +**优势:** + +- 通过避免对同一贴纸重复调用视觉能力来降低 API 成本 +- 缓存贴纸的响应速度更快(无视觉处理延迟) +- 支持基于缓存描述的贴纸搜索功能 + +缓存在接收贴纸时自动填充,无需手动管理。 + +### 发送贴纸 + +智能体可以使用 `sticker` 和 `sticker-search` 动作发送和搜索贴纸。这些功能默认禁用,必须在配置中启用: + +```json5 +{ + channels: { + telegram: { + actions: { + sticker: true, + }, + }, + }, +} +``` + +**发送贴纸:** + +```json5 +{ + action: "sticker", + channel: "telegram", + to: "123456789", + fileId: "CAACAgIAAxkBAAI...", +} +``` + +参数: + +- `fileId`(必填)— 贴纸的 Telegram 文件 ID。可从接收贴纸时的 `Sticker.fileId` 获取,或从 `sticker-search` 结果获取。 +- `replyTo`(可选)— 要回复的消息 ID。 +- `threadId`(可选)— 论坛话题的消息线程 ID。 + +**搜索贴纸:** + +智能体可以通过描述、表情或集合名称搜索缓存的贴纸: + +```json5 +{ + action: "sticker-search", + channel: "telegram", + query: "cat waving", + limit: 5, +} +``` + +从缓存返回匹配的贴纸: + +```json5 +{ + ok: true, + count: 2, + stickers: [ + { + fileId: "CAACAgIAAxkBAAI...", + emoji: "👋", + description: "A cartoon cat waving enthusiastically", + setName: "CoolCats", + }, + ], +} +``` + +搜索使用跨描述文本、表情字符和集合名称的模糊匹配。 + +**带线程的示例:** + +```json5 +{ + action: "sticker", + channel: "telegram", + to: "-1001234567890", + fileId: "CAACAgIAAxkBAAI...", + replyTo: 42, + threadId: 123, +} +``` + +## 流式传输(草稿) + +Telegram 可以在智能体生成回复时流式传输**草稿气泡**。 +OpenClaw 使用 Bot API 的 `sendMessageDraft`(非真实消息),然后将 +最终回复作为普通消息发送。 + +要求(Telegram Bot API 9.3+): + +- **启用话题的私聊**(机器人的论坛话题模式)。 +- 入站消息必须包含 `message_thread_id`(私聊话题线程)。 +- 群组/超级群组/频道中的流式传输会被忽略。 + +配置: + +- `channels.telegram.streamMode: "off" | "partial" | "block"`(默认:`partial`) + - `partial`:用最新的流式文本更新草稿气泡。 + - `block`:以更大的块更新草稿气泡(分块)。 + - `off`:禁用草稿流式传输。 +- 可选(仅适用于 `streamMode: "block"`): + - `channels.telegram.draftChunk: { minChars?, maxChars?, breakPreference? }` + - 默认值:`minChars: 200`、`maxChars: 800`、`breakPreference: "paragraph"`(受 `channels.telegram.textChunkLimit` 限制)。 + +注意:草稿流式传输与**分块流式传输**(渠道消息)不同。 +分块流式传输默认关闭,如果你想要提前的 Telegram 消息而非草稿更新,需要设置 `channels.telegram.blockStreaming: true`。 + +推理流式传输(仅 Telegram): + +- `/reasoning stream` 在回复生成时将推理过程流式传输到草稿气泡中,然后发送不包含推理过程的最终答案。 +- 如果 `channels.telegram.streamMode` 为 `off`,推理流式传输将被禁用。 + 更多上下文:[流式传输 + 分块](/concepts/streaming)。 + +## 重试策略 + +出站 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)。 +- 工具门控:`channels.telegram.actions.reactions`、`channels.telegram.actions.sendMessage`、`channels.telegram.actions.deleteMessage`(默认:启用),以及 `channels.telegram.actions.sticker`(默认:禁用)。 + +## 表情回应通知 + +**表情回应的工作原理:** +Telegram 表情回应作为**独立的 `message_reaction` 事件**到达,而非消息负载中的属性。当用户添加表情回应时,OpenClaw: + +1. 从 Telegram API 接收 `message_reaction` 更新 +2. 将其转换为**系统事件**,格式为:`"Telegram reaction added: {emoji} by {user} on msg {id}"` +3. 使用与常规消息**相同的会话键**将系统事件入队 +4. 当该对话中的下一条消息到达时,系统事件被排出并添加到智能体上下文的前面 + +智能体将表情回应视为对话历史中的**系统通知**,而非消息元数据。 + +**配置:** + +- `channels.telegram.reactionNotifications`:控制哪些表情回应触发通知 + - `"off"` — 忽略所有表情回应 + - `"own"` — 当用户对机器人消息做出表情回应时通知(尽力而为;内存中)(默认) + - `"all"` — 对所有表情回应进行通知 + +- `channels.telegram.reactionLevel`:控制智能体的表情回应能力 + - `"off"` — 智能体不能对消息做表情回应 + - `"ack"` — 机器人发送确认表情回应(处理时显示 👀)(默认) + - `"minimal"` — 智能体可以少量使用表情回应(指导原则:每 5-10 次交流 1 次) + - `"extensive"` — 智能体可以在适当时大量使用表情回应 + +**论坛群组:** 论坛群组中的表情回应包含 `message_thread_id`,使用如 `agent:main:telegram:group:{chatId}:topic:{threadId}` 的会话键。这确保同一话题中的表情回应和消息保持在一起。 + +**示例配置:** + +```json5 +{ + channels: { + telegram: { + reactionNotifications: "all", // 查看所有表情回应 + reactionLevel: "minimal", // 智能体可以少量使用表情回应 + }, + }, +} +``` + +**要求:** + +- Telegram 机器人必须在 `allowed_updates` 中显式请求 `message_reaction`(由 OpenClaw 自动配置) +- 对于 webhook 模式,表情回应包含在 webhook 的 `allowed_updates` 中 +- 对于轮询模式,表情回应包含在 `getUpdates` 的 `allowed_updates` 中 + +## 投递目标(CLI/定时任务) + +- 使用聊天 ID(`123456789`)或用户名(`@name`)作为目标。 +- 示例:`openclaw message send --channel telegram --target 123456789 --message "hi"`。 + +## 故障排除 + +**机器人在群组中不响应非提及消息:** + +- 如果你设置了 `channels.telegram.groups.*.requireMention=false`,Telegram 的 Bot API **隐私模式**必须被禁用。 + - BotFather:`/setprivacy` → **Disable**(然后从群组中移除并重新添加机器人) +- `openclaw channels status` 在配置期望接收非提及群组消息时会显示警告。 +- `openclaw channels status --probe` 可以额外检查显式数字群组 ID 的成员资格(无法审计通配符 `"*"` 规则)。 +- 快速测试:`/activation always`(仅会话级别;持久化请使用配置) + +**机器人完全看不到群组消息:** + +- 如果设置了 `channels.telegram.groups`,群组必须被列出或使用 `"*"` +- 在 @BotFather 中检查隐私设置 → "Group Privacy" 应为 **OFF** +- 确认机器人确实是成员(而非只是没有读取权限的管理员) +- 检查 Gateway 日志:`openclaw logs --follow`(查找 "skipping group message") + +**机器人响应提及但不响应 `/activation always`:** + +- `/activation` 命令更新会话状态但不会持久化到配置 +- 要持久化行为,将群组添加到 `channels.telegram.groups` 并设置 `requireMention: false` + +**`/status` 等命令不工作:** + +- 确保你的 Telegram 用户 ID 已授权(通过配对或 `channels.telegram.allowFrom`) +- 即使在 `groupPolicy: "open"` 的群组中,命令也需要授权 + +**长轮询在 Node 22+ 上立即中止(通常涉及代理/自定义 fetch):** + +- Node 22+ 对 `AbortSignal` 实例更严格;外部信号可能会立即中止 `fetch` 调用。 +- 升级到规范化 abort 信号的 OpenClaw 版本,或在 Node 20 上运行 Gateway 直到可以升级。 + +**机器人启动后静默停止响应(或日志中出现 `HttpError: Network request ... failed`):** + +- 某些主机优先将 `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) + +完整配置:[配置](/gateway/configuration) + +提供商选项: + +- `channels.telegram.enabled`:启用/禁用渠道启动。 +- `channels.telegram.botToken`:机器人令牌(BotFather)。 +- `channels.telegram.tokenFile`:从文件路径读取令牌。 +- `channels.telegram.dmPolicy`:`pairing | allowlist | open | disabled`(默认:pairing)。 +- `channels.telegram.allowFrom`:私聊白名单(ID/用户名)。`open` 需要 `"*"`。 +- `channels.telegram.groupPolicy`:`open | allowlist | disabled`(默认:allowlist)。 +- `channels.telegram.groupAllowFrom`:群组发送者白名单(ID/用户名)。 +- `channels.telegram.groups`:按群组的默认设置 + 白名单(使用 `"*"` 作为全局默认)。 + - `channels.telegram.groups..requireMention`:提及门控默认值。 + - `channels.telegram.groups..skills`:技能过滤(省略 = 所有技能,空 = 无技能)。 + - `channels.telegram.groups..allowFrom`:按群组的发送者白名单覆盖。 + - `channels.telegram.groups..systemPrompt`:群组的额外系统提示词。 + - `channels.telegram.groups..enabled`:设为 `false` 时禁用该群组。 + - `channels.telegram.groups..topics..*`:按话题覆盖(与群组字段相同)。 + - `channels.telegram.groups..topics..requireMention`:按话题的提及门控覆盖。 +- `channels.telegram.capabilities.inlineButtons`:`off | dm | group | all | allowlist`(默认:allowlist)。 +- `channels.telegram.accounts..capabilities.inlineButtons`:按账户覆盖。 +- `channels.telegram.replyToMode`:`off | first | all`(默认:`first`)。 +- `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 的 autoSelectFamily(true=启用,false=禁用)。在 Node 22 上默认禁用以避免 Happy Eyeballs 超时。 +- `channels.telegram.proxy`:Bot API 调用的代理 URL(SOCKS/HTTP)。 +- `channels.telegram.webhookUrl`:启用 webhook 模式(需要 `channels.telegram.webhookSecret`)。 +- `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`)。 + +相关全局选项: + +- `agents.list[].groupChat.mentionPatterns`(提及门控模式)。 +- `messages.groupChat.mentionPatterns`(全局回退)。 +- `commands.native`(默认为 `"auto"` → Telegram/Discord 启用,Slack 禁用)、`commands.text`、`commands.useAccessGroups`(命令行为)。通过 `channels.telegram.commands.native` 覆盖。 +- `messages.responsePrefix`、`messages.ackReaction`、`messages.ackReactionScope`、`messages.removeAckAfterReply`。 diff --git a/docs/zh-CN/channels/tlon.md b/docs/zh-CN/channels/tlon.md new file mode 100644 index 0000000000..8063578839 --- /dev/null +++ b/docs/zh-CN/channels/tlon.md @@ -0,0 +1,138 @@ +--- +read_when: + - 开发 Tlon/Urbit 渠道功能时 +summary: Tlon/Urbit 支持状态、功能和配置 +title: Tlon +x-i18n: + generated_at: "2026-02-01T19:58:15Z" + model: claude-opus-4-5 + provider: pi + source_hash: 19d7ffe23e82239fd2a2e35913e0d52c809b2c2b939dd39184e6c27a539ed97d + source_path: channels/tlon.md + workflow: 14 +--- + +# Tlon(插件) + +Tlon 是一个基于 Urbit 构建的去中心化通讯工具。OpenClaw 连接到你的 Urbit ship,可以 +回复私信和群聊消息。群聊回复默认需要 @ 提及,并可通过白名单进一步限制。 + +状态:通过插件支持。支持私信、群组提及、线程回复和纯文本媒体回退 +(URL 附加到标题)。不支持反应、投票和原生媒体上传。 + +## 需要插件 + +Tlon 以插件形式提供,不包含在核心安装包中。 + +通过 CLI 安装(npm 注册表): + +```bash +openclaw plugins install @openclaw/tlon +``` + +本地签出(从 git 仓库运行时): + +```bash +openclaw plugins install ./extensions/tlon +``` + +详情:[插件](/plugin) + +## 设置 + +1. 安装 Tlon 插件。 +2. 获取你的 ship URL 和登录代码。 +3. 配置 `channels.tlon`。 +4. 重启 Gateway。 +5. 向机器人发送私信或在群组渠道中提及它。 + +最小配置(单账户): + +```json5 +{ + channels: { + tlon: { + enabled: true, + ship: "~sampel-palnet", + url: "https://your-ship-host", + code: "lidlut-tabwed-pillex-ridrup", + }, + }, +} +``` + +## 群组渠道 + +默认启用自动发现。你也可以手动固定渠道: + +```json5 +{ + channels: { + tlon: { + groupChannels: ["chat/~host-ship/general", "chat/~host-ship/support"], + }, + }, +} +``` + +禁用自动发现: + +```json5 +{ + channels: { + tlon: { + autoDiscoverChannels: false, + }, + }, +} +``` + +## 访问控制 + +私信白名单(为空 = 允许所有): + +```json5 +{ + channels: { + tlon: { + dmAllowlist: ["~zod", "~nec"], + }, + }, +} +``` + +群组授权(默认为受限模式): + +```json5 +{ + channels: { + tlon: { + defaultAuthorizedShips: ["~zod"], + authorization: { + channelRules: { + "chat/~host-ship/general": { + mode: "restricted", + allowedShips: ["~zod", "~nec"], + }, + "chat/~host-ship/announcements": { + mode: "open", + }, + }, + }, + }, + }, +} +``` + +## 投递目标(CLI/定时任务) + +与 `openclaw message send` 或定时投递配合使用: + +- 私信:`~sampel-palnet` 或 `dm/~sampel-palnet` +- 群组:`chat/~host-ship/channel` 或 `group:~host-ship/channel` + +## 备注 + +- 群聊回复需要提及(例如 `~your-bot-ship`)才会响应。 +- 线程回复:如果收到的消息在线程中,OpenClaw 会在线程内回复。 +- 媒体:`sendMedia` 回退为文本 + URL(不支持原生上传)。 diff --git a/docs/zh-CN/channels/troubleshooting.md b/docs/zh-CN/channels/troubleshooting.md new file mode 100644 index 0000000000..ceb3740704 --- /dev/null +++ b/docs/zh-CN/channels/troubleshooting.md @@ -0,0 +1,36 @@ +--- +read_when: + - 渠道已连接但消息无法流通 + - 排查渠道配置错误(意图、权限、隐私模式) +summary: 渠道专属故障排除快捷指南(Discord/Telegram/WhatsApp) +title: 渠道故障排除 +x-i18n: + generated_at: "2026-02-01T19:58:09Z" + model: claude-opus-4-5 + provider: pi + source_hash: 6542ee86b3e50929caeaab127642d135dfbc0d8a44876ec2df0fff15bf57cd63 + source_path: channels/troubleshooting.md + workflow: 14 +--- + +# 渠道故障排除 + +首先运行: + +```bash +openclaw doctor +openclaw channels status --probe +``` + +`channels status --probe` 会在检测到常见渠道配置错误时输出警告,并包含小型实时检查(凭据、部分权限/成员资格)。 + +## 渠道 + +- Discord:[/channels/discord#troubleshooting](/channels/discord#troubleshooting) +- Telegram:[/channels/telegram#troubleshooting](/channels/telegram#troubleshooting) +- WhatsApp:[/channels/whatsapp#troubleshooting-quick](/channels/whatsapp#troubleshooting-quick) + +## Telegram 快速修复 + +- 日志显示 `HttpError: Network request for 'sendMessage' failed` 或 `sendChatAction` → 检查 IPv6 DNS。如果 `api.telegram.org` 优先解析为 IPv6 而主机缺少 IPv6 出站连接,请强制使用 IPv4 或启用 IPv6。参见 [/channels/telegram#troubleshooting](/channels/telegram#troubleshooting)。 +- 日志显示 `setMyCommands failed` → 检查到 `api.telegram.org` 的出站 HTTPS 和 DNS 可达性(常见于限制严格的 VPS 或代理环境)。 diff --git a/docs/zh-CN/channels/twitch.md b/docs/zh-CN/channels/twitch.md new file mode 100644 index 0000000000..db0c9b0752 --- /dev/null +++ b/docs/zh-CN/channels/twitch.md @@ -0,0 +1,384 @@ +--- +read_when: + - 为 OpenClaw 设置 Twitch 聊天集成 +summary: Twitch 聊天机器人配置与设置 +title: Twitch +x-i18n: + generated_at: "2026-02-01T19:58:38Z" + model: claude-opus-4-5 + provider: pi + source_hash: aa7d60444e7f7e5dd7d02ce21527089058e024b8f427aeedf9e200a2818eb007 + source_path: channels/twitch.md + workflow: 14 +--- + +# Twitch(插件) + +通过 IRC 连接支持 Twitch 聊天。OpenClaw 以 Twitch 用户(机器人账号)身份连接,在频道中接收和发送消息。 + +## 需要插件 + +Twitch 以插件形式提供,未包含在核心安装中。 + +通过 CLI(npm 注册表)安装: + +```bash +openclaw plugins install @openclaw/twitch +``` + +本地签出(从 git 仓库运行时): + +```bash +openclaw plugins install ./extensions/twitch +``` + +详情:[插件](/plugin) + +## 快速设置(入门) + +1. 为机器人创建一个专用 Twitch 账号(或使用现有账号)。 +2. 生成凭证:[Twitch Token Generator](https://twitchtokengenerator.com/) + - 选择 **Bot Token** + - 确认已勾选 `chat:read` 和 `chat:write` 权限范围 + - 复制 **Client ID** 和 **Access Token** +3. 查找你的 Twitch 用户 ID:https://www.streamweasels.com/tools/convert-twitch-username-to-user-id/ +4. 配置令牌: + - 环境变量:`OPENCLAW_TWITCH_ACCESS_TOKEN=...`(仅限默认账号) + - 或配置文件:`channels.twitch.accessToken` + - 如果两者都设置了,配置文件优先(环境变量回退仅适用于默认账号)。 +5. 启动 Gateway。 + +**⚠️ 重要:** 添加访问控制(`allowFrom` 或 `allowedRoles`)以防止未授权用户触发机器人。`requireMention` 默认为 `true`。 + +最小配置: + +```json5 +{ + channels: { + twitch: { + enabled: true, + username: "openclaw", // 机器人的 Twitch 账号 + accessToken: "oauth:abc123...", // OAuth Access Token(或使用 OPENCLAW_TWITCH_ACCESS_TOKEN 环境变量) + 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::twitch:`。 +- `username` 是机器人的账号(用于认证),`channel` 是要加入的聊天室。 + +## 设置(详细) + +### 生成凭证 + +使用 [Twitch Token Generator](https://twitchtokengenerator.com/): + +- 选择 **Bot Token** +- 确认已勾选 `chat:read` 和 `chat:write` 权限范围 +- 复制 **Client ID** 和 **Access Token** + +无需手动注册应用。令牌在数小时后过期。 + +### 配置机器人 + +**环境变量(仅限默认账号):** + +```bash +OPENCLAW_TWITCH_ACCESS_TOKEN=oauth:abc123... +``` + +**或配置文件:** + +```json5 +{ + channels: { + twitch: { + enabled: true, + username: "openclaw", + accessToken: "oauth:abc123...", + clientId: "xyz789...", + channel: "vevisk", + }, + }, +} +``` + +如果环境变量和配置文件都设置了,配置文件优先。 + +### 访问控制(推荐) + +```json5 +{ + channels: { + twitch: { + allowFrom: ["123456789"], // (推荐)仅限你的 Twitch 用户 ID + allowedRoles: ["moderator"], // 或按角色限制 + }, + }, +} +``` + +**可用角色:** `"moderator"`、`"owner"`、`"vip"`、`"subscriber"`、`"all"`。 + +**为什么使用用户 ID?** 用户名可以更改,存在冒充风险。用户 ID 是永久的。 + +查找你的 Twitch 用户 ID:https://www.streamweasels.com/tools/convert-twitch-username-%20to-user-id/(将 Twitch 用户名转换为 ID) + +## 令牌刷新(可选) + +从 [Twitch Token Generator](https://twitchtokengenerator.com/) 获取的令牌无法自动刷新——过期后需重新生成。 + +如需自动刷新令牌,请在 [Twitch Developer Console](https://dev.twitch.tv/console) 创建你自己的 Twitch 应用,并添加到配置中: + +```json5 +{ + channels: { + twitch: { + clientSecret: "your_client_secret", + refreshToken: "your_refresh_token", + }, + }, +} +``` + +机器人会在令牌过期前自动刷新,并记录刷新事件。 + +## 多账号支持 + +使用 `channels.twitch.accounts` 配置每个账号的令牌。参见 [`gateway/configuration`](/gateway/configuration) 了解通用模式。 + +示例(一个机器人账号加入两个频道): + +```json5 +{ + channels: { + twitch: { + accounts: { + channel1: { + username: "openclaw", + accessToken: "oauth:abc123...", + clientId: "xyz789...", + channel: "vevisk", + }, + channel2: { + username: "openclaw", + accessToken: "oauth:def456...", + clientId: "uvw012...", + channel: "secondchannel", + }, + }, + }, + }, +} +``` + +**注意:** 每个账号需要自己的令牌(每个频道一个令牌)。 + +## 访问控制 + +### 基于角色的限制 + +```json5 +{ + channels: { + twitch: { + accounts: { + default: { + allowedRoles: ["moderator", "vip"], + }, + }, + }, + }, +} +``` + +### 按用户 ID 设置允许列表(最安全) + +```json5 +{ + channels: { + twitch: { + accounts: { + default: { + allowFrom: ["123456789", "987654321"], + }, + }, + }, + }, +} +``` + +### 组合允许列表 + 角色 + +`allowFrom` 中的用户可绕过角色检查: + +```json5 +{ + channels: { + twitch: { + accounts: { + default: { + allowFrom: ["123456789"], + allowedRoles: ["moderator"], + }, + }, + }, + }, +} +``` + +### 禁用 @提及要求 + +默认情况下,`requireMention` 为 `true`。要禁用并响应所有消息: + +```json5 +{ + channels: { + twitch: { + accounts: { + default: { + requireMention: false, + }, + }, + }, + }, +} +``` + +## 故障排除 + +首先,运行诊断命令: + +```bash +openclaw doctor +openclaw channels status --probe +``` + +### 机器人不响应消息 + +**检查访问控制:** 临时设置 `allowedRoles: ["all"]` 进行测试。 + +**检查机器人是否在频道中:** 机器人必须加入 `channel` 中指定的频道。 + +### 令牌问题 + +**"Failed to connect" 或认证错误:** + +- 确认 `accessToken` 是 OAuth 访问令牌值(通常以 `oauth:` 前缀开头) +- 检查令牌是否具有 `chat:read` 和 `chat:write` 权限范围 +- 如果使用令牌刷新,确认已设置 `clientSecret` 和 `refreshToken` + +### 令牌刷新不工作 + +**检查日志中的刷新事件:** + +``` +Using env token source for mybot +Access token refreshed for user 123456 (expires in 14400s) +``` + +如果看到 "token refresh disabled (no refresh token)": + +- 确保已提供 `clientSecret` +- 确保已提供 `refreshToken` + +## 配置 + +**账号配置:** + +- `username` - 机器人用户名 +- `accessToken` - 具有 `chat:read` 和 `chat:write` 权限的 OAuth 访问令牌 +- `clientId` - Twitch Client ID(来自 Token Generator 或你的应用) +- `channel` - 要加入的频道(必填) +- `enabled` - 启用此账号(默认:`true`) +- `clientSecret` - 可选:用于自动刷新令牌 +- `refreshToken` - 可选:用于自动刷新令牌 +- `expiresIn` - 令牌过期时间(秒) +- `obtainmentTimestamp` - 令牌获取时间戳 +- `allowFrom` - 用户 ID 允许列表 +- `allowedRoles` - 基于角色的访问控制(`"moderator" | "owner" | "vip" | "subscriber" | "all"`) +- `requireMention` - 要求 @提及(默认:`true`) + +**提供商选项:** + +- `channels.twitch.enabled` - 启用/禁用渠道启动 +- `channels.twitch.username` - 机器人用户名(简化单账号配置) +- `channels.twitch.accessToken` - OAuth 访问令牌(简化单账号配置) +- `channels.twitch.clientId` - Twitch Client ID(简化单账号配置) +- `channels.twitch.channel` - 要加入的频道(简化单账号配置) +- `channels.twitch.accounts.` - 多账号配置(上述所有账号字段) + +完整示例: + +```json5 +{ + channels: { + twitch: { + enabled: true, + username: "openclaw", + accessToken: "oauth:abc123...", + clientId: "xyz789...", + channel: "vevisk", + clientSecret: "secret123...", + refreshToken: "refresh456...", + allowFrom: ["123456789"], + allowedRoles: ["moderator", "vip"], + accounts: { + default: { + username: "mybot", + accessToken: "oauth:abc123...", + clientId: "xyz789...", + channel: "your_channel", + enabled: true, + clientSecret: "secret123...", + refreshToken: "refresh456...", + expiresIn: 14400, + obtainmentTimestamp: 1706092800000, + allowFrom: ["123456789", "987654321"], + allowedRoles: ["moderator"], + }, + }, + }, + }, +} +``` + +## 工具操作 + +智能体可以调用 `twitch` 执行以下操作: + +- `send` - 向频道发送消息 + +示例: + +```json5 +{ + action: "twitch", + params: { + message: "Hello Twitch!", + to: "#mychannel", + }, +} +``` + +## 安全与运维 + +- **将令牌视为密码** - 切勿将令牌提交到 git +- **使用自动令牌刷新** 用于长时间运行的机器人 +- **使用用户 ID 允许列表** 而非用户名进行访问控制 +- **监控日志** 关注令牌刷新事件和连接状态 +- **最小化令牌权限范围** - 仅请求 `chat:read` 和 `chat:write` +- **如遇问题**:确认没有其他进程占用会话后,重启 Gateway + +## 限制 + +- 每条消息最多 **500 个字符**(按词边界自动分块) +- 分块前会移除 Markdown 格式 +- 无速率限制(使用 Twitch 内置的速率限制) diff --git a/docs/zh-CN/channels/whatsapp.md b/docs/zh-CN/channels/whatsapp.md new file mode 100644 index 0000000000..1320aeea2c --- /dev/null +++ b/docs/zh-CN/channels/whatsapp.md @@ -0,0 +1,410 @@ +--- +read_when: + - 处理 WhatsApp/网页渠道行为或收件箱路由时 +summary: WhatsApp(网页渠道)集成:登录、收件箱、回复、媒体和运维 +title: WhatsApp +x-i18n: + generated_at: "2026-02-01T20:00:02Z" + model: claude-opus-4-5 + provider: pi + source_hash: 44fd88f8e269284999e5a5a52b230edae6e6f978528dd298d6a5603d03c0c38d + source_path: channels/whatsapp.md + workflow: 14 +--- + +# WhatsApp(网页渠道) + +状态:仅支持通过 Baileys 的 WhatsApp Web。Gateway 拥有会话。 + +## 快速设置(入门) + +1. 如果可能,使用**单独的手机号码**(推荐)。 +2. 在 `~/.openclaw/openclaw.json` 中配置 WhatsApp。 +3. 运行 `openclaw channels login` 扫描二维码(已关联设备)。 +4. 启动 Gateway。 + +最小配置: + +```json5 +{ + channels: { + whatsapp: { + dmPolicy: "allowlist", + allowFrom: ["+15551234567"], + }, + }, +} +``` + +## 目标 + +- 单个 Gateway 进程中支持多个 WhatsApp 账号(多账号)。 +- 确定性路由:回复返回到 WhatsApp,无模型路由。 +- 模型获得足够的上下文以理解引用回复。 + +## 配置写入 + +默认情况下,WhatsApp 允许通过 `/config set|unset` 触发配置更新写入(需要 `commands.config: true`)。 + +禁用方式: + +```json5 +{ + channels: { whatsapp: { configWrites: false } }, +} +``` + +## 架构(职责划分) + +- **Gateway** 拥有 Baileys socket 和收件箱循环。 +- **CLI / macOS 应用** 与 Gateway 通信;不直接使用 Baileys。 +- **活跃监听器** 是出站发送的必要条件;否则发送会快速失败。 + +## 获取手机号码(两种模式) + +WhatsApp 需要真实的手机号码进行验证。VoIP 和虚拟号码通常会被屏蔽。在 WhatsApp 上运行 OpenClaw 有两种支持的方式: + +### 专用号码(推荐) + +为 OpenClaw 使用**单独的手机号码**。最佳用户体验,干净的路由,无自聊天问题。理想设置:**备用/旧 Android 手机 + eSIM**。保持 Wi-Fi 和充电连接,通过二维码关联。 + +**WhatsApp Business:** 你可以在同一设备上使用不同号码的 WhatsApp Business。非常适合将个人 WhatsApp 分开 — 安装 WhatsApp Business 并在其中注册 OpenClaw 号码。 + +**示例配置(专用号码,单用户允许列表):** + +```json5 +{ + channels: { + whatsapp: { + dmPolicy: "allowlist", + allowFrom: ["+15551234567"], + }, + }, +} +``` + +**配对模式(可选):** +如果你想使用配对而非允许列表,将 `channels.whatsapp.dmPolicy` 设置为 `pairing`。未知发送者会收到配对码;通过以下命令批准: +`openclaw pairing approve whatsapp ` + +### 个人号码(备选方案) + +快速备选方案:在**你自己的号码**上运行 OpenClaw。给自己发消息(WhatsApp "给自己发消息")进行测试,避免打扰联系人。在设置和实验期间,需要在主手机上读取验证码。**必须启用自聊天模式。** +当向导询问你的个人 WhatsApp 号码时,输入你将用来发消息的手机号(所有者/发送者),而不是助手号码。 + +**示例配置(个人号码,自聊天):** + +```json +{ + "whatsapp": { + "selfChatMode": true, + "dmPolicy": "allowlist", + "allowFrom": ["+15551234567"] + } +} +``` + +当设置了 `messages.responsePrefix` 时,自聊天回复默认使用 `[{identity.name}]`(否则为 `[openclaw]`)。 +如果 `messages.responsePrefix` 未设置,则使用默认值。显式设置可自定义或禁用前缀(使用 `""` 来移除)。 + +### 号码获取技巧 + +- **本国 eSIM**,来自你所在国家的移动运营商(最可靠) + - 奥地利:[hot.at](https://www.hot.at) + - 英国:[giffgaff](https://www.giffgaff.com) — 免费 SIM 卡,无合约 +- **预付费 SIM 卡** — 便宜,只需接收一条验证短信 + +**避免使用:** TextNow、Google Voice、大多数"免费短信"服务 — WhatsApp 会积极屏蔽这些号码。 + +**提示:** 该号码只需接收一条验证短信。之后,WhatsApp Web 会话通过 `creds.json` 持久保存。 + +## 为什么不用 Twilio? + +- 早期 OpenClaw 版本支持 Twilio 的 WhatsApp Business 集成。 +- WhatsApp Business 号码不适合个人助手。 +- Meta 强制执行 24 小时回复窗口;如果你在过去 24 小时内没有回复,商业号码无法发起新消息。 +- 高频或"频繁"使用会触发激进的封禁,因为商业账号不适合发送大量个人助手消息。 +- 结果:投递不可靠且频繁被封禁,因此已移除支持。 + +## 登录 + 凭证 + +- 登录命令:`openclaw channels login`(通过已关联设备扫描二维码)。 +- 多账号登录:`openclaw channels login --account `(`` = `accountId`)。 +- 默认账号(省略 `--account` 时):如果存在则为 `default`,否则为第一个已配置的账号 ID(排序后)。 +- 凭证存储在 `~/.openclaw/credentials/whatsapp//creds.json`。 +- 备份副本位于 `creds.json.bak`(损坏时恢复)。 +- 旧版兼容:早期安装将 Baileys 文件直接存储在 `~/.openclaw/credentials/`。 +- 注销:`openclaw channels logout`(或 `--account `)删除 WhatsApp 认证状态(但保留共享的 `oauth.json`)。 +- 已注销的 socket => 错误提示重新关联。 + +## 入站流程(私聊 + 群聊) + +- WhatsApp 事件来自 `messages.upsert`(Baileys)。 +- 收件箱监听器在关闭时解除绑定,以避免在测试/重启中累积事件处理器。 +- 状态/广播聊天被忽略。 +- 私聊使用 E.164 格式;群聊使用群组 JID。 +- **私聊策略**:`channels.whatsapp.dmPolicy` 控制私聊访问(默认:`pairing`)。 + - 配对:未知发送者会收到配对码(通过 `openclaw pairing approve whatsapp ` 批准;码在 1 小时后过期)。 + - 开放:需要 `channels.whatsapp.allowFrom` 包含 `"*"`。 + - 你关联的 WhatsApp 号码被隐式信任,因此自消息跳过 `channels.whatsapp.dmPolicy` 和 `channels.whatsapp.allowFrom` 检查。 + +### 个人号码模式(备选方案) + +如果你在**个人 WhatsApp 号码**上运行 OpenClaw,启用 `channels.whatsapp.selfChatMode`(参见上方示例配置)。 + +行为: + +- 出站私聊消息不会触发配对回复(防止骚扰联系人)。 +- 入站未知发送者仍遵循 `channels.whatsapp.dmPolicy`。 +- 自聊天模式(allowFrom 包含你的号码)避免自动已读回执并忽略提及 JID。 +- 非自聊天私聊会发送已读回执。 + +## 已读回执 + +默认情况下,Gateway 会在接受入站 WhatsApp 消息后将其标记为已读(蓝色对勾)。 + +全局禁用: + +```json5 +{ + channels: { whatsapp: { sendReadReceipts: false } }, +} +``` + +按账号禁用: + +```json5 +{ + channels: { + whatsapp: { + accounts: { + personal: { sendReadReceipts: false }, + }, + }, + }, +} +``` + +备注: + +- 自聊天模式始终跳过已读回执。 + +## WhatsApp 常见问题:发送消息 + 配对 + +**关联 WhatsApp 后,OpenClaw 会给随机联系人发消息吗?** +不会。默认私聊策略是**配对**,因此未知发送者只会收到配对码,其消息**不会被处理**。OpenClaw 只回复收到的聊天,或你显式触发的发送(智能体/CLI)。 + +**WhatsApp 上的配对是如何工作的?** +配对是针对未知发送者的私聊门控: + +- 新发送者的首条私聊消息会返回一个短码(消息不会被处理)。 +- 通过以下命令批准:`openclaw pairing approve whatsapp `(用 `openclaw pairing list whatsapp` 列出)。 +- 码在 1 小时后过期;每个渠道的待处理请求上限为 3 个。 + +**多人可以在同一个 WhatsApp 号码上使用不同的 OpenClaw 实例吗?** +可以,通过 `bindings` 将每个发送者路由到不同的智能体(peer `kind: "dm"`,发送者 E.164 如 `+15551234567`)。回复仍然来自**同一个 WhatsApp 账号**,且私聊会折叠到每个智能体的主会话,因此请使用**每人一个智能体**。私聊访问控制(`dmPolicy`/`allowFrom`)在每个 WhatsApp 账号级别是全局的。参见[多智能体路由](/concepts/multi-agent)。 + +**为什么向导要询问我的手机号码?** +向导使用它来设置你的**允许列表/所有者**,以便允许你自己的私聊消息。它不用于自动发送。如果你在个人 WhatsApp 号码上运行,使用相同的号码并启用 `channels.whatsapp.selfChatMode`。 + +## 消息标准化(模型看到的内容) + +- `Body` 是当前消息正文及其信封。 +- 引用回复上下文**始终附加**: + ``` + [Replying to +1555 id:ABC123] + > + [/Replying] + ``` +- 回复元数据也会设置: + - `ReplyToId` = stanzaId + - `ReplyToBody` = 引用正文或媒体占位符 + - `ReplyToSender` = E.164(已知时) +- 纯媒体入站消息使用占位符: + - `` + +## 群聊 + +- 群聊映射到 `agent::whatsapp:group:` 会话。 +- 群聊策略:`channels.whatsapp.groupPolicy = open|disabled|allowlist`(默认 `allowlist`)。 +- 激活模式: + - `mention`(默认):需要 @提及或正则匹配。 + - `always`:始终触发。 +- `/activation mention|always` 仅限所有者且必须作为独立消息发送。 +- 所有者 = `channels.whatsapp.allowFrom`(未设置时为自身 E.164)。 +- **历史注入**(仅待处理): + - 最近*未处理*的消息(默认 50 条)插入在: + `[Chat messages since your last reply - for context]`(已在会话中的消息不会被重复注入) + - 当前消息位于: + `[Current message - respond to this]` + - 发送者后缀附加:`[from: Name (+E164)]` +- 群聊元数据缓存 5 分钟(主题 + 参与者)。 + +## 回复投递(线程) + +- WhatsApp Web 发送标准消息(当前 Gateway 中无引用回复线程)。 +- 此渠道忽略回复标签。 + +## 确认反应(收到消息时自动反应) + +WhatsApp 可以在收到消息时立即自动发送表情反应,在机器人生成回复之前。这为用户提供即时反馈,表明其消息已收到。 + +**配置:** + +```json +{ + "whatsapp": { + "ackReaction": { + "emoji": "👀", + "direct": true, + "group": "mentions" + } + } +} +``` + +**选项:** + +- `emoji`(字符串):用于确认的表情(例如 "👀"、"✅"、"📨")。为空或省略 = 功能禁用。 +- `direct`(布尔值,默认:`true`):在私聊/DM 中发送反应。 +- `group`(字符串,默认:`"mentions"`):群聊行为: + - `"always"`:对所有群聊消息做出反应(即使没有 @提及) + - `"mentions"`:仅在机器人被 @提及时做出反应 + - `"never"`:从不在群聊中做出反应 + +**按账号覆盖:** + +```json +{ + "whatsapp": { + "accounts": { + "work": { + "ackReaction": { + "emoji": "✅", + "direct": false, + "group": "always" + } + } + } + } +} +``` + +**行为说明:** + +- 反应在收到消息时**立即**发送,在输入指示器或机器人回复之前。 +- 在 `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)。 +- 工具门控:`channels.whatsapp.actions.reactions`(默认:启用)。 + +## 限制 + +- 出站文本按 `channels.whatsapp.textChunkLimit` 分块(默认 4000)。 +- 可选换行分块:设置 `channels.whatsapp.chunkMode="newline"` 在空行(段落边界)处分割,再进行长度分块。 +- 入站媒体保存受 `channels.whatsapp.mediaMaxMb` 限制(默认 50 MB)。 +- 出站媒体项受 `agents.defaults.mediaMaxMb` 限制(默认 5 MB)。 + +## 出站发送(文本 + 媒体) + +- 使用活跃的网页监听器;如果 Gateway 未运行则报错。 +- 文本分块:每条消息最大 4k(可通过 `channels.whatsapp.textChunkLimit` 配置,可选 `channels.whatsapp.chunkMode`)。 +- 媒体: + - 支持图片/视频/音频/文档。 + - 音频以 PTT 发送;`audio/ogg` => `audio/ogg; codecs=opus`。 + - 仅第一个媒体项带字幕。 + - 媒体获取支持 HTTP(S) 和本地路径。 + - 动态 GIF:WhatsApp 期望带 `gifPlayback: true` 的 MP4 以实现内联循环播放。 + - CLI:`openclaw message send --media --gif-playback` + - Gateway:`send` 参数包含 `gifPlayback: true` + +## 语音消息(PTT 音频) + +WhatsApp 以**语音消息**(PTT 气泡)发送音频。 + +- 最佳效果:OGG/Opus。OpenClaw 将 `audio/ogg` 重写为 `audio/ogg; codecs=opus`。 +- WhatsApp 忽略 `[[audio_as_voice]]`(音频已作为语音消息发送)。 + +## 媒体限制 + 优化 + +- 默认出站上限:5 MB(每个媒体项)。 +- 覆盖:`agents.defaults.mediaMaxMb`。 +- 图片会自动优化为 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` 跳过行为。 + - 投递默认到最后使用的渠道(或已配置的目标)。 + +## 重连行为 + +- 退避策略:`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.mediaMaxMb`(入站媒体保存上限)。 +- `channels.whatsapp.ackReaction`(消息收到时的自动反应:`{emoji, direct, group}`)。 +- `channels.whatsapp.accounts..*`(按账号设置 + 可选 `authDir`)。 +- `channels.whatsapp.accounts..mediaMaxMb`(按账号入站媒体上限)。 +- `channels.whatsapp.accounts..ackReaction`(按账号确认反应覆盖)。 +- `channels.whatsapp.groupAllowFrom`(群聊发送者允许列表)。 +- `channels.whatsapp.groupPolicy`(群聊策略)。 +- `channels.whatsapp.historyLimit` / `channels.whatsapp.accounts..historyLimit`(群聊历史上下文;`0` 禁用)。 +- `channels.whatsapp.dmHistoryLimit`(私聊历史限制,按用户轮数)。按用户覆盖:`channels.whatsapp.dms[""].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..messagePrefix`;已弃用:`messages.messagePrefix`) +- `messages.responsePrefix`(出站前缀) +- `agents.defaults.mediaMaxMb` +- `agents.defaults.heartbeat.every` +- `agents.defaults.heartbeat.model`(可选覆盖) +- `agents.defaults.heartbeat.target` +- `agents.defaults.heartbeat.to` +- `agents.defaults.heartbeat.session` +- `agents.list[].heartbeat.*`(按智能体覆盖) +- `session.*`(scope、idle、store、mainKey) +- `web.enabled`(为 false 时禁用渠道启动) +- `web.heartbeatSeconds` +- `web.reconnect.*` + +## 日志 + 故障排除 + +- 子系统:`whatsapp/inbound`、`whatsapp/outbound`、`web-heartbeat`、`web-reconnect`。 +- 日志文件:`/tmp/openclaw/openclaw-YYYY-MM-DD.log`(可配置)。 +- 故障排除指南:[Gateway 故障排除](/gateway/troubleshooting)。 + +## 故障排除(快速) + +**未关联 / 需要二维码登录** + +- 症状:`channels status` 显示 `linked: false` 或警告"未关联"。 +- 修复:在 Gateway 主机上运行 `openclaw channels login` 并扫描二维码(WhatsApp → 设置 → 已关联设备)。 + +**已关联但断开连接 / 重连循环** + +- 症状:`channels status` 显示 `running, disconnected` 或警告"已关联但断开连接"。 +- 修复:`openclaw doctor`(或重启 Gateway)。如果问题持续,通过 `channels login` 重新关联并检查 `openclaw logs --follow`。 + +**Bun 运行时** + +- **不推荐**使用 Bun。WhatsApp(Baileys)和 Telegram 在 Bun 上不稳定。 + 请使用 **Node** 运行 Gateway。(参见入门指南运行时说明。) diff --git a/docs/zh-CN/channels/zalo.md b/docs/zh-CN/channels/zalo.md new file mode 100644 index 0000000000..b5238630d2 --- /dev/null +++ b/docs/zh-CN/channels/zalo.md @@ -0,0 +1,196 @@ +--- +read_when: + - 处理 Zalo 功能或 webhook 时 +summary: Zalo 机器人支持状态、功能和配置 +title: Zalo +x-i18n: + generated_at: "2026-02-01T19:58:32Z" + model: claude-opus-4-5 + provider: pi + source_hash: 0311d932349f96412b712970b5d37329b91929bf3020536edf3ca0ff464373c0 + source_path: channels/zalo.md + workflow: 14 +--- + +# Zalo (Bot API) + +状态:实验性。仅支持私信;根据 Zalo 文档,群组功能即将推出。 + +## 需要插件 + +Zalo 以插件形式提供,不包含在核心安装中。 + +- 通过 CLI 安装:`openclaw plugins install @openclaw/zalo` +- 或在上手引导中选择 **Zalo** 并确认安装提示 +- 详情:[插件](/plugin) + +## 快速设置(新手) + +1. 安装 Zalo 插件: + - 从源码检出安装:`openclaw plugins install ./extensions/zalo` + - 从 npm 安装(如已发布):`openclaw plugins install @openclaw/zalo` + - 或在上手引导中选择 **Zalo** 并确认安装提示 +2. 设置令牌: + - 环境变量:`ZALO_BOT_TOKEN=...` + - 或配置:`channels.zalo.botToken: "..."`。 +3. 重启 Gateway(或完成上手引导)。 +4. 私信访问默认使用配对模式;首次联系时需批准配对码。 + +最小配置: + +```json5 +{ + channels: { + zalo: { + enabled: true, + botToken: "12345689:abc-xyz", + dmPolicy: "pairing", + }, + }, +} +``` + +## 简介 + +Zalo 是一款面向越南市场的即时通讯应用;其 Bot API 允许 Gateway 运行一个用于一对一对话的机器人。 +它非常适合需要将消息确定性路由回 Zalo 的客服或通知场景。 + +- 由 Gateway 管理的 Zalo Bot API 渠道。 +- 确定性路由:回复始终返回 Zalo;模型不会选择渠道。 +- 私信共享智能体的主会话。 +- 群组尚不支持(Zalo 文档标注"即将推出")。 + +## 设置(快速路径) + +### 1) 创建机器人令牌(Zalo Bot Platform) + +1. 前往 **https://bot.zaloplatforms.com** 并登录。 +2. 创建新机器人并配置其设置。 +3. 复制机器人令牌(格式:`12345689:abc-xyz`)。 + +### 2) 配置令牌(环境变量或配置文件) + +示例: + +```json5 +{ + channels: { + zalo: { + enabled: true, + botToken: "12345689:abc-xyz", + dmPolicy: "pairing", + }, + }, +} +``` + +环境变量选项:`ZALO_BOT_TOKEN=...`(仅适用于默认账户)。 + +多账户支持:使用 `channels.zalo.accounts`,为每个账户配置令牌和可选的 `name`。 + +3. 重启 Gateway。当令牌被解析(通过环境变量或配置)时,Zalo 将启动。 +4. 私信访问默认使用配对模式。机器人首次被联系时,请批准配对码。 + +## 工作原理(行为) + +- 入站消息被标准化为共享渠道信封,并包含媒体占位符。 +- 回复始终路由回同一个 Zalo 聊天。 +- 默认使用长轮询;可通过 `channels.zalo.webhookUrl` 启用 webhook 模式。 + +## 限制 + +- 出站文本按 2000 字符分块(Zalo API 限制)。 +- 媒体下载/上传受 `channels.zalo.mediaMaxMb` 限制(默认 5)。 +- 由于 2000 字符限制导致流式传输意义不大,默认禁用流式传输。 + +## 访问控制(私信) + +### 私信访问 + +- 默认:`channels.zalo.dmPolicy = "pairing"`。未知发送者会收到配对码;消息在批准前将被忽略(配对码 1 小时后过期)。 +- 批准方式: + - `openclaw pairing list zalo` + - `openclaw pairing approve zalo ` +- 配对是默认的令牌交换方式。详情:[配对](/start/pairing) +- `channels.zalo.allowFrom` 接受数字用户 ID(不支持用户名查找)。 + +## 长轮询与 webhook + +- 默认:长轮询(无需公网 URL)。 +- Webhook 模式:设置 `channels.zalo.webhookUrl` 和 `channels.zalo.webhookSecret`。 + - Webhook 密钥必须为 8-256 个字符。 + - Webhook URL 必须使用 HTTPS。 + - Zalo 通过 `X-Bot-Api-Secret-Token` 请求头发送事件以进行验证。 + - Gateway HTTP 在 `channels.zalo.webhookPath` 处理 webhook 请求(默认为 webhook URL 路径)。 + +**注意:** 根据 Zalo API 文档,getUpdates(轮询)和 webhook 互斥。 + +## 支持的消息类型 + +- **文本消息**:完全支持,按 2000 字符分块。 +- **图片消息**:下载并处理入站图片;通过 `sendPhoto` 发送图片。 +- **贴纸**:已记录但未完全处理(无智能体响应)。 +- **不支持的类型**:已记录(例如来自受保护用户的消息)。 + +## 功能 + +| 功能 | 状态 | +| ------------ | ----------------------------- | +| 私信 | ✅ 支持 | +| 群组 | ❌ 即将推出(根据 Zalo 文档) | +| 媒体(图片) | ✅ 支持 | +| 表情回应 | ❌ 不支持 | +| 话题 | ❌ 不支持 | +| 投票 | ❌ 不支持 | +| 原生命令 | ❌ 不支持 | +| 流式传输 | ⚠️ 已禁用(2000 字符限制) | + +## 投递目标(CLI/定时任务) + +- 使用聊天 ID 作为目标。 +- 示例:`openclaw message send --channel zalo --target 123456789 --message "hi"`。 + +## 故障排除 + +**机器人无响应:** + +- 检查令牌是否有效:`openclaw channels status --probe` +- 验证发送者是否已批准(配对或 allowFrom) +- 检查 Gateway 日志:`openclaw logs --follow` + +**Webhook 未收到事件:** + +- 确保 webhook URL 使用 HTTPS +- 验证密钥令牌为 8-256 个字符 +- 确认 Gateway HTTP 端点在配置的路径上可达 +- 检查 getUpdates 轮询是否未在运行(两者互斥) + +## 配置参考(Zalo) + +完整配置:[配置](/gateway/configuration) + +提供商选项: + +- `channels.zalo.enabled`:启用/禁用渠道启动。 +- `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.webhookUrl`:启用 webhook 模式(需要 HTTPS)。 +- `channels.zalo.webhookSecret`:webhook 密钥(8-256 个字符)。 +- `channels.zalo.webhookPath`:Gateway HTTP 服务器上的 webhook 路径。 +- `channels.zalo.proxy`:API 请求的代理 URL。 + +多账户选项: + +- `channels.zalo.accounts..botToken`:每个账户的令牌。 +- `channels.zalo.accounts..tokenFile`:每个账户的令牌文件。 +- `channels.zalo.accounts..name`:显示名称。 +- `channels.zalo.accounts..enabled`:启用/禁用账户。 +- `channels.zalo.accounts..dmPolicy`:每个账户的私信策略。 +- `channels.zalo.accounts..allowFrom`:每个账户的允许列表。 +- `channels.zalo.accounts..webhookUrl`:每个账户的 webhook URL。 +- `channels.zalo.accounts..webhookSecret`:每个账户的 webhook 密钥。 +- `channels.zalo.accounts..webhookPath`:每个账户的 webhook 路径。 +- `channels.zalo.accounts..proxy`:每个账户的代理 URL。 diff --git a/docs/zh-CN/channels/zalouser.md b/docs/zh-CN/channels/zalouser.md new file mode 100644 index 0000000000..593fae872a --- /dev/null +++ b/docs/zh-CN/channels/zalouser.md @@ -0,0 +1,147 @@ +--- +read_when: + - 为 OpenClaw 设置 Zalo Personal + - 调试 Zalo Personal 登录或消息流 +summary: 通过 zca-cli(二维码登录)支持 Zalo 个人账号,功能与配置说明 +title: Zalo Personal +x-i18n: + generated_at: "2026-02-01T19:58:27Z" + model: claude-opus-4-5 + provider: pi + source_hash: 2a249728d556e5cc52274627bdaf390fa10e815afa04f4497feb57a2a0cb9261 + source_path: channels/zalouser.md + workflow: 14 +--- + +# Zalo Personal(非官方) + +状态:实验性。此集成通过 `zca-cli` 自动化操作一个**个人 Zalo 账号**。 + +> **警告:** 这是一个非官方集成,可能导致账号被暂停或封禁。使用风险自负。 + +## 需要安装插件 + +Zalo Personal 以插件形式提供,不包含在核心安装包中。 + +- 通过 CLI 安装:`openclaw plugins install @openclaw/zalouser` +- 或从源码检出安装:`openclaw plugins install ./extensions/zalouser` +- 详情:[插件](/plugin) + +## 前置条件:zca-cli + +Gateway 所在机器必须在 `PATH` 中包含 `zca` 可执行文件。 + +- 验证:`zca --version` +- 如果缺失,请安装 zca-cli(参见 `extensions/zalouser/README.md` 或上游 zca-cli 文档)。 + +## 快速设置(入门) + +1. 安装插件(见上文)。 +2. 登录(二维码方式,在 Gateway 机器上操作): + - `openclaw channels login --channel zalouser` + - 使用 Zalo 手机应用扫描终端中的二维码。 +3. 启用渠道: + +```json5 +{ + channels: { + zalouser: { + enabled: true, + dmPolicy: "pairing", + }, + }, +} +``` + +4. 重启 Gateway(或完成上手引导)。 +5. 私信访问默认为配对模式;首次联系时需批准配对码。 + +## 功能说明 + +- 使用 `zca listen` 接收入站消息。 +- 使用 `zca msg ...` 发送回复(文本/媒体/链接)。 +- 专为 Zalo Bot API 不可用时的"个人账号"使用场景设计。 + +## 命名说明 + +渠道 ID 为 `zalouser`,以明确表示这是对**个人 Zalo 用户账号**的自动化操作(非官方)。我们将 `zalo` 保留给未来可能的官方 Zalo API 集成。 + +## 查找 ID(通讯录) + +使用通讯录 CLI 发现联系人/群组及其 ID: + +```bash +openclaw directory self --channel zalouser +openclaw directory peers list --channel zalouser --query "name" +openclaw directory groups list --channel zalouser --query "work" +``` + +## 限制 + +- 出站文本按约 2000 字符分块(Zalo 客户端限制)。 +- 流式传输默认被禁用。 + +## 访问控制(私信) + +`channels.zalouser.dmPolicy` 支持:`pairing | allowlist | open | disabled`(默认:`pairing`)。 +`channels.zalouser.allowFrom` 接受用户 ID 或名称。向导在可用时通过 `zca friend find` 将名称解析为 ID。 + +通过以下方式批准: + +- `openclaw pairing list zalouser` +- `openclaw pairing approve zalouser ` + +## 群组访问(可选) + +- 默认:`channels.zalouser.groupPolicy = "open"`(允许群组)。未设置时使用 `channels.defaults.groupPolicy` 覆盖默认值。 +- 通过允许列表进行限制: + - `channels.zalouser.groupPolicy = "allowlist"` + - `channels.zalouser.groups`(键为群组 ID 或名称) +- 禁止所有群组:`channels.zalouser.groupPolicy = "disabled"`。 +- 配置向导可以提示设置群组允许列表。 +- 启动时,OpenClaw 会将允许列表中的群组/用户名称解析为 ID 并记录映射关系;未解析的条目保持原样。 + +示例: + +```json5 +{ + channels: { + zalouser: { + groupPolicy: "allowlist", + groups: { + "123456789": { allow: true }, + "Work Chat": { allow: true }, + }, + }, + }, +} +``` + +## 多账号 + +账号映射到 zca 配置文件。示例: + +```json5 +{ + channels: { + zalouser: { + enabled: true, + defaultAccount: "default", + accounts: { + work: { enabled: true, profile: "work" }, + }, + }, + }, +} +``` + +## 故障排除 + +**找不到 `zca`:** + +- 安装 zca-cli 并确保 Gateway 进程的 `PATH` 中包含该命令。 + +**登录状态无法保持:** + +- `openclaw channels status --probe` +- 重新登录:`openclaw channels logout --channel zalouser && openclaw channels login --channel zalouser` diff --git a/docs/zh-CN/cli/acp.md b/docs/zh-CN/cli/acp.md new file mode 100644 index 0000000000..edd42e29db --- /dev/null +++ b/docs/zh-CN/cli/acp.md @@ -0,0 +1,173 @@ +--- +read_when: + - 设置基于 ACP 的 IDE 集成 + - 调试 ACP 会话到 Gateway 的路由 +summary: 运行用于 IDE 集成的 ACP 桥接 +title: acp +x-i18n: + generated_at: "2026-02-01T19:58:33Z" + model: claude-opus-4-5 + provider: pi + source_hash: 0c09844297da250bc1a558423e7e534d6b6be9045de12d797c07ecd64a0c63ed + source_path: cli/acp.md + workflow: 14 +--- + +# acp + +运行与 OpenClaw Gateway 通信的 ACP(Agent Client Protocol)桥接。 + +此命令通过 stdio 使用 ACP 协议与 IDE 通信,并通过 WebSocket 将提示转发到 Gateway。它将 ACP 会话映射到 Gateway 会话密钥。 + +## 用法 + +```bash +openclaw acp + +# 远程 Gateway +openclaw acp --url wss://gateway-host:18789 --token + +# 附加到现有会话密钥 +openclaw acp --session agent:main:main + +# 通过标签附加(必须已存在) +openclaw acp --session-label "support inbox" + +# 在第一个提示之前重置会话密钥 +openclaw acp --session agent:main:main --reset-session +``` + +## ACP 客户端(调试) + +使用内置 ACP 客户端在无需 IDE 的情况下对桥接进行安装完整性检查。 +它会启动 ACP 桥接并允许你交互式地输入提示。 + +```bash +openclaw acp client + +# 将启动的桥接指向远程 Gateway +openclaw acp client --server-args --url wss://gateway-host:18789 --token + +# 覆盖服务器命令(默认: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。 + +1. 确保 Gateway 正在运行(本地或远程)。 +2. 配置 Gateway 目标(通过配置文件或标志)。 +3. 将你的 IDE 配置为通过 stdio 运行 `openclaw acp`。 + +示例配置(持久化): + +```bash +openclaw config set gateway.remote.url wss://gateway-host:18789 +openclaw config set gateway.remote.token +``` + +示例直接运行(不写入配置): + +```bash +openclaw acp --url wss://gateway-host:18789 --token +``` + +## 选择智能体 + +ACP 不直接选择智能体。它通过 Gateway 会话密钥进行路由。 + +使用智能体作用域的会话密钥来指定特定智能体: + +```bash +openclaw acp --session agent:main:main +openclaw acp --session agent:design:main +openclaw acp --session agent:qa:bug-123 +``` + +每个 ACP 会话映射到单个 Gateway 会话密钥。一个智能体可以有多个会话;除非你覆盖密钥或标签,否则 ACP 默认使用隔离的 `acp:` 会话。 + +## Zed 编辑器设置 + +在 `~/.config/zed/settings.json` 中添加自定义 ACP 智能体(或使用 Zed 的设置界面): + +```json +{ + "agent_servers": { + "OpenClaw ACP": { + "type": "custom", + "command": "openclaw", + "args": ["acp"], + "env": {} + } + } +} +``` + +要指定特定的 Gateway 或智能体: + +```json +{ + "agent_servers": { + "OpenClaw ACP": { + "type": "custom", + "command": "openclaw", + "args": [ + "acp", + "--url", + "wss://gateway-host:18789", + "--token", + "", + "--session", + "agent:design:main" + ], + "env": {} + } + } +} +``` + +在 Zed 中,打开 Agent 面板并选择 "OpenClaw ACP" 来开始一个对话线程。 + +## 会话映射 + +默认情况下,ACP 会话会获得一个带有 `acp:` 前缀的隔离 Gateway 会话密钥。 +要复用已知会话,请传递会话密钥或标签: + +- `--session `:使用特定的 Gateway 会话密钥。 +- `--session-label