From 282f46f26416fed26f262b7d48904deb0e099ef6 Mon Sep 17 00:00:00 2001 From: "openclaw-docs-i18n[bot]" Date: Thu, 30 Apr 2026 03:51:34 +0000 Subject: [PATCH] chore(i18n): refresh zh-TW translations --- docs/.i18n/zh-TW.tm.jsonl | 0 docs/zh-TW/.i18n/README.md | 44 + docs/zh-TW/AGENTS.md | 38 + docs/zh-TW/auth-credential-semantics.md | 116 + docs/zh-TW/automation/auth-monitoring.md | 18 + docs/zh-TW/automation/clawflow.md | 19 + docs/zh-TW/automation/cron-jobs.md | 489 ++++ docs/zh-TW/automation/cron-vs-heartbeat.md | 18 + docs/zh-TW/automation/gmail-pubsub.md | 18 + docs/zh-TW/automation/hooks.md | 332 +++ docs/zh-TW/automation/index.md | 132 ++ docs/zh-TW/automation/poll.md | 19 + docs/zh-TW/automation/standing-orders.md | 257 +++ docs/zh-TW/automation/taskflow.md | 162 ++ docs/zh-TW/automation/tasks.md | 375 ++++ docs/zh-TW/automation/troubleshooting.md | 19 + docs/zh-TW/automation/webhook.md | 19 + docs/zh-TW/brave-search.md | 114 + docs/zh-TW/channels/bluebubbles.md | 645 ++++++ docs/zh-TW/channels/broadcast-groups.md | 477 ++++ docs/zh-TW/channels/channel-routing.md | 157 ++ docs/zh-TW/channels/discord.md | 1267 +++++++++++ docs/zh-TW/channels/feishu.md | 485 ++++ docs/zh-TW/channels/googlechat.md | 275 +++ docs/zh-TW/channels/group-messages.md | 97 + docs/zh-TW/channels/groups.md | 496 +++++ docs/zh-TW/channels/imessage.md | 434 ++++ docs/zh-TW/channels/index.md | 65 + docs/zh-TW/channels/irc.md | 259 +++ docs/zh-TW/channels/line.md | 235 ++ docs/zh-TW/channels/location.md | 78 + docs/zh-TW/channels/matrix-migration.md | 380 ++++ docs/zh-TW/channels/matrix-push-rules.md | 157 ++ docs/zh-TW/channels/matrix.md | 926 ++++++++ docs/zh-TW/channels/mattermost.md | 550 +++++ docs/zh-TW/channels/msteams.md | 1028 +++++++++ docs/zh-TW/channels/nextcloud-talk.md | 182 ++ docs/zh-TW/channels/nostr.md | 260 +++ docs/zh-TW/channels/pairing.md | 179 ++ docs/zh-TW/channels/qa-channel.md | 93 + docs/zh-TW/channels/qqbot.md | 276 +++ docs/zh-TW/channels/signal.md | 345 +++ docs/zh-TW/channels/slack.md | 1040 +++++++++ docs/zh-TW/channels/synology-chat.md | 189 ++ docs/zh-TW/channels/telegram.md | 989 +++++++++ docs/zh-TW/channels/tlon.md | 298 +++ docs/zh-TW/channels/troubleshooting.md | 148 ++ docs/zh-TW/channels/twitch.md | 439 ++++ docs/zh-TW/channels/wechat.md | 155 ++ docs/zh-TW/channels/whatsapp.md | 681 ++++++ docs/zh-TW/channels/yuanbao.md | 425 ++++ docs/zh-TW/channels/zalo.md | 262 +++ docs/zh-TW/channels/zalouser.md | 207 ++ docs/zh-TW/ci.md | 367 +++ docs/zh-TW/cli/acp.md | 295 +++ docs/zh-TW/cli/agent.md | 76 + docs/zh-TW/cli/agents.md | 238 ++ docs/zh-TW/cli/approvals.md | 197 ++ docs/zh-TW/cli/backup.md | 92 + docs/zh-TW/cli/browser.md | 270 +++ docs/zh-TW/cli/channels.md | 146 ++ docs/zh-TW/cli/clawbot.md | 32 + docs/zh-TW/cli/commitments.md | 95 + docs/zh-TW/cli/completion.md | 46 + docs/zh-TW/cli/config.md | 507 +++++ docs/zh-TW/cli/configure.md | 79 + docs/zh-TW/cli/crestodian.md | 278 +++ docs/zh-TW/cli/cron.md | 246 +++ docs/zh-TW/cli/daemon.md | 70 + docs/zh-TW/cli/dashboard.md | 36 + docs/zh-TW/cli/devices.md | 181 ++ docs/zh-TW/cli/directory.md | 74 + docs/zh-TW/cli/dns.md | 60 + docs/zh-TW/cli/docs.md | 39 + docs/zh-TW/cli/doctor.md | 82 + docs/zh-TW/cli/flows.md | 30 + docs/zh-TW/cli/gateway.md | 548 +++++ docs/zh-TW/cli/health.md | 48 + docs/zh-TW/cli/hooks.md | 350 +++ docs/zh-TW/cli/index.md | 381 ++++ docs/zh-TW/cli/infer.md | 361 +++ docs/zh-TW/cli/logs.md | 71 + docs/zh-TW/cli/mcp.md | 525 +++++ docs/zh-TW/cli/memory.md | 188 ++ docs/zh-TW/cli/message.md | 311 +++ docs/zh-TW/cli/migrate.md | 177 ++ docs/zh-TW/cli/models.md | 203 ++ docs/zh-TW/cli/node.md | 162 ++ docs/zh-TW/cli/nodes.md | 81 + docs/zh-TW/cli/onboard.md | 225 ++ docs/zh-TW/cli/pairing.md | 84 + docs/zh-TW/cli/plugins.md | 378 ++++ docs/zh-TW/cli/proxy.md | 54 + docs/zh-TW/cli/qr.md | 64 + docs/zh-TW/cli/reset.md | 46 + docs/zh-TW/cli/sandbox.md | 204 ++ docs/zh-TW/cli/secrets.md | 209 ++ docs/zh-TW/cli/security.md | 96 + docs/zh-TW/cli/sessions.md | 130 ++ docs/zh-TW/cli/setup.md | 62 + docs/zh-TW/cli/skills.md | 80 + docs/zh-TW/cli/status.md | 50 + docs/zh-TW/cli/system.md | 82 + docs/zh-TW/cli/tasks.md | 109 + docs/zh-TW/cli/tui.md | 73 + docs/zh-TW/cli/uninstall.md | 51 + docs/zh-TW/cli/update.md | 167 ++ docs/zh-TW/cli/voicecall.md | 68 + docs/zh-TW/cli/webhooks.md | 103 + docs/zh-TW/cli/wiki.md | 243 ++ docs/zh-TW/concepts/active-memory.md | 629 ++++++ docs/zh-TW/concepts/agent-loop.md | 187 ++ docs/zh-TW/concepts/agent-runtimes.md | 170 ++ docs/zh-TW/concepts/agent-workspace.md | 236 ++ docs/zh-TW/concepts/agent.md | 118 + docs/zh-TW/concepts/architecture.md | 157 ++ docs/zh-TW/concepts/channel-docking.md | 138 ++ docs/zh-TW/concepts/commitments.md | 148 ++ docs/zh-TW/concepts/compaction.md | 205 ++ docs/zh-TW/concepts/context-engine.md | 301 +++ docs/zh-TW/concepts/context.md | 184 ++ docs/zh-TW/concepts/delegate-architecture.md | 326 +++ docs/zh-TW/concepts/dreaming.md | 250 +++ docs/zh-TW/concepts/experimental-features.md | 57 + docs/zh-TW/concepts/features.md | 86 + docs/zh-TW/concepts/markdown-formatting.md | 125 ++ docs/zh-TW/concepts/memory-builtin.md | 147 ++ docs/zh-TW/concepts/memory-honcho.md | 130 ++ docs/zh-TW/concepts/memory-qmd.md | 206 ++ docs/zh-TW/concepts/memory-search.md | 145 ++ docs/zh-TW/concepts/memory.md | 193 ++ docs/zh-TW/concepts/messages.md | 212 ++ docs/zh-TW/concepts/model-failover.md | 350 +++ docs/zh-TW/concepts/model-providers.md | 707 ++++++ docs/zh-TW/concepts/models.md | 348 +++ docs/zh-TW/concepts/multi-agent.md | 621 ++++++ docs/zh-TW/concepts/oauth.md | 199 ++ docs/zh-TW/concepts/openclaw-sdk.md | 272 +++ docs/zh-TW/concepts/presence.md | 102 + docs/zh-TW/concepts/qa-e2e-automation.md | 434 ++++ docs/zh-TW/concepts/qa-matrix.md | 146 ++ docs/zh-TW/concepts/queue-steering.md | 72 + docs/zh-TW/concepts/queue.md | 130 ++ docs/zh-TW/concepts/retry.md | 91 + docs/zh-TW/concepts/session-pruning.md | 93 + docs/zh-TW/concepts/session-tool.md | 181 ++ docs/zh-TW/concepts/session.md | 158 ++ docs/zh-TW/concepts/soul.md | 115 + docs/zh-TW/concepts/streaming.md | 210 ++ docs/zh-TW/concepts/system-prompt.md | 234 ++ docs/zh-TW/concepts/timezone.md | 102 + docs/zh-TW/concepts/typebox.md | 314 +++ docs/zh-TW/concepts/typing-indicators.md | 78 + docs/zh-TW/concepts/usage-tracking.md | 51 + docs/zh-TW/date-time.md | 135 ++ docs/zh-TW/debug/node-issue.md | 97 + docs/zh-TW/diagnostics/flags.md | 127 ++ docs/zh-TW/gateway/authentication.md | 232 ++ docs/zh-TW/gateway/background-process.md | 137 ++ docs/zh-TW/gateway/bonjour.md | 284 +++ docs/zh-TW/gateway/bridge-protocol.md | 97 + docs/zh-TW/gateway/cli-backends.md | 405 ++++ docs/zh-TW/gateway/config-agents.md | 1386 ++++++++++++ docs/zh-TW/gateway/config-channels.md | 912 ++++++++ docs/zh-TW/gateway/config-tools.md | 709 ++++++ docs/zh-TW/gateway/configuration-examples.md | 665 ++++++ docs/zh-TW/gateway/configuration-reference.md | 1242 +++++++++++ docs/zh-TW/gateway/configuration.md | 726 ++++++ docs/zh-TW/gateway/diagnostics.md | 152 ++ docs/zh-TW/gateway/discovery.md | 156 ++ docs/zh-TW/gateway/doctor.md | 491 ++++ docs/zh-TW/gateway/gateway-lock.md | 44 + docs/zh-TW/gateway/health.md | 74 + docs/zh-TW/gateway/heartbeat.md | 497 +++++ docs/zh-TW/gateway/index.md | 416 ++++ docs/zh-TW/gateway/local-models.md | 299 +++ docs/zh-TW/gateway/logging.md | 136 ++ docs/zh-TW/gateway/multiple-gateways.md | 184 ++ docs/zh-TW/gateway/network-model.md | 36 + docs/zh-TW/gateway/openai-http-api.md | 290 +++ docs/zh-TW/gateway/openresponses-http-api.md | 345 +++ docs/zh-TW/gateway/openshell.md | 302 +++ docs/zh-TW/gateway/opentelemetry.md | 323 +++ docs/zh-TW/gateway/pairing.md | 210 ++ docs/zh-TW/gateway/prometheus.md | 220 ++ docs/zh-TW/gateway/protocol.md | 633 ++++++ docs/zh-TW/gateway/remote-gateway-readme.md | 176 ++ docs/zh-TW/gateway/remote.md | 271 +++ .../sandbox-vs-tool-policy-vs-elevated.md | 146 ++ docs/zh-TW/gateway/sandboxing.md | 503 +++++ docs/zh-TW/gateway/secrets-plan-contract.md | 121 + docs/zh-TW/gateway/secrets.md | 574 +++++ docs/zh-TW/gateway/security/audit-checks.md | 132 ++ docs/zh-TW/gateway/security/index.md | 1313 +++++++++++ docs/zh-TW/gateway/tailscale.md | 156 ++ docs/zh-TW/gateway/tools-invoke-http-api.md | 173 ++ docs/zh-TW/gateway/troubleshooting.md | 636 ++++++ docs/zh-TW/gateway/trusted-proxy-auth.md | 458 ++++ docs/zh-TW/help/debugging.md | 385 ++++ docs/zh-TW/help/environment.md | 181 ++ docs/zh-TW/help/faq-first-run.md | 867 ++++++++ docs/zh-TW/help/faq-models.md | 541 +++++ docs/zh-TW/help/faq.md | 1965 +++++++++++++++++ .../gpt55-codex-agentic-parity-maintainers.md | 203 ++ docs/zh-TW/help/gpt55-codex-agentic-parity.md | 239 ++ docs/zh-TW/help/index.md | 45 + docs/zh-TW/help/scripts.md | 63 + docs/zh-TW/help/testing-live.md | 578 +++++ docs/zh-TW/help/testing.md | 755 +++++++ docs/zh-TW/help/troubleshooting.md | 387 ++++ docs/zh-TW/index.md | 203 ++ docs/zh-TW/install/ansible.md | 238 ++ docs/zh-TW/install/azure.md | 324 +++ docs/zh-TW/install/bun.md | 66 + docs/zh-TW/install/clawdock.md | 111 + docs/zh-TW/install/development-channels.md | 143 ++ docs/zh-TW/install/digitalocean.md | 141 ++ docs/zh-TW/install/docker-vm-runtime.md | 160 ++ docs/zh-TW/install/docker.md | 504 +++++ docs/zh-TW/install/exe-dev.md | 202 ++ docs/zh-TW/install/fly.md | 529 +++++ docs/zh-TW/install/gcp.md | 425 ++++ docs/zh-TW/install/hetzner.md | 291 +++ docs/zh-TW/install/hostinger.md | 105 + docs/zh-TW/install/index.md | 218 ++ docs/zh-TW/install/installer.md | 460 ++++ docs/zh-TW/install/kubernetes.md | 204 ++ docs/zh-TW/install/macos-vm.md | 290 +++ docs/zh-TW/install/migrating-claude.md | 172 ++ docs/zh-TW/install/migrating-hermes.md | 184 ++ docs/zh-TW/install/migrating.md | 136 ++ docs/zh-TW/install/nix.md | 106 + docs/zh-TW/install/node.md | 149 ++ docs/zh-TW/install/northflank.mdx | 51 + docs/zh-TW/install/oracle.md | 169 ++ docs/zh-TW/install/podman.md | 216 ++ docs/zh-TW/install/railway.mdx | 99 + docs/zh-TW/install/raspberry-pi.md | 170 ++ docs/zh-TW/install/render.mdx | 172 ++ docs/zh-TW/install/uninstall.md | 138 ++ docs/zh-TW/install/updating.md | 223 ++ docs/zh-TW/logging.md | 232 ++ docs/zh-TW/network.md | 77 + docs/zh-TW/nodes/audio.md | 224 ++ docs/zh-TW/nodes/camera.md | 173 ++ docs/zh-TW/nodes/images.md | 86 + docs/zh-TW/nodes/index.md | 434 ++++ docs/zh-TW/nodes/location-command.md | 109 + docs/zh-TW/nodes/media-understanding.md | 476 ++++ docs/zh-TW/nodes/talk.md | 124 ++ docs/zh-TW/nodes/troubleshooting.md | 134 ++ docs/zh-TW/nodes/voicewake.md | 100 + docs/zh-TW/perplexity.md | 193 ++ docs/zh-TW/pi-dev.md | 89 + docs/zh-TW/pi.md | 573 +++++ .../plan/codex-context-engine-harness.md | 543 +++++ docs/zh-TW/plan/ui-channels.md | 263 +++ docs/zh-TW/platforms/android.md | 270 +++ docs/zh-TW/platforms/digitalocean.md | 273 +++ docs/zh-TW/platforms/index.md | 67 + docs/zh-TW/platforms/ios.md | 279 +++ docs/zh-TW/platforms/linux.md | 147 ++ docs/zh-TW/platforms/mac/bundled-gateway.md | 78 + docs/zh-TW/platforms/mac/canvas.md | 130 ++ docs/zh-TW/platforms/mac/child-process.md | 68 + docs/zh-TW/platforms/mac/dev-setup.md | 119 + docs/zh-TW/platforms/mac/health.md | 46 + docs/zh-TW/platforms/mac/icon.md | 43 + docs/zh-TW/platforms/mac/logging.md | 69 + docs/zh-TW/platforms/mac/menu-bar.md | 93 + docs/zh-TW/platforms/mac/peekaboo.md | 77 + docs/zh-TW/platforms/mac/permissions.md | 55 + docs/zh-TW/platforms/mac/remote.md | 108 + docs/zh-TW/platforms/mac/signing.md | 59 + docs/zh-TW/platforms/mac/skills.md | 50 + docs/zh-TW/platforms/mac/voice-overlay.md | 73 + docs/zh-TW/platforms/mac/voicewake.md | 80 + docs/zh-TW/platforms/mac/webchat.md | 60 + docs/zh-TW/platforms/mac/xpc.md | 73 + docs/zh-TW/platforms/macos.md | 218 ++ docs/zh-TW/platforms/oracle.md | 312 +++ docs/zh-TW/platforms/raspberry-pi.md | 426 ++++ docs/zh-TW/platforms/windows.md | 261 +++ docs/zh-TW/plugins/agent-tools.md | 22 + docs/zh-TW/plugins/architecture-internals.md | 1092 +++++++++ docs/zh-TW/plugins/architecture.md | 488 ++++ docs/zh-TW/plugins/building-extensions.md | 20 + docs/zh-TW/plugins/building-plugins.md | 341 +++ docs/zh-TW/plugins/bundles.md | 310 +++ docs/zh-TW/plugins/codex-computer-use.md | 277 +++ docs/zh-TW/plugins/codex-harness.md | 856 +++++++ docs/zh-TW/plugins/community.md | 173 ++ docs/zh-TW/plugins/compatibility.md | 120 + docs/zh-TW/plugins/google-meet.md | 1270 +++++++++++ docs/zh-TW/plugins/hooks.md | 264 +++ docs/zh-TW/plugins/manifest.md | 1059 +++++++++ docs/zh-TW/plugins/memory-lancedb.md | 372 ++++ docs/zh-TW/plugins/memory-wiki.md | 490 ++++ docs/zh-TW/plugins/message-presentation.md | 338 +++ docs/zh-TW/plugins/sdk-agent-harness.md | 265 +++ docs/zh-TW/plugins/sdk-channel-plugins.md | 677 ++++++ docs/zh-TW/plugins/sdk-channel-turn.md | 400 ++++ docs/zh-TW/plugins/sdk-entrypoints.md | 266 +++ docs/zh-TW/plugins/sdk-migration.md | 780 +++++++ docs/zh-TW/plugins/sdk-overview.md | 316 +++ docs/zh-TW/plugins/sdk-provider-plugins.md | 754 +++++++ docs/zh-TW/plugins/sdk-runtime.md | 551 +++++ docs/zh-TW/plugins/sdk-setup.md | 536 +++++ docs/zh-TW/plugins/sdk-subpaths.md | 336 +++ docs/zh-TW/plugins/sdk-testing.md | 401 ++++ docs/zh-TW/plugins/skill-workshop.md | 713 ++++++ docs/zh-TW/plugins/voice-call.md | 634 ++++++ docs/zh-TW/plugins/webhooks.md | 194 ++ docs/zh-TW/plugins/zalouser.md | 94 + docs/zh-TW/prose.md | 144 ++ docs/zh-TW/providers/alibaba.md | 120 + docs/zh-TW/providers/anthropic.md | 347 +++ docs/zh-TW/providers/arcee.md | 151 ++ docs/zh-TW/providers/azure-speech.md | 121 + docs/zh-TW/providers/bedrock-mantle.md | 206 ++ docs/zh-TW/providers/bedrock.md | 335 +++ docs/zh-TW/providers/cerebras.md | 101 + docs/zh-TW/providers/chutes.md | 152 ++ docs/zh-TW/providers/claude-max-api-proxy.md | 193 ++ docs/zh-TW/providers/cloudflare-ai-gateway.md | 126 ++ docs/zh-TW/providers/comfy.md | 369 ++++ docs/zh-TW/providers/deepgram.md | 178 ++ docs/zh-TW/providers/deepinfra.md | 85 + docs/zh-TW/providers/deepseek.md | 148 ++ docs/zh-TW/providers/elevenlabs.md | 121 + docs/zh-TW/providers/fal.md | 175 ++ docs/zh-TW/providers/fireworks.md | 114 + docs/zh-TW/providers/github-copilot.md | 172 ++ docs/zh-TW/providers/glm.md | 117 + docs/zh-TW/providers/google.md | 439 ++++ docs/zh-TW/providers/gradium.md | 71 + docs/zh-TW/providers/groq.md | 146 ++ docs/zh-TW/providers/huggingface.md | 242 ++ docs/zh-TW/providers/index.md | 108 + docs/zh-TW/providers/inferrs.md | 199 ++ docs/zh-TW/providers/inworld.md | 104 + docs/zh-TW/providers/kilocode.md | 129 ++ docs/zh-TW/providers/litellm.md | 239 ++ docs/zh-TW/providers/lmstudio.md | 213 ++ docs/zh-TW/providers/minimax.md | 506 +++++ docs/zh-TW/providers/mistral.md | 180 ++ docs/zh-TW/providers/models.md | 74 + docs/zh-TW/providers/moonshot.md | 418 ++++ docs/zh-TW/providers/nvidia.md | 114 + docs/zh-TW/providers/ollama.md | 1178 ++++++++++ docs/zh-TW/providers/openai.md | 900 ++++++++ docs/zh-TW/providers/opencode-go.md | 129 ++ docs/zh-TW/providers/opencode.md | 156 ++ docs/zh-TW/providers/openrouter.md | 179 ++ docs/zh-TW/providers/perplexity-provider.md | 115 + docs/zh-TW/providers/qianfan.md | 138 ++ docs/zh-TW/providers/qwen.md | 321 +++ docs/zh-TW/providers/runway.md | 96 + docs/zh-TW/providers/senseaudio.md | 67 + docs/zh-TW/providers/sglang.md | 156 ++ docs/zh-TW/providers/stepfun.md | 236 ++ docs/zh-TW/providers/synthetic.md | 159 ++ docs/zh-TW/providers/tencent.md | 103 + docs/zh-TW/providers/together.md | 143 ++ docs/zh-TW/providers/venice.md | 322 +++ docs/zh-TW/providers/vercel-ai-gateway.md | 131 ++ docs/zh-TW/providers/vllm.md | 345 +++ docs/zh-TW/providers/volcengine.md | 185 ++ docs/zh-TW/providers/vydra.md | 179 ++ docs/zh-TW/providers/xai.md | 435 ++++ docs/zh-TW/providers/xiaomi.md | 189 ++ docs/zh-TW/providers/zai.md | 201 ++ docs/zh-TW/reference/AGENTS.default.md | 138 ++ docs/zh-TW/reference/RELEASING.md | 341 +++ docs/zh-TW/reference/api-usage-costs.md | 176 ++ .../application-modernization-plan.md | 192 ++ docs/zh-TW/reference/credits.md | 42 + docs/zh-TW/reference/device-models.md | 57 + docs/zh-TW/reference/memory-config.md | 635 ++++++ .../reference/openclaw-sdk-api-design.md | 380 ++++ docs/zh-TW/reference/prompt-caching.md | 316 +++ docs/zh-TW/reference/rich-output-protocol.md | 75 + docs/zh-TW/reference/rpc.md | 52 + .../reference/secretref-credential-surface.md | 163 ++ .../session-management-compaction.md | 404 ++++ docs/zh-TW/reference/templates/AGENTS.dev.md | 96 + docs/zh-TW/reference/templates/AGENTS.md | 232 ++ docs/zh-TW/reference/templates/BOOT.md | 23 + docs/zh-TW/reference/templates/BOOTSTRAP.md | 73 + docs/zh-TW/reference/templates/HEARTBEAT.md | 23 + .../zh-TW/reference/templates/IDENTITY.dev.md | 59 + docs/zh-TW/reference/templates/IDENTITY.md | 41 + docs/zh-TW/reference/templates/SOUL.dev.md | 89 + docs/zh-TW/reference/templates/SOUL.md | 56 + docs/zh-TW/reference/templates/TOOLS.dev.md | 36 + docs/zh-TW/reference/templates/TOOLS.md | 58 + docs/zh-TW/reference/templates/USER.dev.md | 30 + docs/zh-TW/reference/templates/USER.md | 35 + docs/zh-TW/reference/test.md | 149 ++ docs/zh-TW/reference/token-use.md | 232 ++ docs/zh-TW/reference/transcript-hygiene.md | 210 ++ docs/zh-TW/reference/wizard.md | 259 +++ .../security/CONTRIBUTING-THREAT-MODEL.md | 110 + docs/zh-TW/security/THREAT-MODEL-ATLAS.md | 620 ++++++ docs/zh-TW/security/formal-verification.md | 175 ++ docs/zh-TW/security/network-proxy.md | 176 ++ docs/zh-TW/start/bootstrapping.md | 53 + docs/zh-TW/start/docs-directory.md | 77 + docs/zh-TW/start/getting-started.md | 153 ++ docs/zh-TW/start/hubs.md | 209 ++ docs/zh-TW/start/lore.md | 230 ++ docs/zh-TW/start/onboarding-overview.md | 77 + docs/zh-TW/start/onboarding.md | 97 + docs/zh-TW/start/openclaw.md | 244 ++ docs/zh-TW/start/quickstart.md | 32 + docs/zh-TW/start/setup.md | 181 ++ docs/zh-TW/start/showcase.md | 390 ++++ docs/zh-TW/start/wizard-cli-automation.md | 239 ++ docs/zh-TW/start/wizard-cli-reference.md | 328 +++ docs/zh-TW/start/wizard.md | 132 ++ ...4-22-tweakcn-custom-theme-import-design.md | 327 +++ docs/zh-TW/tools/acp-agents-setup.md | 321 +++ docs/zh-TW/tools/acp-agents.md | 809 +++++++ docs/zh-TW/tools/agent-send.md | 101 + docs/zh-TW/tools/apply-patch.md | 63 + docs/zh-TW/tools/brave-search.md | 138 ++ docs/zh-TW/tools/browser-control.md | 382 ++++ .../tools/browser-linux-troubleshooting.md | 176 ++ docs/zh-TW/tools/browser-login.md | 86 + ...wsl2-windows-remote-cdp-troubleshooting.md | 226 ++ docs/zh-TW/tools/browser.md | 689 ++++++ docs/zh-TW/tools/btw.md | 132 ++ docs/zh-TW/tools/capability-cookbook.md | 143 ++ docs/zh-TW/tools/clawhub.md | 456 ++++ docs/zh-TW/tools/code-execution.md | 95 + docs/zh-TW/tools/creating-skills.md | 127 ++ docs/zh-TW/tools/diffs.md | 506 +++++ docs/zh-TW/tools/duckduckgo-search.md | 107 + docs/zh-TW/tools/elevated.md | 115 + docs/zh-TW/tools/exa-search.md | 150 ++ docs/zh-TW/tools/exec-approvals-advanced.md | 276 +++ docs/zh-TW/tools/exec-approvals.md | 417 ++++ docs/zh-TW/tools/exec.md | 277 +++ docs/zh-TW/tools/firecrawl.md | 151 ++ docs/zh-TW/tools/gemini-search.md | 98 + docs/zh-TW/tools/grok-search.md | 106 + docs/zh-TW/tools/image-generation.md | 365 +++ docs/zh-TW/tools/index.md | 225 ++ docs/zh-TW/tools/kimi-search.md | 92 + docs/zh-TW/tools/llm-task.md | 125 ++ docs/zh-TW/tools/lobster.md | 355 +++ docs/zh-TW/tools/loop-detection.md | 114 + docs/zh-TW/tools/media-overview.md | 145 ++ docs/zh-TW/tools/minimax-search.md | 102 + docs/zh-TW/tools/multi-agent-sandbox-tools.md | 405 ++++ docs/zh-TW/tools/music-generation.md | 301 +++ docs/zh-TW/tools/ollama-search.md | 143 ++ docs/zh-TW/tools/pdf.md | 202 ++ docs/zh-TW/tools/perplexity-search.md | 218 ++ docs/zh-TW/tools/plugin.md | 437 ++++ docs/zh-TW/tools/reactions.md | 89 + docs/zh-TW/tools/searxng-search.md | 137 ++ docs/zh-TW/tools/skills-config.md | 127 ++ docs/zh-TW/tools/skills.md | 405 ++++ docs/zh-TW/tools/slash-commands.md | 485 ++++ docs/zh-TW/tools/subagents.md | 510 +++++ docs/zh-TW/tools/tavily.md | 126 ++ docs/zh-TW/tools/thinking.md | 139 ++ docs/zh-TW/tools/tokenjuice.md | 87 + docs/zh-TW/tools/trajectory.md | 196 ++ docs/zh-TW/tools/tts.md | 947 ++++++++ docs/zh-TW/tools/video-generation.md | 525 +++++ docs/zh-TW/tools/web-fetch.md | 178 ++ docs/zh-TW/tools/web.md | 405 ++++ docs/zh-TW/tts.md | 18 + docs/zh-TW/vps.md | 146 ++ docs/zh-TW/web/control-ui.md | 458 ++++ docs/zh-TW/web/dashboard.md | 98 + docs/zh-TW/web/index.md | 133 ++ docs/zh-TW/web/tui.md | 247 +++ docs/zh-TW/web/webchat.md | 91 + 481 files changed, 122613 insertions(+) create mode 100644 docs/.i18n/zh-TW.tm.jsonl create mode 100644 docs/zh-TW/.i18n/README.md create mode 100644 docs/zh-TW/AGENTS.md create mode 100644 docs/zh-TW/auth-credential-semantics.md create mode 100644 docs/zh-TW/automation/auth-monitoring.md create mode 100644 docs/zh-TW/automation/clawflow.md create mode 100644 docs/zh-TW/automation/cron-jobs.md create mode 100644 docs/zh-TW/automation/cron-vs-heartbeat.md create mode 100644 docs/zh-TW/automation/gmail-pubsub.md create mode 100644 docs/zh-TW/automation/hooks.md create mode 100644 docs/zh-TW/automation/index.md create mode 100644 docs/zh-TW/automation/poll.md create mode 100644 docs/zh-TW/automation/standing-orders.md create mode 100644 docs/zh-TW/automation/taskflow.md create mode 100644 docs/zh-TW/automation/tasks.md create mode 100644 docs/zh-TW/automation/troubleshooting.md create mode 100644 docs/zh-TW/automation/webhook.md create mode 100644 docs/zh-TW/brave-search.md create mode 100644 docs/zh-TW/channels/bluebubbles.md create mode 100644 docs/zh-TW/channels/broadcast-groups.md create mode 100644 docs/zh-TW/channels/channel-routing.md create mode 100644 docs/zh-TW/channels/discord.md create mode 100644 docs/zh-TW/channels/feishu.md create mode 100644 docs/zh-TW/channels/googlechat.md create mode 100644 docs/zh-TW/channels/group-messages.md create mode 100644 docs/zh-TW/channels/groups.md create mode 100644 docs/zh-TW/channels/imessage.md create mode 100644 docs/zh-TW/channels/index.md create mode 100644 docs/zh-TW/channels/irc.md create mode 100644 docs/zh-TW/channels/line.md create mode 100644 docs/zh-TW/channels/location.md create mode 100644 docs/zh-TW/channels/matrix-migration.md create mode 100644 docs/zh-TW/channels/matrix-push-rules.md create mode 100644 docs/zh-TW/channels/matrix.md create mode 100644 docs/zh-TW/channels/mattermost.md create mode 100644 docs/zh-TW/channels/msteams.md create mode 100644 docs/zh-TW/channels/nextcloud-talk.md create mode 100644 docs/zh-TW/channels/nostr.md create mode 100644 docs/zh-TW/channels/pairing.md create mode 100644 docs/zh-TW/channels/qa-channel.md create mode 100644 docs/zh-TW/channels/qqbot.md create mode 100644 docs/zh-TW/channels/signal.md create mode 100644 docs/zh-TW/channels/slack.md create mode 100644 docs/zh-TW/channels/synology-chat.md create mode 100644 docs/zh-TW/channels/telegram.md create mode 100644 docs/zh-TW/channels/tlon.md create mode 100644 docs/zh-TW/channels/troubleshooting.md create mode 100644 docs/zh-TW/channels/twitch.md create mode 100644 docs/zh-TW/channels/wechat.md create mode 100644 docs/zh-TW/channels/whatsapp.md create mode 100644 docs/zh-TW/channels/yuanbao.md create mode 100644 docs/zh-TW/channels/zalo.md create mode 100644 docs/zh-TW/channels/zalouser.md create mode 100644 docs/zh-TW/ci.md create mode 100644 docs/zh-TW/cli/acp.md create mode 100644 docs/zh-TW/cli/agent.md create mode 100644 docs/zh-TW/cli/agents.md create mode 100644 docs/zh-TW/cli/approvals.md create mode 100644 docs/zh-TW/cli/backup.md create mode 100644 docs/zh-TW/cli/browser.md create mode 100644 docs/zh-TW/cli/channels.md create mode 100644 docs/zh-TW/cli/clawbot.md create mode 100644 docs/zh-TW/cli/commitments.md create mode 100644 docs/zh-TW/cli/completion.md create mode 100644 docs/zh-TW/cli/config.md create mode 100644 docs/zh-TW/cli/configure.md create mode 100644 docs/zh-TW/cli/crestodian.md create mode 100644 docs/zh-TW/cli/cron.md create mode 100644 docs/zh-TW/cli/daemon.md create mode 100644 docs/zh-TW/cli/dashboard.md create mode 100644 docs/zh-TW/cli/devices.md create mode 100644 docs/zh-TW/cli/directory.md create mode 100644 docs/zh-TW/cli/dns.md create mode 100644 docs/zh-TW/cli/docs.md create mode 100644 docs/zh-TW/cli/doctor.md create mode 100644 docs/zh-TW/cli/flows.md create mode 100644 docs/zh-TW/cli/gateway.md create mode 100644 docs/zh-TW/cli/health.md create mode 100644 docs/zh-TW/cli/hooks.md create mode 100644 docs/zh-TW/cli/index.md create mode 100644 docs/zh-TW/cli/infer.md create mode 100644 docs/zh-TW/cli/logs.md create mode 100644 docs/zh-TW/cli/mcp.md create mode 100644 docs/zh-TW/cli/memory.md create mode 100644 docs/zh-TW/cli/message.md create mode 100644 docs/zh-TW/cli/migrate.md create mode 100644 docs/zh-TW/cli/models.md create mode 100644 docs/zh-TW/cli/node.md create mode 100644 docs/zh-TW/cli/nodes.md create mode 100644 docs/zh-TW/cli/onboard.md create mode 100644 docs/zh-TW/cli/pairing.md create mode 100644 docs/zh-TW/cli/plugins.md create mode 100644 docs/zh-TW/cli/proxy.md create mode 100644 docs/zh-TW/cli/qr.md create mode 100644 docs/zh-TW/cli/reset.md create mode 100644 docs/zh-TW/cli/sandbox.md create mode 100644 docs/zh-TW/cli/secrets.md create mode 100644 docs/zh-TW/cli/security.md create mode 100644 docs/zh-TW/cli/sessions.md create mode 100644 docs/zh-TW/cli/setup.md create mode 100644 docs/zh-TW/cli/skills.md create mode 100644 docs/zh-TW/cli/status.md create mode 100644 docs/zh-TW/cli/system.md create mode 100644 docs/zh-TW/cli/tasks.md create mode 100644 docs/zh-TW/cli/tui.md create mode 100644 docs/zh-TW/cli/uninstall.md create mode 100644 docs/zh-TW/cli/update.md create mode 100644 docs/zh-TW/cli/voicecall.md create mode 100644 docs/zh-TW/cli/webhooks.md create mode 100644 docs/zh-TW/cli/wiki.md create mode 100644 docs/zh-TW/concepts/active-memory.md create mode 100644 docs/zh-TW/concepts/agent-loop.md create mode 100644 docs/zh-TW/concepts/agent-runtimes.md create mode 100644 docs/zh-TW/concepts/agent-workspace.md create mode 100644 docs/zh-TW/concepts/agent.md create mode 100644 docs/zh-TW/concepts/architecture.md create mode 100644 docs/zh-TW/concepts/channel-docking.md create mode 100644 docs/zh-TW/concepts/commitments.md create mode 100644 docs/zh-TW/concepts/compaction.md create mode 100644 docs/zh-TW/concepts/context-engine.md create mode 100644 docs/zh-TW/concepts/context.md create mode 100644 docs/zh-TW/concepts/delegate-architecture.md create mode 100644 docs/zh-TW/concepts/dreaming.md create mode 100644 docs/zh-TW/concepts/experimental-features.md create mode 100644 docs/zh-TW/concepts/features.md create mode 100644 docs/zh-TW/concepts/markdown-formatting.md create mode 100644 docs/zh-TW/concepts/memory-builtin.md create mode 100644 docs/zh-TW/concepts/memory-honcho.md create mode 100644 docs/zh-TW/concepts/memory-qmd.md create mode 100644 docs/zh-TW/concepts/memory-search.md create mode 100644 docs/zh-TW/concepts/memory.md create mode 100644 docs/zh-TW/concepts/messages.md create mode 100644 docs/zh-TW/concepts/model-failover.md create mode 100644 docs/zh-TW/concepts/model-providers.md create mode 100644 docs/zh-TW/concepts/models.md create mode 100644 docs/zh-TW/concepts/multi-agent.md create mode 100644 docs/zh-TW/concepts/oauth.md create mode 100644 docs/zh-TW/concepts/openclaw-sdk.md create mode 100644 docs/zh-TW/concepts/presence.md create mode 100644 docs/zh-TW/concepts/qa-e2e-automation.md create mode 100644 docs/zh-TW/concepts/qa-matrix.md create mode 100644 docs/zh-TW/concepts/queue-steering.md create mode 100644 docs/zh-TW/concepts/queue.md create mode 100644 docs/zh-TW/concepts/retry.md create mode 100644 docs/zh-TW/concepts/session-pruning.md create mode 100644 docs/zh-TW/concepts/session-tool.md create mode 100644 docs/zh-TW/concepts/session.md create mode 100644 docs/zh-TW/concepts/soul.md create mode 100644 docs/zh-TW/concepts/streaming.md create mode 100644 docs/zh-TW/concepts/system-prompt.md create mode 100644 docs/zh-TW/concepts/timezone.md create mode 100644 docs/zh-TW/concepts/typebox.md create mode 100644 docs/zh-TW/concepts/typing-indicators.md create mode 100644 docs/zh-TW/concepts/usage-tracking.md create mode 100644 docs/zh-TW/date-time.md create mode 100644 docs/zh-TW/debug/node-issue.md create mode 100644 docs/zh-TW/diagnostics/flags.md create mode 100644 docs/zh-TW/gateway/authentication.md create mode 100644 docs/zh-TW/gateway/background-process.md create mode 100644 docs/zh-TW/gateway/bonjour.md create mode 100644 docs/zh-TW/gateway/bridge-protocol.md create mode 100644 docs/zh-TW/gateway/cli-backends.md create mode 100644 docs/zh-TW/gateway/config-agents.md create mode 100644 docs/zh-TW/gateway/config-channels.md create mode 100644 docs/zh-TW/gateway/config-tools.md create mode 100644 docs/zh-TW/gateway/configuration-examples.md create mode 100644 docs/zh-TW/gateway/configuration-reference.md create mode 100644 docs/zh-TW/gateway/configuration.md create mode 100644 docs/zh-TW/gateway/diagnostics.md create mode 100644 docs/zh-TW/gateway/discovery.md create mode 100644 docs/zh-TW/gateway/doctor.md create mode 100644 docs/zh-TW/gateway/gateway-lock.md create mode 100644 docs/zh-TW/gateway/health.md create mode 100644 docs/zh-TW/gateway/heartbeat.md create mode 100644 docs/zh-TW/gateway/index.md create mode 100644 docs/zh-TW/gateway/local-models.md create mode 100644 docs/zh-TW/gateway/logging.md create mode 100644 docs/zh-TW/gateway/multiple-gateways.md create mode 100644 docs/zh-TW/gateway/network-model.md create mode 100644 docs/zh-TW/gateway/openai-http-api.md create mode 100644 docs/zh-TW/gateway/openresponses-http-api.md create mode 100644 docs/zh-TW/gateway/openshell.md create mode 100644 docs/zh-TW/gateway/opentelemetry.md create mode 100644 docs/zh-TW/gateway/pairing.md create mode 100644 docs/zh-TW/gateway/prometheus.md create mode 100644 docs/zh-TW/gateway/protocol.md create mode 100644 docs/zh-TW/gateway/remote-gateway-readme.md create mode 100644 docs/zh-TW/gateway/remote.md create mode 100644 docs/zh-TW/gateway/sandbox-vs-tool-policy-vs-elevated.md create mode 100644 docs/zh-TW/gateway/sandboxing.md create mode 100644 docs/zh-TW/gateway/secrets-plan-contract.md create mode 100644 docs/zh-TW/gateway/secrets.md create mode 100644 docs/zh-TW/gateway/security/audit-checks.md create mode 100644 docs/zh-TW/gateway/security/index.md create mode 100644 docs/zh-TW/gateway/tailscale.md create mode 100644 docs/zh-TW/gateway/tools-invoke-http-api.md create mode 100644 docs/zh-TW/gateway/troubleshooting.md create mode 100644 docs/zh-TW/gateway/trusted-proxy-auth.md create mode 100644 docs/zh-TW/help/debugging.md create mode 100644 docs/zh-TW/help/environment.md create mode 100644 docs/zh-TW/help/faq-first-run.md create mode 100644 docs/zh-TW/help/faq-models.md create mode 100644 docs/zh-TW/help/faq.md create mode 100644 docs/zh-TW/help/gpt55-codex-agentic-parity-maintainers.md create mode 100644 docs/zh-TW/help/gpt55-codex-agentic-parity.md create mode 100644 docs/zh-TW/help/index.md create mode 100644 docs/zh-TW/help/scripts.md create mode 100644 docs/zh-TW/help/testing-live.md create mode 100644 docs/zh-TW/help/testing.md create mode 100644 docs/zh-TW/help/troubleshooting.md create mode 100644 docs/zh-TW/index.md create mode 100644 docs/zh-TW/install/ansible.md create mode 100644 docs/zh-TW/install/azure.md create mode 100644 docs/zh-TW/install/bun.md create mode 100644 docs/zh-TW/install/clawdock.md create mode 100644 docs/zh-TW/install/development-channels.md create mode 100644 docs/zh-TW/install/digitalocean.md create mode 100644 docs/zh-TW/install/docker-vm-runtime.md create mode 100644 docs/zh-TW/install/docker.md create mode 100644 docs/zh-TW/install/exe-dev.md create mode 100644 docs/zh-TW/install/fly.md create mode 100644 docs/zh-TW/install/gcp.md create mode 100644 docs/zh-TW/install/hetzner.md create mode 100644 docs/zh-TW/install/hostinger.md create mode 100644 docs/zh-TW/install/index.md create mode 100644 docs/zh-TW/install/installer.md create mode 100644 docs/zh-TW/install/kubernetes.md create mode 100644 docs/zh-TW/install/macos-vm.md create mode 100644 docs/zh-TW/install/migrating-claude.md create mode 100644 docs/zh-TW/install/migrating-hermes.md create mode 100644 docs/zh-TW/install/migrating.md create mode 100644 docs/zh-TW/install/nix.md create mode 100644 docs/zh-TW/install/node.md create mode 100644 docs/zh-TW/install/northflank.mdx create mode 100644 docs/zh-TW/install/oracle.md create mode 100644 docs/zh-TW/install/podman.md create mode 100644 docs/zh-TW/install/railway.mdx create mode 100644 docs/zh-TW/install/raspberry-pi.md create mode 100644 docs/zh-TW/install/render.mdx create mode 100644 docs/zh-TW/install/uninstall.md create mode 100644 docs/zh-TW/install/updating.md create mode 100644 docs/zh-TW/logging.md create mode 100644 docs/zh-TW/network.md create mode 100644 docs/zh-TW/nodes/audio.md create mode 100644 docs/zh-TW/nodes/camera.md create mode 100644 docs/zh-TW/nodes/images.md create mode 100644 docs/zh-TW/nodes/index.md create mode 100644 docs/zh-TW/nodes/location-command.md create mode 100644 docs/zh-TW/nodes/media-understanding.md create mode 100644 docs/zh-TW/nodes/talk.md create mode 100644 docs/zh-TW/nodes/troubleshooting.md create mode 100644 docs/zh-TW/nodes/voicewake.md create mode 100644 docs/zh-TW/perplexity.md create mode 100644 docs/zh-TW/pi-dev.md create mode 100644 docs/zh-TW/pi.md create mode 100644 docs/zh-TW/plan/codex-context-engine-harness.md create mode 100644 docs/zh-TW/plan/ui-channels.md create mode 100644 docs/zh-TW/platforms/android.md create mode 100644 docs/zh-TW/platforms/digitalocean.md create mode 100644 docs/zh-TW/platforms/index.md create mode 100644 docs/zh-TW/platforms/ios.md create mode 100644 docs/zh-TW/platforms/linux.md create mode 100644 docs/zh-TW/platforms/mac/bundled-gateway.md create mode 100644 docs/zh-TW/platforms/mac/canvas.md create mode 100644 docs/zh-TW/platforms/mac/child-process.md create mode 100644 docs/zh-TW/platforms/mac/dev-setup.md create mode 100644 docs/zh-TW/platforms/mac/health.md create mode 100644 docs/zh-TW/platforms/mac/icon.md create mode 100644 docs/zh-TW/platforms/mac/logging.md create mode 100644 docs/zh-TW/platforms/mac/menu-bar.md create mode 100644 docs/zh-TW/platforms/mac/peekaboo.md create mode 100644 docs/zh-TW/platforms/mac/permissions.md create mode 100644 docs/zh-TW/platforms/mac/remote.md create mode 100644 docs/zh-TW/platforms/mac/signing.md create mode 100644 docs/zh-TW/platforms/mac/skills.md create mode 100644 docs/zh-TW/platforms/mac/voice-overlay.md create mode 100644 docs/zh-TW/platforms/mac/voicewake.md create mode 100644 docs/zh-TW/platforms/mac/webchat.md create mode 100644 docs/zh-TW/platforms/mac/xpc.md create mode 100644 docs/zh-TW/platforms/macos.md create mode 100644 docs/zh-TW/platforms/oracle.md create mode 100644 docs/zh-TW/platforms/raspberry-pi.md create mode 100644 docs/zh-TW/platforms/windows.md create mode 100644 docs/zh-TW/plugins/agent-tools.md create mode 100644 docs/zh-TW/plugins/architecture-internals.md create mode 100644 docs/zh-TW/plugins/architecture.md create mode 100644 docs/zh-TW/plugins/building-extensions.md create mode 100644 docs/zh-TW/plugins/building-plugins.md create mode 100644 docs/zh-TW/plugins/bundles.md create mode 100644 docs/zh-TW/plugins/codex-computer-use.md create mode 100644 docs/zh-TW/plugins/codex-harness.md create mode 100644 docs/zh-TW/plugins/community.md create mode 100644 docs/zh-TW/plugins/compatibility.md create mode 100644 docs/zh-TW/plugins/google-meet.md create mode 100644 docs/zh-TW/plugins/hooks.md create mode 100644 docs/zh-TW/plugins/manifest.md create mode 100644 docs/zh-TW/plugins/memory-lancedb.md create mode 100644 docs/zh-TW/plugins/memory-wiki.md create mode 100644 docs/zh-TW/plugins/message-presentation.md create mode 100644 docs/zh-TW/plugins/sdk-agent-harness.md create mode 100644 docs/zh-TW/plugins/sdk-channel-plugins.md create mode 100644 docs/zh-TW/plugins/sdk-channel-turn.md create mode 100644 docs/zh-TW/plugins/sdk-entrypoints.md create mode 100644 docs/zh-TW/plugins/sdk-migration.md create mode 100644 docs/zh-TW/plugins/sdk-overview.md create mode 100644 docs/zh-TW/plugins/sdk-provider-plugins.md create mode 100644 docs/zh-TW/plugins/sdk-runtime.md create mode 100644 docs/zh-TW/plugins/sdk-setup.md create mode 100644 docs/zh-TW/plugins/sdk-subpaths.md create mode 100644 docs/zh-TW/plugins/sdk-testing.md create mode 100644 docs/zh-TW/plugins/skill-workshop.md create mode 100644 docs/zh-TW/plugins/voice-call.md create mode 100644 docs/zh-TW/plugins/webhooks.md create mode 100644 docs/zh-TW/plugins/zalouser.md create mode 100644 docs/zh-TW/prose.md create mode 100644 docs/zh-TW/providers/alibaba.md create mode 100644 docs/zh-TW/providers/anthropic.md create mode 100644 docs/zh-TW/providers/arcee.md create mode 100644 docs/zh-TW/providers/azure-speech.md create mode 100644 docs/zh-TW/providers/bedrock-mantle.md create mode 100644 docs/zh-TW/providers/bedrock.md create mode 100644 docs/zh-TW/providers/cerebras.md create mode 100644 docs/zh-TW/providers/chutes.md create mode 100644 docs/zh-TW/providers/claude-max-api-proxy.md create mode 100644 docs/zh-TW/providers/cloudflare-ai-gateway.md create mode 100644 docs/zh-TW/providers/comfy.md create mode 100644 docs/zh-TW/providers/deepgram.md create mode 100644 docs/zh-TW/providers/deepinfra.md create mode 100644 docs/zh-TW/providers/deepseek.md create mode 100644 docs/zh-TW/providers/elevenlabs.md create mode 100644 docs/zh-TW/providers/fal.md create mode 100644 docs/zh-TW/providers/fireworks.md create mode 100644 docs/zh-TW/providers/github-copilot.md create mode 100644 docs/zh-TW/providers/glm.md create mode 100644 docs/zh-TW/providers/google.md create mode 100644 docs/zh-TW/providers/gradium.md create mode 100644 docs/zh-TW/providers/groq.md create mode 100644 docs/zh-TW/providers/huggingface.md create mode 100644 docs/zh-TW/providers/index.md create mode 100644 docs/zh-TW/providers/inferrs.md create mode 100644 docs/zh-TW/providers/inworld.md create mode 100644 docs/zh-TW/providers/kilocode.md create mode 100644 docs/zh-TW/providers/litellm.md create mode 100644 docs/zh-TW/providers/lmstudio.md create mode 100644 docs/zh-TW/providers/minimax.md create mode 100644 docs/zh-TW/providers/mistral.md create mode 100644 docs/zh-TW/providers/models.md create mode 100644 docs/zh-TW/providers/moonshot.md create mode 100644 docs/zh-TW/providers/nvidia.md create mode 100644 docs/zh-TW/providers/ollama.md create mode 100644 docs/zh-TW/providers/openai.md create mode 100644 docs/zh-TW/providers/opencode-go.md create mode 100644 docs/zh-TW/providers/opencode.md create mode 100644 docs/zh-TW/providers/openrouter.md create mode 100644 docs/zh-TW/providers/perplexity-provider.md create mode 100644 docs/zh-TW/providers/qianfan.md create mode 100644 docs/zh-TW/providers/qwen.md create mode 100644 docs/zh-TW/providers/runway.md create mode 100644 docs/zh-TW/providers/senseaudio.md create mode 100644 docs/zh-TW/providers/sglang.md create mode 100644 docs/zh-TW/providers/stepfun.md create mode 100644 docs/zh-TW/providers/synthetic.md create mode 100644 docs/zh-TW/providers/tencent.md create mode 100644 docs/zh-TW/providers/together.md create mode 100644 docs/zh-TW/providers/venice.md create mode 100644 docs/zh-TW/providers/vercel-ai-gateway.md create mode 100644 docs/zh-TW/providers/vllm.md create mode 100644 docs/zh-TW/providers/volcengine.md create mode 100644 docs/zh-TW/providers/vydra.md create mode 100644 docs/zh-TW/providers/xai.md create mode 100644 docs/zh-TW/providers/xiaomi.md create mode 100644 docs/zh-TW/providers/zai.md create mode 100644 docs/zh-TW/reference/AGENTS.default.md create mode 100644 docs/zh-TW/reference/RELEASING.md create mode 100644 docs/zh-TW/reference/api-usage-costs.md create mode 100644 docs/zh-TW/reference/application-modernization-plan.md create mode 100644 docs/zh-TW/reference/credits.md create mode 100644 docs/zh-TW/reference/device-models.md create mode 100644 docs/zh-TW/reference/memory-config.md create mode 100644 docs/zh-TW/reference/openclaw-sdk-api-design.md create mode 100644 docs/zh-TW/reference/prompt-caching.md create mode 100644 docs/zh-TW/reference/rich-output-protocol.md create mode 100644 docs/zh-TW/reference/rpc.md create mode 100644 docs/zh-TW/reference/secretref-credential-surface.md create mode 100644 docs/zh-TW/reference/session-management-compaction.md create mode 100644 docs/zh-TW/reference/templates/AGENTS.dev.md create mode 100644 docs/zh-TW/reference/templates/AGENTS.md create mode 100644 docs/zh-TW/reference/templates/BOOT.md create mode 100644 docs/zh-TW/reference/templates/BOOTSTRAP.md create mode 100644 docs/zh-TW/reference/templates/HEARTBEAT.md create mode 100644 docs/zh-TW/reference/templates/IDENTITY.dev.md create mode 100644 docs/zh-TW/reference/templates/IDENTITY.md create mode 100644 docs/zh-TW/reference/templates/SOUL.dev.md create mode 100644 docs/zh-TW/reference/templates/SOUL.md create mode 100644 docs/zh-TW/reference/templates/TOOLS.dev.md create mode 100644 docs/zh-TW/reference/templates/TOOLS.md create mode 100644 docs/zh-TW/reference/templates/USER.dev.md create mode 100644 docs/zh-TW/reference/templates/USER.md create mode 100644 docs/zh-TW/reference/test.md create mode 100644 docs/zh-TW/reference/token-use.md create mode 100644 docs/zh-TW/reference/transcript-hygiene.md create mode 100644 docs/zh-TW/reference/wizard.md create mode 100644 docs/zh-TW/security/CONTRIBUTING-THREAT-MODEL.md create mode 100644 docs/zh-TW/security/THREAT-MODEL-ATLAS.md create mode 100644 docs/zh-TW/security/formal-verification.md create mode 100644 docs/zh-TW/security/network-proxy.md create mode 100644 docs/zh-TW/start/bootstrapping.md create mode 100644 docs/zh-TW/start/docs-directory.md create mode 100644 docs/zh-TW/start/getting-started.md create mode 100644 docs/zh-TW/start/hubs.md create mode 100644 docs/zh-TW/start/lore.md create mode 100644 docs/zh-TW/start/onboarding-overview.md create mode 100644 docs/zh-TW/start/onboarding.md create mode 100644 docs/zh-TW/start/openclaw.md create mode 100644 docs/zh-TW/start/quickstart.md create mode 100644 docs/zh-TW/start/setup.md create mode 100644 docs/zh-TW/start/showcase.md create mode 100644 docs/zh-TW/start/wizard-cli-automation.md create mode 100644 docs/zh-TW/start/wizard-cli-reference.md create mode 100644 docs/zh-TW/start/wizard.md create mode 100644 docs/zh-TW/superpowers/specs/2026-04-22-tweakcn-custom-theme-import-design.md create mode 100644 docs/zh-TW/tools/acp-agents-setup.md create mode 100644 docs/zh-TW/tools/acp-agents.md create mode 100644 docs/zh-TW/tools/agent-send.md create mode 100644 docs/zh-TW/tools/apply-patch.md create mode 100644 docs/zh-TW/tools/brave-search.md create mode 100644 docs/zh-TW/tools/browser-control.md create mode 100644 docs/zh-TW/tools/browser-linux-troubleshooting.md create mode 100644 docs/zh-TW/tools/browser-login.md create mode 100644 docs/zh-TW/tools/browser-wsl2-windows-remote-cdp-troubleshooting.md create mode 100644 docs/zh-TW/tools/browser.md create mode 100644 docs/zh-TW/tools/btw.md create mode 100644 docs/zh-TW/tools/capability-cookbook.md create mode 100644 docs/zh-TW/tools/clawhub.md create mode 100644 docs/zh-TW/tools/code-execution.md create mode 100644 docs/zh-TW/tools/creating-skills.md create mode 100644 docs/zh-TW/tools/diffs.md create mode 100644 docs/zh-TW/tools/duckduckgo-search.md create mode 100644 docs/zh-TW/tools/elevated.md create mode 100644 docs/zh-TW/tools/exa-search.md create mode 100644 docs/zh-TW/tools/exec-approvals-advanced.md create mode 100644 docs/zh-TW/tools/exec-approvals.md create mode 100644 docs/zh-TW/tools/exec.md create mode 100644 docs/zh-TW/tools/firecrawl.md create mode 100644 docs/zh-TW/tools/gemini-search.md create mode 100644 docs/zh-TW/tools/grok-search.md create mode 100644 docs/zh-TW/tools/image-generation.md create mode 100644 docs/zh-TW/tools/index.md create mode 100644 docs/zh-TW/tools/kimi-search.md create mode 100644 docs/zh-TW/tools/llm-task.md create mode 100644 docs/zh-TW/tools/lobster.md create mode 100644 docs/zh-TW/tools/loop-detection.md create mode 100644 docs/zh-TW/tools/media-overview.md create mode 100644 docs/zh-TW/tools/minimax-search.md create mode 100644 docs/zh-TW/tools/multi-agent-sandbox-tools.md create mode 100644 docs/zh-TW/tools/music-generation.md create mode 100644 docs/zh-TW/tools/ollama-search.md create mode 100644 docs/zh-TW/tools/pdf.md create mode 100644 docs/zh-TW/tools/perplexity-search.md create mode 100644 docs/zh-TW/tools/plugin.md create mode 100644 docs/zh-TW/tools/reactions.md create mode 100644 docs/zh-TW/tools/searxng-search.md create mode 100644 docs/zh-TW/tools/skills-config.md create mode 100644 docs/zh-TW/tools/skills.md create mode 100644 docs/zh-TW/tools/slash-commands.md create mode 100644 docs/zh-TW/tools/subagents.md create mode 100644 docs/zh-TW/tools/tavily.md create mode 100644 docs/zh-TW/tools/thinking.md create mode 100644 docs/zh-TW/tools/tokenjuice.md create mode 100644 docs/zh-TW/tools/trajectory.md create mode 100644 docs/zh-TW/tools/tts.md create mode 100644 docs/zh-TW/tools/video-generation.md create mode 100644 docs/zh-TW/tools/web-fetch.md create mode 100644 docs/zh-TW/tools/web.md create mode 100644 docs/zh-TW/tts.md create mode 100644 docs/zh-TW/vps.md create mode 100644 docs/zh-TW/web/control-ui.md create mode 100644 docs/zh-TW/web/dashboard.md create mode 100644 docs/zh-TW/web/index.md create mode 100644 docs/zh-TW/web/tui.md create mode 100644 docs/zh-TW/web/webchat.md diff --git a/docs/.i18n/zh-TW.tm.jsonl b/docs/.i18n/zh-TW.tm.jsonl new file mode 100644 index 000000000..e69de29bb diff --git a/docs/zh-TW/.i18n/README.md b/docs/zh-TW/.i18n/README.md new file mode 100644 index 000000000..8b89478f0 --- /dev/null +++ b/docs/zh-TW/.i18n/README.md @@ -0,0 +1,44 @@ +--- +x-i18n: + generated_at: "2026-04-30T02:44:12Z" + model: gpt-5.5 + provider: openai + source_hash: 6e1cf417b0c04d001bc494fbe03ac2fcb66866f759e21646dbfd1a9c3a968bff + source_path: .i18n/README.md + workflow: 16 +--- + +# OpenClaw 文件 i18n 資產 + +此資料夾存放來源文件儲存庫的翻譯設定。 + +產生的語系頁面和即時語系翻譯記憶現在位於發布儲存庫(`openclaw/docs`,本機同層 checkout `~/Projects/openclaw-docs`)。 + +## 檔案 + +- `glossary..json` — 偏好的術語對應(用於提示指引)。 +- `.tm.jsonl` — 以工作流程 + 模型 + 文字雜湊為索引鍵的翻譯記憶(快取)。在此儲存庫中,語系 TM 檔案會隨需產生。 + +## 詞彙表格式 + +`glossary..json` 是項目陣列: + +```json +{ + "source": "troubleshooting", + "target": "故障排除", + "ignore_case": true, + "whole_word": false +} +``` + +欄位: + +- `source`:偏好使用的英文(或來源)片語。 +- `target`:偏好的翻譯輸出。 + +## 備註 + +- 詞彙表項目會作為**提示指引**傳遞給模型(不進行確定性重寫)。 +- `scripts/docs-i18n` 仍負責翻譯產生。 +- 來源儲存庫會將英文文件同步至發布儲存庫;語系產生會在該處依語系於推送、排程和 release dispatch 時執行。 diff --git a/docs/zh-TW/AGENTS.md b/docs/zh-TW/AGENTS.md new file mode 100644 index 000000000..5b34f2e55 --- /dev/null +++ b/docs/zh-TW/AGENTS.md @@ -0,0 +1,38 @@ +--- +x-i18n: + generated_at: "2026-04-30T02:44:12Z" + model: gpt-5.5 + provider: openai + source_hash: 8b046833f9a15dc61894ab9e808a09a9fb055ef7ada5c3d4893fbe5f70dec126 + source_path: AGENTS.md + workflow: 16 +--- + +# 文件指南 + +此目錄負責文件撰寫、Mintlify 連結規則,以及文件 i18n 政策。 + +## Mintlify 規則 + +- 文件託管於 Mintlify (`https://docs.openclaw.ai`)。 +- `docs/**/*.md` 中的內部文件連結必須保持根相對路徑,且不得有 `.md` 或 `.mdx` 後綴(範例:`[Config](/gateway/configuration)`)。 +- 區段交叉參照應在根相對路徑上使用錨點(範例:`[Hooks](/gateway/configuration-reference#hooks)`)。 +- 文件標題應避免使用長破折號和撇號,因為 Mintlify 的錨點產生在這些字元上很脆弱。 +- README 和其他由 GitHub 轉譯的文件應保留絕對文件 URL,讓連結在 Mintlify 之外也能運作。 +- 文件內容必須保持通用:不得包含個人裝置名稱、主機名稱或本機路徑;請使用像 `user@gateway-host` 這樣的佔位符。 + +## 文件內容規則 + +- 對於文件、UI 文案和選擇器清單,除非該區段明確描述執行階段順序或自動偵測順序,否則服務/提供者應依字母順序排列。 +- 保持隨附 Plugin 命名與根目錄 `AGENTS.md` 中 repo 全域的 Plugin 術語規則一致。 + +## 文件 i18n + +- 此 repo 不維護外語文件。產生的發布輸出位於獨立的 `openclaw/docs` repo(本機通常複製為 `../openclaw-docs`)。 +- 不要在此處的 `docs//**` 下新增或編輯在地化文件。 +- 將此 repo 中的英文文件與詞彙表檔案視為事實來源。 +- 流程:在此處更新英文文件,視需要更新 `docs/.i18n/glossary..json`,然後讓發布 repo 同步與 `scripts/docs-i18n` 在 `openclaw/docs` 中執行。 +- 重新執行 `scripts/docs-i18n` 之前,請為任何必須保持英文或使用固定翻譯的新技術術語、頁面標題或短導覽標籤新增詞彙表項目。 +- `pnpm docs:check-i18n-glossary` 是用於檢查已變更英文文件標題與短內部文件標籤的防護。 +- 翻譯記憶位於發布 repo 中產生的 `docs/.i18n/*.tm.jsonl` 檔案。 +- 請參閱 `docs/.i18n/README.md`。 diff --git a/docs/zh-TW/auth-credential-semantics.md b/docs/zh-TW/auth-credential-semantics.md new file mode 100644 index 000000000..4bf1bcdaf --- /dev/null +++ b/docs/zh-TW/auth-credential-semantics.md @@ -0,0 +1,116 @@ +--- +read_when: + - 處理身分驗證設定檔解析或憑證路由 + - 偵錯模型身分驗證失敗或設定檔順序 +summary: 身分驗證設定檔的標準憑證適用條件與解析語意 +title: 驗證憑證語意 +x-i18n: + generated_at: "2026-04-30T02:44:44Z" + model: gpt-5.5 + provider: openai + source_hash: 0525a71d3f08b7aa95e2f06acc6c23d87cd92d6b5fe4fc050ecf2b7caff84b3f + source_path: auth-credential-semantics.md + workflow: 16 +--- + +本文件定義下列各處使用的標準認證資料資格與解析語意: + +- `resolveAuthProfileOrder` +- `resolveApiKeyForProfile` +- `models status --probe` +- `doctor-auth` + +目標是讓選擇時與執行階段行為保持一致。 + +## 穩定的探測原因代碼 + +- `ok` +- `excluded_by_auth_order` +- `missing_credential` +- `invalid_expires` +- `expired` +- `unresolved_ref` +- `no_model` + +## 權杖認證資料 + +權杖認證資料(`type: "token"`)支援內嵌 `token` 和/或 `tokenRef`。 + +### 資格規則 + +1. 當 `token` 和 `tokenRef` 兩者皆不存在時,權杖設定檔不符合資格。 +2. `expires` 是選用項。 +3. 如果存在 `expires`,它必須是大於 `0` 的有限數字。 +4. 如果 `expires` 無效(`NaN`、`0`、負數、非有限值或型別錯誤),設定檔不符合資格,原因為 `invalid_expires`。 +5. 如果 `expires` 是過去時間,設定檔不符合資格,原因為 `expired`。 +6. `tokenRef` 不會略過 `expires` 驗證。 + +### 解析規則 + +1. 解析器對 `expires` 的語意與資格語意相符。 +2. 對符合資格的設定檔,權杖內容可從內嵌值或 `tokenRef` 解析。 +3. 無法解析的參照會在 `models status --probe` 輸出中產生 `unresolved_ref`。 + +## 代理程式複本可攜性 + +代理程式驗證繼承採用讀穿模式。當代理程式沒有本機設定檔時, +它可在執行階段從預設/主要代理程式儲存區解析設定檔,而不需將 +秘密內容複製到自己的 `auth-profiles.json`。 + +明確複製流程(例如 `openclaw agents add`)會使用此可攜性政策: + +- `api_key` 設定檔可攜,除非 `copyToAgents: false`。 +- `token` 設定檔可攜,除非 `copyToAgents: false`。 +- `oauth` 設定檔預設不可攜,因為重新整理權杖可能是 + 單次使用或對輪替敏感。 +- 由提供者擁有的 OAuth 流程只有在已知可安全跨代理程式 + 複製重新整理內容時,才能以 `copyToAgents: true` 選擇加入。 + +不可攜設定檔仍可透過讀穿繼承使用,除非目標代理程式 +另外登入並建立自己的本機設定檔。 + +## 明確驗證順序篩選 + +- 當為某個提供者設定 `auth.order.` 或驗證儲存區順序覆寫時, + `models status --probe` 只會探測仍保留在該提供者已解析驗證順序中的 + 設定檔 ID。 +- 該提供者的已儲存設定檔若從明確順序中省略, + 之後不會被靜默嘗試。探測輸出會以 + `reasonCode: excluded_by_auth_order` 回報,詳細資訊為 + `Excluded by auth.order for this provider.` + +## 探測目標解析 + +- 探測目標可以來自驗證設定檔、環境認證資料或 + `models.json`。 +- 如果提供者具有認證資料,但 OpenClaw 無法為其解析可探測的模型 + 候選項,`models status --probe` 會回報 `status: no_model`,並帶有 + `reasonCode: no_model`。 + +## 外部 CLI 認證資料探索 + +- 由外部 CLI 擁有的僅執行階段認證資料,只會在 + 提供者、執行階段或驗證設定檔屬於目前操作範圍時探索,或在 + 該外部來源的已儲存本機設定檔已存在時探索。 +- 唯讀/狀態路徑會傳入 `allowKeychainPrompt: false`;它們只使用檔案支援的 + 外部 CLI 認證資料,且不會讀取或重用 macOS Keychain 結果。 + +## OAuth SecretRef 政策防護 + +- SecretRef 輸入僅適用於靜態認證資料。 +- 如果設定檔認證資料是 `type: "oauth"`,則該設定檔認證資料內容不支援 SecretRef 物件。 +- 如果 `auth.profiles..mode` 是 `"oauth"`,則會拒絕該設定檔使用由 SecretRef 支援的 `keyRef`/`tokenRef` 輸入。 +- 違規會在啟動/重新載入驗證解析路徑中造成硬性失敗。 + +## 舊版相容訊息 + +為了維持腳本相容性,探測錯誤會讓第一行保持不變: + +`Auth profile credentials are missing or expired.` + +後續行可加入適合閱讀的詳細資訊與穩定原因代碼。 + +## 相關 + +- [秘密管理](/zh-TW/gateway/secrets) +- [驗證儲存](/zh-TW/concepts/oauth) diff --git a/docs/zh-TW/automation/auth-monitoring.md b/docs/zh-TW/automation/auth-monitoring.md new file mode 100644 index 000000000..ecbf5817d --- /dev/null +++ b/docs/zh-TW/automation/auth-monitoring.md @@ -0,0 +1,18 @@ +--- +summary: 重新導向至 /gateway/authentication +title: 身分驗證監控 +x-i18n: + generated_at: "2026-04-30T02:44:25Z" + model: gpt-5.5 + provider: openai + source_hash: d0bb68c2881911afc634aaba017444a5a8356f4cc519f0a2b5e415ff9ad739f3 + source_path: automation/auth-monitoring.md + workflow: 16 +--- + +身份驗證監控位於 [身份驗證](/zh-TW/gateway/authentication) 下。 + +## 相關內容 + +- [自動化疑難排解](/zh-TW/automation/cron-jobs) +- [掛鉤](/zh-TW/automation/hooks) diff --git a/docs/zh-TW/automation/clawflow.md b/docs/zh-TW/automation/clawflow.md new file mode 100644 index 000000000..a38cc9ccb --- /dev/null +++ b/docs/zh-TW/automation/clawflow.md @@ -0,0 +1,19 @@ +--- +summary: 重新導向至任務流程 +title: ClawFlow +x-i18n: + generated_at: "2026-04-30T02:44:25Z" + model: gpt-5.5 + provider: openai + source_hash: dec1ddc0e784b4ad49d0f5e5a8e332032e40281b81fe27de99363178ff8d3272 + source_path: automation/clawflow.md + workflow: 16 +--- + +ClawFlow 已重新命名為 [任務流程](/zh-TW/automation/taskflow)。 + +## 相關 + +- [任務流程](/zh-TW/automation/taskflow) +- [常設指令](/zh-TW/automation/standing-orders) +- [掛鉤](/zh-TW/automation/hooks) diff --git a/docs/zh-TW/automation/cron-jobs.md b/docs/zh-TW/automation/cron-jobs.md new file mode 100644 index 000000000..6c8f146f0 --- /dev/null +++ b/docs/zh-TW/automation/cron-jobs.md @@ -0,0 +1,489 @@ +--- +read_when: + - 排程背景作業或喚醒 + - 將外部觸發器(Webhook、Gmail)接入 OpenClaw + - 為排程任務決定使用 Heartbeat 還是 Cron +sidebarTitle: Scheduled tasks +summary: Gateway 排程器的排程作業、Webhook 和 Gmail PubSub 觸發器 +title: 排程任務 +x-i18n: + generated_at: "2026-04-30T02:44:43Z" + model: gpt-5.5 + provider: openai + source_hash: 021e623bdea786178e0948e9905360c897c26d31fdf866e9af8cfc9538968d60 + source_path: automation/cron-jobs.md + workflow: 16 +--- + +Cron 是 Gateway 的內建排程器。它會持久化作業、在正確時間喚醒代理,並可將輸出送回聊天頻道或 Webhook 端點。 + +## 快速開始 + + + + ```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 + ``` + + + ```bash + openclaw cron list + openclaw cron show + ``` + + + ```bash + openclaw cron runs --id + ``` + + + +## Cron 的運作方式 + +- Cron 在 **Gateway** 程序內執行(不是在模型內)。 +- 作業定義會持久化在 `~/.openclaw/cron/jobs.json`,因此重新啟動不會遺失排程。 +- 執行階段狀態會持久化在旁邊的 `~/.openclaw/cron/jobs-state.json`。如果你在 git 中追蹤 cron 定義,請追蹤 `jobs.json`,並將 `jobs-state.json` 加入 gitignore。 +- 分離後,較舊的 OpenClaw 版本可以讀取 `jobs.json`,但可能會將作業視為全新,因為執行階段欄位現在位於 `jobs-state.json`。 +- 當 Gateway 正在執行或已停止時編輯 `jobs.json`,OpenClaw 會比較已變更的排程欄位與待執行的執行階段時段中繼資料,並清除過期的 `nextRunAtMs` 值。單純格式化或只變更鍵順序的重寫,會保留待執行時段。 +- 所有 cron 執行都會建立[背景任務](/zh-TW/automation/tasks)記錄。 +- Gateway 啟動時,逾期的隔離代理回合作業會被重新排程到頻道連線視窗之外,而不是立即重播,因此 Discord/Telegram 啟動與原生命令設定在重新啟動後仍能保持回應。 +- 一次性作業(`--at`)預設會在成功後自動刪除。 +- 隔離 cron 執行完成時,會盡力關閉其 `cron:` 工作階段追蹤的瀏覽器分頁/程序,因此分離的瀏覽器自動化不會留下孤立程序。 +- 隔離 cron 執行也會防止過期的確認回覆。如果第一個結果只是暫時狀態更新(`on it`、`pulling everything together` 及類似提示),且沒有後代子代理執行仍負責最終答案,OpenClaw 會在交付前重新提示一次以取得實際結果。 +- 隔離 cron 執行會優先使用嵌入式執行中的結構化執行拒絕中繼資料,然後退回到已知的最終摘要/輸出標記,例如 `SYSTEM_RUN_DENIED` 和 `INVALID_REQUEST`,因此被封鎖的命令不會被回報為成功執行。 +- 隔離 cron 執行也會將執行層級的代理失敗視為作業錯誤,即使沒有產生回覆酬載也是如此,因此模型/供應商失敗會增加錯誤計數並觸發失敗通知,而不是將作業清除為成功。 +- 當隔離代理回合作業達到 `timeoutSeconds` 時,cron 會中止底層代理執行,並給它一小段清理視窗。如果執行未能排空,Gateway 擁有的清理會在 cron 記錄逾時前強制清除該執行的工作階段所有權,因此佇列中的聊天工作不會被留在過期的處理工作階段後面。 + + + + +cron 的任務協調先由執行階段擁有,其次才由持久歷史支援:只要 cron 執行階段仍將該作業追蹤為執行中,即使仍存在舊的子工作階段列,作用中的 cron 任務也會保持即時狀態。一旦執行階段停止擁有該作業且 5 分鐘寬限期到期,維護檢查就會查詢持久化執行記錄與作業狀態,以尋找相符的 `cron::` 執行。如果該持久歷史顯示終止結果,任務帳本會據此完成;否則 Gateway 擁有的維護可以將任務標記為 `lost`。離線 CLI 稽核可以從持久歷史復原,但不會將它自己的空白處理程序內作用中作業集合視為 Gateway 擁有的 cron 執行已消失的證明。 + + +## 排程類型 + +| 類型 | CLI 旗標 | 說明 | +| ------- | --------- | ------------------------------------------------------- | +| `at` | `--at` | 一次性時間戳記(ISO 8601 或像 `20m` 這樣的相對時間) | +| `every` | `--every` | 固定間隔 | +| `cron` | `--cron` | 5 欄位或 6 欄位 cron 運算式,可搭配選用的 `--tz` | + +沒有時區的時間戳記會被視為 UTC。若要依本地牆鐘時間排程,請加上 `--tz America/New_York`。 + +整點重複運算式會自動錯開最多 5 分鐘,以降低負載尖峰。使用 `--exact` 強制精準時間,或使用 `--stagger 30s` 指定明確視窗。 + +### 日期與星期使用 OR 邏輯 + +Cron 運算式由 [croner](https://github.com/Hexagon/croner) 解析。當日期與星期欄位都不是萬用字元時,croner 會在**任一**欄位符合時匹配,而不是兩者都符合。這是標準 Vixie cron 行為。 + +``` +# Intended: "9 AM on the 15th, only if it's a Monday" +# Actual: "9 AM on every 15th, AND 9 AM on every Monday" +0 9 15 * 1 +``` + +這會每月觸發約 5 到 6 次,而不是每月 0 到 1 次。OpenClaw 在此使用 Croner 的預設 OR 行為。若要要求兩個條件都成立,請使用 Croner 的 `+` 星期修飾符(`0 9 15 * +1`),或在其中一個欄位上排程,並在作業的提示或命令中保護另一個條件。 + +## 執行樣式 + +| 樣式 | `--session` 值 | 執行位置 | 最適合 | +| --------------- | ------------------- | ------------------------ | ------------------------------- | +| 主工作階段 | `main` | 下一個 Heartbeat 回合 | 提醒、系統事件 | +| 隔離 | `isolated` | 專用 `cron:` | 報告、背景雜務 | +| 目前工作階段 | `current` | 建立時繫結 | 具情境感知的重複工作 | +| 自訂工作階段 | `session:custom-id` | 持久化命名工作階段 | 以歷史為基礎的工作流程 | + + + + **主工作階段**作業會將系統事件加入佇列,並可選擇喚醒 Heartbeat(`--wake now` 或 `--wake next-heartbeat`)。這些系統事件不會延長目標工作階段的每日/閒置重設新鮮度。**隔離**作業會以全新工作階段執行專用代理回合。**自訂工作階段**(`session:xxx`)會跨執行持久化情境,啟用像每日站會這類以先前摘要為基礎的工作流程。 + + + 對隔離作業而言,「全新工作階段」表示每次執行都有新的逐字稿/工作階段 ID。OpenClaw 可以攜帶安全偏好,例如思考/快速/詳細設定、標籤,以及明確由使用者選擇的模型/驗證覆寫,但不會從較舊的 cron 列繼承環境對話情境:頻道/群組路由、傳送或佇列政策、提升權限、來源,或 ACP 執行階段繫結。當重複作業應刻意以同一個對話情境為基礎時,請使用 `current` 或 `session:`。 + + + 對隔離作業而言,執行階段拆除現在包含該 cron 工作階段的盡力瀏覽器清理。清理失敗會被忽略,因此實際 cron 結果仍會優先。 + + 隔離 cron 執行也會透過共用的執行階段清理路徑,處置為該作業建立的任何內建 MCP 執行階段執行個體。這符合主工作階段與自訂工作階段 MCP 用戶端的拆除方式,因此隔離 cron 作業不會在多次執行之間洩漏 stdio 子程序或長時間存在的 MCP 連線。 + + + + 當隔離 cron 執行協調子代理時,交付也會優先使用最終後代輸出,而不是過期的父層暫時文字。如果後代仍在執行,OpenClaw 會抑制該部分父層更新,而不是公告它。 + + 對於純文字 Discord 公告目標,OpenClaw 只會傳送一次標準最終助理文字,而不是同時重播串流/中間文字酬載與最終答案。媒體與結構化 Discord 酬載仍會作為個別酬載交付,因此附件和元件不會被丟棄。 + + + + +### 隔離作業的酬載選項 + + + 提示文字(隔離作業必填)。 + + + 模型覆寫;使用為該作業選取的允許模型。 + + + 思考層級覆寫。 + + + 跳過工作區啟動檔案注入。 + + + 限制作業可使用的工具,例如 `--tools exec,read`。 + + +`--model` 會使用選取的允許模型作為該作業的主要模型。這與聊天工作階段的 `/model` 覆寫不同:當作業主要模型失敗時,已設定的備援鏈仍會套用。如果要求的模型不被允許或無法解析,cron 會以明確的驗證錯誤使執行失敗,而不是靜默退回到作業的代理/預設模型選擇。 + +Cron 作業也可以攜帶酬載層級的 `fallbacks`。存在時,該清單會取代作業的已設定備援鏈。當你想要嚴格的 cron 執行、只嘗試所選模型時,請在作業酬載/API 中使用 `fallbacks: []`。如果作業有 `--model`,但沒有酬載或已設定的備援,OpenClaw 會傳遞明確的空白備援覆寫,因此代理主要模型不會被附加為隱藏的額外重試目標。 + +隔離作業的模型選擇優先順序如下: + +1. Gmail hook 模型覆寫(當執行來自 Gmail 且該覆寫被允許時) +2. 每個作業酬載的 `model` +3. 使用者選取且已儲存的 cron 工作階段模型覆寫 +4. 代理/預設模型選擇 + +快速模式也會遵循解析出的即時選擇。如果選取的模型設定有 `params.fastMode`,隔離 cron 預設會使用它。已儲存的工作階段 `fastMode` 覆寫仍會在任一方向上優先於設定。 + +如果隔離執行遇到即時模型切換交接,cron 會使用切換後的供應商/模型重試,並在重試前為作用中執行持久化該即時選擇。當切換也攜帶新的驗證設定檔時,cron 也會為作用中執行持久化該驗證設定檔覆寫。重試有界限:初始嘗試加上 2 次切換重試後,cron 會中止,而不是永遠迴圈。 + +在隔離 cron 執行進入代理執行器前,OpenClaw 會檢查已設定 `api: "ollama"` 和 `api: "openai-completions"` 供應商的可到達本地供應商端點,其 `baseUrl` 為回送、私有網路或 `.local`。如果該端點停機,執行會被記錄為 `skipped`,並附上清楚的供應商/模型錯誤,而不是開始模型呼叫。端點結果會快取 5 分鐘,因此使用同一個停機本地 Ollama、vLLM、SGLang 或 LM Studio 伺服器的許多到期作業,會共用一次小型探測,而不是造成請求風暴。跳過的供應商預檢執行不會增加執行錯誤退避;當你想要重複跳過通知時,請啟用 `failureAlert.includeSkipped`。 + +## 交付與輸出 + +| 模式 | 發生的事 | +| ---------- | ------------------------------------------------------------------- | +| `announce` | 如果代理未傳送,則以備援方式將最終文字交付給目標 | +| `webhook` | 將完成事件酬載 POST 到 URL | +| `none` | 沒有執行器備援交付 | + +使用 `--announce --channel telegram --to "-1001234567890"` 進行頻道傳遞。對於 Telegram 論壇主題,使用 `-1001234567890:topic:123`;直接 RPC/設定呼叫端也可以將 `delivery.threadId` 以字串或數字傳入。Slack/Discord/Mattermost 目標應使用明確前綴(`channel:`、`user:`)。Matrix 房間 ID 區分大小寫;請使用確切房間 ID 或 Matrix 提供的 `room:!room:server` 形式。 + +對於隔離作業,聊天傳遞是共享的。如果有聊天路由可用,即使作業使用 `--no-deliver`,代理也可以使用 `message` 工具。如果代理傳送到已設定/目前的目標,OpenClaw 會略過備援公告。否則,`announce`、`webhook` 與 `none` 只控制執行器在代理回合後如何處理最終回覆。 + +當代理從作用中的聊天建立隔離提醒時,OpenClaw 會儲存保留的即時傳遞目標,用於備援公告路由。內部工作階段鍵可能是小寫;當目前聊天情境可用時,提供者傳遞目標不會從這些鍵重建。 + +失敗通知會走獨立的目的地路徑: + +- `cron.failureDestination` 設定失敗通知的全域預設值。 +- `job.delivery.failureDestination` 會針對每個作業覆寫該值。 +- 如果兩者都未設定,且作業已經透過 `announce` 傳遞,失敗通知現在會退回到該主要公告目標。 +- 除非主要傳遞模式是 `webhook`,否則 `delivery.failureDestination` 只支援 `sessionTarget="isolated"` 作業。 +- `failureAlert.includeSkipped: true` 會讓作業或全域 cron 警示政策納入重複的略過執行警示。略過的執行會保留獨立的連續略過計數器,因此不會影響執行錯誤退避。 + +## CLI 範例 + + + + ```bash + openclaw cron add \ + --name "Calendar check" \ + --at "20m" \ + --session main \ + --system-event "Next heartbeat: check calendar." \ + --wake now + ``` + + + ```bash + openclaw cron add \ + --name "Morning brief" \ + --cron "0 7 * * *" \ + --tz "America/Los_Angeles" \ + --session isolated \ + --message "Summarize overnight updates." \ + --announce \ + --channel slack \ + --to "channel:C1234567890" + ``` + + + ```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 \ + --announce + ``` + + + +## Webhook + +Gateway 可以公開 HTTP Webhook 端點供外部觸發。在設定中啟用: + +```json5 +{ + hooks: { + enabled: true, + token: "shared-secret", + path: "/hooks", + }, +} +``` + +### 驗證 + +每個請求都必須透過標頭包含 hook 權杖: + +- `Authorization: Bearer `(建議) +- `x-openclaw-token: ` + +查詢字串權杖會被拒絕。 + + + + 為主要工作階段排入系統事件: + + ```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"}' + ``` + + + 事件描述。 + + + `now` 或 `next-heartbeat`。 + + + + + 執行隔離代理回合: + + ```bash + curl -X POST http://127.0.0.1:18789/hooks/agent \ + -H 'Authorization: Bearer SECRET' \ + -H 'Content-Type: application/json' \ + -d '{"message":"Summarize inbox","name":"Email","model":"openai/gpt-5.4"}' + ``` + + 欄位:`message`(必填)、`name`、`agentId`、`wakeMode`、`deliver`、`channel`、`to`、`model`、`fallbacks`、`thinking`、`timeoutSeconds`。 + + + + 自訂 hook 名稱會透過設定中的 `hooks.mappings` 解析。對應可以使用範本或程式碼轉換,將任意酬載轉換成 `wake` 或 `agent` 動作。 + + + + +將 hook 端點限制在 loopback、tailnet 或受信任的反向代理後方。 + +- 使用專用 hook 權杖;不要重複使用 Gateway 驗證權杖。 +- 將 `hooks.path` 保持在專用子路徑;`/` 會被拒絕。 +- 設定 `hooks.allowedAgentIds` 以限制明確的 `agentId` 路由。 +- 除非你需要呼叫端選擇工作階段,否則請保持 `hooks.allowRequestSessionKey=false`。 +- 如果啟用 `hooks.allowRequestSessionKey`,也請設定 `hooks.allowedSessionKeyPrefixes` 以限制允許的工作階段鍵形狀。 +- Hook 酬載預設會以安全邊界包裝。 + + + +## Gmail PubSub 整合 + +透過 Google PubSub 將 Gmail 收件匣觸發器接到 OpenClaw。 + + +**先決條件:** `gcloud` CLI、`gog`(gogcli)、已啟用的 OpenClaw hook、用於公開 HTTPS 端點的 Tailscale。 + + +### 精靈設定(建議) + +```bash +openclaw webhooks gmail setup --account openclaw@gmail.com +``` + +這會寫入 `hooks.gmail` 設定、啟用 Gmail 預設集,並使用 Tailscale Funnel 作為推送端點。 + +### Gateway 自動啟動 + +當 `hooks.enabled=true` 且已設定 `hooks.gmail.account` 時,Gateway 會在啟動時啟動 `gog gmail watch serve`,並自動續訂 watch。設定 `OPENCLAW_SKIP_GMAIL_WATCHER=1` 可選擇退出。 + +### 手動一次性設定 + + + + 選取擁有 `gog` 所使用 OAuth 用戶端的 GCP 專案: + + ```bash + gcloud auth login + gcloud config set project + gcloud services enable gmail.googleapis.com pubsub.googleapis.com + ``` + + + + ```bash + gcloud pubsub topics create gog-gmail-watch + gcloud pubsub topics add-iam-policy-binding gog-gmail-watch \ + --member=serviceAccount:gmail-api-push@system.gserviceaccount.com \ + --role=roles/pubsub.publisher + ``` + + + ```bash + gog gmail watch start \ + --account openclaw@gmail.com \ + --label INBOX \ + --topic projects//topics/gog-gmail-watch + ``` + + + +### Gmail 模型覆寫 + +```json5 +{ + hooks: { + gmail: { + model: "openrouter/meta-llama/llama-3.3-70b-instruct:free", + thinking: "off", + }, + }, +} +``` + +## 管理作業 + +```bash +# List all jobs +openclaw cron list + +# Show one job, including resolved delivery route +openclaw cron show + +# Edit a job +openclaw cron edit --message "Updated prompt" --model "opus" + +# Force run a job now +openclaw cron run + +# Run only if due +openclaw cron run --due + +# View run history +openclaw cron runs --id --limit 50 + +# Delete a job +openclaw cron remove + +# Agent selection (multi-agent setups) +openclaw cron add --name "Ops sweep" --cron "0 6 * * *" --session isolated --message "Check ops queue" --agent ops +openclaw cron edit --clear-agent +``` + + +模型覆寫注意事項: + +- `openclaw cron add|edit --model ...` 會變更作業選取的模型。 +- 如果允許該模型,該確切的提供者/模型會送達隔離代理執行。 +- 如果不允許或無法解析,cron 會以明確的驗證錯誤讓該次執行失敗。 +- 已設定的備援鏈仍會套用,因為 cron `--model` 是作業主要模型,而不是工作階段 `/model` 覆寫。 +- 酬載 `fallbacks` 會取代該作業已設定的備援;`fallbacks: []` 會停用備援,並讓執行變成嚴格模式。 +- 沒有明確或已設定備援清單的純 `--model`,不會靜默接續到代理主要模型作為額外重試目標。 + + + +## 設定 + +```json5 +{ + cron: { + enabled: true, + store: "~/.openclaw/cron/jobs.json", + maxConcurrentRuns: 1, + retry: { + maxAttempts: 3, + backoffMs: [60000, 120000, 300000], + retryOn: ["rate_limit", "overloaded", "network", "server_error"], + }, + webhookToken: "replace-with-dedicated-webhook-token", + sessionRetention: "24h", + runLog: { maxBytes: "2mb", keepLines: 2000 }, + }, +} +``` + +`maxConcurrentRuns` 會限制排程 cron 分派與隔離代理回合執行。隔離 cron 代理回合會在內部使用佇列的專用 `cron-nested` 執行通道,因此提高此值可讓獨立的 cron LLM 執行並行推進,而不只是啟動其外層 cron 包裝器。共享的非 cron `nested` 通道不會因為此設定而加寬。 + +執行階段狀態 sidecar 會從 `cron.store` 推導:像 `~/clawd/cron/jobs.json` 這樣的 `.json` 儲存會使用 `~/clawd/cron/jobs-state.json`,而沒有 `.json` 後綴的儲存路徑會附加 `-state.json`。 + +如果你手動編輯 `jobs.json`,請不要將 `jobs-state.json` 納入原始碼控制。OpenClaw 會使用該 sidecar 保存待處理槽位、作用中標記、上次執行中繼資料,以及告知排程器外部編輯過的作業何時需要新的 `nextRunAtMs` 的排程身分。 + +停用 cron:`cron.enabled: false` 或 `OPENCLAW_SKIP_CRON=1`。 + + + + **一次性重試**:暫時性錯誤(速率限制、過載、網路、伺服器錯誤)最多重試 3 次,並使用指數退避。永久錯誤會立即停用。 + + **重複重試**:重試之間使用指數退避(30 秒到 60 分鐘)。下一次成功執行後會重設退避。 + + + + `cron.sessionRetention`(預設 `24h`)會修剪隔離執行工作階段項目。`cron.runLog.maxBytes` / `cron.runLog.keepLines` 會自動修剪執行記錄檔。 + + + +## 疑難排解 + +### 命令階梯 + +```bash +openclaw status +openclaw gateway status +openclaw cron status +openclaw cron list +openclaw cron runs --id --limit 20 +openclaw system heartbeat last +openclaw logs --follow +openclaw doctor +``` + + + + - 檢查 `cron.enabled` 與 `OPENCLAW_SKIP_CRON` 環境變數。 + - 確認 Gateway 正在持續執行。 + - 對於 `cron` 排程,驗證時區(`--tz`)與主機時區。 + - 執行輸出中的 `reason: not-due` 表示手動執行是以 `openclaw cron run --due` 檢查,且作業尚未到期。 + + + + - 傳遞模式 `none` 表示不預期有執行器備援傳送。當聊天路由可用時,代理仍可使用 `message` 工具直接傳送。 + - 傳遞目標缺失/無效(`channel`/`to`)表示已略過外送。 + - 對於 Matrix,複製或舊版作業若有小寫的 `delivery.to` 房間 ID,可能會失敗,因為 Matrix 房間 ID 區分大小寫。請將作業編輯為 Matrix 提供的確切 `!room:server` 或 `room:!room:server` 值。 + - 頻道驗證錯誤(`unauthorized`、`Forbidden`)表示傳遞已被憑證封鎖。 + - 如果隔離執行只回傳靜默權杖(`NO_REPLY` / `no_reply`),OpenClaw 會抑制直接外送傳遞,也會抑制備援佇列摘要路徑,因此不會有任何內容傳回聊天。 + - 如果代理應自行傳訊給使用者,請檢查作業是否有可用路由(`channel: "last"` 搭配先前聊天,或明確的頻道/目標)。 + + + + - 每日與閒置重設的新鮮度不是依據 `updatedAt`;請參閱[工作階段管理](/zh-TW/concepts/session#session-lifecycle)。 + - Cron 喚醒、Heartbeat 執行、exec 通知,以及 Gateway 簿記可能會為了路由/狀態而更新工作階段資料列,但它們不會延長 `sessionStartedAt` 或 `lastInteractionAt`。 + - 對於在這些欄位存在之前建立的舊版資料列,若檔案仍可用,OpenClaw 可以從逐行 JSONL 轉錄稿的工作階段標頭復原 `sessionStartedAt`。沒有 `lastInteractionAt` 的舊版閒置資料列會使用該復原的開始時間作為其閒置基準。 + + + + - 未使用 `--tz` 的 Cron 會使用 Gateway 主機時區。 + - 未指定時區的 `at` 排程會被視為 UTC。 + - Heartbeat `activeHours` 會使用已設定的時區解析。 + + + + +## 相關 + +- [自動化與任務](/zh-TW/automation) — 所有自動化機制一覽 +- [背景任務](/zh-TW/automation/tasks) — Cron 執行的任務台帳 +- [Heartbeat](/zh-TW/gateway/heartbeat) — 定期的主工作階段回合 +- [時區](/zh-TW/concepts/timezone) — 時區設定 diff --git a/docs/zh-TW/automation/cron-vs-heartbeat.md b/docs/zh-TW/automation/cron-vs-heartbeat.md new file mode 100644 index 000000000..28b01a345 --- /dev/null +++ b/docs/zh-TW/automation/cron-vs-heartbeat.md @@ -0,0 +1,18 @@ +--- +summary: 重新導向至 /automation +title: Cron 與 Heartbeat +x-i18n: + generated_at: "2026-04-30T02:44:28Z" + model: gpt-5.5 + provider: openai + source_hash: 4a4951f926f9050a9bd33b338cf4cd1869d73b9c3e7222349ea8265b959f41b4 + source_path: automation/cron-vs-heartbeat.md + workflow: 16 +--- + +Cron 與 Heartbeat 的決策指南位於 [自動化與任務](/zh-TW/automation) 下。 + +## 相關內容 + +- [排程任務](/zh-TW/automation/cron-jobs) +- [背景任務](/zh-TW/automation/tasks) diff --git a/docs/zh-TW/automation/gmail-pubsub.md b/docs/zh-TW/automation/gmail-pubsub.md new file mode 100644 index 000000000..65ac39d40 --- /dev/null +++ b/docs/zh-TW/automation/gmail-pubsub.md @@ -0,0 +1,18 @@ +--- +summary: 重新導向至 /automation/cron-jobs +title: Gmail 發布/訂閱 +x-i18n: + generated_at: "2026-04-30T02:44:41Z" + model: gpt-5.5 + provider: openai + source_hash: 4462fb58fa73ac3eb3d8d2994760b96424dcad3f1543e8ff10222936f6c54caf + source_path: automation/gmail-pubsub.md + workflow: 16 +--- + +此頁面已移至 [排程任務](/zh-TW/automation/cron-jobs#gmail-pubsub-integration)。請參閱 [排程任務](/zh-TW/automation/cron-jobs#gmail-pubsub-integration) 以取得 Gmail PubSub 文件。 + +## 相關 + +- [Webhook](/zh-TW/automation/cron-jobs) +- [自動化疑難排解](/zh-TW/automation/cron-jobs) diff --git a/docs/zh-TW/automation/hooks.md b/docs/zh-TW/automation/hooks.md new file mode 100644 index 000000000..5296516ba --- /dev/null +++ b/docs/zh-TW/automation/hooks.md @@ -0,0 +1,332 @@ +--- +read_when: + - 你需要針對 /new、/reset、/stop 和代理程式生命週期事件的事件驅動自動化 + - 你想要建置、安裝或偵錯鉤子 +summary: 掛鉤:用於命令與生命週期事件的事件驅動自動化 +title: 鉤子 +x-i18n: + generated_at: "2026-04-30T02:44:59Z" + model: gpt-5.5 + provider: openai + source_hash: a6c567ab79fbff8228d174816e9fb4613f0544ea15a99b5917190a4066af0f57 + source_path: automation/hooks.md + workflow: 16 +--- + +掛鉤是在 Gateway 內部發生事件時執行的小型腳本。它們可以從目錄中探索,並可使用 `openclaw hooks` 檢視。只有在你啟用掛鉤,或設定至少一個掛鉤項目、掛鉤套件、舊版處理常式或額外掛鉤目錄後,Gateway 才會載入內部掛鉤。 + +OpenClaw 中有兩種掛鉤: + +- **內部掛鉤**(本頁):在代理事件觸發時於 Gateway 內執行,例如 `/new`、`/reset`、`/stop` 或生命週期事件。 +- **Webhooks**:外部 HTTP 端點,可讓其他系統觸發 OpenClaw 中的工作。請參閱 [Webhooks](/zh-TW/automation/cron-jobs#webhooks)。 + +掛鉤也可以封裝在 plugins 內。`openclaw hooks list` 會顯示獨立掛鉤與 plugin 管理的掛鉤。 + +## 快速開始 + +```bash +# List available hooks +openclaw hooks list + +# Enable a hook +openclaw hooks enable session-memory + +# Check hook status +openclaw hooks check + +# Get detailed information +openclaw hooks info session-memory +``` + +## 事件類型 + +| 事件 | 觸發時機 | +| ------------------------ | ---------------------------------------------------------- | +| `command:new` | 發出 `/new` 命令 | +| `command:reset` | 發出 `/reset` 命令 | +| `command:stop` | 發出 `/stop` 命令 | +| `command` | 任何命令事件(一般監聽器) | +| `session:compact:before` | Compaction 摘要歷程記錄之前 | +| `session:compact:after` | Compaction 完成之後 | +| `session:patch` | 工作階段屬性被修改時 | +| `agent:bootstrap` | 注入工作區啟動程序檔案之前 | +| `gateway:startup` | 頻道啟動且掛鉤載入之後 | +| `gateway:shutdown` | Gateway 關閉開始時 | +| `gateway:pre-restart` | 預期的 Gateway 重新啟動之前 | +| `message:received` | 來自任何頻道的傳入訊息 | +| `message:transcribed` | 音訊轉錄完成之後 | +| `message:preprocessed` | 媒體與連結前處理完成或略過之後 | +| `message:sent` | 傳出訊息已送達 | + +## 撰寫掛鉤 + +### 掛鉤結構 + +每個掛鉤都是一個包含兩個檔案的目錄: + +``` +my-hook/ +├── HOOK.md # Metadata + documentation +└── handler.ts # Handler implementation +``` + +### HOOK.md 格式 + +```markdown +--- +name: my-hook +description: "Short description of what this hook does" +metadata: + { "openclaw": { "emoji": "🔗", "events": ["command:new"], "requires": { "bins": ["node"] } } } +--- + +# My Hook + +Detailed documentation goes here. +``` + +**中繼資料欄位**(`metadata.openclaw`): + +| 欄位 | 說明 | +| ---------- | ---------------------------------------------------- | +| `emoji` | CLI 顯示用表情符號 | +| `events` | 要監聽的事件陣列 | +| `export` | 要使用的具名匯出(預設為 `"default"`) | +| `os` | 必要平台(例如 `["darwin", "linux"]`) | +| `requires` | 必要的 `bins`、`anyBins`、`env` 或 `config` 路徑 | +| `always` | 略過資格檢查(布林值) | +| `install` | 安裝方法 | + +### 處理常式實作 + +```typescript +const handler = async (event) => { + if (event.type !== "command" || event.action !== "new") { + return; + } + + console.log(`[my-hook] New command triggered`); + // Your logic here + + // Optionally send message to user + event.messages.push("Hook executed!"); +}; + +export default handler; +``` + +每個事件都包含:`type`、`action`、`sessionKey`、`timestamp`、`messages`(推入即可傳送給使用者)以及 `context`(事件專屬資料)。代理與工具 plugin 掛鉤內容也可以包含 `trace`,這是一個唯讀、相容 W3C 的診斷追蹤內容,plugins 可將其傳入結構化記錄,以便進行 OTEL 關聯。 + +### 事件內容重點 + +**命令事件**(`command:new`、`command:reset`):`context.sessionEntry`、`context.previousSessionEntry`、`context.commandSource`、`context.workspaceDir`、`context.cfg`。 + +**訊息事件**(`message:received`):`context.from`、`context.content`、`context.channelId`、`context.metadata`(供應商專屬資料,包含 `senderId`、`senderName`、`guildId`)。 + +**訊息事件**(`message:sent`):`context.to`、`context.content`、`context.success`、`context.channelId`。 + +**訊息事件**(`message:transcribed`):`context.transcript`、`context.from`、`context.channelId`、`context.mediaPath`。 + +**訊息事件**(`message:preprocessed`):`context.bodyForAgent`(最終強化後的本文)、`context.from`、`context.channelId`。 + +**啟動程序事件**(`agent:bootstrap`):`context.bootstrapFiles`(可變陣列)、`context.agentId`。 + +**工作階段修補事件**(`session:patch`):`context.sessionEntry`、`context.patch`(僅變更的欄位)、`context.cfg`。只有具權限的用戶端可以觸發修補事件。 + +**Compaction 事件**:`session:compact:before` 包含 `messageCount`、`tokenCount`。`session:compact:after` 會新增 `compactedCount`、`summaryLength`、`tokensBefore`、`tokensAfter`。 + +`command:stop` 會觀察使用者發出 `/stop`;它是取消/命令生命週期,不是代理完成閘門。需要檢查自然最終答案並要求代理再執行一次的 plugins,應改用型別化 plugin 掛鉤 `before_agent_finalize`。請參閱 [Plugin 掛鉤](/zh-TW/plugins/hooks)。 + +**Gateway 生命週期事件**:`gateway:shutdown` 包含 `reason` 與 `restartExpectedMs`,並在 Gateway 關閉開始時觸發。`gateway:pre-restart` 包含相同內容,但只會在關閉屬於預期重新啟動的一部分,且提供有限的 `restartExpectedMs` 值時觸發。關閉期間,每個生命週期掛鉤的等待都是盡力而為且有界限,因此即使處理常式停滯,關閉仍會繼續。 + +## 掛鉤探索 + +掛鉤會從這些目錄探索,順序為覆寫優先順序由低到高: + +1. **內建掛鉤**:隨 OpenClaw 發佈 +2. **Plugin 掛鉤**:封裝在已安裝 plugins 內的掛鉤 +3. **受管理掛鉤**:`~/.openclaw/hooks/`(使用者安裝,跨工作區共用)。來自 `hooks.internal.load.extraDirs` 的額外目錄共用此優先順序。 +4. **工作區掛鉤**:`/hooks/`(每個代理專屬,預設停用,直到明確啟用) + +工作區掛鉤可以新增掛鉤名稱,但無法覆寫同名的內建、受管理或 plugin 提供的掛鉤。 + +Gateway 會在內部掛鉤完成設定之前,於啟動時略過內部掛鉤探索。使用 `openclaw hooks enable ` 啟用內建或受管理掛鉤、安裝掛鉤套件,或設定 `hooks.internal.enabled=true` 以選擇啟用。當你啟用一個具名掛鉤時,Gateway 只會載入該掛鉤的處理常式;`hooks.internal.enabled=true`、額外掛鉤目錄與舊版處理常式會選擇進行廣泛探索。 + +### 掛鉤套件 + +掛鉤套件是透過 `package.json` 中的 `openclaw.hooks` 匯出掛鉤的 npm 套件。使用以下命令安裝: + +```bash +openclaw plugins install +``` + +Npm 規格僅限登錄檔(套件名稱 + 選用的精確版本或 dist-tag)。Git/URL/file 規格與 semver 範圍會被拒絕。 + +## 內建掛鉤 + +| 掛鉤 | 事件 | 功能 | +| --------------------- | ------------------------------ | ----------------------------------------------------- | +| session-memory | `command:new`, `command:reset` | 將工作階段內容儲存到 `/memory/` | +| bootstrap-extra-files | `agent:bootstrap` | 從 glob 模式注入額外啟動程序檔案 | +| command-logger | `command` | 將所有命令記錄到 `~/.openclaw/logs/commands.log` | +| boot-md | `gateway:startup` | Gateway 啟動時執行 `BOOT.md` | + +啟用任何內建掛鉤: + +```bash +openclaw hooks enable +``` + + + +### session-memory 詳細資訊 + +擷取最後 15 則使用者/助理訊息,透過 LLM 產生描述性檔名 slug,並使用主機本機日期儲存到 `/memory/YYYY-MM-DD-slug.md`。需要設定 `workspace.dir`。 + + + +### bootstrap-extra-files 設定 + +```json +{ + "hooks": { + "internal": { + "entries": { + "bootstrap-extra-files": { + "enabled": true, + "paths": ["packages/*/AGENTS.md", "packages/*/TOOLS.md"] + } + } + } + } +} +``` + +路徑會相對於工作區解析。只會載入可辨識的啟動程序基礎檔名(`AGENTS.md`、`SOUL.md`、`TOOLS.md`、`IDENTITY.md`、`USER.md`、`HEARTBEAT.md`、`BOOTSTRAP.md`、`MEMORY.md`)。 + + + +### command-logger 詳細資訊 + +將每個斜線命令記錄到 `~/.openclaw/logs/commands.log`。 + + + +### boot-md 詳細資訊 + +Gateway 啟動時,從作用中工作區執行 `BOOT.md`。 + +## Plugin 掛鉤 + +Plugins 可以透過 Plugin SDK 註冊型別化掛鉤以進行更深入整合:攔截工具呼叫、修改提示、控制訊息流程,以及更多功能。當你需要 `before_tool_call`、`before_agent_reply`、`before_install` 或其他程序內生命週期掛鉤時,請使用 plugin 掛鉤。 + +如需完整的 plugin 掛鉤參考,請參閱 [Plugin 掛鉤](/zh-TW/plugins/hooks)。 + +## 設定 + +```json +{ + "hooks": { + "internal": { + "enabled": true, + "entries": { + "session-memory": { "enabled": true }, + "command-logger": { "enabled": false } + } + } + } +} +``` + +每個掛鉤的環境變數: + +```json +{ + "hooks": { + "internal": { + "entries": { + "my-hook": { + "enabled": true, + "env": { "MY_CUSTOM_VAR": "value" } + } + } + } + } +} +``` + +額外掛鉤目錄: + +```json +{ + "hooks": { + "internal": { + "load": { + "extraDirs": ["/path/to/more/hooks"] + } + } + } +} +``` + + +舊版 `hooks.internal.handlers` 陣列設定格式仍支援向後相容性,但新掛鉤應使用以探索為基礎的系統。 + + +## CLI 參考 + +```bash +# List all hooks (add --eligible, --verbose, or --json) +openclaw hooks list + +# Show detailed info about a hook +openclaw hooks info + +# Show eligibility summary +openclaw hooks check + +# Enable/disable +openclaw hooks enable +openclaw hooks disable +``` + +## 最佳實務 + +- **保持處理常式快速。** 掛鉤會在命令處理期間執行。對耗時工作使用 `void processInBackground(event)` 進行啟動後即不等待。 +- **優雅處理錯誤。** 將有風險的操作包在 try/catch 中;不要拋出錯誤,讓其他處理常式可以執行。 +- **及早篩選事件。** 如果事件類型/動作不相關,立即傳回。 +- **使用特定事件鍵。** 偏好 `"events": ["command:new"]`,而非 `"events": ["command"]`,以降低額外負擔。 + +## 疑難排解 + +### 未探索到掛鉤 + +```bash +# Verify directory structure +ls -la ~/.openclaw/hooks/my-hook/ +# Should show: HOOK.md, handler.ts + +# List all discovered hooks +openclaw hooks list +``` + +### 掛鉤不符合資格 + +```bash +openclaw hooks info my-hook +``` + +檢查是否缺少二進位檔(PATH)、環境變數、設定值或作業系統相容性。 + +### 掛鉤未執行 + +1. 確認掛鉤已啟用:`openclaw hooks list` +2. 重新啟動你的 gateway 程序,讓掛鉤重新載入。 +3. 檢查 Gateway 記錄:`./scripts/clawlog.sh | grep hook` + +## 相關 + +- [CLI 參考:鉤子](/zh-TW/cli/hooks) +- [Webhook](/zh-TW/automation/cron-jobs#webhooks) +- [Plugin 鉤子](/zh-TW/plugins/hooks) — 行程內 Plugin 生命週期鉤子 +- [設定](/zh-TW/gateway/configuration-reference#hooks) diff --git a/docs/zh-TW/automation/index.md b/docs/zh-TW/automation/index.md new file mode 100644 index 000000000..9ddf526f4 --- /dev/null +++ b/docs/zh-TW/automation/index.md @@ -0,0 +1,132 @@ +--- +read_when: + - 決定如何使用 OpenClaw 自動化工作 + - 在 Heartbeat、Cron、承諾事項、掛鉤與常設指令之間做選擇 + - 尋找合適的自動化入口點 +summary: 自動化機制概覽:任務、Cron、掛鉤、常設指令,以及 TaskFlow +title: 自動化與任務 +x-i18n: + generated_at: "2026-04-30T02:45:11Z" + model: gpt-5.5 + provider: openai + source_hash: a2465c39f21db8bcb98f980a2c4b2c03018dddd5f43de59d8bf6ce0d6e97d9ef + source_path: automation/index.md + workflow: 16 +--- + +OpenClaw 會透過任務、排程工作、推斷承諾、事件 Hook 與常設指令在背景執行工作。本頁協助你選擇合適的機制,並了解它們如何彼此配合。 + +## 快速決策指南 + +```mermaid +flowchart TD + START([你需要什麼?]) --> Q1{排程工作?} + START --> Q2{追蹤分離的工作?} + START --> Q3{編排多步驟流程?} + START --> Q4{回應生命週期事件?} + START --> Q5{給代理持續性指令?} + START --> Q6{記住自然的後續事項?} + + Q1 -->|是| Q1a{精確時間或彈性時間?} + Q1a -->|精確| CRON["排程任務 (Cron)"] + Q1a -->|彈性| HEARTBEAT[Heartbeat] + + Q2 -->|是| TASKS[背景任務] + Q3 -->|是| FLOW[Task Flow] + Q4 -->|是| HOOKS[Hooks] + Q5 -->|是| SO[常設命令] + Q6 -->|是| COMMITMENTS[推斷承諾] +``` + +| 使用案例 | 建議 | 原因 | +| --------------------------------------- | ---------------------- | ------------------------------------------------ | +| 每天上午 9 點準時傳送報告 | 排程任務 (Cron) | 精確時間、隔離執行 | +| 20 分鐘後提醒我 | 排程任務 (Cron) | 具有精準時間的一次性任務 (`--at`) | +| 執行每週深度分析 | 排程任務 (Cron) | 獨立任務,可使用不同模型 | +| 每 30 分鐘檢查收件匣 | Heartbeat | 與其他檢查批次處理,具備情境感知 | +| 監控日曆中的即將到來事件 | Heartbeat | 很自然適合週期性覺察 | +| 在提到的面試後追蹤確認 | 推斷承諾 | 類似記憶的後續追蹤,沒有精確提醒請求 | +| 根據使用者情境進行溫和關懷確認 | 推斷承諾 | 限定於同一代理與頻道 | +| 檢查子代理或 ACP 執行狀態 | 背景任務 | 任務帳本會追蹤所有分離的工作 | +| 稽核執行了什麼以及何時執行 | 背景任務 | `openclaw tasks list` 與 `openclaw tasks audit` | +| 多步驟研究後彙整摘要 | Task Flow | 具備修訂追蹤的持久編排 | +| 在工作階段重設時執行腳本 | Hooks | 事件驅動,會在生命週期事件觸發 | +| 在每次工具呼叫時執行程式碼 | Plugin hooks | 程序內 Hook 可攔截工具呼叫 | +| 回覆前一律檢查合規性 | 常設命令 | 自動注入每個工作階段 | + +### 排程任務 (Cron) 與 Heartbeat + +| 面向 | 排程任務 (Cron) | Heartbeat | +| --------------- | ----------------------------------- | ------------------------------------- | +| 時間 | 精確(cron 表達式、一次性) | 近似(預設每 30 分鐘) | +| 工作階段情境 | 全新(隔離)或共享 | 完整主工作階段情境 | +| 任務紀錄 | 一律建立 | 從不建立 | +| 交付 | 頻道、Webhook 或靜默 | 在主工作階段內內嵌 | +| 最適合 | 報告、提醒、背景工作 | 收件匣檢查、日曆、通知 | + +需要精確時間或隔離執行時,請使用排程任務 (Cron)。當工作受益於完整工作階段情境,而且近似時間即可時,請使用 Heartbeat。 + +## 核心概念 + +### 排程任務 (cron) + +Cron 是 Gateway 內建的精確時間排程器。它會持久保存工作、在正確時間喚醒代理,並可將輸出交付到聊天頻道或 Webhook 端點。支援一次性提醒、週期性表達式與傳入 Webhook 觸發器。 + +請參閱[排程任務](/zh-TW/automation/cron-jobs)。 + +### 任務 + +背景任務帳本會追蹤所有分離的工作:ACP 執行、子代理產生、隔離的 cron 執行與 CLI 操作。任務是紀錄,不是排程器。使用 `openclaw tasks list` 與 `openclaw tasks audit` 來檢查它們。 + +請參閱[背景任務](/zh-TW/automation/tasks)。 + +### 推斷承諾 + +承諾是選擇加入、短期存在的後續追蹤記憶。OpenClaw 會從一般對話中推斷它們,將其限定於同一代理與頻道,並透過 Heartbeat 交付到期的確認。使用者明確請求的精確提醒仍屬於 cron。 + +請參閱[推斷承諾](/zh-TW/concepts/commitments)。 + +### Task Flow + +Task Flow 是位於背景任務之上的流程編排基底。它會管理持久的多步驟流程,支援受管理與鏡像同步模式、修訂追蹤,以及用於檢查的 `openclaw tasks flow list|show|cancel`。 + +請參閱 [Task Flow](/zh-TW/automation/taskflow)。 + +### 常設命令 + +常設命令會授予代理針對已定義程式的永久操作權限。它們存放於工作區檔案中(通常是 `AGENTS.md`),並會注入每個工作階段。可搭配 cron 執行時間型強制要求。 + +請參閱[常設命令](/zh-TW/automation/standing-orders)。 + +### Hooks + +內部 Hook 是由代理生命週期事件(`/new`、`/reset`、`/stop`)、工作階段 Compaction、Gateway 啟動與訊息流程觸發的事件驅動腳本。它們會從目錄中自動探索,並可使用 `openclaw hooks` 管理。若要進行程序內工具呼叫攔截,請使用 [Plugin hooks](/zh-TW/plugins/hooks)。 + +請參閱 [Hooks](/zh-TW/automation/hooks)。 + +### Heartbeat + +Heartbeat 是週期性的主工作階段回合(預設每 30 分鐘)。它會在一個具備完整工作階段情境的代理回合中批次處理多項檢查(收件匣、日曆、通知)。Heartbeat 回合不會建立任務紀錄,也不會延長每日/閒置工作階段重設的新鮮度。可使用 `HEARTBEAT.md` 放置簡短檢查清單,或在你希望於 Heartbeat 本身內執行僅限到期的週期性檢查時使用 `tasks:` 區塊。空的 Heartbeat 檔案會以 `empty-heartbeat-file` 略過;僅限到期任務模式會以 `no-tasks-due` 略過。Heartbeat 會在 cron 工作處於作用中或已排入佇列時延後,而 `heartbeat.skipWhenBusy` 也可在子代理或巢狀通道忙碌時延後它們。 + +請參閱 [Heartbeat](/zh-TW/gateway/heartbeat)。 + +## 它們如何一起運作 + +- **Cron** 處理精確排程(每日報告、每週回顧)與一次性提醒。所有 cron 執行都會建立任務紀錄。 +- **Heartbeat** 每 30 分鐘在一個批次回合中處理例行監控(收件匣、日曆、通知)。 +- **Hooks** 使用自訂腳本回應特定事件(工作階段重設、Compaction、訊息流程)。Plugin hooks 涵蓋工具呼叫。 +- **常設命令** 為代理提供持續性情境與權限邊界。 +- **Task Flow** 在個別任務之上協調多步驟流程。 +- **任務** 會自動追蹤所有分離的工作,讓你能檢查與稽核。 + +## 相關 + +- [排程任務](/zh-TW/automation/cron-jobs) — 精確排程與一次性提醒 +- [推斷承諾](/zh-TW/concepts/commitments) — 類似記憶的後續追蹤確認 +- [背景任務](/zh-TW/automation/tasks) — 所有分離工作的任務帳本 +- [Task Flow](/zh-TW/automation/taskflow) — 持久的多步驟流程編排 +- [Hooks](/zh-TW/automation/hooks) — 事件驅動的生命週期腳本 +- [Plugin hooks](/zh-TW/plugins/hooks) — 程序內工具、提示、訊息與生命週期 Hook +- [常設命令](/zh-TW/automation/standing-orders) — 持續性代理指令 +- [Heartbeat](/zh-TW/gateway/heartbeat) — 週期性主工作階段回合 +- [設定參考](/zh-TW/gateway/configuration-reference) — 所有設定鍵 diff --git a/docs/zh-TW/automation/poll.md b/docs/zh-TW/automation/poll.md new file mode 100644 index 000000000..66d43d587 --- /dev/null +++ b/docs/zh-TW/automation/poll.md @@ -0,0 +1,19 @@ +--- +summary: 重新導向至 /cli/message +title: 投票 +x-i18n: + generated_at: "2026-04-30T02:44:53Z" + model: gpt-5.5 + provider: openai + source_hash: a277212ed680b7aeb9153d003bc084d2d0c918dc53f2f469c72f7fe5a881cfae + source_path: automation/poll.md + workflow: 16 +--- + +此頁面已移至 [訊息工具](/zh-TW/cli/message)。請參閱 [訊息工具](/zh-TW/cli/message) 以取得輪詢文件。 + +## 相關內容 + +- [Webhook](/zh-TW/automation/cron-jobs) +- [排程任務](/zh-TW/automation/cron-jobs) +- [背景任務](/zh-TW/automation/tasks) diff --git a/docs/zh-TW/automation/standing-orders.md b/docs/zh-TW/automation/standing-orders.md new file mode 100644 index 000000000..627cbb23c --- /dev/null +++ b/docs/zh-TW/automation/standing-orders.md @@ -0,0 +1,257 @@ +--- +read_when: + - 設定無需針對每項任務提示即可執行的自主代理工作流程 + - 定義代理可以獨立執行的事項,以及需要人工核准的事項 + - 使用清楚的邊界與升級規則來建構多程式代理程式 +summary: 定義自主代理程式的永久操作權限 +title: 常設指令 +x-i18n: + generated_at: "2026-04-30T02:45:15Z" + model: gpt-5.5 + provider: openai + source_hash: ff895378cbd53f7e8058137389037ab40201ce2cdfb34c135f480dfef775919b + source_path: automation/standing-orders.md + workflow: 16 +--- + +常設指令會授予你的代理程式針對定義好方案的**永久操作權限**。你不必每次都提供個別任務指示,而是定義具備明確範圍、觸發條件與升級規則的方案,代理程式會在這些邊界內自主執行。 + +這就像是每週五告訴你的助理「寄送週報」,與授予常設權限之間的差異:「週報由你負責。每週五彙整、寄出,只有在看起來有問題時才升級處理。」 + +## 為什麼需要常設指令 + +**沒有常設指令時:** + +- 你必須為每個任務提示代理程式 +- 代理程式會在請求之間閒置 +- 例行工作會被忘記或延誤 +- 你會變成瓶頸 + +**有常設指令時:** + +- 代理程式會在定義好的邊界內自主執行 +- 例行工作會按時發生,無需提示 +- 你只需介入例外與核准事項 +- 代理程式能有效利用閒置時間 + +## 運作方式 + +常設指令定義在你的[代理程式工作區](/zh-TW/concepts/agent-workspace)檔案中。建議做法是直接放在 `AGENTS.md` 中(每個工作階段會自動注入),讓代理程式永遠能在脈絡中取得它們。對於較大型的設定,你也可以把它們放在像 `standing-orders.md` 這樣的專用檔案中,並從 `AGENTS.md` 參照它。 + +每個方案都會指定: + +1. **範圍** — 代理程式被授權執行的事項 +2. **觸發條件** — 何時執行(排程、事件或條件) +3. **核准關卡** — 採取行動前哪些事項需要人工簽核 +4. **升級規則** — 何時停止並請求協助 + +代理程式會透過工作區啟動檔案在每個工作階段載入這些指示(完整的自動注入檔案清單請見[代理程式工作區](/zh-TW/concepts/agent-workspace)),並結合[Cron 工作](/zh-TW/automation/cron-jobs)執行,以便進行以時間為基礎的強制執行。 + + +把常設指令放在 `AGENTS.md` 中,以確保每個工作階段都會載入。工作區啟動程序會自動注入 `AGENTS.md`、`SOUL.md`、`TOOLS.md`、`IDENTITY.md`、`USER.md`、`HEARTBEAT.md`、`BOOTSTRAP.md` 與 `MEMORY.md`,但不會注入子目錄中的任意檔案。 + + +## 常設指令的結構 + +```markdown +## Program: Weekly Status Report + +**Authority:** Compile data, generate report, deliver to stakeholders +**Trigger:** Every Friday at 4 PM (enforced via cron job) +**Approval gate:** None for standard reports. Flag anomalies for human review. +**Escalation:** If data source is unavailable or metrics look unusual (>2σ from norm) + +### Execution steps + +1. Pull metrics from configured sources +2. Compare to prior week and targets +3. Generate report in Reports/weekly/YYYY-MM-DD.md +4. Deliver summary via configured channel +5. Log completion to Agent/Logs/ + +### What NOT to do + +- Do not send reports to external parties +- Do not modify source data +- Do not skip delivery if metrics look bad — report accurately +``` + +## 常設指令加上 Cron 工作 + +常設指令定義代理程式被授權執行的**事項**。[Cron 工作](/zh-TW/automation/cron-jobs)定義它發生的**時間**。兩者會一起運作: + +``` +Standing Order: "You own the daily inbox triage" + ↓ +Cron Job (8 AM daily): "Execute inbox triage per standing orders" + ↓ +Agent: Reads standing orders → executes steps → reports results +``` + +Cron 工作提示應該參照常設指令,而不是重複其內容: + +```bash +openclaw cron add \ + --name daily-inbox-triage \ + --cron "0 8 * * 1-5" \ + --tz America/New_York \ + --timeout-seconds 300 \ + --announce \ + --channel bluebubbles \ + --to "+1XXXXXXXXXX" \ + --message "Execute daily inbox triage per standing orders. Check mail for new alerts. Parse, categorize, and persist each item. Report summary to owner. Escalate unknowns." +``` + +## 範例 + +### 範例 1:內容與社群媒體(每週週期) + +```markdown +## Program: Content & Social Media + +**Authority:** Draft content, schedule posts, compile engagement reports +**Approval gate:** All posts require owner review for first 30 days, then standing approval +**Trigger:** Weekly cycle (Monday review → mid-week drafts → Friday brief) + +### Weekly cycle + +- **Monday:** Review platform metrics and audience engagement +- **Tuesday–Thursday:** Draft social posts, create blog content +- **Friday:** Compile weekly marketing brief → deliver to owner + +### Content rules + +- Voice must match the brand (see SOUL.md or brand voice guide) +- Never identify as AI in public-facing content +- Include metrics when available +- Focus on value to audience, not self-promotion +``` + +### 範例 2:財務作業(事件觸發) + +```markdown +## Program: Financial Processing + +**Authority:** Process transaction data, generate reports, send summaries +**Approval gate:** None for analysis. Recommendations require owner approval. +**Trigger:** New data file detected OR scheduled monthly cycle + +### When new data arrives + +1. Detect new file in designated input directory +2. Parse and categorize all transactions +3. Compare against budget targets +4. Flag: unusual items, threshold breaches, new recurring charges +5. Generate report in designated output directory +6. Deliver summary to owner via configured channel + +### Escalation rules + +- Single item > $500: immediate alert +- Category > budget by 20%: flag in report +- Unrecognizable transaction: ask owner for categorization +- Failed processing after 2 retries: report failure, do not guess +``` + +### 範例 3:監控與警示(連續) + +```markdown +## Program: System Monitoring + +**Authority:** Check system health, restart services, send alerts +**Approval gate:** Restart services automatically. Escalate if restart fails twice. +**Trigger:** Every heartbeat cycle + +### Checks + +- Service health endpoints responding +- Disk space above threshold +- Pending tasks not stale (>24 hours) +- Delivery channels operational + +### Response matrix + +| Condition | Action | Escalate? | +| ---------------- | ------------------------ | ------------------------ | +| Service down | Restart automatically | Only if restart fails 2x | +| Disk space < 10% | Alert owner | Yes | +| Stale task > 24h | Remind owner | No | +| Channel offline | Log and retry next cycle | If offline > 2 hours | +``` + +## 執行、驗證、回報模式 + +常設指令搭配嚴格的執行紀律時效果最好。常設指令中的每個任務都應遵循這個循環: + +1. **執行** — 完成實際工作(不要只是確認收到指示) +2. **驗證** — 確認結果正確(檔案存在、訊息已送達、資料已解析) +3. **回報** — 告訴擁有者已完成哪些事項,以及已驗證哪些事項 + +```markdown +### Execution rules + +- Every task follows Execute-Verify-Report. No exceptions. +- "I'll do that" is not execution. Do it, then report. +- "Done" without verification is not acceptable. Prove it. +- If execution fails: retry once with adjusted approach. +- If still fails: report failure with diagnosis. Never silently fail. +- Never retry indefinitely — 3 attempts max, then escalate. +``` + +這個模式能避免最常見的代理程式失敗模式:確認任務但沒有完成它。 + +## 多方案架構 + +對於管理多個關注領域的代理程式,請將常設指令組織成邊界清楚的獨立方案: + +```markdown +## Program 1: [Domain A] (Weekly) + +... + +## Program 2: [Domain B] (Monthly + On-Demand) + +... + +## Program 3: [Domain C] (As-Needed) + +... + +## Escalation Rules (All Programs) + +- [Common escalation criteria] +- [Approval gates that apply across programs] +``` + +每個方案都應具備: + +- 自己的**觸發節奏**(每週、每月、事件驅動、連續) +- 自己的**核准關卡**(有些方案需要比其他方案更多監督) +- 清楚的**邊界**(代理程式應知道一個方案在哪裡結束,另一個方案在哪裡開始) + +## 最佳實務 + +### 應該做 + +- 從狹窄權限開始,隨著信任建立再擴大 +- 為高風險動作定義明確的核准關卡 +- 包含「不該做什麼」區段,邊界和權限一樣重要 +- 結合 Cron 工作,以可靠地執行以時間為基礎的任務 +- 每週檢閱代理程式日誌,確認常設指令有被遵循 +- 隨著需求演進更新常設指令;它們是持續變動的文件 + +### 避免 + +- 第一天就授予廣泛權限(「做你認為最好的事」) +- 省略升級規則;每個方案都需要「何時停止並詢問」條款 +- 假設代理程式會記得口頭指示;把所有內容都放進檔案 +- 在單一方案中混合不同關注領域;為不同領域分開建立方案 +- 忘記用 Cron 工作強制執行;沒有觸發條件的常設指令會變成建議 + +## 相關 + +- [自動化與任務](/zh-TW/automation):所有自動化機制一覽。 +- [Cron 工作](/zh-TW/automation/cron-jobs):常設指令的排程強制執行。 +- [Hook](/zh-TW/automation/hooks):用於代理程式生命週期事件的事件驅動指令碼。 +- [Webhook](/zh-TW/automation/cron-jobs#webhooks):傳入的 HTTP 事件觸發條件。 +- [代理程式工作區](/zh-TW/concepts/agent-workspace):常設指令所在的位置,包括完整的自動注入啟動檔案清單(`AGENTS.md`、`SOUL.md` 等)。 diff --git a/docs/zh-TW/automation/taskflow.md b/docs/zh-TW/automation/taskflow.md new file mode 100644 index 000000000..535ce8786 --- /dev/null +++ b/docs/zh-TW/automation/taskflow.md @@ -0,0 +1,162 @@ +--- +read_when: + - 你想了解 Task Flow 與背景任務之間的關係 + - 你會在發行說明或文件中遇到 TaskFlow 或 OpenClaw 任務流程 + - 你想要檢視或管理持久化的流程狀態 +summary: 位於背景任務之上的 TaskFlow 流程編排層 +title: 任務流程 +x-i18n: + generated_at: "2026-04-30T02:45:23Z" + model: gpt-5.5 + provider: openai + source_hash: 2ab261dea0ec3beb10b53c641bd188288cada5345aef6ddbbc8071d37eb57bdc + source_path: automation/taskflow.md + workflow: 16 +--- + +TaskFlow 是位於[背景任務](/zh-TW/automation/tasks)之上的流程編排基底。它會管理具有自身狀態、修訂追蹤與同步語義的持久多步驟流程,而個別任務仍是分離工作的單位。 + +## 何時使用 TaskFlow + +當工作橫跨多個循序或分支步驟,且需要在 gateway 重新啟動後仍能持久追蹤進度時,請使用 TaskFlow。對於單一背景作業,普通的[任務](/zh-TW/automation/tasks)就已足夠。 + +| 情境 | 使用方式 | +| ------------------------------------- | -------------------- | +| 單一背景工作 | 普通任務 | +| 多步驟管線(A 接著 B 接著 C) | TaskFlow(受管理) | +| 觀察外部建立的任務 | TaskFlow(鏡像) | +| 一次性提醒 | Cron 工作 | + +## 可靠的排程工作流程模式 + +對於市場情報簡報等週期性工作流程,請將排程、編排與可靠性檢查視為不同層次: + +1. 使用[排程任務](/zh-TW/automation/cron-jobs)處理時機。 +2. 當工作流程應該基於先前脈絡延續時,使用持久 cron 工作階段。 +3. 使用 [Lobster](/zh-TW/tools/lobster) 處理確定性步驟、核准關卡與續接權杖。 +4. 使用 TaskFlow 在子任務、等待、重試與 gateway 重新啟動之間追蹤多步驟執行。 + +範例 cron 形狀: + +```bash +openclaw cron add \ + --name "Market intelligence brief" \ + --cron "0 7 * * 1-5" \ + --tz "America/New_York" \ + --session session:market-intel \ + --message "Run the market-intel Lobster workflow. Verify source freshness before summarizing." \ + --announce \ + --channel slack \ + --to "channel:C1234567890" +``` + +當週期性工作流程需要刻意保留的歷史、前次執行摘要或常駐脈絡時,請使用 `session:` 而不是 `isolated`。當每次執行都應該從全新狀態開始,且所有必要狀態都已在工作流程中明確指定時,請使用 `isolated`。 + +在工作流程內,請將可靠性檢查放在 LLM 摘要步驟之前: + +```yaml +name: market-intel-brief +steps: + - id: preflight + command: market-intel check --json + - id: collect + command: market-intel collect --json + stdin: $preflight.json + - id: summarize + command: market-intel summarize --json + stdin: $collect.json + - id: approve + command: market-intel deliver --preview + stdin: $summarize.json + approval: required + - id: deliver + command: market-intel deliver --execute + stdin: $summarize.json + condition: $approve.approved +``` + +建議的預檢檢查: + +- 瀏覽器可用性與設定檔選擇,例如受管理狀態使用 `openclaw`,需要已登入的 Chrome 工作階段時使用 `user`。請參閱[瀏覽器](/zh-TW/tools/browser)。 +- 每個來源的 API 認證與配額。 +- 必要端點的網路可連線性。 +- 已為 agent 啟用必要工具,例如 `lobster`、`browser` 與 `llm-task`。 +- 已為 cron 設定失敗目的地,讓預檢失敗可見。請參閱[排程任務](/zh-TW/automation/cron-jobs#delivery-and-output)。 + +每個收集項目的建議資料來源欄位: + +```json +{ + "sourceUrl": "https://example.com/report", + "retrievedAt": "2026-04-24T12:00:00Z", + "asOf": "2026-04-24", + "title": "Example report", + "content": "..." +} +``` + +讓工作流程在摘要前拒絕或標記過期項目。LLM 步驟應該只接收結構化 JSON,並應要求它在輸出中保留 `sourceUrl`、`retrievedAt` 與 `asOf`。當你需要在工作流程內使用經 schema 驗證的模型步驟時,請使用 [LLM Task](/zh-TW/tools/llm-task)。 + +對於可重複使用的團隊或社群工作流程,請將 CLI、`.lobster` 檔案與任何設定說明封裝為 skill 或 plugin,並透過 [ClawHub](/zh-TW/tools/clawhub) 發布。除非 plugin API 缺少必要的通用能力,否則請將工作流程特定的防護規則保留在該套件中。 + +## 同步模式 + +### 受管理模式 + +TaskFlow 端到端擁有生命週期。它會建立任務作為流程步驟、驅動它們完成,並自動推進流程狀態。 + +範例:每週報告流程會 (1) 收集資料、(2) 產生報告,並 (3) 傳送報告。TaskFlow 會將每個步驟建立為背景任務,等待完成,然後移至下一個步驟。 + +``` +Flow: weekly-report + Step 1: gather-data → task created → succeeded + Step 2: generate-report → task created → succeeded + Step 3: deliver → task created → running +``` + +### 鏡像模式 + +TaskFlow 會觀察外部建立的任務,並在不取得任務建立所有權的情況下讓流程狀態保持同步。當任務來自 cron 工作、CLI 命令或其他來源,而你想要以流程形式統一檢視其進度時,這很有用。 + +範例:三個獨立的 cron 工作共同構成一個「早晨營運」例行流程。鏡像流程會追蹤它們的整體進度,而不控制它們何時或如何執行。 + +## 持久狀態與修訂追蹤 + +每個流程都會保留自身狀態並追蹤修訂,讓進度能在 gateway 重新啟動後延續。當多個來源嘗試同時推進同一個流程時,修訂追蹤可啟用衝突偵測。 +流程登錄使用 SQLite,並搭配有界限的預寫日誌維護,包括 +定期與關閉時的檢查點,因此長時間執行的 gateway 不會保留 +無界限的 `registry.sqlite-wal` 附屬檔案。 + +## 取消行為 + +`openclaw tasks flow cancel` 會在流程上設定黏著的取消意圖。流程內的作用中任務會被取消,且不會啟動新的步驟。取消意圖會在重新啟動後持續存在,因此即使 gateway 在所有子任務終止前重新啟動,已取消的流程仍會保持取消狀態。 + +## CLI 命令 + +```bash +# List active and recent flows +openclaw tasks flow list + +# Show details for a specific flow +openclaw tasks flow show + +# Cancel a running flow and its active tasks +openclaw tasks flow cancel +``` + +| 命令 | 說明 | +| --------------------------------- | -------------------------------------------- | +| `openclaw tasks flow list` | 顯示受追蹤流程的狀態與同步模式 | +| `openclaw tasks flow show ` | 依流程 ID 或查找鍵檢查單一流程 | +| `openclaw tasks flow cancel ` | 取消執行中的流程及其作用中任務 | + +## 流程與任務的關係 + +流程會協調任務,而不是取代任務。單一流程在其生命週期內可能驅動多個背景任務。使用 `openclaw tasks` 檢查個別任務記錄,並使用 `openclaw tasks flow` 檢查編排流程。 + +## 相關 + +- [背景任務](/zh-TW/automation/tasks) — 流程所協調的分離工作帳本 +- [CLI:任務](/zh-TW/cli/tasks) — `openclaw tasks flow` 的 CLI 命令參考 +- [自動化概覽](/zh-TW/automation) — 所有自動化機制一覽 +- [Cron 工作](/zh-TW/automation/cron-jobs) — 可能提供資料給流程的排程工作 diff --git a/docs/zh-TW/automation/tasks.md b/docs/zh-TW/automation/tasks.md new file mode 100644 index 000000000..e19b06d6c --- /dev/null +++ b/docs/zh-TW/automation/tasks.md @@ -0,0 +1,375 @@ +--- +read_when: + - 檢視進行中或最近完成的背景工作 + - 偵錯分離式代理執行的傳遞失敗 + - 了解背景執行如何與工作階段、Cron 和 Heartbeat 相關 +sidebarTitle: Background tasks +summary: ACP 執行、子代理、隔離的 Cron 作業和 CLI 操作的背景工作追蹤 +title: 背景任務 +x-i18n: + generated_at: "2026-04-30T02:45:25Z" + model: gpt-5.5 + provider: openai + source_hash: 4bbf74f3aeea532738b56b83cd2e1a0a3734bfd453da6636b8be985a28ccc027 + source_path: automation/tasks.md + workflow: 16 +--- + + +正在尋找排程功能嗎?請參閱[自動化與任務](/zh-TW/automation)以選擇正確機制。本頁是背景工作的活動帳本,不是排程器。 + + +背景任務會追蹤在**主要對話工作階段之外**執行的工作:ACP 執行、子代理生成、隔離的 cron 工作執行,以及 CLI 啟動的作業。 + +任務**不會**取代工作階段、cron 工作或 Heartbeat — 它們是記錄已分離工作發生內容、時間與是否成功的**活動帳本**。 + + +不是每次代理執行都會建立任務。Heartbeat 回合與一般互動式聊天不會。所有 cron 執行、ACP 生成、子代理生成與 CLI 代理命令都會。 + + +## TL;DR + +- 任務是**記錄**,不是排程器 — cron 與 Heartbeat 決定工作_何時_執行,任務追蹤_發生了什麼_。 +- ACP、子代理、所有 cron 工作與 CLI 作業都會建立任務。Heartbeat 回合不會。 +- 每個任務都會經過 `queued → running → terminal`(succeeded、failed、timed_out、cancelled 或 lost)。 +- 只要 cron 執行階段仍擁有該工作,cron 任務就會保持有效;如果 + 記憶體中的執行階段狀態已消失,任務維護會先檢查持久化 cron + 執行歷史,然後才將任務標記為 lost。 +- 完成是推送驅動的:分離的工作可以在完成時直接通知,或喚醒 + 請求者工作階段/Heartbeat,因此狀態輪詢迴圈通常不是正確模式。 +- 隔離的 cron 執行與子代理完成會在最終清理簿記前,盡力清理其子工作階段追蹤的瀏覽器分頁/程序。 +- 當後代子代理工作仍在收尾時,隔離的 cron 傳遞會抑制過期的暫時父層回覆,並且在最終後代輸出先於傳遞抵達時優先使用它。 +- 完成通知會直接傳送到頻道,或排入下一次 Heartbeat。 +- `openclaw tasks list` 會顯示所有任務;`openclaw tasks audit` 會顯示問題。 +- 終端記錄會保留 7 天,之後自動修剪。 + +## 快速開始 + + + + ```bash + # List all tasks (newest first) + openclaw tasks list + + # Filter by runtime or status + openclaw tasks list --runtime acp + openclaw tasks list --status running + ``` + + + + ```bash + # Show details for a specific task (by ID, run ID, or session key) + openclaw tasks show + ``` + + + ```bash + # Cancel a running task (kills the child session) + openclaw tasks cancel + + # Change notification policy for a task + openclaw tasks notify state_changes + ``` + + + + ```bash + # Run a health audit + openclaw tasks audit + + # Preview or apply maintenance + openclaw tasks maintenance + openclaw tasks maintenance --apply + ``` + + + + ```bash + # Inspect TaskFlow state + openclaw tasks flow list + openclaw tasks flow show + openclaw tasks flow cancel + ``` + + + +## 什麼會建立任務 + +| 來源 | 執行階段類型 | 建立任務記錄的時機 | 預設通知政策 | +| ---------------------- | ------------ | ------------------------------------------------------ | ------------ | +| ACP 背景執行 | `acp` | 生成子 ACP 工作階段 | `done_only` | +| 子代理協調 | `subagent` | 透過 `sessions_spawn` 生成子代理 | `done_only` | +| Cron 工作(所有類型) | `cron` | 每次 cron 執行(主要工作階段與隔離) | `silent` | +| CLI 作業 | `cli` | 透過 Gateway 執行的 `openclaw agent` 命令 | `silent` | +| 代理媒體工作 | `cli` | 由工作階段支援的 `video_generate` 執行 | `silent` | + + + + 主要工作階段 cron 任務預設使用 `silent` 通知政策 — 它們會建立記錄以供追蹤,但不會產生通知。隔離的 cron 任務也預設為 `silent`,但因為它們在自己的工作階段中執行,所以更可見。 + + 由工作階段支援的 `video_generate` 執行也使用 `silent` 通知政策。它們仍會建立任務記錄,但完成結果會以內部喚醒的形式交回原始代理工作階段,讓代理可以撰寫後續訊息並自行附加完成的影片。如果你選擇啟用 `tools.media.asyncCompletion.directSend`,非同步 `music_generate` 與 `video_generate` 完成會先嘗試直接頻道傳遞,之後才退回請求者工作階段喚醒路徑。 + + + + 當由工作階段支援的 `video_generate` 任務仍處於作用中時,該工具也會作為防護:同一工作階段中重複的 `video_generate` 呼叫會傳回作用中任務狀態,而不是開始第二個並行生成。當你需要從代理端明確查詢進度/狀態時,請使用 `action: "status"`。 + + + - Heartbeat 回合 — 主要工作階段;請參閱 [Heartbeat](/zh-TW/gateway/heartbeat) + - 一般互動式聊天回合 + - 直接 `/command` 回應 + + + + +## 任務生命週期 + +```mermaid +stateDiagram-v2 + [*] --> queued + queued --> running : agent starts + running --> succeeded : completes ok + running --> failed : error + running --> timed_out : timeout exceeded + running --> cancelled : operator cancels + queued --> lost : session gone > 5 min + running --> lost : session gone > 5 min +``` + +| 狀態 | 意義 | +| ----------- | -------------------------------------------------------------------------- | +| `queued` | 已建立,等待代理啟動 | +| `running` | 代理回合正在主動執行 | +| `succeeded` | 已成功完成 | +| `failed` | 已完成但發生錯誤 | +| `timed_out` | 超過設定的逾時 | +| `cancelled` | 由操作者透過 `openclaw tasks cancel` 停止 | +| `lost` | 執行階段在 5 分鐘寬限期後失去權威後援狀態 | + +轉換會自動發生 — 當關聯的代理執行結束時,任務狀態會更新為相符狀態。 + +代理執行完成是作用中任務記錄的權威來源。成功的分離執行會最終化為 `succeeded`,一般執行錯誤會最終化為 `failed`,逾時或中止結果會最終化為 `timed_out`。如果操作者已取消任務,或執行階段已記錄較強的終端狀態,例如 `failed`、`timed_out` 或 `lost`,後續的成功訊號不會將該終端狀態降級。 + +`lost` 具備執行階段感知能力: + +- ACP 任務:後援 ACP 子工作階段中繼資料消失。 +- 子代理任務:後援子工作階段從目標代理儲存中消失。 +- Cron 任務:cron 執行階段不再將該工作追蹤為作用中,且持久化 + cron 執行歷史未顯示該次執行的終端結果。離線 CLI + 稽核不會將其自身空的程序內 cron 執行階段狀態視為權威。 +- CLI 任務:隔離的子工作階段任務使用子工作階段;由聊天支援的 + CLI 任務則改用即時執行內容,因此殘留的 + 頻道/群組/直接工作階段列不會讓它們保持有效。由 Gateway 支援的 + `openclaw agent` 執行也會從其執行結果最終化,因此已完成的執行 + 不會一直保持作用中直到清掃器將它們標記為 `lost`。 + +## 傳遞與通知 + +當任務達到終端狀態時,OpenClaw 會通知你。共有兩種傳遞路徑: + +**直接傳遞** — 如果任務有頻道目標(`requesterOrigin`),完成訊息會直接送到該頻道(Telegram、Discord、Slack 等)。對於子代理完成,OpenClaw 也會在可用時保留繫結的討論串/主題路由,並且可以在放棄直接傳遞前,從請求者工作階段儲存的路由(`lastChannel` / `lastTo` / `lastAccountId`)補上缺少的 `to` / 帳號。 + +**工作階段佇列傳遞** — 如果直接傳遞失敗或未設定來源,更新會以系統事件形式排入請求者的工作階段,並在下一次 Heartbeat 中顯示。 + + +任務完成會觸發立即 Heartbeat 喚醒,讓你快速看到結果 — 你不必等到下一個排定的 Heartbeat tick。 + + +這表示通常的工作流程是推送式:啟動一次分離工作,然後讓執行階段在完成時喚醒或通知你。只有在需要偵錯、介入或明確稽核時,才輪詢任務狀態。 + +### 通知政策 + +控制每個任務要聽到多少訊息: + +| 政策 | 傳遞內容 | +| --------------------- | ----------------------------------------------------------------------- | +| `done_only`(預設) | 僅終端狀態(succeeded、failed 等)— **這是預設值** | +| `state_changes` | 每次狀態轉換與進度更新 | +| `silent` | 完全不傳遞 | + +在任務執行時變更政策: + +```bash +openclaw tasks notify state_changes +``` + +## CLI 參考 + + + + ```bash + openclaw tasks list [--runtime ] [--status ] [--json] + ``` + + 輸出欄位:任務 ID、種類、狀態、傳遞、執行 ID、子工作階段、摘要。 + + + + ```bash + openclaw tasks show + ``` + + 查詢權杖接受任務 ID、執行 ID 或工作階段鍵。顯示完整記錄,包括時間、傳遞狀態、錯誤與終端摘要。 + + + + ```bash + openclaw tasks cancel + ``` + + 對 ACP 與子代理任務而言,這會終止子工作階段。對 CLI 追蹤的任務而言,取消會記錄在任務登錄中(沒有單獨的子執行階段控制代碼)。狀態會轉換為 `cancelled`,並在適用時傳送傳遞通知。 + + + + ```bash + openclaw tasks notify + ``` + + + ```bash + openclaw tasks audit [--json] + ``` + + 顯示營運問題。偵測到問題時,發現項目也會出現在 `openclaw status` 中。 + + | 發現 | 嚴重性 | 觸發條件 | + | ------------------------- | ---------- | ------------------------------------------------------------------------------------------------------------ | + | `stale_queued` | warn | 已佇列超過 10 分鐘 | + | `stale_running` | error | 已執行超過 30 分鐘 | + | `lost` | warn/error | 由執行階段支援的任務所有權已消失;保留的遺失任務在 `cleanupAfter` 前會警告,之後會變成錯誤 | + | `delivery_failed` | warn | 傳遞失敗且通知原則不是 `silent` | + | `missing_cleanup` | warn | 沒有清理時間戳記的終端任務 | + | `inconsistent_timestamps` | warn | 時間軸違規(例如結束早於開始) | + + + + ```bash + openclaw tasks maintenance [--json] + openclaw tasks maintenance --apply [--json] + ``` + + 使用此命令預覽或套用任務與 Task Flow 狀態的協調、清理標記與修剪。 + + 協調會感知執行階段: + + - ACP/subagent 任務會檢查其背後的子工作階段。 + - Cron 任務會檢查 cron 執行階段是否仍擁有該作業,然後先從持久化的 cron 執行記錄/作業狀態復原終端狀態,再退回到 `lost`。只有 Gateway 程序對記憶體內的 cron 作用中作業集合具有權威性;離線 CLI 稽核會使用持久化歷史,但不會只因為該本機 Set 是空的就將 cron 任務標記為遺失。 + - 由聊天支援的 CLI 任務會檢查擁有者的即時執行脈絡,而不只是聊天工作階段列。 + + 完成清理也會感知執行階段: + + - Subagent 完成會盡力關閉子工作階段追蹤的瀏覽器分頁/程序,然後繼續公告清理。 + - 隔離的 cron 完成會盡力關閉 cron 工作階段追蹤的瀏覽器分頁/程序,然後執行才會完全拆除。 + - 隔離的 cron 傳遞會在需要時等待後代 subagent 的後續作業,並抑制過時的父層確認文字,而不是公告它。 + - Subagent 完成傳遞會偏好最新可見的助理文字;如果該文字為空,則退回到已清理的最新 tool/toolResult 文字,且只有逾時的工具呼叫執行可以收斂成簡短的部分進度摘要。終端失敗執行會公告失敗狀態,而不重播擷取的回覆文字。 + - 清理失敗不會遮蔽真正的任務結果。 + + + + ```bash + openclaw tasks flow list [--status ] [--json] + openclaw tasks flow show [--json] + openclaw tasks flow cancel + ``` + + 當你關心的是協調中的 Task Flow,而不是單一背景任務記錄時,使用這些命令。 + + + + +## 聊天任務看板 (`/tasks`) + +在任何聊天工作階段中使用 `/tasks`,即可查看連結到該工作階段的背景任務。看板會顯示作用中與最近完成的任務,以及執行階段、狀態、時間和進度或錯誤詳細資訊。 + +當目前工作階段沒有可見的連結任務時,`/tasks` 會退回到 agent 本機的任務計數,因此你仍可取得概覽,而不會洩漏其他工作階段的詳細資訊。 + +如需完整的操作員分類帳,請使用 CLI:`openclaw tasks list`。 + +## 狀態整合(任務壓力) + +`openclaw status` 包含一眼可讀的任務摘要: + +``` +Tasks: 3 queued · 2 running · 1 issues +``` + +摘要會回報: + +- **active** — `queued` + `running` 的計數 +- **failures** — `failed` + `timed_out` + `lost` 的計數 +- **byRuntime** — 依 `acp`、`subagent`、`cron`、`cli` 分解 + +`/status` 和 `session_status` 工具都會使用可感知清理的任務快照:優先顯示作用中任務、隱藏過時的已完成列,且只有在沒有作用中工作剩下時,才浮現最近的失敗。這會讓狀態卡片聚焦於目前重要的事項。 + +## 儲存與維護 + +### 任務所在位置 + +任務記錄會持久化到 SQLite,位於: + +``` +$OPENCLAW_STATE_DIR/tasks/runs.sqlite +``` + +登錄檔會在 gateway 啟動時載入記憶體,並將寫入同步到 SQLite,以便在重新啟動後保持持久性。 +Gateway 會使用 SQLite 預設的 autocheckpoint 閾值,加上定期與關機時的 `TRUNCATE` checkpoint,讓 SQLite write-ahead log 維持有界。 + +### 自動維護 + +清掃器每 **60 秒** 執行一次,處理四件事: + + + + 檢查作用中任務是否仍有具權威性的執行階段支援。ACP/subagent 任務使用子工作階段狀態,cron 任務使用作用中作業所有權,而由聊天支援的 CLI 任務則使用擁有者的執行脈絡。如果該支援狀態消失超過 5 分鐘,任務會被標記為 `lost`。 + + + 關閉終端或孤立的父層擁有一次性 ACP 工作階段,且只有在沒有作用中對話繫結保留時,才關閉過時的終端或孤立的持久 ACP 工作階段。 + + + 在終端任務上設定 `cleanupAfter` 時間戳記(endedAt + 7 天)。在保留期間,遺失任務仍會在稽核中顯示為警告;在 `cleanupAfter` 到期後,或清理中繼資料缺失時,它們會是錯誤。 + + + 刪除超過其 `cleanupAfter` 日期的記錄。 + + + + +**保留:**終端任務記錄會保留 **7 天**,然後自動修剪。不需要設定。 + + +## 任務如何與其他系統相關 + + + + [Task Flow](/zh-TW/automation/taskflow) 是位於背景任務之上的流程協調層。單一流程可在其生命週期中使用受管理或鏡像同步模式來協調多個任務。使用 `openclaw tasks` 檢查個別任務記錄,使用 `openclaw tasks flow` 檢查協調中的流程。 + + 詳情請參閱 [Task Flow](/zh-TW/automation/taskflow)。 + + + + cron 作業**定義**位於 `~/.openclaw/cron/jobs.json`;執行階段執行狀態位於旁邊的 `~/.openclaw/cron/jobs-state.json`。**每次** cron 執行都會建立一筆任務記錄,包括主工作階段與隔離執行。主工作階段 cron 任務預設為 `silent` 通知原則,因此可以追蹤而不產生通知。 + + 請參閱 [Cron 作業](/zh-TW/automation/cron-jobs)。 + + + + Heartbeat 執行是主工作階段回合,它們不會建立任務記錄。任務完成時,可以觸發 heartbeat 喚醒,讓你能立即看到結果。 + + 請參閱 [Heartbeat](/zh-TW/gateway/heartbeat)。 + + + + 任務可能會參照 `childSessionKey`(工作執行處)與 `requesterSessionKey`(啟動者)。工作階段是對話脈絡;任務是在其上的活動追蹤。 + + + 任務的 `runId` 會連結到正在執行工作的 agent 執行。Agent 生命週期事件(開始、結束、錯誤)會自動更新任務狀態,你不需要手動管理生命週期。 + + + +## 相關 + +- [自動化與任務](/zh-TW/automation) — 所有自動化機制一覽 +- [CLI:任務](/zh-TW/cli/tasks) — CLI 命令參考 +- [Heartbeat](/zh-TW/gateway/heartbeat) — 週期性主工作階段回合 +- [排程任務](/zh-TW/automation/cron-jobs) — 排程背景工作 +- [Task Flow](/zh-TW/automation/taskflow) — 任務之上的流程協調 diff --git a/docs/zh-TW/automation/troubleshooting.md b/docs/zh-TW/automation/troubleshooting.md new file mode 100644 index 000000000..a54d20f99 --- /dev/null +++ b/docs/zh-TW/automation/troubleshooting.md @@ -0,0 +1,19 @@ +--- +summary: 重新導向至 /automation/cron-jobs +title: 自動化疑難排解 +x-i18n: + generated_at: "2026-04-30T02:45:16Z" + model: gpt-5.5 + provider: openai + source_hash: e7784858f6d2594a1d6019435b2a5a1647e12f5de6329198db9539e325f73737 + source_path: automation/troubleshooting.md + workflow: 16 +--- + +此頁面已移至[排程任務](/zh-TW/automation/cron-jobs#troubleshooting)。請參閱[排程任務](/zh-TW/automation/cron-jobs#troubleshooting)以取得疑難排解文件。 + +## 相關 + +- [掛鉤](/zh-TW/automation/hooks) +- [背景任務](/zh-TW/automation/tasks) +- [Gateway 疑難排解](/zh-TW/gateway/troubleshooting) diff --git a/docs/zh-TW/automation/webhook.md b/docs/zh-TW/automation/webhook.md new file mode 100644 index 000000000..e13071bc0 --- /dev/null +++ b/docs/zh-TW/automation/webhook.md @@ -0,0 +1,19 @@ +--- +summary: 重新導向至 /automation/cron-jobs +title: Webhook +x-i18n: + generated_at: "2026-04-30T02:45:20Z" + model: gpt-5.5 + provider: openai + source_hash: b0241fc7232c73d1f595f18fdf1a2d65475c6a82e3068b0aefb4f95f41712086 + source_path: automation/webhook.md + workflow: 16 +--- + +此頁面已移至 [排程任務](/zh-TW/automation/cron-jobs#webhooks)。請參閱 [排程任務](/zh-TW/automation/cron-jobs#webhooks) 以取得 Webhook 文件。 + +## 相關 + +- [輪詢](/zh-TW/cli/message) +- [Gmail PubSub](/zh-TW/automation/cron-jobs) +- [掛鉤](/zh-TW/automation/hooks) diff --git a/docs/zh-TW/brave-search.md b/docs/zh-TW/brave-search.md new file mode 100644 index 000000000..3fd715b5e --- /dev/null +++ b/docs/zh-TW/brave-search.md @@ -0,0 +1,114 @@ +--- +read_when: + - 您想使用 Brave Search 進行 web_search + - 你需要 BRAVE_API_KEY 或方案詳細資訊 +summary: web_search 的 Brave Search API 設定 +title: Brave 搜尋(舊版路徑) +x-i18n: + generated_at: "2026-04-30T02:45:48Z" + model: gpt-5.5 + provider: openai + source_hash: e2769da4db2ff5b94217c09b13ef5ee4106ba108a828db2a99892a4a15d7b517 + source_path: brave-search.md + workflow: 16 +--- + +# Brave Search API + +OpenClaw 支援 Brave Search API 作為 `web_search` 提供者。 + +## 取得 API 金鑰 + +1. 在 [https://brave.com/search/api/](https://brave.com/search/api/) 建立 Brave Search API 帳戶 +2. 在儀表板中,選擇 **Search** 方案並產生 API 金鑰。 +3. 將金鑰儲存在設定中,或在 Gateway 環境中設定 `BRAVE_API_KEY`。 + +## 設定範例 + +```json5 +{ + plugins: { + entries: { + brave: { + config: { + webSearch: { + apiKey: "BRAVE_API_KEY_HERE", + mode: "web", // or "llm-context" + }, + }, + }, + }, + }, + tools: { + web: { + search: { + provider: "brave", + maxResults: 5, + timeoutSeconds: 30, + }, + }, + }, +} +``` + +Brave 專屬的搜尋設定現在位於 `plugins.entries.brave.config.webSearch.*` 下。 +舊版 `tools.web.search.apiKey` 仍會透過相容性 shim 載入,但它不再是標準設定路徑。 + +`webSearch.mode` 控制 Brave 傳輸模式: + +- `web`(預設):一般 Brave 網頁搜尋,包含標題、URL 和摘要 +- `llm-context`:Brave LLM Context API,包含預先擷取的文字區塊和用於依據佐證的來源 + +## 工具參數 + +| 參數 | 說明 | +| ------------- | ------------------------------------------------------------------- | +| `query` | 搜尋查詢(必要) | +| `count` | 要傳回的結果數量(1-10,預設:5) | +| `country` | 2 字母 ISO 國家代碼(例如 "US"、"DE") | +| `language` | 搜尋結果的 ISO 639-1 語言代碼(例如 "en"、"de"、"fr") | +| `search_lang` | Brave 搜尋語言代碼(例如 `en`、`en-gb`、`zh-hans`) | +| `ui_lang` | UI 元素的 ISO 語言代碼 | +| `freshness` | 時間篩選器:`day`(24 小時)、`week`、`month` 或 `year` | +| `date_after` | 只包含此日期之後發布的結果(YYYY-MM-DD) | +| `date_before` | 只包含此日期之前發布的結果(YYYY-MM-DD) | + +**範例:** + +```javascript +// Country and language-specific search +await web_search({ + query: "renewable energy", + country: "DE", + language: "de", +}); + +// Recent results (past week) +await web_search({ + query: "AI news", + freshness: "week", +}); + +// Date range search +await web_search({ + query: "AI developments", + date_after: "2024-01-01", + date_before: "2024-06-30", +}); +``` + +## 注意事項 + +- OpenClaw 使用 Brave **Search** 方案。如果你有舊版訂閱(例如原本每月 2,000 次查詢的 Free 方案),它仍然有效,但不包含 LLM Context 或更高速率限制等較新功能。 +- 每個 Brave 方案都包含**每月 \$5 免費額度**(會續期)。Search 方案每 1,000 次請求收費 \$5,因此該額度可涵蓋每月 1,000 次查詢。請在 Brave 儀表板中設定使用量限制,以避免產生非預期費用。請參閱 [Brave API 入口網站](https://brave.com/search/api/)了解目前方案。 +- Search 方案包含 LLM Context 端點和 AI 推論權限。儲存結果以訓練或微調模型需要具備明確儲存權限的方案。請參閱 Brave [服務條款](https://api-dashboard.search.brave.com/terms-of-service)。 +- `llm-context` 模式會傳回有依據佐證的來源項目,而不是一般網頁搜尋摘要格式。 +- `llm-context` 模式不支援 `ui_lang`、`freshness`、`date_after` 或 `date_before`。 +- `ui_lang` 必須包含像 `en-US` 這樣的區域子標籤。 +- 結果預設會快取 15 分鐘(可透過 `cacheTtlMinutes` 設定)。 + +請參閱 [Web 工具](/zh-TW/tools/web)了解完整的 web_search 設定。 + +## 相關 + +- [Brave 搜尋](/zh-TW/tools/brave-search) diff --git a/docs/zh-TW/channels/bluebubbles.md b/docs/zh-TW/channels/bluebubbles.md new file mode 100644 index 000000000..c4f2aa95d --- /dev/null +++ b/docs/zh-TW/channels/bluebubbles.md @@ -0,0 +1,645 @@ +--- +read_when: + - 設定 BlueBubbles 頻道 + - Webhook 配對疑難排解 + - 在 macOS 上設定 iMessage +sidebarTitle: BlueBubbles +summary: 透過 BlueBubbles macOS 伺服器使用 iMessage(REST 傳送/接收、輸入狀態、回應、配對、進階動作)。 +title: BlueBubbles +x-i18n: + generated_at: "2026-04-30T02:46:00Z" + model: gpt-5.5 + provider: openai + source_hash: 7a77b248ed86eb4114f8b7f1fc6bd4cea004d65095a0439a4a8c814bc180082c + source_path: channels/bluebubbles.md + workflow: 16 +--- + +狀態:透過 HTTP 與 BlueBubbles macOS 伺服器通訊的內建 Plugin。由於相較於舊版 imsg 頻道,它具備更完整的 API 且設定更簡單,因此**建議用於 iMessage 整合**。 + + +目前的 OpenClaw 版本已內建 BlueBubbles,因此一般封裝建置不需要另外執行 `openclaw plugins install` 步驟。 + + +## 概觀 + +- 透過 BlueBubbles 輔助 App([bluebubbles.app](https://bluebubbles.app))在 macOS 上執行。 +- 建議/已測試:macOS Sequoia (15)。macOS Tahoe (26) 可運作;目前 Tahoe 上的編輯功能無法使用,而群組圖示更新可能回報成功但未同步。 +- OpenClaw 透過其 REST API(`GET /api/v1/ping`、`POST /message/text`、`POST /chat/:id/*`)與它通訊。 +- 傳入訊息透過 Webhook 抵達;傳出回覆、輸入中指示、已讀回條與 tapback 都是 REST 呼叫。 +- 附件與貼圖會作為傳入媒體擷取(可行時也會提供給代理)。 +- 合成 MP3 或 CAF 音訊的自動 TTS 回覆會以 iMessage 語音備忘錄氣泡傳送,而不是一般檔案附件。 +- 配對/允許清單的運作方式與其他頻道相同(`/channels/pairing` 等),搭配 `channels.bluebubbles.allowFrom` 與配對碼使用。 +- 回應會像 Slack/Telegram 一樣以系統事件呈現,讓代理可在回覆前「提及」它們。 +- 進階功能:編輯、取消傳送、回覆串接、訊息效果、群組管理。 + +## 快速開始 + + + + 在你的 Mac 上安裝 BlueBubbles 伺服器(依照 [bluebubbles.app/install](https://bluebubbles.app/install) 的指示)。 + + + 在 BlueBubbles 設定中啟用 Web API 並設定密碼。 + + + 執行 `openclaw onboard` 並選取 BlueBubbles,或手動設定: + + ```json5 + { + channels: { + bluebubbles: { + enabled: true, + serverUrl: "http://192.168.1.100:1234", + password: "example-password", + webhookPath: "/bluebubbles-webhook", + }, + }, + } + ``` + + + + 將 BlueBubbles Webhook 指向你的 Gateway(範例:`https://your-gateway-host:3000/bluebubbles-webhook?password=`)。 + + + 啟動 Gateway;它會註冊 Webhook 處理常式並開始配對。 + + + + +**安全性** + +- 一律設定 Webhook 密碼。 +- Webhook 驗證一律為必要。除非 BlueBubbles Webhook 要求包含符合 `channels.bluebubbles.password` 的密碼/guid(例如 `?password=` 或 `x-password`),否則 OpenClaw 會拒絕該要求,不論 loopback/代理拓撲為何。 +- 密碼驗證會在讀取/解析完整 Webhook 本文之前檢查。 + + + +## 讓 Messages.app 保持運作(VM/無頭設定) + +某些 macOS VM/常開設定可能會使 Messages.app 進入「閒置」狀態(傳入事件停止,直到 App 被開啟/切到前景)。簡單的替代方案是使用 AppleScript + LaunchAgent **每 5 分鐘戳一下 Messages**。 + + + + 將此儲存為 `~/Scripts/poke-messages.scpt`: + + ```applescript + try + tell application "Messages" + if not running then + launch + end if + + -- Touch the scripting interface to keep the process responsive. + set _chatCount to (count of chats) + end tell + on error + -- Ignore transient failures (first-run prompts, locked session, etc). + end try + ``` + + + + 將此儲存為 `~/Library/LaunchAgents/com.user.poke-messages.plist`: + + ```xml + + + + + Label + com.user.poke-messages + + ProgramArguments + + /bin/bash + -lc + /usr/bin/osascript "$HOME/Scripts/poke-messages.scpt" + + + RunAtLoad + + + StartInterval + 300 + + StandardOutPath + /tmp/poke-messages.log + StandardErrorPath + /tmp/poke-messages.err + + + ``` + + 這會**每 300 秒**並在**登入時**執行。第一次執行可能會觸發 macOS **Automation** 提示(`osascript` → Messages)。請在執行 LaunchAgent 的同一個使用者工作階段中核准。 + + + + ```bash + launchctl unload ~/Library/LaunchAgents/com.user.poke-messages.plist 2>/dev/null || true + launchctl load ~/Library/LaunchAgents/com.user.poke-messages.plist + ``` + + + +## 上線設定 + +BlueBubbles 可在互動式上線設定中使用: + +``` +openclaw onboard +``` + +精靈會提示輸入: + + + BlueBubbles 伺服器位址(例如 `http://192.168.1.100:1234`)。 + + + 來自 BlueBubbles Server 設定的 API 密碼。 + + + Webhook 端點路徑。 + + + `pairing`、`allowlist`、`open` 或 `disabled`。 + + + 電話號碼、電子郵件或聊天目標。 + + +你也可以透過 CLI 新增 BlueBubbles: + +``` +openclaw channels add bluebubbles --http-url http://192.168.1.100:1234 --password +``` + +## 存取控制(DM + 群組) + + + + - 預設:`channels.bluebubbles.dmPolicy = "pairing"`。 + - 未知寄件者會收到配對碼;在核准前訊息會被忽略(代碼會在 1 小時後過期)。 + - 透過以下方式核准: + - `openclaw pairing list bluebubbles` + - `openclaw pairing approve bluebubbles ` + - 配對是預設的權杖交換。詳細資訊:[配對](/zh-TW/channels/pairing) + + + + - `channels.bluebubbles.groupPolicy = open | allowlist | disabled`(預設:`allowlist`)。 + - 設定 `allowlist` 時,`channels.bluebubbles.groupAllowFrom` 控制誰可以在群組中觸發。 + + + + +### 聯絡人名稱補充(macOS,選用) + +BlueBubbles 群組 Webhook 通常只包含原始參與者位址。如果你希望 `GroupMembers` 內容改為顯示本機聯絡人名稱,可以在 macOS 上選擇啟用本機 Contacts 補充: + +- `channels.bluebubbles.enrichGroupParticipantsFromContacts = true` 啟用查詢。預設:`false`。 +- 查詢只會在群組存取、命令授權與提及閘控允許訊息通過後執行。 +- 只會補充未命名的電話參與者。 +- 找不到本機符合項目時,原始電話號碼會保留作為後備。 + +```json5 +{ + channels: { + bluebubbles: { + enrichGroupParticipantsFromContacts: true, + }, + }, +} +``` + +### 提及閘控(群組) + +BlueBubbles 支援群組聊天的提及閘控,與 iMessage/WhatsApp 行為一致: + +- 使用 `agents.list[].groupChat.mentionPatterns`(或 `messages.groupChat.mentionPatterns`)偵測提及。 +- 對群組啟用 `requireMention` 時,代理只會在被提及時回應。 +- 來自已授權寄件者的控制命令會略過提及閘控。 + +每群組設定: + +```json5 +{ + channels: { + bluebubbles: { + groupPolicy: "allowlist", + groupAllowFrom: ["+15555550123"], + groups: { + "*": { requireMention: true }, // default for all groups + "iMessage;-;chat123": { requireMention: false }, // override for specific group + }, + }, + }, +} +``` + +### 命令閘控 + +- 控制命令(例如 `/config`、`/model`)需要授權。 +- 使用 `allowFrom` 與 `groupAllowFrom` 判定命令授權。 +- 已授權寄件者即使未在群組中提及,也可以執行控制命令。 + +### 每群組系統提示 + +`channels.bluebubbles.groups.*` 下的每個項目都接受選用的 `systemPrompt` 字串。該值會在處理該群組訊息的每一輪中注入代理的系統提示,因此你可以設定每群組的人格或行為規則,而不必編輯代理提示: + +```json5 +{ + channels: { + bluebubbles: { + groups: { + "iMessage;-;chat123": { + systemPrompt: "Keep responses under 3 sentences. Mirror the group's casual tone.", + }, + }, + }, + }, +} +``` + +鍵會符合 BlueBubbles 為該群組回報的 `chatGuid` / `chatIdentifier` / 數字 `chatId`,而 `"*"` 萬用字元項目會為沒有精確符合項目的每個群組提供預設值(與 `requireMention` 和每群組工具政策使用相同模式)。精確符合一律優先於萬用字元。DM 會忽略此欄位;請改用代理層級或帳號層級的提示自訂。 + +#### 實作範例:串接回覆與 tapback 回應(Private API) + +啟用 BlueBubbles Private API 後,傳入訊息會附帶短訊息 ID(例如 `[[reply_to:5]]`),且代理可以呼叫 `action=reply` 以串接到特定訊息,或呼叫 `action=react` 放置 tapback。每群組 `systemPrompt` 是讓代理選擇正確工具的可靠方式: + +```json5 +{ + channels: { + bluebubbles: { + groups: { + "iMessage;+;chat-family": { + systemPrompt: [ + "When replying in this group, always call action=reply with the", + "[[reply_to:N]] messageId from context so your response threads", + "under the triggering message. Never send a new unlinked message.", + "", + "For short acknowledgements ('ok', 'got it', 'on it'), use", + "action=react with an appropriate tapback emoji (❤️, 👍, 😂, ‼️, ❓)", + "instead of sending a text reply.", + ].join(" "), + }, + }, + }, + }, +} +``` + +Tapback 回應和串接回覆都需要 BlueBubbles Private API;請參閱[進階動作](#advanced-actions)與[訊息 ID](#message-ids-short-vs-full)以了解底層機制。 + +## ACP 對話繫結 + +BlueBubbles 聊天可以在不變更傳輸層的情況下轉換為持久 ACP 工作區。 + +快速操作流程: + +- 在 DM 或允許的群組聊天中執行 `/acp spawn codex --bind here`。 +- 同一個 BlueBubbles 對話中的後續訊息會路由到產生的 ACP 工作階段。 +- `/new` 和 `/reset` 會就地重設同一個已繫結的 ACP 工作階段。 +- `/acp close` 會關閉 ACP 工作階段並移除繫結。 + +也支援透過頂層 `bindings[]` 項目設定持久繫結,其中包含 `type: "acp"` 與 `match.channel: "bluebubbles"`。 + +`match.peer.id` 可以使用任何支援的 BlueBubbles 目標形式: + +- 正規化 DM 控點,例如 `+15555550123` 或 `user@example.com` +- `chat_id:` +- `chat_guid:` +- `chat_identifier:` + +對於穩定的群組繫結,建議使用 `chat_id:*` 或 `chat_identifier:*`。 + +範例: + +```json5 +{ + agents: { + list: [ + { + id: "codex", + runtime: { + type: "acp", + acp: { agent: "codex", backend: "acpx", mode: "persistent" }, + }, + }, + ], + }, + bindings: [ + { + type: "acp", + agentId: "codex", + match: { + channel: "bluebubbles", + accountId: "default", + peer: { kind: "dm", id: "+15555550123" }, + }, + acp: { label: "codex-imessage" }, + }, + ], +} +``` + +請參閱 [ACP Agents](/zh-TW/tools/acp-agents) 以了解共用的 ACP 繫結行為。 + +## 輸入中 + 已讀回條 + +- **輸入中指示器**:會在回覆生成前與生成期間自動傳送。 +- **已讀回條**:由 `channels.bluebubbles.sendReadReceipts` 控制(預設值:`true`)。 +- **輸入中指示器**:OpenClaw 會傳送開始輸入事件;BlueBubbles 會在傳送或逾時時自動清除輸入狀態(透過 DELETE 手動停止並不可靠)。 + +```json5 +{ + channels: { + bluebubbles: { + sendReadReceipts: false, // disable read receipts + }, + }, +} +``` + +## 進階動作 + +BlueBubbles 在設定中啟用後支援進階訊息動作: + +```json5 +{ + channels: { + bluebubbles: { + actions: { + reactions: true, // tapbacks (default: true) + edit: true, // edit sent messages (macOS 13+, broken on macOS 26 Tahoe) + unsend: true, // unsend messages (macOS 13+) + reply: true, // reply threading by message GUID + sendWithEffect: true, // message effects (slam, loud, etc.) + renameGroup: true, // rename group chats + setGroupIcon: true, // set group chat icon/photo (flaky on macOS 26 Tahoe) + addParticipant: true, // add participants to groups + removeParticipant: true, // remove participants from groups + leaveGroup: true, // leave group chats + sendAttachment: true, // send attachments/media + }, + }, + }, +} +``` + + + + - **react**:新增/移除 tapback 反應(`messageId`、`emoji`、`remove`)。iMessage 的原生 tapback 集合是 `love`、`like`、`dislike`、`laugh`、`emphasize` 和 `question`。當代理選擇該集合之外的 emoji(例如 `👀`)時,反應工具會退回使用 `love`,讓 tapback 仍能顯示,而不是讓整個請求失敗。已設定的確認反應仍會嚴格驗證,並在未知值上報錯。 + - **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`)。 + - **upload-file**:傳送媒體/檔案(`to`、`buffer`、`filename`、`asVoice`)。 + - 語音備忘錄:設定 `asVoice: true`,並使用 **MP3** 或 **CAF** 音訊,以 iMessage 語音訊息傳送。BlueBubbles 會在傳送語音備忘錄時將 MP3 → CAF。 + - 舊版別名:`sendAttachment` 仍可使用,但 `upload-file` 是標準動作名稱。 + + + + +### 訊息 ID(短 ID 與完整 ID) + +OpenClaw 可能會顯示_短_訊息 ID(例如 `1`、`2`)以節省 Token。 + +- `MessageSid` / `ReplyToId` 可以是短 ID。 +- `MessageSidFull` / `ReplyToIdFull` 包含提供者的完整 ID。 +- 短 ID 儲存在記憶體中;它們可能會在重新啟動或快取淘汰後過期。 +- 動作接受短或完整 `messageId`,但如果短 ID 已無法取得,將會報錯。 + +對於持久的自動化與儲存,請使用完整 ID: + +- 範本:`{{MessageSidFull}}`、`{{ReplyToIdFull}}` +- 情境:傳入酬載中的 `MessageSidFull` / `ReplyToIdFull` + +範本變數請參閱[設定](/zh-TW/gateway/configuration)。 + + + +## 合併分段傳送的 DM(指令 + URL 在同一次組合中) + +當使用者在 iMessage 中同時輸入指令和 URL,例如 `Dump https://example.com/article`,Apple 會將傳送拆成**兩個獨立的 Webhook 投遞**: + +1. 一則文字訊息(`"Dump"`)。 +2. 一個 URL 預覽氣泡(`"https://..."`),並以附件形式包含 OG 預覽圖片。 + +在多數設定中,兩個 Webhook 約相隔 0.8-2.0 秒抵達 OpenClaw。若沒有合併,代理會在第 1 回合只收到指令並回覆(通常是「把 URL 傳給我」),然後只在第 2 回合看到 URL,此時指令情境已經遺失。 + +`channels.bluebubbles.coalesceSameSenderDms` 會選擇讓 DM 將連續的同一寄件者 Webhook 合併成單一代理回合。群組聊天會繼續按每則訊息作為鍵,以保留多使用者回合結構。 + + + + 在以下情況啟用: + + - 你提供預期一則訊息中有 `command + payload` 的 Skills(dump、paste、save、queue 等)。 + - 你的使用者會在指令旁貼上 URL、圖片或長內容。 + - 你可以接受增加的 DM 回合延遲(見下方)。 + + 在以下情況保持停用: + + - 你需要單字 DM 觸發的最低指令延遲。 + - 你的所有流程都是沒有後續酬載的一次性指令。 + + + + ```json5 + { + channels: { + bluebubbles: { + coalesceSameSenderDms: true, // opt in (default: false) + }, + }, + } + ``` + + 啟用此旗標且未明確設定 `messages.inbound.byChannel.bluebubbles` 時,防抖視窗會加寬到 **2500 ms**(未合併時的預設值為 500 ms)。較寬的視窗是必要的,因為 Apple 的分段傳送節奏為 0.8-2.0 秒,無法放入較短的預設值。 + + 若要自行調整視窗: + + ```json5 + { + messages: { + inbound: { + byChannel: { + // 2500 ms works for most setups; raise to 4000 ms if your Mac is slow + // or under memory pressure (observed gap can stretch past 2 s then). + bluebubbles: 2500, + }, + }, + }, + } + ``` + + + + - **DM 控制指令會增加延遲。** 啟用此旗標後,DM 控制指令訊息(例如 `Dump`、`Save` 等)現在會等待最多到防抖視窗結束再派送,以防酬載 Webhook 即將到來。群組聊天指令會保持立即派送。 + - **合併輸出有界限** — 合併文字上限為 4000 字元,並帶有明確的 `…[truncated]` 標記;附件上限為 20;來源項目上限為 10(超過後保留第一個加最新的項目)。每個來源 `messageId` 仍會進入傳入去重,因此稍後 MessagePoller 重新播放任何個別事件時,都會被辨識為重複。 + - **選擇加入,按頻道設定。** 其他頻道(Telegram、WhatsApp、Slack、…)不受影響。 + + + + +### 場景與代理看到的內容 + +| 使用者組合內容 | Apple 投遞 | 關閉旗標(預設) | 開啟旗標 + 2500 ms 視窗 | +| ------------------------------------------------------------------ | ------------------------- | --------------------------------------- | ----------------------------------------------------------------------- | +| `Dump https://example.com`(一次傳送) | 約相隔 1 秒的 2 個 Webhook | 兩個代理回合:只有 "Dump",接著是 URL | 一個回合:合併文字 `Dump https://example.com` | +| `Save this 📎image.jpg caption`(附件 + 文字) | 2 個 Webhook | 兩個回合 | 一個回合:文字 + 圖片 | +| `/status`(獨立指令) | 1 個 Webhook | 立即派送 | **等待最多到視窗結束,然後派送** | +| 單獨貼上的 URL | 1 個 Webhook | 立即派送 | 立即派送(桶中只有一個項目) | +| 文字 + URL 以兩則刻意分開的訊息傳送,相隔數分鐘 | 視窗外的 2 個 Webhook | 兩個回合 | 兩個回合(視窗在兩者之間到期) | +| 快速大量湧入(視窗內 >10 則小型 DM) | N 個 Webhook | N 個回合 | 一個回合,有界限的輸出(套用第一個 + 最新、文字/附件上限) | + +### 分段傳送合併疑難排解 + +如果旗標已開啟,但分段傳送仍以兩個回合抵達,請檢查每一層: + + + + ``` + grep coalesceSameSenderDms ~/.openclaw/openclaw.json + ``` + + 然後執行 `openclaw gateway restart` — 此旗標會在建立防抖器註冊表時讀取。 + + + + 查看 `~/Library/Logs/bluebubbles-server/main.log` 下的 BlueBubbles 伺服器日誌: + + ``` + grep -E "Dispatching event to webhook" main.log | tail -20 + ``` + + 測量 `"Dump"` 風格文字派送與後續 `"https://..."; Attachments:` 派送之間的間隔。將 `messages.inbound.byChannel.bluebubbles` 提高到能從容涵蓋該間隔的值。 + + + + 工作階段事件時間戳(`~/.openclaw/agents//sessions/*.jsonl`)反映 Gateway 將訊息交給代理的時間,**不是** Webhook 抵達的時間。標記為 `[Queued messages while agent was busy]` 的已佇列第二則訊息,表示第二個 Webhook 抵達時第一回合仍在執行,合併桶已經清空。請根據 BB 伺服器日誌調整視窗,而不是工作階段日誌。 + + + 在較小的機器(8 GB)上,代理回合可能會花很久,導致合併桶在回覆完成前清空,而 URL 會以已佇列的第二回合進入。檢查 `memory_pressure` 和 `ps -o rss -p $(pgrep openclaw-gateway)`;如果 Gateway 超過約 500 MB RSS 且壓縮器正在作用,請關閉其他高負載程序或改用更大的主機。 + + + 如果使用者點選 `Dump` 作為既有 URL 氣泡的**回覆**(iMessage 在 Dump 氣泡上顯示「1 Reply」徽章),URL 會位於 `replyToBody`,而不是第二個 Webhook 中。合併不適用 — 那是 Skills/提示詞問題,不是防抖器問題。 + + + +## 區塊串流 + +控制回覆要以單一訊息傳送,或以區塊串流傳送: + +```json5 +{ + channels: { + bluebubbles: { + blockStreaming: true, // enable block streaming (off by default) + }, + }, +} +``` + +## 媒體 + 限制 + +- 傳入附件會下載並儲存在媒體快取中。 +- 透過 `channels.bluebubbles.mediaMaxMb` 設定傳入與傳出媒體的媒體上限(預設值:8 MB)。 +- 傳出文字會依 `channels.bluebubbles.textChunkLimit` 分段(預設值:4000 字元)。 + +## 設定參考 + +完整設定:[設定](/zh-TW/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`:DM 允許清單(帳號、電子郵件、E.164 號碼、`chat_id:*`、`chat_guid:*`)。 + - `channels.bluebubbles.groupPolicy`:`open | allowlist | disabled`(預設值:`allowlist`)。 + - `channels.bluebubbles.groupAllowFrom`:群組寄件者允許清單。 + - `channels.bluebubbles.enrichGroupParticipantsFromContacts`:在 macOS 上,通過門檻檢查後,可選擇從本機「聯絡人」補充未命名群組參與者。預設值:`false`。 + - `channels.bluebubbles.groups`:每個群組的設定(`requireMention` 等)。 + + + + - `channels.bluebubbles.sendReadReceipts`: 傳送已讀回條(預設:`true`)。 + - `channels.bluebubbles.blockStreaming`: 啟用區塊串流(預設:`false`;串流回覆需要此項)。 + - `channels.bluebubbles.textChunkLimit`: 外送分塊大小,以字元數計(預設:4000)。 + - `channels.bluebubbles.sendTimeoutMs`: 透過 `/api/v1/message/text` 傳送外送文字時,每個請求的逾時時間,以毫秒計(預設:30000)。在 macOS 26 設定中,如果 Private API iMessage 傳送可能在 iMessage framework 內停滯 60 秒以上,請提高此值;例如 `45000` 或 `60000`。探測、聊天查找、反應、編輯和健康檢查目前仍保留較短的 10 秒預設值;後續計畫將涵蓋範圍擴大到反應和編輯。每個帳號覆寫:`channels.bluebubbles.accounts..sendTimeoutMs`。 + - `channels.bluebubbles.chunkMode`: `length`(預設)只會在超過 `textChunkLimit` 時分割;`newline` 會先依空白行(段落邊界)分割,再按長度分塊。 + + + + - `channels.bluebubbles.mediaMaxMb`: 傳入/傳出媒體上限,以 MB 計(預設:8)。 + - `channels.bluebubbles.mediaLocalRoots`: 明確允許用於傳出本機媒體路徑的絕對本機目錄允許清單。除非已設定此項,否則預設拒絕傳送本機路徑。每個帳號覆寫:`channels.bluebubbles.accounts..mediaLocalRoots`。 + - `channels.bluebubbles.coalesceSameSenderDms`: 將連續的同一寄件者 DM Webhook 合併成一次代理回合,讓 Apple 的文字+URL 分割傳送以單一訊息抵達(預設:`false`)。請參閱[合併分割傳送的 DM](#coalescing-split-send-dms-command--url-in-one-composition),了解情境、視窗調整與取捨。啟用時若未明確設定 `messages.inbound.byChannel.bluebubbles`,會將預設傳入防抖視窗從 500 ms 擴大到 2500 ms。 + - `channels.bluebubbles.historyLimit`: 內容脈絡的群組訊息數上限(0 會停用)。 + - `channels.bluebubbles.dmHistoryLimit`: DM 歷史記錄限制。 + + + + - `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:...` +- 直接 handle:`+15555550123`、`user@example.com` + - 如果直接 handle 沒有既有的 DM 聊天,OpenClaw 會透過 `POST /api/v1/chat/new` 建立一個。這需要啟用 BlueBubbles Private API。 + +### iMessage 與 SMS 路由 + +當同一個 handle 在 Mac 上同時有 iMessage 和 SMS 聊天時(例如某個電話號碼已註冊 iMessage,但也曾收到綠色氣泡備援),OpenClaw 會優先使用 iMessage 聊天,且絕不會默默降級為 SMS。若要強制使用 SMS 聊天,請使用明確的 `sms:` 目標前綴(例如 `sms:+15555550123`)。沒有相符 iMessage 聊天的 handle 仍會透過 BlueBubbles 回報的任何聊天傳送。 + +## 安全性 + +- Webhook 請求會透過比較 `guid`/`password` 查詢參數或標頭與 `channels.bluebubbles.password` 來驗證。 +- 請將 API 密碼和 Webhook 端點保密(視同憑證處理)。 +- BlueBubbles Webhook 驗證沒有 localhost 繞過。如果你代理 Webhook 流量,請在請求端到端保留 BlueBubbles 密碼。此處的 `gateway.trustedProxies` 不會取代 `channels.bluebubbles.password`。請參閱 [Gateway 安全性](/zh-TW/gateway/security#reverse-proxy-configuration)。 +- 如果要將 BlueBubbles 伺服器暴露到 LAN 外,請啟用 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` 手動停用它。 +- 已啟用 `coalesceSameSenderDms`,但分割傳送(例如 `Dump` + URL)仍以兩個回合抵達:請參閱[分割傳送合併疑難排解](#split-send-coalescing-troubleshooting)檢查清單 — 常見原因包括防抖視窗太短、將工作階段記錄時間戳誤讀為 Webhook 抵達時間,或回覆引用傳送(其使用 `replyToBody`,而不是第二個 Webhook)。 +- 如需狀態/健康資訊:`openclaw status --all` 或 `openclaw status --deep`。 + +如需一般頻道工作流程參考,請參閱[頻道](/zh-TW/channels)和 [Plugin](/zh-TW/tools/plugin) 指南。 + +## 相關 + +- [頻道路由](/zh-TW/channels/channel-routing) — 訊息的工作階段路由 +- [頻道概觀](/zh-TW/channels) — 所有支援的頻道 +- [群組](/zh-TW/channels/groups) — 群組聊天行為與提及閘控 +- [配對](/zh-TW/channels/pairing) — DM 驗證與配對流程 +- [安全性](/zh-TW/gateway/security) — 存取模型與強化 diff --git a/docs/zh-TW/channels/broadcast-groups.md b/docs/zh-TW/channels/broadcast-groups.md new file mode 100644 index 000000000..7d62693b0 --- /dev/null +++ b/docs/zh-TW/channels/broadcast-groups.md @@ -0,0 +1,477 @@ +--- +read_when: + - 設定廣播群組 + - 偵錯 WhatsApp 中的多代理回覆 +sidebarTitle: Broadcast groups +status: experimental +summary: 將 WhatsApp 訊息廣播給多個代理程式 +title: 廣播群組 +x-i18n: + generated_at: "2026-04-30T02:45:59Z" + model: gpt-5.5 + provider: openai + source_hash: b0de4ccc85bf79e2ceb1dddd60db067309b15b7f876c92e7d591ff0b4b4315ec + source_path: channels/broadcast-groups.md + workflow: 16 +--- + + +**狀態:** 實驗性。已於 2026.1.9 新增。 + + +## 概覽 + +廣播群組可讓多個代理同時處理並回應同一則訊息。這讓你能建立專門化的代理團隊,在單一 WhatsApp 群組或私訊中協同工作,而且全都使用同一個電話號碼。 + +目前範圍:**僅限 WhatsApp**(網頁通道)。 + +廣播群組會在通道允許清單與群組啟用規則之後評估。在 WhatsApp 群組中,這表示當 OpenClaw 通常會回覆時就會發生廣播(例如:提及時,取決於你的群組設定)。 + +## 使用案例 + + + + 部署多個具備原子化、聚焦職責的代理: + + ``` + Group: "Development Team" + Agents: + - CodeReviewer (reviews code snippets) + - DocumentationBot (generates docs) + - SecurityAuditor (checks for vulnerabilities) + - TestGenerator (suggests test cases) + ``` + + 每個代理都會處理同一則訊息,並提供其專門觀點。 + + + + ``` + Group: "International Support" + Agents: + - Agent_EN (responds in English) + - Agent_DE (responds in German) + - Agent_ES (responds in Spanish) + ``` + + + ``` + Group: "Customer Support" + Agents: + - SupportAgent (provides answer) + - QAAgent (reviews quality, only responds if issues found) + ``` + + + ``` + Group: "Project Management" + Agents: + - TaskTracker (updates task database) + - TimeLogger (logs time spent) + - ReportGenerator (creates summaries) + ``` + + + +## 設定 + +### 基本設定 + +新增頂層 `broadcast` 區段(與 `bindings` 並列)。鍵是 WhatsApp 對等端 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"] + } +} +``` + +## 運作方式 + +### 訊息流程 + + + + WhatsApp 群組或私訊訊息抵達。 + + + 系統檢查對等端 ID 是否在 `broadcast` 中。 + + + - 所有列出的代理都會處理該訊息。 + - 每個代理都有自己的工作階段鍵與隔離的情境。 + - 代理會平行處理(預設)或依序處理。 + + + + 套用一般路由(第一個相符的繫結)。 + + + + +廣播群組不會繞過通道允許清單或群組啟用規則(提及/命令等)。它們只會在訊息符合處理資格時,變更_哪些代理會執行_。 + + +### 工作階段隔離 + +廣播群組中的每個代理都會維持完全獨立的: + +- **工作階段鍵**(`agent:alfred:whatsapp:group:120363...` 相對於 `agent:baerbel:whatsapp:group:120363...`) +- **對話歷史**(代理看不到其他代理的訊息) +- **工作區**(如有設定,則使用獨立沙箱) +- **工具存取權**(不同的允許/拒絕清單) +- **記憶/情境**(獨立的 IDENTITY.md、SOUL.md 等) +- **群組情境緩衝區**(用於情境的近期群組訊息)會依對等端共享,因此所有廣播代理在觸發時都會看到相同情境 + +這讓每個代理都能擁有: + +- 不同個性 +- 不同工具存取權(例如唯讀與可讀寫) +- 不同模型(例如 opus 與 sonnet) +- 安裝不同 Skills + +### 範例:隔離的工作階段 + +在群組 `120363403215116621@g.us` 中,代理為 `["alfred", "baerbel"]`: + + + + ``` + Session: agent:alfred:whatsapp:group:120363403215116621@g.us + History: [user message, alfred's previous responses] + Workspace: /Users/user/openclaw-alfred/ + Tools: read, write, exec + ``` + + + ``` + Session: agent:baerbel:whatsapp:group:120363403215116621@g.us + History: [user message, baerbel's previous responses] + Workspace: /Users/user/openclaw-baerbel/ + Tools: read only + ``` + + + +## 最佳實務 + + + + 以單一、明確的職責設計每個代理: + + ```json + { + "broadcast": { + "DEV_GROUP": ["formatter", "linter", "tester"] + } + } + ``` + + ✅ **良好:** 每個代理都有一項工作。❌ **不佳:** 一個通用的「dev-helper」代理。 + + + + 讓每個代理的用途清楚明瞭: + + ```json + { + "agents": { + "security-scanner": { "name": "Security Scanner" }, + "code-formatter": { "name": "Code Formatter" }, + "test-generator": { "name": "Test Generator" } + } + } + ``` + + + + 只提供代理所需的工具: + + ```json + { + "agents": { + "reviewer": { + "tools": { "allow": ["read", "exec"] } // Read-only + }, + "fixer": { + "tools": { "allow": ["read", "write", "edit", "exec"] } // Read-write + } + } + } + ``` + + + + 使用多個代理時,請考慮: + + - 使用 `"strategy": "parallel"`(預設)以提高速度 + - 將廣播群組限制為 5 到 10 個代理 + - 為較簡單的代理使用較快的模型 + + + + 代理會獨立失敗。一個代理的錯誤不會阻擋其他代理: + + ``` + Message → [Agent A ✓, Agent B ✗ error, Agent C ✓] + Result: Agent A and C respond, Agent B logs error + ``` + + + + +## 相容性 + +### 提供者 + +廣播群組目前可搭配: + +- ✅ 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. 對等端 ID 格式正確(例如 `120363403215116621@g.us`)。 + 3. 代理不在拒絕清單中。 + + **偵錯:** + + ```bash + tail -f ~/.openclaw/logs/gateway.log | grep broadcast + ``` + + + + **原因:** 對等端 ID 可能在 `bindings` 中,但不在 `broadcast` 中。 + + **修正:** 新增到廣播設定,或從繫結中移除。 + + + + 如果多個代理導致速度緩慢: + + - 減少每個群組的代理數量。 + - 使用較輕量的模型(使用 sonnet 而非 opus)。 + - 檢查沙箱啟動時間。 + + + + +## 範例 + + + + ```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 injection 弱點」 + - test-coverage:「覆蓋率為 45%,缺少錯誤案例的測試」 + - docs-checker:「函式 `process_data` 缺少 docstring」 + + + + ```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[]; + }; +} +``` + +### 欄位 + + + 如何處理代理。`parallel` 會同時執行所有代理;`sequential` 會依陣列順序執行它們。 + + + WhatsApp 群組 JID、E.164 號碼,或其他對等端 ID。值是應處理訊息的代理 ID 陣列。 + + +## 限制 + +1. **代理上限:** 沒有硬性限制,但 10 個以上的代理可能會較慢。 +2. **共享情境:** 代理看不到彼此的回應(這是刻意設計)。 +3. **訊息排序:** 平行回應可能以任何順序抵達。 +4. **速率限制:** 所有代理都會計入 WhatsApp 速率限制。 + +## 未來增強 + +規劃中的功能: + +- [ ] 共享情境模式(代理可看到彼此的回應) +- [ ] 代理協調(代理可彼此發送訊號) +- [ ] 動態代理選擇(根據訊息內容選擇代理) +- [ ] 代理優先順序(某些代理會先於其他代理回應) + +## 相關內容 + +- [通道路由](/zh-TW/channels/channel-routing) +- [群組](/zh-TW/channels/groups) +- [多代理沙箱工具](/zh-TW/tools/multi-agent-sandbox-tools) +- [配對](/zh-TW/channels/pairing) +- [工作階段管理](/zh-TW/concepts/session) diff --git a/docs/zh-TW/channels/channel-routing.md b/docs/zh-TW/channels/channel-routing.md new file mode 100644 index 000000000..03a52b2a7 --- /dev/null +++ b/docs/zh-TW/channels/channel-routing.md @@ -0,0 +1,157 @@ +--- +read_when: + - 變更頻道路由或收件匣行為 +summary: 每個通道(WhatsApp、Telegram、Discord、Slack)的路由規則和共用上下文 +title: 通道路由 +x-i18n: + generated_at: "2026-04-30T02:46:00Z" + model: gpt-5.5 + provider: openai + source_hash: c43347048fcfd137cc3a0b2cfdc4cf36426fdcf9645f2d1a05ce9cf49688cf0d + source_path: channels/channel-routing.md + workflow: 16 +--- + +# 頻道與路由 + +OpenClaw 會將回覆路由**回訊息來源的頻道**。模型不會選擇頻道;路由是確定性的,並由主機設定控制。 + +## 關鍵術語 + +- **頻道**:`telegram`、`whatsapp`、`discord`、`irc`、`googlechat`、`slack`、`signal`、`imessage`、`line`,以及 Plugin 頻道。`webchat` 是內部 WebChat UI 頻道,不是可設定的對外頻道。 +- **AccountId**:每個頻道的帳號實例(支援時)。 +- 選用的頻道預設帳號:`channels..defaultAccount` 會選擇 + 當對外路徑未指定 `accountId` 時使用哪個帳號。 + - 在多帳號設定中,當設定了兩個以上帳號時,請設定明確的預設值(`defaultAccount` 或 `accounts.default`)。若未設定,後援路由可能會選擇第一個正規化的帳號 ID。 +- **AgentId**:隔離的工作區 + 工作階段儲存區(「大腦」)。 +- **SessionKey**:用於儲存脈絡並控制並行性的桶鍵。 + +## 工作階段鍵形狀(範例) + +直接訊息預設會折疊到代理的 **main** 工作階段: + +- `agent::`(預設:`agent:main:main`) + +即使直接訊息對話歷史與 main 共用,沙盒與工具政策仍會針對外部 DM 使用衍生的每帳號直接聊天執行階段鍵, +因此來自頻道的訊息不會被視為本機 main 工作階段執行。 + +群組與頻道會依頻道維持隔離: + +- 群組:`agent:::group:` +- 頻道/聊天室:`agent:::channel:` + +執行緒: + +- Slack/Discord 執行緒會將 `:thread:` 附加到基礎鍵。 +- Telegram 論壇主題會在群組鍵中嵌入 `:topic:`。 + +範例: + +- `agent:main:telegram:group:-1001234567890:topic:42` +- `agent:main:discord:channel:123456:thread:987654` + +## Main DM 路由釘選 + +當 `session.dmScope` 為 `main` 時,直接訊息可能會共用一個 main 工作階段。 +為了防止工作階段的 `lastRoute` 被非擁有者 DM 覆寫, +當下列條件全部成立時,OpenClaw 會從 `allowFrom` 推斷釘選擁有者: + +- `allowFrom` 恰好有一個非萬用字元項目。 +- 該項目可正規化為該頻道的具體寄件者 ID。 +- 傳入的 DM 寄件者不符合該釘選擁有者。 + +在這種不相符的情況下,OpenClaw 仍會記錄傳入工作階段中繼資料,但會 +略過更新 main 工作階段的 `lastRoute`。 + +## 受保護的傳入記錄 + +當受保護路徑不得建立新的 OpenClaw 工作階段時,頻道 Plugin 可將傳入工作階段記錄標示為 `createIfMissing: false`。 +在此模式下,OpenClaw 可能會更新既有工作階段的中繼資料與 `lastRoute`,但不會 +只因為觀察到訊息就建立僅含路由的工作階段項目。 + +## 路由規則(如何選擇代理) + +路由會為每則傳入訊息選擇**一個代理**: + +1. **精確對等方符合**(含 `peer.kind` + `peer.id` 的 `bindings`)。 +2. **父對等方符合**(執行緒繼承)。 +3. **Guild + 角色符合**(Discord),透過 `guildId` + `roles`。 +4. **Guild 符合**(Discord),透過 `guildId`。 +5. **團隊符合**(Slack),透過 `teamId`。 +6. **帳號符合**(頻道上的 `accountId`)。 +7. **頻道符合**(該頻道上的任何帳號,`accountId: "*"`)。 +8. **預設代理**(`agents.list[].default`,否則第一個清單項目,後援為 `main`)。 + +當綁定包含多個符合欄位(`peer`、`guildId`、`teamId`、`roles`)時,**所有提供的欄位都必須符合**,該綁定才會套用。 + +符合的代理會決定要使用哪個工作區與工作階段儲存區。 + +## 廣播群組(執行多個代理) + +廣播群組可讓你針對同一個對等方**執行多個代理**,條件是 **OpenClaw 通常會回覆**(例如:在 WhatsApp 群組中,通過提及/啟用閘門之後)。 + +設定: + +```json5 +{ + broadcast: { + strategy: "parallel", + "120363403215116621@g.us": ["alfred", "baerbel"], + "+15555550123": ["support", "logger"], + }, +} +``` + +請參閱:[廣播群組](/zh-TW/channels/broadcast-groups)。 + +## 設定概覽 + +- `agents.list`:具名代理定義(工作區、模型等)。 +- `bindings`:將傳入頻道/帳號/對等方對應到代理。 + +範例: + +```json5 +{ + agents: { + list: [{ id: "support", name: "Support", workspace: "~/.openclaw/workspace-support" }], + }, + bindings: [ + { match: { channel: "slack", teamId: "T123" }, agentId: "support" }, + { match: { channel: "telegram", peer: { kind: "group", id: "-100123" } }, agentId: "support" }, + ], +} +``` + +## 工作階段儲存 + +工作階段儲存區位於狀態目錄下(預設為 `~/.openclaw`): + +- `~/.openclaw/agents//sessions/sessions.json` +- JSONL 逐字稿會與儲存區並列存放 + +你可以透過 `session.store` 與 `{agentId}` 模板化覆寫儲存區路徑。 + +Gateway 與 ACP 工作階段探索也會掃描預設 `agents/` 根目錄下,以及模板化 `session.store` 根目錄下的磁碟支援代理儲存區。探索到的 +儲存區必須維持在該解析後的代理根目錄內,並使用一般的 +`sessions.json` 檔案。符號連結與根目錄外路徑會被忽略。 + +## WebChat 行為 + +WebChat 會附加到**選取的代理**,並預設使用該代理的 main +工作階段。因此,WebChat 可讓你在同一處查看該代理的跨頻道脈絡。 + +## 回覆脈絡 + +傳入回覆會包含: + +- 可用時包含 `ReplyToId`、`ReplyToBody` 與 `ReplyToSender`。 +- 引用脈絡會作為 `[Replying to ...]` 區塊附加到 `Body`。 + +這在各頻道之間保持一致。 + +## 相關 + +- [群組](/zh-TW/channels/groups) +- [廣播群組](/zh-TW/channels/broadcast-groups) +- [配對](/zh-TW/channels/pairing) diff --git a/docs/zh-TW/channels/discord.md b/docs/zh-TW/channels/discord.md new file mode 100644 index 000000000..2a751c445 --- /dev/null +++ b/docs/zh-TW/channels/discord.md @@ -0,0 +1,1267 @@ +--- +read_when: + - 開發 Discord 頻道功能 +summary: Discord 機器人支援狀態、功能與設定 +title: Discord +x-i18n: + generated_at: "2026-04-30T02:45:58Z" + model: gpt-5.5 + provider: openai + source_hash: e9f31af2801e7faf6456d4452a5f43b0e42a067b86b7e562c308fa450a847356 + source_path: channels/discord.md + workflow: 16 +--- + +準備好透過官方 Discord Gateway 用於私訊和伺服器頻道。 + + + + Discord 私訊預設為配對模式。 + + + 原生指令行為與指令目錄。 + + + 跨頻道診斷與修復流程。 + + + +## 快速設定 + +你需要建立一個包含 Bot 的新應用程式、將 Bot 加入你的伺服器,並將它配對到 OpenClaw。我們建議將 Bot 加入你自己的私人伺服器。如果你還沒有伺服器,請[先建立一個](https://support.discord.com/hc/en-us/articles/204849977-How-do-I-create-a-server)(選擇 **建立我自己的 > 給我和我的朋友**)。 + + + + 前往 [Discord Developer Portal](https://discord.com/developers/applications),然後點選 **New Application**。將它命名為類似「OpenClaw」的名稱。 + + 在側邊欄點選 **Bot**。將 **Username** 設為你給 OpenClaw 代理程式取的名稱。 + + + + + 仍在 **Bot** 頁面上,向下捲動到 **Privileged Gateway Intents** 並啟用: + + - **Message Content Intent**(必要) + - **Server Members Intent**(建議;角色允許清單與名稱對 ID 比對需要) + - **Presence Intent**(選用;只有在需要狀態更新時才需要) + + + + + 在 **Bot** 頁面往回捲到上方,然後點選 **Reset Token**。 + + + 儘管名稱如此,這會產生你的第一個 token,並不是真的在「重設」任何東西。 + + + 複製 token 並儲存在某處。這是你的 **Bot Token**,稍後會用到。 + + + + + 在側邊欄點選 **OAuth2**。你會產生一個具備正確權限的邀請 URL,用來將 Bot 加入你的伺服器。 + + 向下捲動到 **OAuth2 URL Generator** 並啟用: + + - `bot` + - `applications.commands` + + 下方會出現 **Bot Permissions** 區段。至少啟用: + + **一般權限** + - 檢視頻道 + **文字權限** + - 傳送訊息 + - 讀取訊息歷史 + - 嵌入連結 + - 附加檔案 + - 新增回應(選用) + + 這是一般文字頻道的基準設定。如果你打算在 Discord 討論串中發文,包括會建立或延續討論串的論壇或媒體頻道工作流程,也請啟用 **在討論串中傳送訊息**。 + 複製底部產生的 URL,貼到瀏覽器中,選取你的伺服器,然後點選 **繼續** 以連線。現在你應該會在 Discord 伺服器中看到你的 Bot。 + + + + + 回到 Discord 應用程式,你需要啟用開發者模式,才能複製內部 ID。 + + 1. 點選 **使用者設定**(你頭像旁的齒輪圖示)→ **進階** → 開啟 **開發者模式** + 2. 在側邊欄右鍵點選你的 **伺服器圖示** → **複製伺服器 ID** + 3. 右鍵點選你 **自己的頭像** → **複製使用者 ID** + + 將你的 **Server ID** 和 **User ID** 與 Bot Token 一起儲存,下一步你會把這三者都傳給 OpenClaw。 + + + + + 若要讓配對運作,Discord 需要允許你的 Bot 傳送私訊給你。右鍵點選你的 **伺服器圖示** → **隱私設定** → 開啟 **私訊**。 + + 這會讓伺服器成員(包括 Bot)可以傳送私訊給你。如果你想透過 Discord 私訊使用 OpenClaw,請保持啟用。如果你只打算使用伺服器頻道,可以在配對後停用私訊。 + + + + + 你的 Discord Bot token 是機密資訊(就像密碼)。在傳訊息給代理程式之前,請先在執行 OpenClaw 的機器上設定它。 + +```bash +export DISCORD_BOT_TOKEN="YOUR_BOT_TOKEN" +cat > discord.patch.json5 <<'JSON5' +{ + channels: { + discord: { + enabled: true, + token: { source: "env", provider: "default", id: "DISCORD_BOT_TOKEN" }, + }, + }, +} +JSON5 +openclaw config patch --file ./discord.patch.json5 --dry-run +openclaw config patch --file ./discord.patch.json5 +openclaw gateway +``` + + 如果 OpenClaw 已經以背景服務執行,請透過 OpenClaw Mac app 或停止並重新啟動 `openclaw gateway run` 行程來重新啟動它。 + 對於受管理的服務安裝,請從存在 `DISCORD_BOT_TOKEN` 的 shell 執行 `openclaw gateway install`,或將變數儲存在 `~/.openclaw/.env`,讓服務在重新啟動後能解析 env SecretRef。 + 如果你的主機受到 Discord 啟動應用程式查詢封鎖或速率限制,請從 Developer Portal 設定 Discord 應用程式/client ID,讓啟動可以略過該 REST 呼叫。預設帳戶請使用 `channels.discord.applicationId`;執行多個 Discord Bot 時,請使用 `channels.discord.accounts..applicationId`。 + + + + + + + + 在任何既有頻道(例如 Telegram)與你的 OpenClaw 代理程式聊天並告訴它。如果 Discord 是你的第一個頻道,請改用 CLI / config 分頁。 + + >「我已經在 config 中設定 Discord Bot token。請使用 User ID `` 和 Server ID `` 完成 Discord 設定。」 + + + 如果你偏好以檔案為基礎的 config,請設定: + +```json5 +{ + channels: { + discord: { + enabled: true, + token: { + source: "env", + provider: "default", + id: "DISCORD_BOT_TOKEN", + }, + }, + }, +} +``` + + 預設帳戶的 env 備援: + +```bash +DISCORD_BOT_TOKEN=... +``` + + 對於腳本化或遠端設定,請使用 `openclaw config patch --file ./discord.patch.json5 --dry-run` 寫入相同的 JSON5 區塊,然後不帶 `--dry-run` 重新執行。支援純文字 `token` 值。`channels.discord.token` 也支援跨 env/file/exec provider 的 SecretRef 值。請參閱[機密管理](/zh-TW/gateway/secrets)。 + + 若使用多個 Discord Bot,請將每個 Bot token 和 application ID 放在其帳戶之下。頂層的 `channels.discord.applicationId` 會由帳戶繼承,因此只有在每個帳戶都應使用相同 application ID 時,才在該處設定。 + +```json5 +{ + channels: { + discord: { + enabled: true, + accounts: { + personal: { + token: { source: "env", provider: "default", id: "DISCORD_PERSONAL_TOKEN" }, + applicationId: "111111111111111111", + }, + work: { + token: { source: "env", provider: "default", id: "DISCORD_WORK_TOKEN" }, + applicationId: "222222222222222222", + }, + }, + }, + }, +} +``` + + + + + + + + 等到 Gateway 正在執行,然後在 Discord 中傳私訊給你的 Bot。它會回覆一組配對代碼。 + + + + 在既有頻道將配對代碼傳給你的代理程式: + + >「核准這個 Discord 配對代碼:``」 + + + +```bash +openclaw pairing list discord +openclaw pairing approve discord +``` + + + + + 配對代碼會在 1 小時後過期。 + + 現在你應該可以透過私訊在 Discord 中與代理程式聊天。 + + + + + +Token 解析會感知帳戶。Config token 值優先於 env 備援。`DISCORD_BOT_TOKEN` 只會用於預設帳戶。 +如果兩個已啟用的 Discord 帳戶解析到相同的 Bot token,OpenClaw 只會為該 token 啟動一個 Gateway 監視器。來自 config 的 token 優先於預設 env 備援;否則第一個已啟用的帳戶會勝出,重複帳戶會回報為已停用。 +對於進階外送呼叫(message tool/頻道動作),明確的逐次呼叫 `token` 會用於該呼叫。這適用於傳送與讀取/探測類動作(例如 read/search/fetch/thread/pins/permissions)。帳戶政策/重試設定仍來自作用中執行階段快照中選取的帳戶。 + + +## 建議:設定伺服器工作區 + +私訊開始運作後,你可以將 Discord 伺服器設定為完整工作區,讓每個頻道都有自己的代理程式工作階段與自己的情境。這建議用於只有你和 Bot 的私人伺服器。 + + + + 這會讓你的代理程式能在伺服器上的任何頻道回應,而不只是私訊。 + + + + >「將我的 Discord Server ID `` 加入伺服器允許清單」 + + + +```json5 +{ + channels: { + discord: { + groupPolicy: "allowlist", + guilds: { + YOUR_SERVER_ID: { + requireMention: true, + users: ["YOUR_USER_ID"], + }, + }, + }, + }, +} +``` + + + + + + + + 預設情況下,只有在伺服器頻道中被 @mentioned 時,你的代理程式才會回應。對於私人伺服器,你可能希望它回應每則訊息。 + + 在伺服器頻道中,一般助理最終回覆預設會保持私密。可見的 Discord 輸出必須明確使用 `message` tool 傳送,因此代理程式可以預設旁觀,只有在判斷頻道回覆有用時才發文。 + + + + >「允許我的代理程式在這個伺服器上回應,而不必被 @mentioned」 + + + 在你的伺服器 config 中設定 `requireMention: false`: + +```json5 +{ + channels: { + discord: { + guilds: { + YOUR_SERVER_ID: { + requireMention: false, + }, + }, + }, + }, +} +``` + + 若要還原群組/頻道聊天室的舊版自動最終回覆,請設定 `messages.groupChat.visibleReplies: "automatic"`。 + + + + + + + + 預設情況下,長期記憶(MEMORY.md)只會在私訊工作階段中載入。伺服器頻道不會自動載入 MEMORY.md。 + + + + >「當我在 Discord 頻道中提問時,如果你需要 MEMORY.md 的長期情境,請使用 memory_search 或 memory_get。」 + + + 如果你需要在每個頻道中使用共享情境,請將穩定的指示放在 `AGENTS.md` 或 `USER.md`(它們會注入每個工作階段)。將長期筆記保留在 `MEMORY.md`,並依需求透過記憶工具存取。 + + + + + + +現在在你的 Discord 伺服器上建立一些頻道並開始聊天。你的代理程式可以看到頻道名稱,而且每個頻道都有自己的隔離工作階段,所以你可以設定 `#coding`、`#home`、`#research`,或任何符合你工作流程的頻道。 + +## 執行階段模型 + +- Gateway 擁有 Discord 連線。 +- 回覆路由是確定性的:Discord 傳入回覆會回到 Discord。 +- Discord 伺服器/頻道中繼資料會以不受信任的 + 脈絡加入模型提示,而不是作為使用者可見的回覆前綴。如果模型把該封套 + 複製回來,OpenClaw 會從傳出回覆和 + 之後的重播脈絡中移除複製的中繼資料。 +- 預設情況下(`session.dmScope=main`),直接聊天會共用代理程式主工作階段(`agent:main:main`)。 +- 伺服器頻道會使用隔離的工作階段鍵(`agent::discord:channel:`)。 +- 群組 DM 預設會被忽略(`channels.discord.dm.groupEnabled=false`)。 +- 原生斜線命令會在隔離的命令工作階段中執行(`agent::discord:slash:`),同時仍會攜帶 `CommandTargetSessionKey` 到路由後的對話工作階段。 +- 傳送到 Discord 的純文字 Cron/Heartbeat 公告會使用最終 + 助理可見答案一次。當代理程式發出多個可傳遞承載時,媒體和結構化元件承載仍會 + 以多則訊息傳送。 + +## 論壇頻道 + +Discord 論壇和媒體頻道只接受討論串貼文。OpenClaw 支援兩種建立方式: + +- 傳送訊息到論壇父層(`channel:`)以自動建立討論串。討論串標題會使用你訊息中的第一個非空白行。 +- 使用 `openclaw message thread create` 直接建立討論串。論壇頻道請不要傳入 `--message-id`。 + +範例:傳送到論壇父層以建立討論串 + +```bash +openclaw message send --channel discord --target channel: \ + --message "Topic title\nBody of the post" +``` + +範例:明確建立論壇討論串 + +```bash +openclaw message thread create --channel discord --target channel: \ + --thread-name "Topic title" --message "Body of the post" +``` + +論壇父層不接受 Discord 元件。如果需要元件,請傳送到討論串本身(`channel:`)。 + +## 互動式元件 + +OpenClaw 支援用於代理程式訊息的 Discord components v2 容器。請搭配含有 `components` 承載的訊息工具使用。互動結果會作為一般傳入訊息路由回代理程式,並遵循現有的 Discord `replyToMode` 設定。 + +支援的區塊: + +- `text`、`section`、`separator`、`actions`、`media-gallery`、`file` +- 動作列最多允許 5 個按鈕或一個選取選單 +- 選取類型:`string`、`user`、`role`、`mentionable`、`channel` + +預設情況下,元件只能使用一次。設定 `components.reusable=true` 可允許按鈕、選取和表單在到期前被多次使用。 + +若要限制誰可以點擊按鈕,請在該按鈕上設定 `allowedUsers`(Discord 使用者 ID、標籤或 `*`)。設定後,不符合的使用者會收到一則暫時性的拒絕訊息。 + +`/model` 和 `/models` 斜線命令會開啟互動式模型選擇器,其中包含提供者、模型與相容執行階段下拉選單,以及提交步驟。`/models add` 已棄用,現在會傳回棄用訊息,而不是從聊天註冊模型。選擇器回覆是暫時性的,且只有叫用的使用者可以使用。 + +檔案附件: + +- `file` 區塊必須指向附件參照(`attachment://`) +- 透過 `media`/`path`/`filePath` 提供附件(單一檔案);多個檔案請使用 `media-gallery` +- 當上傳名稱應與附件參照相符時,使用 `filename` 覆寫上傳名稱 + +互動視窗表單: + +- 加入最多含 5 個欄位的 `components.modal` +- 欄位類型:`text`、`checkbox`、`radio`、`select`、`role-select`、`user-select` +- OpenClaw 會自動加入觸發按鈕 + +範例: + +```json5 +{ + channel: "discord", + action: "send", + to: "channel:123456789012345678", + message: "Optional fallback text", + components: { + reusable: true, + text: "Choose a path", + blocks: [ + { + type: "actions", + buttons: [ + { + label: "Approve", + style: "success", + allowedUsers: ["123456789012345678"], + }, + { label: "Decline", style: "danger" }, + ], + }, + { + type: "actions", + select: { + type: "string", + placeholder: "Pick an option", + options: [ + { label: "Option A", value: "a" }, + { label: "Option B", value: "b" }, + ], + }, + }, + ], + modal: { + title: "Details", + triggerLabel: "Open form", + fields: [ + { type: "text", label: "Requester" }, + { + type: "select", + label: "Priority", + options: [ + { label: "Low", value: "low" }, + { label: "High", value: "high" }, + ], + }, + ], + }, + }, +} +``` + +## 存取控制與路由 + + + + `channels.discord.dmPolicy` 控制 DM 存取。`channels.discord.allowFrom` 是標準 DM 允許清單。 + + - `pairing`(預設) + - `allowlist` + - `open`(要求 `channels.discord.allowFrom` 包含 `"*"`) + - `disabled` + + 如果 DM 政策不是開放,未知使用者會被封鎖(或在 `pairing` 模式中提示配對)。 + + 多帳號優先順序: + + - `channels.discord.accounts.default.allowFrom` 只套用到 `default` 帳號。 + - 對於單一帳號,`allowFrom` 的優先順序高於舊版 `dm.allowFrom`。 + - 當具名帳號本身的 `allowFrom` 和舊版 `dm.allowFrom` 未設定時,會繼承 `channels.discord.allowFrom`。 + - 具名帳號不會繼承 `channels.discord.accounts.default.allowFrom`。 + + 仍會讀取舊版 `channels.discord.dm.policy` 和 `channels.discord.dm.allowFrom` 以維持相容性。`openclaw doctor --fix` 會在不改變存取權的情況下,盡可能將它們遷移到 `dmPolicy` 和 `allowFrom`。 + + 傳遞用的 DM 目標格式: + + - `user:` + - `<@id>` 提及 + + 當頻道預設值啟用時,裸數字 ID 通常會解析為頻道 ID,但列在帳號有效 DM `allowFrom` 中的 ID 會被視為使用者 DM 目標以維持相容性。 + + + + + 伺服器處理由 `channels.discord.groupPolicy` 控制: + + - `open` + - `allowlist` + - `disabled` + + 當 `channels.discord` 存在時,安全基準是 `allowlist`。 + + `allowlist` 行為: + + - 伺服器必須符合 `channels.discord.guilds`(建議使用 `id`,也接受 slug) + - 選用的傳送者允許清單:`users`(建議使用穩定 ID)和 `roles`(僅角色 ID);若設定其中任一項,傳送者符合 `users` 或 `roles` 時即被允許 + - 直接名稱/標籤比對預設停用;只有在緊急相容模式下才啟用 `channels.discord.dangerouslyAllowNameMatching: true` + - `users` 支援名稱/標籤,但 ID 較安全;使用名稱/標籤項目時,`openclaw security audit` 會發出警告 + - 如果伺服器設定了 `channels`,未列出的頻道會被拒絕 + - 如果伺服器沒有 `channels` 區塊,該允許清單伺服器中的所有頻道都會被允許 + + 範例: + +```json5 +{ + channels: { + discord: { + groupPolicy: "allowlist", + guilds: { + "123456789012345678": { + requireMention: true, + ignoreOtherMentions: true, + users: ["987654321098765432"], + roles: ["123456789012345678"], + channels: { + general: { allow: true }, + help: { allow: true, requireMention: true }, + }, + }, + }, + }, + }, +} +``` + + 如果你只設定 `DISCORD_BOT_TOKEN` 而未建立 `channels.discord` 區塊,執行階段後援會是 `groupPolicy="allowlist"`(並在記錄中發出警告),即使 `channels.defaults.groupPolicy` 是 `open` 也是如此。 + + + + + 伺服器訊息預設受提及閘門控管。 + + 提及偵測包含: + + - 明確提及 bot + - 已設定的提及模式(`agents.list[].groupChat.mentionPatterns`,後援為 `messages.groupChat.mentionPatterns`) + - 在支援案例中的隱含回覆 bot 行為 + + `requireMention` 依伺服器/頻道設定(`channels.discord.guilds...`)。 + `ignoreOtherMentions` 可選擇性丟棄提及其他使用者/角色但未提及 bot 的訊息(不含 @everyone/@here)。 + + 群組 DM: + + - 預設:忽略(`dm.groupEnabled=false`) + - 可選用透過 `dm.groupChannels` 設定允許清單(頻道 ID 或 slug) + + + + +### 以角色為基礎的代理程式路由 + +使用 `bindings[].match.roles` 依角色 ID 將 Discord 伺服器成員路由到不同代理程式。以角色為基礎的繫結只接受角色 ID,並且會在對等或父層對等繫結之後、僅限伺服器繫結之前評估。如果繫結也設定其他比對欄位(例如 `peer` + `guildId` + `roles`),所有已設定欄位都必須符合。 + +```json5 +{ + bindings: [ + { + agentId: "opus", + match: { + channel: "discord", + guildId: "123456789012345678", + roles: ["111111111111111111"], + }, + }, + { + agentId: "sonnet", + match: { + channel: "discord", + guildId: "123456789012345678", + }, + }, + ], +} +``` + +## 原生命令與命令授權 + +- `commands.native` 預設為 `"auto"`,並已為 Discord 啟用。 +- 依頻道覆寫:`channels.discord.commands.native`。 +- `commands.native=false` 會明確清除先前註冊的 Discord 原生命令。 +- 原生命令授權使用與一般訊息處理相同的 Discord 允許清單/政策。 +- 未授權的使用者可能仍會在 Discord UI 中看到命令;執行時仍會強制套用 OpenClaw 授權並傳回「未授權」。 + +請參閱[斜線命令](/zh-TW/tools/slash-commands)了解命令目錄與行為。 + +預設斜線命令設定: + +- `ephemeral: true` + +## 功能詳細資料 + + + + Discord 支援代理程式輸出中的回覆標籤: + + - `[[reply_to_current]]` + - `[[reply_to:]]` + + 由 `channels.discord.replyToMode` 控制: + + - `off`(預設) + - `first` + - `all` + - `batched` + + 注意:`off` 會停用隱含回覆討論串。明確的 `[[reply_to_*]]` 標籤仍會被遵循。 + `first` 一律會將隱含原生回覆參照附加到該回合的第一則傳出 Discord 訊息。 + `batched` 只有在傳入回合是多則訊息的防抖批次時,才會附加 Discord 的隱含原生回覆參照。當你主要想在不明確的密集聊天中使用原生回覆,而不是每個單一訊息回合都使用時,這很有用。 + + 訊息 ID 會在脈絡/歷史中呈現,讓代理程式可以指定特定訊息。 + + + + + OpenClaw 可透過傳送暫時訊息並在文字抵達時編輯它來串流草稿回覆。`channels.discord.streaming` 接受 `off`(預設)| `partial` | `block` | `progress`。在 Discord 上,`progress` 會對應到 `partial`;`streamMode` 是舊版別名,且會自動遷移。 + + 預設維持 `off`,因為當多個 bot 或 Gateway 共用一個帳號時,Discord 預覽編輯很快就會觸及速率限制。 + +```json5 +{ + channels: { + discord: { + streaming: "block", + draftChunk: { + minChars: 200, + maxChars: 800, + breakPreference: "paragraph", + }, + }, + }, +} +``` + + - `partial` 會在 token 抵達時編輯單一預覽訊息。 + - `block` 會發出草稿大小的區塊(使用 `draftChunk` 調整大小和斷點,並限制在 `textChunkLimit` 內)。 + - 媒體、錯誤和明確回覆的最終訊息會取消待處理的預覽編輯。 + - `streaming.preview.toolProgress`(預設 `true`)控制工具/進度更新是否重用預覽訊息。 + + 預覽串流僅限文字;媒體回覆會回退到一般傳遞。當明確啟用 `block` 串流時,OpenClaw 會略過預覽串流以避免雙重串流。 + + + + + 伺服器歷史脈絡: + + - `channels.discord.historyLimit` 預設 `20` + - 後援:`messages.groupChat.historyLimit` + - `0` 會停用 + + DM 歷史控制項: + + - `channels.discord.dmHistoryLimit` + - `channels.discord.dms[""].historyLimit` + + 執行緒行為: + + - Discord 執行緒會作為頻道工作階段路由,並繼承父頻道設定,除非被覆寫。 + - 執行緒工作階段會繼承父頻道的工作階段層級 `/model` 選擇,作為僅限模型的備援;執行緒本機的 `/model` 選擇仍然優先,且除非啟用對話紀錄繼承,否則不會複製父對話紀錄歷史。 + - `channels.discord.thread.inheritParent`(預設為 `false`)會讓新的自動執行緒選擇從父對話紀錄植入。每個帳號的覆寫位於 `channels.discord.accounts..thread.inheritParent` 底下。 + - 訊息工具反應可以解析 `user:` DM 目標。 + - `guilds..channels..requireMention: false` 會在回覆階段啟用備援期間保留。 + + 頻道主題會作為**不受信任**的脈絡注入。允許清單只限制誰能觸發代理,而不是完整的補充脈絡遮蔽邊界。 + + + + + Discord 可以將執行緒繫結到工作階段目標,讓該執行緒中的後續訊息持續路由到同一個工作階段(包含子代理工作階段)。 + + 命令: + + - `/focus ` 將目前/新的執行緒繫結到子代理/工作階段目標 + - `/unfocus` 移除目前的執行緒繫結 + - `/agents` 顯示作用中的執行與繫結狀態 + - `/session idle ` 檢查/更新聚焦繫結的非活動自動取消聚焦 + - `/session max-age ` 檢查/更新聚焦繫結的硬性最長存在時間 + + 設定: + +```json5 +{ + session: { + threadBindings: { + enabled: true, + idleHours: 24, + maxAgeHours: 0, + }, + }, + channels: { + discord: { + threadBindings: { + enabled: true, + idleHours: 24, + maxAgeHours: 0, + spawnSubagentSessions: false, // opt-in + }, + }, + }, +} +``` + + 備註: + + - `session.threadBindings.*` 設定全域預設值。 + - `channels.discord.threadBindings.*` 覆寫 Discord 行為。 + - `spawnSubagentSessions` 必須為 true,才能為 `sessions_spawn({ thread: true })` 自動建立/繫結執行緒。 + - `spawnAcpSessions` 必須為 true,才能為 ACP(`/acp spawn ... --thread ...` 或 `sessions_spawn({ runtime: "acp", thread: true })`)自動建立/繫結執行緒。 + - 如果帳號停用執行緒繫結,`/focus` 和相關的執行緒繫結操作將不可用。 + + 請參閱[子代理](/zh-TW/tools/subagents)、[ACP 代理](/zh-TW/tools/acp-agents)和[設定參考](/zh-TW/gateway/configuration-reference)。 + + + + + 若要使用穩定的「永遠開啟」ACP 工作區,請設定頂層具型別的 ACP 繫結,目標為 Discord 對話。 + + 設定路徑: + + - `bindings[]` 搭配 `type: "acp"` 和 `match.channel: "discord"` + + 範例: + +```json5 +{ + agents: { + list: [ + { + id: "codex", + runtime: { + type: "acp", + acp: { + agent: "codex", + backend: "acpx", + mode: "persistent", + cwd: "/workspace/openclaw", + }, + }, + }, + ], + }, + bindings: [ + { + type: "acp", + agentId: "codex", + match: { + channel: "discord", + accountId: "default", + peer: { kind: "channel", id: "222222222222222222" }, + }, + acp: { label: "codex-main" }, + }, + ], + channels: { + discord: { + guilds: { + "111111111111111111": { + channels: { + "222222222222222222": { + requireMention: false, + }, + }, + }, + }, + }, + }, +} +``` + + 備註: + + - `/acp spawn codex --bind here` 會就地繫結目前頻道或執行緒,並讓未來訊息保留在同一個 ACP 工作階段。執行緒訊息會繼承父頻道繫結。 + - 在已繫結的頻道或執行緒中,`/new` 和 `/reset` 會就地重設同一個 ACP 工作階段。暫時執行緒繫結在啟用期間可以覆寫目標解析。 + - 只有當 OpenClaw 需要透過 `--thread auto|here` 建立/繫結子執行緒時,才需要 `spawnAcpSessions`。 + + 請參閱 [ACP 代理](/zh-TW/tools/acp-agents)以了解繫結行為詳細資訊。 + + + + + 每個伺服器的反應通知模式: + + - `off` + - `own`(預設) + - `all` + - `allowlist`(使用 `guilds..users`) + + 反應事件會轉換為系統事件,並附加到已路由的 Discord 工作階段。 + + + + + `ackReaction` 會在 OpenClaw 處理傳入訊息時傳送確認 emoji。 + + 解析順序: + + - `channels.discord.accounts..ackReaction` + - `channels.discord.ackReaction` + - `messages.ackReaction` + - 代理身分 emoji 備援(`agents.list[].identity.emoji`,否則為 "👀") + + 備註: + + - Discord 接受 unicode emoji 或自訂 emoji 名稱。 + - 使用 `""` 可停用頻道或帳號的反應。 + + + + + 頻道發起的設定寫入預設為啟用。 + + 這會影響 `/config set|unset` 流程(當命令功能啟用時)。 + + 停用: + +```json5 +{ + channels: { + discord: { + configWrites: false, + }, + }, +} +``` + + + + + 透過 HTTP(S) Proxy 搭配 `channels.discord.proxy` 路由 Discord Gateway WebSocket 流量和啟動 REST 查詢(應用程式 ID + 允許清單解析)。 + +```json5 +{ + channels: { + discord: { + proxy: "http://proxy.example:8080", + }, + }, +} +``` + + 每個帳號覆寫: + +```json5 +{ + channels: { + discord: { + accounts: { + primary: { + proxy: "http://proxy.example:8080", + }, + }, + }, + }, +} +``` + + + + + 啟用 PluralKit 解析,將代理訊息對應到系統成員身分: + +```json5 +{ + channels: { + discord: { + pluralkit: { + enabled: true, + token: "pk_live_...", // optional; needed for private systems + }, + }, + }, +} +``` + + 備註: + + - 允許清單可以使用 `pk:` + - 只有當 `channels.discord.dangerouslyAllowNameMatching: true` 時,才會依名稱/slug 比對成員顯示名稱 + - 查詢使用原始訊息 ID,並受時間窗限制 + - 如果查詢失敗,代理訊息會被視為機器人訊息並丟棄,除非 `allowBots=true` + + + + + 當你設定狀態或活動欄位,或啟用自動上線狀態時,會套用上線狀態更新。 + + 僅狀態範例: + +```json5 +{ + channels: { + discord: { + status: "idle", + }, + }, +} +``` + + 活動範例(自訂狀態是預設活動類型): + +```json5 +{ + channels: { + discord: { + activity: "Focus time", + activityType: 4, + }, + }, +} +``` + + 串流範例: + +```json5 +{ + channels: { + discord: { + activity: "Live coding", + activityType: 1, + activityUrl: "https://twitch.tv/openclaw", + }, + }, +} +``` + + 活動類型對照: + + - 0: Playing + - 1: Streaming(需要 `activityUrl`) + - 2: Listening + - 3: Watching + - 4: Custom(使用活動文字作為狀態狀態;emoji 為選填) + - 5: Competing + + 自動上線狀態範例(執行階段健康訊號): + +```json5 +{ + channels: { + discord: { + autoPresence: { + enabled: true, + intervalMs: 30000, + minUpdateIntervalMs: 15000, + exhaustedText: "token exhausted", + }, + }, + }, +} +``` + + 自動上線狀態會將執行階段可用性對應到 Discord 狀態:healthy => online,degraded 或 unknown => idle,exhausted 或 unavailable => dnd。選填文字覆寫: + + - `autoPresence.healthyText` + - `autoPresence.degradedText` + - `autoPresence.exhaustedText`(支援 `{reason}` placeholder) + + + + + Discord 支援 DM 中以按鈕為基礎的核准處理,也可以選擇在來源頻道中張貼核准提示。 + + 設定路徑: + + - `channels.discord.execApprovals.enabled` + - `channels.discord.execApprovals.approvers`(選填;可行時會退回到 `commands.ownerAllowFrom`) + - `channels.discord.execApprovals.target`(`dm` | `channel` | `both`,預設:`dm`) + - `agentFilter`、`sessionFilter`、`cleanupAfterResolve` + + 當 `enabled` 未設定或為 `"auto"`,且至少可解析一位核准者時,Discord 會自動啟用原生 exec 核准;核准者可來自 `execApprovals.approvers` 或 `commands.ownerAllowFrom`。Discord 不會從頻道 `allowFrom`、舊版 `dm.allowFrom` 或直接訊息 `defaultTo` 推斷 exec 核准者。設定 `enabled: false` 可明確停用 Discord 作為原生核准用戶端。 + + 對於敏感的僅限擁有者群組命令,例如 `/diagnostics` 和 `/export-trajectory`,OpenClaw 會私下傳送核准提示和最終結果。當呼叫的擁有者有 Discord 擁有者路由時,它會先嘗試 Discord DM;如果不可用,則退回到 `commands.ownerAllowFrom` 中第一個可用的擁有者路由,例如 Telegram。 + + 當 `target` 為 `channel` 或 `both` 時,核准提示會在頻道中可見。只有已解析的核准者可以使用按鈕;其他使用者會收到暫時性拒絕。核准提示包含命令文字,因此只應在受信任頻道中啟用頻道傳送。如果無法從工作階段鍵推導頻道 ID,OpenClaw 會退回到 DM 傳送。 + + Discord 也會呈現其他聊天頻道使用的共用核准按鈕。原生 Discord 配接器主要新增核准者 DM 路由和頻道扇出。 + 當這些按鈕存在時,它們是主要的核准 UX;OpenClaw + 只有在工具結果表示聊天核准不可用,或手動核准是唯一途徑時, + 才應包含手動 `/approve` 命令。 + 如果 Discord 原生核准執行階段未啟用,OpenClaw 會保持 + 本機確定性的 `/approve ` 提示可見。如果 + 執行階段已啟用,但原生卡片無法傳送到任何目標, + OpenClaw 會使用待處理核准中的確切 `/approve` + 命令傳送同聊天備援通知。 + + Gateway 驗證和核准解析遵循共用 Gateway 用戶端合約(`plugin:` ID 透過 `plugin.approval.resolve` 解析;其他 ID 透過 `exec.approval.resolve` 解析)。核准預設會在 30 分鐘後過期。 + + 請參閱 [Exec 核准](/zh-TW/tools/exec-approvals)。 + + + + +## 工具和動作閘門 + +Discord 訊息動作包含傳訊、頻道管理、審核、上線狀態和中繼資料動作。 + +核心範例: + +- 傳訊:`sendMessage`、`readMessages`、`editMessage`、`deleteMessage`、`threadReply` +- 反應:`react`、`reactions`、`emojiList` +- 審核:`timeout`、`kick`、`ban` +- 上線狀態:`setPresence` + +`event-create` 動作接受選填的 `image` 參數(URL 或本機檔案路徑),用來設定排程事件封面圖片。 + +動作閘門位於 `channels.discord.actions.*` 底下。 + +預設閘門行為: + +| 動作群組 | 預設 | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | -------- | +| reactions, messages, threads, pins, polls, search, memberInfo, roleInfo, channelInfo, channels, voiceStatus, events, stickers, emojiUploads, stickerUploads, permissions | 啟用 | +| roles | 停用 | +| moderation | 停用 | +| presence | 停用 | + +## 元件 v2 UI + +OpenClaw 使用 Discord 元件 v2 來處理執行核准和跨情境標記。Discord 訊息動作也可以接受 `components` 以提供自訂 UI(進階;需要透過 discord 工具建構元件承載資料),而舊版 `embeds` 仍可使用,但不建議使用。 + +- `channels.discord.ui.components.accentColor` 設定 Discord 元件容器使用的強調色(十六進位)。 +- 使用 `channels.discord.accounts..ui.components.accentColor` 針對每個帳號設定。 +- 當元件 v2 存在時,會忽略 `embeds`。 + +範例: + +```json5 +{ + channels: { + discord: { + ui: { + components: { + accentColor: "#5865F2", + }, + }, + }, + }, +} +``` + +## 語音 + +Discord 有兩種不同的語音介面:即時 **語音頻道**(連續對話)和 **語音訊息附件**(波形預覽格式)。Gateway 兩者都支援。 + +### 語音頻道 + +設定檢查清單: + +1. 在 Discord Developer Portal 中啟用訊息內容意圖。 +2. 使用角色/使用者允許清單時,啟用伺服器成員意圖。 +3. 使用 `bot` 和 `applications.commands` 範圍邀請機器人。 +4. 在目標語音頻道授予連線、說話、傳送訊息和讀取訊息歷史權限。 +5. 啟用原生命令(`commands.native` 或 `channels.discord.commands.native`)。 +6. 設定 `channels.discord.voice`。 + +使用 `/vc join|leave|status` 控制工作階段。該命令會使用帳號預設代理,並遵循與其他 Discord 命令相同的允許清單和群組政策規則。 + +```bash +/vc join channel: +/vc status +/vc leave +``` + +自動加入範例: + +```json5 +{ + channels: { + discord: { + voice: { + enabled: true, + model: "openai/gpt-5.4-mini", + autoJoin: [ + { + guildId: "123456789012345678", + channelId: "234567890123456789", + }, + ], + daveEncryption: true, + decryptionFailureTolerance: 24, + tts: { + provider: "openai", + openai: { voice: "onyx" }, + }, + }, + }, + }, +} +``` + +注意事項: + +- `voice.tts` 只會針對語音播放覆寫 `messages.tts`。 +- `voice.model` 只會覆寫用於 Discord 語音頻道回應的 LLM。未設定時會繼承已路由代理的模型。 +- STT 使用 `tools.media.audio`;`voice.model` 不會影響轉錄。 +- 語音逐字稿回合會從 Discord `allowFrom`(或 `dm.allowFrom`)衍生擁有者狀態;非擁有者說話者無法存取僅限擁有者的工具(例如 `gateway` 和 `cron`)。 +- 語音預設啟用;設定 `channels.discord.voice.enabled=false` 可停用語音執行階段和 `GuildVoiceStates` Gateway 意圖。 +- `channels.discord.intents.voiceStates` 可以明確覆寫語音狀態意圖訂閱。未設定時,該意圖會跟隨 `voice.enabled`。 +- `voice.daveEncryption` 和 `voice.decryptionFailureTolerance` 會傳遞至 `@discordjs/voice` 加入選項。 +- 若未設定,`@discordjs/voice` 的預設值為 `daveEncryption=true` 和 `decryptionFailureTolerance=24`。 +- OpenClaw 也會監看接收解密失敗,並在短時間內反覆失敗後,透過離開/重新加入語音頻道自動復原。 +- 如果更新後接收日誌反覆顯示 `DecryptionFailed(UnencryptedWhenPassthroughDisabled)`,請收集相依性報告和日誌。隨附的 `@discordjs/voice` 版本線包含來自 discord.js PR #11449 的上游填充修正,該修正關閉了 discord.js issue #11419。 + +語音頻道管線: + +- Discord PCM 擷取會轉換為 WAV 暫存檔。 +- `tools.media.audio` 處理 STT,例如 `openai/gpt-4o-mini-transcribe`。 +- 逐字稿會透過一般 Discord 入口和路由傳送。 +- 設定 `voice.model` 時,只會覆寫此語音頻道回合的回應 LLM。 +- `voice.tts` 會合併覆蓋 `messages.tts`;產生的音訊會在已加入的頻道播放。 + +憑證會依元件解析:`voice.model` 的 LLM 路由驗證、`tools.media.audio` 的 STT 驗證,以及 `messages.tts`/`voice.tts` 的 TTS 驗證。 + +### 語音訊息 + +Discord 語音訊息會顯示波形預覽,並需要 OGG/Opus 音訊。OpenClaw 會自動產生波形,但需要 Gateway 主機上的 `ffmpeg` 和 `ffprobe` 來檢查和轉換。 + +- 提供 **本機檔案路徑**(URL 會被拒絕)。 +- 省略文字內容(Discord 會拒絕在同一承載資料中同時包含文字和語音訊息)。 +- 接受任何音訊格式;OpenClaw 會視需要轉換為 OGG/Opus。 + +```bash +message(action="send", channel="discord", target="channel:123", path="/path/to/audio.mp3", asVoice=true) +``` + +## 疑難排解 + + + + + - 啟用訊息內容意圖 + - 當你依賴使用者/成員解析時,啟用伺服器成員意圖 + - 變更意圖後重新啟動 Gateway + + + + + + - 驗證 `groupPolicy` + - 驗證 `channels.discord.guilds` 下的伺服器允許清單 + - 如果伺服器 `channels` 對應存在,則只允許列出的頻道 + - 驗證 `requireMention` 行為和提及模式 + + 實用檢查: + +```bash +openclaw doctor +openclaw channels status --probe +openclaw logs --follow +``` + + + + + 常見原因: + + - `groupPolicy="allowlist"` 但沒有相符的伺服器/頻道允許清單 + - `requireMention` 設定在錯誤位置(必須位於 `channels.discord.guilds` 或頻道項目下) + - 傳送者遭伺服器/頻道 `users` 允許清單封鎖 + + + + + + 典型日誌: + + - `Slow listener detected ...` + - `stuck session: sessionKey=agent:...:discord:... state=processing ...` + + Discord Gateway 佇列調整項: + + - 單帳號:`channels.discord.eventQueue.listenerTimeout` + - 多帳號:`channels.discord.accounts..eventQueue.listenerTimeout` + - 這只控制 Discord Gateway 監聽器工作,不控制代理回合生命週期 + + Discord 不會對已排入佇列的代理回合套用頻道擁有的逾時。訊息監聽器會立即交接,而已排入佇列的 Discord 執行會保留每個工作階段的順序,直到工作階段/工具/執行階段生命週期完成或中止工作。 + +```json5 +{ + channels: { + discord: { + accounts: { + default: { + eventQueue: { + listenerTimeout: 120000, + }, + }, + }, + }, + }, +} +``` + + + + + OpenClaw 會在連線前擷取 Discord `/gateway/bot` 中繼資料。暫時性失敗會退回 Discord 的預設 Gateway URL,並在日誌中限速記錄。 + + 中繼資料逾時調整項: + + - 單帳號:`channels.discord.gatewayInfoTimeoutMs` + - 多帳號:`channels.discord.accounts..gatewayInfoTimeoutMs` + - 未設定 config 時的 env 後援:`OPENCLAW_DISCORD_GATEWAY_INFO_TIMEOUT_MS` + - 預設值:`30000`(30 秒),最大值:`120000` + + + + + `channels status --probe` 權限檢查只適用於數字頻道 ID。 + + 如果你使用 slug 鍵,執行階段比對仍可運作,但探測無法完整驗證權限。 + + + + + + - DM 已停用:`channels.discord.dm.enabled=false` + - DM 政策已停用:`channels.discord.dmPolicy="disabled"`(舊版:`channels.discord.dm.policy`) + - 在 `pairing` 模式中等待配對核准 + + + + + 預設會忽略機器人撰寫的訊息。 + + 如果你設定 `channels.discord.allowBots=true`,請使用嚴格的提及和允許清單規則來避免迴圈行為。 + 建議使用 `channels.discord.allowBots="mentions"`,只接受提及該機器人的機器人訊息。 + + + + + + - 保持 OpenClaw 為最新版本(`openclaw update`),以確保 Discord 語音接收復原邏輯存在 + - 確認 `channels.discord.voice.daveEncryption=true`(預設值) + - 從 `channels.discord.voice.decryptionFailureTolerance=24`(上游預設值)開始,且只在需要時調整 + - 監看日誌中的: + - `discord voice: DAVE decrypt failures detected` + - `discord voice: repeated decrypt failures; attempting rejoin` + - 如果自動重新加入後仍持續失敗,請收集日誌,並與 [discord.js #11419](https://github.com/discordjs/discord.js/issues/11419) 和 [discord.js #11449](https://github.com/discordjs/discord.js/pull/11449) 中的上游 DAVE 接收歷史比較 + + + + +## 設定參考 + +主要參考:[設定參考 - Discord](/zh-TW/gateway/config-channels#discord)。 + + + +- 啟動/驗證:`enabled`、`token`、`accounts.*`、`allowBots` +- 政策:`groupPolicy`、`dm.*`、`guilds.*`、`guilds.*.channels.*` +- 命令:`commands.native`、`commands.useAccessGroups`、`configWrites`、`slashCommand.*` +- 事件佇列:`eventQueue.listenerTimeout`(監聽器預算)、`eventQueue.maxQueueSize`、`eventQueue.maxConcurrency` +- Gateway 中繼資料:`gatewayInfoTimeoutMs` +- 回覆/歷史:`replyToMode`、`historyLimit`、`dmHistoryLimit`、`dms.*.historyLimit` +- 傳遞:`textChunkLimit`、`chunkMode`、`maxLinesPerMessage` +- 串流:`streaming`(舊版別名:`streamMode`)、`streaming.preview.toolProgress`、`draftChunk`、`blockStreaming`、`blockStreamingCoalesce` +- 媒體/重試:`mediaMaxMb`(限制對外 Discord 上傳,預設 `100MB`)、`retry` +- 動作:`actions.*` +- 狀態:`activity`、`status`、`activityType`、`activityUrl` +- UI:`ui.components.accentColor` +- 功能:`threadBindings`、頂層 `bindings[]`(`type: "acp"`)、`pluralkit`、`execApprovals`、`intents`、`agentComponents`、`heartbeat`、`responsePrefix` + + + +## 安全與操作 + +- 將機器人 Token 視為秘密(受監督環境中建議使用 `DISCORD_BOT_TOKEN`)。 +- 授予最小權限的 Discord 權限。 +- 如果命令部署/狀態過期,請重新啟動 Gateway,並使用 `openclaw channels status --probe` 重新檢查。 + +## 相關 + + + + 將 Discord 使用者配對到 Gateway。 + + + 群組聊天與允許清單行為。 + + + 將傳入訊息路由到代理。 + + + 威脅模型與強化。 + + + 將伺服器和頻道對應到代理。 + + + 原生命令行為。 + + diff --git a/docs/zh-TW/channels/feishu.md b/docs/zh-TW/channels/feishu.md new file mode 100644 index 000000000..204ba9e4f --- /dev/null +++ b/docs/zh-TW/channels/feishu.md @@ -0,0 +1,485 @@ +--- +read_when: + - 你想要連接 Feishu/Lark 機器人 + - 你正在設定 Feishu 頻道 +summary: Feishu 機器人概觀、功能和設定 +title: 飛書 +x-i18n: + generated_at: "2026-04-30T02:46:17Z" + model: gpt-5.5 + provider: openai + source_hash: 37de7cbb12821f119ca1a06fcdb8e80a07752e1cbfc462344d24750fbf13147a + source_path: channels/feishu.md + workflow: 16 +--- + +# Feishu / Lark + +Feishu/Lark 是一站式協作平台,團隊可以在其中聊天、共享文件、管理行事曆,並共同完成工作。 + +**狀態:** 已可用於生產環境的機器人私訊與群組聊天。WebSocket 是預設模式;Webhook 模式為選用。 + +--- + +## 快速開始 + + +需要 OpenClaw 2026.4.25 或以上版本。執行 `openclaw --version` 檢查版本。使用 `openclaw update` 升級。 + + + + + ```bash + openclaw channels login --channel feishu + ``` + 使用你的 Feishu/Lark 行動 App 掃描 QR code,以自動建立 Feishu/Lark 機器人。 + + + + ```bash + openclaw gateway restart + ``` + + + +--- + +## 存取控制 + +### 私訊 + +設定 `dmPolicy` 來控制誰可以私訊機器人: + +- `"pairing"` — 未知使用者會收到配對碼;透過 CLI 核准 +- `"allowlist"` — 只有列在 `allowFrom` 中的使用者可以聊天(預設:僅限機器人擁有者) +- `"open"` — 只有在 `allowFrom` 包含 `"*"` 時才允許公開私訊;若有較嚴格的項目,只有相符的使用者可以聊天 +- `"disabled"` — 停用所有私訊 + +**核准配對請求:** + +```bash +openclaw pairing list feishu +openclaw pairing approve feishu +``` + +### 群組聊天 + +**群組政策** (`channels.feishu.groupPolicy`): + +| 值 | 行為 | +| ------------- | -------------------------------------------------------------------------------------------- | +| `"open"` | 回應群組中的所有訊息 | +| `"allowlist"` | 只回應 `groupAllowFrom` 中的群組,或明確設定於 `groups.` 下的群組 | +| `"disabled"` | 停用所有群組訊息;明確的 `groups.` 項目不會覆寫此設定 | + +預設值:`allowlist` + +**提及要求** (`channels.feishu.requireMention`): + +- `true` — 需要 @mention(預設) +- `false` — 不需 @mention 即可回應 +- 每個群組覆寫:`channels.feishu.groups..requireMention` +- 僅廣播用途的 `@all` 和 `@_all` 不會被視為機器人提及。同時提及 `@all` 與直接提及機器人的訊息,仍會算作機器人提及。 + +--- + +## 群組設定範例 + +### 允許所有群組,不需要 @mention + +```json5 +{ + channels: { + feishu: { + groupPolicy: "open", + }, + }, +} +``` + +### 允許所有群組,但仍需要 @mention + +```json5 +{ + channels: { + feishu: { + groupPolicy: "open", + requireMention: true, + }, + }, +} +``` + +### 僅允許特定群組 + +```json5 +{ + channels: { + feishu: { + groupPolicy: "allowlist", + // Group IDs look like: oc_xxx + groupAllowFrom: ["oc_xxx", "oc_yyy"], + }, + }, +} +``` + +在 `allowlist` 模式中,你也可以加入明確的 `groups.` 項目來允許某個群組。明確項目不會覆寫 `groupPolicy: "disabled"`。`groups.*` 下的萬用字元預設值會設定相符的群組,但它們本身不會准入群組。 + +```json5 +{ + channels: { + feishu: { + groupPolicy: "allowlist", + groups: { + oc_xxx: { + requireMention: false, + }, + }, + }, + }, +} +``` + +### 限制群組內的傳送者 + +```json5 +{ + channels: { + feishu: { + groupPolicy: "allowlist", + groupAllowFrom: ["oc_xxx"], + groups: { + oc_xxx: { + // User open_ids look like: ou_xxx + allowFrom: ["ou_user1", "ou_user2"], + }, + }, + }, + }, +} +``` + +--- + + + +## 取得群組/使用者 ID + +### 群組 ID(`chat_id`,格式:`oc_xxx`) + +在 Feishu/Lark 中開啟群組,點擊右上角的選單圖示,然後前往 **設定**。群組 ID (`chat_id`) 會列在設定頁面上。 + +![取得群組 ID](/images/feishu-get-group-id.png) + +### 使用者 ID(`open_id`,格式:`ou_xxx`) + +啟動 Gateway,傳送私訊給機器人,然後檢查日誌: + +```bash +openclaw logs --follow +``` + +在日誌輸出中尋找 `open_id`。你也可以檢查待處理的配對請求: + +```bash +openclaw pairing list feishu +``` + +--- + +## 常用命令 + +| 命令 | 說明 | +| --------- | -------------------- | +| `/status` | 顯示機器人狀態 | +| `/reset` | 重設目前工作階段 | +| `/model` | 顯示或切換 AI 模型 | + + +Feishu/Lark 不支援原生斜線命令選單,因此請將這些命令作為純文字訊息傳送。 + + +--- + +## 疑難排解 + +### 機器人在群組聊天中沒有回應 + +1. 確認機器人已加入群組 +2. 確認你已 @mention 機器人(預設需要) +3. 確認 `groupPolicy` 不是 `"disabled"` +4. 檢查日誌:`openclaw logs --follow` + +### 機器人沒有收到訊息 + +1. 確認機器人已在 Feishu Open Platform / Lark Developer 發布並核准 +2. 確認事件訂閱包含 `im.message.receive_v1` +3. 確認已選取 **持久連線**(WebSocket) +4. 確認已授予所有必要的權限範圍 +5. 確認 Gateway 正在執行:`openclaw gateway status` +6. 檢查日誌:`openclaw logs --follow` + +### App Secret 外洩 + +1. 在 Feishu Open Platform / Lark Developer 中重設 App Secret +2. 更新你的設定中的值 +3. 重新啟動 Gateway:`openclaw gateway restart` + +--- + +## 進階設定 + +### 多個帳戶 + +```json5 +{ + channels: { + feishu: { + defaultAccount: "main", + accounts: { + main: { + appId: "cli_xxx", + appSecret: "xxx", + name: "Primary bot", + tts: { + providers: { + openai: { voice: "shimmer" }, + }, + }, + }, + backup: { + appId: "cli_yyy", + appSecret: "yyy", + name: "Backup bot", + enabled: false, + }, + }, + }, + }, +} +``` + +`defaultAccount` 控制在輸出 API 未指定 `accountId` 時使用哪個帳戶。 +`accounts..tts` 使用與 `messages.tts` 相同的形狀,並會深度合併到 +全域 TTS 設定之上,因此多機器人的 Feishu 設定可以在全域保留共用提供者 +憑證,同時只按帳戶覆寫語音、模型、persona 或自動模式。 + +### 訊息限制 + +- `textChunkLimit` — 輸出文字區塊大小(預設:`2000` 字元) +- `mediaMaxMb` — 媒體上傳/下載限制(預設:`30` MB) + +### 串流 + +Feishu/Lark 支援透過互動式卡片提供串流回覆。啟用後,機器人會在產生文字時即時更新卡片。 + +```json5 +{ + channels: { + feishu: { + streaming: true, // enable streaming card output (default: true) + blockStreaming: true, // enable block-level streaming (default: true) + }, + }, +} +``` + +設定 `streaming: false` 可將完整回覆作為單一訊息傳送。 + +### 配額最佳化 + +使用兩個選用旗標減少 Feishu/Lark API 呼叫次數: + +- `typingIndicator`(預設 `true`):設定為 `false` 可略過打字反應呼叫 +- `resolveSenderNames`(預設 `true`):設定為 `false` 可略過傳送者個人資料查詢 + +```json5 +{ + channels: { + feishu: { + typingIndicator: false, + resolveSenderNames: false, + }, + }, +} +``` + +### ACP 工作階段 + +Feishu/Lark 支援 ACP 用於私訊與群組 thread 訊息。Feishu/Lark ACP 由文字命令驅動,沒有原生斜線命令選單,因此請直接在對話中使用 `/acp ...` 訊息。 + +#### 持久 ACP 繫結 + +```json5 +{ + agents: { + list: [ + { + id: "codex", + runtime: { + type: "acp", + acp: { + agent: "codex", + backend: "acpx", + mode: "persistent", + cwd: "/workspace/openclaw", + }, + }, + }, + ], + }, + bindings: [ + { + type: "acp", + agentId: "codex", + match: { + channel: "feishu", + accountId: "default", + peer: { kind: "direct", id: "ou_1234567890" }, + }, + }, + { + type: "acp", + agentId: "codex", + match: { + channel: "feishu", + accountId: "default", + peer: { kind: "group", id: "oc_group_chat:topic:om_topic_root" }, + }, + acp: { label: "codex-feishu-topic" }, + }, + ], +} +``` + +#### 從聊天產生 ACP + +在 Feishu/Lark 私訊或 thread 中: + +```text +/acp spawn codex --thread here +``` + +`--thread here` 適用於私訊與 Feishu/Lark thread 訊息。繫結對話中的後續訊息會直接路由到該 ACP 工作階段。 + +### 多代理路由 + +使用 `bindings` 將 Feishu/Lark 私訊或群組路由到不同代理。 + +```json5 +{ + agents: { + list: [ + { id: "main" }, + { id: "agent-a", workspace: "/home/user/agent-a" }, + { id: "agent-b", workspace: "/home/user/agent-b" }, + ], + }, + bindings: [ + { + agentId: "agent-a", + match: { + channel: "feishu", + peer: { kind: "direct", id: "ou_xxx" }, + }, + }, + { + agentId: "agent-b", + match: { + channel: "feishu", + peer: { kind: "group", id: "oc_zzz" }, + }, + }, + ], +} +``` + +路由欄位: + +- `match.channel`:`"feishu"` +- `match.peer.kind`:`"direct"`(私訊)或 `"group"`(群組聊天) +- `match.peer.id`:使用者 Open ID(`ou_xxx`)或群組 ID(`oc_xxx`) + +請參閱[取得群組/使用者 ID](#get-groupuser-ids) 以取得查詢提示。 + +--- + +## 設定參考 + +完整設定:[Gateway 設定](/zh-TW/gateway/configuration) + +| Setting | Description | Default | +| ------------------------------------------------- | -------------------------------------------------------------------------------- | ---------------- | +| `channels.feishu.enabled` | 啟用/停用通道 | `true` | +| `channels.feishu.domain` | API 網域(`feishu` 或 `lark`) | `feishu` | +| `channels.feishu.connectionMode` | 事件傳輸(`websocket` 或 `webhook`) | `websocket` | +| `channels.feishu.defaultAccount` | 出站路由的預設帳戶 | `default` | +| `channels.feishu.verificationToken` | Webhook 模式必填 | — | +| `channels.feishu.encryptKey` | Webhook 模式必填 | — | +| `channels.feishu.webhookPath` | Webhook 路由路徑 | `/feishu/events` | +| `channels.feishu.webhookHost` | Webhook 綁定主機 | `127.0.0.1` | +| `channels.feishu.webhookPort` | Webhook 綁定連接埠 | `3000` | +| `channels.feishu.accounts..appId` | App ID | — | +| `channels.feishu.accounts..appSecret` | App Secret | — | +| `channels.feishu.accounts..domain` | 每個帳戶的網域覆寫 | `feishu` | +| `channels.feishu.accounts..tts` | 每個帳戶的 TTS 覆寫 | `messages.tts` | +| `channels.feishu.dmPolicy` | DM 政策 | `allowlist` | +| `channels.feishu.allowFrom` | DM 允許清單(open_id 清單) | [BotOwnerId] | +| `channels.feishu.groupPolicy` | 群組政策 | `allowlist` | +| `channels.feishu.groupAllowFrom` | 群組允許清單 | — | +| `channels.feishu.requireMention` | 群組中需要 @提及 | `true` | +| `channels.feishu.groups..requireMention` | 每個群組的 @提及覆寫;明確 ID 也會在允許清單模式中允許該群組 | 繼承 | +| `channels.feishu.groups..enabled` | 啟用/停用特定群組 | `true` | +| `channels.feishu.textChunkLimit` | 訊息分塊大小 | `2000` | +| `channels.feishu.mediaMaxMb` | 媒體大小限制 | `30` | +| `channels.feishu.streaming` | 串流卡片輸出 | `true` | +| `channels.feishu.blockStreaming` | 區塊層級串流 | `true` | +| `channels.feishu.typingIndicator` | 傳送輸入中反應 | `true` | +| `channels.feishu.resolveSenderNames` | 解析傳送者顯示名稱 | `true` | + +--- + +## 支援的訊息類型 + +### 接收 + +- ✅ 文字 +- ✅ 富文字(貼文) +- ✅ 圖片 +- ✅ 檔案 +- ✅ 音訊 +- ✅ 影片/媒體 +- ✅ 貼圖 + +傳入的 Feishu/Lark 音訊訊息會正規化為媒體預留位置,而不是原始 `file_key` JSON。設定 `tools.media.audio` 時,OpenClaw 會下載語音備註資源,並在代理程式回合前執行共用音訊轉錄,因此代理程式會收到語音轉錄稿。如果 Feishu 直接在音訊承載中包含轉錄文字,則會使用該文字而不再進行另一次 ASR 呼叫。若沒有音訊轉錄提供者,代理程式仍會收到 `` 預留位置加上已儲存的附件,而不是原始 Feishu 資源承載。 + +### 傳送 + +- ✅ 文字 +- ✅ 圖片 +- ✅ 檔案 +- ✅ 音訊 +- ✅ 影片/媒體 +- ✅ 互動式卡片(包含串流更新) +- ⚠️ 富文字(貼文樣式格式;不支援完整的 Feishu/Lark 撰寫功能) + +原生 Feishu/Lark 音訊泡泡會使用 Feishu `audio` 訊息類型,並需要 Ogg/Opus 上傳媒體(`file_type: "opus"`)。既有的 `.opus` 和 `.ogg` 媒體會直接作為原生音訊傳送。只有在回覆要求語音傳送(`audioAsVoice` / 訊息工具 `asVoice`,包含 TTS 語音備註回覆)時,MP3/WAV/M4A 和其他可能的音訊格式才會使用 `ffmpeg` 轉碼為 48kHz Ogg/Opus。一般 MP3 附件會保留為一般檔案。如果缺少 `ffmpeg` 或轉換失敗,OpenClaw 會退回為檔案附件並記錄原因。 + +### 討論串與回覆 + +- ✅ 行內回覆 +- ✅ 討論串回覆 +- ✅ 回覆討論串訊息時,媒體回覆會保留討論串感知 + +對於 `groupSessionScope: "group_topic"` 和 `"group_topic_sender"`,原生 Feishu/Lark 主題群組會使用事件 `thread_id`(`omt_*`)作為標準主題工作階段鍵。OpenClaw 轉成討論串的一般群組回覆會繼續使用回覆根訊息 ID(`om_*`),因此第一回合與後續回合會保留在同一個工作階段中。 + +--- + +## 相關 + +- [通道總覽](/zh-TW/channels) — 所有支援的通道 +- [配對](/zh-TW/channels/pairing) — DM 驗證與配對流程 +- [群組](/zh-TW/channels/groups) — 群組聊天行為與提及門檻 +- [通道路由](/zh-TW/channels/channel-routing) — 訊息的工作階段路由 +- [安全性](/zh-TW/gateway/security) — 存取模型與強化 diff --git a/docs/zh-TW/channels/googlechat.md b/docs/zh-TW/channels/googlechat.md new file mode 100644 index 000000000..fe1e3c585 --- /dev/null +++ b/docs/zh-TW/channels/googlechat.md @@ -0,0 +1,275 @@ +--- +read_when: + - 正在開發 Google Chat 通道功能 +summary: Google Chat 應用程式支援狀態、功能與設定 +title: Google Chat +x-i18n: + generated_at: "2026-04-30T02:46:20Z" + model: gpt-5.5 + provider: openai + source_hash: eacc27c89fd563abab6214912687e0f15c80c7d3e652e9159bf8b43190b0886a + source_path: channels/googlechat.md + workflow: 16 +--- + +Status:已可透過 Google Chat API Webhook(僅 HTTP)用於 DM + space。 + +## 快速設定(初學者) + +1. 建立 Google Cloud 專案並啟用 **Google Chat API**。 + - 前往:[Google Chat API Credentials](https://console.cloud.google.com/apis/api/chat.googleapis.com/credentials) + - 如果尚未啟用 API,請啟用它。 +2. 建立 **Service Account**: + - 按 **Create Credentials** > **Service Account**。 + - 依喜好命名(例如 `openclaw-chat`)。 + - 權限留空(按 **Continue**)。 + - 可存取的主體留空(按 **Done**)。 +3. 建立並下載 **JSON Key**: + - 在 Service Account 清單中,點選你剛建立的那一個。 + - 前往 **Keys** 分頁。 + - 點選 **Add Key** > **Create new key**。 + - 選取 **JSON** 並按 **Create**。 +4. 將下載的 JSON 檔案儲存在你的 Gateway 主機上(例如 `~/.openclaw/googlechat-service-account.json`)。 +5. 在 [Google Cloud Console Chat Configuration](https://console.cloud.google.com/apis/api/chat.googleapis.com/hangouts-chat) 中建立 Google Chat 應用程式: + - 填寫 **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 ``**。 + - 在文字方塊中輸入你的電子郵件地址(例如 `user@example.com`)。 + - 點選底部的 **Save**。 +6. **啟用應用程式狀態**: + - 儲存後,**重新整理頁面**。 + - 尋找 **App status** 區段(儲存後通常在頁面上方或下方附近)。 + - 將狀態變更為 **Live - available to users**。 + - 再次點選 **Save**。 +7. 使用 Service Account 路徑 + Webhook audience 設定 OpenClaw: + - Env:`GOOGLE_CHAT_SERVICE_ACCOUNT_FILE=/path/to/service-account.json` + - 或 config:`channels.googlechat.serviceAccountFile: "/path/to/service-account.json"`。 +8. 設定 Webhook audience 類型 + 值(需符合你的 Chat 應用程式設定)。 +9. 啟動 Gateway。Google Chat 會將 POST 傳送到你的 Webhook 路徑。 + +## 新增到 Google Chat + +Gateway 執行中且你的電子郵件已新增至可見性清單後: + +1. 前往 [Google Chat](https://chat.google.com/)。 +2. 點選 **Direct Messages** 旁的 **+**(加號)圖示。 +3. 在搜尋列(你通常新增使用者的位置)中,輸入你在 Google Cloud Console 中設定的 **App name**。 + - **注意**:機器人不會出現在「Marketplace」瀏覽清單中,因為它是私人應用程式。你必須依名稱搜尋它。 +4. 從結果中選取你的機器人。 +5. 點選 **Add** 或 **Chat** 以開始 1:1 對話。 +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 + # If bound to localhost (127.0.0.1 or 0.0.0.0): + tailscale serve --bg --https 8443 http://127.0.0.1:18789 + + # If bound to Tailscale IP only (e.g., 100.106.161.80): + tailscale serve --bg --https 8443 http://100.106.161.80:18789 + ``` + +3. **只公開暴露 Webhook 路徑:** + + ```bash + # If bound to localhost (127.0.0.1 or 0.0.0.0): + tailscale funnel --bg --set-path /googlechat http://127.0.0.1:18789/googlechat + + # If bound to Tailscale IP only (e.g., 100.106.161.80): + tailscale funnel --bg --set-path /googlechat http://100.106.161.80:18789/googlechat + ``` + +4. **授權 Node 以取得 Funnel 存取權:** + 如果出現提示,請造訪輸出中顯示的授權 URL,以在你的 tailnet policy 中為此 Node 啟用 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:反向 Proxy(Caddy) + +如果你使用像 Caddy 這樣的反向 Proxy,只 Proxy 特定路徑: + +```caddy +your-domain.com { + reverse_proxy /googlechat* localhost:18789 +} +``` + +使用此 config 時,任何對 `your-domain.com/` 的請求都會被忽略或傳回 404,而 `your-domain.com/googlechat` 會安全地路由到 OpenClaw。 + +### 選項 C:Cloudflare Tunnel + +設定你的 tunnel ingress 規則,只路由 Webhook 路徑: + +- **Path**:`/googlechat` -> `http://localhost:18789/googlechat` +- **Default Rule**:HTTP 404(Not Found) + +## 運作方式 + +1. Google Chat 會將 Webhook POST 傳送到 Gateway。每個請求都包含 `Authorization: Bearer ` 標頭。 + - OpenClaw 會在讀取/剖析完整 Webhook body 之前,先在標頭存在時驗證 bearer auth。 + - 支援在 body 中攜帶 `authorizationEventObject.systemIdToken` 的 Google Workspace Add-on 請求,並使用更嚴格的 pre-auth body budget。 +2. OpenClaw 會依設定的 `audienceType` + `audience` 驗證 token: + - `audienceType: "app-url"` → audience 是你的 HTTPS Webhook URL。 + - `audienceType: "project-number"` → audience 是 Cloud 專案編號。 +3. 訊息會依 space 路由: + - DM 使用 session key `agent::googlechat:direct:`。 + - Space 使用 session key `agent::googlechat:group:`。 +4. DM 存取預設使用 pairing。未知傳送者會收到 pairing code;使用下列指令核准: + - `openclaw pairing approve googlechat ` +5. 群組 space 預設需要 @-mention。如果提及偵測需要應用程式的使用者名稱,請使用 `botUser`。 + +## 目標 + +使用這些識別碼進行傳送與 allowlist: + +- 直接訊息:`users/`(建議)。 +- 原始電子郵件 `name@example.com` 是可變的,且只有在 `channels.googlechat.dangerouslyAllowNameMatching: true` 時才用於直接 allowlist 比對。 +- 已棄用:`users/` 會被視為使用者 ID,而不是電子郵件 allowlist。 +- Space:`spaces/`。 + +## Config 重點 + +```json5 +{ + channels: { + googlechat: { + enabled: true, + serviceAccountFile: "/path/to/service-account.json", + // or serviceAccountRef: { source: "file", provider: "filemain", id: "/channels/googlechat/serviceAccount" } + audienceType: "app-url", + audience: "https://gateway.example.com/googlechat", + webhookPath: "/googlechat", + botUser: "users/1234567890", // optional; helps mention detection + dm: { + policy: "pairing", + allowFrom: ["users/1234567890"], + }, + groupPolicy: "allowlist", + groups: { + "spaces/AAAA": { + allow: true, + requireMention: true, + users: ["users/1234567890"], + systemPrompt: "Short answers only.", + }, + }, + actions: { reactions: true }, + typingIndicator: "message", + mediaMaxMb: 20, + }, + }, +} +``` + +注意: + +- Service Account 認證也可以用 `serviceAccount`(JSON 字串)內嵌傳入。 +- 也支援 `serviceAccountRef`(env/file SecretRef),包含 `channels.googlechat.accounts..serviceAccountRef` 下的個別 account ref。 +- 如果未設定 `webhookPath`,預設 Webhook 路徑是 `/googlechat`。 +- `dangerouslyAllowNameMatching` 會重新啟用 allowlist 的可變電子郵件主體比對(緊急相容模式)。 +- 啟用 `actions.reactions` 時,可透過 `reactions` 工具與 `channels action` 使用 reaction。 +- 訊息 action 會公開 `send` 以傳送文字,以及 `upload-file` 以明確傳送附件。`upload-file` 接受 `media` / `filePath` / `path`,以及可選的 `message`、`filename` 和 thread target。 +- `typingIndicator` 支援 `none`、`message`(預設)和 `reaction`(reaction 需要使用者 OAuth)。 +- 附件會透過 Chat API 下載,並儲存在 media pipeline 中(大小受 `mediaMaxMb` 限制)。 + +Secrets 參照詳細資訊:[Secrets Management](/zh-TW/gateway/secrets)。 + +## 疑難排解 + +### 405 Method Not Allowed + +如果 Google Cloud Logs Explorer 顯示如下錯誤: + +``` +status code: 405, reason phrase: HTTP error response: HTTP/1.1 405 Method Not Allowed +``` + +這表示尚未註冊 Webhook handler。常見原因: + +1. **尚未設定 channel**:你的 config 中缺少 `channels.googlechat` 區段。使用下列指令驗證: + + ```bash + openclaw config get channels.googlechat + ``` + + 如果傳回「Config path not found」,請新增設定(見 [Config 重點](#config-highlights))。 + +2. **Plugin 未啟用**:檢查 Plugin 狀態: + + ```bash + openclaw plugins list | grep googlechat + ``` + + 如果顯示「disabled」,請將 `plugins.entries.googlechat.enabled: true` 新增到你的 config。 + +3. **Gateway 未重新啟動**:新增 config 後,重新啟動 Gateway: + + ```bash + openclaw gateway restart + ``` + +確認 channel 正在執行: + +```bash +openclaw channels status +# Should show: Google Chat default: enabled, configured, ... +``` + +### 其他問題 + +- 檢查 `openclaw channels status --probe` 是否有 auth 錯誤或缺少 audience config。 +- 如果沒有收到訊息,請確認 Chat 應用程式的 Webhook URL + 事件訂閱。 +- 如果 mention gating 阻擋回覆,請將 `botUser` 設為應用程式的使用者資源名稱,並驗證 `requireMention`。 +- 傳送測試訊息時使用 `openclaw logs --follow`,查看請求是否抵達 Gateway。 + +相關文件: + +- [Gateway configuration](/zh-TW/gateway/configuration) +- [Security](/zh-TW/gateway/security) +- [Reactions](/zh-TW/tools/reactions) + +## 相關 + +- [Channels Overview](/zh-TW/channels) — 所有支援的 channel +- [Pairing](/zh-TW/channels/pairing) — DM 驗證與 pairing 流程 +- [Groups](/zh-TW/channels/groups) — 群組聊天行為與 mention gating +- [Channel Routing](/zh-TW/channels/channel-routing) — 訊息的 session 路由 +- [Security](/zh-TW/gateway/security) — 存取模型與強化 diff --git a/docs/zh-TW/channels/group-messages.md b/docs/zh-TW/channels/group-messages.md new file mode 100644 index 000000000..167b1d2ef --- /dev/null +++ b/docs/zh-TW/channels/group-messages.md @@ -0,0 +1,97 @@ +--- +read_when: + - 變更群組訊息規則或提及 +summary: WhatsApp 群組訊息處理的行為與設定(mentionPatterns 會跨各介面共用) +title: 群組訊息 +x-i18n: + generated_at: "2026-04-30T02:46:41Z" + model: gpt-5.5 + provider: openai + source_hash: eb7713f83b3bf309336c4b09add17835b13facb17a5a1e3db48c25d892988ee4 + source_path: channels/group-messages.md + workflow: 16 +--- + +目標:讓 Clawd 待在 WhatsApp 群組中,只在被 ping 時喚醒,並將該討論串與個人 DM 工作階段分開。 + + +`agents.list[].groupChat.mentionPatterns` 也會由 Telegram、Discord、Slack 和 iMessage 使用。本文件聚焦於 WhatsApp 專屬行為。對於多代理設定,請為每個代理設定 `agents.list[].groupChat.mentionPatterns`,或使用 `messages.groupChat.mentionPatterns` 作為全域後援。 + + +## 目前實作(2025-12-03) + +- 啟用模式:`mention`(預設)或 `always`。`mention` 需要 ping(透過 `mentionedJids` 的真實 WhatsApp @提及、安全的 regex 模式,或文字中任何位置的機器人 E.164)。`always` 會在每則訊息喚醒代理,但只有在能提供有意義價值時才應回覆;否則會回傳精確的靜默權杖 `NO_REPLY` / `no_reply`。預設值可在設定(`channels.whatsapp.groups`)中設定,並可透過 `/activation` 針對每個群組覆寫。設定 `channels.whatsapp.groups` 時,它也會作為群組允許清單(包含 `"*"` 以允許全部)。 +- 群組政策:`channels.whatsapp.groupPolicy` 控制是否接受群組訊息(`open|disabled|allowlist`)。`allowlist` 使用 `channels.whatsapp.groupAllowFrom`(後援:明確的 `channels.whatsapp.allowFrom`)。預設為 `allowlist`(在你加入寄件者前會封鎖)。 +- 每群組工作階段:工作階段鍵看起來像 `agent::whatsapp:group:`,因此像 `/verbose on`、`/trace on` 或 `/think high` 這類命令(以獨立訊息傳送)會限定於該群組;個人 DM 狀態不受影響。群組討論串會略過 Heartbeat。 +- 脈絡注入:**僅待處理**的群組訊息(預設 50 則)若_未_觸發執行,會加上 `[Chat messages since your last reply - for context]` 前綴,觸發行則放在 `[Current message - respond to this]` 之下。已在工作階段中的訊息不會重新注入。 +- 寄件者呈現:每個群組批次現在都會以 `[from: Sender Name (+E164)]` 結尾,讓 Pi 知道誰正在說話。 +- 臨時/僅檢視一次:我們會先展開這些訊息再擷取文字/提及,因此其中的 ping 仍會觸發。 +- 群組系統提示:在群組工作階段的第一輪(以及每次 `/activation` 變更模式時),我們會向系統提示注入一段簡短說明,例如 `You are replying inside the WhatsApp group "". Group members: Alice (+44...), Bob (+43...), … Activation: trigger-only … Address the specific sender noted in the message context.` 如果無法取得中繼資料,我們仍會告知代理這是群組聊天。 + +## 設定範例(WhatsApp) + +將 `groupChat` 區塊加入 `~/.openclaw/openclaw.json`,如此即使 WhatsApp 從文字本文中移除視覺上的 `@`,顯示名稱 ping 仍可運作: + +```json5 +{ + channels: { + whatsapp: { + groups: { + "*": { requireMention: true }, + }, + }, + }, + agents: { + list: [ + { + id: "main", + groupChat: { + historyLimit: 50, + mentionPatterns: ["@?openclaw", "\\+?15555550123"], + }, + }, + ], + }, +} +``` + +注意事項: + +- regex 不區分大小寫,並使用與其他設定 regex 介面相同的 safe-regex 防護措施;無效模式和不安全的巢狀重複會被忽略。 +- 當有人點選聯絡人時,WhatsApp 仍會透過 `mentionedJids` 傳送標準提及,因此很少需要號碼後援,但它是有用的安全網。 + +### 啟用命令(僅限擁有者) + +使用群組聊天命令: + +- `/activation mention` +- `/activation always` + +只有擁有者號碼(來自 `channels.whatsapp.allowFrom`,或未設定時為機器人自己的 E.164)可以變更此設定。在群組中以獨立訊息傳送 `/status`,即可查看目前的啟用模式。 + +## 使用方式 + +1. 將你的 WhatsApp 帳號(執行 OpenClaw 的那個)加入群組。 +2. 說 `@openclaw …`(或包含該號碼)。除非你設定 `groupPolicy: "open"`,否則只有允許清單中的寄件者可以觸發它。 +3. 代理提示會包含最近的群組脈絡,加上尾隨的 `[from: …]` 標記,讓它能對正確的人回應。 +4. 工作階段層級指令(`/verbose on`、`/trace on`、`/think high`、`/new` 或 `/reset`、`/compact`)只會套用到該群組的工作階段;請將它們作為獨立訊息傳送,讓它們能被註冊。你的個人 DM 工作階段會保持獨立。 + +## 測試/驗證 + +- 手動煙霧測試: + - 在群組中傳送 `@openclaw` ping,並確認回覆引用了寄件者名稱。 + - 傳送第二次 ping,並確認歷史區塊已包含其中,且在下一輪被清除。 +- 檢查 Gateway 記錄(使用 `--verbose` 執行),查看顯示 `from: ` 和 `[from: …]` 後綴的 `inbound web message` 項目。 + +## 已知考量 + +- 群組會刻意略過 Heartbeat,以避免吵雜的廣播。 +- 回音抑制使用合併後的批次字串;如果你傳送兩次相同文字且沒有提及,只有第一次會收到回覆。 +- 工作階段儲存項目會在工作階段儲存中顯示為 `agent::whatsapp:group:`(預設為 `~/.openclaw/agents//sessions/sessions.json`);缺少項目只代表該群組尚未觸發執行。 +- 群組中的輸入指示器遵循 `agents.defaults.typingMode`。當可見回覆使用預設的僅訊息工具模式時,預設會立即開始輸入,因此即使沒有發佈自動最終回覆,群組成員也能看到代理正在工作。明確的輸入模式設定仍會優先。 + +## 相關 + +- [群組](/zh-TW/channels/groups) +- [通道路由](/zh-TW/channels/channel-routing) +- [廣播群組](/zh-TW/channels/broadcast-groups) diff --git a/docs/zh-TW/channels/groups.md b/docs/zh-TW/channels/groups.md new file mode 100644 index 000000000..645bd8296 --- /dev/null +++ b/docs/zh-TW/channels/groups.md @@ -0,0 +1,496 @@ +--- +read_when: + - 變更群組聊天行為或提及閘控 +sidebarTitle: Groups +summary: 跨各介面的群組聊天行為 (Discord/iMessage/Matrix/Microsoft Teams/Signal/Slack/Telegram/WhatsApp/Zalo) +title: 群組 +x-i18n: + generated_at: "2026-04-30T02:46:45Z" + model: gpt-5.5 + provider: openai + source_hash: 743dc1ce1a0e5dc5c6d66091854cdcbb8d2b8f7e06b5c1d13c272142265fc998 + source_path: channels/groups.md + workflow: 16 +--- + +OpenClaw 在各個介面上一致地處理群組聊天:Discord、iMessage、Matrix、Microsoft Teams、Signal、Slack、Telegram、WhatsApp、Zalo。 + +## 初學者簡介(2 分鐘) + +OpenClaw「存在」於你自己的訊息帳號中。沒有獨立的 WhatsApp bot 使用者。如果**你**在某個群組中,OpenClaw 就能看見該群組並在其中回應。 + +預設行為: + +- 群組受到限制(`groupPolicy: "allowlist"`)。 +- 除非你明確停用提及閘控,否則回覆需要提及。 +- 群組/頻道中的一般最終回覆預設為私人。可見的聊天室輸出會使用 `message` 工具。 + +換句話說:允許清單中的傳送者可以透過提及 OpenClaw 來觸發它。 + + +**TL;DR** + +- **私訊存取**由 `*.allowFrom` 控制。 +- **群組存取**由 `*.groupPolicy` + 允許清單(`*.groups`、`*.groupAllowFrom`)控制。 +- **回覆觸發**由提及閘控(`requireMention`、`/activation`)控制。 + + + +快速流程(群組訊息會發生什麼): + +``` +groupPolicy? disabled -> drop +groupPolicy? allowlist -> group allowed? no -> drop +requireMention? yes -> mentioned? no -> store for context only +otherwise -> reply +``` + +## 可見回覆 + +對於群組/頻道聊天室,OpenClaw 預設為 `messages.groupChat.visibleReplies: "message_tool"`。 +這表示 agent 仍會處理該回合,並可更新記憶/session 狀態,但它的一般最終答案不會自動貼回聊天室。若要可見地發言,agent 會使用 `message(action=send)`。 + +對於直接聊天和任何其他來源回合,使用 `messages.visibleReplies: "message_tool"` 可在全域套用相同的僅工具可見回覆行為。`messages.groupChat.visibleReplies` 仍是群組/頻道聊天室更具體的覆寫設定。 + +這取代了舊模式,也就是強迫模型在多數潛伏模式回合中回答 `NO_REPLY`。在僅工具模式中,沒有任何可見動作只代表沒有呼叫 message 工具。 + +agent 在僅工具模式下工作時仍會傳送輸入指示器。這些回合的預設群組輸入模式會從「message」升級為「instant」,因為在 agent 決定是否呼叫 message 工具之前,可能永遠不會有一般 assistant 訊息文字。明確的輸入模式設定仍會優先。 + +若要恢復群組/頻道聊天室的舊版自動最終回覆: + +```json5 +{ + messages: { + groupChat: { + visibleReplies: "automatic", + }, + }, +} +``` + +若要要求每個來源聊天的可見輸出都透過 message 工具: + +```json5 +{ + messages: { + visibleReplies: "message_tool", + }, +} +``` + +原生 slash commands(Discord、Telegram,以及其他支援原生命令的介面)會繞過 `visibleReplies: "message_tool"`,並一律可見回覆,讓頻道原生命令 UI 取得預期回應。這只適用於已驗證的原生命令回合;文字輸入的 `/...` 命令和一般聊天回合仍會遵循已設定的群組預設值。 + +## 脈絡可見性與允許清單 + +群組安全涉及兩種不同控制: + +- **觸發授權**:誰可以觸發 agent(`groupPolicy`、`groups`、`groupAllowFrom`、頻道專屬允許清單)。 +- **脈絡可見性**:哪些補充脈絡會注入模型(回覆文字、引文、討論串歷史、轉寄中繼資料)。 + +預設情況下,OpenClaw 會優先維持一般聊天行為,並大多保留接收到的脈絡。這表示允許清單主要決定誰可以觸發動作,而不是每個引用或歷史片段的通用遮蔽邊界。 + + + + - 某些頻道已在特定路徑中對補充脈絡套用以傳送者為基礎的篩選(例如 Slack 討論串種子、Matrix 回覆/討論串查詢)。 + - 其他頻道仍會照接收內容傳遞引用/回覆/轉寄脈絡。 + + + + - `contextVisibility: "all"`(預設)保留目前照接收內容處理的行為。 + - `contextVisibility: "allowlist"` 會將補充脈絡篩選為允許清單中的傳送者。 + - `contextVisibility: "allowlist_quote"` 是 `allowlist` 加上一個明確的引用/回覆例外。 + + 在此強化模型於各頻道一致實作之前,預期不同介面會有差異。 + + + + +![群組訊息流程](/images/groups-flow.svg) + +如果你想要... + +| 目標 | 要設定的內容 | +| -------------------------------------------- | ---------------------------------------------------------- | +| 允許所有群組,但只在 @提及時回覆 | `groups: { "*": { requireMention: true } }` | +| 停用所有群組回覆 | `groupPolicy: "disabled"` | +| 只允許特定群組 | `groups: { "": { ... } }`(沒有 `"*"` 鍵) | +| 只有你可以在群組中觸發 | `groupPolicy: "allowlist"`、`groupAllowFrom: ["+1555..."]` | + +## Session 鍵 + +- 群組 session 使用 `agent:::group:` session 鍵(聊天室/頻道使用 `agent:::channel:`)。 +- Telegram 論壇主題會在群組 ID 加上 `:topic:`,因此每個主題都有自己的 session。 +- 直接聊天使用主要 session(或在設定時使用每位傳送者各自的 session)。 +- 群組 session 會略過 Heartbeat。 + + + +## 模式:個人私訊 + 公開群組(單一 agent) + +可以,若你的「個人」流量是**私訊**,而你的「公開」流量是**群組**,這個做法很適合。 + +原因:在單一 agent 模式中,私訊通常落在**主要** session 鍵(`agent:main:main`),而群組一律使用**非主要** session 鍵(`agent:main::group:`)。如果你使用 `mode: "non-main"` 啟用 sandboxing,這些群組 session 會在設定的 sandbox 後端中執行,而你的主要私訊 session 會留在主機上。如果你沒有選擇後端,Docker 是預設後端。 + +這會給你一個 agent「大腦」(共享工作區 + 記憶),但有兩種執行姿態: + +- **私訊**:完整工具(主機) +- **群組**:sandbox + 受限工具 + + +如果你需要真正分離的工作區/persona(「個人」和「公開」絕不能混在一起),請使用第二個 agent + 繫結。請參閱[多 Agent 路由](/zh-TW/concepts/multi-agent)。 + + + + + ```json5 + { + agents: { + defaults: { + sandbox: { + mode: "non-main", // groups/channels are non-main -> sandboxed + scope: "session", // strongest isolation (one container per group/channel) + workspaceAccess: "none", + }, + }, + }, + tools: { + sandbox: { + tools: { + // If allow is non-empty, everything else is blocked (deny still wins). + allow: ["group:messaging", "group:sessions"], + deny: ["group:runtime", "group:fs", "group:ui", "nodes", "cron", "gateway"], + }, + }, + }, + } + ``` + + + 想要「群組只能看到資料夾 X」,而不是「沒有主機存取權」?保留 `workspaceAccess: "none"`,並只將允許清單中的路徑掛載到 sandbox: + + ```json5 + { + agents: { + defaults: { + sandbox: { + mode: "non-main", + scope: "session", + workspaceAccess: "none", + docker: { + binds: [ + // hostPath:containerPath:mode + "/home/user/FriendsShared:/data:ro", + ], + }, + }, + }, + }, + } + ``` + + + + +相關: + +- 設定鍵與預設值:[Gateway 設定](/zh-TW/gateway/config-agents#agentsdefaultssandbox) +- 偵錯工具為何被封鎖:[Sandbox 與工具政策與提升權限](/zh-TW/gateway/sandbox-vs-tool-policy-vs-elevated) +- Bind mount 詳細資訊:[Sandboxing](/zh-TW/gateway/sandboxing#custom-bind-mounts) + +## 顯示標籤 + +- UI 標籤在可用時使用 `displayName`,格式為 `:`。 +- `#room` 保留給聊天室/頻道;群組聊天使用 `g-`(小寫、空格 -> `-`、保留 `#@+._-`)。 + +## 群組政策 + +控制每個頻道如何處理群組/聊天室訊息: + +```json5 +{ + channels: { + whatsapp: { + groupPolicy: "disabled", // "open" | "disabled" | "allowlist" + groupAllowFrom: ["+15551234567"], + }, + telegram: { + groupPolicy: "disabled", + groupAllowFrom: ["123456789"], // numeric Telegram user id (wizard can resolve @username) + }, + signal: { + groupPolicy: "disabled", + groupAllowFrom: ["+15551234567"], + }, + imessage: { + groupPolicy: "disabled", + groupAllowFrom: ["chat_id:123"], + }, + msteams: { + groupPolicy: "disabled", + groupAllowFrom: ["user@org.com"], + }, + discord: { + groupPolicy: "allowlist", + guilds: { + GUILD_ID: { channels: { help: { allow: true } } }, + }, + }, + slack: { + groupPolicy: "allowlist", + channels: { "#general": { allow: true } }, + }, + matrix: { + groupPolicy: "allowlist", + groupAllowFrom: ["@owner:example.org"], + groups: { + "!roomId:example.org": { enabled: true }, + "#alias:example.org": { enabled: true }, + }, + }, + }, +} +``` + +| 政策 | 行為 | +| ------------- | ------------------------------------------------------------ | +| `"open"` | 群組會繞過允許清單;提及閘控仍會套用。 | +| `"disabled"` | 完全封鎖所有群組訊息。 | +| `"allowlist"` | 只允許符合已設定允許清單的群組/聊天室。 | + + + + - `groupPolicy` 與提及閘控是分開的(後者需要 @提及)。 + - WhatsApp/Telegram/Signal/iMessage/Microsoft Teams/Zalo:使用 `groupAllowFrom`(備援:明確的 `allowFrom`)。 + - 私訊配對核准(`*-allowFrom` 儲存項目)只適用於私訊存取;群組傳送者授權仍明確使用群組允許清單。 + - Discord:允許清單使用 `channels.discord.guilds..channels`。 + - Slack:允許清單使用 `channels.slack.channels`。 + - Matrix:允許清單使用 `channels.matrix.groups`。偏好使用聊天室 ID 或別名;已加入聊天室的名稱查詢是盡力而為,未解析的名稱會在執行階段被忽略。使用 `channels.matrix.groupAllowFrom` 來限制傳送者;也支援每個聊天室的 `users` 允許清單。 + - 群組私訊會分開控制(`channels.discord.dm.*`、`channels.slack.dm.*`)。 + - Telegram 允許清單可比對使用者 ID(`"123456789"`、`"telegram:123456789"`、`"tg:123456789"`)或使用者名稱(`"@alice"` 或 `"alice"`);前綴不區分大小寫。 + - 預設為 `groupPolicy: "allowlist"`;如果你的群組允許清單是空的,群組訊息會被封鎖。 + - 執行階段安全性:當 provider 區塊完全缺失(沒有 `channels.`)時,群組政策會退回失敗關閉模式(通常是 `allowlist`),而不是繼承 `channels.defaults.groupPolicy`。 + + + + +快速心智模型(群組訊息的評估順序): + + + + `groupPolicy`(open/disabled/allowlist)。 + + + 群組允許清單(`*.groups`、`*.groupAllowFrom`、頻道專屬允許清單)。 + + + 提及閘控(`requireMention`、`/activation`)。 + + + +## 提及閘控(預設) + +群組訊息需要提及,除非依群組覆寫。預設值位於每個子系統的 `*.groups."*"` 下。 + +回覆機器人訊息在頻道支援回覆中繼資料時,會算作隱含提及。引用機器人訊息在公開引用中繼資料的頻道上,也可以算作隱含提及。目前內建案例包含 Telegram、WhatsApp、Slack、Discord、Microsoft Teams 與 ZaloUser。 + +```json5 +{ + channels: { + whatsapp: { + groups: { + "*": { requireMention: true }, + "123@g.us": { requireMention: false }, + }, + }, + telegram: { + groups: { + "*": { requireMention: true }, + "123456789": { requireMention: false }, + }, + }, + imessage: { + groups: { + "*": { requireMention: true }, + "123": { requireMention: false }, + }, + }, + }, + agents: { + list: [ + { + id: "main", + groupChat: { + mentionPatterns: ["@openclaw", "openclaw", "\\+15555550123"], + historyLimit: 50, + }, + }, + ], + }, +} +``` + + + + - `mentionPatterns` 是不區分大小寫的安全 regex 模式;無效模式與不安全的巢狀重複形式會被忽略。 + - 提供明確提及的介面仍會通過;模式是備援。 + - 每代理覆寫:`agents.list[].groupChat.mentionPatterns`(在多個代理共用群組時很有用)。 + - 提及門檻只會在可偵測提及時強制執行(已設定原生提及或 `mentionPatterns`)。 + - 群組聊天提示詞上下文會在每一輪攜帶已解析的靜默回覆指令;工作區檔案不應重複 `NO_REPLY` 機制。 + - 允許靜默回覆的群組,會將乾淨的空白或僅推理模型輪次視為靜默,等同於 `NO_REPLY`。直接聊天只有在明確允許直接靜默回覆時才會相同;否則空白回覆仍會保留為失敗的代理輪次。 + - Discord 預設值位於 `channels.discord.guilds."*"`(可依 guild/channel 覆寫)。 + - 群組歷史上下文會跨頻道一致包裝,且為 **pending-only**(因提及門檻而略過的訊息);使用 `messages.groupChat.historyLimit` 作為全域預設值,並使用 `channels..historyLimit`(或 `channels..accounts.*.historyLimit`)進行覆寫。設為 `0` 可停用。 + + + + +## 群組/頻道工具限制(選用) + +某些頻道設定支援限制 **特定群組/聊天室/頻道內** 可用的工具。 + +- `tools`:允許/拒絕整個群組的工具。 +- `toolsBySender`:群組內依傳送者覆寫。使用明確的鍵前綴:`id:`、`e164:`、`username:`、`name:` 與 `"*"` 萬用字元。舊版未加前綴的鍵仍會接受,且只會以 `id:` 比對。 + +解析順序(最具體者優先): + + + + 群組/頻道 `toolsBySender` 比對。 + + + 群組/頻道 `tools`。 + + + 預設 (`"*"`) `toolsBySender` 比對。 + + + 預設 (`"*"`) `tools`。 + + + +範例(Telegram): + +```json5 +{ + channels: { + telegram: { + groups: { + "*": { tools: { deny: ["exec"] } }, + "-1001234567890": { + tools: { deny: ["exec", "read", "write"] }, + toolsBySender: { + "id:123456789": { alsoAllow: ["exec"] }, + }, + }, + }, + }, + }, +} +``` + + +群組/頻道工具限制會在全域/代理工具政策之外另行套用(拒絕仍然優先)。某些頻道會針對聊天室/頻道使用不同的巢狀結構(例如 Discord `guilds.*.channels.*`、Slack `channels.*`、Microsoft Teams `teams.*.channels.*`)。 + + +## 群組允許清單 + +設定 `channels.whatsapp.groups`、`channels.telegram.groups` 或 `channels.imessage.groups` 時,鍵會作為群組允許清單。使用 `"*"` 可允許所有群組,同時仍設定預設提及行為。 + + +常見混淆:DM 配對核准不等同於群組授權。對於支援 DM 配對的頻道,配對儲存區只會解鎖 DM。群組命令仍需要來自設定允許清單(例如 `groupAllowFrom`)或該頻道已記載設定備援的明確群組傳送者授權。 + + +常見意圖(複製/貼上): + + + + ```json5 + { + channels: { whatsapp: { groupPolicy: "disabled" } }, + } + ``` + + + ```json5 + { + channels: { + whatsapp: { + groups: { + "123@g.us": { requireMention: true }, + "456@g.us": { requireMention: false }, + }, + }, + }, + } + ``` + + + ```json5 + { + channels: { + whatsapp: { + groups: { "*": { requireMention: true } }, + }, + }, + } + ``` + + + ```json5 + { + channels: { + whatsapp: { + groupPolicy: "allowlist", + groupAllowFrom: ["+15551234567"], + groups: { "*": { requireMention: true } }, + }, + }, + } + ``` + + + +## 啟用(僅限擁有者) + +群組擁有者可以切換每個群組的啟用狀態: + +- `/activation mention` +- `/activation always` + +擁有者由 `channels.whatsapp.allowFrom` 判定(未設定時則使用機器人自己的 E.164)。請將命令作為獨立訊息傳送。其他介面目前會忽略 `/activation`。 + +## 上下文字段 + +群組傳入 payload 會設定: + +- `ChatType=group` +- `GroupSubject`(若已知) +- `GroupMembers`(若已知) +- `WasMentioned`(提及門檻結果) +- Telegram 論壇主題也會包含 `MessageThreadId` 與 `IsForum`。 + +頻道特定注意事項: + +- BlueBubbles 可以選擇在填入 `GroupMembers` 前,先從本機「聯絡人」資料庫補充未命名的 macOS 群組參與者。這預設關閉,且只會在正常群組門檻通過後執行。 + +代理系統提示詞會在新群組工作階段的第一輪包含群組介紹。它會提醒模型像人類一樣回應、避免 Markdown 表格、盡量減少空白行並遵循一般聊天間距,以及避免輸入字面 `\n` 序列。頻道來源的群組名稱與參與者標籤會呈現為 fenced 不受信任中繼資料,而不是內嵌系統指令。 + +## iMessage 細節 + +- 路由或加入允許清單時,優先使用 `chat_id:`。 +- 列出聊天:`imsg chats --limit 20`。 +- 群組回覆一律傳回相同的 `chat_id`。 + +## WhatsApp 系統提示詞 + +請參閱 [WhatsApp](/zh-TW/channels/whatsapp#system-prompts),了解權威的 WhatsApp 系統提示詞規則,包括群組與直接提示詞解析、萬用字元行為,以及帳號覆寫語意。 + +## WhatsApp 細節 + +請參閱 [群組訊息](/zh-TW/channels/group-messages),了解 WhatsApp 專屬行為(歷史注入、提及處理細節)。 + +## 相關 + +- [廣播群組](/zh-TW/channels/broadcast-groups) +- [頻道路由](/zh-TW/channels/channel-routing) +- [群組訊息](/zh-TW/channels/group-messages) +- [配對](/zh-TW/channels/pairing) diff --git a/docs/zh-TW/channels/imessage.md b/docs/zh-TW/channels/imessage.md new file mode 100644 index 000000000..bf20e7c8a --- /dev/null +++ b/docs/zh-TW/channels/imessage.md @@ -0,0 +1,434 @@ +--- +read_when: + - 設定 iMessage 支援 + - 偵錯 iMessage 傳送/接收 +summary: 透過 imsg(stdio 上的 JSON-RPC)提供舊版 iMessage 支援。新的設定應使用 BlueBubbles。 +title: iMessage +x-i18n: + generated_at: "2026-04-30T02:46:43Z" + model: gpt-5.5 + provider: openai + source_hash: 60eeb3553a6511d56b8177ca4eafbedfed2d0852ac64c230c250911cd18ce17e + source_path: channels/imessage.md + workflow: 16 +--- + + +若要進行新的 iMessage 部署,請使用 BlueBubbles。 + +`imsg` 整合屬於舊版功能,可能會在未來版本中移除。 + + +狀態:舊版外部 CLI 整合。Gateway 會啟動 `imsg rpc`,並透過 stdio 上的 JSON-RPC 通訊(沒有獨立的守護程式/連接埠)。 + + + + 新設定建議使用的 iMessage 路徑。 + + + iMessage 私訊預設使用配對模式。 + + + 完整的 iMessage 欄位參考。 + + + +## 快速設定 + + + + + + +```bash +brew install steipete/tap/imsg +imsg rpc --help +``` + + + + + +```json5 +{ + channels: { + imessage: { + enabled: true, + cliPath: "/usr/local/bin/imsg", + dbPath: "/Users/user/Library/Messages/chat.db", + }, + }, +} +``` + + + + + +```bash +openclaw gateway +``` + + + + + +```bash +openclaw pairing list imessage +openclaw pairing approve imessage +``` + + 配對請求會在 1 小時後過期。 + + + + + + + OpenClaw 只需要與 stdio 相容的 `cliPath`,因此你可以將 `cliPath` 指向一個 wrapper script,由它透過 SSH 連到遠端 Mac 並執行 `imsg`。 + +```bash +#!/usr/bin/env bash +exec ssh -T gateway-host imsg "$@" +``` + + 啟用附件時的建議設定: + +```json5 +{ + channels: { + imessage: { + enabled: true, + cliPath: "~/.openclaw/scripts/imsg-ssh", + remoteHost: "user@gateway-host", // used for SCP attachment fetches + includeAttachments: true, + // Optional: override allowed attachment roots. + // Defaults include /Users/*/Library/Messages/Attachments + attachmentRoots: ["/Users/*/Library/Messages/Attachments"], + remoteAttachmentRoots: ["/Users/*/Library/Messages/Attachments"], + }, + }, +} +``` + + 如果未設定 `remoteHost`,OpenClaw 會嘗試透過剖析 SSH wrapper script 自動偵測。 + `remoteHost` 必須是 `host` 或 `user@host`(不可有空格或 SSH 選項)。 + OpenClaw 對 SCP 使用嚴格的主機金鑰檢查,因此轉送主機金鑰必須已存在於 `~/.ssh/known_hosts`。 + 附件路徑會根據允許的根目錄(`attachmentRoots` / `remoteAttachmentRoots`)進行驗證。 + + + + +## 需求與權限(macOS) + +- Messages 必須已在執行 `imsg` 的 Mac 上登入。 +- 執行 OpenClaw/`imsg` 的程序環境需要完整磁碟存取權(Messages 資料庫存取)。 +- 需要自動化權限,才能透過 Messages.app 傳送訊息。 + + +權限是依程序環境授予。如果 gateway 以無頭模式執行(LaunchAgent/SSH),請在同一環境中執行一次互動式命令以觸發提示: + +```bash +imsg chats --limit 1 +# or +imsg send "test" +``` + + + +## 存取控制與路由 + + + + `channels.imessage.dmPolicy` 控制直接訊息: + + - `pairing`(預設) + - `allowlist` + - `open`(需要 `allowFrom` 包含 `"*"`) + - `disabled` + + Allowlist 欄位:`channels.imessage.allowFrom`。 + + Allowlist 項目可以是 handle 或聊天目標(`chat_id:*`、`chat_guid:*`、`chat_identifier:*`)。 + + + + + `channels.imessage.groupPolicy` 控制群組處理: + + - `allowlist`(已設定時的預設值) + - `open` + - `disabled` + + 群組傳送者 allowlist:`channels.imessage.groupAllowFrom`。 + + 執行階段後援:如果未設定 `groupAllowFrom`,iMessage 群組傳送者檢查會在可用時退回使用 `allowFrom`。 + 執行階段注意事項:如果完全缺少 `channels.imessage`,執行階段會退回到 `groupPolicy="allowlist"` 並記錄警告(即使已設定 `channels.defaults.groupPolicy`)。 + + 群組的提及 gating: + + - iMessage 沒有原生提及 metadata + - 提及偵測使用 regex patterns(`agents.list[].groupChat.mentionPatterns`,後援為 `messages.groupChat.mentionPatterns`) + - 未設定 patterns 時,無法強制執行提及 gating + + 來自授權傳送者的控制命令可以在群組中略過提及 gating。 + + + + + - 私訊使用直接路由;群組使用群組路由。 + - 使用預設 `session.dmScope=main` 時,iMessage 私訊會收斂到 agent main session。 + - 群組 session 會隔離(`agent::imessage:group:`)。 + - 回覆會使用來源 channel/target metadata 路由回 iMessage。 + + 類群組 thread 行為: + + 某些多參與者 iMessage threads 可能會以 `is_group=false` 抵達。 + 如果該 `chat_id` 明確設定於 `channels.imessage.groups` 下,OpenClaw 會將其視為群組流量(群組 gating + 群組 session 隔離)。 + + + + +## ACP 對話繫結 + +舊版 iMessage 聊天也可以繫結到 ACP sessions。 + +快速操作流程: + +- 在私訊或允許的群組聊天內執行 `/acp spawn codex --bind here`。 +- 之後同一個 iMessage 對話中的訊息會路由到產生的 ACP session。 +- `/new` 和 `/reset` 會就地重設同一個已繫結的 ACP session。 +- `/acp close` 會關閉 ACP session 並移除繫結。 + +已設定的持久繫結可透過最上層 `bindings[]` 項目支援,其中 `type: "acp"` 且 `match.channel: "imessage"`。 + +`match.peer.id` 可以使用: + +- 標準化的私訊 handle,例如 `+15555550123` 或 `user@example.com` +- `chat_id:`(建議用於穩定的群組繫結) +- `chat_guid:` +- `chat_identifier:` + +範例: + +```json5 +{ + agents: { + list: [ + { + id: "codex", + runtime: { + type: "acp", + acp: { agent: "codex", backend: "acpx", mode: "persistent" }, + }, + }, + ], + }, + bindings: [ + { + type: "acp", + agentId: "codex", + match: { + channel: "imessage", + accountId: "default", + peer: { kind: "group", id: "chat_id:123" }, + }, + acp: { label: "codex-group" }, + }, + ], +} +``` + +請參閱 [ACP Agents](/zh-TW/tools/acp-agents) 了解共用的 ACP 繫結行為。 + +## 部署模式 + + + + 使用專用 Apple ID 和 macOS 使用者,讓 bot 流量與你的個人 Messages profile 隔離。 + + 典型流程: + + 1. 建立/登入專用 macOS 使用者。 + 2. 在該使用者中使用 bot Apple ID 登入 Messages。 + 3. 在該使用者中安裝 `imsg`。 + 4. 建立 SSH wrapper,讓 OpenClaw 可以在該使用者環境中執行 `imsg`。 + 5. 將 `channels.imessage.accounts..cliPath` 和 `.dbPath` 指向該使用者 profile。 + + 第一次執行可能需要在該 bot 使用者 session 中進行 GUI 核准(自動化 + 完整磁碟存取)。 + + + + + 常見拓撲: + + - gateway 在 Linux/VM 上執行 + - iMessage + `imsg` 在你 tailnet 中的一台 Mac 上執行 + - `cliPath` wrapper 使用 SSH 執行 `imsg` + - `remoteHost` 啟用 SCP 附件擷取 + + 範例: + +```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", + }, + }, +} +``` + +```bash +#!/usr/bin/env bash +exec ssh -T bot@mac-mini.tailnet-1234.ts.net imsg "$@" +``` + + 使用 SSH 金鑰,讓 SSH 和 SCP 都能非互動執行。 + 請先確保主機金鑰已受信任(例如 `ssh bot@mac-mini.tailnet-1234.ts.net`),讓 `known_hosts` 已填入。 + + + + + iMessage 支援 `channels.imessage.accounts` 下的逐帳號設定。 + + 每個帳號都可以覆寫 `cliPath`、`dbPath`、`allowFrom`、`groupPolicy`、`mediaMaxMb`、history settings,以及附件根目錄 allowlists 等欄位。 + + + + +## 媒體、分塊與遞送目標 + + + + - 傳入附件擷取是選用的:`channels.imessage.includeAttachments` + - 設定 `remoteHost` 時,可以透過 SCP 擷取遠端附件路徑 + - 附件路徑必須符合允許的根目錄: + - `channels.imessage.attachmentRoots`(本機) + - `channels.imessage.remoteAttachmentRoots`(遠端 SCP 模式) + - 預設根目錄 pattern:`/Users/*/Library/Messages/Attachments` + - SCP 使用嚴格的主機金鑰檢查(`StrictHostKeyChecking=yes`) + - 傳出媒體大小使用 `channels.imessage.mediaMaxMb`(預設 16 MB) + + + + + - 文字分塊限制:`channels.imessage.textChunkLimit`(預設 4000) + - 分塊模式:`channels.imessage.chunkMode` + - `length`(預設) + - `newline`(段落優先切分) + + + + + 建議的明確目標: + + - `chat_id:123`(建議用於穩定路由) + - `chat_guid:...` + - `chat_identifier:...` + + 也支援 handle 目標: + + - `imessage:+1555...` + - `sms:+1555...` + - `user@example.com` + +```bash +imsg chats --limit 20 +``` + + + + +## 設定寫入 + +iMessage 預設允許 channel 發起的設定寫入(適用於 `commands.config: true` 時的 `/config set|unset`)。 + +停用: + +```json5 +{ + channels: { + imessage: { + configWrites: false, + }, + }, +} +``` + +## 疑難排解 + + + + 驗證 binary 與 RPC 支援: + +```bash +imsg rpc --help +openclaw channels status --probe +``` + + 如果 probe 回報 RPC 不受支援,請更新 `imsg`。 + + + + + 檢查: + + - `channels.imessage.dmPolicy` + - `channels.imessage.allowFrom` + - 配對核准(`openclaw pairing list imessage`) + + + + + 檢查: + + - `channels.imessage.groupPolicy` + - `channels.imessage.groupAllowFrom` + - `channels.imessage.groups` allowlist 行為 + - 提及 pattern 設定(`agents.list[].groupChat.mentionPatterns`) + + + + + 檢查: + + - `channels.imessage.remoteHost` + - `channels.imessage.remoteAttachmentRoots` + - 來自 gateway host 的 SSH/SCP 金鑰驗證 + - gateway host 上的 `~/.ssh/known_hosts` 中存在主機金鑰 + - 執行 Messages 的 Mac 上的遠端路徑可讀性 + + + + + 在同一使用者/session 環境中的互動式 GUI terminal 重新執行並核准提示: + +```bash +imsg chats --limit 1 +imsg send "test" +``` + + 確認完整磁碟存取 + 自動化已授予執行 OpenClaw/`imsg` 的程序環境。 + + + + +## 設定參考指標 + +- [設定參考 - iMessage](/zh-TW/gateway/config-channels#imessage) +- [Gateway 設定](/zh-TW/gateway/configuration) +- [配對](/zh-TW/channels/pairing) +- [BlueBubbles](/zh-TW/channels/bluebubbles) + +## 相關 + +- [Channels Overview](/zh-TW/channels) — 所有支援的 channels +- [配對](/zh-TW/channels/pairing) — 私訊驗證與配對流程 +- [群組](/zh-TW/channels/groups) — 群組聊天行為與提及 gating +- [Channel Routing](/zh-TW/channels/channel-routing) — 訊息的 session 路由 +- [安全性](/zh-TW/gateway/security) — 存取模型與強化措施 diff --git a/docs/zh-TW/channels/index.md b/docs/zh-TW/channels/index.md new file mode 100644 index 000000000..92be8ec60 --- /dev/null +++ b/docs/zh-TW/channels/index.md @@ -0,0 +1,65 @@ +--- +read_when: + - 你想要為 OpenClaw 選擇聊天頻道 + - 需要快速概覽支援的訊息平台 +summary: OpenClaw 可連接的訊息平台 +title: 聊天頻道 +x-i18n: + generated_at: "2026-04-30T02:46:58Z" + model: gpt-5.5 + provider: openai + source_hash: b58a1f1a0500419015985500a301d9f8ee4fa3a67b11e30561cabe2dc57b5049 + source_path: channels/index.md + workflow: 16 +--- + +OpenClaw 可以在你已經使用的任何聊天 App 上與你交談。每個頻道都透過 Gateway 連線。 +所有地方都支援文字;媒體與反應則依頻道而異。 + +## 傳送注意事項 + +- 包含 Markdown 圖片語法的 Telegram 回覆,例如 `![alt](url)`, + 會在可行時於最終傳出路徑上轉換為媒體回覆。 +- Slack 多人私訊會以群組聊天的方式路由,因此群組政策、提及 + 行為與群組工作階段規則會套用到 MPIM 對話。 +- WhatsApp 設定是按需安裝:新手導引可以在 + Baileys 執行階段相依套件完成部署前顯示設定流程,而 Gateway 只會在頻道實際啟用時載入 WhatsApp + 執行階段。 + +## 支援的頻道 + +- [BlueBubbles](/zh-TW/channels/bluebubbles) — **建議用於 iMessage**;使用 BlueBubbles macOS 伺服器 REST API,完整支援功能(內建 Plugin;編輯、收回、效果、反應、群組管理 — 編輯目前在 macOS 26 Tahoe 上故障)。 +- [Discord](/zh-TW/channels/discord) — Discord Bot API + Gateway;支援伺服器、頻道與私訊。 +- [Feishu](/zh-TW/channels/feishu) — 透過 WebSocket 使用 Feishu/Lark 機器人(內建 Plugin)。 +- [Google Chat](/zh-TW/channels/googlechat) — 透過 HTTP Webhook 使用 Google Chat API App。 +- [iMessage(舊版)](/zh-TW/channels/imessage) — 透過 imsg CLI 的舊版 macOS 整合(已棄用,新設定請使用 BlueBubbles)。 +- [IRC](/zh-TW/channels/irc) — 傳統 IRC 伺服器;支援頻道與私訊,並提供配對/允許清單控制。 +- [LINE](/zh-TW/channels/line) — LINE Messaging API 機器人(內建 Plugin)。 +- [Matrix](/zh-TW/channels/matrix) — Matrix 協定(內建 Plugin)。 +- [Mattermost](/zh-TW/channels/mattermost) — Bot API + WebSocket;頻道、群組、私訊(內建 Plugin)。 +- [Microsoft Teams](/zh-TW/channels/msteams) — Bot Framework;企業支援(內建 Plugin)。 +- [Nextcloud Talk](/zh-TW/channels/nextcloud-talk) — 透過 Nextcloud Talk 的自架聊天(內建 Plugin)。 +- [Nostr](/zh-TW/channels/nostr) — 透過 NIP-04 的去中心化私訊(內建 Plugin)。 +- [QQ Bot](/zh-TW/channels/qqbot) — QQ Bot API;私人聊天、群組聊天與豐富媒體(內建 Plugin)。 +- [Signal](/zh-TW/channels/signal) — signal-cli;注重隱私。 +- [Slack](/zh-TW/channels/slack) — Bolt SDK;工作區 App。 +- [Synology Chat](/zh-TW/channels/synology-chat) — 透過傳出與傳入 Webhook 使用 Synology NAS Chat(內建 Plugin)。 +- [Telegram](/zh-TW/channels/telegram) — 透過 grammY 使用 Bot API;支援群組。 +- [Tlon](/zh-TW/channels/tlon) — 以 Urbit 為基礎的 Messenger(內建 Plugin)。 +- [Twitch](/zh-TW/channels/twitch) — 透過 IRC 連線的 Twitch 聊天(內建 Plugin)。 +- [Voice Call](/zh-TW/plugins/voice-call) — 透過 Plivo 或 Twilio 的電話通訊(Plugin,需另行安裝)。 +- [WebChat](/zh-TW/web/webchat) — 透過 WebSocket 的 Gateway WebChat UI。 +- [WeChat](/zh-TW/channels/wechat) — 透過 QR 登入的 Tencent iLink Bot Plugin;僅支援私人聊天(外部 Plugin)。 +- [WhatsApp](/zh-TW/channels/whatsapp) — 最受歡迎;使用 Baileys,並需要 QR 配對。 +- [Yuanbao](/zh-TW/channels/yuanbao) — Tencent Yuanbao 機器人(外部 Plugin)。 +- [Zalo](/zh-TW/channels/zalo) — Zalo Bot API;越南熱門 Messenger(內建 Plugin)。 +- [Zalo Personal](/zh-TW/channels/zalouser) — 透過 QR 登入的 Zalo 個人帳號(內建 Plugin)。 + +## 注意事項 + +- 頻道可以同時執行;設定多個頻道後,OpenClaw 會依聊天進行路由。 +- 最快的設定通常是 **Telegram**(簡單的機器人權杖)。WhatsApp 需要 QR 配對,並且會在磁碟上儲存更多狀態。 +- 群組行為因頻道而異;請參閱[群組](/zh-TW/channels/groups)。 +- 為了安全,會強制執行私訊配對與允許清單;請參閱[安全性](/zh-TW/gateway/security)。 +- 疑難排解:[頻道疑難排解](/zh-TW/channels/troubleshooting)。 +- 模型提供者另有文件說明;請參閱[模型提供者](/zh-TW/providers/models)。 diff --git a/docs/zh-TW/channels/irc.md b/docs/zh-TW/channels/irc.md new file mode 100644 index 000000000..acf08d1e8 --- /dev/null +++ b/docs/zh-TW/channels/irc.md @@ -0,0 +1,259 @@ +--- +read_when: + - 您想要將 OpenClaw 連接到 IRC 頻道或私訊 + - 您正在設定 IRC 允許清單、群組政策或提及閘控 +summary: IRC Plugin 設定、存取控制與疑難排解 +title: IRC +x-i18n: + generated_at: "2026-04-30T02:47:15Z" + model: gpt-5.5 + provider: openai + source_hash: 76f316c0f026d0387a97dc5dcb6d8967f6e4841d94b95b36e42f6f6284882a69 + source_path: channels/irc.md + workflow: 16 +--- + +使用 IRC 可讓 OpenClaw 進入傳統頻道(`#room`)和私訊。 +IRC 以隨附的 Plugin 提供,但設定位於主要設定檔的 `channels.irc` 下。 + +## 快速開始 + +1. 在 `~/.openclaw/openclaw.json` 啟用 IRC 設定。 +2. 至少設定: + +```json5 +{ + channels: { + irc: { + enabled: true, + host: "irc.example.com", + port: 6697, + tls: true, + nick: "openclaw-bot", + channels: ["#openclaw"], + }, + }, +} +``` + +建議使用私人 IRC 伺服器進行機器人協調。如果你刻意使用公開 IRC 網路,常見選擇包括 Libera.Chat、OFTC 和 Snoonet。避免將可預測的公開頻道用於機器人或群集後端通道流量。 + +3. 啟動/重新啟動 Gateway: + +```bash +openclaw gateway run +``` + +## 安全性預設值 + +- `channels.irc.dmPolicy` 預設為 `"pairing"`。 +- `channels.irc.groupPolicy` 預設為 `"allowlist"`。 +- 使用 `groupPolicy="allowlist"` 時,請設定 `channels.irc.groups` 來定義允許的頻道。 +- 除非你刻意接受純文字傳輸,否則請使用 TLS(`channels.irc.tls=true`)。 + +## 存取控制 + +IRC 頻道有兩個獨立的「關卡」: + +1. **頻道存取**(`groupPolicy` + `groups`):機器人是否會接受來自某個頻道的訊息。 +2. **傳送者存取**(`groupAllowFrom` / 每頻道 `groups["#channel"].allowFrom`):誰可以在該頻道內觸發機器人。 + +設定鍵: + +- 私訊允許清單(私訊傳送者存取):`channels.irc.allowFrom` +- 群組傳送者允許清單(頻道傳送者存取):`channels.irc.groupAllowFrom` +- 每頻道控制(頻道 + 傳送者 + 提及規則):`channels.irc.groups["#channel"]` +- `channels.irc.groupPolicy="open"` 允許未設定的頻道(**預設仍受提及限制**) + +允許清單項目應使用穩定的傳送者身分(`nick!user@host`)。 +裸暱稱比對是可變的,只有在 `channels.irc.dangerouslyAllowNameMatching: true` 時才會啟用。 + +### 常見陷阱:`allowFrom` 用於私訊,不是頻道 + +如果你看到如下記錄: + +- `irc: drop group sender alice!ident@host (policy=allowlist)` + +……這表示該傳送者未被允許傳送**群組/頻道**訊息。可用以下任一方式修正: + +- 設定 `channels.irc.groupAllowFrom`(套用於所有頻道的全域設定),或 +- 設定每頻道傳送者允許清單:`channels.irc.groups["#channel"].allowFrom` + +範例(允許 `#tuirc-dev` 中任何人與機器人對話): + +```json5 +{ + channels: { + irc: { + groupPolicy: "allowlist", + groups: { + "#tuirc-dev": { allowFrom: ["*"] }, + }, + }, + }, +} +``` + +## 回覆觸發(提及) + +即使頻道已被允許(透過 `groupPolicy` + `groups`)且傳送者已被允許,OpenClaw 在群組情境中預設仍會採用**提及限制**。 + +這表示你可能會看到類似 `drop channel … (missing-mention)` 的記錄,除非訊息包含符合機器人的提及模式。 + +若要讓機器人在 IRC 頻道中**不需要提及即可回覆**,請停用該頻道的提及限制: + +```json5 +{ + channels: { + irc: { + groupPolicy: "allowlist", + groups: { + "#tuirc-dev": { + requireMention: false, + allowFrom: ["*"], + }, + }, + }, + }, +} +``` + +或者,若要允許**所有** IRC 頻道(不使用每頻道允許清單),且仍可不需提及就回覆: + +```json5 +{ + channels: { + irc: { + groupPolicy: "open", + groups: { + "*": { requireMention: false, allowFrom: ["*"] }, + }, + }, + }, +} +``` + +## 安全性注意事項(建議用於公開頻道) + +如果你在公開頻道中允許 `allowFrom: ["*"]`,任何人都可以提示機器人。 +若要降低風險,請限制該頻道可用的工具。 + +### 頻道內所有人使用相同工具 + +```json5 +{ + channels: { + irc: { + groups: { + "#tuirc-dev": { + allowFrom: ["*"], + tools: { + deny: ["group:runtime", "group:fs", "gateway", "nodes", "cron", "browser"], + }, + }, + }, + }, + }, +} +``` + +### 依傳送者使用不同工具(擁有者取得更多權限) + +使用 `toolsBySender`,對 `"*"` 套用較嚴格的政策,對你的暱稱套用較寬鬆的政策: + +```json5 +{ + channels: { + irc: { + groups: { + "#tuirc-dev": { + allowFrom: ["*"], + toolsBySender: { + "*": { + deny: ["group:runtime", "group:fs", "gateway", "nodes", "cron", "browser"], + }, + "id:eigen": { + deny: ["gateway", "nodes", "cron"], + }, + }, + }, + }, + }, + }, +} +``` + +注意事項: + +- `toolsBySender` 鍵應對 IRC 傳送者身分值使用 `id:`: + `id:eigen`,或使用 `id:eigen!~eigen@174.127.248.171` 進行更強的比對。 +- 舊版未加前綴的鍵仍會被接受,並且只會以 `id:` 進行比對。 +- 第一個相符的傳送者政策會生效;`"*"` 是萬用字元後備項目。 + +若要深入了解群組存取與提及限制(以及它們如何互動),請參閱:[/channels/groups](/zh-TW/channels/groups)。 + +## NickServ + +若要在連線後向 NickServ 識別身分: + +```json5 +{ + channels: { + irc: { + nickserv: { + enabled: true, + service: "NickServ", + password: "your-nickserv-password", + }, + }, + }, +} +``` + +連線時可選的一次性註冊: + +```json5 +{ + channels: { + irc: { + nickserv: { + register: true, + registerEmail: "bot@example.com", + }, + }, + }, +} +``` + +暱稱註冊完成後,請停用 `register`,以避免重複嘗試 REGISTER。 + +## 環境變數 + +預設帳號支援: + +- `IRC_HOST` +- `IRC_PORT` +- `IRC_TLS` +- `IRC_NICK` +- `IRC_USERNAME` +- `IRC_REALNAME` +- `IRC_PASSWORD` +- `IRC_CHANNELS`(逗號分隔) +- `IRC_NICKSERV_PASSWORD` +- `IRC_NICKSERV_REGISTER_EMAIL` + +`IRC_HOST` 不能從工作區 `.env` 設定;請參閱[工作區 `.env` 檔案](/zh-TW/gateway/security)。 + +## 疑難排解 + +- 如果機器人已連線但從不在頻道中回覆,請確認 `channels.irc.groups` **以及**提及限制是否正在丟棄訊息(`missing-mention`)。如果你希望它不需要 ping 就回覆,請為該頻道設定 `requireMention:false`。 +- 如果登入失敗,請確認暱稱可用性和伺服器密碼。 +- 如果自訂網路上的 TLS 失敗,請確認主機/連接埠和憑證設定。 + +## 相關內容 + +- [頻道概覽](/zh-TW/channels) — 所有支援的頻道 +- [配對](/zh-TW/channels/pairing) — 私訊驗證與配對流程 +- [群組](/zh-TW/channels/groups) — 群組聊天行為與提及限制 +- [頻道路由](/zh-TW/channels/channel-routing) — 訊息的工作階段路由 +- [安全性](/zh-TW/gateway/security) — 存取模型與強化措施 diff --git a/docs/zh-TW/channels/line.md b/docs/zh-TW/channels/line.md new file mode 100644 index 000000000..78a82e15d --- /dev/null +++ b/docs/zh-TW/channels/line.md @@ -0,0 +1,235 @@ +--- +read_when: + - 您想要將 OpenClaw 連接到 LINE + - 你需要設定 LINE Webhook 與憑證 + - 你想要 LINE 專用的訊息選項 +summary: LINE Messaging API Plugin 的設定、組態與使用方式 +title: 行 +x-i18n: + generated_at: "2026-04-30T02:47:38Z" + model: gpt-5.5 + provider: openai + source_hash: e9f06d882f1e8d2a758e50459fadefd77796a68c28f63bef5790eb1b540c17d1 + source_path: channels/line.md + workflow: 16 +--- + +LINE 透過 LINE Messaging API 連接到 OpenClaw。此 Plugin 會在 Gateway 上作為 Webhook +接收器執行,並使用你的通道存取權杖 + 通道密鑰進行驗證。 + +狀態:內建 Plugin。支援直接訊息、群組聊天、媒體、位置、Flex +訊息、範本訊息與快速回覆。不支援回應與討論串。 + +## 內建 Plugin + +LINE 在目前的 OpenClaw 版本中作為內建 Plugin 隨附,因此一般 +封裝建置不需要另行安裝。 + +如果你使用的是較舊的建置,或排除 LINE 的自訂安裝,請在 npm 套件發布後安裝 +目前的 npm 套件: + +```bash +openclaw plugins install @openclaw/line +``` + +如果 npm 回報 OpenClaw 擁有的套件已淘汰或不存在,請使用 +目前封裝的 OpenClaw 建置或本機 checkout,直到 npm 套件發布流程 +趕上。 + +本機 checkout(從 git repo 執行時): + +```bash +openclaw plugins install ./path/to/local/line-plugin +``` + +## 設定 + +1. 建立 LINE Developers 帳號並開啟 Console: + [https://developers.line.biz/console/](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。 + +安全性注意事項: + +- LINE 簽章驗證取決於請求本文(對原始本文做 HMAC),因此 OpenClaw 會在驗證前套用嚴格的預驗證本文大小限制與逾時。 +- OpenClaw 會從已驗證的原始請求位元組處理 Webhook 事件。為了簽章完整性安全,會忽略上游中介軟體轉換過的 `req.body` 值。 + +## 設定 + +最小設定: + +```json5 +{ + channels: { + line: { + enabled: true, + channelAccessToken: "LINE_CHANNEL_ACCESS_TOKEN", + channelSecret: "LINE_CHANNEL_SECRET", + dmPolicy: "pairing", + }, + }, +} +``` + +環境變數(僅限預設帳號): + +- `LINE_CHANNEL_ACCESS_TOKEN` +- `LINE_CHANNEL_SECRET` + +權杖/密鑰檔案: + +```json5 +{ + channels: { + line: { + tokenFile: "/path/to/line-token.txt", + secretFile: "/path/to/line-secret.txt", + }, + }, +} +``` + +`tokenFile` 與 `secretFile` 必須指向一般檔案。符號連結會被拒絕。 + +多個帳號: + +```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`:允許傳送 DM 的 LINE 使用者 ID +- `channels.line.groupPolicy`:`allowlist | open | disabled` +- `channels.line.groupAllowFrom`:允許在群組中傳送訊息的 LINE 使用者 ID +- 個別群組覆寫:`channels.line.groups..allowFrom` +- 執行階段注意事項:如果 `channels.line` 完全不存在,執行階段會在群組檢查時回退到 `groupPolicy="allowlist"`(即使已設定 `channels.defaults.groupPolicy`)。 + +LINE ID 區分大小寫。有效 ID 如下: + +- 使用者:`U` + 32 個十六進位字元 +- 群組:`C` + 32 個十六進位字元 +- 聊天室:`R` + 32 個十六進位字元 + +## 訊息行為 + +- 文字會以 5000 個字元為一段進行分段。 +- Markdown 格式會被移除;程式碼區塊與表格會在可行時轉換成 Flex + 卡片。 +- 串流回應會被緩衝;Agent 工作期間,LINE 會收到完整分段並顯示載入 + 動畫。 +- 媒體下載受 `channels.line.mediaMaxMb` 限制(預設 10)。 +- 傳入媒體會先儲存在 `~/.openclaw/media/inbound/` 下,再傳給 + Agent,與其他內建通道 Plugin 使用的共用媒體儲存區一致。 + +## 通道資料(豐富訊息) + +使用 `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 payload */ + }, + }, + templateMessage: { + type: "confirm", + text: "Proceed?", + confirmLabel: "Yes", + confirmData: "yes", + cancelLabel: "No", + cancelData: "no", + }, + }, + }, +} +``` + +LINE Plugin 也隨附 `/card` 命令,可用於 Flex 訊息預設: + +``` +/card info "Welcome" "Thanks for joining!" +``` + +## ACP 支援 + +LINE 支援 ACP(Agent Communication Protocol)對話繫結: + +- `/acp spawn --bind here` 會將目前 LINE 聊天繫結到 ACP 工作階段,而不建立子討論串。 +- 已設定的 ACP 繫結與作用中的對話繫結 ACP 工作階段,在 LINE 上的運作方式與其他對話通道相同。 + +詳情請參閱 [ACP Agent](/zh-TW/tools/acp-agents)。 + +## 傳出媒體 + +LINE Plugin 支援透過 Agent 訊息工具傳送圖片、影片與音訊檔案。媒體會透過 LINE 專用的傳遞路徑送出,並具備適當的預覽與追蹤處理: + +- **圖片**:作為 LINE 圖片訊息傳送,並自動產生預覽。 +- **影片**:傳送時明確處理預覽與內容類型。 +- **音訊**:作為 LINE 音訊訊息傳送。 + +傳出媒體 URL 必須是公開 HTTPS URL。OpenClaw 會先驗證目標主機名稱,再將 URL 交給 LINE,並拒絕 loopback、link-local 與私人網路目標。 + +當 LINE 專用路徑不可用時,一般媒體傳送會回退到既有的僅圖片路由。 + +## 疑難排解 + +- **Webhook 驗證失敗:** 確認 Webhook URL 使用 HTTPS,且 + `channelSecret` 與 LINE console 相符。 +- **沒有傳入事件:** 確認 Webhook 路徑符合 `channels.line.webhookPath`, + 且 LINE 能連線到 Gateway。 +- **媒體下載錯誤:** 如果媒體超過預設限制,請提高 `channels.line.mediaMaxMb`。 + +## 相關 + +- [通道概觀](/zh-TW/channels) — 所有支援的通道 +- [配對](/zh-TW/channels/pairing) — DM 驗證與配對流程 +- [群組](/zh-TW/channels/groups) — 群組聊天行為與提及門檻 +- [通道路由](/zh-TW/channels/channel-routing) — 訊息的工作階段路由 +- [安全性](/zh-TW/gateway/security) — 存取模型與強化 diff --git a/docs/zh-TW/channels/location.md b/docs/zh-TW/channels/location.md new file mode 100644 index 000000000..a090ce5e0 --- /dev/null +++ b/docs/zh-TW/channels/location.md @@ -0,0 +1,78 @@ +--- +read_when: + - 新增或修改頻道位置解析 + - 在代理提示詞或工具中使用位置情境欄位 +summary: 傳入頻道位置解析(Telegram/WhatsApp/Matrix)和上下文欄位 +title: 通道位置解析 +x-i18n: + generated_at: "2026-04-30T02:47:31Z" + model: gpt-5.5 + provider: openai + source_hash: 19c10a55e30c70a7af5d041f9a25c0a2783e3191403e7c0cedfbe7dd8f1a77c1 + source_path: channels/location.md + workflow: 16 +--- + +OpenClaw 會將聊天頻道分享的位置正規化為: + +- 附加到傳入本文的簡短座標文字,以及 +- 自動回覆情境承載中的結構化欄位。頻道提供的標籤、地址和說明/留言會透過共用的不受信任中繼資料 JSON 區塊轉譯到提示中,而不是內嵌在使用者本文裡。 + +目前支援: + +- **Telegram**(位置圖釘 + 場所 + 即時位置) +- **WhatsApp**(locationMessage + liveLocationMessage) +- **Matrix**(含有 `geo_uri` 的 `m.location`) + +## 文字格式 + +位置會轉譯為不含括號的友善行: + +- 圖釘: + - `📍 48.858844, 2.294351 ±12m` +- 具名地點: + - `📍 48.858844, 2.294351 ±12m` +- 即時分享: + - `🛰 Live location: 48.858844, 2.294351 ±12m` + +如果頻道包含標籤、地址或說明/留言,會保留在情境承載中,並以加上圍欄的不受信任 JSON 顯示在提示中: + +````text +Location (untrusted metadata): +```json +{ + "latitude": 48.858844, + "longitude": 2.294351, + "name": "Eiffel Tower", + "address": "Champ de Mars, Paris", + "caption": "Meet here" +} +``` +```` + +## 情境欄位 + +當存在位置時,這些欄位會加入 `ctx`: + +- `LocationLat`(數字) +- `LocationLon`(數字) +- `LocationAccuracy`(數字,公尺;選用) +- `LocationName`(字串;選用) +- `LocationAddress`(字串;選用) +- `LocationSource`(`pin | place | live`) +- `LocationIsLive`(布林值) +- `LocationCaption`(字串;選用) + +提示轉譯器會將 `LocationName`、`LocationAddress` 和 `LocationCaption` 視為不受信任的中繼資料,並透過與其他頻道情境相同的有界 JSON 路徑將它們序列化。 + +## 頻道附註 + +- **Telegram**:場所會對應到 `LocationName/LocationAddress`;即時位置使用 `live_period`。 +- **WhatsApp**:`locationMessage.comment` 和 `liveLocationMessage.caption` 會填入 `LocationCaption`。 +- **Matrix**:`geo_uri` 會剖析為圖釘位置;高度會被忽略,且 `LocationIsLive` 一律為 false。 + +## 相關 + +- [位置命令(節點)](/zh-TW/nodes/location-command) +- [相機擷取](/zh-TW/nodes/camera) +- [媒體理解](/zh-TW/nodes/media-understanding) diff --git a/docs/zh-TW/channels/matrix-migration.md b/docs/zh-TW/channels/matrix-migration.md new file mode 100644 index 000000000..c9c27145b --- /dev/null +++ b/docs/zh-TW/channels/matrix-migration.md @@ -0,0 +1,380 @@ +--- +read_when: + - 升級現有的 Matrix 安裝 + - 遷移加密的 Matrix 歷史記錄與裝置狀態 +summary: OpenClaw 如何就地升級舊版 Matrix Plugin,包括加密狀態復原限制與手動復原步驟。 +title: Matrix 遷移 +x-i18n: + generated_at: "2026-04-30T02:47:39Z" + model: gpt-5.5 + provider: openai + source_hash: fff409eef1b7da7be4b63d8459a62b8365a04adf989f271a2f2c4aef46e90716 + source_path: channels/matrix-migration.md + workflow: 16 +--- + +從先前公開的 `matrix` Plugin 升級到目前實作。 + +對大多數使用者而言,升級會就地完成: + +- Plugin 保持為 `@openclaw/matrix` +- 通道保持為 `matrix` +- 你的設定保持在 `channels.matrix` 下 +- 快取的憑證保持在 `~/.openclaw/credentials/matrix/` 下 +- 執行階段狀態保持在 `~/.openclaw/matrix/` 下 + +你不需要重新命名設定鍵,也不需要以新名稱重新安裝 Plugin。 + +## 遷移會自動做什麼 + +當 Gateway 啟動時,以及當你執行 [`openclaw doctor --fix`](/zh-TW/gateway/doctor) 時,OpenClaw 會嘗試自動修復舊的 Matrix 狀態。 +在任何可操作的 Matrix 遷移步驟變更磁碟狀態之前,OpenClaw 會建立或重用一個聚焦的復原快照。 + +當你使用 `openclaw update` 時,確切觸發方式取決於 OpenClaw 的安裝方式: + +- 原始碼安裝會在更新流程期間執行 `openclaw doctor --fix`,然後預設重新啟動 Gateway +- 套件管理器安裝會更新套件、執行一次非互動式 doctor 檢查,然後依賴預設 Gateway 重新啟動,讓啟動流程完成 Matrix 遷移 +- 如果你使用 `openclaw update --no-restart`,由啟動支援的 Matrix 遷移會延後到你稍後執行 `openclaw doctor --fix` 並重新啟動 Gateway 時 + +自動遷移涵蓋: + +- 在 `~/Backups/openclaw-migrations/` 下建立或重用遷移前快照 +- 重用你快取的 Matrix 憑證 +- 保持相同的帳號選擇和 `channels.matrix` 設定 +- 將最舊的扁平 Matrix 同步儲存移到目前以帳號為範圍的位置 +- 當可以安全解析目標帳號時,將最舊的扁平 Matrix 加密儲存移到目前以帳號為範圍的位置 +- 當舊 rust 加密儲存中本機存在先前儲存的 Matrix 房間金鑰備份解密金鑰時,擷取該金鑰 +- 當存取權杖稍後變更時,為相同的 Matrix 帳號、homeserver 和使用者重用最完整的既有權杖雜湊儲存根目錄 +- 當 Matrix 存取權杖已變更但帳號/裝置身分保持相同時,掃描相鄰的權杖雜湊儲存根目錄以尋找待處理的加密狀態還原中繼資料 +- 在下一次 Matrix 啟動時,將已備份的房間金鑰還原到新的加密儲存中 + +快照詳細資訊: + +- OpenClaw 會在快照成功後,將標記檔寫入 `~/.openclaw/matrix/migration-snapshot.json`,讓稍後的啟動和修復檢查可以重用同一個封存檔。 +- 這些自動 Matrix 遷移快照只會備份設定 + 狀態(`includeWorkspace: false`)。 +- 如果 Matrix 只有警告型遷移狀態,例如因為 `userId` 或 `accessToken` 仍缺失,OpenClaw 還不會建立快照,因為沒有可操作的 Matrix 變更。 +- 如果快照步驟失敗,OpenClaw 會略過該次執行的 Matrix 遷移,而不是在沒有復原點的情況下變更狀態。 + +關於多帳號升級: + +- 最舊的扁平 Matrix 儲存(`~/.openclaw/matrix/bot-storage.json` 和 `~/.openclaw/matrix/crypto/`)來自單一儲存版面,因此 OpenClaw 只能將它遷移到一個已解析的 Matrix 帳號目標 +- 已經以帳號為範圍的舊版 Matrix 儲存會依每個已設定的 Matrix 帳號偵測並準備 + +## 遷移無法自動做什麼 + +先前公開的 Matrix Plugin **不會**自動建立 Matrix 房間金鑰備份。它會保存本機加密狀態並請求裝置驗證,但不保證你的房間金鑰已備份到 homeserver。 + +這表示某些加密安裝只能部分遷移。 + +OpenClaw 無法自動復原: + +- 從未備份的僅本機房間金鑰 +- 目標 Matrix 帳號尚無法解析時的加密狀態,因為 `homeserver`、`userId` 或 `accessToken` 仍不可用 +- 當設定了多個 Matrix 帳號但未設定 `channels.matrix.defaultAccount` 時,無法自動遷移一個共用的扁平 Matrix 儲存 +- 釘選到 repo 路徑而非標準 Matrix 套件的自訂 Plugin 路徑安裝 +- 當舊儲存有已備份金鑰但未在本機保留解密金鑰時,無法取得缺失的復原金鑰 + +目前警告範圍: + +- 自訂 Matrix Plugin 路徑安裝會同時由 Gateway 啟動和 `openclaw doctor` 顯示 + +如果你的舊安裝有從未備份的僅本機加密歷史紀錄,升級後某些較舊的加密訊息可能仍無法讀取。 + +## 建議升級流程 + +1. 正常更新 OpenClaw 和 Matrix Plugin。 + 偏好使用不帶 `--no-restart` 的普通 `openclaw update`,讓啟動流程可以立即完成 Matrix 遷移。 +2. 執行: + + ```bash + openclaw doctor --fix + ``` + + 如果 Matrix 有可操作的遷移工作,doctor 會先建立或重用遷移前快照,並印出封存檔路徑。 + +3. 啟動或重新啟動 Gateway。 +4. 檢查目前驗證和備份狀態: + + ```bash + openclaw matrix verify status + openclaw matrix verify backup status + ``` + +5. 將你正在修復的 Matrix 帳號復原金鑰放入帳號專用環境變數。對單一預設帳號而言,`MATRIX_RECOVERY_KEY` 即可。對多個帳號,請為每個帳號使用一個變數,例如 `MATRIX_RECOVERY_KEY_ASSISTANT`,並在命令中加入 `--account assistant`。 + +6. 如果 OpenClaw 告訴你需要復原金鑰,請針對相符帳號執行命令: + + ```bash + printf '%s\n' "$MATRIX_RECOVERY_KEY" | openclaw matrix verify backup restore --recovery-key-stdin + printf '%s\n' "$MATRIX_RECOVERY_KEY_ASSISTANT" | openclaw matrix verify backup restore --recovery-key-stdin --account assistant + ``` + +7. 如果此裝置仍未驗證,請針對相符帳號執行命令: + + ```bash + printf '%s\n' "$MATRIX_RECOVERY_KEY" | openclaw matrix verify device --recovery-key-stdin + printf '%s\n' "$MATRIX_RECOVERY_KEY_ASSISTANT" | openclaw matrix verify device --recovery-key-stdin --account assistant + ``` + + 如果復原金鑰已接受且備份可用,但 `Cross-signing verified` + 仍為 `no`,請從另一個 Matrix 用戶端完成自我驗證: + + ```bash + openclaw matrix verify self + ``` + + 在另一個 Matrix 用戶端中接受請求,比對表情符號或十進位數字, + 並且只有在相符時輸入 `yes`。此命令只有在 + `Cross-signing verified` 變為 `yes` 之後才會成功結束。 + +8. 如果你有意放棄無法復原的舊歷史紀錄,並想為未來訊息建立全新的備份基準,請執行: + + ```bash + openclaw matrix verify backup reset --yes + ``` + +9. 如果尚未存在伺服器端金鑰備份,請建立一個以供未來復原: + + ```bash + openclaw matrix verify bootstrap + ``` + +## 加密遷移如何運作 + +加密遷移是兩階段流程: + +1. 如果加密遷移可操作,啟動流程或 `openclaw doctor --fix` 會建立或重用遷移前快照。 +2. 啟動流程或 `openclaw doctor --fix` 會透過啟用中的 Matrix Plugin 安裝檢查舊 Matrix 加密儲存。 +3. 如果找到備份解密金鑰,OpenClaw 會將它寫入新的復原金鑰流程,並將房間金鑰還原標記為待處理。 +4. 在下一次 Matrix 啟動時,OpenClaw 會自動將已備份的房間金鑰還原到新的加密儲存中。 + +如果舊儲存回報有從未備份的房間金鑰,OpenClaw 會發出警告,而不是假裝復原成功。 + +## 常見訊息及其含義 + +### 升級與偵測訊息 + +`Matrix plugin upgraded in place.` + +- 含義:偵測到舊的磁碟 Matrix 狀態,並已遷移到目前版面。 +- 要做什麼:除非同一輸出也包含警告,否則不需要做任何事。 + +`Matrix migration snapshot created before applying Matrix upgrades.` + +- 含義:OpenClaw 在變更 Matrix 狀態之前建立了復原封存檔。 +- 要做什麼:保留印出的封存檔路徑,直到你確認遷移成功。 + +`Matrix migration snapshot reused before applying Matrix upgrades.` + +- 含義:OpenClaw 找到既有的 Matrix 遷移快照標記,並重用該封存檔,而不是建立重複備份。 +- 要做什麼:保留印出的封存檔路徑,直到你確認遷移成功。 + +`Legacy Matrix state detected at ... but channels.matrix is not configured yet.` + +- 含義:舊的 Matrix 狀態存在,但 OpenClaw 無法將它對應到目前 Matrix 帳號,因為 Matrix 尚未設定。 +- 要做什麼:設定 `channels.matrix`,然後重新執行 `openclaw doctor --fix` 或重新啟動 Gateway。 + +`Legacy Matrix state detected at ... but the new account-scoped target could not be resolved yet (need homeserver, userId, and access token for channels.matrix...).` + +- 含義:OpenClaw 找到舊狀態,但仍無法判定確切的目前帳號/裝置根目錄。 +- 要做什麼:使用可運作的 Matrix 登入啟動 Gateway 一次,或在快取憑證存在後重新執行 `openclaw doctor --fix`。 + +`Legacy Matrix state detected at ... but multiple Matrix accounts are configured and channels.matrix.defaultAccount is not set.` + +- 含義:OpenClaw 找到一個共用的扁平 Matrix 儲存,但拒絕猜測哪個具名 Matrix 帳號應該接收它。 +- 要做什麼:將 `channels.matrix.defaultAccount` 設為預期帳號,然後重新執行 `openclaw doctor --fix` 或重新啟動 Gateway。 + +`Matrix legacy sync store not migrated because the target already exists (...)` + +- 含義:新的以帳號為範圍的位置已經有同步或加密儲存,因此 OpenClaw 沒有自動覆寫它。 +- 要做什麼:在手動移除或移動衝突目標之前,確認目前帳號是正確帳號。 + +`Failed migrating Matrix legacy sync store (...)` 或 `Failed migrating Matrix legacy crypto store (...)` + +- 含義:OpenClaw 嘗試移動舊 Matrix 狀態,但檔案系統操作失敗。 +- 要做什麼:檢查檔案系統權限和磁碟狀態,然後重新執行 `openclaw doctor --fix`。 + +`Legacy Matrix encrypted state detected at ... but channels.matrix is not configured yet.` + +- 含義:OpenClaw 找到舊的加密 Matrix 儲存,但沒有目前 Matrix 設定可附加到它。 +- 要做什麼:設定 `channels.matrix`,然後重新執行 `openclaw doctor --fix` 或重新啟動 Gateway。 + +`Legacy Matrix encrypted state detected at ... but the account-scoped target could not be resolved yet (need homeserver, userId, and access token for channels.matrix...).` + +- 含義:加密儲存存在,但 OpenClaw 無法安全判定它屬於哪個目前帳號/裝置。 +- 要做什麼:使用可運作的 Matrix 登入啟動 Gateway 一次,或在快取憑證可用後重新執行 `openclaw doctor --fix`。 + +`Legacy Matrix encrypted state detected at ... but multiple Matrix accounts are configured and channels.matrix.defaultAccount is not set.` + +- 含義:OpenClaw 找到一個共用的扁平舊版加密儲存,但拒絕猜測哪個具名 Matrix 帳號應該接收它。 +- 要做什麼:將 `channels.matrix.defaultAccount` 設為預期帳號,然後重新執行 `openclaw doctor --fix` 或重新啟動 Gateway。 + +`Matrix migration warnings are present, but no on-disk Matrix mutation is actionable yet. No pre-migration snapshot was needed.` + +- 含義:OpenClaw 偵測到舊 Matrix 狀態,但遷移仍因缺少身分或憑證資料而受阻。 +- 要做什麼:完成 Matrix 登入或設定配置,然後重新執行 `openclaw doctor --fix` 或重新啟動 Gateway。 + +`Legacy Matrix encrypted state was detected, but the Matrix plugin helper is unavailable. Install or repair @openclaw/matrix so OpenClaw can inspect the old rust crypto store before upgrading.` + +- 意義:OpenClaw 找到舊的加密 Matrix 狀態,但無法從 Matrix Plugin 載入通常會檢查該儲存區的輔助進入點。 +- 處理方式:重新安裝或修復 Matrix Plugin(`openclaw plugins install @openclaw/matrix`,或針對 repo checkout 使用 `openclaw plugins install ./path/to/local/matrix-plugin`),然後重新執行 `openclaw doctor --fix` 或重新啟動 Gateway。 +- 如果 npm 回報 OpenClaw 擁有的 Matrix 套件已棄用,請使用目前封裝版 OpenClaw 建置中隨附的 + Plugin,或使用本機 checkout 路徑,直到發布較新的 npm 套件為止。 + +`Matrix plugin helper path is unsafe: ... Reinstall @openclaw/matrix and try again.` + +- 意義:OpenClaw 找到的輔助檔案路徑會跳出 Plugin 根目錄,或未通過 Plugin 邊界檢查,因此拒絕匯入它。 +- 處理方式:從受信任的路徑重新安裝 Matrix Plugin,然後重新執行 `openclaw doctor --fix` 或重新啟動 Gateway。 + +`- Failed creating a Matrix migration snapshot before repair: ...` + +`- Skipping Matrix migration changes for now. Resolve the snapshot failure, then rerun "openclaw doctor --fix".` + +- 意義:OpenClaw 拒絕修改 Matrix 狀態,因為它無法先建立復原快照。 +- 處理方式:解決備份錯誤,然後重新執行 `openclaw doctor --fix` 或重新啟動 Gateway。 + +`Failed migrating legacy Matrix client storage: ...` + +- 意義:Matrix 用戶端側備援流程找到舊的扁平儲存區,但移動失敗。OpenClaw 現在會中止該備援流程,而不是在沒有提示的情況下以全新儲存區啟動。 +- 處理方式:檢查檔案系統權限或衝突,保留舊狀態不變,並在修正錯誤後重試。 + +`Matrix is installed from a custom path: ...` + +- 意義:Matrix 已釘選為路徑安裝,因此主線更新不會自動以 repo 的標準 Matrix 套件取代它。 +- 處理方式:當你想回到預設 Matrix Plugin 時,使用 `openclaw plugins install @openclaw/matrix` 重新安裝。 +- 如果 npm 回報 OpenClaw 擁有的 Matrix 套件已棄用,請使用目前封裝版 OpenClaw 建置中隨附的 + Plugin,直到發布較新的 npm 套件為止。 + +### 加密狀態復原訊息 + +`matrix: restored X/Y room key(s) from legacy encrypted-state backup` + +- 意義:已備份的房間金鑰已成功還原到新的加密儲存區。 +- 處理方式:通常不需要做任何事。 + +`matrix: N legacy local-only room key(s) were never backed up and could not be restored automatically` + +- 意義:部分舊房間金鑰只存在舊的本機儲存區,且從未上傳到 Matrix 備份。 +- 處理方式:除非你能從另一個已驗證的用戶端手動復原那些金鑰,否則應預期部分舊的加密歷史記錄仍無法使用。 + +`Legacy Matrix encrypted state for account "..." has backed-up room keys, but no local backup decryption key was found. Ask the operator to run "openclaw matrix verify backup restore --recovery-key-stdin" after upgrade if they have the recovery key.` + +- 意義:備份存在,但 OpenClaw 無法自動復原復原金鑰。 +- 處理方式:執行 `printf '%s\n' "$MATRIX_RECOVERY_KEY" | openclaw matrix verify backup restore --recovery-key-stdin`。 + +`Failed inspecting legacy Matrix encrypted state for account "..." (...): ...` + +- 意義:OpenClaw 找到舊的加密儲存區,但無法以足夠安全的方式檢查它以準備復原。 +- 處理方式:重新執行 `openclaw doctor --fix`。如果重複發生,請保留舊狀態目錄不變,並使用另一個已驗證的 Matrix 用戶端加上 `printf '%s\n' "$MATRIX_RECOVERY_KEY" | openclaw matrix verify backup restore --recovery-key-stdin` 進行復原。 + +`Legacy Matrix backup key was found for account "...", but .../recovery-key.json already contains a different recovery key. Leaving the existing file unchanged.` + +- 意義:OpenClaw 偵測到備份金鑰衝突,並拒絕自動覆寫目前的 recovery-key 檔案。 +- 處理方式:在重試任何還原命令之前,先確認哪個復原金鑰才是正確的。 + +`Legacy Matrix encrypted state for account "..." cannot be fully converted automatically because the old rust crypto store does not expose all local room keys for export.` + +- 意義:這是舊儲存格式的硬性限制。 +- 處理方式:已備份的金鑰仍可還原,但僅存在本機的加密歷史記錄可能仍無法使用。 + +`matrix: failed restoring room keys from legacy encrypted-state backup: ...` + +- 意義:新的 Plugin 嘗試還原,但 Matrix 回傳錯誤。 +- 處理方式:執行 `openclaw matrix verify backup status`,必要時再使用 `printf '%s\n' "$MATRIX_RECOVERY_KEY" | openclaw matrix verify backup restore --recovery-key-stdin` 重試。 + +### 手動復原訊息 + +`Backup key is not loaded on this device. Run 'openclaw matrix verify backup restore' to load it and restore old room keys.` + +- 意義:OpenClaw 知道你應該有備份金鑰,但它目前未在此裝置上啟用。 +- 處理方式:執行 `openclaw matrix verify backup restore`,或必要時設定 `MATRIX_RECOVERY_KEY` 並執行 `printf '%s\n' "$MATRIX_RECOVERY_KEY" | openclaw matrix verify backup restore --recovery-key-stdin`。 + +`Store a recovery key with 'openclaw matrix verify device --recovery-key-stdin', then run 'openclaw matrix verify backup restore'.` + +- 意義:此裝置目前沒有儲存復原金鑰。 +- 處理方式:設定 `MATRIX_RECOVERY_KEY`,執行 `printf '%s\n' "$MATRIX_RECOVERY_KEY" | openclaw matrix verify device --recovery-key-stdin`,然後還原備份。 + +`Backup key mismatch on this device. Re-run 'openclaw matrix verify device --recovery-key-stdin' with the matching recovery key.` + +- 意義:已儲存的金鑰與作用中的 Matrix 備份不相符。 +- 處理方式:將 `MATRIX_RECOVERY_KEY` 設為正確的金鑰,並執行 `printf '%s\n' "$MATRIX_RECOVERY_KEY" | openclaw matrix verify device --recovery-key-stdin`。 + +如果你接受失去無法復原的舊加密歷史記錄,也可以改用 +`openclaw matrix verify backup reset --yes` 重設目前的備份基準。當已儲存的備份秘密損壞時,該重設也可能重新建立秘密儲存區,讓新的備份金鑰在重新啟動後能正確載入。 + +`Backup trust chain is not verified on this device. Re-run 'openclaw matrix verify device --recovery-key-stdin'.` + +- 意義:備份存在,但此裝置尚未充分信任交叉簽署鏈。 +- 處理方式:設定 `MATRIX_RECOVERY_KEY` 並執行 `printf '%s\n' "$MATRIX_RECOVERY_KEY" | openclaw matrix verify device --recovery-key-stdin`。 + +`Matrix recovery key is required` + +- 意義:你嘗試執行需要復原金鑰的復原步驟,但未提供復原金鑰。 +- 處理方式:使用 `--recovery-key-stdin` 重新執行命令,例如 `printf '%s\n' "$MATRIX_RECOVERY_KEY" | openclaw matrix verify device --recovery-key-stdin`。 + +`Invalid Matrix recovery key: ...` + +- 意義:提供的金鑰無法解析,或不符合預期格式。 +- 處理方式:使用你的 Matrix 用戶端或 recovery-key 檔案中的確切復原金鑰重試。 + +`Matrix recovery key was applied, but this device still lacks full Matrix identity trust.` + +- 意義:OpenClaw 可以套用復原金鑰,但 Matrix 仍尚未為此裝置 + 建立完整的交叉簽署身分信任。請檢查命令輸出中的 `Recovery key accepted`、`Backup usable`、 + `Cross-signing verified` 和 `Device verified by owner`。 +- 處理方式:執行 `openclaw matrix verify self`,在另一個 + Matrix 用戶端接受請求,比對 SAS,並且只有在相符時輸入 `yes`。該 + 命令會等待完整的 Matrix 身分信任後才回報成功。只有在你有意 + 取代目前的交叉簽署身分時,才使用 + `printf '%s\n' "$MATRIX_RECOVERY_KEY" | openclaw matrix verify bootstrap --recovery-key-stdin --force-reset-cross-signing`。 + +`Matrix key backup is not active on this device after loading from secret storage.` + +- 意義:秘密儲存區未在此裝置上產生活動的備份工作階段。 +- 處理方式:先驗證裝置,然後使用 `openclaw matrix verify backup status` 重新檢查。 + +`Matrix crypto backend cannot load backup keys from secret storage. Verify this device with 'openclaw matrix verify device --recovery-key-stdin' first.` + +- 意義:此裝置在完成裝置驗證前,無法從秘密儲存區還原。 +- 處理方式:先執行 `printf '%s\n' "$MATRIX_RECOVERY_KEY" | openclaw matrix verify device --recovery-key-stdin`。 + +### 自訂 Plugin 安裝訊息 + +`Matrix is installed from a custom path that no longer exists: ...` + +- 意義:你的 Plugin 安裝記錄指向一個已不存在的本機路徑。 +- 處理方式:使用 `openclaw plugins install @openclaw/matrix` 重新安裝;如果你是從 repo checkout 執行,則使用 `openclaw plugins install ./path/to/local/matrix-plugin`。 +- 如果 npm 回報 OpenClaw 擁有的 Matrix 套件已棄用,請使用目前封裝版 OpenClaw 建置中隨附的 + Plugin,或使用本機 checkout 路徑,直到發布較新的 npm 套件為止。 + +## 如果加密歷史記錄仍未恢復 + +依序執行以下檢查: + +```bash +openclaw matrix verify status --verbose +openclaw matrix verify backup status --verbose +printf '%s\n' "$MATRIX_RECOVERY_KEY" | openclaw matrix verify backup restore --recovery-key-stdin --verbose +``` + +如果備份成功還原,但某些舊房間仍缺少歷史記錄,那些遺失的金鑰很可能從未由先前的 Plugin 備份。 + +## 如果你想讓未來訊息從頭開始 + +如果你接受失去無法復原的舊加密歷史記錄,並且只想為往後建立乾淨的備份基準,請依序執行以下命令: + +```bash +openclaw matrix verify backup reset --yes +openclaw matrix verify backup status --verbose +openclaw matrix verify status +``` + +如果裝置在此之後仍未驗證,請從你的 Matrix 用戶端完成驗證:比對 SAS 表情符號或十進位代碼,並確認它們相符。 + +## 相關 + +- [Matrix](/zh-TW/channels/matrix):頻道設定與設定。 +- [Matrix 推送規則](/zh-TW/channels/matrix-push-rules):通知路由。 +- [Doctor](/zh-TW/gateway/doctor):健康檢查與自動遷移觸發器。 +- [遷移指南](/zh-TW/install/migrating):所有遷移路徑(機器搬移、跨系統匯入)。 +- [Plugin](/zh-TW/tools/plugin):Plugin 安裝與註冊。 diff --git a/docs/zh-TW/channels/matrix-push-rules.md b/docs/zh-TW/channels/matrix-push-rules.md new file mode 100644 index 000000000..5d5dabafb --- /dev/null +++ b/docs/zh-TW/channels/matrix-push-rules.md @@ -0,0 +1,157 @@ +--- +read_when: + - 為自行託管的 Synapse 或 Tuwunel 設定 Matrix 靜默串流 + - 使用者希望只在區塊完成時收到通知,而不是每次預覽編輯時都收到通知 +summary: 用於靜默完成預覽編輯的逐收件者 Matrix 推送規則 +title: 用於靜音預覽的 Matrix 推播規則 +x-i18n: + generated_at: "2026-04-30T02:47:44Z" + model: gpt-5.5 + provider: openai + source_hash: e2f037a50a85b350163c74cf6b9cce335ecaaa5cccc762124122ad6d0321a1fa + source_path: channels/matrix-push-rules.md + workflow: 16 +--- + +當 `channels.matrix.streaming` 為 `"quiet"` 時,OpenClaw 會就地編輯單一預覽事件,並以自訂內容旗標標記最終編輯。只有當每位使用者的推送規則符合該旗標時,Matrix 用戶端才會在最終編輯時通知。此頁面適用於自行託管 Matrix,並想為每個接收者帳號安裝該規則的維運人員。 + +如果你只想使用標準的 Matrix 通知行為,請使用 `streaming: "partial"` 或關閉串流。請參閱 [Matrix 頻道設定](/zh-TW/channels/matrix#streaming-previews)。 + +## 先決條件 + +- 接收者使用者 = 應該收到通知的人 +- 機器人使用者 = 傳送回覆的 OpenClaw Matrix 帳號 +- 下方 API 呼叫請使用接收者使用者的存取權杖 +- 在推送規則中將 `sender` 比對為機器人使用者的完整 MXID +- 接收者帳號必須已經有可運作的推送器 — 靜默預覽規則只有在一般 Matrix 推送傳遞健全時才會運作 + +## 步驟 + + + + +```json5 +{ + channels: { + matrix: { + streaming: "quiet", + }, + }, +} +``` + + + + + 盡可能重用現有用戶端工作階段權杖。若要核發新的權杖: + +```bash +curl -sS -X POST \ + "https://matrix.example.org/_matrix/client/v3/login" \ + -H "Content-Type: application/json" \ + --data '{ + "type": "m.login.password", + "identifier": { "type": "m.id.user", "user": "@alice:example.org" }, + "password": "REDACTED" + }' +``` + + + + + +```bash +curl -sS \ + -H "Authorization: Bearer $USER_ACCESS_TOKEN" \ + "https://matrix.example.org/_matrix/client/v3/pushers" +``` + +如果沒有傳回任何推送器,請先修正此帳號的一般 Matrix 推送傳遞,再繼續。 + + + + + OpenClaw 會以 `content["com.openclaw.finalized_preview"] = true` 標記已最終化的純文字預覽編輯。安裝一條規則,比對該標記以及作為傳送者的機器人 MXID: + +```bash +curl -sS -X PUT \ + "https://matrix.example.org/_matrix/client/v3/pushrules/global/override/openclaw-finalized-preview-botname" \ + -H "Authorization: Bearer $USER_ACCESS_TOKEN" \ + -H "Content-Type: application/json" \ + --data '{ + "conditions": [ + { "kind": "event_match", "key": "type", "pattern": "m.room.message" }, + { + "kind": "event_property_is", + "key": "content.m\\.relates_to.rel_type", + "value": "m.replace" + }, + { + "kind": "event_property_is", + "key": "content.com\\.openclaw\\.finalized_preview", + "value": true + }, + { "kind": "event_match", "key": "sender", "pattern": "@bot:example.org" } + ], + "actions": [ + "notify", + { "set_tweak": "sound", "value": "default" }, + { "set_tweak": "highlight", "value": false } + ] + }' +``` + + 執行前請替換: + + - `https://matrix.example.org`:你的家伺服器基底 URL + - `$USER_ACCESS_TOKEN`:接收者使用者的存取權杖 + - `openclaw-finalized-preview-botname`:每個機器人、每個接收者都唯一的規則 ID(模式:`openclaw-finalized-preview-`) + - `@bot:example.org`:你的 OpenClaw 機器人 MXID,不是接收者的 + + + + + +```bash +curl -sS \ + -H "Authorization: Bearer $USER_ACCESS_TOKEN" \ + "https://matrix.example.org/_matrix/client/v3/pushrules/global/override/openclaw-finalized-preview-botname" +``` + +接著測試串流回覆。在靜默模式中,房間會顯示靜默草稿預覽,並在區塊或回合完成時通知一次。 + + + + +若稍後要移除規則,請使用接收者的權杖對同一個規則 URL 執行 `DELETE`。 + +## 多機器人注意事項 + +推送規則以 `ruleId` 作為鍵:對同一個 ID 重新執行 `PUT` 會更新單一規則。若有多個 OpenClaw 機器人要通知同一個接收者,請為每個機器人建立一條規則,並使用不同的傳送者比對。 + +新的使用者定義 `override` 規則會插入在預設抑制規則之前,因此不需要額外的排序參數。此規則只會影響可就地最終化的純文字預覽編輯;媒體後備與過期預覽後備會使用一般 Matrix 傳遞。 + +## 家伺服器注意事項 + + + + 不需要特殊的 `homeserver.yaml` 變更。如果一般 Matrix 通知已經能送達此使用者,上方的接收者權杖加上 `pushrules` 呼叫就是主要設定步驟。 + + 如果你在反向代理或工作節點後方執行 Synapse,請確認 `/_matrix/client/.../pushrules/` 能正確到達 Synapse。推送傳遞由主程序或 `synapse.app.pusher`/已設定的推送工作節點處理 — 請確認它們都正常運作。 + + 此規則使用 `event_property_is` 推送規則條件(MSC3758,推送規則 v1.10),Synapse 於 2023 年加入此條件。較舊的 Synapse 版本會接受 `PUT pushrules/...` 呼叫,但會默默永遠無法比對條件 — 若最終化預覽編輯沒有送出通知,請升級 Synapse。 + + + + + 流程與 Synapse 相同;最終化預覽標記不需要 Tuwunel 專屬設定。 + + 如果使用者在另一台裝置上處於活動狀態時通知消失,請檢查是否已啟用 `suppress_push_when_active`。Tuwunel 於 1.4.2(2025 年 9 月)加入此選項,且它可以在一台裝置處於活動狀態時刻意抑制傳送到其他裝置的推送。 + + + + +## 相關 + +- [Matrix 頻道設定](/zh-TW/channels/matrix) +- [串流概念](/zh-TW/concepts/streaming) diff --git a/docs/zh-TW/channels/matrix.md b/docs/zh-TW/channels/matrix.md new file mode 100644 index 000000000..dbcb97fd4 --- /dev/null +++ b/docs/zh-TW/channels/matrix.md @@ -0,0 +1,926 @@ +--- +read_when: + - 在 OpenClaw 中設定 Matrix + - 設定 Matrix E2EE 與驗證 +summary: Matrix 支援狀態、設定與組態範例 +title: Matrix +x-i18n: + generated_at: "2026-04-30T02:47:50Z" + model: gpt-5.5 + provider: openai + source_hash: 261b0eaae452cff7bb9ddf8dc67ddda45fb27b6468e95450b19207348d0b577a + source_path: channels/matrix.md + workflow: 16 +--- + +Matrix 是 OpenClaw 隨附的頻道 Plugin。 +它使用官方的 `matrix-js-sdk`,並支援 DM、房間、執行緒、媒體、反應、投票、位置和 E2EE。 + +## 隨附 Plugin + +目前封裝的 OpenClaw 發行版本內建 Matrix Plugin。你不需要安裝任何東西;設定 `channels.matrix.*`(請參閱[設定](#setup))就會啟用它。 + +對於較舊的建置版本,或排除 Matrix 的自訂安裝,請在發布後安裝目前的 npm +套件: + +```bash +openclaw plugins install @openclaw/matrix +``` + +如果 npm 回報 OpenClaw 擁有的套件已被棄用,請使用目前封裝的 +OpenClaw 建置版本或本機 checkout,直到較新的 npm 套件發布為止。 + +從本機 checkout: + +```bash +openclaw plugins install ./path/to/local/matrix-plugin +``` + +`plugins install` 會註冊並啟用 Plugin,因此不需要另外執行 `openclaw plugins enable matrix` 步驟。不過在你設定下方的頻道之前,Plugin 仍然不會執行任何動作。請參閱 [Plugins](/zh-TW/tools/plugin) 了解一般 Plugin 行為與安裝規則。 + +## 設定 + +1. 在你的 homeserver 上建立 Matrix 帳號。 +2. 使用 `homeserver` + `accessToken`,或 `homeserver` + `userId` + `password` 設定 `channels.matrix`。 +3. 重新啟動 Gateway。 +4. 與 bot 開始 DM,或邀請它加入房間(請參閱 [auto-join](#auto-join) — 只有在 `autoJoin` 允許時,新邀請才會進入)。 + +### 互動式設定 + +```bash +openclaw channels add +openclaw configure --section channels +``` + +精靈會詢問:homeserver URL、驗證方法(存取權杖或密碼)、使用者 ID(僅限密碼驗證)、選用的裝置名稱、是否啟用 E2EE,以及是否設定房間存取與 auto-join。 + +如果相符的 `MATRIX_*` 環境變數已存在,且所選帳號沒有已儲存的驗證資訊,精靈會提供環境變數捷徑。若要在儲存 allowlist 前解析房間名稱,請執行 `openclaw channels resolve --channel matrix "Project Room"`。啟用 E2EE 時,精靈會寫入設定,並執行與 [`openclaw matrix encryption setup`](#encryption-and-verification) 相同的 bootstrap。 + +### 最小設定 + +以權杖為基礎: + +```json5 +{ + channels: { + matrix: { + enabled: true, + homeserver: "https://matrix.example.org", + accessToken: "syt_xxx", + dm: { policy: "pairing" }, + }, + }, +} +``` + +以密碼為基礎(首次登入後會快取權杖): + +```json5 +{ + channels: { + matrix: { + enabled: true, + homeserver: "https://matrix.example.org", + userId: "@bot:example.org", + password: "replace-me", // pragma: allowlist secret + deviceName: "OpenClaw Gateway", + }, + }, +} +``` + +### Auto-join + +`channels.matrix.autoJoin` 預設為 `off`。使用預設值時,bot 不會因新邀請而出現在新的房間或 DM 中,直到你手動加入為止。 + +OpenClaw 無法在邀請時判斷受邀房間是 DM 還是群組,因此所有邀請(包括 DM 形式的邀請)都會先經過 `autoJoin`。`dm.policy` 只會在之後套用,也就是 bot 已加入且房間已分類之後。 + + +設定 `autoJoin: "allowlist"` 加上 `autoJoinAllowlist`,可限制 bot 接受哪些邀請;或設定 `autoJoin: "always"` 以接受所有邀請。 + +`autoJoinAllowlist` 只接受穩定目標:`!roomId:server`、`#alias:server` 或 `*`。純房間名稱會被拒絕;alias 項目會根據 homeserver 解析,而不是根據受邀房間宣稱的狀態解析。 + + +```json5 +{ + channels: { + matrix: { + autoJoin: "allowlist", + autoJoinAllowlist: ["!ops:example.org", "#support:example.org"], + groups: { + "!ops:example.org": { requireMention: true }, + }, + }, + }, +} +``` + +若要接受所有邀請,請使用 `autoJoin: "always"`。 + +### Allowlist 目標格式 + +DM 和房間 allowlist 最好填入穩定 ID: + +- DM(`dm.allowFrom`、`groupAllowFrom`、`groups..users`):使用 `@user:server`。只有在 homeserver 目錄剛好回傳一個相符項目時,才會解析顯示名稱。 +- 房間(`groups`、`autoJoinAllowlist`):使用 `!room:server` 或 `#alias:server`。名稱會盡力根據已加入的房間解析;未解析的項目會在執行階段被忽略。 + +### 帳號 ID 正規化 + +精靈會將友善名稱轉換成正規化的帳號 ID。例如,`Ops Bot` 會變成 `ops-bot`。標點符號會在 scoped 環境變數名稱中逸出,避免兩個帳號衝突:`-` → `_X2D_`,因此 `ops-prod` 會對應到 `MATRIX_OPS_X2D_PROD_*`。 + +### 快取的憑證 + +Matrix 會將快取的憑證儲存在 `~/.openclaw/credentials/matrix/` 下: + +- 預設帳號:`credentials.json` +- 命名帳號:`credentials-.json` + +當快取憑證存在於該處時,即使設定檔中沒有存取權杖,OpenClaw 也會將 Matrix 視為已設定 — 這涵蓋設定流程、`openclaw doctor` 和頻道狀態探測。 + +### 環境變數 + +在等效的設定鍵未設定時使用。預設帳號使用未加前綴的名稱;命名帳號會在尾碼前插入帳號 ID。 + +| 預設帳號 | 命名帳號(`` 是正規化的帳號 ID) | +| --------------------- | --------------------------------------------------- | +| `MATRIX_HOMESERVER` | `MATRIX__HOMESERVER` | +| `MATRIX_ACCESS_TOKEN` | `MATRIX__ACCESS_TOKEN` | +| `MATRIX_USER_ID` | `MATRIX__USER_ID` | +| `MATRIX_PASSWORD` | `MATRIX__PASSWORD` | +| `MATRIX_DEVICE_ID` | `MATRIX__DEVICE_ID` | +| `MATRIX_DEVICE_NAME` | `MATRIX__DEVICE_NAME` | +| `MATRIX_RECOVERY_KEY` | `MATRIX__RECOVERY_KEY` | + +對於帳號 `ops`,名稱會變成 `MATRIX_OPS_HOMESERVER`、`MATRIX_OPS_ACCESS_TOKEN`,依此類推。recovery-key 環境變數會由具備 recovery 感知能力的 CLI 流程(`verify backup restore`、`verify device`、`verify bootstrap`)讀取,前提是你透過 `--recovery-key-stdin` 將金鑰 pipe 進去。 + +`MATRIX_HOMESERVER` 不能從 workspace `.env` 設定;請參閱 [Workspace `.env` 檔案](/zh-TW/gateway/security)。 + +## 設定範例 + +包含 DM pairing、房間 allowlist 和 E2EE 的實用基準: + +```json5 +{ + channels: { + matrix: { + enabled: true, + homeserver: "https://matrix.example.org", + accessToken: "syt_xxx", + encryption: true, + + dm: { + policy: "pairing", + sessionScope: "per-room", + threadReplies: "off", + }, + + groupPolicy: "allowlist", + groupAllowFrom: ["@admin:example.org"], + groups: { + "!roomid:example.org": { requireMention: true }, + }, + + autoJoin: "allowlist", + autoJoinAllowlist: ["!roomid:example.org"], + threadReplies: "inbound", + replyToMode: "off", + streaming: "partial", + }, + }, +} +``` + +## 串流預覽 + +Matrix 回覆串流是選擇性啟用的。`streaming` 控制 OpenClaw 如何傳遞進行中的 assistant 回覆;`blockStreaming` 控制每個已完成的區塊是否保留為自己的 Matrix 訊息。 + +```json5 +{ + channels: { + matrix: { + streaming: "partial", + }, + }, +} +``` + +若要保留即時答案預覽,但隱藏暫時性的工具/進度列,請使用物件 +形式: + +```json5 +{ + channels: { + matrix: { + streaming: { + mode: "partial", + preview: { + toolProgress: false, + }, + }, + }, + }, +} +``` + +| `streaming` | 行為 | +| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `"off"`(預設) | 等待完整回覆,然後傳送一次。`true` ↔ `"partial"`,`false` ↔ `"off"`。 | +| `"partial"` | 在模型寫入目前區塊時,就地編輯一則一般文字訊息。標準 Matrix 用戶端可能會在第一次預覽時通知,而不是在最終編輯時通知。 | +| `"quiet"` | 與 `"partial"` 相同,但訊息是非通知 notice。只有當每位使用者的 push rule 符合最終編輯時,收件人才會收到通知(如下所述)。 | + +`blockStreaming` 獨立於 `streaming`: + +| `streaming` | `blockStreaming: true` | `blockStreaming: false`(預設) | +| ----------------------- | ------------------------------------------------------------------- | ---------------------------------------------------- | +| `"partial"` / `"quiet"` | 目前區塊的即時草稿,已完成的區塊保留為訊息 | 目前區塊的即時草稿,並就地完成 | +| `"off"` | 每個完成區塊一則會通知的 Matrix 訊息 | 完整回覆一則會通知的 Matrix 訊息 | + +注意事項: + +- 如果預覽超過 Matrix 的單一事件大小限制,OpenClaw 會停止預覽串流,並退回只傳遞最終內容。 +- 媒體回覆一律正常傳送附件。如果過期預覽無法再安全重用,OpenClaw 會在傳送最終媒體回覆前將其 redact。 +- Matrix 預覽串流啟用時,預設會啟用工具進度預覽更新。設定 `streaming.preview.toolProgress: false` 可保留答案文字的預覽編輯,但讓工具進度走一般傳遞路徑。 +- 預覽編輯會耗費額外的 Matrix API 呼叫。如果你想要最保守的 rate-limit profile,請保留 `streaming: "off"`。 + +## 核准 metadata + +Matrix 原生核准提示是一般 `m.room.message` 事件,其 OpenClaw 專用自訂事件內容位於 `com.openclaw.approval` 下。Matrix 允許自訂事件內容鍵,因此標準用戶端仍會顯示文字 body,而支援 OpenClaw 的用戶端可以讀取結構化的核准 ID、類型、狀態、可用決策,以及 exec/Plugin 詳細資料。 + +當核准提示過長,無法放入單一 Matrix 事件時,OpenClaw 會將可見文字分成多個 chunk,並只將 `com.openclaw.approval` 附加到第一個 chunk。允許/拒絕決策的反應會綁定到該第一個事件,因此長提示會和單一事件提示保持相同的核准目標。 + +### 自行託管的 quiet 最終預覽 push rule + +`streaming: "quiet"` 只會在區塊或 turn 完成後通知收件人 — 每位使用者的 push rule 必須符合最終預覽標記。請參閱 [quiet 預覽的 Matrix push rule](/zh-TW/channels/matrix-push-rules) 取得完整流程(收件人權杖、pusher 檢查、規則安裝、每個 homeserver 的注意事項)。 + +## Bot 對 bot 房間 + +預設情況下,來自其他已設定 OpenClaw Matrix 帳號的 Matrix 訊息會被忽略。 + +當你有意需要 inter-agent Matrix 流量時,請使用 `allowBots`: + +```json5 +{ + channels: { + matrix: { + allowBots: "mentions", // true | "mentions" + groups: { + "!roomid:example.org": { + requireMention: true, + }, + }, + }, + }, +} +``` + +- `allowBots: true` 會接受來自其他已設定 Matrix bot 帳號、且位於允許房間與 DM 中的訊息。 +- `allowBots: "mentions"` 只會在那些訊息於房間中明顯提及此 bot 時接受。DM 仍然允許。 +- `groups..allowBots` 會覆寫單一房間的帳號層級設定。 +- OpenClaw 仍會忽略來自相同 Matrix 使用者 ID 的訊息,以避免自我回覆迴圈。 +- Matrix 在此不公開原生 bot 旗標;OpenClaw 將「bot-authored」視為「由此 OpenClaw Gateway 上另一個已設定的 Matrix 帳號傳送」。 + +在共享房間中啟用 bot 對 bot 流量時,請使用嚴格的房間 allowlist 和提及要求。 + +## 加密與驗證 + +在加密(E2EE)聊天室中,對外送出的圖片事件會使用 `thumbnail_file`,因此圖片預覽會與完整附件一併加密。未加密的聊天室仍使用一般的 `thumbnail_url`。不需要任何設定 — Plugin 會自動偵測 E2EE 狀態。 + +所有 `openclaw matrix` 命令都接受 `--verbose`(完整診斷)、`--json`(機器可讀輸出)以及 `--account `(多帳號設定)。預設輸出簡潔,內部 SDK 記錄會保持安靜。下列範例顯示標準形式;視需要加入旗標。 + +### 啟用加密 + +```bash +openclaw matrix encryption setup +``` + +啟動密鑰儲存與交叉簽署,必要時建立聊天室金鑰備份,然後列印狀態與後續步驟。實用旗標: + +- `--recovery-key ` 在啟動前套用復原金鑰(建議使用下方文件說明的 stdin 形式) +- `--force-reset-cross-signing` 捨棄目前的交叉簽署身分並建立新的身分(僅在有意為之時使用) + +對於新帳號,請在建立時啟用 E2EE: + +```bash +openclaw matrix account add \ + --homeserver https://matrix.example.org \ + --access-token syt_xxx \ + --enable-e2ee +``` + +`--encryption` 是 `--enable-e2ee` 的別名。 + +等效的手動設定: + +```json5 +{ + channels: { + matrix: { + enabled: true, + homeserver: "https://matrix.example.org", + accessToken: "syt_xxx", + encryption: true, + dm: { policy: "pairing" }, + }, + }, +} +``` + +### 狀態與信任訊號 + +```bash +openclaw matrix verify status +openclaw matrix verify status --include-recovery-key --json +``` + +`verify status` 會報告三個獨立的信任訊號(`--verbose` 會顯示全部): + +- `Locally trusted`:僅受此用戶端信任 +- `Cross-signing verified`:SDK 回報已透過交叉簽署驗證 +- `Signed by owner`:由你自己的自我簽署金鑰簽署(僅供診斷) + +只有當 `Cross-signing verified` 為 `yes` 時,`Verified by owner` 才會變成 `yes`。僅有本機信任或擁有者簽章並不足夠。 + +`--allow-degraded-local-state` 會在不先準備 Matrix 帳號的情況下回傳盡力而為的診斷;適合用於離線或部分設定完成的探測。 + +### 使用復原金鑰驗證此裝置 + +復原金鑰屬於敏感資訊 — 請透過 stdin 傳入,而不要放在命令列上。設定 `MATRIX_RECOVERY_KEY`(或對具名帳號使用 `MATRIX__RECOVERY_KEY`): + +```bash +printf '%s\n' "$MATRIX_RECOVERY_KEY" | openclaw matrix verify device --recovery-key-stdin +``` + +此命令會回報三種狀態: + +- `Recovery key accepted`:Matrix 已接受此金鑰用於密鑰儲存或裝置信任。 +- `Backup usable`:可以使用受信任的復原材料載入聊天室金鑰備份。 +- `Device verified by owner`:此裝置具有完整的 Matrix 交叉簽署身分信任。 + +當完整身分信任尚未完成時,即使復原金鑰已解鎖備份材料,也會以非零狀態結束。在這種情況下,請從另一個 Matrix 用戶端完成自我驗證: + +```bash +openclaw matrix verify self +``` + +`verify self` 會等到 `Cross-signing verified: yes` 後才成功結束。使用 `--timeout-ms ` 調整等待時間。 + +也接受字面金鑰形式 `openclaw matrix verify device ""`,但金鑰會留在你的 shell 歷史記錄中。 + +### 啟動或修復交叉簽署 + +```bash +openclaw matrix verify bootstrap +``` + +`verify bootstrap` 是加密帳號的修復與設定命令。依序會: + +- 啟動密鑰儲存,並在可能時重用既有復原金鑰 +- 啟動交叉簽署並上傳遺漏的公開金鑰 +- 標記並交叉簽署目前裝置 +- 如果尚未存在,建立伺服器端聊天室金鑰備份 + +如果 homeserver 需要 UIA 才能上傳交叉簽署金鑰,OpenClaw 會先嘗試不使用驗證,接著嘗試 `m.login.dummy`,再嘗試 `m.login.password`(需要 `channels.matrix.password`)。 + +實用旗標: + +- `--recovery-key-stdin`(搭配 `printf '%s\n' "$MATRIX_RECOVERY_KEY" | …`)或 `--recovery-key ` +- `--force-reset-cross-signing` 用於捨棄目前的交叉簽署身分(僅限有意為之) + +### 聊天室金鑰備份 + +```bash +openclaw matrix verify backup status +printf '%s\n' "$MATRIX_RECOVERY_KEY" | openclaw matrix verify backup restore --recovery-key-stdin +``` + +`backup status` 會顯示是否存在伺服器端備份,以及此裝置是否能解密該備份。`backup restore` 會將已備份的聊天室金鑰匯入本機加密儲存;如果復原金鑰已在磁碟上,可以省略 `--recovery-key-stdin`。 + +若要以全新基準取代損壞的備份(接受遺失無法復原的舊歷史記錄;如果目前備份密鑰無法載入,也可以重新建立密鑰儲存): + +```bash +openclaw matrix verify backup reset --yes +``` + +只有在你有意讓先前的復原金鑰無法再解鎖新的備份基準時,才加入 `--rotate-recovery-key`。 + +### 列出、請求與回應驗證 + +```bash +openclaw matrix verify list +``` + +列出所選帳號的待處理驗證請求。 + +```bash +openclaw matrix verify request --own-user +openclaw matrix verify request --user-id @ops:example.org --device-id ABCDEF +``` + +從此 OpenClaw 帳號送出驗證請求。`--own-user` 會請求自我驗證(你在同一使用者的另一個 Matrix 用戶端中接受提示);`--user-id`/`--device-id`/`--room-id` 會指定其他人。`--own-user` 不能與其他指定目標的旗標合併使用。 + +對於較底層的生命週期處理 — 通常是在旁路追蹤另一個用戶端傳入的請求時 — 這些命令會作用於特定請求 ``(由 `verify list` 和 `verify request` 列印): + +| 命令 | 用途 | +| ------------------------------------------ | ----------------------------------------------------------- | +| `openclaw matrix verify accept ` | 接受傳入請求 | +| `openclaw matrix verify start ` | 啟動 SAS 流程 | +| `openclaw matrix verify sas ` | 列印 SAS 表情符號或十進位數字 | +| `openclaw matrix verify confirm-sas ` | 確認 SAS 與另一個用戶端顯示的內容相符 | +| `openclaw matrix verify mismatch-sas ` | 當表情符號或十進位數字不相符時拒絕 SAS | +| `openclaw matrix verify cancel ` | 取消;接受選用的 `--reason ` 與 `--code ` | + +當驗證錨定到特定直接訊息聊天室時,`accept`、`start`、`sas`、`confirm-sas`、`mismatch-sas` 和 `cancel` 全都接受 `--user-id` 與 `--room-id` 作為 DM 後續提示。 + +### 多帳號注意事項 + +若沒有 `--account `,Matrix CLI 命令會使用隱含的預設帳號。如果你有多個具名帳號且尚未設定 `channels.matrix.defaultAccount`,它們會拒絕猜測並要求你選擇。當具名帳號停用或無法使用 E2EE 時,錯誤會指出該帳號的設定鍵,例如 `channels.matrix.accounts.assistant.encryption`。 + + + + 使用 `encryption: true` 時,`startupVerification` 預設為 `"if-unverified"`。啟動時,未驗證裝置會在另一個 Matrix 用戶端中請求自我驗證,並略過重複請求與套用冷卻時間(預設 24 小時)。使用 `startupVerificationCooldownHours` 調整,或使用 `startupVerification: "off"` 停用。 + + 啟動時也會執行保守的加密啟動程序,重用目前的密鑰儲存與交叉簽署身分。如果啟動狀態損壞,OpenClaw 會即使沒有 `channels.matrix.password` 也嘗試受保護的修復;如果 homeserver 需要密碼 UIA,啟動會記錄警告並保持非致命狀態。已由擁有者簽署的裝置會保留。 + + 請參閱 [Matrix 遷移](/zh-TW/channels/matrix-migration) 了解完整升級流程。 + + + + + Matrix 會將驗證生命週期通知以 `m.notice` 訊息發布到嚴格 DM 驗證聊天室中:請求、就緒(含「以表情符號驗證」指引)、開始/完成,以及可用時的 SAS(表情符號/十進位)詳細資訊。 + + 來自另一個 Matrix 用戶端的傳入請求會被追蹤並自動接受。對於自我驗證,OpenClaw 會自動啟動 SAS 流程,並在表情符號驗證可用後確認自身這一側 — 你仍需要在 Matrix 用戶端中比較並確認「它們相符」。 + + 驗證系統通知不會轉送到代理聊天管線。 + + + + + 如果 `verify status` 顯示目前裝置不再列於 homeserver 上,請建立新的 OpenClaw Matrix 裝置。對於密碼登入: + +```bash +openclaw matrix account add \ + --account assistant \ + --homeserver https://matrix.example.org \ + --user-id '@assistant:example.org' \ + --password '' \ + --device-name OpenClaw-Gateway +``` + + 對於權杖驗證,請在你的 Matrix 用戶端或管理 UI 中建立新的存取權杖,然後更新 OpenClaw: + +```bash +openclaw matrix account add \ + --account assistant \ + --homeserver https://matrix.example.org \ + --access-token '' +``` + + 將 `assistant` 替換為失敗命令中的帳號 ID,或省略 `--account` 以使用預設帳號。 + + + + + 舊的 OpenClaw 管理裝置可能會累積。列出並修剪: + +```bash +openclaw matrix devices list +openclaw matrix devices prune-stale +``` + + + + + Matrix E2EE 使用官方 `matrix-js-sdk` Rust 加密路徑,並以 `fake-indexeddb` 作為 IndexedDB shim。加密狀態會持久化到 `crypto-idb-snapshot.json`(限制性檔案權限)。 + + 加密的執行階段狀態位於 `~/.openclaw/matrix/accounts//__//` 底下,並包含同步儲存、加密儲存、復原金鑰、IDB 快照、執行緒綁定與啟動驗證狀態。當權杖變更但帳號身分維持相同時,OpenClaw 會重用最佳的既有根目錄,因此先前狀態仍保持可見。 + + + + +## 個人檔案管理 + +更新所選帳號的 Matrix 自我個人檔案: + +```bash +openclaw matrix profile set --name "OpenClaw Assistant" +openclaw matrix profile set --avatar-url https://cdn.example.org/avatar.png +``` + +你可以在一次呼叫中同時傳入兩個選項。Matrix 可直接接受 `mxc://` 頭像 URL;當你傳入 `http://` 或 `https://` 時,OpenClaw 會先上傳檔案,並將解析後的 `mxc://` URL 儲存到 `channels.matrix.avatarUrl`(或每帳號覆寫值)。 + +## 執行緒 + +Matrix 支援原生 Matrix 執行緒,可用於自動回覆與訊息工具傳送。兩個獨立旋鈕控制行為: + +### 工作階段路由(`sessionScope`) + +`dm.sessionScope` 決定 Matrix DM 聊天室如何對應到 OpenClaw 工作階段: + +- `"per-user"`(預設):與同一個已路由對等方的所有 DM 聊天室共用一個工作階段。 +- `"per-room"`:即使對等方相同,每個 Matrix DM 聊天室也會取得自己的工作階段鍵。 + +明確對話綁定一律優先於 `sessionScope`,因此已綁定的聊天室與執行緒會保留其選定的目標工作階段。 + +### 回覆執行緒(`threadReplies`) + +`threadReplies` 決定 bot 發布回覆的位置: + +- `"off"`:回覆為頂層訊息。傳入的執行緒訊息會留在父工作階段。 +- `"inbound"`:只有當傳入訊息已在該執行緒中時,才在執行緒內回覆。 +- `"always"`:在以觸發訊息為根的執行緒內回覆;該對話會從第一次觸發起,透過相符的執行緒範圍工作階段路由。 + +`dm.threadReplies` 僅對 DM 覆寫此設定 — 例如,保持聊天室執行緒隔離,同時讓 DM 維持扁平。 + +### 執行緒繼承與斜線命令 + +- 傳入的對話串訊息會包含對話串根訊息,作為額外的 agent 脈絡。 +- 訊息工具傳送在目標為同一個房間(或同一個 DM 使用者目標)時,會自動繼承目前的 Matrix 對話串,除非明確提供 `threadId`。 +- DM 使用者目標重用只有在目前工作階段中繼資料證明是同一個 Matrix 帳號上的同一個 DM 對象時才會啟用;否則 OpenClaw 會退回一般的使用者範圍路由。 +- `/focus`、`/unfocus`、`/agents`、`/session idle`、`/session max-age`,以及繫結對話串的 `/acp spawn` 都可在 Matrix 房間和 DM 中使用。 +- 當 `threadBindings.spawnSubagentSessions: true` 時,頂層 `/focus` 會建立新的 Matrix 對話串,並將其繫結到目標工作階段。 +- 在現有 Matrix 對話串內執行 `/focus` 或 `/acp spawn --thread here`,會就地繫結該對話串。 + +當 OpenClaw 偵測到 Matrix DM 房間與同一個共享工作階段上的另一個 DM 房間衝突時,會在該房間張貼一次性的 `m.notice`,指向 `/focus` 逃生路徑並建議變更 `dm.sessionScope`。此通知只會在啟用對話串繫結時出現。 + +## ACP 對話繫結 + +Matrix 房間、DM 和現有 Matrix 對話串都可以轉換成持久的 ACP 工作區,而不改變聊天介面。 + +快速操作流程: + +- 在你想持續使用的 Matrix DM、房間或現有對話串內執行 `/acp spawn codex --bind here`。 +- 在頂層 Matrix DM 或房間中,目前的 DM/房間會保留為聊天介面,未來訊息會路由到新產生的 ACP 工作階段。 +- 在現有 Matrix 對話串內,`--bind here` 會就地繫結目前的對話串。 +- `/new` 和 `/reset` 會就地重設同一個已繫結的 ACP 工作階段。 +- `/acp close` 會關閉 ACP 工作階段並移除繫結。 + +注意事項: + +- `--bind here` 不會建立子 Matrix 對話串。 +- `threadBindings.spawnAcpSessions` 只有在 `/acp spawn --thread auto|here` 時才需要,此時 OpenClaw 需要建立或繫結子 Matrix 對話串。 + +### 對話串繫結設定 + +Matrix 會從 `session.threadBindings` 繼承全域預設值,也支援各通道覆寫: + +- `threadBindings.enabled` +- `threadBindings.idleHours` +- `threadBindings.maxAgeHours` +- `threadBindings.spawnSubagentSessions` +- `threadBindings.spawnAcpSessions` + +Matrix 繫結對話串的 spawn 旗標採選擇啟用: + +- 設定 `threadBindings.spawnSubagentSessions: true`,允許頂層 `/focus` 建立並繫結新的 Matrix 對話串。 +- 設定 `threadBindings.spawnAcpSessions: true`,允許 `/acp spawn --thread auto|here` 將 ACP 工作階段繫結到 Matrix 對話串。 + +## 回應 + +Matrix 支援傳出回應、傳入回應通知和確認回應。 + +傳出回應工具由 `channels.matrix.actions.reactions` 控制: + +- `react` 會將回應新增到 Matrix 事件。 +- `reactions` 會列出 Matrix 事件目前的回應摘要。 +- `emoji=""` 會移除該事件上 bot 自己的回應。 +- `remove: true` 只會從 bot 移除指定的 emoji 回應。 + +**解析順序**(第一個已定義的值優先): + +| 設定 | 順序 | +| ----------------------- | -------------------------------------------------------------------------------- | +| `ackReaction` | 每帳號 → 通道 → `messages.ackReaction` → agent 身分 emoji 後備 | +| `ackReactionScope` | 每帳號 → 通道 → `messages.ackReactionScope` → 預設 `"group-mentions"` | +| `reactionNotifications` | 每帳號 → 通道 → 預設 `"own"` | + +`reactionNotifications: "own"` 會在新增的 `m.reaction` 事件以 bot 撰寫的 Matrix 訊息為目標時轉送;`"off"` 會停用回應系統事件。回應移除不會合成為系統事件,因為 Matrix 會將其呈現為刪訂,而不是獨立的 `m.reaction` 移除。 + +## 歷史脈絡 + +- `channels.matrix.historyLimit` 控制當 Matrix 房間訊息觸發 agent 時,會有多少最近的房間訊息作為 `InboundHistory` 包含進來。會退回 `messages.groupChat.historyLimit`;如果兩者都未設定,實際預設值為 `0`。設定為 `0` 可停用。 +- Matrix 房間歷史只限房間。DM 會繼續使用一般工作階段歷史。 +- Matrix 房間歷史只包含待處理內容:OpenClaw 會緩衝尚未觸發回覆的房間訊息,然後在提及或其他觸發到達時快照該視窗。 +- 目前的觸發訊息不會包含在 `InboundHistory` 中;它會留在該回合的主要傳入本文中。 +- 同一個 Matrix 事件的重試會重用原始歷史快照,而不是向前漂移到較新的房間訊息。 + +## 脈絡可見性 + +Matrix 支援共享的 `contextVisibility` 控制,用於補充房間脈絡,例如擷取的回覆文字、對話串根和待處理歷史。 + +- `contextVisibility: "all"` 是預設值。補充脈絡會按收到的內容保留。 +- `contextVisibility: "allowlist"` 會將補充脈絡篩選為主動房間/使用者允許清單檢查所允許的傳送者。 +- `contextVisibility: "allowlist_quote"` 的行為類似 `allowlist`,但仍會保留一則明確引用的回覆。 + +此設定影響補充脈絡可見性,不影響傳入訊息本身是否可以觸發回覆。 +觸發授權仍來自 `groupPolicy`、`groups`、`groupAllowFrom` 和 DM 政策設定。 + +## DM 和房間政策 + +```json5 +{ + channels: { + matrix: { + dm: { + policy: "allowlist", + allowFrom: ["@admin:example.org"], + threadReplies: "off", + }, + groupPolicy: "allowlist", + groupAllowFrom: ["@admin:example.org"], + groups: { + "!roomid:example.org": { requireMention: true }, + }, + }, + }, +} +``` + +若要完全靜音 DM,同時保持房間可用,請設定 `dm.enabled: false`: + +```json5 +{ + channels: { + matrix: { + dm: { enabled: false }, + groupPolicy: "allowlist", + groupAllowFrom: ["@admin:example.org"], + }, + }, +} +``` + +請參閱[群組](/zh-TW/channels/groups),了解提及閘控和允許清單行為。 + +Matrix DM 的配對範例: + +```bash +openclaw pairing list matrix +openclaw pairing approve matrix +``` + +如果未核准的 Matrix 使用者在核准前持續傳訊息給你,OpenClaw 會重用同一個待處理配對碼,並可能在短暫冷卻後傳送提醒回覆,而不是鑄造新的代碼。 + +請參閱[配對](/zh-TW/channels/pairing),了解共享的 DM 配對流程和儲存配置。 + +## 直接房間修復 + +如果直接訊息狀態不同步,OpenClaw 可能會留下過時的 `m.direct` 對應,指向舊的單人房間,而不是即時 DM。檢查某個對象目前的對應: + +```bash +openclaw matrix direct inspect --user-id @alice:example.org +``` + +修復它: + +```bash +openclaw matrix direct repair --user-id @alice:example.org +``` + +兩個命令都接受 `--account `,可用於多帳號設定。修復流程: + +- 偏好已在 `m.direct` 中對應的嚴格 1:1 DM +- 退回目前已加入、與該使用者的任何嚴格 1:1 DM +- 如果沒有健康的 DM,則建立新的直接房間並重寫 `m.direct` + +它不會自動刪除舊房間。它會選擇健康的 DM 並更新對應,讓未來的 Matrix 傳送、驗證通知和其他直接訊息流程都以正確房間為目標。 + +## Exec 核准 + +Matrix 可以作為原生核准用戶端。在 `channels.matrix.execApprovals` 下設定(或使用 `channels.matrix.accounts..execApprovals` 作為每帳號覆寫): + +- `enabled`:透過 Matrix 原生提示傳遞核准。未設定或為 `"auto"` 時,只要至少可解析一位核准者,Matrix 就會自動啟用。設定 `false` 可明確停用。 +- `approvers`:允許核准 exec 要求的 Matrix 使用者 ID(`@owner:example.org`)。選用 — 會退回 `channels.matrix.dm.allowFrom`。 +- `target`:提示送達位置。`"dm"`(預設)會傳送到核准者 DM;`"channel"` 會傳送到來源 Matrix 房間或 DM;`"both"` 會傳送到兩者。 +- `agentFilter` / `sessionFilter`:選用允許清單,指定哪些 agent/工作階段會觸發 Matrix 傳遞。 + +不同核准種類的授權略有差異: + +- **Exec 核准**使用 `execApprovals.approvers`,並退回 `dm.allowFrom`。 +- **Plugin 核准**只透過 `dm.allowFrom` 授權。 + +兩種核准都共用 Matrix 回應捷徑和訊息更新。核准者會在主要核准訊息上看到回應捷徑: + +- `✅` 允許一次 +- `❌` 拒絕 +- `♾️` 永遠允許(當有效 exec 政策允許時) + +後備斜線命令:`/approve allow-once`、`/approve allow-always`、`/approve deny`。 + +只有已解析的核准者可以核准或拒絕。Exec 核准的通道傳遞會包含命令文字 — 只有在受信任的房間中才啟用 `channel` 或 `both`。 + +相關:[Exec 核准](/zh-TW/tools/exec-approvals)。 + +## 斜線命令 + +斜線命令(`/new`、`/reset`、`/model`、`/focus`、`/unfocus`、`/agents`、`/session`、`/acp`、`/approve` 等)可直接在 DM 中使用。在房間中,OpenClaw 也會辨識以 bot 自己的 Matrix 提及作為前綴的命令,因此 `@bot:server /new` 會觸發命令路徑,而不需要自訂提及 regex。這讓 bot 能回應 Element 和類似用戶端在使用者於輸入命令前以 Tab 補全 bot 時送出的房間風格 `@mention /command` 貼文。 + +授權規則仍適用:命令傳送者必須符合與一般訊息相同的 DM 或房間允許清單/擁有者政策。 + +## 多帳號 + +```json5 +{ + channels: { + matrix: { + enabled: true, + defaultAccount: "assistant", + dm: { policy: "pairing" }, + accounts: { + assistant: { + homeserver: "https://matrix.example.org", + accessToken: "syt_assistant_xxx", + encryption: true, + }, + alerts: { + homeserver: "https://matrix.example.org", + accessToken: "syt_alerts_xxx", + dm: { + policy: "allowlist", + allowFrom: ["@ops:example.org"], + threadReplies: "off", + }, + }, + }, + }, + }, +} +``` + +**繼承:** + +- 頂層 `channels.matrix` 值會作為具名帳號的預設值,除非帳號覆寫它們。 +- 使用 `groups..account` 將繼承的房間項目限定到特定帳號。沒有 `account` 的項目會在帳號之間共享;當預設帳號設定於頂層時,`account: "default"` 仍然可用。 + +**預設帳號選擇:** + +- 設定 `defaultAccount` 以選擇隱式路由、探測和 CLI 命令偏好的具名帳號。 +- 如果你有多個帳號,且其中一個字面名稱為 `default`,即使未設定 `defaultAccount`,OpenClaw 也會隱式使用它。 +- 如果你有多個具名帳號且未選擇預設帳號,CLI 命令會拒絕猜測 — 請設定 `defaultAccount` 或傳入 `--account `。 +- 只有在頂層 `channels.matrix.*` 區塊的驗證完整(`homeserver` + `accessToken`,或 `homeserver` + `userId` + `password`)時,才會被視為隱式 `default` 帳號。只要快取認證涵蓋驗證,具名帳號仍可從 `homeserver` + `userId` 探索。 + +**升級:** + +- 當 OpenClaw 在修復或設定期間將單帳號設定升級為多帳號時,如果已有具名帳號或 `defaultAccount` 已指向某個帳號,它會保留現有具名帳號。只有 Matrix 驗證/啟動鍵會移入升級後的帳號;共享傳遞政策鍵會保留在頂層。 + +請參閱[設定參考](/zh-TW/gateway/config-channels#multi-account-all-channels),了解共享的多帳號模式。 + +## 私有/LAN homeserver + +預設情況下,OpenClaw 會封鎖私有/內部 Matrix homeserver 以防護 SSRF,除非你 +明確針對每個帳號選擇啟用。 + +如果你的 homeserver 在 localhost、LAN/Tailscale IP 或內部主機名稱上執行,請為該 Matrix 帳號啟用 +`network.dangerouslyAllowPrivateNetwork`: + +```json5 +{ + channels: { + matrix: { + homeserver: "http://matrix-synapse:8008", + network: { + dangerouslyAllowPrivateNetwork: true, + }, + accessToken: "syt_internal_xxx", + }, + }, +} +``` + +CLI 設定範例: + +```bash +openclaw matrix account add \ + --account ops \ + --homeserver http://matrix-synapse:8008 \ + --allow-private-network \ + --access-token syt_ops_xxx +``` + +此選擇加入設定只允許受信任的私人/內部目標。公開的明文 homeserver,例如 +`http://matrix.example.org:8008` 仍會被封鎖。請盡可能優先使用 `https://`。 + +## 代理 Matrix 流量 + +如果你的 Matrix 部署需要明確的對外 HTTP(S) Proxy,請設定 `channels.matrix.proxy`: + +```json5 +{ + channels: { + matrix: { + homeserver: "https://matrix.example.org", + accessToken: "syt_bot_xxx", + proxy: "http://127.0.0.1:7890", + }, + }, +} +``` + +具名帳號可以使用 `channels.matrix.accounts..proxy` 覆寫頂層預設值。 +OpenClaw 會對執行階段 Matrix 流量與帳號狀態探測使用相同的 Proxy 設定。 + +## 目標解析 + +凡是 OpenClaw 要求你提供房間或使用者目標的位置,Matrix 都接受下列目標格式: + +- 使用者:`@user:server`、`user:@user:server` 或 `matrix:user:@user:server` +- 房間:`!room:server`、`room:!room:server` 或 `matrix:room:!room:server` +- 別名:`#alias:server`、`channel:#alias:server` 或 `matrix:channel:#alias:server` + +Matrix 房間 ID 區分大小寫。設定明確的傳遞目標、Cron 作業、繫結或允許清單時, +請使用 Matrix 中完全相同大小寫的房間 ID。OpenClaw 會將內部工作階段金鑰正規化後儲存, +因此這些小寫金鑰並不是 Matrix 傳遞 ID 的可靠來源。 + +即時目錄查詢會使用已登入的 Matrix 帳號: + +- 使用者查詢會查詢該 homeserver 上的 Matrix 使用者目錄。 +- 房間查詢會直接接受明確的房間 ID 與別名,然後退回搜尋該帳號已加入的房間名稱。 +- 已加入房間的名稱查詢是盡力而為。如果房間名稱無法解析為 ID 或別名,執行階段允許清單解析會忽略它。 + +## 設定參考 + +允許清單樣式欄位(`groupAllowFrom`、`dm.allowFrom`、`groups..users`)接受完整的 Matrix 使用者 ID(最安全)。精確目錄相符項目會在啟動時解析,並在監視器執行期間允許清單變更時重新解析;無法解析的項目會在執行階段被忽略。基於同樣原因,房間允許清單優先使用房間 ID 或別名。 + +### 帳號與連線 + +- `enabled`:啟用或停用此頻道。 +- `name`:帳號的選用顯示標籤。 +- `defaultAccount`:設定多個 Matrix 帳號時偏好的帳號 ID。 +- `accounts`:具名的逐帳號覆寫。頂層 `channels.matrix` 值會作為預設值繼承。 +- `homeserver`:homeserver URL,例如 `https://matrix.example.org`。 +- `network.dangerouslyAllowPrivateNetwork`:允許此帳號連線到 `localhost`、LAN/Tailscale IP 或內部主機名稱。 +- `proxy`:Matrix 流量的選用 HTTP(S) Proxy URL。支援逐帳號覆寫。 +- `userId`:完整的 Matrix 使用者 ID(`@bot:example.org`)。 +- `accessToken`:Token 型驗證的存取 Token。支援跨 env/file/exec 提供者使用明文與 SecretRef 值([密鑰管理](/zh-TW/gateway/secrets))。 +- `password`:密碼型登入使用的密碼。支援明文與 SecretRef 值。 +- `deviceId`:明確的 Matrix 裝置 ID。 +- `deviceName`:密碼登入時使用的裝置顯示名稱。 +- `avatarUrl`:用於個人檔案同步與 `profile set` 更新的已儲存自身頭像 URL。 +- `initialSyncLimit`:啟動同步期間擷取的事件數量上限。 + +### 加密 + +- `encryption`:啟用 E2EE。預設:`false`。 +- `startupVerification`:`"if-unverified"`(E2EE 開啟時的預設值)或 `"off"`。當此裝置尚未驗證時,在啟動時自動要求自我驗證。 +- `startupVerificationCooldownHours`:下一次自動啟動要求前的冷卻時間。預設:`24`。 + +### 存取與政策 + +- `groupPolicy`:`"open"`、`"allowlist"` 或 `"disabled"`。預設:`"allowlist"`。 +- `groupAllowFrom`:房間流量的使用者 ID 允許清單。 +- `dm.enabled`:為 `false` 時,忽略所有 DM。預設:`true`。 +- `dm.policy`:`"pairing"`(預設)、`"allowlist"`、`"open"` 或 `"disabled"`。在 bot 已加入且將房間分類為 DM 後套用;不影響邀請處理。 +- `dm.allowFrom`:DM 流量的使用者 ID 允許清單。 +- `dm.sessionScope`:`"per-user"`(預設)或 `"per-room"`。 +- `dm.threadReplies`:僅限 DM 的回覆執行緒覆寫(`"off"`、`"inbound"`、`"always"`)。 +- `allowBots`:接受來自其他已設定 Matrix bot 帳號的訊息(`true` 或 `"mentions"`)。 +- `allowlistOnly`:為 `true` 時,強制所有作用中的 DM 政策(除了 `"disabled"`)與 `"open"` 群組政策改為 `"allowlist"`。不會變更 `"disabled"` 政策。 +- `autoJoin`:`"always"`、`"allowlist"` 或 `"off"`。預設:`"off"`。套用於每個 Matrix 邀請,包括 DM 樣式邀請。 +- `autoJoinAllowlist`:當 `autoJoin` 為 `"allowlist"` 時允許的房間/別名。別名項目會依據 homeserver 解析,而不是依據受邀房間宣稱的狀態。 +- `contextVisibility`:補充內容脈絡可見性(預設 `"all"`、`"allowlist"`、`"allowlist_quote"`)。 + +### 回覆行為 + +- `replyToMode`:`"off"`、`"first"`、`"all"` 或 `"batched"`。 +- `threadReplies`:`"off"`、`"inbound"` 或 `"always"`。 +- `threadBindings`:執行緒繫結工作階段路由與生命週期的逐頻道覆寫。 +- `streaming`:`"off"`(預設)、`"partial"`、`"quiet"`,或物件形式 `{ mode, preview: { toolProgress } }`。`true` ↔ `"partial"`,`false` ↔ `"off"`。 +- `blockStreaming`:為 `true` 時,已完成的助理區塊會保留為獨立的進度訊息。 +- `markdown`:輸出文字的選用 Markdown 算繪設定。 +- `responsePrefix`:附加到輸出回覆前方的選用字串。 +- `textChunkLimit`:當 `chunkMode: "length"` 時,以字元計算的輸出分塊大小。預設:`4000`。 +- `chunkMode`:`"length"`(預設,依字元數分割)或 `"newline"`(在行邊界分割)。 +- `historyLimit`:當房間訊息觸發 agent 時,作為 `InboundHistory` 包含的近期房間訊息數量。退回使用 `messages.groupChat.historyLimit`;有效預設值為 `0`(停用)。 +- `mediaMaxMb`:輸出傳送與輸入處理的媒體大小上限,單位為 MB。 + +### 回應設定 + +- `ackReaction`:此頻道/帳號的 ack 回應覆寫。 +- `ackReactionScope`:範圍覆寫(預設 `"group-mentions"`、`"group-all"`、`"direct"`、`"all"`、`"none"`、`"off"`)。 +- `reactionNotifications`:輸入回應通知模式(預設 `"own"`、`"off"`)。 + +### 工具與逐房間覆寫 + +- `actions`:逐動作工具控管(`messages`、`reactions`、`pins`、`profile`、`memberInfo`、`channelInfo`、`verification`)。 +- `groups`:逐房間政策對應。解析後,工作階段識別會使用穩定的房間 ID。(`rooms` 是舊版別名。) + - `groups..account`:將一個繼承的房間項目限制到特定帳號。 + - `groups..allowBots`:頻道層級設定的逐房間覆寫(`true` 或 `"mentions"`)。 + - `groups..users`:逐房間傳送者允許清單。 + - `groups..tools`:逐房間工具允許/拒絕覆寫。 + - `groups..autoReply`:逐房間提及控管覆寫。`true` 會停用該房間的提及要求;`false` 會強制重新啟用。 + - `groups..skills`:逐房間 skill 篩選器。 + - `groups..systemPrompt`:逐房間系統提示片段。 + +### Exec 核准設定 + +- `execApprovals.enabled`:透過 Matrix 原生提示傳遞 exec 核准。 +- `execApprovals.approvers`:允許核准的 Matrix 使用者 ID。退回使用 `dm.allowFrom`。 +- `execApprovals.target`:`"dm"`(預設)、`"channel"` 或 `"both"`。 +- `execApprovals.agentFilter` / `execApprovals.sessionFilter`:傳遞用的選用 agent/工作階段允許清單。 + +## 相關 + +- [頻道概觀](/zh-TW/channels) — 所有支援的頻道 +- [配對](/zh-TW/channels/pairing) — DM 驗證與配對流程 +- [群組](/zh-TW/channels/groups) — 群組聊天行為與提及控管 +- [頻道路由](/zh-TW/channels/channel-routing) — 訊息的工作階段路由 +- [安全性](/zh-TW/gateway/security) — 存取模型與強化 diff --git a/docs/zh-TW/channels/mattermost.md b/docs/zh-TW/channels/mattermost.md new file mode 100644 index 000000000..b4ce87923 --- /dev/null +++ b/docs/zh-TW/channels/mattermost.md @@ -0,0 +1,550 @@ +--- +read_when: + - 設定 Mattermost + - 偵錯 Mattermost 路由 +sidebarTitle: Mattermost +summary: Mattermost 機器人設定與 OpenClaw 設定 +title: Mattermost +x-i18n: + generated_at: "2026-04-30T02:47:59Z" + model: gpt-5.5 + provider: openai + source_hash: 1926a1d7347ff35ed60f8d5c3e0b26a064863ada213ad0e171776af5a84d8475 + source_path: channels/mattermost.md + workflow: 16 +--- + +狀態:隨附 Plugin(bot token + WebSocket 事件)。支援頻道、群組和 DM。Mattermost 是可自行託管的團隊訊息平台;產品詳細資料與下載請參閱官方網站 [mattermost.com](https://mattermost.com)。 + +## 隨附 Plugin + + +Mattermost 在目前的 OpenClaw 發行版本中以隨附 Plugin 提供,因此一般封裝組建不需要另外安裝。 + + +如果你使用的是較舊的組建,或是排除 Mattermost 的自訂安裝,請在發布後安裝目前的 npm 套件: + + + + ```bash + openclaw plugins install @openclaw/mattermost + ``` + + + ```bash + openclaw plugins install ./path/to/local/mattermost-plugin + ``` + + + +如果 npm 回報 OpenClaw 擁有的套件已棄用,請使用目前封裝的 +OpenClaw 組建,或在較新的 npm 套件發布前使用本機 checkout 路徑。 + +詳細資料:[Plugins](/zh-TW/tools/plugin) + +## 快速設定 + + + + 目前封裝的 OpenClaw 發行版本已經內建它。較舊或自訂安裝可以使用上述命令手動新增。 + + + 建立 Mattermost bot 帳號並複製 **bot token**。 + + + 複製 Mattermost **基底 URL**(例如 `https://chat.example.com`)。 + + + 最小設定: + + ```json5 + { + channels: { + mattermost: { + enabled: true, + botToken: "mm-token", + baseUrl: "https://chat.example.com", + dmPolicy: "pairing", + }, + }, + } + ``` + + + + +## 原生 slash commands + +原生 slash commands 需要選擇啟用。啟用後,OpenClaw 會透過 Mattermost API 註冊 `oc_*` slash commands,並在 Gateway HTTP 伺服器上接收 callback POST。 + +```json5 +{ + channels: { + mattermost: { + commands: { + native: true, + nativeSkills: true, + callbackPath: "/api/channels/mattermost/command", + // Use when Mattermost cannot reach the gateway directly (reverse proxy/public URL). + callbackUrl: "https://gateway.example.com/api/channels/mattermost/command", + }, + }, + }, +} +``` + + + + - `native: "auto"` 對 Mattermost 預設為停用。設定 `native: true` 以啟用。 + - 如果省略 `callbackUrl`,OpenClaw 會從 Gateway 主機/連接埠 + `callbackPath` 推導出一個。 + - 對於多帳號設定,`commands` 可以設定在最上層,或設定在 `channels.mattermost.accounts..commands` 底下(帳號值會覆寫最上層欄位)。 + - 命令 callback 會使用 OpenClaw 註冊 `oc_*` 命令時 Mattermost 傳回的每個命令 token 進行驗證。 + - 當註冊失敗、啟動不完整,或 callback token 與任何已註冊命令不相符時,slash callback 會以安全失敗方式拒絕。 + + + + callback 端點必須能由 Mattermost 伺服器連線到。 + + - 除非 Mattermost 與 OpenClaw 在同一主機/網路命名空間中執行,否則不要將 `callbackUrl` 設為 `localhost`。 + - 除非該 URL 會將 `/api/channels/mattermost/command` 反向代理到 OpenClaw,否則不要將 `callbackUrl` 設為你的 Mattermost 基底 URL。 + - 快速檢查方式是 `curl https:///api/channels/mattermost/command`;GET 應該從 OpenClaw 傳回 `405 Method Not Allowed`,而不是 `404`。 + + + + 如果你的 callback 目標是私有/tailnet/內部位址,請設定 Mattermost `ServiceSettings.AllowedUntrustedInternalConnections` 以包含 callback 主機/網域。 + + 使用主機/網域項目,而不是完整 URL。 + + - 正確:`gateway.tailnet-name.ts.net` + - 錯誤:`https://gateway.tailnet-name.ts.net` + + + + +## 環境變數(預設帳號) + +如果你偏好使用 env vars,請在 Gateway 主機上設定這些項目: + +- `MATTERMOST_BOT_TOKEN=...` +- `MATTERMOST_URL=https://chat.example.com` + + +Env vars 只套用至**預設**帳號(`default`)。其他帳號必須使用設定值。 + +`MATTERMOST_URL` 無法從 workspace `.env` 設定;請參閱 [Workspace `.env` 檔案](/zh-TW/gateway/security)。 + + +## 聊天模式 + +Mattermost 會自動回應 DM。頻道行為由 `chatmode` 控制: + + + + 只在頻道中被 @提及 時回應。 + + + 回應每則頻道訊息。 + + + 當訊息以觸發前綴開頭時回應。 + + + +設定範例: + +```json5 +{ + channels: { + mattermost: { + chatmode: "onchar", + oncharPrefixes: [">", "!"], + }, + }, +} +``` + +注意事項: + +- `onchar` 仍會回應明確的 @提及。 +- `channels.mattermost.requireMention` 會為舊版設定保留支援,但建議使用 `chatmode`。 + +## 執行緒與工作階段 + +使用 `channels.mattermost.replyToMode` 控制頻道與群組回覆要留在主要頻道,或是在觸發貼文下方開始執行緒。 + +- `off`(預設):只有在傳入貼文已經位於執行緒中時,才在執行緒中回覆。 +- `first`:對於最上層頻道/群組貼文,在該貼文下方開始執行緒,並將對話路由到執行緒範圍的工作階段。 +- `all`:目前對 Mattermost 與 `first` 行為相同。 +- 直接訊息會忽略此設定並保持非執行緒。 + +設定範例: + +```json5 +{ + channels: { + mattermost: { + replyToMode: "all", + }, + }, +} +``` + +注意事項: + +- 執行緒範圍的工作階段會使用觸發貼文 ID 作為執行緒根。 +- `first` 和 `all` 目前等效,因為一旦 Mattermost 有執行緒根,後續片段與媒體會繼續留在同一個執行緒中。 + +## 存取控制(DM) + +- 預設:`channels.mattermost.dmPolicy = "pairing"`(未知傳送者會取得 pairing code)。 +- 透過以下方式核准: + - `openclaw pairing list mattermost` + - `openclaw pairing approve mattermost ` +- 公開 DM:`channels.mattermost.dmPolicy="open"` 加上 `channels.mattermost.allowFrom=["*"]`。 + +## 頻道(群組) + +- 預設:`channels.mattermost.groupPolicy = "allowlist"`(需提及)。 +- 使用 `channels.mattermost.groupAllowFrom` 將傳送者加入 allowlist(建議使用使用者 ID)。 +- 每個頻道的提及覆寫位於 `channels.mattermost.groups..requireMention` 底下,或以 `channels.mattermost.groups["*"].requireMention` 作為預設值。 +- `@username` 比對是可變的,且只在 `channels.mattermost.dangerouslyAllowNameMatching: true` 時啟用。 +- 開放頻道:`channels.mattermost.groupPolicy="open"`(需提及)。 +- 執行階段注意事項:如果完全缺少 `channels.mattermost`,執行階段會針對群組檢查退回使用 `groupPolicy="allowlist"`(即使已設定 `channels.defaults.groupPolicy`)。 + +範例: + +```json5 +{ + channels: { + mattermost: { + groupPolicy: "open", + groups: { + "*": { requireMention: true }, + "team-channel-id": { requireMention: false }, + }, + }, + }, +} +``` + +## 對外傳遞的目標 + +搭配 `openclaw message send` 或 cron/webhooks 使用這些目標格式: + +- `channel:` 表示頻道 +- `user:` 表示 DM +- `@username` 表示 DM(透過 Mattermost API 解析) + + +裸露的不透明 ID(例如 `64ifufp...`)在 Mattermost 中是**不明確的**(使用者 ID 與頻道 ID)。 + +OpenClaw 會以**使用者優先**方式解析它們: + +- 如果該 ID 作為使用者存在(`GET /api/v4/users/` 成功),OpenClaw 會透過 `/api/v4/channels/direct` 解析直接頻道後傳送 **DM**。 +- 否則該 ID 會被視為**頻道 ID**。 + +如果你需要確定性行為,請一律使用明確前綴(`user:` / `channel:`)。 + + +## DM 頻道重試 + +當 OpenClaw 傳送到 Mattermost DM 目標且需要先解析直接頻道時,預設會重試暫時性的直接頻道建立失敗。 + +使用 `channels.mattermost.dmChannelRetry` 為 Mattermost Plugin 全域調整該行為,或使用 `channels.mattermost.accounts..dmChannelRetry` 為單一帳號調整。 + +```json5 +{ + channels: { + mattermost: { + dmChannelRetry: { + maxRetries: 3, + initialDelayMs: 1000, + maxDelayMs: 10000, + timeoutMs: 30000, + }, + }, + }, +} +``` + +注意事項: + +- 這只套用至 DM 頻道建立(`/api/v4/channels/direct`),不套用至每個 Mattermost API 呼叫。 +- 重試會套用至暫時性失敗,例如速率限制、5xx 回應,以及網路或逾時錯誤。 +- 除了 `429` 以外的 4xx 用戶端錯誤會被視為永久錯誤,不會重試。 + +## 預覽串流 + +Mattermost 會將思考、工具活動和部分回覆文字串流到單一**草稿預覽貼文**,並在最終答案可安全傳送時就地完成。預覽會更新同一個貼文 ID,而不是用每個片段訊息洗版頻道。媒體/錯誤最終內容會取消待處理的預覽編輯,並使用正常傳遞,而不是送出一次性的預覽貼文。 + +透過 `channels.mattermost.streaming` 啟用: + +```json5 +{ + channels: { + mattermost: { + streaming: "partial", // off | partial | block | progress + }, + }, +} +``` + + + + - `partial` 是一般選擇:一篇預覽貼文會隨著回覆增加而被編輯,接著以完整答案完成。 + - `block` 會在預覽貼文中使用附加式草稿片段。 + - `progress` 會在產生期間顯示狀態預覽,並只在完成時發布最終答案。 + - `off` 會停用預覽串流。 + + + + - 如果串流無法就地完成(例如貼文在串流中途被刪除),OpenClaw 會退回傳送新的最終貼文,確保回覆不會遺失。 + - 純推理 payload 會從頻道貼文中隱藏,包括以 `> Reasoning:` blockquote 到達的文字。設定 `/reasoning on` 可在其他介面看到思考;Mattermost 最終貼文只保留答案。 + - 請參閱[串流](/zh-TW/concepts/streaming#preview-streaming-modes)了解頻道對應矩陣。 + + + + +## 回應(訊息工具) + +- 使用 `message action=react` 並搭配 `channel=mattermost`。 +- `messageId` 是 Mattermost 貼文 ID。 +- `emoji` 接受像 `thumbsup` 或 `:+1:` 這類名稱(冒號可選)。 +- 設定 `remove=true`(boolean)以移除回應。 +- 新增/移除回應事件會作為系統事件轉送至已路由的代理工作階段。 + +範例: + +``` +message action=react channel=mattermost target=channel: messageId= emoji=thumbsup +message action=react channel=mattermost target=channel: messageId= emoji=thumbsup remove=true +``` + +設定: + +- `channels.mattermost.actions.reactions`:啟用/停用回應動作(預設為 true)。 +- 每帳號覆寫:`channels.mattermost.accounts..actions.reactions`。 + +## 互動式按鈕(訊息工具) + +傳送含可點擊按鈕的訊息。使用者點擊按鈕時,代理會收到選項並可以回應。 + +將 `inlineButtons` 新增到頻道 capabilities 以啟用按鈕: + +```json5 +{ + channels: { + mattermost: { + capabilities: ["inlineButtons"], + }, + }, +} +``` + +使用 `message action=send` 並搭配 `buttons` 參數。按鈕是 2D 陣列(按鈕列): + +``` +message action=send channel=mattermost target=channel: buttons=[[{"text":"Yes","callback_data":"yes"},{"text":"No","callback_data":"no"}]] +``` + +按鈕欄位: + + + 顯示標籤。 + + + 點擊時傳回的值(用作動作 ID)。 + + + 按鈕樣式。 + + +當使用者點擊按鈕時: + + + + 所有按鈕都會替換為一行確認訊息(例如「✓ **Yes** selected by @user」)。 + + + 代理會以傳入訊息的形式收到該選擇並回應。 + + + + + + - 按鈕回呼使用 HMAC-SHA256 驗證(自動執行,無需設定)。 + - Mattermost 會從其 API 回應中移除回呼資料(安全功能),因此點擊後會移除所有按鈕 — 無法只移除部分按鈕。 + - 包含連字號或底線的動作 ID 會自動清理(Mattermost 路由限制)。 + + + + - `channels.mattermost.capabilities`:能力字串陣列。新增 `"inlineButtons"` 可在代理系統提示中啟用按鈕工具說明。 + - `channels.mattermost.interactions.callbackBaseUrl`:按鈕回呼的選用外部基礎 URL(例如 `https://gateway.example.com`)。當 Mattermost 無法直接透過 Gateway 的繫結主機連到 Gateway 時使用。 + - 在多帳戶設定中,你也可以在 `channels.mattermost.accounts..interactions.callbackBaseUrl` 下設定相同欄位。 + - 如果省略 `interactions.callbackBaseUrl`,OpenClaw 會從 `gateway.customBindHost` + `gateway.port` 推導回呼 URL,然後退回到 `http://localhost:`。 + - 可達性規則:按鈕回呼 URL 必須能從 Mattermost 伺服器連到。`localhost` 只有在 Mattermost 和 OpenClaw 執行於同一主機/網路命名空間時才有效。 + - 如果你的回呼目標是私有/tailnet/內部目標,請將其主機/網域加入 Mattermost `ServiceSettings.AllowedUntrustedInternalConnections`。 + + + + +### 直接 API 整合(外部指令碼) + +外部指令碼和 Webhook 可以透過 Mattermost REST API 直接發佈按鈕,而不必透過代理的 `message` 工具。可行時請使用 Plugin 中的 `buildButtonAttachments()`;如果要發佈原始 JSON,請遵循這些規則: + +**承載結構:** + +```json5 +{ + channel_id: "", + message: "Choose an option:", + props: { + attachments: [ + { + actions: [ + { + id: "mybutton01", // alphanumeric only — see below + type: "button", // required, or clicks are silently ignored + name: "Approve", // display label + style: "primary", // optional: "default", "primary", "danger" + integration: { + url: "https://gateway.example.com/mattermost/interactions/default", + context: { + action_id: "mybutton01", // must match button id (for name lookup) + action: "approve", + // ... any custom fields ... + _token: "", // see HMAC section below + }, + }, + }, + ], + }, + ], + }, +} +``` + + +**關鍵規則** + +1. 附件放在 `props.attachments`,不要放在頂層 `attachments`(會被靜默忽略)。 +2. 每個動作都需要 `type: "button"` — 沒有它,點擊會被靜默吞掉。 +3. 每個動作都需要 `id` 欄位 — Mattermost 會忽略沒有 ID 的動作。 +4. 動作 `id` 必須**只能是英數字元**(`[a-zA-Z0-9]`)。連字號和底線會破壞 Mattermost 的伺服器端動作路由(回傳 404)。使用前請移除它們。 +5. `context.action_id` 必須符合按鈕的 `id`,這樣確認訊息才會顯示按鈕名稱(例如「Approve」),而不是原始 ID。 +6. `context.action_id` 是必要欄位 — 沒有它,互動處理器會回傳 400。 + + + +**HMAC 權杖產生** + +Gateway 會使用 HMAC-SHA256 驗證按鈕點擊。外部指令碼必須產生符合 Gateway 驗證邏輯的權杖: + + + + `HMAC-SHA256(key="openclaw-mattermost-interactions", data=botToken)` + + + 使用 `_token` **以外**的所有欄位建構內容物件。 + + + 使用**排序鍵**且**不含空格**進行序列化(Gateway 使用含排序鍵的 `JSON.stringify`,會產生緊湊輸出)。 + + + `HMAC-SHA256(key=secret, data=serializedContext)` + + + 將產生的十六進位摘要作為 `_token` 加入內容中。 + + + +Python 範例: + +```python +import hmac, hashlib, json + +secret = hmac.new( + b"openclaw-mattermost-interactions", + bot_token.encode(), hashlib.sha256 +).hexdigest() + +ctx = {"action_id": "mybutton01", "action": "approve"} +payload = json.dumps(ctx, sort_keys=True, separators=(",", ":")) +token = hmac.new(secret.encode(), payload.encode(), hashlib.sha256).hexdigest() + +context = {**ctx, "_token": token} +``` + + + + - Python 的 `json.dumps` 預設會加入空格(`{"key": "val"}`)。使用 `separators=(",", ":")` 以符合 JavaScript 的緊湊輸出(`{"key":"val"}`)。 + - 一律簽署**所有**內容欄位(扣除 `_token`)。Gateway 會移除 `_token`,然後簽署剩下的所有內容。只簽署子集會導致靜默驗證失敗。 + - 使用 `sort_keys=True` — Gateway 會在簽署前排序鍵,而且 Mattermost 儲存承載時可能會重新排序內容欄位。 + - 從機器人權杖推導密鑰(確定性),不要使用隨機位元組。建立按鈕的程序與驗證按鈕的 Gateway 必須使用相同密鑰。 + + + + +## 目錄配接器 + +Mattermost Plugin 包含一個目錄配接器,可透過 Mattermost API 解析頻道和使用者名稱。這會在 `openclaw message send` 與 Cron/Webhook 傳遞中啟用 `#channel-name` 和 `@username` 目標。 + +無需設定 — 配接器會使用帳戶設定中的機器人權杖。 + +## 多帳戶 + +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"`。 + + + - 檢查機器人權杖、基礎 URL,以及帳戶是否已啟用。 + - 多帳戶問題:環境變數只會套用到 `default` 帳戶。 + + + + - `Unauthorized: invalid command token.`:OpenClaw 未接受回呼權杖。典型原因: + - 斜線命令註冊在啟動時失敗,或只完成一部分 + - 回呼打到錯誤的 Gateway/帳戶 + - Mattermost 仍有舊命令指向先前的回呼目標 + - Gateway 重新啟動後未重新啟用斜線命令 + - 如果原生斜線命令停止運作,請檢查記錄中是否有 `mattermost: failed to register slash commands` 或 `mattermost: native slash commands enabled but no commands could be registered`。 + - 如果省略 `callbackUrl`,且記錄警告回呼解析為 `http://127.0.0.1:18789/...`,該 URL 可能只有在 Mattermost 與 OpenClaw 執行於同一主機/網路命名空間時才能連到。請改為設定明確可從外部連到的 `commands.callbackUrl`。 + + + + - 按鈕顯示為白色方塊:代理可能正在傳送格式錯誤的按鈕資料。檢查每個按鈕是否同時具有 `text` 和 `callback_data` 欄位。 + - 按鈕有呈現但點擊沒有反應:確認 Mattermost 伺服器設定中的 `AllowedUntrustedInternalConnections` 包含 `127.0.0.1 localhost`,且 ServiceSettings 中的 `EnablePostActionIntegration` 為 `true`。 + - 按鈕點擊後回傳 404:按鈕 `id` 可能包含連字號或底線。Mattermost 的動作路由器會因非英數 ID 而失效。只能使用 `[a-zA-Z0-9]`。 + - Gateway 記錄 `invalid _token`:HMAC 不相符。檢查你是否簽署所有內容欄位(不是子集)、使用排序鍵,並使用緊湊 JSON(沒有空格)。請參閱上方 HMAC 區段。 + - Gateway 記錄 `missing _token in context`:`_token` 欄位不在按鈕內容中。請確保建構整合承載時已包含它。 + - 確認訊息顯示原始 ID 而不是按鈕名稱:`context.action_id` 與按鈕的 `id` 不相符。將兩者設定為相同的清理後值。 + - 代理不知道按鈕:將 `capabilities: ["inlineButtons"]` 加入 Mattermost 頻道設定。 + + + + +## 相關 + +- [頻道路由](/zh-TW/channels/channel-routing) — 訊息的工作階段路由 +- [頻道概覽](/zh-TW/channels) — 所有支援的頻道 +- [群組](/zh-TW/channels/groups) — 群組聊天行為與提及門檻 +- [配對](/zh-TW/channels/pairing) — DM 驗證與配對流程 +- [安全性](/zh-TW/gateway/security) — 存取模型與強化 diff --git a/docs/zh-TW/channels/msteams.md b/docs/zh-TW/channels/msteams.md new file mode 100644 index 000000000..773db20f1 --- /dev/null +++ b/docs/zh-TW/channels/msteams.md @@ -0,0 +1,1028 @@ +--- +read_when: + - 開發 Microsoft Teams 通道功能 +summary: Microsoft Teams 機器人支援狀態、功能和設定 +title: Microsoft Teams +x-i18n: + generated_at: "2026-04-30T02:48:04Z" + model: gpt-5.5 + provider: openai + source_hash: c2c8cd13a72941a18d609b1f7263d9b9ed3284873f9b1483975ca1356b543979 + source_path: channels/msteams.md + workflow: 16 +--- + +狀態:支援文字 + DM 附件;頻道/群組傳送檔案需要 `sharePointSiteId` + Graph 權限(請參閱[在群組聊天中傳送檔案](#sending-files-in-group-chats))。投票會透過 Adaptive Cards 傳送。訊息動作會公開明確的 `upload-file`,用於檔案優先的傳送。 + +## 內建 Plugin + +Microsoft Teams 在目前的 OpenClaw 版本中以內建 Plugin 提供,因此一般封裝建置不需要 +另外安裝。 + +如果你使用的是較舊的建置,或是排除內建 Teams 的自訂安裝, +請在有發布時安裝目前的 npm 套件: + +```bash +openclaw plugins install @openclaw/msteams +``` + +如果 npm 回報 OpenClaw 擁有的套件已被棄用,請使用目前封裝的 +OpenClaw 建置,或在較新的 npm 套件發布前使用本機 checkout 路徑。 + +本機 checkout(從 git repo 執行時): + +```bash +openclaw plugins install ./path/to/local/msteams-plugin +``` + +詳細資訊:[Plugins](/zh-TW/tools/plugin) + +## 快速設定 + +[`@microsoft/teams.cli`](https://www.npmjs.com/package/@microsoft/teams.cli) 可用單一命令處理 Bot 註冊、manifest 建立與憑證產生。 + +**1. 安裝並登入** + +```bash +npm install -g @microsoft/teams.cli@preview +teams login +teams status # verify you're logged in and see your tenant info +``` + + +Teams CLI 目前為預覽版。命令與旗標可能會在不同版本之間變更。 + + +**2. 啟動通道**(Teams 無法連到 localhost) + +如果尚未安裝並驗證 devtunnel CLI,請先完成安裝與驗證([入門指南](https://learn.microsoft.com/en-us/azure/developer/dev-tunnels/get-started))。 + +```bash +# One-time setup (persistent URL across sessions): +devtunnel create my-openclaw-bot --allow-anonymous +devtunnel port create my-openclaw-bot -p 3978 --protocol auto + +# Each dev session: +devtunnel host my-openclaw-bot +# Your endpoint: https://.devtunnels.ms/api/messages +``` + + +需要 `--allow-anonymous`,因為 Teams 無法使用 devtunnels 進行驗證。每個傳入的 Bot 請求仍會由 Teams SDK 自動驗證。 + + +替代方案:`ngrok http 3978` 或 `tailscale funnel 3978`(但這些可能每次工作階段都會變更 URL)。 + +**3. 建立應用程式** + +```bash +teams app create \ + --name "OpenClaw" \ + --endpoint "https:///api/messages" +``` + +這個單一命令會: + +- 建立 Entra ID (Azure AD) 應用程式 +- 產生用戶端密碼 +- 建置並上傳 Teams app manifest(含圖示) +- 註冊 Bot(預設由 Teams 管理,不需要 Azure 訂閱) + +輸出會顯示 `CLIENT_ID`、`CLIENT_SECRET`、`TENANT_ID` 和 **Teams App ID**,請記下這些值以供後續步驟使用。它也會提供直接在 Teams 中安裝應用程式的選項。 + +**4. 設定 OpenClaw**,使用輸出中的憑證: + +```json5 +{ + channels: { + msteams: { + enabled: true, + appId: "", + appPassword: "", + tenantId: "", + webhook: { port: 3978, path: "/api/messages" }, + }, + }, +} +``` + +或直接使用環境變數:`MSTEAMS_APP_ID`、`MSTEAMS_APP_PASSWORD`、`MSTEAMS_TENANT_ID`。 + +**5. 在 Teams 中安裝應用程式** + +`teams app create` 會提示你安裝應用程式,請選取「Install in Teams」。如果你略過了,稍後可以取得連結: + +```bash +teams app get --install-link +``` + +**6. 驗證一切正常運作** + +```bash +teams app doctor +``` + +這會針對 Bot 註冊、AAD 應用程式設定、manifest 有效性與 SSO 設定執行診斷。 + +對於生產部署,請考慮使用[同盟驗證](/zh-TW/channels/msteams#federated-authentication-certificate-plus-managed-identity)(憑證或受控身分)取代用戶端密碼。 + + +群組聊天預設會被封鎖(`channels.msteams.groupPolicy: "allowlist"`)。若要允許群組回覆,請設定 `channels.msteams.groupAllowFrom`,或使用 `groupPolicy: "open"` 允許任何成員(仍受提及控管)。 + + +## 目標 + +- 透過 Teams DM、群組聊天或頻道與 OpenClaw 對話。 +- 保持路由具決定性:回覆一律回到原始抵達的頻道。 +- 預設使用安全的頻道行為(除非另有設定,否則需要提及)。 + +## 設定寫入 + +預設允許 Microsoft Teams 寫入由 `/config set|unset` 觸發的設定更新(需要 `commands.config: true`)。 + +使用以下設定停用: + +```json5 +{ + channels: { msteams: { configWrites: false } }, +} +``` + +## 存取控制(DM + 群組) + +**DM 存取** + +- 預設:`channels.msteams.dmPolicy = "pairing"`。未知傳送者會被忽略,直到核准為止。 +- `channels.msteams.allowFrom` 應使用穩定的 AAD 物件 ID。 +- 不要依賴 UPN/顯示名稱比對來做允許清單,因為它們可能變更。OpenClaw 預設會停用直接名稱比對;若要啟用,請明確選擇使用 `channels.msteams.dangerouslyAllowNameMatching: true`。 +- 當憑證允許時,精靈可透過 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"], + }, + }, +} +``` + +**Teams + 頻道允許清單** + +- 在 `channels.msteams.teams` 下列出團隊和頻道,以限定群組/頻道回覆範圍。 +- 金鑰應使用 Teams 連結中的穩定 Teams 對話 ID,而不是可變的顯示名稱。 +- 當 `groupPolicy="allowlist"` 且存在 teams 允許清單時,只接受列出的團隊/頻道(受提及控管)。 +- 設定精靈接受 `Team/Channel` 項目,並會替你儲存。 +- 啟動時,OpenClaw 會將團隊/頻道和使用者允許清單名稱解析為 ID(當 Graph 權限允許時) + 並記錄對應關係;未解析的團隊/頻道名稱會依輸入保留,但預設會在路由時忽略,除非已啟用 `channels.msteams.dangerouslyAllowNameMatching: true`。 + +範例: + +```json5 +{ + channels: { + msteams: { + groupPolicy: "allowlist", + teams: { + "My Team": { + channels: { + General: { requireMention: true }, + }, + }, + }, + }, + }, +} +``` + +
+手動設定(不使用 Teams CLI) + +如果你無法使用 Teams CLI,可以透過 Azure Portal 手動設定 Bot。 + +### 運作方式 + +1. 確認 Microsoft Teams Plugin 可用(目前版本已內建)。 +2. 建立 **Azure Bot**(App ID + 密碼 + tenant ID)。 +3. 建置參照該 Bot 且包含下列 RSC 權限的 **Teams app package**。 +4. 將 Teams 應用程式上傳/安裝到團隊中(或針對 DM 使用個人範圍)。 +5. 在 `~/.openclaw/openclaw.json`(或環境變數)中設定 `msteams` 並啟動 Gateway。 +6. Gateway 預設會在 `/api/messages` 監聽 Bot Framework Webhook 流量。 + +### 步驟 1:建立 Azure Bot + +1. 前往[建立 Azure Bot](https://portal.azure.com/#create/Microsoft.AzureBot) +2. 填寫 **Basics** 分頁: + + | 欄位 | 值 | + | ------------------ | -------------------------------------------------------- | + | **Bot handle** | 你的 Bot 名稱,例如 `openclaw-msteams`(必須唯一) | + | **Subscription** | 選取你的 Azure 訂閱 | + | **Resource group** | 建立新的或使用現有的 | + | **Pricing tier** | 開發/測試使用 **Free** | + | **Type of App** | **Single Tenant**(建議,請參閱下方注意事項) | + | **Creation type** | **Create new Microsoft App ID** | + + +2025-07-31 之後已棄用建立新的多租用戶 Bot。新 Bot 請使用 **Single Tenant**。 + + +3. 按一下 **Review + create** → **Create**(等待約 1-2 分鐘) + +### 步驟 2:取得憑證 + +1. 前往你的 Azure Bot 資源 → **Configuration** +2. 複製 **Microsoft App ID** → 這就是你的 `appId` +3. 按一下 **Manage Password** → 前往 App Registration +4. 在 **Certificates & secrets** 下 → **New client secret** → 複製 **Value** → 這就是你的 `appPassword` +5. 前往 **Overview** → 複製 **Directory (tenant) ID** → 這就是你的 `tenantId` + +### 步驟 3:設定 Messaging Endpoint + +1. 在 Azure Bot → **Configuration** +2. 將 **Messaging endpoint** 設定為你的 Webhook URL: + - 生產:`https://your-domain.com/api/messages` + - 本機開發:使用通道(請參閱下方[本機開發](#local-development-tunneling)) + +### 步驟 4:啟用 Teams Channel + +1. 在 Azure Bot → **Channels** +2. 按一下 **Microsoft Teams** → Configure → Save +3. 接受服務條款 + +### 步驟 5:建置 Teams App Manifest + +- 包含 `bot` 項目,且 `botId = `。 +- 範圍:`personal`、`team`、`groupChat`。 +- `supportsFiles: true`(個人範圍檔案處理所需)。 +- 新增 RSC 權限(請參閱 [RSC 權限](#current-teams-rsc-permissions-manifest))。 +- 建立圖示:`outline.png` (32x32) 和 `color.png` (192x192)。 +- 將三個檔案壓縮在一起:`manifest.json`、`outline.png`、`color.png`。 + +### 步驟 6:設定 OpenClaw + +```json5 +{ + channels: { + msteams: { + enabled: true, + appId: "", + appPassword: "", + tenantId: "", + webhook: { port: 3978, path: "/api/messages" }, + }, + }, +} +``` + +環境變數:`MSTEAMS_APP_ID`、`MSTEAMS_APP_PASSWORD`、`MSTEAMS_TENANT_ID`。 + +### 步驟 7:執行 Gateway + +當 Plugin 可用,且 `msteams` 設定存在並包含憑證時,Teams 頻道會自動啟動。 + +
+ +## 同盟驗證(憑證加受控身分) + +> 已於 2026.4.11 新增 + +對於生產部署,OpenClaw 支援**同盟驗證**,作為比用戶端密碼更安全的替代方案。可使用兩種方法: + +### 選項 A:憑證型驗證 + +使用在你的 Entra ID 應用程式註冊中註冊的 PEM 憑證。 + +**設定:** + +1. 產生或取得憑證(含私密金鑰的 PEM 格式)。 +2. 在 Entra ID → App Registration → **Certificates & secrets** → **Certificates** → 上傳公開憑證。 + +**設定:** + +```json5 +{ + channels: { + msteams: { + enabled: true, + appId: "", + tenantId: "", + authType: "federated", + certificatePath: "/path/to/cert.pem", + webhook: { port: 3978, path: "/api/messages" }, + }, + }, +} +``` + +**環境變數:** + +- `MSTEAMS_AUTH_TYPE=federated` +- `MSTEAMS_CERTIFICATE_PATH=/path/to/cert.pem` + +### 選項 B:Azure Managed Identity + +使用 Azure Managed Identity 進行無密碼驗證。這非常適合部署在 Azure 基礎架構(AKS、App Service、Azure VM)且可使用受控身分的情境。 + +**運作方式:** + +1. Bot pod/VM 具有受控身分(系統指派或使用者指派)。 +2. **同盟身分憑證**會將受控身分連結至 Entra ID 應用程式註冊。 +3. 執行階段,OpenClaw 使用 `@azure/identity` 從 Azure IMDS 端點(`169.254.169.254`)取得權杖。 +4. 權杖會傳遞給 Teams SDK 以進行 Bot 驗證。 + +**先決條件:** + +- 已啟用受控身分的 Azure 基礎架構(AKS workload identity、App Service、VM) +- 已在 Entra ID 應用程式註冊中建立同盟身分憑證 +- pod/VM 可連線至 IMDS(`169.254.169.254:80`) + +**設定(系統指派受控身分):** + +```json5 +{ + channels: { + msteams: { + enabled: true, + appId: "", + tenantId: "", + authType: "federated", + useManagedIdentity: true, + webhook: { port: 3978, path: "/api/messages" }, + }, + }, +} +``` + +**設定(系統指派的受控身分):** + +```json5 +{ + channels: { + msteams: { + enabled: true, + appId: "", + tenantId: "", + authType: "federated", + useManagedIdentity: true, + managedIdentityClientId: "", + webhook: { port: 3978, path: "/api/messages" }, + }, + }, +} +``` + +**環境變數:** + +- `MSTEAMS_AUTH_TYPE=federated` +- `MSTEAMS_USE_MANAGED_IDENTITY=true` +- `MSTEAMS_MANAGED_IDENTITY_CLIENT_ID=`(僅限使用者指派) + +### AKS 工作負載身分設定 + +對於使用工作負載身分的 AKS 部署: + +1. 在你的 AKS 叢集上**啟用工作負載身分**。 +2. 在 Entra ID 應用程式註冊上**建立同盟身分認證**: + + ```bash + az ad app federated-credential create --id --parameters '{ + "name": "my-bot-workload-identity", + "issuer": "", + "subject": "system:serviceaccount::", + "audiences": ["api://AzureADTokenExchange"] + }' + ``` + +3. 使用應用程式用戶端 ID **標註 Kubernetes 服務帳戶**: + + ```yaml + apiVersion: v1 + kind: ServiceAccount + metadata: + name: my-bot-sa + annotations: + azure.workload.identity/client-id: "" + ``` + +4. 為工作負載身分注入**標記 Pod**: + + ```yaml + metadata: + labels: + azure.workload.identity/use: "true" + ``` + +5. **確保可存取** IMDS(`169.254.169.254`)網路;如果使用 NetworkPolicy,請新增一條輸出規則,允許連到 `169.254.169.254/32` 的 80 連接埠。 + +### 驗證類型比較 + +| 方法 | 設定 | 優點 | 缺點 | +| -------------------- | ---------------------------------------------- | ------------------------ | ---------------------------- | +| **用戶端密碼** | `appPassword` | 設定簡單 | 需要輪替密碼,安全性較低 | +| **憑證** | `authType: "federated"` + `certificatePath` | 不透過網路共用密碼 | 憑證管理成本 | +| **受控身分** | `authType: "federated"` + `useManagedIdentity` | 無密碼,無需管理密碼 | 需要 Azure 基礎架構 | + +**預設行為:** 未設定 `authType` 時,OpenClaw 預設使用用戶端密碼驗證。現有設定不需變更即可繼續運作。 + +## 本機開發(通道) + +Teams 無法連到 `localhost`。請使用持久的開發通道,讓你的 URL 在不同工作階段中保持不變: + +```bash +# One-time setup: +devtunnel create my-openclaw-bot --allow-anonymous +devtunnel port create my-openclaw-bot -p 3978 --protocol auto + +# Each dev session: +devtunnel host my-openclaw-bot +``` + +替代方案:`ngrok http 3978` 或 `tailscale funnel 3978`(URL 可能在每個工作階段變更)。 + +如果你的通道 URL 變更,請更新端點: + +```bash +teams app update --endpoint "https:///api/messages" +``` + +## 測試 Bot + +**執行診斷:** + +```bash +teams app doctor +``` + +一次檢查 Bot 註冊、AAD 應用程式、資訊清單和 SSO 設定。 + +**傳送測試訊息:** + +1. 安裝 Teams 應用程式(使用 `teams app get --install-link` 取得的安裝連結) +2. 在 Teams 中找到 Bot 並傳送 DM +3. 檢查 Gateway 記錄中的傳入活動 + +## 環境變數 + +所有設定鍵也可以改用環境變數設定: + +- `MSTEAMS_APP_ID` +- `MSTEAMS_APP_PASSWORD` +- `MSTEAMS_TENANT_ID` +- `MSTEAMS_AUTH_TYPE`(選用:`"secret"` 或 `"federated"`) +- `MSTEAMS_CERTIFICATE_PATH`(同盟 + 憑證) +- `MSTEAMS_CERTIFICATE_THUMBPRINT`(選用,驗證不需要) +- `MSTEAMS_USE_MANAGED_IDENTITY`(同盟 + 受控身分) +- `MSTEAMS_MANAGED_IDENTITY_CLIENT_ID`(僅限使用者指派的 MI) + +## 成員資訊動作 + +OpenClaw 為 Microsoft Teams 提供由 Graph 支援的 `member-info` 動作,讓代理程式和自動化流程能直接從 Microsoft Graph 解析頻道成員詳細資料(顯示名稱、電子郵件、角色)。 + +需求: + +- `Member.Read.Group` RSC 權限(已在建議的資訊清單中) +- 跨團隊查詢:具有系統管理員同意的 `User.Read.All` Graph 應用程式權限 + +此動作由 `channels.msteams.actions.memberInfo` 控制(預設:Graph 認證可用時啟用)。 + +## 歷史脈絡 + +- `channels.msteams.historyLimit` 控制要將多少最近的頻道/群組訊息包進提示詞。 +- 回退至 `messages.groupChat.historyLimit`。設定為 `0` 可停用(預設 50)。 +- 擷取的執行緒歷史會依傳送者允許清單(`allowFrom` / `groupAllowFrom`)過濾,因此執行緒脈絡種子只包含來自允許傳送者的訊息。 +- 引用附件脈絡(從 Teams 回覆 HTML 衍生的 `ReplyTo*`)目前會照收到的內容傳遞。 +- 換句話說,允許清單會控管誰能觸發代理程式;目前只有特定補充脈絡路徑會被過濾。 +- DM 歷史可透過 `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 CLI 新增 RSC 權限: + +```bash +teams app rsc add ChannelMessage.Read.Group --type Application +``` + +## Teams 資訊清單範例(已遮蔽) + +包含必要欄位的最小有效範例。請替換 ID 和 URL。 + +```json5 +{ + $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 權限): + +```bash +# Download, edit, and re-upload the manifest +teams app manifest download manifest.json +# Edit manifest.json locally... +teams app manifest upload manifest.json +# Version is auto-bumped if content changed +``` + +更新後,請在每個團隊中重新安裝應用程式,讓新權限生效,並**完全結束並重新啟動 Teams**(不要只是關閉視窗)以清除快取的應用程式中繼資料。 + +
+手動更新資訊清單(不使用 CLI) + +1. 使用新設定更新你的 `manifest.json` +2. **遞增 `version` 欄位**(例如 `1.0.0` → `1.1.0`) +3. 將資訊清單與圖示(`manifest.json`、`outline.png`、`color.png`)**重新壓縮** +4. 上傳新的 zip: + - **Teams 管理中心:** Teams 應用程式 → 管理應用程式 → 找到你的應用程式 → 上傳新版本 + - **側載:** 在 Teams 中 → 應用程式 → 管理你的應用程式 → 上傳自訂應用程式 + +
+ +## 功能:僅 RSC 與 Graph + +### 僅使用 **Teams RSC**(已安裝應用程式,沒有 Graph API 權限) + +可運作: + +- 讀取頻道訊息**文字**內容。 +- 傳送頻道訊息**文字**內容。 +- 接收**個人(DM)**檔案附件。 + +不可運作: + +- 頻道/群組**圖片或檔案內容**(承載內容只包含 HTML stub)。 +- 下載儲存在 SharePoint/OneDrive 的附件。 +- 讀取訊息歷史(即時 Webhook 事件之外)。 + +### 使用 **Teams RSC + Microsoft Graph 應用程式權限** + +新增: + +- 下載託管內容(貼到訊息中的圖片)。 +- 下載儲存在 SharePoint/OneDrive 的檔案附件。 +- 透過 Graph 讀取頻道/聊天訊息歷史。 + +### RSC 與 Graph API + +| 功能 | RSC 權限 | Graph API | +| ---------------------- | -------------------- | ----------------------------------- | +| **即時訊息** | 是(透過 Webhook) | 否(僅能輪詢) | +| **歷史訊息** | 否 | 是(可以查詢歷史) | +| **設定複雜度** | 僅需應用程式資訊清單 | 需要系統管理員同意 + 權杖流程 | +| **離線時可用** | 否(必須執行中) | 是(隨時查詢) | + +**重點:** RSC 用於即時監聽;Graph API 用於歷史存取。若要在離線期間補抓漏掉的訊息,你需要使用具備 `ChannelMessage.Read.All` 的 Graph API(需要系統管理員同意)。 + +## 啟用 Graph 的媒體 + 歷史(頻道必要) + +如果你需要**頻道**中的圖片/檔案,或想擷取**訊息歷史**,你必須啟用 Microsoft Graph 權限並授與系統管理員同意。 + +1. 在 Entra ID(Azure AD)**應用程式註冊**中,新增 Microsoft Graph **應用程式權限**: + - `ChannelMessage.Read.All`(頻道附件 + 歷史) + - `Chat.Read.All` 或 `ChatMessage.Read.All`(群組聊天) +2. 為租用戶**授與系統管理員同意**。 +3. 提升 Teams 應用程式**資訊清單版本**,重新上傳,並**在 Teams 中重新安裝應用程式**。 +4. **完全結束並重新啟動 Teams**,以清除快取的應用程式中繼資料。 + +**使用者提及的額外權限:** 對話中的使用者 @提及可直接運作。不過,如果你想動態搜尋並提及**不在目前對話中**的使用者,請新增 `User.Read.All`(Application)權限並授與系統管理員同意。 + +## 已知限制 + +### Webhook 逾時 + +Teams 透過 HTTP Webhook 傳遞訊息。如果處理時間太長(例如 LLM 回應很慢),你可能會看到: + +- Gateway 逾時 +- Teams 重試訊息(造成重複) +- 回覆被丟棄 + +OpenClaw 會透過快速返回並主動傳送回覆來處理此情況,但非常慢的回應仍可能造成問題。 + +### 格式設定 + +Teams Markdown 比 Slack 或 Discord 更受限: + +- 基本格式可運作:**粗體**、_斜體_、`code`、連結 +- 複雜 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`:DM 允許清單(建議使用 AAD 物件 ID)。設定精靈會在可用 Graph 存取權時,於設定期間將名稱解析為 ID。 +- `channels.msteams.dangerouslyAllowNameMatching`:緊急切換開關,用於重新啟用可變的 UPN/顯示名稱比對,以及直接依團隊/通道名稱路由。 +- `channels.msteams.textChunkLimit`:外送文字區塊大小。 +- `channels.msteams.chunkMode`:`length`(預設)或 `newline`,在依長度切分前先依空白行(段落邊界)切分。 +- `channels.msteams.mediaAllowHosts`:入站附件主機允許清單(預設為 Microsoft/Teams 網域)。 +- `channels.msteams.mediaAuthAllowHosts`:在媒體重試時允許附加 Authorization 標頭的主機允許清單(預設為 Graph + Bot Framework 主機)。 +- `channels.msteams.requireMention`:在通道/群組中要求 @mention(預設為 true)。 +- `channels.msteams.replyStyle`:`thread | top-level`(請參閱[回覆樣式](#reply-style-threads-vs-posts))。 +- `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`:每個通道、每寄件者工具政策覆寫(支援 `"*"` 萬用字元)。 +- `toolsBySender` 鍵應使用明確前綴: + `id:`、`e164:`、`username:`、`name:`(舊版無前綴鍵仍只會對應到 `id:`)。 +- `channels.msteams.actions.memberInfo`:啟用或停用由 Graph 支援的成員資訊動作(預設:Graph 認證資訊可用時啟用)。 +- `channels.msteams.authType`:驗證類型 — `"secret"`(預設)或 `"federated"`。 +- `channels.msteams.certificatePath`:PEM 憑證檔案路徑(federated + certificate auth)。 +- `channels.msteams.certificateThumbprint`:憑證指紋(選用,驗證不需要)。 +- `channels.msteams.useManagedIdentity`:啟用受控識別驗證(federated 模式)。 +- `channels.msteams.managedIdentityClientId`:使用者指派受控識別的用戶端 ID。 +- `channels.msteams.sharePointSiteId`:用於群組聊天/通道檔案上傳的 SharePoint 網站 ID(請參閱[在群組聊天中傳送檔案](#sending-files-in-group-chats))。 + +## 路由與工作階段 + +- 工作階段鍵遵循標準代理程式格式(請參閱 [/concepts/session](/zh-TW/concepts/session)): + - 直接訊息共用主工作階段(`agent::`)。 + - 通道/群組訊息使用 conversation id: + - `agent::msteams:channel:` + - `agent::msteams:group:` + +## 回覆樣式:討論串與貼文 + +Teams 最近在相同的底層資料模型上引入了兩種通道 UI 樣式: + +| 樣式 | 說明 | 建議的 `replyStyle` | +| ------------------------ | ---------------------------------------------- | ------------------- | +| **貼文**(傳統) | 訊息顯示為卡片,下方有討論串回覆 | `thread`(預設) | +| **討論串**(類 Slack) | 訊息以線性方式流動,更像 Slack | `top-level` | + +**問題:** Teams API 不會公開通道使用哪一種 UI 樣式。如果使用錯誤的 `replyStyle`: + +- 在討論串樣式通道中使用 `thread` → 回覆會顯得彆扭地巢狀化 +- 在貼文樣式通道中使用 `top-level` → 回覆會顯示為獨立的頂層貼文,而不是在討論串內 + +**解決方案:** 根據通道的設定方式,逐通道設定 `replyStyle`: + +```json5 +{ + channels: { + msteams: { + replyStyle: "thread", + teams: { + "19:abc...@thread.tacv2": { + channels: { + "19:xyz...@thread.tacv2": { + replyStyle: "top-level", + }, + }, + }, + }, + }, + }, +} +``` + +## 附件與圖片 + +**目前限制:** + +- **DM:** 圖片與檔案附件可透過 Teams 機器人檔案 API 運作。 +- **通道/群組:** 附件位於 M365 儲存空間(SharePoint/OneDrive)。Webhook 承載內容只包含 HTML stub,而非實際檔案位元組。**必須具備 Graph API 權限**才能下載通道附件。 +- 若要明確傳送以檔案優先的內容,請使用 `action=upload-file` 搭配 `media` / `filePath` / `path`;選用的 `message` 會成為隨附文字/留言,而 `filename` 會覆寫上傳名稱。 + +沒有 Graph 權限時,含圖片的通道訊息會以純文字形式接收(機器人無法存取圖片內容)。 +預設情況下,OpenClaw 只會從 Microsoft/Teams 主機名稱下載媒體。可使用 `channels.msteams.mediaAllowHosts` 覆寫(使用 `["*"]` 允許任何主機)。 +Authorization 標頭只會附加至 `channels.msteams.mediaAuthAllowHosts` 中的主機(預設為 Graph + Bot Framework 主機)。請讓此清單保持嚴格(避免多租戶尾碼)。 + +## 在群組聊天中傳送檔案 + +機器人可以使用 FileConsentCard 流程(內建)在 DM 中傳送檔案。不過,**在群組聊天/通道中傳送檔案**需要額外設定: + +| 情境 | 檔案傳送方式 | 所需設定 | +| ------------------------ | ------------------------------------------- | ----------------------------------------------- | +| **DM** | FileConsentCard → 使用者接受 → 機器人上傳 | 可直接運作 | +| **群組聊天/通道** | 上傳至 SharePoint → 分享連結 | 需要 `sharePointSiteId` + Graph 權限 | +| **圖片(任何情境)** | Base64 編碼內嵌 | 可直接運作 | + +### 為什麼群組聊天需要 SharePoint + +機器人沒有個人 OneDrive 磁碟機(`/me/drive` Graph API 端點不適用於應用程式身分)。若要在群組聊天/通道中傳送檔案,機器人會上傳至 **SharePoint 網站**並建立分享連結。 + +### 設定 + +1. 在 Entra ID (Azure AD) → App Registration 中**新增 Graph API 權限**: + - `Sites.ReadWrite.All`(Application)- 將檔案上傳至 SharePoint + - `Chat.Read.All`(Application)- 選用,啟用每使用者分享連結 + +2. 為租戶**授與管理員同意**。 + +3. **取得你的 SharePoint 網站 ID:** + + ```bash + # Via Graph Explorer or curl with a valid token: + curl -H "Authorization: Bearer $TOKEN" \ + "https://graph.microsoft.com/v1.0/sites/{hostname}:/{site-path}" + + # Example: for a site at "contoso.sharepoint.com/sites/BotFiles" + curl -H "Authorization: Bearer $TOKEN" \ + "https://graph.microsoft.com/v1.0/sites/contoso.sharepoint.com:/sites/BotFiles" + + # Response includes: "id": "contoso.sharepoint.com,guid1,guid2" + ``` + +4. **設定 OpenClaw:** + + ```json5 + { + channels: { + msteams: { + // ... other config ... + 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 會將 Teams 投票傳送為 Adaptive Cards(沒有原生 Teams 投票 API)。 + +- CLI:`openclaw message poll --channel msteams --target conversation: ...` +- 投票由 Gateway 記錄在 `~/.openclaw/msteams-polls.json`。 +- Gateway 必須保持線上才能記錄投票。 +- 投票尚不會自動發布結果摘要(如有需要,請檢查儲存檔案)。 + +## 呈現卡片 + +使用 `message` 工具或 CLI,將語意呈現承載內容傳送給 Teams 使用者或對話。OpenClaw 會從通用呈現合約將其呈現為 Teams Adaptive Cards。 + +`presentation` 參數接受語意區塊。提供 `presentation` 時,訊息文字為選用。 + +**代理程式工具:** + +```json5 +{ + action: "send", + channel: "msteams", + target: "user:", + presentation: { + title: "Hello", + blocks: [{ type: "text", text: "Hello!" }], + }, +} +``` + +**CLI:** + +```bash +openclaw message send --channel msteams \ + --target "conversation:19:abc...@thread.tacv2" \ + --presentation '{"title":"Hello","blocks":[{"type":"text","text":"Hello!"}]}' +``` + +目標格式詳細資訊請參閱下方的[目標格式](#target-formats)。 + +## 目標格式 + +MSTeams 目標使用前綴來區分使用者與對話: + +| 目標類型 | 格式 | 範例 | +| ------------------- | -------------------------------- | --------------------------------------------------- | +| 使用者(依 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 +# Send to a user by ID +openclaw message send --channel msteams --target "user:40a1a0ed-..." --message "Hello" + +# Send to a user by display name (triggers Graph API lookup) +openclaw message send --channel msteams --target "user:John Smith" --message "Hello" + +# Send to a group chat or channel +openclaw message send --channel msteams --target "conversation:19:abc...@thread.tacv2" --message "Hello" + +# Send a presentation card to a conversation +openclaw message send --channel msteams --target "conversation:19:abc...@thread.tacv2" \ + --presentation '{"title":"Hello","blocks":[{"type":"text","text":"Hello"}]}' +``` + +**Agent 工具範例:** + +```json5 +{ + action: "send", + channel: "msteams", + target: "user:John Smith", + message: "Hello!", +} +``` + +```json5 +{ + action: "send", + channel: "msteams", + target: "conversation:19:abc...@thread.tacv2", + presentation: { + title: "Hello", + blocks: [{ type: "text", text: "Hello" }], + }, +} +``` + + +若沒有 `user:` 前綴,名稱預設會解析為群組或團隊。依顯示名稱指定人員時,請一律使用 `user:`。 + + +## 主動訊息 + +- 只有在使用者互動**之後**,才可能傳送主動訊息,因為我們會在該時間點儲存對話參照。 +- 請參閱 `/gateway/configuration` 以了解 `dmPolicy` 和允許清單控管。 + +## 團隊和頻道 ID(常見陷阱) + +Teams URL 中的 `groupId` 查詢參數**不是**用於設定的團隊 ID。請改從 URL 路徑擷取 ID: + +**團隊 URL:** + +``` +https://teams.microsoft.com/l/team/19%3ABk4j...%40thread.tacv2/conversations?groupId=... + └────────────────────────────┘ + Team conversation ID (URL-decode this) +``` + +**頻道 URL:** + +``` +https://teams.microsoft.com/l/channel/19%3A15bc...%40thread.tacv2/ChannelName?groupId=... + └─────────────────────────┘ + Channel ID (URL-decode this) +``` + +**設定用:** + +- 團隊鍵 = `/team/` 之後的路徑區段(URL 解碼後,例如 `19:Bk4j...@thread.tacv2`;較舊的租用戶可能會顯示 `@thread.skype`,這也有效) +- 頻道鍵 = `/channel/` 之後的路徑區段(URL 解碼後) +- 對 OpenClaw 路由來說,請**忽略** `groupId` 查詢參數。它是 Microsoft Entra 群組 ID,不是傳入 Teams 活動中使用的 Bot Framework 對話 ID。 + +## 私人頻道 + +機器人在私人頻道中的支援有限: + +| 功能 | 標準頻道 | 私人頻道 | +| ---------------------------- | -------- | -------------------- | +| 機器人安裝 | 是 | 有限 | +| 即時訊息 (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](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 Developer Portal](https://dev.teams.microsoft.com/apps) - 建立/管理 Teams 應用程式 +- [Teams 應用程式資訊清單結構描述](https://learn.microsoft.com/en-us/microsoftteams/platform/resources/schema/manifest-schema) +- [使用 RSC 接收頻道訊息](https://learn.microsoft.com/en-us/microsoftteams/platform/bots/how-to/conversations/channel-messages-with-rsc) +- [RSC 權限參考](https://learn.microsoft.com/en-us/microsoftteams/platform/graph-api/rsc/resource-specific-consent) +- [Teams 機器人檔案處理](https://learn.microsoft.com/en-us/microsoftteams/platform/bots/how-to/bots-filesv4)(頻道/群組需要 Graph) +- [主動傳訊](https://learn.microsoft.com/en-us/microsoftteams/platform/bots/how-to/conversations/send-proactive-messages) +- [@microsoft/teams.cli](https://www.npmjs.com/package/@microsoft/teams.cli) - 用於機器人管理的 Teams CLI + +## 相關 + +- [頻道概觀](/zh-TW/channels) — 所有支援的頻道 +- [配對](/zh-TW/channels/pairing) — 私訊驗證與配對流程 +- [群組](/zh-TW/channels/groups) — 群組聊天行為與提及門檻 +- [頻道路由](/zh-TW/channels/channel-routing) — 訊息的工作階段路由 +- [安全性](/zh-TW/gateway/security) — 存取模型與強化 diff --git a/docs/zh-TW/channels/nextcloud-talk.md b/docs/zh-TW/channels/nextcloud-talk.md new file mode 100644 index 000000000..66a809b7e --- /dev/null +++ b/docs/zh-TW/channels/nextcloud-talk.md @@ -0,0 +1,182 @@ +--- +read_when: + - 開發 Nextcloud Talk 頻道功能 +summary: Nextcloud Talk 支援狀態、功能與設定 +title: Nextcloud Talk +x-i18n: + generated_at: "2026-04-30T02:48:12Z" + model: gpt-5.5 + provider: openai + source_hash: fcbe8a65adfddc95d2b4944af88f9982e23a1676752efec2bbf40cfc4dd846d2 + source_path: channels/nextcloud-talk.md + workflow: 16 +--- + +Status: 內建 Plugin(Webhook 機器人)。支援直接訊息、聊天室、回應,以及 Markdown 訊息。 + +## 內建 Plugin + +Nextcloud Talk 在目前的 OpenClaw 版本中以內建 Plugin 提供,因此 +一般封裝建置不需要另行安裝。 + +如果你使用的是較舊的建置,或是排除 Nextcloud Talk 的自訂安裝, +請在有目前版本套件發布時安裝目前的 npm 套件: + +透過 CLI 安裝(npm registry,有目前套件時): + +```bash +openclaw plugins install @openclaw/nextcloud-talk +``` + +如果 npm 回報 OpenClaw 擁有的套件已棄用,請使用目前的封裝 +OpenClaw 建置,或在較新的 npm 套件發布前使用本機 checkout 路徑。 + +本機 checkout(從 git repo 執行時): + +```bash +openclaw plugins install ./path/to/local/nextcloud-talk-plugin +``` + +詳細資訊:[Plugin](/zh-TW/tools/plugin) + +## 快速設定(初學者) + +1. 確認 Nextcloud Talk Plugin 可用。 + - 目前的封裝 OpenClaw 版本已內建它。 + - 較舊或自訂安裝可以使用上述指令手動加入。 +2. 在你的 Nextcloud 伺服器上建立機器人: + + ```bash + ./occ talk:bot:install "OpenClaw" "" "" --feature reaction + ``` + +3. 在目標聊天室設定中啟用機器人。 +4. 設定 OpenClaw: + - 設定:`channels.nextcloud-talk.baseUrl` + `channels.nextcloud-talk.botSecret` + - 或 env:`NEXTCLOUD_TALK_BOT_SECRET`(僅預設帳號) + + CLI 設定: + + ```bash + openclaw channels add --channel nextcloud-talk \ + --url https://cloud.example.com \ + --token "" + ``` + + 等效的明確欄位: + + ```bash + openclaw channels add --channel nextcloud-talk \ + --base-url https://cloud.example.com \ + --secret "" + ``` + + 檔案支援的 secret: + + ```bash + openclaw channels add --channel nextcloud-talk \ + --base-url https://cloud.example.com \ + --secret-file /path/to/nextcloud-talk-secret + ``` + +5. 重新啟動 Gateway(或完成設定)。 + +最小設定: + +```json5 +{ + channels: { + "nextcloud-talk": { + enabled: true, + baseUrl: "https://cloud.example.com", + botSecret: "shared-secret", + dmPolicy: "pairing", + }, + }, +} +``` + +## 注意事項 + +- 機器人無法主動發起 DM。使用者必須先傳訊息給機器人。 +- Webhook URL 必須可由 Gateway 存取;如果位於代理後方,請設定 `webhookPublicUrl`。 +- 機器人 API 不支援媒體上傳;媒體會以 URL 傳送。 +- Webhook payload 不會區分 DM 與聊天室;設定 `apiUser` + `apiPassword` 可啟用聊天室類型查詢(否則 DM 會被視為聊天室)。 + +## 存取控制(DM) + +- 預設:`channels.nextcloud-talk.dmPolicy = "pairing"`。未知傳送者會取得配對碼。 +- 透過下列方式核准: + - `openclaw pairing list nextcloud-talk` + - `openclaw pairing approve nextcloud-talk ` +- 公開 DM:`channels.nextcloud-talk.dmPolicy="open"` 加上 `channels.nextcloud-talk.allowFrom=["*"]`。 +- `allowFrom` 只會比對 Nextcloud 使用者 ID;顯示名稱會被忽略。 + +## 聊天室(群組) + +- 預設:`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) + +完整設定:[設定](/zh-TW/gateway/configuration) + +Provider 選項: + +- `channels.nextcloud-talk.enabled`:啟用/停用 channel 啟動。 +- `channels.nextcloud-talk.baseUrl`:Nextcloud 執行個體 URL。 +- `channels.nextcloud-talk.botSecret`:機器人 shared secret。 +- `channels.nextcloud-talk.botSecretFile`:一般檔案 secret 路徑。symlink 會被拒絕。 +- `channels.nextcloud-talk.apiUser`:用於聊天室查詢的 API 使用者(DM 偵測)。 +- `channels.nextcloud-talk.apiPassword`:用於聊天室查詢的 API/app 密碼。 +- `channels.nextcloud-talk.apiPasswordFile`:API 密碼檔案路徑。 +- `channels.nextcloud-talk.webhookPort`:Webhook listener 連接埠(預設:8788)。 +- `channels.nextcloud-talk.webhookHost`:Webhook host(預設:0.0.0.0)。 +- `channels.nextcloud-talk.webhookPath`:Webhook path(預設:/nextcloud-talk-webhook)。 +- `channels.nextcloud-talk.webhookPublicUrl`:外部可存取的 Webhook URL。 +- `channels.nextcloud-talk.dmPolicy`:`pairing | allowlist | open | disabled`。 +- `channels.nextcloud-talk.allowFrom`:DM 允許清單(使用者 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`:DM 歷史記錄限制(0 會停用)。 +- `channels.nextcloud-talk.dms`:各 DM 覆寫(historyLimit)。 +- `channels.nextcloud-talk.textChunkLimit`:輸出文字區塊大小(字元)。 +- `channels.nextcloud-talk.chunkMode`:`length`(預設)或 `newline`,在依長度分塊前先依空白行(段落邊界)分割。 +- `channels.nextcloud-talk.blockStreaming`:停用此 channel 的區塊串流。 +- `channels.nextcloud-talk.blockStreamingCoalesce`:區塊串流合併調校。 +- `channels.nextcloud-talk.mediaMaxMb`:傳入媒體上限(MB)。 + +## 相關 + +- [Channels 概覽](/zh-TW/channels) — 所有支援的 channels +- [配對](/zh-TW/channels/pairing) — DM 驗證與配對流程 +- [群組](/zh-TW/channels/groups) — 群組聊天行為與提及閘控 +- [Channel 路由](/zh-TW/channels/channel-routing) — 訊息的工作階段路由 +- [安全性](/zh-TW/gateway/security) — 存取模型與強化 diff --git a/docs/zh-TW/channels/nostr.md b/docs/zh-TW/channels/nostr.md new file mode 100644 index 000000000..9e563a8e9 --- /dev/null +++ b/docs/zh-TW/channels/nostr.md @@ -0,0 +1,260 @@ +--- +read_when: + - 你想讓 OpenClaw 透過 Nostr 接收私訊 + - 你正在設定去中心化訊息傳遞 +summary: 透過 NIP-04 加密訊息的 Nostr 私訊通道 +title: Nostr +x-i18n: + generated_at: "2026-04-30T02:48:23Z" + model: gpt-5.5 + provider: openai + source_hash: 545d68077c9fe81d5fa5a17262d37e3688185a1fb12d67b8b1053b27b96c3c7f + source_path: channels/nostr.md + workflow: 16 +--- + +**狀態:** 選用隨附 Plugin(設定前預設停用)。 + +Nostr 是用於社群網路的去中心化通訊協定。此頻道讓 OpenClaw 能透過 NIP-04 接收並回覆加密直接訊息(DM)。 + +## 隨附 Plugin + +目前的 OpenClaw 版本將 Nostr 作為隨附 Plugin 發佈,因此一般封裝建置 +不需要另外安裝。 + +### 較舊/自訂安裝 + +- Onboarding (`openclaw onboard`) 和 `openclaw channels add` 仍會從共用頻道目錄 + 顯示 Nostr。 +- 如果你的建置排除了隨附的 Nostr,請在目前的 npm 套件發佈後安裝。 + +```bash +openclaw plugins install @openclaw/nostr +``` + +如果 npm 回報 OpenClaw 擁有的套件已棄用,請使用目前封裝的 +OpenClaw 建置,或在較新的 npm 套件發佈前使用本機 checkout。 + +使用本機 checkout(開發工作流程): + +```bash +openclaw plugins install --link +``` + +安裝或啟用 Plugin 後重新啟動 Gateway。 + +### 非互動式設定 + +```bash +openclaw channels add --channel nostr --private-key "$NOSTR_PRIVATE_KEY" +openclaw channels add --channel nostr --private-key "$NOSTR_PRIVATE_KEY" --relay-urls "wss://relay.damus.io,wss://relay.primal.net" +``` + +使用 `--use-env` 將 `NOSTR_PRIVATE_KEY` 保留在環境中,而不是將金鑰儲存在設定裡。 + +## 快速設定 + +1. 產生 Nostr 金鑰組(如有需要): + +```bash +# Using nak +nak key generate +``` + +2. 加入設定: + +```json5 +{ + 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']` | Relay URL(WebSocket) | +| `dmPolicy` | string | `pairing` | DM 存取政策 | +| `allowFrom` | string[] | `[]` | 允許的傳送者 pubkey | +| `enabled` | boolean | `true` | 啟用/停用頻道 | +| `name` | string | - | 顯示名稱 | +| `profile` | object | - | NIP-01 個人檔案中繼資料 | + +## 個人檔案中繼資料 + +個人檔案資料會作為 NIP-01 `kind:0` 事件發佈。你可以從 Control UI(Channels -> Nostr -> Profile)管理,或直接在設定中指定。 + +範例: + +```json5 +{ + 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://`。 +- 從 relay 匯入會合併欄位並保留本機覆寫。 + +## 存取控制 + +### DM 政策 + +- **pairing**(預設):未知傳送者會收到配對碼。 +- **allowlist**:只有 `allowFrom` 中的 pubkey 可以傳送 DM。 +- **open**:公開傳入 DM(需要 `allowFrom: ["*"]`)。 +- **disabled**:忽略傳入 DM。 + +強制執行注意事項: + +- 傳入事件簽章會在傳送者政策和 NIP-04 解密前驗證,因此偽造事件會提早遭到拒絕。 +- 配對回覆會在不處理原始 DM 內文的情況下送出。 +- 傳入 DM 會受到速率限制,過大的 payload 會在解密前被丟棄。 + +### 允許清單範例 + +```json5 +{ + channels: { + nostr: { + privateKey: "${NOSTR_PRIVATE_KEY}", + dmPolicy: "allowlist", + allowFrom: ["npub1abc...", "npub1xyz..."], + }, + }, +} +``` + +## 金鑰格式 + +接受的格式: + +- **私密金鑰:** `nsec...` 或 64 字元十六進位 +- **Pubkeys (`allowFrom`):** `npub...` 或十六進位 + +## Relays + +預設值:`relay.damus.io` 和 `nos.lol`。 + +```json5 +{ + channels: { + nostr: { + privateKey: "${NOSTR_PRIVATE_KEY}", + relays: ["wss://relay.damus.io", "wss://relay.primal.net", "wss://nostr.wine"], + }, + }, +} +``` + +提示: + +- 使用 2-3 個 relay 以提供備援。 +- 避免使用太多 relay(延遲、重複)。 +- 付費 relay 可以提升可靠性。 +- 本機 relay 適合測試(`ws://localhost:7777`)。 + +## 通訊協定支援 + +| NIP | 狀態 | 說明 | +| ------ | ------ | --------------------------------- | +| NIP-01 | 已支援 | 基本事件格式 + 個人檔案中繼資料 | +| NIP-04 | 已支援 | 加密 DM(`kind:4`) | +| NIP-17 | 已規劃 | 禮物包裝 DM | +| NIP-44 | 已規劃 | 版本化加密 | + +## 測試 + +### 本機 relay + +```bash +# Start strfry +docker run -p 7777:7777 ghcr.io/hoytech/strfry +``` + +```json5 +{ + channels: { + nostr: { + privateKey: "${NOSTR_PRIVATE_KEY}", + relays: ["ws://localhost:7777"], + }, + }, +} +``` + +### 手動測試 + +1. 從記錄中記下 bot pubkey(npub)。 +2. 開啟 Nostr 用戶端(Damus、Amethyst 等)。 +3. 對 bot pubkey 傳送 DM。 +4. 驗證回應。 + +## 疑難排解 + +### 未收到訊息 + +- 驗證私密金鑰有效。 +- 確認 relay URL 可連線,且使用 `wss://`(本機則使用 `ws://`)。 +- 確認 `enabled` 不是 `false`。 +- 檢查 Gateway 記錄中的 relay 連線錯誤。 + +### 未傳送回應 + +- 檢查 relay 是否接受寫入。 +- 驗證對外連線能力。 +- 留意 relay 速率限制。 + +### 重複回應 + +- 使用多個 relay 時屬於預期情況。 +- 訊息會依事件 ID 去重;只有第一次傳遞會觸發回應。 + +## 安全性 + +- 絕不要提交私密金鑰。 +- 使用環境變數儲存金鑰。 +- 對正式環境 bot,請考慮使用 `allowlist`。 +- 簽章會在傳送者政策前驗證,且傳送者政策會在解密前強制執行,因此偽造事件會提早遭到拒絕,未知傳送者也無法強制執行完整的密碼學工作。 + +## 限制(MVP) + +- 僅支援直接訊息(不支援群組聊天)。 +- 不支援媒體附件。 +- 僅支援 NIP-04(已規劃 NIP-17 gift-wrap)。 + +## 相關 + +- [頻道概覽](/zh-TW/channels) — 所有支援的頻道 +- [配對](/zh-TW/channels/pairing) — DM 驗證與配對流程 +- [群組](/zh-TW/channels/groups) — 群組聊天行為與提及門檻 +- [頻道路由](/zh-TW/channels/channel-routing) — 訊息的工作階段路由 +- [安全性](/zh-TW/gateway/security) — 存取模型與強化 diff --git a/docs/zh-TW/channels/pairing.md b/docs/zh-TW/channels/pairing.md new file mode 100644 index 000000000..b508fe780 --- /dev/null +++ b/docs/zh-TW/channels/pairing.md @@ -0,0 +1,179 @@ +--- +read_when: + - 設定私訊存取控制 + - 配對新的 iOS/Android 節点 + - 檢視 OpenClaw 安全態勢 +summary: 配對概覽:核准誰可以私訊你 + 哪些節點可以加入 +title: 配對 +x-i18n: + generated_at: "2026-04-30T02:48:36Z" + model: gpt-5.5 + provider: openai + source_hash: cfdcaf831aedb122ea85200518b8dc1c6f42eff365444dee6c4b740050b1ce26 + source_path: channels/pairing.md + workflow: 16 +--- + +「配對」是 OpenClaw 明確的存取核准步驟。 +它用於兩個地方: + +1. **DM 配對**(誰被允許與機器人交談) +2. **Node 配對**(哪些裝置/Node 被允許加入 Gateway 網路) + +安全性脈絡:[安全性](/zh-TW/gateway/security) + +## 1) DM 配對(傳入聊天存取) + +當某個頻道設定為 DM 政策 `pairing` 時,未知寄件者會取得一組短代碼,而且在你核准前,其訊息**不會被處理**。 + +預設 DM 政策記錄於:[安全性](/zh-TW/gateway/security) + +只有在有效的 DM 允許清單包含 `"*"` 時,`dmPolicy: "open"` 才是公開的。 +設定與驗證公開開放設定時需要這個萬用字元。若既有狀態包含 +`open` 以及具體的 `allowFrom` 項目,執行階段仍只允許 +那些寄件者,而配對儲存區核准不會擴大 `open` 存取權。 + +配對代碼: + +- 8 個字元、大寫、不含易混淆字元(`0O1I`)。 +- **1 小時後過期**。機器人只會在建立新請求時傳送配對訊息(約每位寄件者每小時一次)。 +- 待處理的 DM 配對請求預設上限為**每個頻道 3 個**;額外請求會被忽略,直到其中一個過期或被核准。 + +### 核准寄件者 + +```bash +openclaw pairing list telegram +openclaw pairing approve telegram +``` + +如果尚未設定命令擁有者,核准 DM 配對代碼也會將 +`commands.ownerAllowFrom` 啟動設定為已核准的寄件者,例如 `telegram:123456789`。 +這會讓首次設定具備一位明確擁有者,可用於特權命令與 exec +核准提示。在擁有者存在後,後續配對核准只會授予 DM +存取權;它們不會新增更多擁有者。 + +支援的頻道:`bluebubbles`、`discord`、`feishu`、`googlechat`、`imessage`、`irc`、`line`、`matrix`、`mattermost`、`msteams`、`nextcloud-talk`、`nostr`、`openclaw-weixin`、`signal`、`slack`、`synology-chat`、`telegram`、`twitch`、`whatsapp`、`zalo`、`zalouser`。 + +### 狀態存放位置 + +存放於 `~/.openclaw/credentials/`: + +- 待處理請求:`-pairing.json` +- 已核准允許清單儲存區: + - 預設帳號:`-allowFrom.json` + - 非預設帳號:`--allowFrom.json` + +帳號範圍行為: + +- 非預設帳號只會讀寫其範圍限定的允許清單檔案。 +- 預設帳號使用頻道範圍、未限定範圍的允許清單檔案。 + +請將這些視為敏感資料(它們控管對你的助理的存取權)。 + + +配對允許清單儲存區用於 DM 存取。群組授權是分開的。 +核准 DM 配對代碼不會自動允許該寄件者執行群組 +命令或在群組中控制機器人。第一位擁有者啟動設定是 +`commands.ownerAllowFrom` 中的獨立設定狀態,而群組聊天傳遞仍遵循 +頻道的群組允許清單(例如 `groupAllowFrom`、`groups`,或依頻道而定的個別群組 +或個別主題覆寫)。 + + +## 2) Node 裝置配對(iOS/Android/macOS/無頭 Node) + +Node 會以具備 `role: node` 的**裝置**身分連線至 Gateway。Gateway +會建立必須核准的裝置配對請求。 + +### 透過 Telegram 配對(建議用於 iOS) + +如果你使用 `device-pair` Plugin,可以完全透過 Telegram 完成首次裝置配對: + +1. 在 Telegram 中傳訊息給你的機器人:`/pair` +2. 機器人會回覆兩則訊息:一則指示訊息,以及另一則獨立的**設定代碼**訊息(在 Telegram 中易於複製/貼上)。 +3. 在手機上開啟 OpenClaw iOS app → Settings → Gateway。 +4. 貼上設定代碼並連線。 +5. 回到 Telegram:`/pair pending`(檢閱請求 ID、角色與範圍),然後核准。 + +設定代碼是 base64 編碼的 JSON 承載,其中包含: + +- `url`:Gateway WebSocket URL(`ws://...` 或 `wss://...`) +- `bootstrapToken`:短效、單一裝置的啟動權杖,用於初始配對交握 + +該啟動權杖帶有內建的配對啟動設定檔: + +- 主要交接的 `node` 權杖維持 `scopes: []` +- 任何交接的 `operator` 權杖都會限制在啟動允許清單內: + `operator.approvals`、`operator.read`、`operator.talk.secrets`、`operator.write` +- 啟動範圍檢查以角色作為前綴,而不是單一扁平範圍池: + operator 範圍項目只會滿足 operator 請求,且非 operator 角色 + 仍必須在其自身角色前綴下請求範圍 +- 後續權杖輪換/撤銷仍同時受限於裝置已核准的 + 角色合約,以及呼叫者工作階段的 operator 範圍 + +在設定代碼有效期間,請像密碼一樣看待它。 + +### 核准 Node 裝置 + +```bash +openclaw devices list +openclaw devices approve +openclaw devices reject +``` + +如果同一裝置以不同驗證詳細資料重試(例如不同的 +角色/範圍/公開金鑰),先前的待處理請求會被取代,並建立新的 +`requestId`。 + + +已配對的裝置不會被靜默授予更廣的存取權。如果它重新連線並要求更多範圍或更廣的角色,OpenClaw 會保持既有核准不變,並建立新的待處理升級請求。在核准前,請使用 `openclaw devices list` 比較目前已核准的存取權與新請求的存取權。 + + +### 選用的受信任 CIDR Node 自動核准 + +裝置配對預設仍為手動。對於嚴格控管的 Node 網路, +你可以使用明確 CIDR 或精確 IP 選擇加入首次 Node 自動核准: + +```json5 +{ + gateway: { + nodes: { + pairing: { + autoApproveCidrs: ["192.168.1.0/24"], + }, + }, + }, +} +``` + +這只適用於沒有請求 +範圍的全新 `role: node` 配對請求。Operator、瀏覽器、Control UI 與 WebChat 用戶端仍需要手動 +核准。角色、範圍、中繼資料與公開金鑰變更仍需要手動 +核准。 + +### Node 配對狀態儲存 + +存放於 `~/.openclaw/devices/`: + +- `pending.json`(短效;待處理請求會過期) +- `paired.json`(已配對裝置 + 權杖) + +### 注意事項 + +- 舊版 `node.pair.*` API(CLI:`openclaw nodes pending|approve|reject|remove|rename`)是 + 獨立、由 Gateway 擁有的配對儲存區。WS Node 仍需要裝置配對。 +- 配對記錄是已核准角色的持久真實來源。作用中的 + 裝置權杖仍受限於該已核准角色集合;位於已核准角色之外的零散權杖項目 + 不會建立新的存取權。 + +## 相關文件 + +- 安全性模型 + 提示注入:[安全性](/zh-TW/gateway/security) +- 安全更新(執行 doctor):[更新](/zh-TW/install/updating) +- 頻道設定: + - Telegram:[Telegram](/zh-TW/channels/telegram) + - WhatsApp:[WhatsApp](/zh-TW/channels/whatsapp) + - Signal:[Signal](/zh-TW/channels/signal) + - BlueBubbles(iMessage):[BlueBubbles](/zh-TW/channels/bluebubbles) + - iMessage(舊版):[iMessage](/zh-TW/channels/imessage) + - Discord:[Discord](/zh-TW/channels/discord) + - Slack:[Slack](/zh-TW/channels/slack) diff --git a/docs/zh-TW/channels/qa-channel.md b/docs/zh-TW/channels/qa-channel.md new file mode 100644 index 000000000..399e6347c --- /dev/null +++ b/docs/zh-TW/channels/qa-channel.md @@ -0,0 +1,93 @@ +--- +read_when: + - 您正在將合成 QA 傳輸接入本機或 CI 測試執行 + - 你需要隨附的 qa-channel 設定介面 + - 你正在反覆改進端對端品質保證自動化 +summary: 用於決定性 OpenClaw QA 情境的合成 Slack 級頻道 Plugin +title: QA 頻道 +x-i18n: + generated_at: "2026-04-30T02:48:54Z" + model: gpt-5.5 + provider: openai + source_hash: e1de1f52da1a14c845cf2a536ddc6f36ab52ed6364f68d9ece32ce272e2a2f96 + source_path: channels/qa-channel.md + workflow: 16 +--- + +`qa-channel` 是一個隨附的合成訊息傳輸,用於自動化 OpenClaw QA。它不是生產用通道,而是用來演練實際傳輸所使用的相同通道 Plugin 邊界,同時保持狀態具備確定性且可完整檢查。 + +## 功能 + +- Slack 類型目標語法: + - `dm:` + - `channel:` + - `thread:/` +- 以 HTTP 支援的合成匯流排,用於注入傳入訊息、擷取傳出逐字稿、建立討論串、反應、編輯、刪除,以及搜尋/讀取動作。 +- 主機端自我檢查執行器,會將 Markdown 報告寫入 `.artifacts/qa-e2e/`。 + +## 設定 + +```json +{ + "channels": { + "qa-channel": { + "baseUrl": "http://127.0.0.1:43123", + "botUserId": "openclaw", + "botDisplayName": "OpenClaw QA", + "allowFrom": ["*"], + "pollTimeoutMs": 1000 + } + } +} +``` + +帳號鍵: + +- `enabled` — 此帳號的主開關。 +- `name` — 選用的顯示標籤。 +- `baseUrl` — 合成匯流排 URL。 +- `botUserId` — 目標語法中使用的 Matrix 樣式機器人使用者 ID。 +- `botDisplayName` — 傳出訊息的顯示名稱。 +- `pollTimeoutMs` — 長輪詢等待時間窗。介於 100 到 30000 之間的整數。 +- `allowFrom` — 寄件者允許清單(使用者 ID 或 `"*"`)。 +- `defaultTo` — 未提供目標時的後備目標。 +- `actions.messages` / `actions.reactions` / `actions.search` / `actions.threads` — 依動作設定的工具門控。 + +頂層的多帳號鍵: + +- `accounts` — 以帳號 ID 作為鍵的具名逐帳號覆寫記錄。 +- `defaultAccount` — 設定多個帳號時偏好的帳號 ID。 + +## 執行器 + +主機端自我檢查(在 `.artifacts/qa-e2e/` 下寫入 Markdown 報告): + +```bash +pnpm qa:e2e +``` + +這會透過 `qa-lab` 路由,啟動儲存庫內的 QA 匯流排,啟動隨附的 `qa-channel` 執行階段切片,並執行具確定性的自我檢查。 + +完整的儲存庫支援情境套件: + +```bash +pnpm openclaw qa suite +``` + +針對 QA Gateway lane 平行執行情境。情境、設定檔與供應商模式請參閱 [QA 概觀](/zh-TW/concepts/qa-e2e-automation)。 + +Docker 支援的 QA 站台(Gateway + QA Lab 除錯器 UI 位於同一個堆疊中): + +```bash +pnpm qa:lab:up +``` + +建置 QA 站台,啟動 Docker 支援的 Gateway + QA Lab 堆疊,並列印 QA Lab URL。接著你可以挑選情境、選擇模型 lane、啟動個別執行,並即時觀看結果。QA Lab 除錯器與已出貨的 Control UI bundle 是分開的。 + +## 相關 + +- [QA 概觀](/zh-TW/concepts/qa-e2e-automation) — 整體堆疊、傳輸配接器、情境撰寫 +- [Matrix QA](/zh-TW/concepts/qa-matrix) — 驅動真實通道的範例即時傳輸執行器 +- [配對](/zh-TW/channels/pairing) +- [群組](/zh-TW/channels/groups) +- [通道概觀](/zh-TW/channels) diff --git a/docs/zh-TW/channels/qqbot.md b/docs/zh-TW/channels/qqbot.md new file mode 100644 index 000000000..d63b1c788 --- /dev/null +++ b/docs/zh-TW/channels/qqbot.md @@ -0,0 +1,276 @@ +--- +read_when: + - 您想要將 OpenClaw 連接到 QQ + - 你需要設定 QQ Bot 憑證 + - 你想要 QQ Bot 群組或私聊支援 +summary: QQ Bot 設定、組態與使用方式 +title: QQ 機器人 +x-i18n: + generated_at: "2026-04-30T02:49:04Z" + model: gpt-5.5 + provider: openai + source_hash: aefece6b05bb16d5c4f588bf7af4fd710b5f98aab0dbed8221490c46bf3f379c + source_path: channels/qqbot.md + workflow: 16 +--- + +QQ Bot 透過官方 QQ Bot API(WebSocket gateway)連接到 OpenClaw。此 Plugin 支援 C2C 私聊、群組 @訊息,以及頻道訊息,並支援豐富媒體(圖片、語音、影片、檔案)。 + +狀態:內建 Plugin。支援私訊、群組聊天、頻道和媒體。不支援反應和討論串。 + +## 內建 Plugin + +目前的 OpenClaw 版本內建 QQ Bot,因此一般封裝建置不需要額外執行 `openclaw plugins install` 步驟。 + +## 設定 + +1. 前往 [QQ Open Platform](https://q.qq.com/),並用手機 QQ 掃描 QR code 以註冊 / 登入。 +2. 點擊 **Create Bot** 建立新的 QQ bot。 +3. 在 bot 的設定頁面找到 **AppID** 和 **AppSecret**,並複製它們。 + +> AppSecret 不會以明文儲存,如果你未儲存就離開頁面, +> 就必須重新產生新的 AppSecret。 + +4. 加入 channel: + +```bash +openclaw channels add --channel qqbot --token "AppID:AppSecret" +``` + +5. 重新啟動 Gateway。 + +互動式設定路徑: + +```bash +openclaw channels add +openclaw configure --section channels +``` + +## 設定 + +最小設定: + +```json5 +{ + channels: { + qqbot: { + enabled: true, + appId: "YOUR_APP_ID", + clientSecret: "YOUR_APP_SECRET", + }, + }, +} +``` + +預設帳號環境變數: + +- `QQBOT_APP_ID` +- `QQBOT_CLIENT_SECRET` + +以檔案提供的 AppSecret: + +```json5 +{ + channels: { + qqbot: { + enabled: true, + appId: "YOUR_APP_ID", + clientSecretFile: "/path/to/qqbot-secret.txt", + }, + }, +} +``` + +注意事項: + +- 環境變數 fallback 只適用於預設 QQ Bot 帳號。 +- `openclaw channels add --channel qqbot --token-file ...` 只提供 + AppSecret;AppID 必須已在 config 或 `QQBOT_APP_ID` 中設定。 +- `clientSecret` 也接受 SecretRef 輸入,而不只是明文字串。 + +### 多帳號設定 + +在單一 OpenClaw 實例下執行多個 QQ bot: + +```json5 +{ + channels: { + qqbot: { + enabled: true, + appId: "111111111", + clientSecret: "secret-of-bot-1", + accounts: { + bot2: { + enabled: true, + appId: "222222222", + clientSecret: "secret-of-bot-2", + }, + }, + }, + }, +} +``` + +每個帳號會啟動自己的 WebSocket 連線,並維護獨立的 token 快取(以 `appId` 隔離)。 + +透過 CLI 加入第二個 bot: + +```bash +openclaw channels add --channel qqbot --account bot2 --token "222222222:secret-of-bot-2" +``` + +### 群組聊天 + +QQ Bot 群組聊天支援使用 QQ 群組 OpenID,而不是顯示名稱。將 bot 加入群組,然後提及它,或設定群組讓它不需提及即可執行。 + +```json5 +{ + channels: { + qqbot: { + groupPolicy: "allowlist", + groupAllowFrom: ["member_openid"], + groups: { + "*": { + requireMention: true, + historyLimit: 50, + toolPolicy: "restricted", + }, + GROUP_OPENID: { + name: "Release room", + requireMention: false, + ignoreOtherMentions: true, + historyLimit: 20, + prompt: "Keep replies short and operational.", + }, + }, + }, + }, +} +``` + +`groups["*"]` 會設定每個群組的預設值,而具體的 +`groups.GROUP_OPENID` 項目會覆寫單一群組的這些預設值。群組設定包含: + +- `requireMention`:bot 回覆前需要 @mention。預設值:`true`。 +- `ignoreOtherMentions`:丟棄提及其他人但未提及 bot 的訊息。 +- `historyLimit`:保留最近未提及 bot 的群組訊息,作為下一次被提及回合的情境。設為 `0` 可停用。 +- `toolPolicy`:群組範圍工具的 `full`、`restricted` 或 `none`。 +- `name`:用於日誌和群組情境的友善標籤。 +- `prompt`:附加到 agent 情境的個別群組行為提示。 + +啟用模式為 `mention` 和 `always`。`requireMention: true` 對應到 +`mention`;`requireMention: false` 對應到 `always`。若存在工作階段層級的啟用覆寫,則其優先於 config。 + +入站佇列以 peer 為單位。群組 peer 具有較大的佇列上限,佇列已滿時會讓人類訊息排在 bot 撰寫的聊天內容之前,並將一般群組訊息的突發串流合併成一個具署名的回合。斜線命令仍會逐一執行。 + +### 語音(STT / TTS) + +STT 和 TTS 支援具有優先 fallback 的雙層設定: + +| 設定 | Plugin 專屬 | Framework fallback | +| ------- | -------------------------------------------------------- | ----------------------------- | +| STT | `channels.qqbot.stt` | `tools.media.audio.models[0]` | +| TTS | `channels.qqbot.tts`, `channels.qqbot.accounts..tts` | `messages.tts` | + +```json5 +{ + channels: { + qqbot: { + stt: { + provider: "your-provider", + model: "your-stt-model", + }, + tts: { + provider: "your-provider", + model: "your-tts-model", + voice: "your-voice", + }, + accounts: { + qq-main: { + tts: { + providers: { + openai: { voice: "shimmer" }, + }, + }, + }, + }, + }, + }, +} +``` + +在任一項上設定 `enabled: false` 可停用。 +帳號層級的 TTS 覆寫使用與 `messages.tts` 相同的形狀,並會深度合併到 channel/global TTS config 之上。 + +入站 QQ 語音附件會以音訊媒體中繼資料的形式公開給 agent,同時讓原始語音檔案不進入通用的 `MediaPaths`。當 TTS 已設定時,`[[audio_as_voice]]` 純文字回覆會合成 TTS 並傳送原生 QQ 語音訊息。 + +出站音訊上傳 / 轉碼行為也可使用 +`channels.qqbot.audioFormatPolicy` 調整: + +- `sttDirectFormats` +- `uploadDirectFormats` +- `transcodeEnabled` + +## 目標格式 + +| 格式 | 說明 | +| -------------------------- | ------------------ | +| `qqbot:c2c:OPENID` | 私聊(C2C) | +| `qqbot:group:GROUP_OPENID` | 群組聊天 | +| `qqbot:channel:CHANNEL_ID` | 頻道 | + +> 每個 bot 都有自己的使用者 OpenID 集合。Bot A 收到的 OpenID **不能** +> 用來透過 Bot B 傳送訊息。 + +## 斜線命令 + +在 AI 佇列前攔截的內建命令: + +| 命令 | 說明 | +| -------------- | -------------------------------------------------------------------------------------------------------- | +| `/bot-ping` | 延遲測試 | +| `/bot-version` | 顯示 OpenClaw framework 版本 | +| `/bot-help` | 列出所有命令 | +| `/bot-upgrade` | 顯示 QQBot 升級指南連結 | +| `/bot-logs` | 將最近的 gateway 日誌匯出為檔案 | +| `/bot-approve` | 透過原生流程核准待處理的 QQ Bot 動作(例如確認 C2C 或群組上傳)。 | + +在任何命令後加上 `?` 可查看用法說明(例如 `/bot-upgrade ?`)。 + +## 引擎架構 + +QQ Bot 以 Plugin 內自包含引擎的形式提供: + +- 每個帳號都擁有以 `appId` 作為索引鍵的隔離資源堆疊(WebSocket 連線、API client、token 快取、媒體儲存根目錄)。帳號絕不共享入站 / 出站狀態。 +- 多帳號 logger 會以擁有帳號標記日誌行,因此在同一個 gateway 下執行多個 bot 時,診斷資訊仍可分開檢視。 +- 入站、出站和 gateway bridge 路徑共用 `~/.openclaw/media` 下的單一媒體 payload 根目錄,因此上傳、下載和轉碼快取會落在同一個受保護目錄下,而不是分散在各子系統樹狀結構中。 +- 豐富媒體傳送會透過單一 `sendMedia` 路徑送往 C2C 和群組目標。超過大檔案閾值的本機檔案和緩衝區會使用 QQ 的分塊上傳 endpoint,而較小的 payload 則使用一次性媒體 API。 +- 認證可作為標準 OpenClaw 認證快照的一部分備份和還原;引擎會在還原時重新附加每個帳號的資源堆疊,不需要新的 QR-code 配對。 + +## QR-code onboarding + +除了手動貼上 `AppID:AppSecret`,引擎也支援用於將 QQ Bot 連結到 OpenClaw 的 QR-code onboarding 流程: + +1. 執行 QQ Bot 設定路徑(例如 `openclaw channels add --channel qqbot`),並在提示時選擇 QR-code 流程。 +2. 使用綁定目標 QQ Bot 的手機 app 掃描產生的 QR code。 +3. 在手機上核准配對。OpenClaw 會將回傳的認證保存到正確帳號範圍下的 `credentials/`。 + +由 bot 本身產生的核准提示(例如 QQ Bot API 公開的「允許此動作?」流程)會呈現為原生 OpenClaw 提示,你可以用 `/bot-approve` 接受,而不必透過原始 QQ client 回覆。 + +## 疑難排解 + +- **Bot 回覆「gone to Mars」:** 認證未設定或 Gateway 未啟動。 +- **沒有入站訊息:** 驗證 `appId` 和 `clientSecret` 是否正確,且 + bot 已在 QQ Open Platform 上啟用。 +- **重複自我回覆:** OpenClaw 會將 QQ 出站 ref index 記錄為 + bot 撰寫,並忽略目前 `msgIdx` 符合同一 bot 帳號的入站事件。這會防止平台回音迴圈,同時仍允許使用者引用或回覆先前的 bot 訊息。 +- **使用 `--token-file` 設定後仍顯示未設定:** `--token-file` 只會設定 + AppSecret。你仍需要在 config 或 `QQBOT_APP_ID` 中設定 `appId`。 +- **主動訊息未送達:** 如果使用者近期未互動,QQ 可能會攔截 bot 主動發起的訊息。 +- **語音未轉錄:** 確認 STT 已設定,且 provider 可連線。 + +## 相關 + +- [配對](/zh-TW/channels/pairing) +- [群組](/zh-TW/channels/groups) +- [Channel 疑難排解](/zh-TW/channels/troubleshooting) diff --git a/docs/zh-TW/channels/signal.md b/docs/zh-TW/channels/signal.md new file mode 100644 index 000000000..5d733ce97 --- /dev/null +++ b/docs/zh-TW/channels/signal.md @@ -0,0 +1,345 @@ +--- +read_when: + - 設定 Signal 支援 + - Signal 傳送/接收偵錯 +summary: 透過 signal-cli (JSON-RPC + SSE) 支援 Signal、設定路徑與號碼模型 +title: Signal +x-i18n: + generated_at: "2026-04-30T02:48:59Z" + model: gpt-5.5 + provider: openai + source_hash: d450454550a86cbf0e2b7231bb149f78275a756517db1f20d7a07e3d298febee + source_path: channels/signal.md + workflow: 16 +--- + +狀態:外部 CLI 整合。Gateway 透過 HTTP JSON-RPC + SSE 與 `signal-cli` 通訊。 + +## 先決條件 + +- 你的伺服器上已安裝 OpenClaw(以下 Linux 流程已在 Ubuntu 24 測試)。 +- Gateway 執行所在主機上可使用 `signal-cli`。 +- 可接收一則驗證簡訊的電話號碼(用於簡訊註冊路徑)。 +- 註冊期間可透過瀏覽器存取 Signal captcha(`signalcaptchas.org`)。 + +## 快速設定(初學者) + +1. 為機器人使用**獨立的 Signal 號碼**(建議)。 +2. 安裝 `signal-cli`(如果使用 JVM 建置版本,需安裝 Java)。 +3. 選擇一種設定路徑: + - **路徑 A(QR 連結):** `signal-cli link -n "OpenClaw"`,然後使用 Signal 掃描。 + - **路徑 B(簡訊註冊):** 使用 captcha + 簡訊驗證註冊專用號碼。 +4. 設定 OpenClaw 並重新啟動 Gateway。 +5. 傳送第一則私訊並核准配對(`openclaw pairing approve signal `)。 + +最小設定: + +```json5 +{ + channels: { + signal: { + enabled: true, + account: "+15551234567", + cliPath: "signal-cli", + dmPolicy: "pairing", + allowFrom: ["+15557654321"], + }, + }, +} +``` + +欄位參考: + +| 欄位 | 說明 | +| ----------- | ------------------------------------------------- | +| `account` | E.164 格式的機器人電話號碼(`+15551234567`) | +| `cliPath` | `signal-cli` 的路徑(若在 `PATH` 上則為 `signal-cli`) | +| `dmPolicy` | 私訊存取政策(建議使用 `pairing`) | +| `allowFrom` | 允許傳送私訊的電話號碼或 `uuid:` 值 | + +## 它是什麼 + +- 透過 `signal-cli` 的 Signal 頻道(不是內嵌 libsignal)。 +- 決定性路由:回覆一律回到 Signal。 +- 私訊共用 agent 的主要工作階段;群組則隔離(`agent::signal:group:`)。 + +## 設定寫入 + +預設情況下,Signal 允許寫入由 `/config set|unset` 觸發的設定更新(需要 `commands.config: true`)。 + +使用以下設定停用: + +```json5 +{ + channels: { signal: { configWrites: false } }, +} +``` + +## 號碼模型(重要) + +- Gateway 會連線到一個 **Signal 裝置**(`signal-cli` 帳號)。 +- 如果你在**自己的個人 Signal 帳號**上執行機器人,它會忽略你自己的訊息(迴圈保護)。 +- 若要「我傳訊息給機器人,然後它回覆」,請使用**獨立的機器人號碼**。 + +## 設定路徑 A:連結現有 Signal 帳號(QR) + +1. 安裝 `signal-cli`(JVM 或原生建置版本)。 +2. 連結機器人帳號: + - `signal-cli link -n "OpenClaw"`,然後在 Signal 中掃描 QR。 +3. 設定 Signal 並啟動 Gateway。 + +範例: + +```json5 +{ + channels: { + signal: { + enabled: true, + account: "+15551234567", + cliPath: "signal-cli", + dmPolicy: "pairing", + allowFrom: ["+15557654321"], + }, + }, +} +``` + +多帳號支援:使用 `channels.signal.accounts` 搭配每個帳號的設定與選用的 `name`。共享模式請參閱 [`gateway/configuration`](/zh-TW/gateway/config-channels#multi-account-all-channels)。 + +## 設定路徑 B:註冊專用機器人號碼(簡訊,Linux) + +當你想使用專用機器人號碼,而不是連結現有 Signal 應用程式帳號時,請使用此方式。 + +1. 取得可接收簡訊的號碼(或固定電話的語音驗證)。 + - 使用專用機器人號碼,以避免帳號/工作階段衝突。 +2. 在 Gateway 主機上安裝 `signal-cli`: + +```bash +VERSION=$(curl -Ls -o /dev/null -w %{url_effective} https://github.com/AsamK/signal-cli/releases/latest | sed -e 's/^.*\/v//') +curl -L -O "https://github.com/AsamK/signal-cli/releases/download/v${VERSION}/signal-cli-${VERSION}-Linux-native.tar.gz" +sudo tar xf "signal-cli-${VERSION}-Linux-native.tar.gz" -C /opt +sudo ln -sf /opt/signal-cli /usr/local/bin/ +signal-cli --version +``` + +如果你使用 JVM 建置版本(`signal-cli-${VERSION}.tar.gz`),請先安裝 JRE 25+。 +請保持 `signal-cli` 更新;上游說明指出,舊版本可能會因 Signal 伺服器 API 變更而故障。 + +3. 註冊並驗證號碼: + +```bash +signal-cli -a + register +``` + +如果需要 captcha: + +1. 開啟 `https://signalcaptchas.org/registration/generate.html`。 +2. 完成 captcha,從「Open Signal」複製 `signalcaptcha://...` 連結目標。 +3. 盡可能從與瀏覽器工作階段相同的外部 IP 執行。 +4. 立即再次執行註冊(captcha token 很快會過期): + +```bash +signal-cli -a + register --captcha '' +signal-cli -a + verify +``` + +4. 設定 OpenClaw、重新啟動 Gateway、驗證頻道: + +```bash +# If you run the gateway as a user systemd service: +systemctl --user restart openclaw-gateway.service + +# Then verify: +openclaw doctor +openclaw channels status --probe +``` + +5. 配對你的私訊傳送者: + - 傳送任何訊息到機器人號碼。 + - 在伺服器上核准代碼:`openclaw pairing approve signal `。 + - 將機器人號碼儲存為手機聯絡人,以避免顯示「未知聯絡人」。 + + +使用 `signal-cli` 註冊電話號碼帳號,可能會讓該號碼的主要 Signal 應用程式工作階段失效。建議使用專用機器人號碼,或者如果你需要保留現有手機應用程式設定,請使用 QR 連結模式。 + + +上游參考: + +- `signal-cli` README:`https://github.com/AsamK/signal-cli` +- Captcha 流程:`https://github.com/AsamK/signal-cli/wiki/Registration-with-captcha` +- 連結流程:`https://github.com/AsamK/signal-cli/wiki/Linking-other-devices-(Provisioning)` + +## 外部 daemon 模式(httpUrl) + +如果你想自行管理 `signal-cli`(JVM 冷啟動較慢、容器初始化,或共用 CPU),請另外執行 daemon,並讓 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 私訊的預設 token 交換方式。詳情:[配對](/zh-TW/channels/pairing) +- 僅 UUID 的傳送者(來自 `sourceUuid`)會以 `uuid:` 儲存在 `channels.signal.allowFrom`。 + +群組: + +- `channels.signal.groupPolicy = open | allowlist | disabled`。 +- 當設定為 `allowlist` 時,`channels.signal.groupAllowFrom` 控制誰可以在群組中觸發。 +- `channels.signal.groups["" | "*"]` 可以使用 `requireMention`、`tools` 和 `toolsBySender` 覆寫群組行為。 +- 在多帳號設定中,使用 `channels.signal.accounts..groups` 設定每個帳號的覆寫。 +- 執行階段注意事項:如果完全缺少 `channels.signal`,執行階段會針對群組檢查回退到 `groupPolicy="allowlist"`(即使已設定 `channels.defaults.groupPolicy`)。 + +## 運作方式(行為) + +- `signal-cli` 以 daemon 形式執行;Gateway 透過 SSE 讀取事件。 +- 傳入訊息會正規化為共享頻道 envelope。 +- 回覆一律路由回相同號碼或群組。 + +## 媒體 + 限制 + +- 傳出文字會切分到 `channels.signal.textChunkLimit`(預設 4000)。 +- 選用換行切分:設定 `channels.signal.chunkMode="newline"`,先依空白行(段落邊界)切分,再依長度切分。 +- 支援附件(從 `signal-cli` 擷取 base64)。 +- 當缺少 `contentType` 時,語音備忘附件會使用 `signal-cli` 檔名作為 MIME 後備,因此音訊轉錄仍可分類 AAC 語音備忘。 +- 預設媒體上限:`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 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` 會停用 agent 反應(訊息工具 `react` 會出錯)。 + - `minimal`/`extensive` 會啟用 agent 反應並設定指引層級。 +- 每個帳號的覆寫:`channels.signal.accounts..actions.reactions`、`channels.signal.accounts..reactionLevel`。 + +## 傳送目標(CLI/Cron) + +- 私訊:`signal:+15551234567`(或純 E.164)。 +- UUID 私訊:`uuid:`(或裸 UUID)。 +- 群組:`signal:group:`。 +- 使用者名稱:`username:`(如果你的 Signal 帳號支援)。 + +## 疑難排解 + +先執行此階梯: + +```bash +openclaw status +openclaw gateway status +openclaw logs --follow +openclaw doctor +openclaw channels status --probe +``` + +必要時再確認私訊配對狀態: + +```bash +openclaw pairing list signal +``` + +常見失敗: + +- Daemon 可連線但沒有回覆:確認帳號/daemon 設定(`httpUrl`、`account`)與接收模式。 +- 私訊被忽略:傳送者正在等待配對核准。 +- 群組訊息被忽略:群組傳送者/提及閘控阻擋了傳送。 +- 編輯後出現設定驗證錯誤:執行 `openclaw doctor --fix`。 +- 診斷中缺少 Signal:確認 `channels.signal.enabled: true`。 + +額外檢查: + +```bash +openclaw pairing list signal +pgrep -af signal-cli +grep -i "signal" "/tmp/openclaw/openclaw-$(date +%Y-%m-%d).log" | tail -20 +``` + +分流流程:[/channels/troubleshooting](/zh-TW/channels/troubleshooting)。 + +## 安全性注意事項 + +- `signal-cli` 會將帳號金鑰儲存在本機(通常是 `~/.local/share/signal-cli/data/`)。 +- 伺服器遷移或重建前,請備份 Signal 帳號狀態。 +- 除非你明確想要更廣泛的私訊存取,否則請保留 `channels.signal.dmPolicy: "pairing"`。 +- 簡訊驗證只在註冊或復原流程需要,但失去對號碼/帳號的控制可能會讓重新註冊變得複雜。 + +## 設定參考(Signal) + +完整設定:[設定](/zh-TW/gateway/configuration) + +提供者選項: + +- `channels.signal.enabled`: 啟用/停用頻道啟動。 +- `channels.signal.account`: bot 帳號的 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`: DM 允許清單(E.164 或 `uuid:`)。`open` 需要 `"*"`。Signal 沒有使用者名稱;請使用電話/UUID ID。 +- `channels.signal.groupPolicy`: `open | allowlist | disabled`(預設:allowlist)。 +- `channels.signal.groupAllowFrom`: 群組傳送者允許清單。 +- `channels.signal.groups`: 依 Signal 群組 ID(或 `"*"`)設定的個別群組覆寫。支援的欄位:`requireMention`、`tools`、`toolsBySender`。 +- `channels.signal.accounts..groups`: 多帳號設定中,`channels.signal.groups` 的個別帳號版本。 +- `channels.signal.historyLimit`: 要納入上下文的群組訊息上限(0 表示停用)。 +- `channels.signal.dmHistoryLimit`: 以使用者回合數計算的 DM 歷史記錄限制。個別使用者覆寫:`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`。 + +## 相關 + +- [頻道總覽](/zh-TW/channels) — 所有支援的頻道 +- [配對](/zh-TW/channels/pairing) — DM 驗證與配對流程 +- [群組](/zh-TW/channels/groups) — 群組聊天行為與提及閘控 +- [頻道路由](/zh-TW/channels/channel-routing) — 訊息的工作階段路由 +- [安全性](/zh-TW/gateway/security) — 存取模型與強化 diff --git a/docs/zh-TW/channels/slack.md b/docs/zh-TW/channels/slack.md new file mode 100644 index 000000000..4244a2388 --- /dev/null +++ b/docs/zh-TW/channels/slack.md @@ -0,0 +1,1040 @@ +--- +read_when: + - 設定 Slack 或偵錯 Slack socket/HTTP 模式 +summary: Slack 設定與執行階段行為(Socket 模式 + HTTP 請求網址) +title: Slack +x-i18n: + generated_at: "2026-04-30T02:49:07Z" + model: gpt-5.5 + provider: openai + source_hash: 08024bd947ddeb00a1ab3aaa3864cf31817303bbc0523902acdc539fc662e127 + source_path: channels/slack.md + workflow: 16 +--- + +可透過 Slack app 整合用於 DM 和頻道,並已達生產就緒。預設模式是 Socket Mode;也支援 HTTP Request URLs。 + + + + Slack DM 預設使用配對模式。 + + + 原生命令行為與命令目錄。 + + + 跨頻道診斷與修復手冊。 + + + +## 快速設定 + + + + + + 在 Slack app 設定中按下 **[Create New App](https://api.slack.com/apps/new)** 按鈕: + + - 選擇 **from a manifest**,並為你的 app 選取工作區 + - 貼上下面的[範例 manifest](#manifest-and-scope-checklist),並繼續建立 + - 產生具備 `connections:write` 的 **App-Level Token** (`xapp-...`) + - 安裝 app,並複製顯示的 **Bot Token** (`xoxb-...`) + + + + + + 建議的 SecretRef 設定: + +```bash +export SLACK_APP_TOKEN=xapp-... +export SLACK_BOT_TOKEN=xoxb-... +cat > slack.socket.patch.json5 <<'JSON5' +{ + channels: { + slack: { + enabled: true, + mode: "socket", + appToken: { source: "env", provider: "default", id: "SLACK_APP_TOKEN" }, + botToken: { source: "env", provider: "default", id: "SLACK_BOT_TOKEN" }, + }, + }, +} +JSON5 +openclaw config patch --file ./slack.socket.patch.json5 --dry-run +openclaw config patch --file ./slack.socket.patch.json5 +``` + + env 後備方式(僅限預設帳戶): + +```bash +SLACK_APP_TOKEN=xapp-... +SLACK_BOT_TOKEN=xoxb-... +``` + + + + + +```bash +openclaw gateway +``` + + + + + + + + + + 在 Slack app 設定中按下 **[Create New App](https://api.slack.com/apps/new)** 按鈕: + + - 選擇 **from a manifest**,並為你的 app 選取工作區 + - 貼上[範例 manifest](#manifest-and-scope-checklist),並在建立前更新 URL + - 儲存用於要求驗證的 **Signing Secret** + - 安裝 app,並複製顯示的 **Bot Token** (`xoxb-...`) + + + + + + 建議的 SecretRef 設定: + +```bash +export SLACK_BOT_TOKEN=xoxb-... +export SLACK_SIGNING_SECRET=... +cat > slack.http.patch.json5 <<'JSON5' +{ + channels: { + slack: { + enabled: true, + mode: "http", + botToken: { source: "env", provider: "default", id: "SLACK_BOT_TOKEN" }, + signingSecret: { source: "env", provider: "default", id: "SLACK_SIGNING_SECRET" }, + webhookPath: "/slack/events", + }, + }, +} +JSON5 +openclaw config patch --file ./slack.http.patch.json5 --dry-run +openclaw config patch --file ./slack.http.patch.json5 +``` + + + 多帳戶 HTTP 請使用唯一的 Webhook 路徑 + + 為每個帳戶指定不同的 `webhookPath`(預設為 `/slack/events`),避免註冊互相衝突。 + + + + + + +```bash +openclaw gateway +``` + + + + + + + +## Socket Mode 傳輸調整 + +OpenClaw 預設會將 Socket Mode 的 Slack SDK 用戶端 pong 逾時設為 15 秒。只有在需要針對工作區或主機進行特定調整時,才覆寫傳輸設定: + +```json5 +{ + channels: { + slack: { + mode: "socket", + socketMode: { + clientPingTimeout: 20000, + serverPingTimeout: 30000, + pingPongLoggingEnabled: false, + }, + }, + }, +} +``` + +只有在 Socket Mode 工作區記錄 Slack websocket pong/server-ping 逾時,或在已知事件迴圈飢餓的主機上執行時,才使用此設定。`clientPingTimeout` 是 SDK 傳送用戶端 ping 後等待 pong 的時間;`serverPingTimeout` 是等待 Slack 伺服器 ping 的時間。App 訊息與事件仍是應用程式狀態,不是傳輸活性訊號。 + +## Manifest 與 scope 檢查清單 + +Socket Mode 和 HTTP Request URLs 使用相同的基礎 Slack app manifest。只有 `settings` 區塊(以及 slash command 的 `url`)不同。 + +基礎 manifest(Socket Mode 預設): + +```json +{ + "display_information": { + "name": "OpenClaw", + "description": "Slack connector for OpenClaw" + }, + "features": { + "bot_user": { "display_name": "OpenClaw", "always_online": true }, + "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": [ + "app_mentions:read", + "assistant:write", + "channels:history", + "channels:read", + "chat:write", + "commands", + "emoji:read", + "files:read", + "files:write", + "groups:history", + "groups:read", + "im:history", + "im:read", + "im:write", + "mpim:history", + "mpim:read", + "mpim:write", + "pins:read", + "pins:write", + "reactions:read", + "reactions:write", + "users:read" + ] + } + }, + "settings": { + "socket_mode_enabled": true, + "event_subscriptions": { + "bot_events": [ + "app_mention", + "channel_rename", + "member_joined_channel", + "member_left_channel", + "message.channels", + "message.groups", + "message.im", + "message.mpim", + "pin_added", + "pin_removed", + "reaction_added", + "reaction_removed" + ] + } + } +} +``` + +對於 **HTTP Request URLs 模式**,請將 `settings` 替換為 HTTP 版本,並為每個 slash command 加上 `url`。需要公開 URL: + +```json +{ + "features": { + "slash_commands": [ + { + "command": "/openclaw", + "description": "Send a message to OpenClaw", + "should_escape": false, + "url": "https://gateway-host.example.com/slack/events" + } + ] + }, + "settings": { + "event_subscriptions": { + "request_url": "https://gateway-host.example.com/slack/events", + "bot_events": [ + /* same as Socket Mode */ + ] + }, + "interactivity": { + "is_enabled": true, + "request_url": "https://gateway-host.example.com/slack/events", + "message_menu_options_url": "https://gateway-host.example.com/slack/events" + } + } +} +``` + +### 其他 manifest 設定 + +呈現擴充上述預設值的不同功能。 + + + + + 可使用多個[原生 slash commands](#commands-and-slash-behavior),取代單一已設定命令,並有以下細節: + + - 使用 `/agentstatus` 而不是 `/status`,因為 `/status` 命令已保留。 + - 一次最多只能提供 25 個 slash commands。 + + 將現有的 `features.slash_commands` 區段替換為[可用命令](/zh-TW/tools/slash-commands#command-list)的子集: + + + + +```json + "slash_commands": [ + { + "command": "/new", + "description": "Start a new session", + "usage_hint": "[model]" + }, + { + "command": "/reset", + "description": "Reset the current session" + }, + { + "command": "/compact", + "description": "Compact the session context", + "usage_hint": "[instructions]" + }, + { + "command": "/stop", + "description": "Stop the current run" + }, + { + "command": "/session", + "description": "Manage thread-binding expiry", + "usage_hint": "idle or max-age " + }, + { + "command": "/think", + "description": "Set the thinking level", + "usage_hint": "" + }, + { + "command": "/verbose", + "description": "Toggle verbose output", + "usage_hint": "on|off|full" + }, + { + "command": "/fast", + "description": "Show or set fast mode", + "usage_hint": "[status|on|off]" + }, + { + "command": "/reasoning", + "description": "Toggle reasoning visibility", + "usage_hint": "[on|off|stream]" + }, + { + "command": "/elevated", + "description": "Toggle elevated mode", + "usage_hint": "[on|off|ask|full]" + }, + { + "command": "/exec", + "description": "Show or set exec defaults", + "usage_hint": "host= security= ask= node=" + }, + { + "command": "/model", + "description": "Show or set the model", + "usage_hint": "[name|#|status]" + }, + { + "command": "/models", + "description": "List providers/models", + "usage_hint": "[provider] [page] [limit=|size=|all]" + }, + { + "command": "/help", + "description": "Show the short help summary" + }, + { + "command": "/commands", + "description": "Show the generated command catalog" + }, + { + "command": "/tools", + "description": "Show what the current agent can use right now", + "usage_hint": "[compact|verbose]" + }, + { + "command": "/agentstatus", + "description": "Show runtime status, including provider usage/quota when available" + }, + { + "command": "/tasks", + "description": "List active/recent background tasks for the current session" + }, + { + "command": "/context", + "description": "Explain how context is assembled", + "usage_hint": "[list|detail|json]" + }, + { + "command": "/whoami", + "description": "Show your sender identity" + }, + { + "command": "/skill", + "description": "Run a skill by name", + "usage_hint": " [input]" + }, + { + "command": "/btw", + "description": "Ask a side question without changing session context", + "usage_hint": "" + }, + { + "command": "/usage", + "description": "Control the usage footer or show cost summary", + "usage_hint": "off|tokens|full|cost" + } + ] +``` + + + + 使用與上方 Socket Mode 相同的 `slash_commands` 清單,並在每個項目加上 `"url": "https://gateway-host.example.com/slack/events"`。範例: + +```json + "slash_commands": [ + { + "command": "/new", + "description": "Start a new session", + "usage_hint": "[model]", + "url": "https://gateway-host.example.com/slack/events" + }, + { + "command": "/help", + "description": "Show the short help summary", + "url": "https://gateway-host.example.com/slack/events" + } + // ...repeat for every command with the same `url` value + ] +``` + + + + + + + 如果你希望外送訊息使用作用中代理的身分(自訂使用者名稱與圖示),而不是預設 Slack app 身分,請新增 `chat:write.customize` bot scope。 + + 如果使用 emoji 圖示,Slack 會預期採用 `:emoji_name:` 語法。 + + + + 如果你設定 `channels.slack.userToken`,典型的讀取 scope 包括: + + - `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`(如果你依賴 Slack 搜尋讀取) + + + + +## Token 模型 + +- Socket Mode 需要 `botToken` + `appToken`。 +- HTTP 模式需要 `botToken` + `signingSecret`。 +- `botToken`、`appToken`、`signingSecret` 和 `userToken` 接受純文字 + 字串或 SecretRef 物件。 +- 設定權杖會覆寫環境變數備援。 +- `SLACK_BOT_TOKEN` / `SLACK_APP_TOKEN` 環境變數備援只套用於預設帳戶。 +- `userToken` (`xoxp-...`) 只能透過設定提供(沒有環境變數備援),並預設為唯讀行為 (`userTokenReadOnly: true`)。 + +狀態快照行為: + +- Slack 帳戶檢查會追蹤每個憑證的 `*Source` 和 `*Status` + 欄位(`botToken`、`appToken`、`signingSecret`、`userToken`)。 +- 狀態為 `available`、`configured_unavailable` 或 `missing`。 +- `configured_unavailable` 表示帳戶是透過 SecretRef + 或其他非內嵌祕密來源設定,但目前的命令/執行階段路徑 + 無法解析實際值。 +- 在 HTTP 模式中會包含 `signingSecretStatus`;在 Socket Mode 中, + 必要配對是 `botTokenStatus` + `appTokenStatus`。 + + +對於動作/目錄讀取,已設定時可優先使用使用者權杖。對於寫入,仍優先使用機器人權杖;只有在 `userTokenReadOnly: false` 且機器人權杖不可用時,才允許使用使用者權杖寫入。 + + +## 動作與閘門 + +Slack 動作由 `channels.slack.actions.*` 控制。 + +目前 Slack 工具中可用的動作群組: + +| 群組 | 預設值 | +| ---------- | ------- | +| messages | 已啟用 | +| reactions | 已啟用 | +| pins | 已啟用 | +| memberInfo | 已啟用 | +| emojiList | 已啟用 | + +目前 Slack 訊息動作包括 `send`、`upload-file`、`download-file`、`read`、`edit`、`delete`、`pin`、`unpin`、`list-pins`、`member-info` 和 `emoji-list`。`download-file` 接受傳入檔案佔位符中顯示的 Slack 檔案 ID,並針對圖片回傳圖片預覽,或針對其他檔案類型回傳本機檔案中繼資料。 + +## 存取控制與路由 + + + + `channels.slack.dmPolicy` 控制 DM 存取。`channels.slack.allowFrom` 是標準 DM 允許清單。 + + - `pairing`(預設) + - `allowlist` + - `open`(需要 `channels.slack.allowFrom` 包含 `"*"`) + - `disabled` + + DM 旗標: + + - `dm.enabled`(預設為 true) + - `channels.slack.allowFrom` + - `dm.allowFrom`(舊版) + - `dm.groupEnabled`(群組 DM 預設為 false) + - `dm.groupChannels`(選用 MPIM 允許清單) + + 多帳戶優先順序: + + - `channels.slack.accounts.default.allowFrom` 只套用於 `default` 帳戶。 + - 具名帳戶在本身的 `allowFrom` 未設定時,會繼承 `channels.slack.allowFrom`。 + - 具名帳戶不會繼承 `channels.slack.accounts.default.allowFrom`。 + + 為相容性仍會讀取舊版 `channels.slack.dm.policy` 和 `channels.slack.dm.allowFrom`。`openclaw doctor --fix` 會在不變更存取權的情況下,將其遷移到 `dmPolicy` 和 `allowFrom`。 + + DM 中的配對使用 `openclaw pairing approve slack `。 + + + + + `channels.slack.groupPolicy` 控制頻道處理: + + - `open` + - `allowlist` + - `disabled` + + 頻道允許清單位於 `channels.slack.channels` 底下,且**必須使用穩定的 Slack 頻道 ID**(例如 `C12345678`)作為設定鍵。 + + 執行階段注意事項:如果 `channels.slack` 完全缺少(僅使用環境變數設定),執行階段會退回到 `groupPolicy="allowlist"` 並記錄警告(即使已設定 `channels.defaults.groupPolicy`)。 + + 名稱/ID 解析: + + - 頻道允許清單項目和 DM 允許清單項目會在啟動時於權杖存取允許時解析 + - 未解析的頻道名稱項目會保留為已設定狀態,但預設會在路由時忽略 + - 傳入授權與頻道路由預設以 ID 優先;直接使用者名稱/代稱比對需要 `channels.slack.dangerouslyAllowNameMatching: true` + + + 以名稱為基礎的鍵(`#channel-name` 或 `channel-name`)在 `groupPolicy: "allowlist"` 下**不會**相符。頻道查找預設以 ID 優先,因此以名稱為基礎的鍵永遠無法成功路由,該頻道中的所有訊息都會被靜默封鎖。這不同於 `groupPolicy: "open"`,在該模式中路由不需要頻道鍵,因此以名稱為基礎的鍵看起來可用。 + + 一律使用 Slack 頻道 ID 作為鍵。尋找方式:在 Slack 中以右鍵點選頻道 → **複製連結** — ID (`C...`) 會出現在 URL 結尾。 + + 正確: + + ```json5 + { + channels: { + slack: { + groupPolicy: "allowlist", + channels: { + C12345678: { allow: true, requireMention: true }, + }, + }, + }, + } + ``` + + 不正確(在 `groupPolicy: "allowlist"` 下會被靜默封鎖): + + ```json5 + { + channels: { + slack: { + groupPolicy: "allowlist", + channels: { + "#eng-my-channel": { allow: true, requireMention: true }, + }, + }, + }, + } + ``` + + + + + + 頻道訊息預設以提及作為門檻。 + + 提及來源: + + - 明確的應用程式提及(`<@botId>`) + - 提及正則表示式模式(`agents.list[].groupChat.mentionPatterns`,備援為 `messages.groupChat.mentionPatterns`) + - 隱含的回覆機器人執行緒行為(當 `thread.requireExplicitMention` 為 `true` 時停用) + + 個別頻道控制項(`channels.slack.channels.`;名稱只能透過啟動解析或 `dangerouslyAllowNameMatching` 使用): + + - `requireMention` + - `users`(允許清單) + - `allowBots` + - `skills` + - `systemPrompt` + - `tools`、`toolsBySender` + - `toolsBySender` 鍵格式:`id:`、`e164:`、`username:`、`name:` 或 `"*"` 萬用字元 + (舊版未加前綴的鍵仍只會對應到 `id:`) + + + + +## 執行緒、工作階段與回覆標籤 + +- DM 會路由為 `direct`;頻道為 `channel`;MPIM 為 `group`。 +- 使用預設 `session.dmScope=main` 時,Slack DM 會收斂到代理主工作階段。 +- 頻道工作階段:`agent::slack:channel:`。 +- 適用時,執行緒回覆可以建立執行緒工作階段後綴(`:thread:`)。 +- `channels.slack.thread.historyScope` 預設為 `thread`;`thread.inheritParent` 預設為 `false`。 +- `channels.slack.thread.initialHistoryLimit` 控制新執行緒工作階段開始時會擷取多少現有執行緒訊息(預設 `20`;設為 `0` 可停用)。 +- `channels.slack.thread.requireExplicitMention`(預設 `false`):當為 `true` 時,會抑制隱含的執行緒提及,因此機器人只會回應執行緒內明確的 `@bot` 提及,即使機器人已參與該執行緒也是如此。若沒有此設定,機器人已參與執行緒中的回覆會繞過 `requireMention` 門檻。 + +回覆執行緒控制項: + +- `channels.slack.replyToMode`:`off|first|all|batched`(預設 `off`) +- `channels.slack.replyToModeByChatType`:依 `direct|group|channel` +- 直接聊天的舊版備援:`channels.slack.dm.replyToMode` + +支援手動回覆標籤: + +- `[[reply_to_current]]` +- `[[reply_to:]]` + + +`replyToMode="off"` 會停用 Slack 中的**所有**回覆執行緒,包括明確的 `[[reply_to_*]]` 標籤。這與 Telegram 不同,在 Telegram 中,明確標籤在 `"off"` 模式下仍會被採用。Slack 執行緒會將訊息從頻道中隱藏,而 Telegram 回覆會保持行內可見。 + + +## 確認反應 + +`ackReaction` 會在 OpenClaw 處理傳入訊息時傳送確認 emoji。 + +解析順序: + +- `channels.slack.accounts..ackReaction` +- `channels.slack.ackReaction` +- `messages.ackReaction` +- 代理身分 emoji 備援(`agents.list[].identity.emoji`,否則為 "👀") + +注意事項: + +- Slack 預期使用短碼(例如 `"eyes"`)。 +- 使用 `""` 可停用 Slack 帳戶或全域的反應。 + +## 文字串流 + +`channels.slack.streaming` 控制即時預覽行為: + +- `off`:停用即時預覽串流。 +- `partial`(預設):以最新的部分輸出取代預覽文字。 +- `block`:附加分塊預覽更新。 +- `progress`:產生時顯示進度狀態文字,然後傳送最終文字。 +- `streaming.preview.toolProgress`:當草稿預覽啟用時,將工具/進度更新路由到同一則已編輯的預覽訊息中(預設:`true`)。設為 `false` 可保留獨立的工具/進度訊息。 + +當 `channels.slack.streaming.mode` 為 `partial` 時,`channels.slack.streaming.nativeTransport` 控制 Slack 原生文字串流(預設:`true`)。 + +- 必須有可用的回覆執行緒,才會顯示原生文字串流和 Slack 助理執行緒狀態。執行緒選擇仍遵循 `replyToMode`。 +- 當原生串流不可用時,頻道和群組聊天根訊息仍可使用一般草稿預覽。 +- 頂層 Slack DM 預設不在執行緒中,因此不會顯示執行緒樣式預覽;如果你想在那裡顯示可見進度,請使用執行緒回覆或 `typingReaction`。 +- 媒體和非文字承載會退回一般傳遞。 +- 媒體/錯誤最終訊息會取消待處理的預覽編輯;符合條件的文字/區塊最終訊息只有在能就地編輯預覽時才會清出。 +- 如果串流在回覆中途失敗,OpenClaw 會針對剩餘承載退回一般傳遞。 + +使用草稿預覽而非 Slack 原生文字串流: + +```json5 +{ + channels: { + slack: { + streaming: { + mode: "partial", + nativeTransport: false, + }, + }, + }, +} +``` + +舊版鍵: + +- `channels.slack.streamMode` (`replace | status_final | append`) 會自動遷移到 `channels.slack.streaming.mode`。 +- 布林值 `channels.slack.streaming` 會自動遷移到 `channels.slack.streaming.mode` 和 `channels.slack.streaming.nativeTransport`。 +- 舊版 `channels.slack.nativeStreaming` 會自動遷移到 `channels.slack.streaming.nativeTransport`。 + +## 輸入中反應備援 + +`typingReaction` 會在 OpenClaw 處理回覆時,對傳入的 Slack 訊息新增暫時反應,然後在執行完成時移除。這在執行緒回覆之外最有用,因為執行緒回覆會使用預設的「正在輸入...」狀態指示器。 + +解析順序: + +- `channels.slack.accounts..typingReaction` +- `channels.slack.typingReaction` + +注意事項: + +- Slack 預期使用短碼(例如 `"hourglass_flowing_sand"`)。 +- 此反應是盡力而為,並會在回覆或失敗路徑完成後自動嘗試清理。 + +## 媒體、分塊與傳遞 + + + + Slack 檔案附件會從 Slack 託管的私人 URL 下載(以權杖驗證的請求流程),並在擷取成功且大小限制允許時寫入媒體儲存區。檔案佔位符包含 Slack `fileId`,讓代理可以透過 `download-file` 擷取原始檔案。 + + 下載會使用有界的閒置與總逾時。如果 Slack 檔案擷取停滯或失敗,OpenClaw 會繼續處理訊息,並退回到檔案佔位符。 + + 執行階段傳入大小上限預設為 `20MB`,除非由 `channels.slack.mediaMaxMb` 覆寫。 + + + + + - 文字分塊使用 `channels.slack.textChunkLimit`(預設 4000) + - `channels.slack.chunkMode="newline"` 啟用段落優先切分 + - 檔案傳送使用 Slack 上傳 API,並可包含執行緒回覆(`thread_ts`) + - 設定後,傳出媒體上限會遵循 `channels.slack.mediaMaxMb`;否則頻道傳送會使用媒體管線中的 MIME 類型預設值 + + + + + 建議的明確目標: + + - `user:` 用於 DM + - `channel:` 用於頻道 + + 傳送到使用者目標時,Slack DM 會透過 Slack 對話 API 開啟。 + + + + +## 命令與斜線行為 + +斜線命令會在 Slack 中顯示為單一已設定命令或多個原生命令。設定 `channels.slack.slashCommand` 可變更命令預設值: + +- `enabled: false` +- `name: "openclaw"` +- `sessionPrefix: "slack:slash"` +- `ephemeral: true` + +```txt +/openclaw /help +``` + +原生命令需要在你的 Slack app 中設定[額外的 manifest 設定](#additional-manifest-settings),並改用全域設定中的 `channels.slack.commands.native: true` 或 `commands.native: true` 啟用。 + +- Slack 的原生命令自動模式預設為**關閉**,因此 `commands.native: "auto"` 不會啟用 Slack 原生命令。 + +```txt +/help +``` + +原生引數選單使用自適應轉譯策略,會在派送所選選項值前顯示確認 modal: + +- 最多 5 個選項:按鈕區塊 +- 6-100 個選項:靜態選取選單 +- 超過 100 個選項:當 interactivity options handlers 可用時,使用外部選取並進行非同步選項篩選 +- 超出 Slack 限制:已編碼的選項值會退回使用按鈕 + +```txt +/think +``` + +Slash 工作階段使用像 `agent::slack:slash:` 這類隔離 key,並且仍會使用 `CommandTargetSessionKey` 將命令執行路由到目標對話工作階段。 + +## 互動式回覆 + +Slack 可以轉譯由代理撰寫的互動式回覆控制項,但此功能預設為停用。 + +全域啟用: + +```json5 +{ + channels: { + slack: { + capabilities: { + interactiveReplies: true, + }, + }, + }, +} +``` + +或只為一個 Slack 帳號啟用: + +```json5 +{ + channels: { + slack: { + accounts: { + ops: { + capabilities: { + interactiveReplies: true, + }, + }, + }, + }, + }, +} +``` + +啟用後,代理可以發出僅限 Slack 的回覆指令: + +- `[[slack_buttons: Approve:approve, Reject:reject]]` +- `[[slack_select: Choose a target | Canary:canary, Production:production]]` + +這些指令會編譯成 Slack Block Kit,並透過既有的 Slack 互動事件路徑將點擊或選取路由回來。 + +注意事項: + +- 這是 Slack 專用 UI。其他通道不會將 Slack Block Kit 指令轉譯成自己的按鈕系統。 +- 互動式 callback 值是 OpenClaw 產生的不透明 token,不是代理原始撰寫的值。 +- 如果產生的互動式區塊會超出 Slack Block Kit 限制,OpenClaw 會退回原始文字回覆,而不是傳送無效的 blocks payload。 + +## Slack 中的 exec 核准 + +Slack 可以作為具備互動式按鈕與互動的原生核准用戶端,而不是退回使用 Web UI 或 terminal。 + +- Exec 核准使用 `channels.slack.execApprovals.*` 進行原生 DM/頻道路由。 +- 當請求已經落在 Slack 且核准 id kind 為 `plugin:` 時,Plugin 核准仍可透過相同的 Slack 原生按鈕介面解析。 +- 核准者授權仍會強制執行:只有被識別為核准者的使用者可以透過 Slack 核准或拒絕請求。 + +這會使用與其他通道相同的共用核准按鈕介面。當你的 Slack app 設定已啟用 `interactivity` 時,核准提示會直接在對話中轉譯為 Block Kit 按鈕。 +當這些按鈕存在時,它們就是主要核准 UX;OpenClaw 只有在工具結果表示聊天核准不可用,或手動核准是唯一路徑時,才應包含手動 `/approve` 命令。 + +設定路徑: + +- `channels.slack.execApprovals.enabled` +- `channels.slack.execApprovals.approvers`(選用;可行時會退回使用 `commands.ownerAllowFrom`) +- `channels.slack.execApprovals.target`(`dm` | `channel` | `both`,預設:`dm`) +- `agentFilter`、`sessionFilter` + +當 `enabled` 未設定或為 `"auto"`,且至少解析出一位核准者時,Slack 會自動啟用原生 exec 核准。設定 `enabled: false` 可明確停用 Slack 作為原生核准用戶端。 +設定 `enabled: true` 可在核准者解析成功時強制啟用原生核准。 + +沒有明確 Slack exec 核准設定時的預設行為: + +```json5 +{ + commands: { + ownerAllowFrom: ["slack:U12345678"], + }, +} +``` + +只有在你想覆寫核准者、新增篩選器,或選擇加入來源聊天遞送時,才需要明確的 Slack 原生設定: + +```json5 +{ + channels: { + slack: { + execApprovals: { + enabled: true, + approvers: ["U12345678"], + target: "both", + }, + }, + }, +} +``` + +共用的 `approvals.exec` 轉送是分開的。只有當 exec 核准提示也必須路由到其他聊天或明確的頻外目標時才使用它。共用的 `approvals.plugin` 轉送也同樣分開;當這些請求已經落在 Slack 時,Slack 原生按鈕仍可解析 Plugin 核准。 + +相同聊天中的 `/approve` 也可在已支援命令的 Slack 頻道與 DM 中運作。完整核准轉送模型請參閱 [Exec 核准](/zh-TW/tools/exec-approvals)。 + +## 事件與操作行為 + +- 訊息編輯/刪除會對應為系統事件。 +- 執行緒廣播(「也傳送到頻道」的執行緒回覆)會作為一般使用者訊息處理。 +- 新增/移除 reaction 事件會對應為系統事件。 +- 成員加入/離開、頻道建立/重新命名,以及新增/移除 pin 事件會對應為系統事件。 +- 啟用 `configWrites` 時,`channel_id_changed` 可以遷移頻道設定 key。 +- 頻道 topic/purpose metadata 會被視為不可信任的 context,並可注入到路由 context 中。 +- 適用時,執行緒起始訊息與初始執行緒歷史 context 種子會依設定的傳送者 allowlists 篩選。 +- Block actions 與 modal 互動會發出結構化的 `Slack interaction: ...` 系統事件,並包含豐富的 payload 欄位: + - block actions:所選值、標籤、picker 值,以及 `workflow_*` metadata + - modal `view_submission` 與 `view_closed` 事件,包含已路由的頻道 metadata 與表單輸入 + +## 設定參考 + +主要參考:[設定參考 - Slack](/zh-TW/gateway/config-channels#slack)。 + + + +- 模式/驗證:`mode`、`botToken`、`appToken`、`signingSecret`、`webhookPath`、`accounts.*` +- DM 存取:`dm.enabled`、`dmPolicy`、`allowFrom`(舊版:`dm.policy`、`dm.allowFrom`)、`dm.groupEnabled`、`dm.groupChannels` +- 相容性切換:`dangerouslyAllowNameMatching`(緊急例外;除非需要,否則保持關閉) +- 頻道存取:`groupPolicy`、`channels.*`、`channels.*.users`、`channels.*.requireMention` +- 執行緒/歷史:`replyToMode`、`replyToModeByChatType`、`thread.*`、`historyLimit`、`dmHistoryLimit`、`dms.*.historyLimit` +- 遞送:`textChunkLimit`、`chunkMode`、`mediaMaxMb`、`streaming`、`streaming.nativeTransport`、`streaming.preview.toolProgress` +- 操作/功能:`configWrites`、`commands.native`、`slashCommand.*`、`actions.*`、`userToken`、`userTokenReadOnly` + + + +## 疑難排解 + + + + 依序檢查: + + - `groupPolicy` + - 頻道 allowlist(`channels.slack.channels`)— **key 必須是頻道 ID**(`C12345678`),不是名稱(`#channel-name`)。在 `groupPolicy: "allowlist"` 下,名稱式 key 會靜默失敗,因為頻道路由預設優先使用 ID。若要尋找 ID:在 Slack 中對頻道按右鍵 → **複製連結** — URL 結尾的 `C...` 值就是頻道 ID。 + - `requireMention` + - 個別頻道的 `users` allowlist + + 實用命令: + +```bash +openclaw channels status --probe +openclaw logs --follow +openclaw doctor +``` + + + + + 檢查: + + - `channels.slack.dm.enabled` + - `channels.slack.dmPolicy`(或舊版 `channels.slack.dm.policy`) + - 配對核准 / allowlist 項目 + - Slack Assistant DM 事件:提到 `drop message_changed` 的 verbose logs + 通常表示 Slack 傳送了已編輯的 Assistant 執行緒事件,但訊息 metadata 中 + 沒有可復原的人類傳送者 + +```bash +openclaw pairing list slack +``` + + + + + 驗證 bot + app tokens,以及 Slack app 設定中的 Socket Mode 啟用狀態。 + + 如果 `openclaw channels status --probe --json` 顯示 `botTokenStatus` 或 + `appTokenStatus: "configured_unavailable"`,表示 Slack 帳號已設定, + 但目前 runtime 無法解析 SecretRef 支援的值。 + + + + + 驗證: + + - signing secret + - webhook path + - Slack Request URLs(Events + Interactivity + Slash Commands) + - 每個 HTTP 帳號的唯一 `webhookPath` + + 如果帳號 snapshot 中出現 `signingSecretStatus: "configured_unavailable"`, + 表示 HTTP 帳號已設定,但目前 runtime 無法解析 SecretRef 支援的 signing secret。 + + + + + 確認你的預期是: + + - 原生命令模式(`channels.slack.commands.native: true`),並在 Slack 中註冊相符的 slash commands + - 或單一 slash command 模式(`channels.slack.slashCommand.enabled: true`) + + 同時檢查 `commands.useAccessGroups` 與頻道/使用者 allowlists。 + + + + +## 附件視覺參考 + +當 Slack 檔案下載成功且大小限制允許時,Slack 可以將下載的媒體附加到代理回合。影像檔可透過媒體理解路徑傳遞,或直接傳給支援視覺的回覆模型;其他檔案會保留為可下載檔案 context,而不是被視為影像輸入。 + +### 支援的媒體類型 + +| 媒體類型 | 來源 | 目前行為 | 注意事項 | +| ------------------------------ | -------------------- | --------------------------------------------------------------------------------- | ------------------------------------------------------------------------- | +| JPEG / PNG / GIF / WebP 影像 | Slack 檔案 URL | 已下載並附加到回合,以便支援視覺的處理 | 每檔案上限:`channels.slack.mediaMaxMb`(預設 20 MB) | +| PDF 檔案 | Slack 檔案 URL | 已下載並公開為檔案 context,供 `download-file` 或 `pdf` 等工具使用 | Slack inbound 不會自動將 PDF 轉換為影像視覺輸入 | +| 其他檔案 | Slack 檔案 URL | 可行時下載並公開為檔案 context | 二進位檔案不會被視為影像輸入 | +| 執行緒回覆 | 執行緒起始檔案 | 當回覆沒有直接媒體時,可將根訊息檔案補齊為 context | 只有檔案的起始訊息會使用附件 placeholder | +| 多影像訊息 | 多個 Slack 檔案 | 每個檔案都會獨立評估 | Slack 處理每則訊息最多八個檔案 | + +### Inbound pipeline + +當帶有檔案附件的 Slack 訊息抵達時: + +1. OpenClaw 使用 bot token(`xoxb-...`)從 Slack 的私有 URL 下載檔案。 +2. 成功時,檔案會寫入媒體儲存區。 +3. 已下載的媒體路徑與內容類型會加入 inbound context。 +4. 支援影像的模型/工具路徑可以使用該 context 中的影像附件。 +5. 非影像檔案會以檔案 metadata 或媒體 reference 的形式保留,供可處理它們的工具使用。 + +### 執行緒根附件繼承 + +當訊息抵達執行緒中(具有 `thread_ts` parent)時: + +- 如果回覆本身沒有直接媒體,而包含的根訊息有檔案,Slack 可以將根檔案補齊為執行緒起始 context。 +- 直接回覆附件優先於根訊息附件。 +- 只有檔案且沒有文字的根訊息會以附件 placeholder 表示,因此 fallback 仍可包含其檔案。 + +### 多附件處理 + +當單一 Slack 訊息包含多個檔案附件時: + +- 每個附件都會透過媒體管線獨立處理。 +- 已下載的媒體參照會彙總到訊息情境中。 +- 處理順序會依照事件有效負載中的 Slack 檔案順序。 +- 其中一個附件下載失敗不會阻擋其他附件。 + +### 大小、下載與模型限制 + +- **大小上限**:預設每個檔案 20 MB。可透過 `channels.slack.mediaMaxMb` 設定。 +- **下載失敗**:Slack 無法提供的檔案、過期的 URL、無法存取的檔案、超過大小限制的檔案,以及 Slack 驗證/登入 HTML 回應都會被略過,而不是回報為不支援的格式。 +- **視覺模型**:影像分析會在作用中的回覆模型支援視覺時使用該模型,否則使用 `agents.defaults.imageModel` 設定的影像模型。 + +### 已知限制 + +| 情境 | 目前行為 | 解決方式 | +| -------------------------------------- | ---------------------------------------------------------------------------- | -------------------------------------------------------------------------- | +| 過期的 Slack 檔案 URL | 檔案被略過;不顯示錯誤 | 在 Slack 中重新上傳檔案 | +| 未設定視覺模型 | 影像附件會儲存為媒體參照,但不會作為影像分析 | 設定 `agents.defaults.imageModel`,或使用支援視覺的回覆模型 | +| 非常大的影像(預設 > 20 MB) | 依大小上限略過 | 如果 Slack 允許,請提高 `channels.slack.mediaMaxMb` | +| 轉寄/共享的附件 | 文字與 Slack 託管的影像/檔案媒體會以最佳努力方式處理 | 直接在 OpenClaw 執行緒中重新分享 | +| PDF 附件 | 儲存為檔案/媒體情境,不會自動透過影像視覺路由 | 使用 `download-file` 取得檔案中繼資料,或使用 `pdf` 工具進行 PDF 分析 | + +### 相關文件 + +- [媒體理解管線](/zh-TW/nodes/media-understanding) +- [PDF 工具](/zh-TW/tools/pdf) +- Epic: [#51349](https://github.com/openclaw/openclaw/issues/51349) — Slack 附件視覺啟用 +- 迴歸測試:[#51353](https://github.com/openclaw/openclaw/issues/51353) +- 即時驗證:[#51354](https://github.com/openclaw/openclaw/issues/51354) + +## 相關 + + + + 將 Slack 使用者與 Gateway 配對。 + + + Channel 與群組 DM 行為。 + + + 將傳入訊息路由至代理程式。 + + + 威脅模型與強化措施。 + + + 設定版面配置與優先順序。 + + + 指令目錄與行為。 + + diff --git a/docs/zh-TW/channels/synology-chat.md b/docs/zh-TW/channels/synology-chat.md new file mode 100644 index 000000000..8e06b2b60 --- /dev/null +++ b/docs/zh-TW/channels/synology-chat.md @@ -0,0 +1,189 @@ +--- +read_when: + - 設定 Synology Chat 與 OpenClaw 搭配使用 + - 偵錯 Synology Chat Webhook 路由 +summary: Synology Chat Webhook 設定與 OpenClaw 配置 +title: Synology Chat +x-i18n: + generated_at: "2026-04-30T02:49:19Z" + model: gpt-5.5 + provider: openai + source_hash: c3d6d7a56bd15d29de38c6ae29ae496b491c2e75df5e0a0a15410b0fbdc55a00 + source_path: channels/synology-chat.md + workflow: 16 +--- + +狀態:使用 Synology Chat Webhook 的隨附 Plugin 直接訊息頻道。 +此 Plugin 接受來自 Synology Chat outgoing Webhook 的傳入訊息,並透過 Synology Chat incoming Webhook 傳送回覆。 + +## 隨附 Plugin + +Synology Chat 在目前的 OpenClaw 版本中以隨附 Plugin 形式提供,因此一般封裝建置不需要另外安裝。 + +如果你使用的是較舊的建置,或是不包含 Synology Chat 的自訂安裝,請手動安裝: + +從本機 checkout 安裝: + +```bash +openclaw plugins install ./path/to/local/synology-chat-plugin +``` + +詳細資訊:[Plugins](/zh-TW/tools/plugin) + +## 快速設定 + +1. 確認 Synology Chat Plugin 可用。 + - 目前封裝的 OpenClaw 版本已經隨附它。 + - 較舊或自訂安裝可以使用上方指令,從原始碼 checkout 手動加入。 + - `openclaw onboard` 現在會在與 `openclaw channels add` 相同的頻道設定清單中顯示 Synology Chat。 + - 非互動式設定:`openclaw channels add --channel synology-chat --token --url ` +2. 在 Synology Chat integrations 中: + - 建立 incoming Webhook 並複製其 URL。 + - 使用你的秘密 token 建立 outgoing Webhook。 +3. 將 outgoing Webhook URL 指向你的 OpenClaw Gateway: + - 預設為 `https://gateway-host/webhook/synology`。 + - 或使用你的自訂 `channels.synology-chat.webhookPath`。 +4. 在 OpenClaw 中完成設定。 + - 引導式:`openclaw onboard` + - 直接:`openclaw channels add --channel synology-chat --token --url ` +5. 重新啟動 Gateway,並向 Synology Chat bot 傳送 DM。 + +Webhook 驗證詳細資訊: + +- OpenClaw 會先從 `body.token` 接受 outgoing Webhook token,接著是 + `?token=...`,再來是 headers。 +- 接受的 header 形式: + - `x-synology-token` + - `x-webhook-token` + - `x-openclaw-token` + - `Authorization: Bearer ` +- 空白或缺少的 token 會安全失敗。 + +最小設定: + +```json5 +{ + channels: { + "synology-chat": { + enabled: true, + token: "synology-outgoing-token", + incomingUrl: "https://nas.example.com/webapi/entry.cgi?api=SYNO.Chat.External&method=incoming&version=2&token=...", + webhookPath: "/webhook/synology", + dmPolicy: "allowlist", + allowedUserIds: ["123456"], + rateLimitPerMinute: 30, + allowInsecureSsl: false, + }, + }, +} +``` + +## 環境變數 + +對於預設帳號,你可以使用環境變數: + +- `SYNOLOGY_CHAT_TOKEN` +- `SYNOLOGY_CHAT_INCOMING_URL` +- `SYNOLOGY_NAS_HOST` +- `SYNOLOGY_ALLOWED_USER_IDS`(以逗號分隔) +- `SYNOLOGY_RATE_LIMIT` +- `OPENCLAW_BOT_NAME` + +設定值會覆寫環境變數。 + +`SYNOLOGY_CHAT_INCOMING_URL` 無法從工作區 `.env` 設定;請參閱[工作區 `.env` 檔案](/zh-TW/gateway/security)。 + +## DM 政策與存取控制 + +- `dmPolicy: "allowlist"` 是建議的預設值。 +- `allowedUserIds` 接受 Synology 使用者 ID 的清單(或以逗號分隔的字串)。 +- 在 `allowlist` 模式中,空的 `allowedUserIds` 清單會視為設定錯誤,Webhook 路由將不會啟動(若要允許全部,請使用 `dmPolicy: "open"` 搭配 `allowedUserIds: ["*"]`)。 +- `dmPolicy: "open"` 只有在 `allowedUserIds` 包含 `"*"` 時才允許公開 DM;如果是限制性項目,只有相符的使用者可以聊天。 +- `dmPolicy: "disabled"` 會封鎖 DM。 +- 回覆收件者繫結預設維持在穩定的數字 `user_id`。`channels.synology-chat.dangerouslyAllowNameMatching: true` 是破窗相容模式,會重新啟用可變更的使用者名稱/暱稱查找以進行回覆傳送。 +- 配對核准可搭配: + - `openclaw pairing list synology-chat` + - `openclaw pairing approve synology-chat ` + +## 對外傳送 + +使用數字 Synology Chat 使用者 ID 作為目標。 + +範例: + +```bash +openclaw message send --channel synology-chat --target 123456 --text "Hello from OpenClaw" +openclaw message send --channel synology-chat --target synology-chat:123456 --text "Hello again" +``` + +支援透過 URL 型檔案傳送媒體。 +對外檔案 URL 必須使用 `http` 或 `https`,而且私有或其他遭封鎖的網路目標會在 OpenClaw 將 URL 轉送至 NAS Webhook 前被拒絕。 + +## 多帳號 + +`channels.synology-chat.accounts` 下支援多個 Synology Chat 帳號。 +每個帳號都可以覆寫 token、incoming URL、Webhook path、DM 政策與限制。 +直接訊息工作階段會依帳號與使用者隔離,因此兩個不同 Synology 帳號上的相同數字 `user_id` +不會共用 transcript 狀態。 +請為每個啟用的帳號提供不同的 `webhookPath`。OpenClaw 現在會拒絕重複的完全相同路徑, +並拒絕啟動在多帳號設定中只繼承共用 Webhook path 的具名帳號。 +如果你刻意需要具名帳號的舊版繼承行為,請在該帳號或 `channels.synology-chat` 上設定 +`dangerouslyAllowInheritedWebhookPath: true`,但重複的完全相同路徑仍會安全失敗並遭拒絕。請優先使用明確的各帳號路徑。 + +```json5 +{ + channels: { + "synology-chat": { + enabled: true, + accounts: { + default: { + token: "token-a", + incomingUrl: "https://nas-a.example.com/...token=...", + }, + alerts: { + token: "token-b", + incomingUrl: "https://nas-b.example.com/...token=...", + webhookPath: "/webhook/synology-alerts", + dmPolicy: "allowlist", + allowedUserIds: ["987654"], + }, + }, + }, + }, +} +``` + +## 安全性注意事項 + +- 請保護 `token` 秘密,若外洩請輪換它。 +- 除非你明確信任自簽的本機 NAS 憑證,否則請保持 `allowInsecureSsl: false`。 +- 傳入 Webhook 請求會經過 token 驗證,並依傳送者套用速率限制。 +- 無效 token 檢查使用固定時間秘密比較,並會安全失敗。 +- 生產環境建議使用 `dmPolicy: "allowlist"`。 +- 除非你明確需要舊版以使用者名稱為基礎的回覆傳送,否則請保持 `dangerouslyAllowNameMatching` 關閉。 +- 除非你明確接受多帳號設定中的共用路徑路由風險,否則請保持 `dangerouslyAllowInheritedWebhookPath` 關閉。 + +## 疑難排解 + +- `Missing required fields (token, user_id, text)`: + - outgoing Webhook payload 缺少其中一個必填欄位 + - 如果 Synology 在 headers 中傳送 token,請確認 Gateway/proxy 保留這些 headers +- `Invalid token`: + - outgoing Webhook secret 與 `channels.synology-chat.token` 不相符 + - 請求打到錯誤的帳號/Webhook path + - reverse proxy 在請求到達 OpenClaw 前移除了 token header +- `Rate limit exceeded`: + - 來自同一來源的過多無效 token 嘗試可能會暫時鎖定該來源 + - 已驗證的傳送者也有另一個依使用者套用的訊息速率限制 +- `Allowlist is empty. Configure allowedUserIds or use dmPolicy=open with allowedUserIds=["*"].`: + - 已啟用 `dmPolicy="allowlist"`,但尚未設定任何使用者 +- `User not authorized`: + - 傳送者的數字 `user_id` 不在 `allowedUserIds` 中 + +## 相關 + +- [頻道概覽](/zh-TW/channels) — 所有支援的頻道 +- [配對](/zh-TW/channels/pairing) — DM 驗證與配對流程 +- [群組](/zh-TW/channels/groups) — 群組聊天行為與提及閘控 +- [頻道路由](/zh-TW/channels/channel-routing) — 訊息的工作階段路由 +- [安全性](/zh-TW/gateway/security) — 存取模型與強化 diff --git a/docs/zh-TW/channels/telegram.md b/docs/zh-TW/channels/telegram.md new file mode 100644 index 000000000..e92f8cf1e --- /dev/null +++ b/docs/zh-TW/channels/telegram.md @@ -0,0 +1,989 @@ +--- +read_when: + - 開發 Telegram 功能或 Webhook +summary: Telegram 機器人支援狀態、功能與設定 +title: Telegram +x-i18n: + generated_at: "2026-04-30T02:49:17Z" + model: gpt-5.5 + provider: openai + source_hash: 1ffc0c1a6bb94fbab81ede0f08b0e3a165f06c599d4d06d4b9e70c8ba41121f7 + source_path: channels/telegram.md + workflow: 16 +--- + +Production-ready for bot DMs and groups via grammY. Long polling is the default mode; webhook mode is optional. + + + + Default DM policy for Telegram is pairing. + + + Cross-channel diagnostics and repair playbooks. + + + Full channel config patterns and examples. + + + +## Quick setup + + + + Open Telegram and chat with **@BotFather** (confirm the handle is exactly `@BotFather`). + + Run `/newbot`, follow prompts, and save the token. + + + + + +```json5 +{ + channels: { + telegram: { + enabled: true, + botToken: "123:abc", + dmPolicy: "pairing", + groups: { "*": { requireMention: true } }, + }, + }, +} +``` + + Env fallback: `TELEGRAM_BOT_TOKEN=...` (default account only). + Telegram does **not** use `openclaw channels login telegram`; configure token in config/env, then start gateway. + + + + + +```bash +openclaw gateway +openclaw pairing list telegram +openclaw pairing approve telegram +``` + + Pairing codes expire after 1 hour. + + + + + Add the bot to your group, then set `channels.telegram.groups` and `groupPolicy` to match your access model. + + + + +Token resolution order is account-aware. In practice, config values win over env fallback, and `TELEGRAM_BOT_TOKEN` only applies to the default account. + + +## Telegram side settings + + + + Telegram bots default to **Privacy Mode**, which limits what group messages they receive. + + If the bot must see all group messages, either: + + - disable privacy mode via `/setprivacy`, or + - make the bot a group admin. + + When toggling privacy mode, remove + re-add the bot in each group so Telegram applies the change. + + + + + Admin status is controlled in Telegram group settings. + + Admin bots receive all group messages, which is useful for always-on group behavior. + + + + + + - `/setjoingroups` to allow/deny group adds + - `/setprivacy` for group visibility behavior + + + + +## Access control and activation + + + + `channels.telegram.dmPolicy` controls direct message access: + + - `pairing` (default) + - `allowlist` (requires at least one sender ID in `allowFrom`) + - `open` (requires `allowFrom` to include `"*"`) + - `disabled` + + `dmPolicy: "open"` with `allowFrom: ["*"]` lets any Telegram account that finds or guesses the bot username command the bot. Use it only for intentionally public bots with tightly restricted tools; one-owner bots should use `allowlist` with numeric user IDs. + + `channels.telegram.allowFrom` accepts numeric Telegram user IDs. `telegram:` / `tg:` prefixes are accepted and normalized. + In multi-account configs, a restrictive top-level `channels.telegram.allowFrom` is treated as a safety boundary: account-level `allowFrom: ["*"]` entries do not make that account public unless the effective account allowlist still contains an explicit wildcard after merging. + `dmPolicy: "allowlist"` with empty `allowFrom` blocks all DMs and is rejected by config validation. + Setup asks for numeric user IDs only. + If you upgraded and your config contains `@username` allowlist entries, run `openclaw doctor --fix` to resolve them (best-effort; requires a Telegram bot token). + If you previously relied on pairing-store allowlist files, `openclaw doctor --fix` can recover entries into `channels.telegram.allowFrom` in allowlist flows (for example when `dmPolicy: "allowlist"` has no explicit IDs yet). + + For one-owner bots, prefer `dmPolicy: "allowlist"` with explicit numeric `allowFrom` IDs to keep access policy durable in config (instead of depending on previous pairing approvals). + + Common confusion: DM pairing approval does not mean "this sender is authorized everywhere". + Pairing grants DM access. If no command owner exists yet, the first approved pairing also sets `commands.ownerAllowFrom` so owner-only commands and exec approvals have an explicit operator account. + Group sender authorization still comes from explicit config allowlists. + If you want "I am authorized once and both DMs and group commands work", put your numeric Telegram user ID in `channels.telegram.allowFrom`; for owner-only commands, make sure `commands.ownerAllowFrom` contains `telegram:`. + + ### Finding your Telegram user ID + + Safer (no third-party bot): + + 1. DM your bot. + 2. Run `openclaw logs --follow`. + 3. Read `from.id`. + + Official Bot API method: + +```bash +curl "https://api.telegram.org/bot/getUpdates" +``` + + Third-party method (less private): `@userinfobot` or `@getidsbot`. + + + + + Two controls apply together: + + 1. **Which groups are allowed** (`channels.telegram.groups`) + - no `groups` config: + - with `groupPolicy: "open"`: any group can pass group-ID checks + - with `groupPolicy: "allowlist"` (default): groups are blocked until you add `groups` entries (or `"*"`) + - `groups` configured: acts as allowlist (explicit IDs or `"*"`) + + 2. **Which senders are allowed in groups** (`channels.telegram.groupPolicy`) + - `open` + - `allowlist` (default) + - `disabled` + + `groupAllowFrom` is used for group sender filtering. If not set, Telegram falls back to `allowFrom`. + `groupAllowFrom` entries should be numeric Telegram user IDs (`telegram:` / `tg:` prefixes are normalized). + Do not put Telegram group or supergroup chat IDs in `groupAllowFrom`. Negative chat IDs belong under `channels.telegram.groups`. + Non-numeric entries are ignored for sender authorization. + Security boundary (`2026.2.25+`): group sender auth does **not** inherit DM pairing-store approvals. + Pairing stays DM-only. For groups, set `groupAllowFrom` or per-group/per-topic `allowFrom`. + If `groupAllowFrom` is unset, Telegram falls back to config `allowFrom`, not the pairing store. + Practical pattern for one-owner bots: set your user ID in `channels.telegram.allowFrom`, leave `groupAllowFrom` unset, and allow the target groups under `channels.telegram.groups`. + Runtime note: if `channels.telegram` is completely missing, runtime defaults to fail-closed `groupPolicy="allowlist"` unless `channels.defaults.groupPolicy` is explicitly set. + + Example: allow any member in one specific group: + +```json5 +{ + channels: { + telegram: { + groups: { + "-1001234567890": { + groupPolicy: "open", + requireMention: false, + }, + }, + }, + }, +} +``` + + Example: allow only specific users inside one specific group: + +```json5 +{ + channels: { + telegram: { + groups: { + "-1001234567890": { + requireMention: true, + allowFrom: ["8734062810", "745123456"], + }, + }, + }, + }, +} +``` + + + Common mistake: `groupAllowFrom` is not a Telegram group allowlist. + + - Put negative Telegram group or supergroup chat IDs like `-1001234567890` under `channels.telegram.groups`. + - Put Telegram user IDs like `8734062810` under `groupAllowFrom` when you want to limit which people inside an allowed group can trigger the bot. + - Use `groupAllowFrom: ["*"]` only when you want any member of an allowed group to be able to talk to the bot. + + + + + + + Group replies require mention by default. + + Mention can come from: + + - native `@botusername` mention, or + - mention patterns in: + - `agents.list[].groupChat.mentionPatterns` + - `messages.groupChat.mentionPatterns` + + Session-level command toggles: + + - `/activation always` + - `/activation mention` + + These update session state only. Use config for persistence. + + Persistent config example: + +```json5 +{ + channels: { + telegram: { + groups: { + "*": { requireMention: false }, + }, + }, + }, +} +``` + + Getting the group chat ID: + + - forward a group message to `@userinfobot` / `@getidsbot` + - or read `chat.id` from `openclaw logs --follow` + - or inspect Bot API `getUpdates` + + + + +## Runtime behavior + +- Telegram is owned by the gateway process. +- Routing is deterministic: Telegram inbound replies back to Telegram (the model does not pick channels). +- Inbound messages normalize into the shared channel envelope with reply metadata and media placeholders. +- Group sessions are isolated by group ID. Forum topics append `:topic:` to keep topics isolated. +- DM messages can carry `message_thread_id`; OpenClaw routes them with thread-aware session keys and preserves thread ID for replies. +- Long polling uses grammY runner with per-chat/per-thread sequencing. Overall runner sink concurrency uses `agents.defaults.maxConcurrent`. +- Long polling is guarded inside each gateway process so only one active poller can use a bot token at a time. If you still see `getUpdates` 409 conflicts, another OpenClaw gateway, script, or external poller is likely using the same token. +- Long-polling watchdog restarts trigger after 120 seconds without completed `getUpdates` liveness by default. Increase `channels.telegram.pollingStallThresholdMs` only if your deployment still sees false polling-stall restarts during long-running work. The value is in milliseconds and is allowed from `30000` to `600000`; per-account overrides are supported. +- Telegram Bot API has no read-receipt support (`sendReadReceipts` does not apply). + +## Feature reference + + + + OpenClaw can stream partial replies in real time: + + - direct chats: preview message + `editMessageText` + - groups/topics: preview message + `editMessageText` + + Requirement: + + - `channels.telegram.streaming` is `off | partial | block | progress` (default: `partial`) + - `progress` maps to `partial` on Telegram (compat with cross-channel naming) + - `streaming.preview.toolProgress` controls whether tool/progress updates reuse the same edited preview message (default: `true` when preview streaming is active) + - legacy `channels.telegram.streamMode` and boolean `streaming` values are detected; run `openclaw doctor --fix` to migrate them to `channels.telegram.streaming.mode` + + Tool-progress preview updates are the short "Working..." lines shown while tools run, for example command execution, file reads, planning updates, or patch summaries. Telegram keeps these enabled by default to match released OpenClaw behavior from `v2026.4.22` and later. To keep the edited preview for answer text but hide tool-progress lines, set: + + ```json + { + "channels": { + "telegram": { + "streaming": { + "mode": "partial", + "preview": { + "toolProgress": false + } + } + } + } + } + ``` + + Use `streaming.mode: "off"` only when you want final-only delivery: Telegram preview edits are disabled and generic tool/progress chatter is suppressed instead of being sent as standalone "Working..." messages. Approval prompts, media payloads, and errors still route through normal final delivery. Use `streaming.preview.toolProgress: false` when you only want to keep answer preview edits while hiding the tool-progress status lines. + + For text-only replies: + + - 簡短的私訊/群組/主題預覽:OpenClaw 會保留相同的預覽訊息,並在原處執行最終編輯 + - 超過約一分鐘的預覽:OpenClaw 會將完成的回覆作為新的最終訊息送出,然後清理預覽,因此 Telegram 可見的時間戳會反映完成時間,而不是預覽建立時間 + + 對於複雜回覆(例如媒體 payload),OpenClaw 會退回一般最終傳遞,然後清理預覽訊息。 + + 預覽串流與區塊串流是分開的。當 Telegram 明確啟用區塊串流時,OpenClaw 會略過預覽串流,以避免雙重串流。 + + 如果原生草稿傳輸不可用/遭拒,OpenClaw 會自動退回 `sendMessage` + `editMessageText`。 + + 僅限 Telegram 的 reasoning 串流: + + - `/reasoning stream` 會在生成時將 reasoning 傳送到即時預覽 + - 最終答案會在不含 reasoning 文字的情況下送出 + + + + + 對外文字使用 Telegram `parse_mode: "HTML"`。 + + - 類似 Markdown 的文字會轉譯為 Telegram 安全的 HTML。 + - 原始模型 HTML 會被逸出,以減少 Telegram 解析失敗。 + - 如果 Telegram 拒絕已解析的 HTML,OpenClaw 會以純文字重試。 + + 連結預覽預設啟用,可透過 `channels.telegram.linkPreview: false` 停用。 + + + + + Telegram 命令選單註冊會在啟動時透過 `setMyCommands` 處理。 + + 原生命令預設值: + + - `commands.native: "auto"` 會為 Telegram 啟用原生命令 + + 新增自訂命令選單項目: + +```json5 +{ + channels: { + telegram: { + customCommands: [ + { command: "backup", description: "Git backup" }, + { command: "generate", description: "Create an image" }, + ], + }, + }, +} +``` + + 規則: + + - 名稱會正規化(移除開頭的 `/`、轉為小寫) + - 有效模式:`a-z`、`0-9`、`_`,長度 `1..32` + - 自訂命令不能覆寫原生命令 + - 衝突/重複項目會被略過並記錄 + + 注意: + + - 自訂命令只是選單項目;它們不會自動實作行為 + - plugin/skill 命令即使未顯示在 Telegram 選單中,輸入時仍可運作 + + 如果停用原生命令,內建命令會被移除。Custom/plugin 命令若已設定,仍可能註冊。 + + 常見設定失敗: + + - `setMyCommands failed` 搭配 `BOT_COMMANDS_TOO_MUCH` 表示 Telegram 選單在修剪後仍然超出限制;請減少 plugin/skill/custom 命令,或停用 `channels.telegram.commands.native`。 + - 當直接使用 Bot API curl 命令可運作,但 `deleteWebhook`、`deleteMyCommands` 或 `setMyCommands` 因 `404: Not Found` 失敗時,可能表示 `channels.telegram.apiRoot` 被設定為完整的 `/bot` 端點。`apiRoot` 必須只包含 Bot API 根路徑,而 `openclaw doctor --fix` 會移除意外尾隨的 `/bot`。 + - `getMe returned 401` 表示 Telegram 拒絕已設定的 bot token。請使用目前的 BotFather token 更新 `botToken`、`tokenFile` 或 `TELEGRAM_BOT_TOKEN`;OpenClaw 會在輪詢前停止,因此這不會被回報為 Webhook 清理失敗。 + - `setMyCommands failed` 搭配網路/fetch 錯誤,通常表示對 `api.telegram.org` 的對外 DNS/HTTPS 被封鎖。 + + ### 裝置配對命令(`device-pair` plugin) + + 安裝 `device-pair` plugin 時: + + 1. `/pair` 產生設定程式碼 + 2. 將程式碼貼到 iOS app + 3. `/pair pending` 列出待處理請求(包含角色/scopes) + 4. 核准請求: + - `/pair approve ` 用於明確核准 + - `/pair approve` 用於只有一個待處理請求時 + - `/pair approve latest` 用於最近一筆 + + 設定程式碼帶有短效 bootstrap token。內建 bootstrap 交接會將主要 node token 維持在 `scopes: []`;任何已交接的 operator token 都會限制在 `operator.approvals`、`operator.read`、`operator.talk.secrets` 和 `operator.write`。Bootstrap scope 檢查會加上角色前綴,因此該 operator allowlist 只滿足 operator 請求;非 operator 角色仍需要其自身角色前綴下的 scopes。 + + 如果裝置以變更後的驗證詳細資料重試(例如角色/scopes/公開金鑰),先前的待處理請求會被取代,新請求會使用不同的 `requestId`。核准前請重新執行 `/pair pending`。 + + 更多詳細資訊:[配對](/zh-TW/channels/pairing#pair-via-telegram-recommended-for-ios)。 + + + + + 設定行內鍵盤範圍: + +```json5 +{ + channels: { + telegram: { + capabilities: { + inlineButtons: "allowlist", + }, + }, + }, +} +``` + + 每個帳號覆寫: + +```json5 +{ + channels: { + telegram: { + accounts: { + main: { + capabilities: { + inlineButtons: "allowlist", + }, + }, + }, + }, + }, +} +``` + + 範圍: + + - `off` + - `dm` + - `group` + - `all` + - `allowlist`(預設) + + 舊版 `capabilities: ["inlineButtons"]` 會對應到 `inlineButtons: "all"`。 + + 訊息動作範例: + +```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 點擊會作為文字傳給 agent: + `callback_data: ` + + + + + Telegram 工具動作包含: + + - `sendMessage`(`to`、`content`、選用 `mediaUrl`、`replyToMessageId`、`messageThreadId`) + - `react`(`chatId`、`messageId`、`emoji`) + - `deleteMessage`(`chatId`、`messageId`) + - `editMessage`(`chatId`、`messageId`、`content`) + - `createForumTopic`(`chatId`、`name`、選用 `iconColor`、`iconCustomEmojiId`) + + 頻道訊息動作提供符合人體工學的別名(`send`、`react`、`delete`、`edit`、`sticker`、`sticker-search`、`topic-create`)。 + + Gate 控制: + + - `channels.telegram.actions.sendMessage` + - `channels.telegram.actions.deleteMessage` + - `channels.telegram.actions.reactions` + - `channels.telegram.actions.sticker`(預設:停用) + + 注意:`edit` 和 `topic-create` 目前預設啟用,且沒有個別的 `channels.telegram.actions.*` 切換。 + Runtime 傳送會使用作用中的 config/secrets 快照(啟動/重新載入),因此動作路徑不會在每次傳送時執行臨時 SecretRef 重新解析。 + + 反應移除語意:[/tools/reactions](/zh-TW/tools/reactions) + + + + + Telegram 支援在生成輸出中使用明確的回覆 threading 標籤: + + - `[[reply_to_current]]` 回覆觸發訊息 + - `[[reply_to:]]` 回覆特定 Telegram 訊息 ID + + `channels.telegram.replyToMode` 控制處理方式: + + - `off`(預設) + - `first` + - `all` + + 啟用回覆 threading 且原始 Telegram 文字或 caption 可用時,OpenClaw 會自動包含原生 Telegram 引言摘錄。Telegram 將原生引言文字限制為 1024 個 UTF-16 code units,因此較長訊息會從開頭開始引用,若 Telegram 拒絕引言,則退回純回覆。 + + 注意:`off` 會停用隱含回覆 threading。明確的 `[[reply_to_*]]` 標籤仍會被遵循。 + + + + + 論壇 supergroups: + + - 主題 session keys 會附加 `:topic:` + - 回覆與 typing 會以主題 thread 為目標 + - 主題 config 路徑: + `channels.telegram.groups..topics.` + + 一般主題(`threadId=1`)特殊情況: + + - 訊息傳送會省略 `message_thread_id`(Telegram 會拒絕 `sendMessage(...thread_id=1)`) + - typing 動作仍會包含 `message_thread_id` + + 主題繼承:主題項目會繼承群組設定,除非已覆寫(`requireMention`、`allowFrom`、`skills`、`systemPrompt`、`enabled`、`groupPolicy`)。 + `agentId` 只屬於主題,不會從群組預設值繼承。 + + **每個主題的 agent 路由**:每個主題都可以透過在主題 config 中設定 `agentId` 路由到不同的 agent。這讓每個主題都有自己的隔離工作區、記憶體和 session。範例: + + ```json5 + { + channels: { + telegram: { + groups: { + "-1001234567890": { + topics: { + "1": { agentId: "main" }, // General topic → main agent + "3": { agentId: "zu" }, // Dev topic → zu agent + "5": { agentId: "coder" } // Code review → coder agent + } + } + } + } + } + } + ``` + + 接著每個主題都有自己的 session key:`agent:zu:telegram:group:-1001234567890:topic:3` + + **持久 ACP 主題綁定**:論壇主題可透過頂層 typed ACP bindings(`bindings[]` 搭配 `type: "acp"`、`match.channel: "telegram"`、`peer.kind: "group"`,以及類似 `-1001234567890:topic:42` 的主題限定 id)釘選 ACP harness sessions。目前範圍限於 groups/supergroups 中的論壇主題。請參閱 [ACP Agents](/zh-TW/tools/acp-agents)。 + + **從聊天室產生 thread-bound ACP**:`/acp spawn --thread here|auto` 會將目前主題綁定到新的 ACP session;後續訊息會直接路由至該處。OpenClaw 會將 spawn 確認釘選在主題內。需要 `channels.telegram.threadBindings.spawnAcpSessions=true`。 + + Template context 會公開 `MessageThreadId` 和 `IsForum`。帶有 `message_thread_id` 的私訊聊天室會保留私訊路由,但使用 thread-aware session keys。 + + + + + ### 音訊訊息 + + Telegram 會區分語音備忘 vs 音訊檔案。 + + - 預設:音訊檔案行為 + - 在 agent 回覆中加入標籤 `[[audio_as_voice]]` 以強制作為語音備忘傳送 + - 內送語音備忘逐字稿會在 agent context 中被標示為機器生成、 + 不受信任的文字;提及偵測仍會使用原始 + 逐字稿,因此受提及 gate 控制的語音訊息仍可運作。 + + 訊息動作範例: + +```json5 +{ + action: "send", + channel: "telegram", + to: "123456789", + media: "https://example.com/voice.ogg", + asVoice: true, +} +``` + + ### 影片訊息 + + Telegram 會區分影片檔案 vs 影片備忘。 + + 訊息動作範例: + +```json5 +{ + action: "send", + channel: "telegram", + to: "123456789", + media: "https://example.com/video.mp4", + asVideoNote: true, +} +``` + + 影片備忘不支援 caption;提供的訊息文字會另行傳送。 + + ### 貼圖 + + 內送貼圖處理: + + - 靜態 WEBP:下載並處理(placeholder ``) + - 動畫 TGS:略過 + - 影片 WEBM:略過 + + 貼圖 context 欄位: + + - `Sticker.emoji` + - `Sticker.setName` + - `Sticker.fileId` + - `Sticker.fileUniqueId` + - `Sticker.cachedDescription` + + 貼圖快取檔案: + + - `~/.openclaw/telegram/sticker-cache.json` + + 貼圖會被描述一次(可行時)並快取,以減少重複的視覺呼叫。 + + 啟用貼圖動作: + +```json5 +{ + channels: { + telegram: { + actions: { + sticker: true, + }, + }, + }, +} +``` + + 傳送貼圖動作: + +```json5 +{ + action: "sticker", + channel: "telegram", + to: "123456789", + fileId: "CAACAgIAAxkBAAI...", +} +``` + + 搜尋快取的貼圖: + +```json5 +{ + action: "sticker-search", + channel: "telegram", + query: "cat waving", + limit: 5, +} +``` + + + + + Telegram 反應會以 `message_reaction` updates 抵達(與訊息 payloads 分開)。 + + 啟用後,OpenClaw 會將如下系統事件排入佇列: + + - `Telegram reaction added: 👍 by Alice (@alice) on msg 42` + + Config: + + - `channels.telegram.reactionNotifications`: `off | own | all`(預設:`own`) + - `channels.telegram.reactionLevel`: `off | ack | minimal | extensive`(預設:`minimal`) + + 備註: + + - `own` 表示僅限使用者對機器人傳送訊息的反應(透過已傳送訊息快取盡力處理)。 + - 反應事件仍會遵守 Telegram 存取控制(`dmPolicy`、`allowFrom`、`groupPolicy`、`groupAllowFrom`);未授權的傳送者會被丟棄。 + - Telegram 不會在反應更新中提供對話串 ID。 + - 非論壇群組會路由到群組聊天工作階段 + - 論壇群組會路由到群組的一般主題工作階段(`:topic:1`),而不是確切的原始主題 + + 輪詢/Webhook 的 `allowed_updates` 會自動包含 `message_reaction`。 + + + + + `ackReaction` 會在 OpenClaw 處理傳入訊息時傳送確認表情符號。 + + 解析順序: + + - `channels.telegram.accounts..ackReaction` + - `channels.telegram.ackReaction` + - `messages.ackReaction` + - agent 身分表情符號後援(`agents.list[].identity.emoji`,否則為「👀」) + + 備註: + + - Telegram 預期使用 unicode 表情符號(例如「👀」)。 + - 使用 `""` 可停用某個頻道或帳號的反應。 + + + + + 頻道設定寫入預設啟用(`configWrites !== false`)。 + + Telegram 觸發的寫入包含: + + - 群組遷移事件(`migrate_to_chat_id`),用於更新 `channels.telegram.groups` + - `/config set` 和 `/config unset`(需要啟用命令) + + 停用: + +```json5 +{ + channels: { + telegram: { + configWrites: false, + }, + }, +} +``` + + + + + 預設為長輪詢。若要使用 Webhook 模式,請設定 `channels.telegram.webhookUrl` 和 `channels.telegram.webhookSecret`;可選擇設定 `webhookPath`、`webhookHost`、`webhookPort`(預設為 `/telegram-webhook`、`127.0.0.1`、`8787`)。 + + 本機監聽器會繫結到 `127.0.0.1:8787`。若要使用公開入口,請在本機連接埠前方放置反向代理,或有意地設定 `webhookHost: "0.0.0.0"`。 + + Webhook 模式會先驗證請求防護、Telegram 密鑰權杖和 JSON 本文,才向 Telegram 回傳 `200`。 + OpenClaw 接著會透過與長輪詢相同的每聊天/每主題機器人通道非同步處理更新,因此緩慢的 agent 回合不會卡住 Telegram 的傳遞 ACK。 + + + + + - `channels.telegram.textChunkLimit` 預設為 4000。 + - `channels.telegram.chunkMode="newline"` 會在依長度分割前優先使用段落邊界(空白行)。 + - `channels.telegram.mediaMaxMb`(預設 100)會限制傳入和傳出的 Telegram 媒體大小。 + - `channels.telegram.timeoutSeconds` 會覆寫 Telegram API 用戶端逾時(若未設定,則套用 grammY 預設值)。 + - `channels.telegram.pollingStallThresholdMs` 預設為 `120000`;只有在輪詢停滯重新啟動出現誤判時,才在 `30000` 到 `600000` 之間調整。 + - 群組上下文歷史記錄使用 `channels.telegram.historyLimit` 或 `messages.groupChat.historyLimit`(預設 50);`0` 會停用。 + - 回覆/引用/轉寄的補充上下文目前會依收到的內容傳遞。 + - Telegram 允許清單主要管控誰可以觸發 agent,而不是完整的補充上下文遮蔽邊界。 + - 私訊歷史記錄控制: + - `channels.telegram.dmHistoryLimit` + - `channels.telegram.dms[""].historyLimit` + - `channels.telegram.retry` 設定會套用到 Telegram 傳送輔助工具(CLI/工具/動作),用於可復原的傳出 API 錯誤。傳入最終回覆傳遞也會針對 Telegram 預連線失敗使用有界限的安全傳送重試,但不會重試可能造成可見訊息重複的不明確傳送後網路封包。 + + CLI 傳送目標可以是數值聊天 ID 或使用者名稱: + +```bash +openclaw message send --channel telegram --target 123456789 --message "hi" +openclaw message send --channel telegram --target @name --message "hi" +``` + + Telegram 投票使用 `openclaw message poll`,並支援論壇主題: + +```bash +openclaw message poll --channel telegram --target 123456789 \ + --poll-question "Ship it?" --poll-option "Yes" --poll-option "No" +openclaw message poll --channel telegram --target -1001234567890:topic:42 \ + --poll-question "Pick a time" --poll-option "10am" --poll-option "2pm" \ + --poll-duration-seconds 300 --poll-public +``` + + 僅限 Telegram 的投票旗標: + + - `--poll-duration-seconds`(5-600) + - `--poll-anonymous` + - `--poll-public` + - `--thread-id` 用於論壇主題(或使用 `:topic:` 目標) + + Telegram 傳送也支援: + + - 當 `channels.telegram.capabilities.inlineButtons` 允許時,搭配 `buttons` 區塊的 `--presentation` 可用於行內鍵盤 + - `--pin` 或 `--delivery '{"pin":true}'` 可在機器人能於該聊天中釘選時要求釘選傳遞 + - `--force-document` 會將傳出圖片和 GIF 作為文件傳送,而不是使用壓縮相片或動畫媒體上傳 + + 動作管控: + + - `channels.telegram.actions.sendMessage=false` 會停用傳出的 Telegram 訊息,包括投票 + - `channels.telegram.actions.poll=false` 會停用 Telegram 投票建立,同時保留一般傳送啟用 + + + + + Telegram 支援在核准者私訊中進行執行核准,也可以選擇在原始聊天或主題中發布提示。核准者必須是數值 Telegram 使用者 ID。 + + 設定路徑: + + - `channels.telegram.execApprovals.enabled`(至少可解析一位核准者時會自動啟用) + - `channels.telegram.execApprovals.approvers`(後援為 `commands.ownerAllowFrom` 中的數值擁有者 ID) + - `channels.telegram.execApprovals.target`: `dm`(預設)| `channel` | `both` + - `agentFilter`, `sessionFilter` + + `channels.telegram.allowFrom`、`groupAllowFrom` 和 `defaultTo` 控制誰可以和機器人對話,以及機器人將一般回覆傳送到哪裡。它們不會讓某人成為執行核准者。當尚未存在命令擁有者時,第一個核准的私訊配對會啟動 `commands.ownerAllowFrom`,因此單一擁有者設定仍可運作,而不必在 `execApprovals.approvers` 下重複 ID。 + + 頻道傳遞會在聊天中顯示命令文字;只有在受信任的群組/主題中才啟用 `channel` 或 `both`。當提示出現在論壇主題中時,OpenClaw 會為核准提示和後續訊息保留該主題。執行核准預設會在 30 分鐘後過期。 + + 行內核准按鈕也需要 `channels.telegram.capabilities.inlineButtons` 允許目標介面(`dm`、`group` 或 `all`)。以 `plugin:` 為前綴的核准 ID 會透過 Plugin 核准解析;其他 ID 會先透過執行核准解析。 + + 請參閱[執行核准](/zh-TW/tools/exec-approvals)。 + + + + +## 錯誤回覆控制 + +當 agent 遇到傳遞或提供者錯誤時,Telegram 可以回覆錯誤文字,或隱藏錯誤。這個行為由兩個設定鍵控制: + +| 鍵 | 值 | 預設值 | 說明 | +| ----------------------------------- | ----------------- | ------- | ----------------------------------------------------------------------------------------------- | +| `channels.telegram.errorPolicy` | `reply`, `silent` | `reply` | `reply` 會向聊天傳送友善的錯誤訊息。`silent` 會完全隱藏錯誤回覆。 | +| `channels.telegram.errorCooldownMs` | number (ms) | `60000` | 對同一聊天傳送錯誤回覆之間的最短時間。可防止中斷期間出現錯誤垃圾訊息。 | + +支援每帳號、每群組和每主題覆寫(繼承方式與其他 Telegram 設定鍵相同)。 + +```json5 +{ + channels: { + telegram: { + errorPolicy: "reply", + errorCooldownMs: 120000, + groups: { + "-1001234567890": { + errorPolicy: "silent", // suppress errors in this group + }, + }, + }, + }, +} +``` + +## 疑難排解 + + + + + - 如果 `requireMention=false`,Telegram 隱私模式必須允許完整可見性。 + - BotFather:`/setprivacy` -> Disable + - 然後移除機器人並重新加入群組 + - 當設定預期未提及的群組訊息時,`openclaw channels status` 會發出警告。 + - `openclaw channels status --probe` 可以檢查明確的數值群組 ID;萬用字元 `"*"` 無法探測成員資格。 + - 快速工作階段測試:`/activation always`。 + + + + + + - 當 `channels.telegram.groups` 存在時,群組必須列在其中(或包含 `"*"`) + - 驗證機器人在群組中的成員資格 + - 檢閱記錄:使用 `openclaw logs --follow` 查看略過原因 + + + + + + - 授權你的傳送者身分(配對和/或數值 `allowFrom`) + - 即使群組政策是 `open`,命令授權仍會套用 + - `setMyCommands failed` 且出現 `BOT_COMMANDS_TOO_MUCH` 表示原生命令選單有太多項目;請減少 Plugin/skill/自訂命令,或停用原生選單 + - `deleteMyCommands` / `setMyCommands` 啟動呼叫有界限,且在請求逾時時會透過 Telegram 的傳輸後援重試一次。持續性的網路/擷取錯誤通常表示對 `api.telegram.org` 的 DNS/HTTPS 可達性問題 + + + + + + - `getMe returned 401` 是已設定機器人權杖的 Telegram 驗證失敗。 + - 在 BotFather 中重新複製或重新產生機器人權杖,然後更新預設帳號的 `channels.telegram.botToken`、`channels.telegram.tokenFile`、`channels.telegram.accounts..botToken` 或 `TELEGRAM_BOT_TOKEN`。 + - 啟動期間的 `deleteWebhook 401 Unauthorized` 也是驗證失敗;將其視為「不存在 Webhook」只會把同一個錯誤權杖失敗延後到後續 API 呼叫。 + - 如果 `deleteWebhook` 在輪詢啟動期間因暫時性網路錯誤而失敗,OpenClaw 會檢查 `getWebhookInfo`;當 Telegram 回報空的 Webhook URL 時,輪詢會繼續,因為清理已經滿足。 + + + + + + - Node 22+ + 自訂 fetch/proxy 可能會在 AbortSignal 型別不相符時觸發立即中止行為。 + - 有些主機會先將 `api.telegram.org` 解析為 IPv6;損壞的 IPv6 對外連線可能導致間歇性的 Telegram API 失敗。 + - 如果日誌包含 `TypeError: fetch failed` 或 `Network request for 'getUpdates' failed!`,OpenClaw 現在會將這些作為可復原的網路錯誤重試。 + - 如果日誌包含 `Polling stall detected`,OpenClaw 預設會在 120 秒內沒有完成長輪詢活性後,重新啟動輪詢並重建 Telegram 傳輸。 + - `openclaw channels status --probe` 和 `openclaw doctor` 會在執行中的輪詢帳戶於啟動寬限期後尚未完成 `getUpdates`、執行中的 webhook 帳戶於啟動寬限期後尚未完成 `setWebhook`,或最後一次成功的輪詢傳輸活動已過舊時發出警告。 + - 只有在長時間執行的 `getUpdates` 呼叫正常,但你的主機仍回報錯誤的輪詢停滯重新啟動時,才增加 `channels.telegram.pollingStallThresholdMs`。持續停滯通常表示主機與 `api.telegram.org` 之間存在 proxy、DNS、IPv6 或 TLS 對外連線問題。 + - Telegram 也會遵循 Bot API 傳輸的程序 proxy 環境變數,包括 `HTTP_PROXY`、`HTTPS_PROXY`、`ALL_PROXY` 以及它們的小寫變體。`NO_PROXY` / `no_proxy` 仍可繞過 `api.telegram.org`。 + - 如果服務環境透過 `OPENCLAW_PROXY_URL` 設定了 OpenClaw 受管 proxy,且沒有標準 proxy 環境變數,Telegram 也會將該 URL 用於 Bot API 傳輸。 + - 在直接對外連線/TLS 不穩定的 VPS 主機上,請透過 `channels.telegram.proxy` 路由 Telegram API 呼叫: + +```yaml +channels: + telegram: + proxy: socks5://:@proxy-host:1080 +``` + + - Node 22+ 預設為 `autoSelectFamily=true`(WSL2 除外)和 `dnsResultOrder=ipv4first`。 + - 如果你的主機是 WSL2,或明確以僅 IPv4 行為運作得更好,請強制指定位址族選擇: + +```yaml +channels: + telegram: + network: + autoSelectFamily: false +``` + + - RFC 2544 基準測試範圍的答案(`198.18.0.0/15`)預設已允許 + 用於 Telegram 媒體下載。如果受信任的 fake-IP 或 + 透明 proxy 在媒體下載期間將 `api.telegram.org` 重寫為其他 + 私有/內部/特殊用途位址,你可以選擇啟用僅限 Telegram 的繞過: + +```yaml +channels: + telegram: + network: + dangerouslyAllowPrivateNetwork: true +``` + + - 同樣的選擇啟用可在每個帳戶層級透過 + `channels.telegram.accounts..network.dangerouslyAllowPrivateNetwork` 使用。 + - 如果你的 proxy 將 Telegram 媒體主機解析為 `198.18.x.x`,請先保持 + 危險旗標關閉。Telegram 媒體預設已允許 RFC 2544 + 基準測試範圍。 + + + `channels.telegram.network.dangerouslyAllowPrivateNetwork` 會削弱 Telegram + 媒體 SSRF 防護。僅在受信任、由操作者控制的 proxy + 環境中使用,例如 Clash、Mihomo 或 Surge fake-IP 路由,且它們 + 會合成 RFC 2544 基準測試 + 範圍之外的私有或特殊用途答案。一般公開網際網路 Telegram 存取請保持關閉。 + + + - 環境覆寫(暫時): + - `OPENCLAW_TELEGRAM_DISABLE_AUTO_SELECT_FAMILY=1` + - `OPENCLAW_TELEGRAM_ENABLE_AUTO_SELECT_FAMILY=1` + - `OPENCLAW_TELEGRAM_DNS_RESULT_ORDER=ipv4first` + - 驗證 DNS 答案: + +```bash +dig +short api.telegram.org A +dig +short api.telegram.org AAAA +``` + + + + +更多協助:[Channel 疑難排解](/zh-TW/channels/troubleshooting)。 + +## 設定參考 + +主要參考:[設定參考 - Telegram](/zh-TW/gateway/config-channels#telegram)。 + + + +- 啟動/驗證:`enabled`、`botToken`、`tokenFile`、`accounts.*`(`tokenFile` 必須指向一般檔案;符號連結會被拒絕) +- 存取控制:`dmPolicy`、`allowFrom`、`groupPolicy`、`groupAllowFrom`、`groups`、`groups.*.topics.*`、頂層 `bindings[]`(`type: "acp"`) +- exec 核准:`execApprovals`、`accounts.*.execApprovals` +- 指令/選單:`commands.native`、`commands.nativeSkills`、`customCommands` +- 執行緒/回覆:`replyToMode` +- 串流:`streaming`(預覽)、`streaming.preview.toolProgress`、`blockStreaming` +- 格式化/傳遞:`textChunkLimit`、`chunkMode`、`linkPreview`、`responsePrefix` +- 媒體/網路:`mediaMaxMb`、`timeoutSeconds`、`pollingStallThresholdMs`、`retry`、`network.autoSelectFamily`、`network.dangerouslyAllowPrivateNetwork`、`proxy` +- 自訂 API 根目錄:`apiRoot`(僅 Bot API 根目錄;不要包含 `/bot`) +- Webhook:`webhookUrl`、`webhookSecret`、`webhookPath`、`webhookHost` +- 動作/能力:`capabilities.inlineButtons`、`actions.sendMessage|editMessage|deleteMessage|reactions|sticker` +- 回應:`reactionNotifications`、`reactionLevel` +- 錯誤:`errorPolicy`、`errorCooldownMs` +- 寫入/歷史記錄:`configWrites`、`historyLimit`、`dmHistoryLimit`、`dms.*.historyLimit` + + + + +多帳戶優先順序:設定兩個或更多帳戶 ID 時,請設定 `channels.telegram.defaultAccount`(或包含 `channels.telegram.accounts.default`),以明確指定預設路由。否則 OpenClaw 會退回到第一個正規化的帳戶 ID,且 `openclaw doctor` 會發出警告。命名帳戶會繼承 `channels.telegram.allowFrom` / `groupAllowFrom`,但不會繼承 `accounts.default.*` 值。 + + +## 相關 + + + + 將 Telegram 使用者與 Gateway 配對。 + + + 群組與主題允許清單行為。 + + + 將傳入訊息路由到代理。 + + + 威脅模型與強化。 + + + 將群組與主題對應到代理。 + + + 跨 Channel 診斷。 + + diff --git a/docs/zh-TW/channels/tlon.md b/docs/zh-TW/channels/tlon.md new file mode 100644 index 000000000..e4604474f --- /dev/null +++ b/docs/zh-TW/channels/tlon.md @@ -0,0 +1,298 @@ +--- +read_when: + - 正在開發 Tlon/Urbit 頻道功能 +summary: Tlon/Urbit 支援狀態、功能與設定 +title: Tlon +x-i18n: + generated_at: "2026-04-30T02:49:23Z" + model: gpt-5.5 + provider: openai + source_hash: bec632f946796a0ea4bceb5ad26f1ff1825c4304bf7252e9d2fd4d3889d36b52 + source_path: channels/tlon.md + workflow: 16 +--- + +Tlon 是建構於 Urbit 之上的去中心化通訊軟體。OpenClaw 會連線到你的 Urbit ship,並可 +回應私訊和群組聊天室訊息。群組回覆預設需要 @ 提及,且可 +透過允許清單進一步限制。 + +狀態:隨附 Plugin。支援私訊、群組提及、討論串回覆、富文字格式,以及 +圖片上傳。尚不支援反應和投票。 + +## 隨附 Plugin + +Tlon 在目前的 OpenClaw 版本中作為隨附 Plugin 提供,因此一般封裝 +建置不需要另外安裝。 + +如果你使用的是較舊的建置,或排除 Tlon 的自訂安裝,請在發布 +目前的 npm 套件後安裝它: + +透過 CLI 安裝(npm registry,在目前套件存在時): + +```bash +openclaw plugins install @openclaw/tlon +``` + +如果 npm 回報 OpenClaw 擁有的套件已淘汰,請使用目前封裝的 +OpenClaw 建置,或在較新的 npm 套件發布前使用本機 checkout 路徑。 + +本機 checkout(從 git repo 執行時): + +```bash +openclaw plugins install ./path/to/local/tlon-plugin +``` + +詳細資訊:[Plugins](/zh-TW/tools/plugin) + +## 設定 + +1. 確認 Tlon Plugin 可用。 + - 目前封裝的 OpenClaw 版本已隨附它。 + - 較舊/自訂安裝可使用上述命令手動加入。 +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", + ownerShip: "~your-main-ship", // recommended: your ship, always allowed + }, + }, +} +``` + +## 私有/LAN ships + +OpenClaw 預設會封鎖私有/內部主機名稱和 IP 範圍,以提供 SSRF 防護。 +如果你的 ship 在私有網路上執行(localhost、LAN IP 或內部主機名稱), +你必須明確選擇啟用: + +```json5 +{ + channels: { + tlon: { + url: "http://localhost:8080", + allowPrivateNetwork: true, + }, + }, +} +``` + +這適用於下列 URL: + +- `http://localhost:8080` +- `http://192.168.x.x:8080` +- `http://my-ship.local:8080` + +⚠️ 只有在你信任本機網路時才啟用此設定。此設定會停用 +對你的 ship URL 發出請求時的 SSRF 防護。 + +## 群組頻道 + +預設啟用自動探索。你也可以手動固定頻道: + +```json5 +{ + channels: { + tlon: { + groupChannels: ["chat/~host-ship/general", "chat/~host-ship/support"], + }, + }, +} +``` + +停用自動探索: + +```json5 +{ + channels: { + tlon: { + autoDiscoverChannels: false, + }, + }, +} +``` + +## 存取控制 + +私訊允許清單(空白 = 不允許私訊,使用 `ownerShip` 進行核准流程): + +```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", + }, + }, + }, + }, + }, +} +``` + +## 擁有者與核准系統 + +設定擁有者 ship,在未授權使用者嘗試互動時接收核准請求: + +```json5 +{ + channels: { + tlon: { + ownerShip: "~your-main-ship", + }, + }, +} +``` + +擁有者 ship 會**自動在所有地方獲得授權**——私訊邀請會自動接受, +頻道訊息也一律允許。你不需要將擁有者加入 `dmAllowlist` 或 +`defaultAuthorizedShips`。 + +設定後,擁有者會收到下列私訊通知: + +- 來自不在允許清單中 ship 的私訊請求 +- 未經授權頻道中的提及 +- 群組邀請請求 + +## 自動接受設定 + +自動接受私訊邀請(適用於 dmAllowlist 中的 ships): + +```json5 +{ + channels: { + tlon: { + autoAcceptDmInvites: true, + }, + }, +} +``` + +自動接受群組邀請: + +```json5 +{ + channels: { + tlon: { + autoAcceptGroupInvites: true, + }, + }, +} +``` + +## 傳遞目標(CLI/Cron) + +搭配 `openclaw message send` 或 Cron 傳遞使用這些目標: + +- 私訊:`~sampel-palnet` 或 `dm/~sampel-palnet` +- 群組:`chat/~host-ship/channel` 或 `group:~host-ship/channel` + +## 隨附 Skills + +Tlon Plugin 包含隨附的 Skills([`@tloncorp/tlon-skill`](https://github.com/tloncorp/tlon-skill)), +可提供 Tlon 操作的 CLI 存取: + +- **聯絡人**:取得/更新個人檔案、列出聯絡人 +- **頻道**:列出、建立、張貼訊息、擷取歷程 +- **群組**:列出、建立、管理成員 +- **私訊**:傳送訊息、對訊息加入反應 +- **反應**:對貼文和私訊新增/移除 emoji 反應 +- **設定**:透過 slash commands 管理 Plugin 權限 + +安裝 Plugin 後,該 Skills 會自動可用。 + +## 功能 + +| 功能 | 狀態 | +| --------------- | --------------------------------------- | +| 直接訊息 | ✅ 支援 | +| 群組/頻道 | ✅ 支援(預設需要提及) | +| 討論串 | ✅ 支援(在討論串中自動回覆) | +| 富文字 | ✅ Markdown 會轉換為 Tlon 格式 | +| 圖片 | ✅ 上傳到 Tlon 儲存空間 | +| 反應 | ✅ 透過[隨附 Skills](#bundled-skill) | +| 投票 | ❌ 尚不支援 | +| 原生命令 | ✅ 支援(預設僅擁有者) | + +## 疑難排解 + +先執行這個階梯: + +```bash +openclaw status +openclaw gateway status +openclaw logs --follow +openclaw doctor +``` + +常見失敗: + +- **私訊被忽略**:寄件者不在 `dmAllowlist` 中,且未設定 `ownerShip` 以供核准流程使用。 +- **群組訊息被忽略**:頻道未被探索到,或寄件者未獲授權。 +- **連線錯誤**:檢查 ship URL 是否可連線;對本機 ships 啟用 `allowPrivateNetwork`。 +- **驗證錯誤**:確認登入代碼是目前有效的(代碼會輪替)。 + +## 設定參考 + +完整設定:[設定](/zh-TW/gateway/configuration) + +提供者選項: + +- `channels.tlon.enabled`:啟用/停用頻道啟動。 +- `channels.tlon.ship`:機器人的 Urbit ship 名稱(例如 `~sampel-palnet`)。 +- `channels.tlon.url`:ship URL(例如 `https://sampel-palnet.tlon.network`)。 +- `channels.tlon.code`:ship 登入代碼。 +- `channels.tlon.allowPrivateNetwork`:允許 localhost/LAN URL(SSRF 繞過)。 +- `channels.tlon.ownerShip`:核准系統的擁有者 ship(一律獲授權)。 +- `channels.tlon.dmAllowlist`:允許私訊的 ships(空白 = 無)。 +- `channels.tlon.autoAcceptDmInvites`:自動接受來自允許清單中 ships 的私訊。 +- `channels.tlon.autoAcceptGroupInvites`:自動接受所有群組邀請。 +- `channels.tlon.autoDiscoverChannels`:自動探索群組頻道(預設:true)。 +- `channels.tlon.groupChannels`:手動固定的頻道 nests。 +- `channels.tlon.defaultAuthorizedShips`:對所有頻道都獲授權的 ships。 +- `channels.tlon.authorization.channelRules`:每個頻道的驗證規則。 +- `channels.tlon.showModelSignature`:在訊息後附加模型名稱。 + +## 備註 + +- 群組回覆需要提及(例如 `~your-bot-ship`)才會回應。 +- 討論串回覆:如果傳入訊息位於討論串中,OpenClaw 會在討論串內回覆。 +- 富文字:Markdown 格式(粗體、斜體、程式碼、標題、清單)會轉換為 Tlon 的原生格式。 +- 圖片:URL 會上傳到 Tlon 儲存空間,並嵌入為圖片區塊。 + +## 相關 + +- [頻道概觀](/zh-TW/channels) — 所有支援的頻道 +- [配對](/zh-TW/channels/pairing) — 私訊驗證與配對流程 +- [群組](/zh-TW/channels/groups) — 群組聊天室行為與提及閘控 +- [頻道路由](/zh-TW/channels/channel-routing) — 訊息的 session 路由 +- [安全性](/zh-TW/gateway/security) — 存取模型與強化措施 diff --git a/docs/zh-TW/channels/troubleshooting.md b/docs/zh-TW/channels/troubleshooting.md new file mode 100644 index 000000000..3d8d0a060 --- /dev/null +++ b/docs/zh-TW/channels/troubleshooting.md @@ -0,0 +1,148 @@ +--- +read_when: + - 通道傳輸顯示已連線,但回覆失敗 + - 深入查閱提供者文件前,需要頻道特定檢查 +summary: 快速通道層級疑難排解,包含各通道的失敗特徵與修復方式 +title: 通道疑難排解 +x-i18n: + generated_at: "2026-04-30T02:50:00Z" + model: gpt-5.5 + provider: openai + source_hash: 6024f2ae0a058b2296758c237c912a5cd8ea6bbafea33cc201690cc081efcbee + source_path: channels/troubleshooting.md + workflow: 16 +--- + +當通道已連線但行為不正確時,請使用此頁面。 + +## 命令階梯 + +先依序執行這些命令: + +```bash +openclaw status +openclaw gateway status +openclaw logs --follow +openclaw doctor +openclaw channels status --probe +``` + +健康基準: + +- `Runtime: running` +- `Connectivity probe: ok` +- `Capability: read-only`、`write-capable` 或 `admin-capable` +- 通道探測顯示傳輸已連線,且在支援的情況下顯示 `works` 或 `audit ok` + +## WhatsApp + +### WhatsApp 失敗特徵 + +| 症狀 | 最快檢查 | 修正 | +| ------------------------------- | --------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- | +| 已連線但沒有私人訊息回覆 | `openclaw pairing list whatsapp` | 核准寄件者,或切換私人訊息政策/允許清單。 | +| 群組訊息被忽略 | 檢查設定中的 `requireMention` + 提及模式 | 提及機器人,或放寬該群組的提及政策。 | +| QR 登入因 408 而逾時 | 檢查 Gateway 的 `HTTPS_PROXY` / `HTTP_PROXY` 環境變數 | 設定可連線的 Proxy;僅將 `NO_PROXY` 用於略過連線。 | +| 隨機斷線/重新登入迴圈 | `openclaw channels status --probe` + 日誌 | 即使目前已連線,最近重新連線也會被標記;監看日誌、重新啟動 Gateway,若持續不穩再重新連結。 | + +完整疑難排解:[WhatsApp 疑難排解](/zh-TW/channels/whatsapp#troubleshooting) + +## Telegram + +### Telegram 失敗特徵 + +| 症狀 | 最快檢查 | 修正 | +| ------------------------------------ | ------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------- | +| `/start` 但沒有可用的回覆流程 | `openclaw pairing list telegram` | 核准配對或變更私人訊息政策。 | +| 機器人在線上但群組保持沉默 | 驗證提及要求與機器人隱私模式 | 停用隱私模式以允許群組可見,或提及機器人。 | +| 傳送因網路錯誤而失敗 | 檢查日誌中的 Telegram API 呼叫失敗 | 修正到 `api.telegram.org` 的 DNS/IPv6/Proxy 路由。 | +| 啟動回報 `getMe returned 401` | 檢查設定的 Token 來源 | 重新複製或重新產生 BotFather Token,並更新 `botToken`、`tokenFile` 或預設帳號的 `TELEGRAM_BOT_TOKEN`。 | +| 輪詢停滯或重新連線緩慢 | 使用 `openclaw logs --follow` 檢查輪詢診斷 | 升級;若重新啟動是誤判,請調整 `pollingStallThresholdMs`。持續停滯仍表示 Proxy/DNS/IPv6 有問題。 | +| 啟動時 `setMyCommands` 被拒絕 | 檢查日誌中的 `BOT_COMMANDS_TOO_MUCH` | 減少 Plugin/skill/自訂 Telegram 命令,或停用原生選單。 | +| 升級後允許清單封鎖了你 | `openclaw security audit` 和設定允許清單 | 執行 `openclaw doctor --fix`,或將 `@username` 替換為數字寄件者 ID。 | + +完整疑難排解:[Telegram 疑難排解](/zh-TW/channels/telegram#troubleshooting) + +## Discord + +### Discord 失敗特徵 + +| 症狀 | 最快檢查 | 修正 | +| ------------------------------- | ----------------------------------- | ---------------------------------------------------------- | +| 機器人在線上但沒有伺服器回覆 | `openclaw channels status --probe` | 允許伺服器/頻道,並驗證訊息內容 Intent。 | +| 群組訊息被忽略 | 檢查日誌中的提及閘控丟棄 | 提及機器人,或設定伺服器/頻道 `requireMention: false`。 | +| 私人訊息回覆遺失 | `openclaw pairing list discord` | 核准私人訊息配對或調整私人訊息政策。 | + +完整疑難排解:[Discord 疑難排解](/zh-TW/channels/discord#troubleshooting) + +## Slack + +### Slack 失敗特徵 + +| 症狀 | 最快檢查 | 修正 | +| -------------------------------------- | ----------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- | +| Socket mode 已連線但沒有回應 | `openclaw channels status --probe` | 驗證 App Token + Bot Token 和必要 Scope;在 SecretRef 支援的設定中留意 `botTokenStatus` / `appTokenStatus = configured_unavailable`。 | +| 私人訊息被封鎖 | `openclaw pairing list slack` | 核准配對或放寬私人訊息政策。 | +| 頻道訊息被忽略 | 檢查 `groupPolicy` 和頻道允許清單 | 允許該頻道,或將政策切換為 `open`。 | + +完整疑難排解:[Slack 疑難排解](/zh-TW/channels/slack#troubleshooting) + +## iMessage 和 BlueBubbles + +### iMessage 和 BlueBubbles 失敗特徵 + +| 症狀 | 最快檢查 | 修正 | +| -------------------------------- | ----------------------------------------------------------------------- | ------------------------------------------------------ | +| 沒有傳入事件 | 驗證 Webhook/伺服器可達性與 App 權限 | 修正 Webhook URL 或 BlueBubbles 伺服器狀態。 | +| 在 macOS 上可傳送但無法接收 | 檢查 macOS 對 Messages 自動化的隱私權限 | 重新授予 TCC 權限並重新啟動通道程序。 | +| 私人訊息寄件者被封鎖 | `openclaw pairing list imessage` 或 `openclaw pairing list bluebubbles` | 核准配對或更新允許清單。 | + +完整疑難排解: + +- [iMessage 疑難排解](/zh-TW/channels/imessage#troubleshooting) +- [BlueBubbles 疑難排解](/zh-TW/channels/bluebubbles#troubleshooting) + +## Signal + +### Signal 失敗特徵 + +| 症狀 | 最快檢查 | 修正 | +| ------------------------------- | ------------------------------------------ | --------------------------------------------------------- | +| Daemon 可達但機器人沉默 | `openclaw channels status --probe` | 驗證 `signal-cli` Daemon URL/帳號和接收模式。 | +| 私人訊息被封鎖 | `openclaw pairing list signal` | 核准寄件者或調整私人訊息政策。 | +| 群組回覆未觸發 | 檢查群組允許清單和提及模式 | 新增寄件者/群組或放寬閘控。 | + +完整疑難排解:[Signal 疑難排解](/zh-TW/channels/signal#troubleshooting) + +## QQ Bot + +### QQ Bot 失敗特徵 + +| 症狀 | 最快檢查 | 修正 | +| ------------------------------- | ------------------------------------------- | --------------------------------------------------------------- | +| 機器人回覆「gone to Mars」 | 驗證設定中的 `appId` 和 `clientSecret` | 設定憑證或重新啟動 Gateway。 | +| 沒有傳入訊息 | `openclaw channels status --probe` | 在 QQ Open Platform 上驗證憑證。 | +| 語音未被轉錄 | 檢查 STT 提供者設定 | 設定 `channels.qqbot.stt` 或 `tools.media.audio`。 | +| 主動訊息未送達 | 檢查 QQ 平台互動要求 | 若近期沒有互動,QQ 可能會封鎖機器人主動發起的訊息。 | + +完整疑難排解:[QQ Bot 疑難排解](/zh-TW/channels/qqbot#troubleshooting) + +## Matrix + +### Matrix 失敗特徵 + +| 症狀 | 最快檢查 | 修正 | +| ----------------------------------- | -------------------------------------- | ------------------------------------------------------------------------- | +| 已登入但忽略房間訊息 | `openclaw channels status --probe` | 檢查 `groupPolicy`、房間允許清單與提及閘控。 | +| 私人訊息未處理 | `openclaw pairing list matrix` | 核准寄件者或調整私人訊息政策。 | +| 加密房間失敗 | `openclaw matrix verify status` | 重新驗證裝置,然後檢查 `openclaw matrix verify backup status`。 | +| 備份還原擱置/損壞 | `openclaw matrix verify backup status` | 執行 `openclaw matrix verify backup restore`,或使用復原金鑰重新執行。 | +| 交叉簽署/啟動流程看起來不正確 | `openclaw matrix verify bootstrap` | 一次修復祕密儲存、交叉簽署與備份狀態。 | + +完整設定與配置:[Matrix](/zh-TW/channels/matrix) + +## 相關 + +- [配對](/zh-TW/channels/pairing) +- [通道路由](/zh-TW/channels/channel-routing) +- [Gateway 疑難排解](/zh-TW/gateway/troubleshooting) diff --git a/docs/zh-TW/channels/twitch.md b/docs/zh-TW/channels/twitch.md new file mode 100644 index 000000000..3cc879ef5 --- /dev/null +++ b/docs/zh-TW/channels/twitch.md @@ -0,0 +1,439 @@ +--- +read_when: + - 設定 OpenClaw 的 Twitch 聊天整合 +sidebarTitle: Twitch +summary: Twitch 聊天機器人組態與設定 +title: Twitch +x-i18n: + generated_at: "2026-04-30T02:49:56Z" + model: gpt-5.5 + provider: openai + source_hash: 897079687a243c9c2ce2be63167e59f4413bbd89735fb79f03928547023bd787 + source_path: channels/twitch.md + workflow: 16 +--- + +透過 IRC 連線支援 Twitch 聊天。OpenClaw 會以 Twitch 使用者(機器人帳號)身分連線,以在頻道中接收與傳送訊息。 + +## 內建 Plugin + + +Twitch 在目前的 OpenClaw 發行版本中以內建 Plugin 提供,因此一般封裝建置不需要另外安裝。 + + +如果你使用的是較舊的建置,或是不包含 Twitch 的自訂安裝,請在新版 npm 套件發布後安裝: + + + + ```bash + openclaw plugins install @openclaw/twitch + ``` + + + ```bash + openclaw plugins install ./path/to/local/twitch-plugin + ``` + + + +如果 npm 回報 OpenClaw 擁有的套件已棄用,請使用目前封裝好的 +OpenClaw 建置,或使用本機 checkout 路徑,直到更新的 npm 套件 +發布為止。 + +詳細資訊:[Plugins](/zh-TW/tools/plugin) + +## 快速設定(初學者) + + + + 目前封裝好的 OpenClaw 發行版本已經內建它。較舊或自訂安裝可使用上方命令手動加入。 + + + 為機器人建立專用的 Twitch 帳號(或使用現有帳號)。 + + + 使用 [Twitch Token Generator](https://twitchtokengenerator.com/): + + - 選取 **Bot Token** + - 確認已選取 `chat:read` 和 `chat:write` scopes + - 複製 **Client ID** 和 **Access Token** + + + + 使用 [https://www.streamweasels.com/tools/convert-twitch-username-to-user-id/](https://www.streamweasels.com/tools/convert-twitch-username-to-user-id/) 將使用者名稱轉換為 Twitch 使用者 ID。 + + + - Env:`OPENCLAW_TWITCH_ACCESS_TOKEN=...`(僅預設帳號) + - 或 config:`channels.twitch.accessToken` + + 如果兩者都設定,config 優先(env fallback 僅適用於預設帳號)。 + + + + 使用已設定的 channel 啟動 Gateway。 + + + + +加入存取控制(`allowFrom` 或 `allowedRoles`),以防止未授權使用者觸發機器人。`requireMention` 預設為 `true`。 + + +最小設定: + +```json5 +{ + channels: { + twitch: { + enabled: true, + username: "openclaw", // Bot's Twitch account + accessToken: "oauth:abc123...", // OAuth Access Token (or use OPENCLAW_TWITCH_ACCESS_TOKEN env var) + clientId: "xyz789...", // Client ID from Token Generator + channel: "vevisk", // Which Twitch channel's chat to join (required) + allowFrom: ["123456789"], // (recommended) Your Twitch user ID only - get it from https://www.streamweasels.com/tools/convert-twitch-username-to-user-id/ + }, + }, +} +``` + +## 它是什麼 + +- 由 Gateway 擁有的 Twitch channel。 +- 決定性路由:回覆一律回到 Twitch。 +- 每個帳號都對應到隔離的 session key `agent::twitch:`。 +- `username` 是機器人的帳號(用於驗證身分),`channel` 是要加入的聊天室。 + +## 設定(詳細) + +### 產生憑證 + +使用 [Twitch Token Generator](https://twitchtokengenerator.com/): + +- 選取 **Bot Token** +- 確認已選取 `chat:read` 和 `chat:write` scopes +- 複製 **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", + }, + }, + } + ``` + + + +如果 env 和 config 都已設定,config 優先。 + +### 存取控制(建議) + +```json5 +{ + channels: { + twitch: { + allowFrom: ["123456789"], // (recommended) Your Twitch user ID only + }, + }, +} +``` + +偏好使用 `allowFrom` 作為嚴格允許清單。如果你想使用以角色為基礎的存取,請改用 `allowedRoles`。 + +**可用角色:** `"moderator"`、`"owner"`、`"vip"`、`"subscriber"`、`"all"`。 + + +**為什麼使用使用者 ID?** 使用者名稱可以變更,可能導致冒名。使用者 ID 是永久的。 + +找出你的 Twitch 使用者 ID:[https://www.streamweasels.com/tools/convert-twitch-username-to-user-id/](https://www.streamweasels.com/tools/convert-twitch-username-to-user-id/)(將你的 Twitch 使用者名稱轉換為 ID) + + +## 權杖重新整理(選用) + +來自 [Twitch Token Generator](https://twitchtokengenerator.com/) 的權杖無法自動重新整理;過期時請重新產生。 + +若要自動重新整理權杖,請在 [Twitch Developer Console](https://dev.twitch.tv/console) 建立你自己的 Twitch 應用程式,並加入 config: + +```json5 +{ + channels: { + twitch: { + clientSecret: "your_client_secret", + refreshToken: "your_refresh_token", + }, + }, +} +``` + +機器人會在過期前自動重新整理權杖,並記錄重新整理事件。 + +## 多帳號支援 + +使用 `channels.twitch.accounts` 搭配每個帳號各自的權杖。共享模式請參閱[設定](/zh-TW/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: { + allowFrom: ["123456789", "987654321"], + }, + }, + }, + }, + } + ``` + + + ```json5 + { + channels: { + twitch: { + accounts: { + default: { + allowedRoles: ["moderator", "vip"], + }, + }, + }, + }, + } + ``` + + `allowFrom` 是嚴格允許清單。設定後,只允許這些使用者 ID。如果你想使用以角色為基礎的存取,請不要設定 `allowFrom`,並改為設定 `allowedRoles`。 + + + + 預設情況下,`requireMention` 為 `true`。若要停用並回應所有訊息: + + ```json5 + { + channels: { + twitch: { + accounts: { + default: { + requireMention: false, + }, + }, + }, + }, + } + ``` + + + + +## 疑難排解 + +首先,執行診斷命令: + +```bash +openclaw doctor +openclaw channels status --probe +``` + + + + - **檢查存取控制:** 確保你的使用者 ID 位於 `allowFrom` 中,或暫時移除 `allowFrom` 並設定 `allowedRoles: ["all"]` 進行測試。 + - **檢查機器人是否在該頻道中:** 機器人必須加入 `channel` 中指定的頻道。 + + + + 「連線失敗」或驗證錯誤: + + - 確認 `accessToken` 是 OAuth access token 值(通常以 `oauth:` 前綴開頭) + - 檢查權杖具有 `chat:read` 和 `chat:write` scopes + - 如果使用權杖重新整理,請確認已設定 `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` + + + + +## Config + +### 帳號 config + + + 機器人使用者名稱。 + + + 具有 `chat:read` 和 `chat:write` 的 OAuth access token。 + + + Twitch Client ID(來自 Token Generator 或你的應用程式)。 + + + 要加入的頻道。 + + + 啟用此帳號。 + + + 選用:用於自動重新整理權杖。 + + + 選用:用於自動重新整理權杖。 + + + 權杖到期秒數。 + + + 權杖取得時間戳記。 + + + 使用者 ID 允許清單。 + + + 以角色為基礎的存取控制。 + + + 要求 @mention。 + + +### Provider 選項 + +- `channels.twitch.enabled` - 啟用/停用 channel 啟動 +- `channels.twitch.username` - 機器人使用者名稱(簡化的單帳號 config) +- `channels.twitch.accessToken` - OAuth access token(簡化的單帳號 config) +- `channels.twitch.clientId` - Twitch Client ID(簡化的單帳號 config) +- `channels.twitch.channel` - 要加入的頻道(簡化的單帳號 config) +- `channels.twitch.accounts.` - 多帳號 config(以上所有帳號欄位) + +完整範例: + +```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"], + }, + }, + }, + }, +} +``` + +## 工具動作 + +agent 可以使用動作呼叫 `twitch`: + +- `send` - 傳送訊息到頻道 + +範例: + +```json5 +{ + action: "twitch", + params: { + message: "Hello Twitch!", + to: "#mychannel", + }, +} +``` + +## 安全性與營運 + +- **將權杖視同密碼** — 絕不要將權杖提交到 git。 +- **使用自動權杖重新整理** 以支援長時間執行的機器人。 +- **使用使用者 ID 允許清單** 而不是使用者名稱來做存取控制。 +- **監控記錄** 以查看權杖重新整理事件和連線狀態。 +- **最小化權杖 scopes** — 只要求 `chat:read` 和 `chat:write`。 +- **如果卡住**:確認沒有其他程序佔用 session 後,重新啟動 Gateway。 + +## 限制 + +- 每則訊息 **500 個字元**(會在單字邊界自動分塊)。 +- Markdown 會在分塊前移除。 +- 沒有速率限制(使用 Twitch 內建的速率限制)。 + +## 相關 + +- [Channel 路由](/zh-TW/channels/channel-routing) — 訊息的 session 路由 +- [Channels 概觀](/zh-TW/channels) — 所有支援的 channels +- [群組](/zh-TW/channels/groups) — 群組聊天行為與 mention 閘控 +- [配對](/zh-TW/channels/pairing) — DM 驗證與配對流程 +- [安全性](/zh-TW/gateway/security) — 存取模型與強化 diff --git a/docs/zh-TW/channels/wechat.md b/docs/zh-TW/channels/wechat.md new file mode 100644 index 000000000..a74f6f221 --- /dev/null +++ b/docs/zh-TW/channels/wechat.md @@ -0,0 +1,155 @@ +--- +read_when: + - 您想要將 OpenClaw 連接到 WeChat 或 Weixin + - 您正在安裝或排解 openclaw-weixin 頻道 Plugin 的問題 + - 你需要了解外部頻道 Plugin 如何與 Gateway 並行執行 +summary: 透過外部 openclaw-weixin Plugin 設定 WeChat 通道 +title: WeChat +x-i18n: + generated_at: "2026-04-30T02:50:18Z" + model: gpt-5.5 + provider: openai + source_hash: ea7c815a364c2ae087041bf6de5b4182334c67377e18b9bedfa0f9d949afc09c + source_path: channels/wechat.md + workflow: 16 +--- + +OpenClaw 透過 Tencent 的外部 +`@tencent-weixin/openclaw-weixin` 頻道 Plugin 連接 WeChat。 + +狀態:外部 Plugin。支援直接聊天與媒體。目前 Plugin 能力中繼資料未宣告支援群組聊天。 + +## 命名 + +- **WeChat** 是這些文件中面向使用者的名稱。 +- **Weixin** 是 Tencent 套件與 Plugin id 使用的名稱。 +- `openclaw-weixin` 是 OpenClaw 頻道 id。 +- `@tencent-weixin/openclaw-weixin` 是 npm 套件。 + +在 CLI 指令與設定路徑中使用 `openclaw-weixin`。 + +## 運作方式 + +WeChat 程式碼不在 OpenClaw 核心 repo 中。OpenClaw 提供通用頻道 Plugin 合約,而外部 Plugin 提供 WeChat 專用 runtime: + +1. `openclaw plugins install` 安裝 `@tencent-weixin/openclaw-weixin`。 +2. Gateway 探索 Plugin manifest 並載入 Plugin entrypoint。 +3. Plugin 註冊頻道 id `openclaw-weixin`。 +4. `openclaw channels login --channel openclaw-weixin` 啟動 QR 登入。 +5. Plugin 將帳號憑證儲存在 OpenClaw 狀態目錄下。 +6. Gateway 啟動時,Plugin 會為每個已設定帳號啟動其 Weixin 監控器。 +7. 傳入的 WeChat 訊息會透過頻道合約標準化、路由到選取的 OpenClaw agent,並透過 Plugin 輸出路徑送回。 + +這種分離很重要:OpenClaw 核心應保持頻道無關。WeChat 登入、Tencent iLink API 呼叫、媒體上傳/下載、context tokens,以及帳號監控都由外部 Plugin 擁有。 + +## 安裝 + +快速安裝: + +```bash +npx -y @tencent-weixin/openclaw-weixin-cli install +``` + +手動安裝: + +```bash +openclaw plugins install "@tencent-weixin/openclaw-weixin" +openclaw config set plugins.entries.openclaw-weixin.enabled true +``` + +安裝後重新啟動 Gateway: + +```bash +openclaw gateway restart +``` + +## 登入 + +在執行 Gateway 的同一台機器上執行 QR 登入: + +```bash +openclaw channels login --channel openclaw-weixin +``` + +使用手機上的 WeChat 掃描 QR code 並確認登入。成功掃描後,Plugin 會在本機儲存帳號 token。 + +若要新增另一個 WeChat 帳號,請再次執行相同的登入指令。若有多個帳號,請依帳號、頻道與傳送者隔離直接訊息工作階段: + +```bash +openclaw config set session.dmScope per-account-channel-peer +``` + +## 存取控制 + +直接訊息會使用頻道 Plugin 的一般 OpenClaw pairing 與 allowlist 模型。 + +核准新的傳送者: + +```bash +openclaw pairing list openclaw-weixin +openclaw pairing approve openclaw-weixin +``` + +完整的存取控制模型請參閱 [Pairing](/zh-TW/channels/pairing)。 + +## 相容性 + +Plugin 會在啟動時檢查主機的 OpenClaw 版本。 + +| Plugin 線 | OpenClaw 版本 | npm tag | +| ----------- | ----------------------- | -------- | +| `2.x` | `>=2026.3.22` | `latest` | +| `1.x` | `>=2026.1.0 <2026.3.22` | `legacy` | + +如果 Plugin 回報你的 OpenClaw 版本太舊,請更新 OpenClaw,或安裝舊版 Plugin 線: + +```bash +openclaw plugins install @tencent-weixin/openclaw-weixin@legacy +``` + +## Sidecar process + +WeChat Plugin 在監控 Tencent iLink API 時,可以在 Gateway 旁執行輔助工作。在 issue #68451 中,該輔助路徑暴露了 OpenClaw 通用過時 Gateway 清理中的一個錯誤:子行程可能會嘗試清理父 Gateway 行程,導致在 systemd 等 process manager 下出現重新啟動迴圈。 + +目前 OpenClaw 啟動清理會排除目前行程及其祖先,因此頻道輔助程式不得終止啟動它的 Gateway。此修正是通用的;它不是核心中的 WeChat 專用路徑。 + +## 疑難排解 + +檢查安裝與狀態: + +```bash +openclaw plugins list +openclaw channels status --probe +openclaw --version +``` + +如果頻道顯示已安裝但沒有連線,請確認 Plugin 已啟用並重新啟動: + +```bash +openclaw config set plugins.entries.openclaw-weixin.enabled true +openclaw gateway restart +``` + +如果啟用 WeChat 後 Gateway 反覆重新啟動,請同時更新 OpenClaw 與 Plugin: + +```bash +npm view @tencent-weixin/openclaw-weixin version +openclaw plugins install "@tencent-weixin/openclaw-weixin" --force +openclaw gateway restart +``` + +暫時停用: + +```bash +openclaw config set plugins.entries.openclaw-weixin.enabled false +openclaw gateway restart +``` + +## 相關文件 + +- 頻道概覽:[Chat Channels](/zh-TW/channels) +- Pairing:[Pairing](/zh-TW/channels/pairing) +- 頻道路由:[Channel Routing](/zh-TW/channels/channel-routing) +- Plugin 架構:[Plugin Architecture](/zh-TW/plugins/architecture) +- 頻道 Plugin SDK:[Channel Plugin SDK](/zh-TW/plugins/sdk-channel-plugins) +- 外部套件:[@tencent-weixin/openclaw-weixin](https://www.npmjs.com/package/@tencent-weixin/openclaw-weixin) diff --git a/docs/zh-TW/channels/whatsapp.md b/docs/zh-TW/channels/whatsapp.md new file mode 100644 index 000000000..79b473255 --- /dev/null +++ b/docs/zh-TW/channels/whatsapp.md @@ -0,0 +1,681 @@ +--- +read_when: + - 處理 WhatsApp/網頁通道行為或收件匣路由 +summary: WhatsApp 通道支援、存取控制、傳遞行為與維運 +title: WhatsApp +x-i18n: + generated_at: "2026-04-30T02:50:06Z" + model: gpt-5.5 + provider: openai + source_hash: 5d0268e068de0001a11a6ed87fe70df8e685d1dcc87c8142ee5b3c77d7a727f3 + source_path: channels/whatsapp.md + workflow: 16 +--- + +狀態:可透過 WhatsApp Web (Baileys) 用於生產環境。Gateway 擁有已連結的工作階段。 + +## 安裝(隨需) + +- Onboarding (`openclaw onboard`) 和 `openclaw channels add --channel whatsapp` + 會在你第一次選取 WhatsApp Plugin 時提示安裝。 +- 當 Plugin 尚未存在時,`openclaw channels login --channel whatsapp` 也會提供安裝流程。 +- 開發通道 + git checkout:預設使用本機 Plugin 路徑。 +- Stable/Beta:當目前套件已發布時,使用 npm 套件 `@openclaw/whatsapp`。 + +手動安裝仍可使用: + +```bash +openclaw plugins install @openclaw/whatsapp +``` + +如果 npm 回報 OpenClaw 擁有的套件已棄用或缺失,請使用目前已封裝的 OpenClaw 建置,或使用本機 checkout,直到 npm 套件發布列車跟上為止。 + + + + 預設 DM 政策會對未知傳送者使用配對。 + + + 跨通道診斷與修復操作手冊。 + + + 完整的通道設定模式與範例。 + + + +## 快速設定 + + + + +```json5 +{ + channels: { + whatsapp: { + dmPolicy: "pairing", + allowFrom: ["+15551234567"], + groupPolicy: "allowlist", + groupAllowFrom: ["+15551234567"], + }, + }, +} +``` + + + + + +```bash +openclaw channels login --channel whatsapp +``` + + 針對特定帳號: + +```bash +openclaw channels login --channel whatsapp --account work +``` + + 若要在登入前附加既有/自訂 WhatsApp Web 驗證目錄: + +```bash +openclaw channels add --channel whatsapp --account work --auth-dir /path/to/wa-auth +openclaw channels login --channel whatsapp --account work +``` + + + + + +```bash +openclaw gateway +``` + + + + + +```bash +openclaw pairing list whatsapp +openclaw pairing approve whatsapp +``` + + 配對要求會在 1 小時後過期。每個通道最多保留 3 個待處理要求。 + + + + + +OpenClaw 建議在可行時使用獨立號碼執行 WhatsApp。(通道中繼資料與設定流程已針對該設定最佳化,但也支援個人號碼設定。) + + +## 部署模式 + + + + 這是最乾淨的操作模式: + + - 為 OpenClaw 使用獨立的 WhatsApp 身分 + - 更清楚的 DM allowlist 與路由邊界 + - 較低的自我聊天混淆機率 + + 最小政策模式: + + ```json5 + { + channels: { + whatsapp: { + dmPolicy: "allowlist", + allowFrom: ["+15551234567"], + }, + }, + } + ``` + + + + + Onboarding 支援個人號碼模式,並寫入適合自我聊天的基準設定: + + - `dmPolicy: "allowlist"` + - `allowFrom` 包含你的個人號碼 + - `selfChatMode: true` + + 在執行階段,自我聊天保護會依據已連結的自身號碼與 `allowFrom` 判定。 + + + + + 在目前的 OpenClaw 通道架構中,訊息平台通道以 WhatsApp Web (`Baileys`) 為基礎。 + + 內建聊天通道登錄中沒有獨立的 Twilio WhatsApp 訊息通道。 + + + + +## 執行階段模型 + +- Gateway 擁有 WhatsApp socket 與重新連線迴圈。 +- 重新連線 watchdog 使用 WhatsApp Web 傳輸活動,而不只是傳入應用程式訊息量,因此安靜的已連結裝置工作階段不會只因最近沒人傳訊息就重新啟動。若傳輸 frame 持續抵達但 watchdog 視窗內沒有處理任何應用程式訊息,較長的應用程式靜默上限仍會強制重新連線;對於最近活躍工作階段的暫時性重新連線,該應用程式靜默檢查會在第一個復原視窗使用一般訊息逾時。 +- Baileys socket 時序明確位於 `web.whatsapp.*` 下:`keepAliveIntervalMs` 控制 WhatsApp Web 應用程式 ping,`connectTimeoutMs` 控制開啟握手逾時,而 `defaultQueryTimeoutMs` 控制 Baileys 查詢逾時。 +- 對外傳送需要目標帳號有作用中的 WhatsApp listener。 +- 狀態與廣播聊天會被忽略(`@status`、`@broadcast`)。 +- 重新連線 watchdog 追蹤 WhatsApp Web 傳輸活動,而不只是傳入應用程式訊息量:安靜的已連結裝置工作階段會在傳輸 frame 持續時保持連線,但傳輸停滯會在較晚的遠端斷線路徑之前就強制重新連線。 +- 直接聊天使用 DM 工作階段規則(`session.dmScope`;預設 `main` 會將 DM 收合至代理程式主工作階段)。 +- 群組工作階段是隔離的(`agent::whatsapp:group:`)。 +- WhatsApp Web 傳輸會遵循 gateway 主機上的標準 proxy 環境變數(`HTTPS_PROXY`、`HTTP_PROXY`、`NO_PROXY` / 小寫變體)。請優先使用主機層級 proxy 設定,而非通道特定的 WhatsApp proxy 設定。 +- 啟用 `messages.removeAckAfterReply` 時,OpenClaw 會在可見回覆送達後清除 WhatsApp ack reaction。 + +## Plugin hook 與隱私 + +WhatsApp 傳入訊息可能包含個人訊息內容、電話號碼、群組識別碼、傳送者名稱,以及工作階段關聯欄位。因此,除非你明確選擇加入,否則 WhatsApp 不會將傳入的 `message_received` hook payload 廣播給 Plugin: + +```json5 +{ + channels: { + whatsapp: { + pluginHooks: { + messageReceived: true, + }, + }, + }, +} +``` + +你可以將選擇加入範圍限定到單一帳號: + +```json5 +{ + channels: { + whatsapp: { + accounts: { + work: { + pluginHooks: { + messageReceived: true, + }, + }, + }, + }, + }, +} +``` + +只應對你信任可接收傳入 WhatsApp 訊息內容與識別碼的 Plugin 啟用此功能。 + +## 存取控制與啟用 + + + + `channels.whatsapp.dmPolicy` 控制直接聊天存取: + + - `pairing`(預設) + - `allowlist` + - `open`(需要 `allowFrom` 包含 `"*"`) + - `disabled` + + `allowFrom` 接受 E.164 風格號碼(內部會正規化)。 + + 多帳號覆寫:`channels.whatsapp.accounts..dmPolicy`(以及 `allowFrom`)會優先於該帳號的通道層級預設值。 + + 執行階段行為詳細資訊: + + - 配對會保存在通道 allow-store 中,並與設定的 `allowFrom` 合併 + - 若未設定 allowlist,預設允許已連結的自身號碼 + - OpenClaw 永遠不會自動配對對外 `fromMe` DM(你從已連結裝置傳送給自己的訊息) + + + + + 群組存取有兩層: + + 1. **群組成員 allowlist** (`channels.whatsapp.groups`) + - 若省略 `groups`,所有群組都符合資格 + - 若存在 `groups`,它會作為群組 allowlist(允許 `"*"`) + + 2. **群組傳送者政策** (`channels.whatsapp.groupPolicy` + `groupAllowFrom`) + - `open`:略過傳送者 allowlist + - `allowlist`:傳送者必須符合 `groupAllowFrom`(或 `*`) + - `disabled`:封鎖所有群組傳入 + + 傳送者 allowlist 備援: + + - 若未設定 `groupAllowFrom`,執行階段會在可用時退回使用 `allowFrom` + - 傳送者 allowlist 會在 mention/reply 啟用前評估 + + 注意:如果完全沒有 `channels.whatsapp` 區塊,即使已設定 `channels.defaults.groupPolicy`,執行階段群組政策備援仍會是 `allowlist`(並記錄 warning log)。 + + + + + 群組回覆預設需要 mention。 + + Mention 偵測包含: + + - 對機器人身分的明確 WhatsApp mention + - 已設定的 mention regex pattern(`agents.list[].groupChat.mentionPatterns`,備援為 `messages.groupChat.mentionPatterns`) + - 已授權群組訊息的傳入語音筆記 transcript + - 隱含的回覆給機器人偵測(回覆傳送者符合機器人身分) + + 安全性注意事項: + + - 引用/回覆只滿足 mention gating;它**不會**授予傳送者授權 + - 使用 `groupPolicy: "allowlist"` 時,即使非 allowlist 傳送者回覆 allowlist 使用者的訊息,仍會被封鎖 + + 工作階段層級啟用命令: + + - `/activation mention` + - `/activation always` + + `activation` 會更新工作階段狀態(不是全域設定)。它受 owner gating 控制。 + + + + +## 個人號碼與自我聊天行為 + +當已連結的自身號碼也出現在 `allowFrom` 中時,WhatsApp 自我聊天防護會啟用: + +- 跳過自我聊天回合的讀取回條 +- 忽略 mention-JID 自動觸發行為,否則它會 ping 你自己 +- 如果未設定 `messages.responsePrefix`,自我聊天回覆預設為 `[{identity.name}]` 或 `[openclaw]` + +## 訊息正規化與上下文 + + + + 傳入 WhatsApp 訊息會包裝在共享的傳入 envelope 中。 + + 如果存在引用回覆,會以下列形式附加上下文: + + ```text + [Replying to id:] + + [/Replying] + ``` + + 可用時也會填入回覆中繼資料欄位(`ReplyToId`、`ReplyToBody`、`ReplyToSender`、傳送者 JID/E.164)。 + + + + + 純媒體傳入訊息會使用下列 placeholder 正規化: + + - `` + - `` + - `` + - `` + - `` + + 已授權群組語音筆記會在 mention gating 前轉錄,前提是本文只有 ``,因此在語音筆記中說出機器人 mention 可觸發回覆。如果 transcript 仍未 mention 機器人,transcript 會保留在待處理群組歷史中,而不是保留原始 placeholder。 + + 位置本文使用簡短座標文字。位置標籤/註解與聯絡人/vCard 詳細資料會呈現為 fenced 的不受信任中繼資料,而不是 inline prompt text。 + + + + + 對於群組,未處理訊息可被緩衝,並在機器人最後被觸發時作為上下文注入。 + + - 預設限制:`50` + - 設定:`channels.whatsapp.historyLimit` + - 備援:`messages.groupChat.historyLimit` + - `0` 會停用 + + 注入標記: + + - `[Chat messages since your last reply - for context]` + - `[Current message - respond to this]` + + + + + 已接受的傳入 WhatsApp 訊息預設會啟用讀取回條。 + + 全域停用: + + ```json5 + { + channels: { + whatsapp: { + sendReadReceipts: false, + }, + }, + } + ``` + + 每帳號覆寫: + + ```json5 + { + channels: { + whatsapp: { + accounts: { + work: { + sendReadReceipts: false, + }, + }, + }, + }, + } + ``` + + 即使全域啟用,自我聊天回合也會跳過讀取回條。 + + + + +## 傳遞、分段與媒體 + + + + - 預設分段限制:`channels.whatsapp.textChunkLimit = 4000` + - `channels.whatsapp.chunkMode = "length" | "newline"` + - `newline` 模式偏好段落邊界(空白行),然後退回到長度安全的分段 + + + + + - 支援圖片、影片、音訊(PTT 語音訊息)和文件 payload + - 音訊媒體會透過 Baileys `audio` payload 並帶有 `ptt: true` 傳送,因此 WhatsApp 用戶端會將其呈現為按住說話語音訊息 + - 回覆 payload 會保留 `audioAsVoice`;即使 provider 傳回 MP3 或 WebM,WhatsApp 的 TTS 語音訊息輸出仍會走這條 PTT 路徑 + - 原生 Ogg/Opus 音訊會以 `audio/ogg; codecs=opus` 傳送,以相容語音訊息 + - 非 Ogg 音訊,包括 Microsoft Edge TTS 的 MP3/WebM 輸出,會先用 `ffmpeg` 轉碼為 48 kHz 單聲道 Ogg/Opus,再透過 PTT 傳遞 + - `/tts latest` 會將最新的助理回覆作為一則語音訊息傳送,並防止同一則回覆重複傳送;`/tts chat on|off|default` 控制目前 WhatsApp 聊天的自動 TTS + - 透過影片傳送時使用 `gifPlayback: true` 支援動態 GIF 播放 + - 傳送多媒體回覆 payload 時,caption 會套用到第一個媒體項目;但 PTT 語音訊息會先傳送音訊,再另外傳送可見文字,因為 WhatsApp 用戶端無法一致呈現語音訊息 caption + - 媒體來源可以是 HTTP(S)、`file://` 或本機路徑 + + + + + - 傳入媒體儲存上限:`channels.whatsapp.mediaMaxMb`(預設 `50`) + - 傳出媒體傳送上限:`channels.whatsapp.mediaMaxMb`(預設 `50`) + - 每個帳號的覆寫使用 `channels.whatsapp.accounts..mediaMaxMb` + - 圖片會自動最佳化(調整大小/品質掃描)以符合限制 + - 媒體傳送失敗時,第一項 fallback 會傳送文字警告,而不是默默丟棄回應 + + + + +## 回覆引用 + +WhatsApp 支援原生回覆引用,傳出回覆會明顯引用傳入訊息。使用 `channels.whatsapp.replyToMode` 控制。 + +| 值 | 行為 | +| ----------- | --------------------------------------------------------------------- | +| `"off"` | 永不引用;作為一般訊息傳送 | +| `"first"` | 只引用第一個傳出回覆片段 | +| `"all"` | 引用每個傳出回覆片段 | +| `"batched"` | 引用佇列中的批次回覆,但立即回覆不引用 | + +預設為 `"off"`。每個帳號的覆寫使用 `channels.whatsapp.accounts..replyToMode`。 + +```json5 +{ + channels: { + whatsapp: { + replyToMode: "first", + }, + }, +} +``` + +## 反應層級 + +`channels.whatsapp.reactionLevel` 控制 agent 在 WhatsApp 上使用 emoji reactions 的範圍: + +| 層級 | Ack reactions | Agent 發起的 reactions | 說明 | +| ------------- | ------------- | ---------------------- | ------------------------------------------------ | +| `"off"` | 否 | 否 | 完全不使用 reactions | +| `"ack"` | 是 | 否 | 僅 Ack reactions(回覆前收件確認) | +| `"minimal"` | 是 | 是(保守) | Ack + agent reactions,採用保守指引 | +| `"extensive"` | 是 | 是(鼓勵) | Ack + agent reactions,採用鼓勵指引 | + +預設:`"minimal"`。 + +每個帳號的覆寫使用 `channels.whatsapp.accounts..reactionLevel`。 + +```json5 +{ + channels: { + whatsapp: { + reactionLevel: "ack", + }, + }, +} +``` + +## 確認 reactions + +WhatsApp 支援透過 `channels.whatsapp.ackReaction` 在收到傳入訊息時立即送出 ack reactions。 +Ack reactions 受 `reactionLevel` 控制;當 `reactionLevel` 為 `"off"` 時會被抑制。 + +```json5 +{ + channels: { + whatsapp: { + ackReaction: { + emoji: "👀", + direct: true, + group: "mentions", // always | mentions | never + }, + }, + }, +} +``` + +行為備註: + +- 在傳入訊息被接受後立即傳送(回覆前) +- 失敗會記錄,但不會阻擋正常回覆傳遞 +- 群組模式 `mentions` 會在提及觸發的回合中反應;群組啟用 `always` 會作為此檢查的旁路 +- WhatsApp 使用 `channels.whatsapp.ackReaction`(此處不使用舊版 `messages.ackReaction`) + +## 多帳號與憑證 + + + + - 帳號 id 來自 `channels.whatsapp.accounts` + - 預設帳號選擇:若存在則使用 `default`,否則使用第一個已設定的帳號 id(排序後) + - 帳號 id 會在內部正規化以供查找 + + + + + - 目前的驗證路徑:`~/.openclaw/credentials/whatsapp//creds.json` + - 備份檔案:`creds.json.bak` + - `~/.openclaw/credentials/` 中的舊版預設驗證仍會被辨識/遷移,用於預設帳號流程 + + + + + `openclaw channels logout --channel whatsapp [--account ]` 會清除該帳號的 WhatsApp 驗證狀態。 + + 在舊版驗證目錄中,會保留 `oauth.json`,並移除 Baileys 驗證檔案。 + + + + +## 工具、動作與設定寫入 + +- Agent 工具支援包含 WhatsApp reaction 動作(`react`)。 +- 動作閘門: + - `channels.whatsapp.actions.reactions` + - `channels.whatsapp.actions.polls` +- 頻道發起的設定寫入預設為啟用(可透過 `channels.whatsapp.configWrites=false` 停用)。 + +## 疑難排解 + + + + 症狀:頻道狀態回報未連結。 + + 修正: + + ```bash + openclaw channels login --channel whatsapp + openclaw channels status + ``` + + + + + 症狀:已連結的帳號反覆斷線或嘗試重新連線。 + + 安靜的帳號可以在一般訊息逾時後仍保持連線;當 WhatsApp Web 傳輸活動停止、socket 關閉,或應用程式層級活動靜默超過較長安全視窗時,watchdog 會重新啟動。 + + 如果記錄顯示重複的 `status=408 Request Time-out Connection was lost`,請調整 `web.whatsapp` 下的 Baileys socket 時序。先將 `keepAliveIntervalMs` 縮短到低於網路的閒置逾時,並在慢速或高遺失率連線上增加 `connectTimeoutMs`: + + ```json5 + { + web: { + whatsapp: { + keepAliveIntervalMs: 15000, + connectTimeoutMs: 60000, + defaultQueryTimeoutMs: 60000, + }, + }, + } + ``` + + 修正: + + ```bash + openclaw doctor + openclaw logs --follow + ``` + + 如有需要,請用 `channels login` 重新連結。 + + + + + 症狀:`openclaw channels login --channel whatsapp` 在顯示可用的 QR code 前失敗,並出現 `status=408 Request Time-out` 或 TLS socket 斷線。 + + WhatsApp Web 登入使用 Gateway 主機的標準 proxy 環境(`HTTPS_PROXY`、`HTTP_PROXY`、小寫變體和 `NO_PROXY`)。確認 Gateway 程序繼承 proxy env,且 `NO_PROXY` 不匹配 `mmg.whatsapp.net`。 + + + + + 當目標帳號沒有作用中的 Gateway listener 時,傳出傳送會快速失敗。 + + 確認 Gateway 正在執行,且帳號已連結。 + + + + + Transcript 列會記錄 agent 產生的內容。WhatsApp 傳遞會另行檢查:OpenClaw 只有在 Baileys 對至少一個可見文字或媒體傳送傳回傳出訊息 id 後,才會將自動回覆視為已傳送。 + + Ack reactions 是獨立的回覆前收件確認。成功的 reaction 不代表後續文字或媒體回覆已被 WhatsApp 接受。 + + 檢查 Gateway 記錄中是否有 `auto-reply delivery failed` 或 `auto-reply was not accepted by WhatsApp provider`。 + + + + + 請依下列順序檢查: + + - `groupPolicy` + - `groupAllowFrom` / `allowFrom` + - `groups` allowlist entries + - 提及閘門(`requireMention` + 提及 patterns) + - `openclaw.json`(JSON5)中的重複鍵:後面的項目會覆寫前面的項目,因此每個 scope 只保留一個 `groupPolicy` + + + + + WhatsApp Gateway runtime 應使用 Node。Bun 被標記為不相容於穩定的 WhatsApp/Telegram Gateway 操作。 + + + +## 系統 prompts + +WhatsApp 透過 `groups` 和 `direct` maps 支援 Telegram 風格的群組與直接聊天系統 prompts。 + +群組訊息的解析階層: + +有效的 `groups` map 會先被決定:如果帳號定義自己的 `groups`,它會完全取代根層級的 `groups` map(沒有 deep merge)。Prompt 查找接著會在產生的單一 map 上執行: + +1. **群組專屬系統 prompt**(`groups[""].systemPrompt`):當特定群組項目存在於 map 中,**且**其 `systemPrompt` 鍵已定義時使用。如果 `systemPrompt` 是空字串(`""`),wildcard 會被抑制,且不套用任何系統 prompt。 +2. **群組 wildcard 系統 prompt**(`groups["*"].systemPrompt`):當特定群組項目完全不存在於 map 中,或項目存在但未定義 `systemPrompt` 鍵時使用。 + +直接訊息的解析階層: + +有效的 `direct` map 會先被決定:如果帳號定義自己的 `direct`,它會完全取代根層級的 `direct` map(沒有 deep merge)。Prompt 查找接著會在產生的單一 map 上執行: + +1. **直接對象專屬系統 prompt**(`direct[""].systemPrompt`):當特定對象項目存在於 map 中,**且**其 `systemPrompt` 鍵已定義時使用。如果 `systemPrompt` 是空字串(`""`),wildcard 會被抑制,且不套用任何系統 prompt。 +2. **直接對象 wildcard 系統 prompt**(`direct["*"].systemPrompt`):當特定對象項目完全不存在於 map 中,或項目存在但未定義 `systemPrompt` 鍵時使用。 + + +`dms` 仍是每個 DM 輕量歷史覆寫 bucket(`dms..historyLimit`)。Prompt 覆寫位於 `direct` 下。 + + +**與 Telegram 多帳號行為的差異:** 在 Telegram 中,多帳號設定會刻意對所有帳號抑制根層級 `groups`,即使帳號沒有定義自己的 `groups` 也一樣,以防 bot 接收不屬於它的群組訊息。WhatsApp 不會套用此防護:根層級 `groups` 和根層級 `direct` 一律會由未定義帳號層級覆寫的帳號繼承,無論設定了多少帳號。在多帳號 WhatsApp 設定中,如果你想要每個帳號各自的群組或直接 prompts,請在每個帳號下明確定義完整 map,而不是依賴根層級預設值。 + +重要行為: + +- `channels.whatsapp.groups` 同時是每個群組的設定映射,也是聊天層級的群組允許清單。在根層級或帳號作用域中,`groups["*"]` 都表示該作用域「允許所有群組」。 +- 只有在你已經希望該作用域允許所有群組時,才加入通配群組 `systemPrompt`。如果你仍然只希望固定的一組群組 ID 符合資格,請不要使用 `groups["*"]` 作為提示預設值。請改為在每個明確列入允許清單的群組項目上重複該提示。 +- 群組准入與寄件者授權是分開的檢查。`groups["*"]` 會擴大可進入群組處理的群組集合,但它本身不會授權這些群組中的每個寄件者。寄件者存取仍由 `channels.whatsapp.groupPolicy` 和 `channels.whatsapp.groupAllowFrom` 分別控制。 +- `channels.whatsapp.direct` 對 DM 沒有相同的副作用。`direct["*"]` 只會在 DM 已由 `dmPolicy` 加上 `allowFrom` 或配對儲存規則准入後,提供預設的直接聊天設定。 + +範例: + +```json5 +{ + channels: { + whatsapp: { + groups: { + // Use only if all groups should be admitted at the root scope. + // Applies to all accounts that do not define their own groups map. + "*": { systemPrompt: "Default prompt for all groups." }, + }, + direct: { + // Applies to all accounts that do not define their own direct map. + "*": { systemPrompt: "Default prompt for all direct chats." }, + }, + accounts: { + work: { + groups: { + // This account defines its own groups, so root groups are fully + // replaced. To keep a wildcard, define "*" explicitly here too. + "120363406415684625@g.us": { + requireMention: false, + systemPrompt: "Focus on project management.", + }, + // Use only if all groups should be admitted in this account. + "*": { systemPrompt: "Default prompt for work groups." }, + }, + direct: { + // This account defines its own direct map, so root direct entries are + // fully replaced. To keep a wildcard, define "*" explicitly here too. + "+15551234567": { systemPrompt: "Prompt for a specific work direct chat." }, + "*": { systemPrompt: "Default prompt for work direct chats." }, + }, + }, + }, + }, + }, +} +``` + +## 設定參考指標 + +主要參考: + +- [設定參考 - WhatsApp](/zh-TW/gateway/config-channels#whatsapp) + +高訊號 WhatsApp 欄位: + +- 存取:`dmPolicy`、`allowFrom`、`groupPolicy`、`groupAllowFrom`、`groups` +- 傳遞:`textChunkLimit`、`chunkMode`、`mediaMaxMb`、`sendReadReceipts`、`ackReaction`、`reactionLevel` +- 多帳號:`accounts..enabled`、`accounts..authDir`、帳號層級覆寫 +- 操作:`configWrites`、`debounceMs`、`web.enabled`、`web.heartbeatSeconds`、`web.reconnect.*`、`web.whatsapp.*` +- 工作階段行為:`session.dmScope`、`historyLimit`、`dmHistoryLimit`、`dms..historyLimit` +- 提示:`groups..systemPrompt`、`groups["*"].systemPrompt`、`direct..systemPrompt`、`direct["*"].systemPrompt` + +## 相關 + +- [配對](/zh-TW/channels/pairing) +- [群組](/zh-TW/channels/groups) +- [安全性](/zh-TW/gateway/security) +- [Channel 路由](/zh-TW/channels/channel-routing) +- [多代理路由](/zh-TW/concepts/multi-agent) +- [疑難排解](/zh-TW/channels/troubleshooting) diff --git a/docs/zh-TW/channels/yuanbao.md b/docs/zh-TW/channels/yuanbao.md new file mode 100644 index 000000000..583020a06 --- /dev/null +++ b/docs/zh-TW/channels/yuanbao.md @@ -0,0 +1,425 @@ +--- +read_when: + - 你想要連接 Yuanbao 機器人 + - 您正在設定 Yuanbao 頻道 +summary: Yuanbao 機器人概覽、功能與設定 +title: 元寶 +x-i18n: + generated_at: "2026-04-30T02:50:19Z" + model: gpt-5.5 + provider: openai + source_hash: d82b6d275ae8aa4cc5e62321772c5ba2b5044c6058be0d2e5215cdb1488118e9 + source_path: channels/yuanbao.md + workflow: 16 +--- + +# Yuanbao + +Tencent Yuanbao 是 Tencent 的 AI 助理平台。OpenClaw 頻道 Plugin +透過 WebSocket 將 Yuanbao 機器人連接到 OpenClaw,讓它們可以透過私訊和群組聊天 +與使用者互動。 + +**狀態:** 可用於生產環境,支援機器人私訊與群組聊天。WebSocket 是唯一支援的連線模式。 + +--- + +## 快速開始 + +> **需要 OpenClaw 2026.4.10 或以上版本。** 執行 `openclaw --version` 檢查。使用 `openclaw update` 升級。 + + + + ```bash + openclaw channels add --channel yuanbao --token "appKey:appSecret" + ``` + `--token` 值使用以冒號分隔的 `appKey:appSecret` 格式。你可以在 Yuanbao 應用程式的應用設定中建立機器人來取得這些資訊。 + + + + ```bash + openclaw gateway restart + ``` + + + +### 互動式設定(替代方式) + +你也可以使用互動式精靈: + +```bash +openclaw channels login --channel yuanbao +``` + +依照提示輸入你的 App ID 和 App Secret。 + +--- + +## 存取控制 + +### 私訊 + +設定 `dmPolicy` 以控制誰可以私訊機器人: + +- `"pairing"` — 未知使用者會收到配對碼;透過 CLI 核准 +- `"allowlist"` — 只有列於 `allowFrom` 的使用者可以聊天 +- `"open"` — 允許所有使用者(預設) +- `"disabled"` — 停用所有私訊 + +**核准配對請求:** + +```bash +openclaw pairing list yuanbao +openclaw pairing approve yuanbao +``` + +### 群組聊天 + +**提及要求** (`channels.yuanbao.requireMention`): + +- `true` — 需要 @提及(預設) +- `false` — 不需要 @提及即可回應 + +在群組聊天中回覆機器人的訊息會被視為隱含提及。 + +--- + +## 設定範例 + +### 使用開放私訊政策的基本設定 + +```json5 +{ + channels: { + yuanbao: { + appKey: "your_app_key", + appSecret: "your_app_secret", + dm: { + policy: "open", + }, + }, + }, +} +``` + +### 將私訊限制為特定使用者 + +```json5 +{ + channels: { + yuanbao: { + appKey: "your_app_key", + appSecret: "your_app_secret", + dm: { + policy: "allowlist", + allowFrom: ["user_id_1", "user_id_2"], + }, + }, + }, +} +``` + +### 停用群組中的 @提及要求 + +```json5 +{ + channels: { + yuanbao: { + requireMention: false, + }, + }, +} +``` + +### 最佳化外送訊息傳遞 + +```json5 +{ + channels: { + yuanbao: { + // 立即傳送每個片段,不進行緩衝 + outboundQueueStrategy: "immediate", + }, + }, +} +``` + +### 調整合併文字策略 + +```json5 +{ + channels: { + yuanbao: { + outboundQueueStrategy: "merge-text", + minChars: 2800, // 緩衝直到達到此字元數 + maxChars: 3000, // 超過此限制時強制分割 + idleMs: 5000, // 閒置逾時後自動清空緩衝(毫秒) + }, + }, +} +``` + +--- + +## 常用命令 + +| 命令 | 說明 | +| ---------- | ---------------- | +| `/help` | 顯示可用命令 | +| `/status` | 顯示機器人狀態 | +| `/new` | 開始新工作階段 | +| `/stop` | 停止目前執行 | +| `/restart` | 重新啟動 OpenClaw | +| `/compact` | 壓縮工作階段內容 | + +> Yuanbao 支援原生斜線命令選單。命令會在 Gateway 啟動時自動同步到平台。 + +--- + +## 疑難排解 + +### 機器人在群組聊天中沒有回應 + +1. 確認機器人已加入群組 +2. 確認你有 @提及機器人(預設為必要) +3. 檢查記錄:`openclaw logs --follow` + +### 機器人沒有接收訊息 + +1. 確認機器人已在 Yuanbao 應用程式中建立並核准 +2. 確認 `appKey` 和 `appSecret` 已正確設定 +3. 確認 Gateway 正在執行:`openclaw gateway status` +4. 檢查記錄:`openclaw logs --follow` + +### 機器人傳送空白或備援回覆 + +1. 檢查 AI 模型是否回傳有效內容 +2. 預設備援回覆是:"暫時無法解答,你可以換個問題問問我哦" +3. 透過 `channels.yuanbao.fallbackReply` 自訂 + +### App Secret 洩漏 + +1. 在 YuanBao APP 中重設 App Secret +2. 更新你的設定中的值 +3. 重新啟動 Gateway:`openclaw gateway restart` + +--- + +## 進階設定 + +### 多個帳號 + +```json5 +{ + channels: { + yuanbao: { + defaultAccount: "main", + accounts: { + main: { + appKey: "key_xxx", + appSecret: "secret_xxx", + name: "Primary bot", + }, + backup: { + appKey: "key_yyy", + appSecret: "secret_yyy", + name: "Backup bot", + enabled: false, + }, + }, + }, + }, +} +``` + +`defaultAccount` 控制當外送 API 未指定 `accountId` 時使用哪個帳號。 + +### 訊息限制 + +- `maxChars` — 單則訊息最大字元數(預設:`3000` 個字元) +- `mediaMaxMb` — 媒體上傳/下載限制(預設:`20` MB) +- `overflowPolicy` — 訊息超過限制時的行為:`"split"`(預設)或 `"stop"` + +### 串流 + +Yuanbao 支援區塊層級串流輸出。啟用後,機器人會在產生文字時分段傳送。 + +```json5 +{ + channels: { + yuanbao: { + disableBlockStreaming: false, // 已啟用區塊串流(預設) + }, + }, +} +``` + +設定 `disableBlockStreaming: true` 以在單則訊息中傳送完整回覆。 + +### 群組聊天歷史內容 + +控制在群組聊天的 AI 內容中包含多少則歷史訊息: + +```json5 +{ + channels: { + yuanbao: { + historyLimit: 100, // 預設:100,設為 0 可停用 + }, + }, +} +``` + +### 回覆目標模式 + +控制機器人在群組聊天中回覆時如何引用訊息: + +```json5 +{ + channels: { + yuanbao: { + replyToMode: "first", // "off" | "first" | "all"(預設:"first") + }, + }, +} +``` + +| 值 | 行為 | +| --------- | ---------------------------------- | +| `"off"` | 不引用回覆 | +| `"first"` | 每則傳入訊息只引用第一個回覆(預設) | +| `"all"` | 引用每個回覆 | + +### Markdown 提示注入 + +預設情況下,機器人會在系統提示中注入指示,防止 AI 模型將整個回覆包在 markdown 程式碼區塊中。 + +```json5 +{ + channels: { + yuanbao: { + markdownHintEnabled: true, // 預設:true + }, + }, +} +``` + +### 偵錯模式 + +針對特定機器人 ID 啟用未清理的記錄輸出: + +```json5 +{ + channels: { + yuanbao: { + debugBotIds: ["bot_user_id_1", "bot_user_id_2"], + }, + }, +} +``` + +### 多代理路由 + +使用 `bindings` 將 Yuanbao 私訊或群組路由到不同代理。 + +```json5 +{ + agents: { + list: [ + { id: "main" }, + { id: "agent-a", workspace: "/home/user/agent-a" }, + { id: "agent-b", workspace: "/home/user/agent-b" }, + ], + }, + bindings: [ + { + agentId: "agent-a", + match: { + channel: "yuanbao", + peer: { kind: "direct", id: "user_xxx" }, + }, + }, + { + agentId: "agent-b", + match: { + channel: "yuanbao", + peer: { kind: "group", id: "group_zzz" }, + }, + }, + ], +} +``` + +路由欄位: + +- `match.channel`: `"yuanbao"` +- `match.peer.kind`: `"direct"`(私訊)或 `"group"`(群組聊天) +- `match.peer.id`: 使用者 ID 或群組代碼 + +--- + +## 設定參考 + +完整設定:[Gateway 設定](/zh-TW/gateway/configuration) + +| 設定 | 說明 | 預設 | +| ------------------------------------------ | ----------------------------------------- | -------------------------------------- | +| `channels.yuanbao.enabled` | 啟用/停用頻道 | `true` | +| `channels.yuanbao.defaultAccount` | 外送路由的預設帳號 | `default` | +| `channels.yuanbao.accounts..appKey` | App Key(用於簽署和產生票證) | — | +| `channels.yuanbao.accounts..appSecret` | App Secret(用於簽署) | — | +| `channels.yuanbao.accounts..token` | 預先簽署的權杖(略過自動票證簽署) | — | +| `channels.yuanbao.accounts..name` | 帳號顯示名稱 | — | +| `channels.yuanbao.accounts..enabled` | 啟用/停用特定帳號 | `true` | +| `channels.yuanbao.dm.policy` | 私訊政策 | `open` | +| `channels.yuanbao.dm.allowFrom` | 私訊允許清單(使用者 ID 清單) | — | +| `channels.yuanbao.requireMention` | 在群組中要求 @提及 | `true` | +| `channels.yuanbao.overflowPolicy` | 長訊息處理(`split` 或 `stop`) | `split` | +| `channels.yuanbao.replyToMode` | 群組回覆目標策略(`off`、`first`、`all`) | `first` | +| `channels.yuanbao.outboundQueueStrategy` | 外送策略(`merge-text` 或 `immediate`) | `merge-text` | +| `channels.yuanbao.minChars` | 合併文字:觸發傳送的最小字元數 | `2800` | +| `channels.yuanbao.maxChars` | 合併文字:每則訊息的最大字元數 | `3000` | +| `channels.yuanbao.idleMs` | 合併文字:自動清空緩衝前的閒置逾時(毫秒) | `5000` | +| `channels.yuanbao.mediaMaxMb` | 媒體大小限制(MB) | `20` | +| `channels.yuanbao.historyLimit` | 群組聊天歷史內容項目 | `100` | +| `channels.yuanbao.disableBlockStreaming` | 停用區塊層級串流輸出 | `false` | +| `channels.yuanbao.fallbackReply` | AI 未回傳內容時的備援回覆 | `暫時無法解答,你可以換個問題問問我哦` | +| `channels.yuanbao.markdownHintEnabled` | 注入 markdown 防包覆指示 | `true` | +| `channels.yuanbao.debugBotIds` | 偵錯允許清單機器人 ID(未清理記錄) | `[]` | + +--- + +## 支援的訊息類型 + +### 接收 + +- ✅ 文字 +- ✅ 圖片 +- ✅ 檔案 +- ✅ 音訊/語音 +- ✅ 影片 +- ✅ 貼圖/自訂表情符號 +- ✅ 自訂元素(連結卡片等) + +### 傳送 + +- ✅ 文字(支援 markdown) +- ✅ 圖片 +- ✅ 檔案 +- ✅ 音訊 +- ✅ 影片 +- ✅ 貼圖 + +### 對話串與回覆 + +- ✅ 引用回覆(可透過 `replyToMode` 設定) +- ❌ 對話串回覆(平台不支援) + +--- + +## 相關 + +- [頻道概覽](/zh-TW/channels) — 所有支援的頻道 +- [配對](/zh-TW/channels/pairing) — 私訊驗證和配對流程 +- [群組](/zh-TW/channels/groups) — 群組聊天行為和提及閘控 +- [頻道路由](/zh-TW/channels/channel-routing) — 訊息的工作階段路由 +- [安全性](/zh-TW/gateway/security) — 存取模型和強化 diff --git a/docs/zh-TW/channels/zalo.md b/docs/zh-TW/channels/zalo.md new file mode 100644 index 000000000..7d682347a --- /dev/null +++ b/docs/zh-TW/channels/zalo.md @@ -0,0 +1,262 @@ +--- +read_when: + - 處理 Zalo 功能或 Webhook +summary: Zalo 機器人支援狀態、功能與設定 +title: Zalo +x-i18n: + generated_at: "2026-04-30T02:50:42Z" + model: gpt-5.5 + provider: openai + source_hash: e79a4a27accc7f460bd3ae9c01e8f5f80e21a285af5d89b94bb9c89244a4438f + source_path: channels/zalo.md + workflow: 16 +--- + +狀態:實驗性。支援 DM。下方的[功能](#capabilities)章節反映目前 Marketplace Bot 的行為。 + +## 內建 Plugin + +Zalo 會以內建 Plugin 隨目前 OpenClaw 版本提供,因此一般封裝版本 +不需要另外安裝。 + +如果你使用的是較舊版本,或自訂安裝排除了 Zalo,請在 npm 套件發布後安裝 +目前版本的 npm 套件: + +- 透過 CLI 安裝:`openclaw plugins install @openclaw/zalo` +- 或從原始碼 checkout 安裝:`openclaw plugins install ./path/to/local/zalo-plugin` +- 詳細資訊:[Plugins](/zh-TW/tools/plugin) + +如果 npm 回報 OpenClaw 擁有的套件已被標記為 deprecated,請使用目前封裝的 +OpenClaw 版本,或在較新的 npm 套件發布前使用本機 checkout 路徑。 + +## 快速設定(初學者) + +1. 確認 Zalo Plugin 可用。 + - 目前封裝的 OpenClaw 版本已經內建它。 + - 較舊或自訂安裝可使用上方指令手動加入。 +2. 設定權杖: + - Env:`ZALO_BOT_TOKEN=...` + - 或設定:`channels.zalo.accounts.default.botToken: "..."`。 +3. 重新啟動 Gateway(或完成設定)。 +4. DM 存取預設使用配對;第一次聯絡時核准配對碼。 + +最小設定: + +```json5 +{ + channels: { + zalo: { + enabled: true, + accounts: { + default: { + botToken: "12345689:abc-xyz", + dmPolicy: "pairing", + }, + }, + }, + }, +} +``` + +## 這是什麼 + +Zalo 是一款以越南為主的通訊應用程式;它的 Bot API 讓 Gateway 能為 1:1 對話執行 Bot。 +當你希望確定性地路由回 Zalo 來處理支援或通知時,它很適合使用。 + +此頁面反映目前 OpenClaw 對 **Zalo Bot Creator / Marketplace Bot** 的行為。 +**Zalo Official Account (OA) Bot** 是不同的 Zalo 產品介面,行為可能不同。 + +- 由 Gateway 擁有的 Zalo Bot API 頻道。 +- 確定性路由:回覆會回到 Zalo;模型不會選擇頻道。 +- DM 共用代理程式的主要工作階段。 +- 下方的[功能](#capabilities)章節顯示目前 Marketplace Bot 的支援情況。 + +## 設定(快速路徑) + +### 1) 建立 Bot 權杖(Zalo Bot Platform) + +1. 前往 [https://bot.zaloplatforms.com](https://bot.zaloplatforms.com) 並登入。 +2. 建立新的 Bot 並設定其選項。 +3. 複製完整 Bot 權杖(通常是 `numeric_id:secret`)。對於 Marketplace Bot,可用的執行階段權杖可能會在建立後出現在 Bot 的歡迎訊息中。 + +### 2) 設定權杖(env 或設定) + +範例: + +```json5 +{ + channels: { + zalo: { + enabled: true, + accounts: { + default: { + botToken: "12345689:abc-xyz", + dmPolicy: "pairing", + }, + }, + }, + }, +} +``` + +如果你之後移至支援群組的 Zalo Bot 介面,可以明確加入群組專屬設定,例如 `groupPolicy` 和 `groupAllowFrom`。關於目前 Marketplace Bot 的行為,請參閱[功能](#capabilities)。 + +Env 選項:`ZALO_BOT_TOKEN=...`(僅適用於預設帳號)。 + +多帳號支援:使用 `channels.zalo.accounts`,並為每個帳號設定權杖與選用的 `name`。 + +3. 重新啟動 Gateway。Zalo 會在解析到權杖(env 或設定)時啟動。 +4. DM 存取預設為配對。Bot 首次被聯絡時請核准代碼。 + +## 運作方式(行為) + +- 傳入訊息會被正規化為含媒體佔位符的共用頻道信封。 +- 回覆一律路由回相同的 Zalo 聊天。 +- 預設使用長輪詢;Webhook 模式可透過 `channels.zalo.webhookUrl` 使用。 + +## 限制 + +- 傳出文字會分塊為 2000 個字元(Zalo API 限制)。 +- 媒體下載/上傳受 `channels.zalo.mediaMaxMb` 限制(預設 5)。 +- 串流預設會被封鎖,因為 2000 字元限制讓串流用途較低。 + +## 存取控制(DM) + +### DM 存取 + +- 預設:`channels.zalo.dmPolicy = "pairing"`。未知寄件者會收到配對碼;在核准前訊息會被忽略(代碼會在 1 小時後過期)。 +- 透過以下方式核准: + - `openclaw pairing list zalo` + - `openclaw pairing approve zalo ` +- 配對是預設的權杖交換方式。詳細資訊:[Pairing](/zh-TW/channels/pairing) +- `channels.zalo.allowFrom` 接受數字使用者 ID(沒有可用的使用者名稱查詢)。 + +## 存取控制(群組) + +對於 **Zalo Bot Creator / Marketplace Bot**,實務上群組支援不可用,因為 Bot 完全無法被加入群組。 + +這表示下列群組相關設定鍵存在於 schema 中,但 Marketplace Bot 無法使用: + +- `channels.zalo.groupPolicy` 控制群組傳入處理:`open | allowlist | disabled`。 +- `channels.zalo.groupAllowFrom` 限制哪些寄件者 ID 可在群組中觸發 Bot。 +- 如果未設定 `groupAllowFrom`,Zalo 會回退到 `allowFrom` 進行寄件者檢查。 +- 執行階段注意事項:如果完全缺少 `channels.zalo`,執行階段仍會為安全起見回退到 `groupPolicy="allowlist"`。 + +群組政策值(當你的 Bot 介面可使用群組存取時)如下: + +- `groupPolicy: "disabled"` — 封鎖所有群組訊息。 +- `groupPolicy: "open"` — 允許任何群組成員(由提及觸發)。 +- `groupPolicy: "allowlist"` — 預設失敗關閉;只接受允許的寄件者。 + +如果你使用不同的 Zalo Bot 產品介面,並且已驗證群組行為可正常運作,請另外記錄,而不是假設它符合 Marketplace Bot 流程。 + +## 長輪詢 vs 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 路徑)。 + - 請求必須使用 `Content-Type: application/json`(或 `+json` 媒體類型)。 + - 重複事件(`event_name + message_id`)會在短暫的重放視窗中被忽略。 + - 突發流量會依路徑/來源進行速率限制,且可能回傳 HTTP 429。 + +**注意:** 根據 Zalo API 文件,getUpdates(輪詢)與 Webhook 彼此互斥。 + +## 支援的訊息類型 + +如需快速支援概覽,請參閱[功能](#capabilities)。下方說明會在行為需要額外脈絡時補充細節。 + +- **文字訊息**:完整支援,並會以 2000 個字元分塊。 +- **文字中的純 URL**:行為如同一般文字輸入。 +- **連結預覽 / 豐富連結卡片**:請參閱[功能](#capabilities)中的 Marketplace Bot 狀態;它們未能可靠觸發回覆。 +- **圖片訊息**:請參閱[功能](#capabilities)中的 Marketplace Bot 狀態;傳入圖片處理不可靠(顯示輸入指示器但沒有最終回覆)。 +- **貼圖**:請參閱[功能](#capabilities)中的 Marketplace Bot 狀態。 +- **語音訊息 / 音訊檔案 / 影片 / 一般檔案附件**:請參閱[功能](#capabilities)中的 Marketplace Bot 狀態。 +- **不支援的類型**:會記錄(例如來自受保護使用者的訊息)。 + +## 功能 + +此表摘要目前 OpenClaw 中 **Zalo Bot Creator / Marketplace Bot** 的行為。 + +| 功能 | 狀態 | +| --------------------------- | --------------------------------------- | +| 直接訊息 | ✅ 支援 | +| 群組 | ❌ Marketplace Bot 不可用 | +| 媒體(傳入圖片) | ⚠️ 有限 / 請在你的環境中驗證 | +| 媒體(傳出圖片) | ⚠️ 尚未針對 Marketplace Bot 重新測試 | +| 文字中的純 URL | ✅ 支援 | +| 連結預覽 | ⚠️ Marketplace Bot 不可靠 | +| 回應 | ❌ 不支援 | +| 貼圖 | ⚠️ Marketplace Bot 沒有代理程式回覆 | +| 語音訊息 / 音訊 / 影片 | ⚠️ Marketplace Bot 沒有代理程式回覆 | +| 檔案附件 | ⚠️ Marketplace Bot 沒有代理程式回覆 | +| 執行緒 | ❌ 不支援 | +| 投票 | ❌ 不支援 | +| 原生命令 | ❌ 不支援 | +| 串流 | ⚠️ 已封鎖(2000 字元限制) | + +## 傳送目標(CLI/Cron) + +- 使用聊天 ID 作為目標。 +- 範例:`openclaw message send --channel zalo --target 123456789 --message "hi"`。 + +## 疑難排解 + +**Bot 沒有回應:** + +- 檢查權杖是否有效:`openclaw channels status --probe` +- 確認寄件者已核准(配對或 allowFrom) +- 檢查 Gateway 記錄:`openclaw logs --follow` + +**Webhook 未收到事件:** + +- 確認 Webhook URL 使用 HTTPS +- 驗證密鑰權杖為 8-256 個字元 +- 確認 Gateway HTTP 端點可在設定的路徑上連線 +- 檢查 getUpdates 輪詢未在執行(兩者彼此互斥) + +## 設定參考(Zalo) + +完整設定:[Configuration](/zh-TW/gateway/configuration) + +扁平的頂層鍵(`channels.zalo.botToken`、`channels.zalo.dmPolicy` 及類似鍵)是舊版單帳號縮寫。新設定建議使用 `channels.zalo.accounts..*`。這兩種形式仍在此文件中記錄,因為它們存在於 schema 中。 + +提供者選項: + +- `channels.zalo.enabled`:啟用/停用頻道啟動。 +- `channels.zalo.botToken`:來自 Zalo Bot Platform 的 Bot 權杖。 +- `channels.zalo.tokenFile`:從一般檔案路徑讀取權杖。符號連結會被拒絕。 +- `channels.zalo.dmPolicy`:`pairing | allowlist | open | disabled`(預設:pairing)。 +- `channels.zalo.allowFrom`:DM 允許清單(使用者 ID)。`open` 需要 `"*"`。精靈會要求輸入數字 ID。 +- `channels.zalo.groupPolicy`:`open | allowlist | disabled`(預設:allowlist)。存在於設定中;關於目前 Marketplace Bot 的行為,請參閱[功能](#capabilities)與[存取控制(群組)](#access-control-groups)。 +- `channels.zalo.groupAllowFrom`:群組寄件者允許清單(使用者 ID)。未設定時會回退到 `allowFrom`。 +- `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`:每個帳號的 DM 政策。 +- `channels.zalo.accounts..allowFrom`:每個帳號的允許清單。 +- `channels.zalo.accounts..groupPolicy`:每個帳號的群組政策。存在於設定中;關於目前 Marketplace Bot 的行為,請參閱[功能](#capabilities)與[存取控制(群組)](#access-control-groups)。 +- `channels.zalo.accounts..groupAllowFrom`:每個帳號的群組寄件者允許清單。 +- `channels.zalo.accounts..webhookUrl`:每個帳號的 Webhook URL。 +- `channels.zalo.accounts..webhookSecret`:每個帳號的 Webhook 密鑰。 +- `channels.zalo.accounts..webhookPath`:每個帳號的 Webhook 路徑。 +- `channels.zalo.accounts..proxy`:每個帳號的代理 URL。 + +## 相關 + +- [Channels Overview](/zh-TW/channels) — 所有支援的頻道 +- [Pairing](/zh-TW/channels/pairing) — DM 驗證與配對流程 +- [Groups](/zh-TW/channels/groups) — 群組聊天行為與提及閘控 +- [Channel Routing](/zh-TW/channels/channel-routing) — 訊息的工作階段路由 +- [Security](/zh-TW/gateway/security) — 存取模型與強化 diff --git a/docs/zh-TW/channels/zalouser.md b/docs/zh-TW/channels/zalouser.md new file mode 100644 index 000000000..54d2908ed --- /dev/null +++ b/docs/zh-TW/channels/zalouser.md @@ -0,0 +1,207 @@ +--- +read_when: + - 為 OpenClaw 設定 Zalo Personal + - 偵錯 Zalo Personal 登入或訊息流程 +summary: 透過原生 zca-js(QR 登入)提供 Zalo 個人帳號支援、功能與設定 +title: Zalo 個人版 +x-i18n: + generated_at: "2026-04-30T02:50:51Z" + model: gpt-5.5 + provider: openai + source_hash: 581a427f7fa37b0fa204f6b813c767eaa7af1f577baf2ac6ea3a31bf23ca6a49 + source_path: channels/zalouser.md + workflow: 16 +--- + +狀態:實驗性。此整合透過 OpenClaw 內的原生 `zca-js` 自動化一個**個人 Zalo 帳號**。 + + +這是非官方整合,可能導致帳號遭停權或封鎖。請自行承擔使用風險。 + + +## 內建 Plugin + +Zalo Personal 在目前的 OpenClaw 發行版本中作為內建 Plugin 隨附,因此一般 +封裝建置不需要另外安裝。 + +如果你使用的是較舊的建置,或是不包含 Zalo Personal 的自訂安裝, +請在有發布時安裝目前的 npm 套件: + +- 透過 CLI 安裝:`openclaw plugins install @openclaw/zalouser` +- 或從原始碼 checkout 安裝:`openclaw plugins install ./path/to/local/zalouser-plugin` +- 詳細資訊:[Plugins](/zh-TW/tools/plugin) + +如果 npm 回報 OpenClaw 擁有的套件已棄用,請使用目前封裝的 +OpenClaw 建置,或使用本機 checkout 路徑,直到較新的 npm 套件 +發布為止。 + +不需要外部 `zca`/`openzca` CLI 二進位檔。 + +## 快速設定(初學者) + +1. 確認 Zalo Personal Plugin 可用。 + - 目前封裝的 OpenClaw 發行版本已內建。 + - 較舊/自訂安裝可使用上述命令手動加入。 +2. 登入(QR,在 Gateway 機器上): + - `openclaw channels login --channel zalouser` + - 使用 Zalo 行動應用程式掃描 QR code。 +3. 啟用通道: + +```json5 +{ + channels: { + zalouser: { + enabled: true, + dmPolicy: "pairing", + }, + }, +} +``` + +4. 重新啟動 Gateway(或完成設定)。 +5. DM 存取預設使用配對;首次聯絡時核准配對碼。 + +## 它是什麼 + +- 完全透過 `zca-js` 在程序內執行。 +- 使用原生事件監聽器接收傳入訊息。 +- 直接透過 JS API 傳送回覆(文字/媒體/連結)。 +- 專為無法使用 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 用戶端限制)。 +- 預設封鎖串流。 + +## 存取控制(DM) + +`channels.zalouser.dmPolicy` 支援:`pairing | allowlist | open | disabled`(預設:`pairing`)。 + +`channels.zalouser.allowFrom` 接受使用者 ID 或名稱。設定期間,名稱會使用 Plugin 的程序內聯絡人查找解析為 ID。 + +透過以下命令核准: + +- `openclaw pairing list zalouser` +- `openclaw pairing approve zalouser ` + +## 群組存取(選用) + +- 預設:`channels.zalouser.groupPolicy = "open"`(允許群組)。未設定時,使用 `channels.defaults.groupPolicy` 覆寫預設值。 +- 使用以下設定限制為允許清單: + - `channels.zalouser.groupPolicy = "allowlist"` + - `channels.zalouser.groups`(key 應為穩定的群組 ID;啟動時會在可能情況下將名稱解析為 ID) + - `channels.zalouser.groupAllowFrom`(控制允許群組中的哪些傳送者可以觸發 bot) +- 封鎖所有群組:`channels.zalouser.groupPolicy = "disabled"`。 +- 設定精靈可以提示輸入群組允許清單。 +- 啟動時,OpenClaw 會將允許清單中的群組/使用者名稱解析為 ID,並記錄對應關係。 +- 群組允許清單比對預設僅使用 ID。除非啟用 `channels.zalouser.dangerouslyAllowNameMatching: true`,否則未解析的名稱會在驗證時被忽略。 +- `channels.zalouser.dangerouslyAllowNameMatching: true` 是一種緊急相容模式,會重新啟用可變的群組名稱比對。 +- 如果未設定 `groupAllowFrom`,執行階段會退回使用 `allowFrom` 進行群組傳送者檢查。 +- 傳送者檢查同時套用於一般群組訊息和控制命令(例如 `/new`)。 + +範例: + +```json5 +{ + channels: { + zalouser: { + groupPolicy: "allowlist", + groupAllowFrom: ["1471383327500481391"], + groups: { + "123456789": { allow: true }, + "Work Chat": { allow: true }, + }, + }, + }, +} +``` + +### 群組提及閘控 + +- `channels.zalouser.groups..requireMention` 控制群組回覆是否需要提及。 +- 解析順序:精確群組 id/名稱 -> 正規化群組 slug -> `*` -> 預設(`true`)。 +- 這同時套用於允許清單群組和開放群組模式。 +- 引用 bot 訊息會算作群組啟用的隱含提及。 +- 已授權的控制命令(例如 `/new`)可以略過提及閘控。 +- 當群組訊息因需要提及而被略過時,OpenClaw 會將它儲存為待處理群組歷史,並在下一則已處理的群組訊息中包含它。 +- 群組歷史限制預設為 `messages.groupChat.historyLimit`(備援 `50`)。你可以使用 `channels.zalouser.historyLimit` 依帳號覆寫。 + +範例: + +```json5 +{ + channels: { + zalouser: { + groupPolicy: "allowlist", + groups: { + "*": { allow: true, requireMention: true }, + "Work Chat": { allow: true, requireMention: false }, + }, + }, + }, +} +``` + +## 多帳號 + +帳號會對應到 OpenClaw 狀態中的 `zalouser` 設定檔。範例: + +```json5 +{ + channels: { + zalouser: { + enabled: true, + defaultAccount: "default", + accounts: { + work: { enabled: true, profile: "work" }, + }, + }, + }, +} +``` + +## 輸入狀態、反應與送達確認 + +- OpenClaw 會在送出回覆前傳送輸入中事件(盡力而為)。 +- 訊息反應動作 `react` 在通道動作中支援 `zalouser`。 + - 使用 `remove: true` 從訊息移除特定反應 emoji。 + - 反應語意:[Reactions](/zh-TW/tools/reactions) +- 對於包含事件中繼資料的傳入訊息,OpenClaw 會傳送已送達 + 已讀確認(盡力而為)。 + +## 疑難排解 + +**登入無法保留:** + +- `openclaw channels status --probe` +- 重新登入:`openclaw channels logout --channel zalouser && openclaw channels login --channel zalouser` + +**允許清單/群組名稱未解析:** + +- 在 `allowFrom`/`groupAllowFrom`/`groups` 中使用數字 ID,或使用精確的朋友/群組名稱。 + +**從舊的 CLI 架構設定升級:** + +- 移除任何舊的外部 `zca` 程序假設。 +- 通道現在完全在 OpenClaw 中執行,不需要外部 CLI 二進位檔。 + +## 相關 + +- [通道概覽](/zh-TW/channels) — 所有支援的通道 +- [配對](/zh-TW/channels/pairing) — DM 驗證與配對流程 +- [群組](/zh-TW/channels/groups) — 群組聊天行為與提及閘控 +- [通道路由](/zh-TW/channels/channel-routing) — 訊息的工作階段路由 +- [安全性](/zh-TW/gateway/security) — 存取模型與強化 diff --git a/docs/zh-TW/ci.md b/docs/zh-TW/ci.md new file mode 100644 index 000000000..766c67134 --- /dev/null +++ b/docs/zh-TW/ci.md @@ -0,0 +1,367 @@ +--- +read_when: + - 你需要了解為什麼 CI 作業有執行或未執行 + - 您正在偵錯失敗的 GitHub Actions 檢查 +summary: CI 作業圖、範圍門檻與對應的本機命令 +title: CI 管線 +x-i18n: + generated_at: "2026-04-30T02:50:58Z" + model: gpt-5.5 + provider: openai + source_hash: 60576e126bd5012b12c62acfb72a991d2c3207e532a5b7137b218ae9b37852d2 + source_path: ci.md + workflow: 16 +--- + +CI 會在每次推送到 `main` 以及每個 pull request 時執行。它會使用智慧範圍界定,在只有不相關區域變更時跳過昂貴的作業。手動 `workflow_dispatch` 執行會刻意略過智慧範圍界定,並展開完整的一般 CI 圖供候選版本或廣泛驗證使用;Android 通道則透過 `include_android` 為獨立手動執行選擇性啟用。僅供發行使用的 Plugin 預發行通道位於獨立的 `Plugin Prerelease` workflow,且只會從 `Full Release Validation` 或明確的手動 dispatch 執行。 + +`check-dependencies` shard 會執行 `pnpm deadcode:dependencies`,這是一個僅針對生產 Knip 依賴項的檢查流程,固定使用該 script 所使用的最新 Knip 版本,並在 `dlx` 安裝時停用 pnpm 的最低發布年齡限制。它也會執行 `pnpm deadcode:unused-files`,將 Knip 的生產環境未使用檔案發現結果與 `scripts/deadcode-unused-files.allowlist.mjs` 比對。當 PR 新增未經審查的未使用檔案,或在清理後留下過時的 allowlist 項目時,該防護會失敗,同時保留 Knip 無法靜態解析的刻意動態 Plugin、產生檔、建置、即時測試與套件橋接表面。 + +`Full Release Validation` 是「發行前執行所有項目」的手動總括 workflow。它接受分支、標籤或完整 commit SHA,使用該目標 dispatch 手動 `CI` workflow,dispatch `Plugin Prerelease` 以進行僅供發行使用的 Plugin/套件/靜態/Docker 證明,並 dispatch `OpenClaw Release Checks` 以進行安裝 smoke、套件驗收、Docker 發行路徑套件、即時/E2E、OpenWebUI、QA Lab parity、Matrix 與 Telegram 通道。當提供已發布的套件 spec 時,它也可以執行發布後的 `NPM Telegram Beta E2E` workflow。`release_profile=minimum|stable|full` 控制傳入發行檢查的即時/供應商廣度:`minimum` 保留最快的 OpenAI/核心發行關鍵通道,`stable` 加入穩定的供應商/後端集合,而 `full` 會執行廣泛的 advisory 供應商/媒體矩陣。總括 workflow 會記錄已 dispatch 的子執行 ID,而最終的 `Verify full validation` job 會重新檢查目前子執行結論,並為每個子執行附加最慢 job 表格。如果子 workflow 重新執行並轉為綠燈,只需重新執行父 verifier job,即可重新整理總括結果與時間摘要。 + +針對復原,`Full Release Validation` 與 `OpenClaw Release Checks` 都接受 `rerun_group`。對候選版本使用 `all`,只針對一般完整 CI 子項使用 `ci`,針對每個發行子項使用 `release-checks`,或在總括 workflow 使用更窄的發行群組:`install-smoke`、`cross-os`、`live-e2e`、`package`、`qa`、`qa-parity`、`qa-live` 或 `npm-telegram`。這能在聚焦修正後,將失敗發行機器的重新執行限制在有界範圍內。 + +發行即時/E2E 子項保留廣泛的原生 `pnpm test:live` 涵蓋範圍,但它會透過 `scripts/test-live-shard.mjs` 以命名 shard 執行(`native-live-src-agents`、`native-live-src-gateway-core`、依供應商篩選的 `native-live-src-gateway-profiles` jobs、`native-live-src-gateway-backends`、`native-live-test`、`native-live-extensions-a-k`、`native-live-extensions-l-n`、`native-live-extensions-openai`、`native-live-extensions-o-z-other`、`native-live-extensions-xai`、拆分的媒體音訊/影片 shard,以及依供應商篩選的音樂 shard),而不是一個序列 job。這會維持相同的檔案涵蓋範圍,同時讓緩慢的即時供應商失敗更容易重新執行與診斷。彙總 `native-live-extensions-o-z`、`native-live-extensions-media` 與 `native-live-extensions-media-music` shard 名稱仍可用於手動一次性重新執行。 + +原生即時媒體 shard 會在 `ghcr.io/openclaw/openclaw-live-media-runner:ubuntu-24.04` 中執行,該映像由 `Live Media Runner Image` workflow 建置。該映像預先安裝 `ffmpeg` 與 `ffprobe`;媒體 job 只會在設定前驗證二進位檔。請將 Docker 支援的即時套件維持在一般 Blacksmith runner 上,因為容器 job 並不是啟動巢狀 Docker 測試的正確位置。 + +Docker 支援的即時模型/後端 shard 會對每個選定 commit 使用獨立的共享 `ghcr.io/openclaw/openclaw-live-test:` 映像。即時發行 workflow 會建置並推送該映像一次,然後 Docker 即時模型、Gateway、CLI 後端、ACP bind 與 Codex harness shard 會以 `OPENCLAW_SKIP_DOCKER_BUILD=1` 執行。如果這些 shard 各自重新建置完整來源 Docker 目標,表示發行執行設定錯誤,並會將 wall clock 浪費在重複映像建置上。 + +`OpenClaw Release Checks` 使用可信任的 workflow ref,將選定 ref 一次解析成 `release-package-under-test` tarball,然後將該 artifact 傳給即時/E2E 發行路徑 Docker workflow 與套件驗收 shard。這可讓套件位元組在各發行機器間保持一致,並避免在多個子 job 中重複封裝相同候選項。 + +`Package Acceptance` 是用於驗證套件 artifact 的旁路 workflow,不會阻塞發行 workflow。它會從已發布的 npm spec、以選定 `workflow_ref` harness 建置的可信任 `package_ref`、帶有 SHA-256 的 HTTPS tarball URL,或另一個 GitHub Actions 執行中的 tarball artifact 解析出一個候選項,將其上傳為 `package-under-test`,然後以該 tarball 重新使用 Docker 發行/E2E scheduler,而不是重新封裝 workflow checkout。Profile 涵蓋 smoke、套件、產品、完整與自訂 Docker 通道選擇。`package` profile 使用離線 Plugin 涵蓋範圍,因此已發布套件驗證不會受即時 ClawHub 可用性限制。選用的 Telegram 通道會在 `NPM Telegram Beta E2E` workflow 中重用 `package-under-test` artifact,並保留已發布 npm spec 路徑供獨立 dispatch 使用。 + +## 套件驗收 + +當問題是「這個可安裝的 OpenClaw 套件是否能作為產品運作?」時,使用 `Package Acceptance`。它不同於一般 CI:一般 CI 驗證來源樹,而套件驗收會透過使用者在安裝或更新後會使用的相同 Docker E2E harness 來驗證單一 tarball。 + +該 workflow 有四個 job: + +1. `resolve_package` checkout `workflow_ref`、解析一個套件候選項、寫入 `.artifacts/docker-e2e-package/openclaw-current.tgz`、寫入 `.artifacts/docker-e2e-package/package-candidate.json`,將兩者上傳為 `package-under-test` artifact,並在 GitHub 步驟摘要中列印來源、workflow ref、套件 ref、版本、SHA-256 與 profile。 +2. `docker_acceptance` 會呼叫 `openclaw-live-and-e2e-checks-reusable.yml`,並帶入 `ref=workflow_ref` 與 `package_artifact_name=package-under-test`。可重用 workflow 會下載該 artifact、驗證 tarball inventory、在需要時準備 package-digest Docker 映像,並針對該套件執行選定的 Docker 通道,而不是封裝 workflow checkout。當 profile 選擇多個目標 `docker_lanes` 時,可重用 workflow 會準備套件與共享映像一次,然後將這些通道展開為平行的目標 Docker jobs,且各自具有唯一 artifact。 +3. `package_telegram` 會選擇性呼叫 `NPM Telegram Beta E2E`。它會在 `telegram_mode` 不是 `none` 時執行,且當 Package Acceptance 已解析出套件時,會安裝相同的 `package-under-test` artifact;獨立 Telegram dispatch 仍可安裝已發布的 npm spec。 +4. `summary` 會在套件解析、Docker 驗收或選用 Telegram 通道失敗時讓 workflow 失敗。 + +候選來源: + +- `source=npm`:僅接受 `openclaw@beta`、`openclaw@latest`,或精確的 OpenClaw 發行版本,例如 `openclaw@2026.4.27-beta.2`。用於已發布的 beta/stable 驗收。 +- `source=ref`:封裝可信任的 `package_ref` 分支、標籤或完整 commit SHA。解析器會擷取 OpenClaw 分支/標籤、驗證選定 commit 可從儲存庫分支歷史或發行標籤到達、在 detached worktree 中安裝依賴項,並使用 `scripts/package-openclaw-for-docker.mjs` 進行封裝。 +- `source=url`:下載 HTTPS `.tgz`;必須提供 `package_sha256`。 +- `source=artifact`:從 `artifact_run_id` 與 `artifact_name` 下載一個 `.tgz`;`package_sha256` 為選用,但外部共享 artifact 應提供。 + +請將 `workflow_ref` 與 `package_ref` 分開。`workflow_ref` 是執行測試的可信任 workflow/harness 程式碼。`package_ref` 是在 `source=ref` 時會被封裝的來源 commit。這可讓目前的測試 harness 驗證較舊的可信任來源 commit,而不執行舊的 workflow 邏輯。 + +Profile 對應到 Docker 涵蓋範圍: + +- `smoke`:`npm-onboard-channel-agent`、`gateway-network`、`config-reload` +- `package`:`npm-onboard-channel-agent`、`doctor-switch`、`update-channel-switch`、`bundled-channel-deps-compat`、`plugins-offline`、`plugin-update` +- `product`:`package` 加上 `mcp-channels`、`cron-mcp-cleanup`、`openai-web-search-minimal`、`openwebui` +- `full`:包含 OpenWebUI 的完整 Docker 發行路徑 chunks +- `custom`:精確的 `docker_lanes`;當 `suite_profile=custom` 時必填 + +發行檢查會以 `source=ref`、`package_ref=`、`workflow_ref=`、`suite_profile=custom`、`docker_lanes='bundled-channel-deps-compat plugins-offline'` 與 `telegram_mode=mock-openai` 呼叫 Package Acceptance。發行路徑 Docker chunks 會涵蓋重疊的套件/更新/Plugin 通道,而 Package Acceptance 會針對相同解析出的套件 tarball,保留 artifact 原生的 bundled-channel 相容性、離線 Plugin 與 Telegram 證明。 +跨 OS 發行檢查仍會涵蓋 OS 特定的 onboarding、安裝程式與平台行為;套件/更新產品驗證應從 Package Acceptance 開始。Windows packaged 與 installer fresh 通道也會驗證已安裝的套件可以從原始絕對 Windows 路徑匯入 browser-control override。OpenAI 跨 OS agent-turn smoke 預設在設定時使用 `OPENCLAW_CROSS_OS_OPENAI_MODEL`,否則使用 `openai/gpt-5.4-mini`,因此安裝與 Gateway 證明會保持快速且決定性。專用的即時供應商/模型通道仍會涵蓋更廣泛的模型路由,包括較慢的 frontier 預設值。 + +Package Acceptance 對已發布套件有有界的舊版相容性窗口。到 `2026.4.25` 為止的套件,包括 `2026.4.25-beta.*`,可以針對 `dist/postinstall-inventory.json` 中指向 tarball 省略檔案的已知私有 QA 項目使用相容性路徑;當套件未公開該旗標時,`doctor-switch` 可以跳過 `gateway install --wrapper` persistence 子案例;`update-channel-switch` 可以從 tarball 衍生的 fake git fixture 中修剪缺少的 `pnpm.patchedDependencies`,也可以記錄缺少的持久化 `update.channel`;Plugin smoke 可以讀取舊版 install-record 位置,或接受缺少 marketplace install-record persistence;而 `plugin-update` 可以允許 config metadata migration,同時仍要求 install record 與 no-reinstall 行為保持不變。已發布的 `2026.4.26` 套件也可以對已出貨的本機建置 metadata stamp 檔案發出警告。之後的套件必須滿足現代合約;相同條件會失敗,而不是警告或跳過。 + +範例: + +```bash +# Validate the current beta package with product-level coverage. +gh workflow run package-acceptance.yml \ + --ref main \ + -f workflow_ref=main \ + -f source=npm \ + -f package_spec=openclaw@beta \ + -f suite_profile=product \ + -f telegram_mode=mock-openai + +# Pack and validate a release branch with the current harness. +gh workflow run package-acceptance.yml \ + --ref main \ + -f workflow_ref=main \ + -f source=ref \ + -f package_ref=release/YYYY.M.D \ + -f suite_profile=package \ + -f telegram_mode=mock-openai + +# Validate a tarball URL. SHA-256 is mandatory for source=url. +gh workflow run package-acceptance.yml \ + --ref main \ + -f workflow_ref=main \ + -f source=url \ + -f package_url=https://example.com/openclaw-current.tgz \ + -f package_sha256=<64-char-sha256> \ + -f suite_profile=smoke + +# Reuse a tarball uploaded by another Actions run. +gh workflow run package-acceptance.yml \ + --ref main \ + -f workflow_ref=main \ + -f source=artifact \ + -f artifact_run_id= \ + -f artifact_name=package-under-test \ + -f suite_profile=custom \ + -f docker_lanes='install-e2e plugin-update' +``` + +偵錯失敗的套件接受度執行時,請先從 `resolve_package` +摘要開始,確認套件來源、版本與 SHA-256。接著檢查 +`docker_acceptance` 子執行及其 Docker 成果: +`.artifacts/docker-tests/**/summary.json`、`failures.json`、通道記錄、階段 +計時,以及重新執行命令。請優先重新執行失敗的套件設定檔或 +精確的 Docker 通道,而不是重新執行完整的發布驗證。 + +QA Lab 在主要智慧範圍工作流程之外有專用 CI 通道。 +`Parity gate` 工作流程會在符合的 PR 變更與手動分派時執行;它會 +建置私有 QA 執行階段,並比較模擬 GPT-5.5 與 Opus 4.6 +代理套件。`QA-Lab - All Lanes` 工作流程會每晚在 `main` 上執行,也會在 +手動分派時執行;它會將模擬同等性閘門、即時 Matrix 通道,以及即時 +Telegram 與 Discord 通道分散成平行作業。即時作業會使用 +`qa-live-shared` 環境,而 Telegram/Discord 會使用 Convex 租約。發布 +檢查會以確定性的模擬提供者與模擬限定模型(`mock-openai/gpt-5.5` 與 +`mock-openai/gpt-5.5-alt`)執行 Matrix 與 Telegram 即時傳輸通道,讓通道 +契約與即時模型延遲及一般提供者 Plugin 啟動隔離。即時傳輸 Gateway 也會 +停用記憶體搜尋,因為 QA 同等性會另外涵蓋記憶體行為;提供者連線能力則由 +獨立的即時模型、原生提供者與 Docker 提供者套件涵蓋。Matrix 在排程與發布閘門中使用 `--profile fast`, +只有在已簽出的 CLI 支援時才加上 `--fail-fast`。CLI 預設值 +與手動工作流程輸入仍為 `all`;手動 `matrix_profile=all` +分派一律會將完整 Matrix 覆蓋分片成 `transport`、`media`、 +`e2ee-smoke`、`e2ee-deep` 與 `e2ee-cli` 作業。`OpenClaw Release Checks` 也會 +在發布核准前執行發布關鍵的 QA Lab 通道;其 QA 同等性 +閘門會將候選與基準套件作為平行通道作業執行,接著將 +兩個成果下載到小型報告作業,以進行最終同等性比較。 +除非變更實際觸及 QA 執行階段、模型套件同等性,或同等性工作流程擁有的介面, +否則不要把 PR 登陸路徑放在 `Parity gate` 後面。 +對於一般通道、設定、文件或單元測試修正,請把它視為可選 +訊號,並遵循範圍化的 CI/檢查證據。 + +`Duplicate PRs After Merge` 工作流程是供維護者在登陸後清理重複項目的 +手動工作流程。它預設為試跑,且只有在 `apply=true` 時才會關閉明確 +列出的 PR。在變更 GitHub 之前,它會驗證已登陸 PR 已合併,且每個重複項目 +都有共用的參照議題,或有重疊的變更區塊。 + +`CodeQL` 工作流程刻意作為窄範圍的第一道安全掃描器, +而不是完整儲存庫掃描。每日、手動與非草稿拉取請求防護 +執行會在 `/codeql-critical-security/core-auth-secrets` 類別下,以高精準度安全 +查詢掃描 Actions 工作流程程式碼,以及最高風險的 JavaScript/TypeScript +驗證、祕密、沙箱、Cron 與 Gateway 介面。 +channel-runtime-boundary 作業會在 `/codeql-critical-security/channel-runtime-boundary` +類別下,另外掃描核心通道實作 +契約,以及通道 Plugin 執行階段、Gateway、Plugin SDK、祕密與 +稽核接觸點,讓通道安全訊號能在不擴大基準 +驗證/祕密類別的情況下擴展。network-ssrf-boundary 作業會在 +`/codeql-critical-security/network-ssrf-boundary` 類別下,掃描核心 SSRF、IP 解析、 +網路防護、web-fetch 與 Plugin SDK SSRF 政策介面,讓網路信任 +邊界訊號與驗證/祕密安全基準保持分離。 +mcp-process-tool-boundary 作業會在 +`/codeql-critical-security/mcp-process-tool-boundary` 類別下,掃描 MCP 伺服器、程序執行輔助程式、 +外送交付與代理工具執行閘門,讓命令與 +工具邊界訊號同時與驗證/祕密基準及 +非安全 MCP/程序品質分片保持分離。plugin-trust-boundary 作業會在 +`/codeql-critical-security/plugin-trust-boundary` 類別下,掃描 +Plugin 安裝、載入器、資訊清單、登錄、執行階段相依項暫存、 +來源載入、公開介面與 Plugin SDK 套件契約信任介面,讓 Plugin +供應鏈與執行階段載入訊號同時與內建 Plugin +實作程式碼及非安全 Plugin 品質分片保持分離。 +拉取請求防護維持輕量:它只會針對 +`.github/actions`、`.github/codeql`、`.github/workflows`、`packages` 或 `src` +底下的變更啟動,並執行與排程工作流程相同的關鍵安全矩陣。Android、 +macOS 與非安全品質 CodeQL 不列入 PR 預設值。 + +`CodeQL Android Critical Security` 工作流程是排程 Android +安全分片。它會在 workflow sanity 接受的最小 +Blacksmith Linux runner 標籤上,為 CodeQL 手動建置 Android 應用程式,並在 +`/codeql-critical-security/android` 類別下上傳結果。 + +`CodeQL macOS Critical Security` 工作流程是每週/手動 macOS +安全分片。它會在 Blacksmith macOS 上為 CodeQL 手動建置 macOS 應用程式、 +從上傳的 SARIF 中過濾掉相依項建置結果,並在 +`/codeql-critical-security/macos` 類別下上傳結果。請讓它留在每日 +預設工作流程之外,因為即使乾淨,macOS 建置也會主導執行時間。 + +`CodeQL Critical Quality` 工作流程是對應的非安全分片。它 +只會在較小的 Blacksmith Linux runner 上,對窄範圍高價值介面執行 +錯誤嚴重性、非安全的 JavaScript/TypeScript 品質查詢。其 +手動分派接受 +`profile=all|plugin-sdk-package-contract|plugin-sdk-reply-runtime|provider-runtime-boundary|session-diagnostics-boundary`; +窄範圍設定檔是教學/迭代掛鉤,可在不分派其餘工作流程的情況下 +單獨執行一個品質分片。 +其 +core-auth-secrets 作業會在獨立的 `/codeql-critical-quality/core-auth-secrets` +類別下,掃描驗證、祕密、沙箱、Cron 與 Gateway 安全 +邊界程式碼。config-boundary +作業會在獨立的 `/codeql-critical-quality/config-boundary` 類別下,掃描設定結構描述、 +遷移、正規化與 IO 契約。gateway-runtime-boundary 作業會在獨立的 +`/codeql-critical-quality/gateway-runtime-boundary` 類別下,掃描 Gateway 協定結構描述與伺服器方法 +契約。channel-runtime-boundary 作業會在 +獨立的 `/codeql-critical-quality/channel-runtime-boundary` 類別下,掃描核心通道實作契約。agent-runtime-boundary 作業會在 +獨立的 `/codeql-critical-quality/agent-runtime-boundary` 類別下,掃描命令執行、模型/提供者分派、 +自動回覆分派與佇列,以及 ACP 控制平面執行階段契約。 +mcp-process-runtime-boundary 作業會在獨立的 +`/codeql-critical-quality/mcp-process-runtime-boundary` 類別下,掃描 MCP 伺服器與工具橋接、程序 +監督輔助程式,以及外送交付契約。memory-runtime-boundary 作業會在 +獨立的 `/codeql-critical-quality/memory-runtime-boundary` +類別下,掃描記憶體主機 SDK、記憶體執行階段 facade、 +記憶體 Plugin SDK 別名、記憶體執行階段啟用黏合,以及記憶體 doctor +命令。session-diagnostics-boundary 作業會在獨立的 +`/codeql-critical-quality/session-diagnostics-boundary` 類別下,掃描回覆佇列內部、 +工作階段交付佇列、外送工作階段繫結/交付輔助程式、診斷 +事件/記錄套件介面,以及工作階段 doctor CLI 契約。plugin-sdk-reply-runtime 作業會在獨立的 +`/codeql-critical-quality/plugin-sdk-reply-runtime` 類別下,掃描 Plugin SDK 入站回覆分派、回覆 +承載/分塊/執行階段輔助程式、通道回覆選項、交付佇列,以及 +工作階段/執行緒繫結輔助程式。 +provider-runtime-boundary 作業會在獨立的 +`/codeql-critical-quality/provider-runtime-boundary` 類別下,掃描模型目錄正規化、提供者驗證 +與探索、提供者執行階段註冊、提供者預設值/目錄,以及 +網頁/搜尋/擷取/嵌入提供者登錄。 +ui-control-plane 作業會在獨立的 +`/codeql-critical-quality/ui-control-plane` 類別下,掃描 Control UI 啟動、本機持久化、Gateway +控制流程,以及任務控制平面執行階段契約。 +web-media-runtime-boundary 作業會在 +獨立的 `/codeql-critical-quality/web-media-runtime-boundary` 類別下,掃描核心網頁擷取/搜尋、媒體 IO、媒體 +理解、影像生成與媒體生成執行階段契約。plugin-boundary 作業會在獨立的 `/codeql-critical-quality/plugin-boundary` +類別下,掃描載入器、登錄、公開介面與 Plugin SDK +進入點契約。plugin-sdk-package-contract 作業會在獨立的 +`/codeql-critical-quality/plugin-sdk-package-contract` 類別下,掃描已發布套件端 +Plugin SDK 原始碼與 Plugin 套件契約輔助程式。請讓此 +工作流程與安全分離,讓品質發現項目可以被 +排程、測量、停用或擴展,而不會模糊安全訊號。 +Swift、Python 與內建 Plugin CodeQL 擴展,應只在窄範圍設定檔有穩定 +執行時間與訊號後,作為範圍化或分片後續工作加回。 + +`Docs Agent` 工作流程是事件驅動的 Codex 維護通道,用於讓 +現有文件與最近登陸的變更保持一致。它沒有純排程:在 `main` 上 +成功的非機器人推送 CI 執行可以觸發它,手動分派也可以 +直接執行它。當 `main` 已前進,或上一小時內已建立另一個非略過的 Docs Agent 執行時, +workflow-run 叫用會略過。執行時,它會 +檢閱從上一個非略過 Docs Agent 來源 SHA 到目前 `main` 的提交範圍, +因此每小時一次的執行可以涵蓋自上次文件檢查以來累積的所有 main 變更。 + +`Test Performance Agent` 工作流程是事件驅動的 Codex 維護通道, +用於慢速測試。它沒有純排程:在 +`main` 上成功的非機器人推送 CI 執行可以觸發它,但如果該 UTC 日已有另一個 workflow-run 叫用 +已執行或正在執行,它會略過。手動分派會繞過該每日活動 +閘門。此通道會建置完整套件分組的 Vitest 效能報告,讓 Codex +只進行小型且保留覆蓋率的測試效能修正,而不是廣泛 +重構,接著重新執行完整套件報告,並拒絕會降低 +通過基準測試數量的變更。如果基準有失敗測試,Codex 只能修正 +明顯失敗項目,且代理後的完整套件報告必須通過,才會 +提交任何內容。當 `main` 在機器人推送登陸前前進時,此通道 +會 rebase 已驗證的修補、重新執行 `pnpm check:changed`,並重試推送; +有衝突的過期修補會被略過。它使用 GitHub 託管的 Ubuntu,讓 Codex +動作可以維持與 docs agent 相同的 drop-sudo 安全姿態。 + +```bash +gh workflow run duplicate-after-merge.yml \ + -f landed_pr=70532 \ + -f duplicate_prs='70530,70592' \ + -f apply=true +``` + +## 工作概覽 + +| 工作 | 用途 | 執行時機 | +| -------------------------------- | -------------------------------------------------------------------------------------------- | ---------------------------------- | +| `preflight` | 偵測僅文件變更、變更範圍、變更的 Plugin,並建置 CI 資訊清單 | 非草稿推送和 PR 時一律執行 | +| `security-scm-fast` | 透過 `zizmor` 進行私密金鑰偵測和工作流程稽核 | 非草稿推送和 PR 時一律執行 | +| `security-dependency-audit` | 針對 npm 公告執行不需依賴項的生產 lockfile 稽核 | 非草稿推送和 PR 時一律執行 | +| `security-fast` | 快速安全性工作的必要彙總 | 非草稿推送和 PR 時一律執行 | +| `build-artifacts` | 建置 `dist/`、Control UI、建置成品檢查,以及可重用的下游成品 | Node 相關變更 | +| `checks-fast-core` | 快速 Linux 正確性通道,例如 bundled/plugin-contract/protocol 檢查 | Node 相關變更 | +| `checks-fast-contracts-channels` | 分片的頻道合約檢查,具備穩定的彙總檢查結果 | Node 相關變更 | +| `checks-node-core-test` | Core Node 測試分片,不包含頻道、bundled、合約和 Plugin 通道 | Node 相關變更 | +| `check` | 分片的主要本機閘門等效項目:生產型別、lint、防護、測試型別和嚴格 smoke | Node 相關變更 | +| `check-additional` | 架構、邊界、Plugin 介面防護、套件邊界,以及 gateway-watch 分片 | Node 相關變更 | +| `build-smoke` | 已建置 CLI smoke 測試和啟動記憶體 smoke | Node 相關變更 | +| `checks` | 已建置成品頻道測試的驗證器 | Node 相關變更 | +| `checks-node-compat-node22` | Node 22 相容性建置和 smoke 通道 | 發行版的手動 CI 觸發 | +| `check-docs` | 文件格式化、lint 和損壞連結檢查 | 文件已變更 | +| `skills-python` | Python 支援 Skills 的 Ruff + pytest | Python Skills 相關變更 | +| `checks-windows` | Windows 特定程序/路徑測試,加上共用執行階段匯入規範回歸測試 | Windows 相關變更 | +| `macos-node` | 使用共用建置成品的 macOS TypeScript 測試通道 | macOS 相關變更 | +| `macos-swift` | macOS app 的 Swift lint、建置和測試 | macOS 相關變更 | +| `android` | 兩種 flavor 的 Android 單元測試,加上一個 debug APK 建置 | Android 相關變更 | +| `test-performance-agent` | 在可信活動後,每日執行 Codex 慢速測試最佳化 | Main CI 成功或手動觸發 | + +手動 CI 觸發會執行與一般 CI 相同的工作圖,但會強制啟用每個非 Android 範圍通道:Linux Node 分片、bundled-plugin 分片、頻道合約、Node 22 相容性、`check`、`check-additional`、建置 smoke、文件檢查、Python Skills、Windows、macOS,以及 Control UI i18n。獨立的手動 CI 觸發只會在 `include_android=true` 時執行 Android;完整發行總控流程會透過傳入 `include_android=true` 啟用 Android。Plugin 預發行靜態檢查、僅發行使用的 `agentic-plugins` 分片、完整 Plugin 批次掃描,以及 Plugin 預發行 Docker 通道都排除在 CI 之外。Docker 預發行套件只會在 `Full Release Validation` 觸發獨立的 `Plugin Prerelease` 工作流程,且啟用發行驗證閘門時執行。手動執行使用唯一並行群組,因此候選發行版本的完整套件不會被相同 ref 上的另一個推送或 PR 執行取消。選用的 `target_ref` 輸入可讓可信呼叫端針對分支、tag 或完整 commit SHA 執行該圖,同時使用所選觸發 ref 的工作流程檔案。 + +```bash +gh workflow run ci.yml --ref release/YYYY.M.D +gh workflow run ci.yml --ref main -f target_ref= -f include_android=true +gh workflow run full-release-validation.yml --ref main -f ref= +``` + +## 快速失敗順序 + +工作已排序,讓低成本檢查在高成本工作執行前先失敗: + +1. `preflight` 決定哪些通道實際存在。`docs-scope` 和 `changed-scope` 邏輯是此工作內的步驟,不是獨立工作。 +2. `security-scm-fast`、`security-dependency-audit`、`security-fast`、`check`、`check-additional`、`check-docs` 和 `skills-python` 會快速失敗,不等待較重的成品和平台矩陣工作。 +3. `build-artifacts` 會與快速 Linux 通道重疊執行,讓下游消費者可在共用建置準備就緒後立即開始。 +4. 較重的平台和執行階段通道會在之後展開:`checks-fast-core`、`checks-fast-contracts-channels`、`checks-node-core-test`、`checks`、`checks-windows`、`macos-node`、`macos-swift` 和 `android`。 + +範圍邏輯位於 `scripts/ci-changed-scope.mjs`,並由 `src/scripts/ci-changed-scope.test.ts` 中的單元測試涵蓋。 +手動觸發會略過變更範圍偵測,並讓預檢 manifest +表現得像每個限定範圍都已變更。 +CI 工作流程編輯會驗證 Node CI 圖以及工作流程 lint,但不會自行強制執行 Windows、Android 或 macOS 原生建置;這些平台 lane 仍限定於平台來源變更。 +僅限 CI 路由的編輯、選定的低成本核心測試 fixture 編輯,以及狹窄的 Plugin contract helper/test-routing 編輯會使用快速的僅 Node manifest 路徑:預檢、安全性,以及單一 `checks-fast-core` 工作。當變更檔案僅限於該快速工作直接演練的路由或 helper surface 時,該路徑會避開建置成品、Node 22 相容性、channel contract、完整核心 shard、內建 Plugin shard,以及額外的 guard matrix。 +Windows Node 檢查限定於 Windows 特定的 process/path wrapper、npm/pnpm/UI runner helper、package manager 設定,以及執行該 lane 的 CI 工作流程 surface;不相關的原始碼、Plugin、install-smoke 與僅測試變更會留在 Linux Node lane,因此不會為已由一般 test shard 演練的覆蓋範圍保留 16-vCPU Windows worker。 +獨立的 `install-smoke` 工作流程會透過自己的 `preflight` job 重用相同的範圍 script。它會將 smoke 覆蓋範圍拆分為 `run_fast_install_smoke` 與 `run_full_install_smoke`。Pull request 會針對 Docker/package surface、內建 Plugin package/manifest 變更,以及 Docker smoke job 會演練的核心 Plugin/channel/gateway/Plugin SDK surface 執行快速路徑。僅來源的內建 Plugin 變更、僅測試編輯,以及僅文件編輯不會保留 Docker worker。快速路徑會建置一次根 Dockerfile 映像、檢查 CLI、執行 agents delete shared-workspace CLI smoke、執行 container gateway-network e2e、驗證內建 extension build arg,並在 240 秒彙總命令逾時下執行有界的內建 Plugin Docker profile,且每個情境的 Docker run 也會分別設限。完整路徑會保留 QR package install 與 installer Docker/update 覆蓋範圍,用於夜間排程執行、手動觸發、workflow-call release check,以及真正觸及 installer/package/Docker surface 的 pull request。在完整模式中,install-smoke 會準備或重用一個 target-SHA GHCR root Dockerfile smoke 映像,然後以獨立 job 執行 QR package install、root Dockerfile/gateway smoke、installer/update smoke,以及快速內建 Plugin Docker E2E,讓 installer 工作不必等待 root image smoke。`main` push,包括 merge commit,不會強制完整路徑;當變更範圍邏輯會在 push 上要求完整覆蓋時,工作流程會保留快速 Docker smoke,並將完整 install smoke 留給夜間或 release 驗證。較慢的 Bun global install image-provider smoke 會由 `run_bun_global_install_smoke` 另行 gate;它會在夜間排程與 release checks 工作流程中執行,且手動 `install-smoke` 觸發可以選擇加入,但 pull request 與 `main` push 不會執行它。QR 與 installer Docker 測試保留各自以安裝為重點的 Dockerfile。本機 `test:docker:all` 會預先建置一個共用 live-test 映像、將 OpenClaw 打包一次為 npm tarball,並建置兩個共用 `scripts/e2e/Dockerfile` 映像:一個用於 installer/update/plugin-dependency lane 的裸 Node/Git runner,以及一個會將相同 tarball 安裝到 `/app`、供一般功能 lane 使用的 functional image。Docker lane 定義位於 `scripts/lib/docker-e2e-scenarios.mjs`,planner 邏輯位於 `scripts/lib/docker-e2e-plan.mjs`,runner 只會執行選定的 plan。排程器會使用 `OPENCLAW_DOCKER_E2E_BARE_IMAGE` 與 `OPENCLAW_DOCKER_E2E_FUNCTIONAL_IMAGE` 為每個 lane 選擇映像,然後以 `OPENCLAW_SKIP_DOCKER_BUILD=1` 執行 lane;用 `OPENCLAW_DOCKER_ALL_PARALLELISM` 調整預設值為 10 的 main-pool slot count,並用 `OPENCLAW_DOCKER_ALL_TAIL_PARALLELISM` 調整預設值為 10 的 provider-sensitive tail-pool slot count。重型 lane 上限預設為 `OPENCLAW_DOCKER_ALL_LIVE_LIMIT=9`、`OPENCLAW_DOCKER_ALL_NPM_LIMIT=10` 與 `OPENCLAW_DOCKER_ALL_SERVICE_LIMIT=7`,讓 npm install 與多服務 lane 不會讓 Docker 超額承載,而較輕的 lane 仍能填滿可用 slot。單一 lane 即使比有效上限更重,仍可從空 pool 啟動,然後獨自執行直到釋放容量。lane 啟動預設錯開 2 秒,以避免本機 Docker daemon 建立風暴;可用 `OPENCLAW_DOCKER_ALL_START_STAGGER_MS=0` 或其他毫秒值覆寫。本機彙總會預檢 Docker、移除過期的 OpenClaw E2E container、發出 active-lane 狀態、持久化 lane timing 以進行 longest-first 排序,並支援 `OPENCLAW_DOCKER_ALL_DRY_RUN=1` 供排程器檢查。預設在第一次失敗後停止排程新的 pooled lane,且每個 lane 都有 120 分鐘 fallback timeout,可用 `OPENCLAW_DOCKER_ALL_LANE_TIMEOUT_MS` 覆寫;選定的 live/tail lane 會使用更嚴格的 per-lane 上限。`OPENCLAW_DOCKER_ALL_LANES=` 會執行精確的排程器 lane,包括僅 release 的 lane,例如 `install-e2e`,以及拆分的內建 update lane,例如 `bundled-channel-update-acpx`,同時略過 cleanup smoke,讓 agent 能重現單一失敗 lane。可重用的 live/E2E 工作流程會詢問 `scripts/test-docker-all.mjs --plan-json` 需要哪些 package、image kind、live image、lane 與 credential 覆蓋範圍,然後 `scripts/docker-e2e.mjs` 會將該 plan 轉換為 GitHub output 與 summary。它會透過 `scripts/package-openclaw-for-docker.mjs` 打包 OpenClaw、下載目前執行的 package artifact,或從 `package_artifact_run_id` 下載 package artifact;驗證 tarball inventory;當 plan 需要 package-installed lane 時,透過 Blacksmith 的 Docker layer cache 建置並推送 package-digest-tagged bare/functional GHCR Docker E2E 映像;並重用提供的 `docker_e2e_bare_image`/`docker_e2e_functional_image` input 或既有的 package-digest image,而不是重新建置。Docker image pull 會以有界的每次嘗試 180 秒 timeout 重試,讓卡住的 registry/cache stream 能快速重試,而不是耗掉大部分 CI 關鍵路徑。`Package Acceptance` 工作流程是高階 package gate:它會從 npm、受信任的 `package_ref`、HTTPS tarball 加上 SHA-256,或先前的工作流程 artifact 解析 candidate,然後將該單一 `package-under-test` artifact 傳入可重用的 Docker E2E 工作流程。它會讓 `workflow_ref` 與 `package_ref` 分離,讓目前的 acceptance 邏輯可驗證較舊的受信任 commit,而不必 checkout 舊工作流程程式碼。Release check 會針對目標 ref 執行自訂 Package Acceptance delta:內建 channel compat、離線 Plugin fixture,以及針對解析後 tarball 的 Telegram package QA。release-path Docker suite 會以 `OPENCLAW_SKIP_DOCKER_BUILD=1` 執行較小的分塊 job,讓每個 chunk 只 pull 所需的 image kind,並透過相同的加權排程器執行多個 lane(`OPENCLAW_DOCKER_ALL_PROFILE=release-path`、`OPENCLAW_DOCKER_ALL_CHUNK=core|package-update-openai|package-update-anthropic|package-update-core|plugins-runtime-plugins|plugins-runtime-services|plugins-runtime-install-a|plugins-runtime-install-b|plugins-runtime-install-c|plugins-runtime-install-d|plugins-runtime-install-e|plugins-runtime-install-f|plugins-runtime-install-g|plugins-runtime-install-h|bundled-channels`)。當完整 release-path 覆蓋要求 OpenWebUI 時,OpenWebUI 會併入 `plugins-runtime-services`,且只有在 OpenWebUI-only 觸發時才保留獨立的 `openwebui` chunk。舊版彙總 chunk 名稱 `package-update`、`plugins-runtime-core`、`plugins-runtime` 與 `plugins-integrations` 仍可用於手動重新執行,但 release 工作流程使用拆分 chunk,讓 installer E2E 與內建 Plugin install/uninstall sweep 不會主宰關鍵路徑。`install-e2e` lane alias 仍是兩個 provider installer lane 的彙總手動重新執行 alias。`bundled-channels` chunk 會執行拆分的 `bundled-channel-*` 與 `bundled-channel-update-*` lane,而不是序列式 all-in-one `bundled-channel-deps` lane。每個 chunk 都會上傳 `.artifacts/docker-tests/`,其中包含 lane log、timing、`summary.json`、`failures.json`、phase timing、scheduler plan JSON、slow-lane table,以及每個 lane 的重新執行命令。工作流程 `docker_lanes` input 會針對已準備好的映像執行選定 lane,而不是 chunk job,這會將失敗 lane 偵錯限定在一個目標 Docker job,並為該執行準備、下載或重用 package artifact;如果選定 lane 是 live Docker lane,目標 job 會為該次重新執行在本機建置 live-test 映像。產生的每個 lane GitHub 重新執行命令會在這些值存在時包含 `package_artifact_run_id`、`package_artifact_name` 與已準備的 image input,因此失敗 lane 可重用失敗執行中的精確 package 與映像。使用 `pnpm test:docker:rerun ` 可從 GitHub run 下載 Docker artifact,並列印合併/每 lane 的目標重新執行命令;使用 `pnpm test:docker:timings ` 可取得 slow-lane 與 phase critical-path summary。排程的 live/E2E 工作流程每天執行完整 release-path Docker suite。內建 update matrix 依 update target 拆分,讓重複的 npm update 與 doctor repair pass 能與其他內建檢查分 shard 執行。 + +目前 release Docker chunk 為 `core`、`package-update-openai`、`package-update-anthropic`、`package-update-core`、`plugins-runtime-plugins`、`plugins-runtime-services`、`plugins-runtime-install-a`、`plugins-runtime-install-b`、`plugins-runtime-install-c`、`plugins-runtime-install-d`、`plugins-runtime-install-e`、`plugins-runtime-install-f`、`plugins-runtime-install-g`、`plugins-runtime-install-h`、`bundled-channels-core`、`bundled-channels-update-a`、`bundled-channels-update-discord`、`bundled-channels-update-b` 與 `bundled-channels-contracts`。彙總 `bundled-channels` chunk 仍可用於手動一次性重新執行,且 `plugins-runtime-core`、`plugins-runtime` 與 `plugins-integrations` 仍是彙總 Plugin/runtime alias,但 release 工作流程會使用拆分 chunk,讓 channel smoke、update target、Plugin runtime check 與內建 Plugin install/uninstall sweep 能平行執行。目標 `docker_lanes` 觸發也會在一個共用 package/image 準備步驟後,將多個選定 lane 拆成平行 job,且內建 channel update lane 會針對暫時性 npm 網路失敗重試一次。 + +本機變更通道邏輯位於 `scripts/changed-lanes.mjs`,並由 `scripts/check-changed.mjs` 執行。該本機檢查閘門對架構邊界的要求比廣泛 CI 平台範圍更嚴格:核心生產變更會執行核心生產與核心測試型別檢查,加上核心 lint/防護;僅核心測試變更只會執行核心測試型別檢查加核心 lint;擴充功能生產變更會執行擴充功能生產與擴充功能測試型別檢查,加上擴充功能 lint;僅擴充功能測試變更會執行擴充功能測試型別檢查加擴充功能 lint。公開 Plugin SDK 或 Plugin 合約變更會擴展到擴充功能型別檢查,因為擴充功能依賴這些核心合約,但 Vitest 擴充功能掃描屬於明確的測試工作。僅發行中繼資料的版本遞增會執行目標式版本/設定/根依賴檢查。未知的根目錄/設定變更會以安全失敗方式落到所有檢查通道。 +本機變更測試路由位於 `scripts/test-projects.test-support.mjs`,並且刻意比 `check:changed` 更低成本:直接測試編輯會執行自身測試,原始碼編輯會優先使用明確對應,接著是同層測試與匯入圖相依項。共享群組聊天室傳遞設定是明確對應之一:對群組可見回覆設定、來源回覆傳遞模式,或訊息工具系統提示的變更,會路由到核心回覆測試以及 Discord 與 Slack 傳遞回歸測試,讓共享預設值變更在第一次 PR 推送前就失敗。只有當變更範圍足夠涵蓋整個測試框架,使低成本對應集合無法作為可信代理時,才使用 `OPENCLAW_TEST_CHANGED_BROAD=1 pnpm test:changed`。 + +進行 Testbox 驗證時,請從儲存庫根目錄執行,並偏好為廣泛證明使用全新預熱的測試盒。在把緩慢閘門花在重用、過期,或剛回報非預期大型同步的測試盒之前,先在測試盒內執行 `pnpm testbox:sanity`。當必要根目錄檔案(例如 `pnpm-lock.yaml`)消失,或 `git status --short` 顯示至少 200 個已追蹤刪除項目時,健全性檢查會快速失敗。這通常表示遠端同步狀態不是 PR 的可信副本。停止該測試盒並預熱新的測試盒,而不是偵錯產品測試失敗。對於有意的大量刪除 PR,請為該健全性執行設定 `OPENCLAW_TESTBOX_ALLOW_MASS_DELETIONS=1`。當本機 Blacksmith CLI 呼叫停留在同步階段超過五分鐘且沒有同步後輸出時,`pnpm testbox:run` 也會終止該呼叫。設定 `OPENCLAW_TESTBOX_SYNC_TIMEOUT_MS=0` 可停用該防護,或為異常大型的本機差異使用較大的毫秒值。 + +手動 CI 派送會執行 `checks-node-compat-node22` 作為廣泛相容性覆蓋。Android 對獨立手動 CI 採用選用方式,透過 `include_android=true` 啟用,並且在 `Full Release Validation` 中一律啟用。`Plugin Prerelease` 是成本較高的產品/套件覆蓋,因此它是由 `Full Release Validation` 或明確操作員派送的獨立工作流程。一般 pull request、`main` 推送,以及獨立手動 CI 派送都會關閉該套件。 + +最慢的 Node 測試家族已被拆分或平衡,讓每個工作在不過度保留 runner 的情況下保持小型:頻道合約以三個加權分片執行,小型核心單元通道會配對,自動回覆以四個平衡 worker 執行,並將回覆子樹拆分為 agent-runner、dispatch,以及 commands/state-routing 分片;agentic Gateway/Plugin 設定則分散到既有的僅原始碼 agentic Node 工作,而不是等待建置成品。廣泛瀏覽器、QA、媒體,以及雜項 Plugin 測試會使用專屬 Vitest 設定,而不是共享 Plugin 全收式設定。`Plugin Prerelease` 會在八個擴充功能 worker 之間平衡內建 Plugin 測試;這些擴充功能分片工作一次最多執行兩個 Plugin 設定群組,每個群組使用一個 Vitest worker 和更大的 Node heap,讓匯入密集的 Plugin 批次不會建立額外 CI 工作。廣泛 agents 通道使用共享 Vitest 檔案平行排程器,因為它主要受匯入/排程支配,而不是由單一緩慢測試檔案主導。`runtime-config` 會與 infra core-runtime 分片一起執行,避免共享 runtime 分片承擔尾端時間。Include-pattern 分片會使用 CI 分片名稱記錄 timing 項目,因此 `.artifacts/vitest-shard-timings.json` 能區分完整設定與經過篩選的分片。`check-additional` 會將套件邊界編譯/canary 工作放在一起,並將 runtime 拓撲架構與 Gateway watch 覆蓋分開;邊界防護分片會在單一工作內並行執行其小型獨立防護。Gateway watch、頻道測試,以及核心支援邊界分片會在 `dist/` 與 `dist-runtime/` 已建置後,於 `build-artifacts` 內並行執行,保留其舊檢查名稱作為輕量驗證工作,同時避免兩個額外 Blacksmith worker 和第二個成品消費者佇列。 +Android CI 會同時執行 `testPlayDebugUnitTest` 和 `testThirdPartyDebugUnitTest`,然後建置 Play debug APK。第三方 flavor 沒有獨立 source set 或 manifest;其單元測試通道仍會使用 SMS/通話記錄 BuildConfig 旗標編譯該 flavor,同時避免在每次 Android 相關推送時產生重複 debug APK 封裝工作。 +當較新的推送落在同一個 PR 或 `main` ref 上時,GitHub 可能會將已被取代的工作標記為 `cancelled`。除非同一 ref 的最新執行也失敗,否則請將其視為 CI 雜訊。彙總分片檢查使用 `!cancelled() && always()`,因此它們仍會回報一般分片失敗,但不會在整個工作流程已被取代後繼續排入佇列。 +自動 CI concurrency key 已版本化(`CI-v7-*`),因此 GitHub 端舊佇列群組中的僵屍項目無法無限期阻擋較新的 main 執行。手動完整套件執行使用 `CI-manual-v1-*`,且不會取消進行中的執行。 + +## Runner + +| Runner | 工作 | +| -------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `ubuntu-24.04` | `preflight`、快速安全性工作與彙總(`security-scm-fast`、`security-dependency-audit`、`security-fast`)、快速 protocol/contract/bundled 檢查、分片頻道合約檢查、除 lint 以外的 `check` 分片、`check-additional` 分片與彙總、Node 測試彙總驗證器、文件檢查、Python skills、workflow-sanity、labeler、auto-response;install-smoke preflight 也使用 GitHub 託管的 Ubuntu,讓 Blacksmith 矩陣可以更早排入佇列 | +| `blacksmith-4vcpu-ubuntu-2404` | `CodeQL Critical Quality`、較低權重的擴充功能分片、`checks-fast-core`、`checks-node-compat-node22`、`check-prod-types` 與 `check-test-types` | +| `blacksmith-8vcpu-ubuntu-2404` | `build-artifacts`、build-smoke、Linux Node 測試分片、內建 Plugin 測試分片、`android` | +| `blacksmith-16vcpu-ubuntu-2404` | `check-lint`,它仍對 CPU 足夠敏感,以致 8 vCPU 的成本高於其節省;install-smoke Docker 建置,其中 32-vCPU 佇列時間的成本高於其節省 | +| `blacksmith-16vcpu-windows-2025` | `checks-windows` | +| `blacksmith-6vcpu-macos-latest` | `openclaw/openclaw` 上的 `macos-node`;fork 會退回到 `macos-latest` | +| `blacksmith-12vcpu-macos-latest` | `openclaw/openclaw` 上的 `macos-swift`;fork 會退回到 `macos-latest` | + +## 本機對應項 + +```bash +pnpm changed:lanes # inspect the local changed-lane classifier for origin/main...HEAD +pnpm check:changed # smart local check gate: changed typecheck/lint/guards by boundary lane +pnpm check # fast local gate: production tsgo + sharded lint + parallel fast guards +pnpm check:test-types +pnpm check:timed # same gate with per-stage timings +pnpm build:strict-smoke +pnpm check:architecture +pnpm test:gateway:watch-regression +pnpm test # vitest tests +pnpm test:changed # cheap smart changed Vitest targets +pnpm test:channels +pnpm test:contracts:channels +pnpm check:docs # docs format + lint + broken links +pnpm build # build dist when CI artifact/build-smoke lanes matter +pnpm ci:timings # summarize the latest origin/main push CI run +pnpm ci:timings:recent # compare recent successful main CI runs +node scripts/ci-run-timings.mjs # summarize wall time, queue time, and slowest jobs +node scripts/ci-run-timings.mjs --latest-main # ignore issue/comment noise and choose origin/main push CI +node scripts/ci-run-timings.mjs --recent 10 # compare recent successful main CI runs +pnpm test:perf:groups --full-suite --allow-failures --output .artifacts/test-perf/baseline-before.json +pnpm test:perf:groups:compare .artifacts/test-perf/baseline-before.json .artifacts/test-perf/after-agent.json +``` + +## 相關 + +- [安裝概覽](/zh-TW/install) +- [發行通道](/zh-TW/install/development-channels) diff --git a/docs/zh-TW/cli/acp.md b/docs/zh-TW/cli/acp.md new file mode 100644 index 000000000..16e507149 --- /dev/null +++ b/docs/zh-TW/cli/acp.md @@ -0,0 +1,295 @@ +--- +read_when: + - 設定以 ACP 為基礎的 IDE 整合 + - 偵錯 ACP 工作階段到 Gateway 的路由 +summary: 執行 ACP 橋接器以支援 IDE 整合 +title: ACP +x-i18n: + generated_at: "2026-04-30T02:50:59Z" + model: gpt-5.5 + provider: openai + source_hash: 88b4d5de9e8e7464fd929ace0471af7d85afc94789c0c45a1f4a00d39b7871e1 + source_path: cli/acp.md + workflow: 16 +--- + +執行與 OpenClaw Gateway 通訊的 [代理程式用戶端通訊協定 (ACP)](https://agentclientprotocol.com/) 橋接器。 + +此命令會透過 stdio 為 IDE 使用 ACP,並透過 WebSocket 將提示轉送至 Gateway。它會讓 ACP 工作階段對應到 Gateway 工作階段金鑰。 + +`openclaw acp` 是由 Gateway 支援的 ACP 橋接器,不是完整的 ACP 原生編輯器執行階段。它專注於工作階段路由、提示傳遞,以及基本串流更新。 + +如果你想讓外部 MCP 用戶端直接與 OpenClaw 頻道對話通訊,而不是代管 ACP harness 工作階段,請改用 [`openclaw mcp serve`](/zh-TW/cli/mcp)。 + +## 這不是什麼 + +此頁面經常與 ACP harness 工作階段混淆。 + +`openclaw acp` 表示: + +- OpenClaw 會作為 ACP 伺服器 +- IDE 或 ACP 用戶端會連線到 OpenClaw +- OpenClaw 會將該工作轉送到 Gateway 工作階段 + +這不同於 [ACP 代理程式](/zh-TW/tools/acp-agents),在後者中,OpenClaw 會透過 `acpx` 執行外部 harness,例如 Codex 或 Claude Code。 + +快速規則: + +- 編輯器/用戶端想要以 ACP 與 OpenClaw 通訊:使用 `openclaw acp` +- OpenClaw 應以 ACP harness 啟動 Codex/Claude/Gemini:使用 `/acp spawn` 和 [ACP 代理程式](/zh-TW/tools/acp-agents) + +## 相容性矩陣 + +| ACP 範圍 | 狀態 | 備註 | +| --------------------------------------------------------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `initialize`, `newSession`, `prompt`, `cancel` | 已實作 | 透過 stdio 到 Gateway chat/send + abort 的核心橋接流程。 | +| `listSessions`, 斜線命令 | 已實作 | 工作階段清單會對照 Gateway 工作階段狀態運作;命令會透過 `available_commands_update` 公告。 | +| `loadSession` | 部分支援 | 會將 ACP 工作階段重新繫結到 Gateway 工作階段金鑰,並重放已儲存的使用者/助理文字歷史紀錄。工具/系統歷史紀錄尚未重建。 | +| 提示內容(`text`、內嵌 `resource`、圖片) | 部分支援 | 文字/資源會扁平化為聊天輸入;圖片會變成 Gateway 附件。 | +| 工作階段模式 | 部分支援 | 支援 `session/set_mode`,且橋接器會公開初始的 Gateway 支援工作階段控制項,用於思考層級、工具詳細程度、推理、用量明細,以及提升權限動作。更廣泛的 ACP 原生模式/設定介面仍不在範圍內。 | +| 工作階段資訊與用量更新 | 部分支援 | 橋接器會從快取的 Gateway 工作階段快照發出 `session_info_update` 和盡力而為的 `usage_update` 通知。用量為近似值,且只有在 Gateway 將 Token 總量標記為最新時才會傳送。 | +| 工具串流 | 部分支援 | 當 Gateway 工具引數/結果公開相關資訊時,`tool_call` / `tool_call_update` 事件會包含原始 I/O、文字內容,以及盡力而為的檔案位置。內嵌終端機和更豐富的差異原生輸出仍未公開。 | +| 每個工作階段的 MCP 伺服器(`mcpServers`) | 不支援 | 橋接模式會拒絕每個工作階段的 MCP 伺服器請求。請改在 OpenClaw gateway 或代理程式上設定 MCP。 | +| 用戶端檔案系統方法(`fs/read_text_file`, `fs/write_text_file`) | 不支援 | 橋接器不會呼叫 ACP 用戶端檔案系統方法。 | +| 用戶端終端機方法(`terminal/*`) | 不支援 | 橋接器不會建立 ACP 用戶端終端機,也不會透過工具呼叫串流終端機 ID。 | +| 工作階段計畫 / 思考串流 | 不支援 | 橋接器目前會發出輸出文字與工具狀態,而不是 ACP 計畫或思考更新。 | + +## 已知限制 + +- `loadSession` 會重放已儲存的使用者與助理文字歷史紀錄,但不會重建歷史工具呼叫、系統通知,或更豐富的 ACP 原生事件類型。 +- 如果多個 ACP 用戶端共用同一個 Gateway 工作階段金鑰,事件與取消路由會是盡力而為,而不是嚴格依用戶端隔離。當你需要乾淨的編輯器本機回合時,請偏好預設隔離的 `acp:` 工作階段。 +- Gateway 停止狀態會轉譯為 ACP 停止原因,但該對應的表達能力不如完整的 ACP 原生執行階段。 +- 初始工作階段控制項目前會公開一組聚焦的 Gateway 旋鈕:思考層級、工具詳細程度、推理、用量明細,以及提升權限動作。模型選擇與 exec 主機控制尚未公開為 ACP 設定選項。 +- `session_info_update` 和 `usage_update` 來自 Gateway 工作階段快照,而不是即時 ACP 原生執行階段計量。用量為近似值,不包含成本資料,且只有在 Gateway 將總 Token 資料標記為最新時才會發出。 +- 工具跟隨資料是盡力而為。橋接器可以公開出現在已知工具引數/結果中的檔案路徑,但尚未發出 ACP 終端機或結構化檔案差異。 + +## 用法 + +```bash +openclaw acp + +# Remote Gateway +openclaw acp --url wss://gateway-host:18789 --token + +# Remote Gateway (token from file) +openclaw acp --url wss://gateway-host:18789 --token-file ~/.openclaw/gateway.token + +# Attach to an existing session key +openclaw acp --session agent:main:main + +# Attach by label (must already exist) +openclaw acp --session-label "support inbox" + +# Reset the session key before the first prompt +openclaw acp --session agent:main:main --reset-session +``` + +## ACP 用戶端(偵錯) + +使用內建 ACP 用戶端,在沒有 IDE 的情況下對橋接器做基本檢查。 +它會產生 ACP 橋接器,並讓你以互動方式輸入提示。 + +```bash +openclaw acp client + +# Point the spawned bridge at a remote Gateway +openclaw acp client --server-args --url wss://gateway-host:18789 --token-file ~/.openclaw/gateway.token + +# Override the server command (default: openclaw) +openclaw acp client --server "node" --server-args openclaw.mjs acp --url ws://127.0.0.1:19001 +``` + +權限模型(用戶端偵錯模式): + +- 自動核准以允許清單為基礎,且只適用於受信任的核心工具 ID。 +- `read` 自動核准的範圍限於目前工作目錄(設定時為 `--cwd`)。 +- ACP 只會自動核准狹窄的唯讀類別:作用中 cwd 底下的範圍限定 `read` 呼叫,以及唯讀搜尋工具(`search`、`web_search`、`memory_search`)。未知/非核心工具、超出範圍的讀取、可執行工具、控制平面工具、變更型工具,以及互動流程一律需要明確的提示核准。 +- 伺服器提供的 `toolCall.kind` 會被視為不受信任的中繼資料(不是授權來源)。 +- 此 ACP 橋接器政策獨立於 ACPX harness 權限。如果你透過 `acpx` 後端執行 OpenClaw,`plugins.entries.acpx.config.permissionMode=approve-all` 是該 harness 工作階段的緊急「yolo」開關。 + +## 如何使用 + +當 IDE(或其他用戶端)使用代理程式用戶端通訊協定,而你想讓它驅動 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 +# preferred for local process safety +openclaw acp --url wss://gateway-host:18789 --token-file ~/.openclaw/gateway.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:` 工作階段。 + +橋接模式不支援每個工作階段的 `mcpServers`。如果 ACP 用戶端在 `newSession` 或 `loadSession` 期間傳送它們,橋接器會回傳清楚的錯誤,而不是默默忽略。 + +如果你想讓 ACPX 支援的工作階段看見 OpenClaw Plugin 工具,或所選內建工具(例如 `cron`),請啟用 Gateway 端 ACPX MCP 橋接器,而不是嘗試傳遞每個工作階段的 `mcpServers`。請參閱 [ACP 代理程式](/zh-TW/tools/acp-agents-setup#plugin-tools-mcp-bridge) 和 [OpenClaw 工具 MCP 橋接器](/zh-TW/tools/acp-agents-setup#openclaw-tools-mcp-bridge)。 + +## 從 `acpx` 使用(Codex、Claude、其他 ACP 用戶端) + +如果你想讓 Codex 或 Claude Code 這類程式碼代理程式透過 ACP 與你的 OpenClaw bot 通訊,請使用 `acpx` 及其內建的 `openclaw` 目標。 + +典型流程: + +1. 執行 Gateway,並確認 ACP 橋接器能連到它。 +2. 將 `acpx openclaw` 指向 `openclaw acp`。 +3. 指定你想讓程式碼代理程式使用的 OpenClaw 工作階段金鑰。 + +範例: + +```bash +# One-shot request into your default OpenClaw ACP session +acpx openclaw exec "Summarize the active OpenClaw session state." + +# Persistent named session for follow-up turns +acpx openclaw sessions ensure --name codex-bridge +acpx openclaw -s codex-bridge --cwd /path/to/repo \ + "Ask my OpenClaw work agent for recent context relevant to this repo." +``` + +如果你想讓 `acpx openclaw` 每次都指定特定 Gateway 和工作階段金鑰,請在 `~/.acpx/config.json` 中覆寫 `openclaw` 代理程式命令: + +```json +{ + "agents": { + "openclaw": { + "command": "env OPENCLAW_HIDE_BANNER=1 OPENCLAW_SUPPRESS_NOTES=1 openclaw acp --url ws://127.0.0.1:18789 --token-file ~/.openclaw/gateway.token --session agent:main:main" + } + } +} +``` + +對於 repo 本機的 OpenClaw checkout,請使用直接 CLI 進入點,而不是 dev runner,讓 ACP 串流保持乾淨。例如: + +```bash +env OPENCLAW_HIDE_BANNER=1 OPENCLAW_SUPPRESS_NOTES=1 node openclaw.mjs acp ... +``` + +這是讓 Codex、Claude Code 或其他支援 ACP 的用戶端從 OpenClaw 代理程式擷取情境資訊,而不需要擷取終端機內容的最簡單方式。 + +## Zed 編輯器設定 + +在 `~/.config/zed/settings.json` 中新增自訂 ACP 代理程式(或使用 Zed 的設定 UI): + +```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 中,開啟代理面板並選取「OpenClaw ACP」以啟動對話串。 + +## 工作階段對應 + +預設情況下,ACP 工作階段會取得具有 `acp:` 前綴的隔離 Gateway 工作階段金鑰。 +若要重複使用已知工作階段,請傳入工作階段金鑰或標籤: + +- `--session `:使用特定 Gateway 工作階段金鑰。 +- `--session-label