diff --git a/docs/docs.json b/docs/docs.json index 490265be9d..5cc1092f9d 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -1319,473 +1319,11 @@ "language": "es", "tabs": [ { - "tab": "Get started", + "tab": "Comenzar", "groups": [ { - "group": "Overview", - "pages": ["es/index", "es/concepts/features", "es/start/showcase", "es/start/lore"] - }, - { - "group": "First run", - "pages": [ - "es/start/getting-started", - { - "group": "Onboarding", - "pages": ["es/start/wizard", "es/start/onboarding", "es/start/bootstrapping"] - }, - "es/start/pairing" - ] - }, - { - "group": "Use cases", - "pages": ["es/start/openclaw"] - } - ] - }, - { - "tab": "Install", - "groups": [ - { - "group": "Install overview", - "pages": ["es/install/index", "es/install/installer"] - }, - { - "group": "Install methods", - "pages": [ - "es/install/node", - "es/install/docker", - "es/install/nix", - "es/install/ansible", - "es/install/bun" - ] - }, - { - "group": "Maintenance", - "pages": ["es/install/updating", "es/install/migrating", "es/install/uninstall"] - }, - { - "group": "Advanced", - "pages": ["es/install/development-channels"] - } - ] - }, - { - "tab": "Channels", - "groups": [ - { - "group": "Overview", - "pages": ["es/channels/index"] - }, - { - "group": "Messaging platforms", - "pages": [ - "es/channels/whatsapp", - "es/channels/telegram", - "es/channels/grammy", - "es/channels/discord", - "es/channels/slack", - "es/channels/feishu", - "es/channels/googlechat", - "es/channels/mattermost", - "es/channels/signal", - "es/channels/imessage", - "es/channels/msteams", - "es/channels/line", - "es/channels/matrix", - "es/channels/zalo", - "es/channels/zalouser" - ] - }, - { - "group": "Configuration", - "pages": [ - "es/concepts/group-messages", - "es/concepts/groups", - "es/broadcast-groups", - "es/concepts/channel-routing", - "es/channels/location", - "es/channels/troubleshooting" - ] - } - ] - }, - { - "tab": "Agents", - "groups": [ - { - "group": "Fundamentals", - "pages": [ - "es/concepts/architecture", - "es/concepts/agent", - "es/concepts/agent-loop", - "es/concepts/system-prompt", - "es/concepts/context", - "es/concepts/agent-workspace", - "es/concepts/oauth" - ] - }, - { - "group": "Sessions and memory", - "pages": [ - "es/concepts/session", - "es/concepts/sessions", - "es/concepts/session-pruning", - "es/concepts/session-tool", - "es/concepts/memory", - "es/concepts/compaction" - ] - }, - { - "group": "Multi-agent", - "pages": ["es/concepts/multi-agent", "es/concepts/presence"] - }, - { - "group": "Messages and delivery", - "pages": [ - "es/concepts/messages", - "es/concepts/streaming", - "es/concepts/retry", - "es/concepts/queue" - ] - } - ] - }, - { - "tab": "Tools", - "groups": [ - { - "group": "Overview", - "pages": ["es/tools/index"] - }, - { - "group": "Built-in tools", - "pages": [ - "es/tools/lobster", - "es/tools/llm-task", - "es/tools/exec", - "es/tools/web", - "es/tools/apply-patch", - "es/tools/elevated", - "es/tools/thinking", - "es/tools/reactions" - ] - }, - { - "group": "Browser", - "pages": [ - "es/tools/browser", - "es/tools/browser-login", - "es/tools/chrome-extension", - "es/tools/browser-linux-troubleshooting" - ] - }, - { - "group": "Agent coordination", - "pages": [ - "es/tools/agent-send", - "es/tools/subagents", - "es/multi-agent-sandbox-tools" - ] - }, - { - "group": "Skills and extensions", - "pages": [ - "es/tools/slash-commands", - "es/tools/skills", - "es/tools/skills-config", - "es/tools/clawhub", - "es/plugin", - "es/plugins/voice-call", - "es/plugins/zalouser" - ] - }, - { - "group": "Automation", - "pages": [ - "es/hooks", - "es/hooks/soul-evil", - "es/automation/cron-jobs", - "es/automation/cron-vs-heartbeat", - "es/automation/webhook", - "es/automation/gmail-pubsub", - "es/automation/poll", - "es/automation/auth-monitoring" - ] - }, - { - "group": "Media and devices", - "pages": [ - "es/nodes/index", - "es/nodes/images", - "es/nodes/audio", - "es/nodes/camera", - "es/nodes/talk", - "es/nodes/voicewake", - "es/nodes/location-command" - ] - } - ] - }, - { - "tab": "Models", - "groups": [ - { - "group": "Overview", - "pages": ["es/providers/index", "es/providers/models", "es/concepts/models"] - }, - { - "group": "Configuration", - "pages": ["es/concepts/model-providers", "es/concepts/model-failover"] - }, - { - "group": "Providers", - "pages": [ - "es/providers/anthropic", - "es/providers/openai", - "es/providers/openrouter", - "es/bedrock", - "es/providers/vercel-ai-gateway", - "es/providers/moonshot", - "es/providers/minimax", - "es/providers/opencode", - "es/providers/glm", - "es/providers/zai", - "es/providers/synthetic" - ] - } - ] - }, - { - "tab": "Gateway & Ops", - "groups": [ - { - "group": "Gateway", - "pages": [ - "es/gateway/index", - { - "group": "Configuration and operations", - "pages": [ - "es/gateway/configuration", - "es/gateway/configuration-examples", - "es/gateway/authentication", - "es/gateway/health", - "es/gateway/heartbeat", - "es/gateway/doctor", - "es/gateway/logging", - "es/gateway/gateway-lock", - "es/gateway/background-process", - "es/gateway/multiple-gateways", - "es/gateway/troubleshooting" - ] - }, - { - "group": "Security and sandboxing", - "pages": [ - "es/gateway/security/index", - "es/gateway/sandboxing", - "es/gateway/sandbox-vs-tool-policy-vs-elevated" - ] - }, - { - "group": "Protocols and APIs", - "pages": [ - "es/gateway/protocol", - "es/gateway/bridge-protocol", - "es/gateway/openai-http-api", - "es/gateway/tools-invoke-http-api", - "es/gateway/cli-backends", - "es/gateway/local-models" - ] - }, - { - "group": "Networking and discovery", - "pages": [ - "es/gateway/network-model", - "es/gateway/pairing", - "es/gateway/discovery", - "es/gateway/bonjour" - ] - } - ] - }, - { - "group": "Remote access and deployment", - "pages": [ - "es/gateway/remote", - "es/gateway/remote-gateway-readme", - "es/gateway/tailscale", - "es/platforms/fly", - "es/platforms/hetzner", - "es/platforms/gcp", - "es/platforms/macos-vm", - "es/platforms/exe-dev", - "es/railway", - "es/render", - "es/northflank" - ] - }, - { - "group": "Security", - "pages": ["es/security/formal-verification"] - }, - { - "group": "Web interfaces", - "pages": [ - "es/web/index", - "es/web/control-ui", - "es/web/dashboard", - "es/web/webchat", - "es/tui" - ] - } - ] - }, - { - "tab": "Platforms", - "groups": [ - { - "group": "Platforms overview", - "pages": [ - "es/platforms/index", - "es/platforms/macos", - "es/platforms/linux", - "es/platforms/windows", - "es/platforms/android", - "es/platforms/ios" - ] - }, - { - "group": "macOS companion app", - "pages": [ - "es/platforms/mac/dev-setup", - "es/platforms/mac/menu-bar", - "es/platforms/mac/voicewake", - "es/platforms/mac/voice-overlay", - "es/platforms/mac/webchat", - "es/platforms/mac/canvas", - "es/platforms/mac/child-process", - "es/platforms/mac/health", - "es/platforms/mac/icon", - "es/platforms/mac/logging", - "es/platforms/mac/permissions", - "es/platforms/mac/remote", - "es/platforms/mac/signing", - "es/platforms/mac/release", - "es/platforms/mac/bundled-gateway", - "es/platforms/mac/xpc", - "es/platforms/mac/skills", - "es/platforms/mac/peekaboo" - ] - } - ] - }, - { - "tab": "Reference", - "groups": [ - { - "group": "CLI commands", - "pages": [ - "es/cli/index", - "es/cli/agent", - "es/cli/agents", - "es/cli/approvals", - "es/cli/browser", - "es/cli/channels", - "es/cli/configure", - "es/cli/cron", - "es/cli/dashboard", - "es/cli/directory", - "es/cli/dns", - "es/cli/docs", - "es/cli/doctor", - "es/cli/gateway", - "es/cli/health", - "es/cli/hooks", - "es/cli/logs", - "es/cli/memory", - "es/cli/message", - "es/cli/models", - "es/cli/nodes", - "es/cli/onboard", - "es/cli/pairing", - "es/cli/plugins", - "es/cli/reset", - "es/cli/sandbox", - "es/cli/security", - "es/cli/sessions", - "es/cli/setup", - "es/cli/skills", - "es/cli/status", - "es/cli/system", - "es/cli/tui", - "es/cli/uninstall", - "es/cli/update", - "es/cli/voicecall" - ] - }, - { - "group": "RPC and API", - "pages": ["es/reference/rpc", "es/reference/device-models"] - }, - { - "group": "Templates", - "pages": [ - "es/reference/AGENTS.default", - "es/reference/templates/AGENTS", - "es/reference/templates/BOOT", - "es/reference/templates/BOOTSTRAP", - "es/reference/templates/HEARTBEAT", - "es/reference/templates/IDENTITY", - "es/reference/templates/SOUL", - "es/reference/templates/TOOLS", - "es/reference/templates/USER" - ] - }, - { - "group": "Technical reference", - "pages": [ - "es/concepts/typebox", - "es/concepts/markdown-formatting", - "es/concepts/typing-indicators", - "es/concepts/usage-tracking", - "es/concepts/timezone", - "es/token-use" - ] - }, - { - "group": "Project", - "pages": ["es/reference/credits"] - }, - { - "group": "Release notes", - "pages": ["es/reference/RELEASING", "es/reference/test"] - } - ] - }, - { - "tab": "Help", - "groups": [ - { - "group": "Help", - "pages": ["es/help/index", "es/help/troubleshooting", "es/help/faq"] - }, - { - "group": "Environment and debugging", - "pages": [ - "es/environment", - "es/debugging", - "es/testing", - "es/scripts", - "es/reference/session-management-compaction" - ] - }, - { - "group": "Developer workflows", - "pages": ["es/start/setup"] - }, - { - "group": "Docs meta", - "pages": ["es/start/hubs", "es/start/docs-directory"] + "group": "Documentación", + "pages": ["es/index"] } ] } @@ -1795,490 +1333,11 @@ "language": "pt-BR", "tabs": [ { - "tab": "Get started", + "tab": "Começar", "groups": [ { - "group": "Overview", - "pages": [ - "pt-BR/index", - "pt-BR/concepts/features", - "pt-BR/start/showcase", - "pt-BR/start/lore" - ] - }, - { - "group": "First run", - "pages": [ - "pt-BR/start/getting-started", - { - "group": "Onboarding", - "pages": [ - "pt-BR/start/wizard", - "pt-BR/start/onboarding", - "pt-BR/start/bootstrapping" - ] - }, - "pt-BR/start/pairing" - ] - }, - { - "group": "Use cases", - "pages": ["pt-BR/start/openclaw"] - } - ] - }, - { - "tab": "Install", - "groups": [ - { - "group": "Install overview", - "pages": ["pt-BR/install/index", "pt-BR/install/installer"] - }, - { - "group": "Install methods", - "pages": [ - "pt-BR/install/node", - "pt-BR/install/docker", - "pt-BR/install/nix", - "pt-BR/install/ansible", - "pt-BR/install/bun" - ] - }, - { - "group": "Maintenance", - "pages": [ - "pt-BR/install/updating", - "pt-BR/install/migrating", - "pt-BR/install/uninstall" - ] - }, - { - "group": "Advanced", - "pages": ["pt-BR/install/development-channels"] - } - ] - }, - { - "tab": "Channels", - "groups": [ - { - "group": "Overview", - "pages": ["pt-BR/channels/index"] - }, - { - "group": "Messaging platforms", - "pages": [ - "pt-BR/channels/whatsapp", - "pt-BR/channels/telegram", - "pt-BR/channels/grammy", - "pt-BR/channels/discord", - "pt-BR/channels/slack", - "pt-BR/channels/feishu", - "pt-BR/channels/googlechat", - "pt-BR/channels/mattermost", - "pt-BR/channels/signal", - "pt-BR/channels/imessage", - "pt-BR/channels/msteams", - "pt-BR/channels/line", - "pt-BR/channels/matrix", - "pt-BR/channels/zalo", - "pt-BR/channels/zalouser" - ] - }, - { - "group": "Configuration", - "pages": [ - "pt-BR/concepts/group-messages", - "pt-BR/concepts/groups", - "pt-BR/broadcast-groups", - "pt-BR/concepts/channel-routing", - "pt-BR/channels/location", - "pt-BR/channels/troubleshooting" - ] - } - ] - }, - { - "tab": "Agents", - "groups": [ - { - "group": "Fundamentals", - "pages": [ - "pt-BR/concepts/architecture", - "pt-BR/concepts/agent", - "pt-BR/concepts/agent-loop", - "pt-BR/concepts/system-prompt", - "pt-BR/concepts/context", - "pt-BR/concepts/agent-workspace", - "pt-BR/concepts/oauth" - ] - }, - { - "group": "Sessions and memory", - "pages": [ - "pt-BR/concepts/session", - "pt-BR/concepts/sessions", - "pt-BR/concepts/session-pruning", - "pt-BR/concepts/session-tool", - "pt-BR/concepts/memory", - "pt-BR/concepts/compaction" - ] - }, - { - "group": "Multi-agent", - "pages": ["pt-BR/concepts/multi-agent", "pt-BR/concepts/presence"] - }, - { - "group": "Messages and delivery", - "pages": [ - "pt-BR/concepts/messages", - "pt-BR/concepts/streaming", - "pt-BR/concepts/retry", - "pt-BR/concepts/queue" - ] - } - ] - }, - { - "tab": "Tools", - "groups": [ - { - "group": "Overview", - "pages": ["pt-BR/tools/index"] - }, - { - "group": "Built-in tools", - "pages": [ - "pt-BR/tools/lobster", - "pt-BR/tools/llm-task", - "pt-BR/tools/exec", - "pt-BR/tools/web", - "pt-BR/tools/apply-patch", - "pt-BR/tools/elevated", - "pt-BR/tools/thinking", - "pt-BR/tools/reactions" - ] - }, - { - "group": "Browser", - "pages": [ - "pt-BR/tools/browser", - "pt-BR/tools/browser-login", - "pt-BR/tools/chrome-extension", - "pt-BR/tools/browser-linux-troubleshooting" - ] - }, - { - "group": "Agent coordination", - "pages": [ - "pt-BR/tools/agent-send", - "pt-BR/tools/subagents", - "pt-BR/multi-agent-sandbox-tools" - ] - }, - { - "group": "Skills and extensions", - "pages": [ - "pt-BR/tools/slash-commands", - "pt-BR/tools/skills", - "pt-BR/tools/skills-config", - "pt-BR/tools/clawhub", - "pt-BR/plugin", - "pt-BR/plugins/voice-call", - "pt-BR/plugins/zalouser" - ] - }, - { - "group": "Automation", - "pages": [ - "pt-BR/hooks", - "pt-BR/hooks/soul-evil", - "pt-BR/automation/cron-jobs", - "pt-BR/automation/cron-vs-heartbeat", - "pt-BR/automation/webhook", - "pt-BR/automation/gmail-pubsub", - "pt-BR/automation/poll", - "pt-BR/automation/auth-monitoring" - ] - }, - { - "group": "Media and devices", - "pages": [ - "pt-BR/nodes/index", - "pt-BR/nodes/images", - "pt-BR/nodes/audio", - "pt-BR/nodes/camera", - "pt-BR/nodes/talk", - "pt-BR/nodes/voicewake", - "pt-BR/nodes/location-command" - ] - } - ] - }, - { - "tab": "Models", - "groups": [ - { - "group": "Overview", - "pages": [ - "pt-BR/providers/index", - "pt-BR/providers/models", - "pt-BR/concepts/models" - ] - }, - { - "group": "Configuration", - "pages": ["pt-BR/concepts/model-providers", "pt-BR/concepts/model-failover"] - }, - { - "group": "Providers", - "pages": [ - "pt-BR/providers/anthropic", - "pt-BR/providers/openai", - "pt-BR/providers/openrouter", - "pt-BR/bedrock", - "pt-BR/providers/vercel-ai-gateway", - "pt-BR/providers/moonshot", - "pt-BR/providers/minimax", - "pt-BR/providers/opencode", - "pt-BR/providers/glm", - "pt-BR/providers/zai", - "pt-BR/providers/synthetic" - ] - } - ] - }, - { - "tab": "Gateway & Ops", - "groups": [ - { - "group": "Gateway", - "pages": [ - "pt-BR/gateway/index", - { - "group": "Configuration and operations", - "pages": [ - "pt-BR/gateway/configuration", - "pt-BR/gateway/configuration-examples", - "pt-BR/gateway/authentication", - "pt-BR/gateway/health", - "pt-BR/gateway/heartbeat", - "pt-BR/gateway/doctor", - "pt-BR/gateway/logging", - "pt-BR/gateway/gateway-lock", - "pt-BR/gateway/background-process", - "pt-BR/gateway/multiple-gateways", - "pt-BR/gateway/troubleshooting" - ] - }, - { - "group": "Security and sandboxing", - "pages": [ - "pt-BR/gateway/security/index", - "pt-BR/gateway/sandboxing", - "pt-BR/gateway/sandbox-vs-tool-policy-vs-elevated" - ] - }, - { - "group": "Protocols and APIs", - "pages": [ - "pt-BR/gateway/protocol", - "pt-BR/gateway/bridge-protocol", - "pt-BR/gateway/openai-http-api", - "pt-BR/gateway/tools-invoke-http-api", - "pt-BR/gateway/cli-backends", - "pt-BR/gateway/local-models" - ] - }, - { - "group": "Networking and discovery", - "pages": [ - "pt-BR/gateway/network-model", - "pt-BR/gateway/pairing", - "pt-BR/gateway/discovery", - "pt-BR/gateway/bonjour" - ] - } - ] - }, - { - "group": "Remote access and deployment", - "pages": [ - "pt-BR/gateway/remote", - "pt-BR/gateway/remote-gateway-readme", - "pt-BR/gateway/tailscale", - "pt-BR/platforms/fly", - "pt-BR/platforms/hetzner", - "pt-BR/platforms/gcp", - "pt-BR/platforms/macos-vm", - "pt-BR/platforms/exe-dev", - "pt-BR/railway", - "pt-BR/render", - "pt-BR/northflank" - ] - }, - { - "group": "Security", - "pages": ["pt-BR/security/formal-verification"] - }, - { - "group": "Web interfaces", - "pages": [ - "pt-BR/web/index", - "pt-BR/web/control-ui", - "pt-BR/web/dashboard", - "pt-BR/web/webchat", - "pt-BR/tui" - ] - } - ] - }, - { - "tab": "Platforms", - "groups": [ - { - "group": "Platforms overview", - "pages": [ - "pt-BR/platforms/index", - "pt-BR/platforms/macos", - "pt-BR/platforms/linux", - "pt-BR/platforms/windows", - "pt-BR/platforms/android", - "pt-BR/platforms/ios" - ] - }, - { - "group": "macOS companion app", - "pages": [ - "pt-BR/platforms/mac/dev-setup", - "pt-BR/platforms/mac/menu-bar", - "pt-BR/platforms/mac/voicewake", - "pt-BR/platforms/mac/voice-overlay", - "pt-BR/platforms/mac/webchat", - "pt-BR/platforms/mac/canvas", - "pt-BR/platforms/mac/child-process", - "pt-BR/platforms/mac/health", - "pt-BR/platforms/mac/icon", - "pt-BR/platforms/mac/logging", - "pt-BR/platforms/mac/permissions", - "pt-BR/platforms/mac/remote", - "pt-BR/platforms/mac/signing", - "pt-BR/platforms/mac/release", - "pt-BR/platforms/mac/bundled-gateway", - "pt-BR/platforms/mac/xpc", - "pt-BR/platforms/mac/skills", - "pt-BR/platforms/mac/peekaboo" - ] - } - ] - }, - { - "tab": "Reference", - "groups": [ - { - "group": "CLI commands", - "pages": [ - "pt-BR/cli/index", - "pt-BR/cli/agent", - "pt-BR/cli/agents", - "pt-BR/cli/approvals", - "pt-BR/cli/browser", - "pt-BR/cli/channels", - "pt-BR/cli/configure", - "pt-BR/cli/cron", - "pt-BR/cli/dashboard", - "pt-BR/cli/directory", - "pt-BR/cli/dns", - "pt-BR/cli/docs", - "pt-BR/cli/doctor", - "pt-BR/cli/gateway", - "pt-BR/cli/health", - "pt-BR/cli/hooks", - "pt-BR/cli/logs", - "pt-BR/cli/memory", - "pt-BR/cli/message", - "pt-BR/cli/models", - "pt-BR/cli/nodes", - "pt-BR/cli/onboard", - "pt-BR/cli/pairing", - "pt-BR/cli/plugins", - "pt-BR/cli/reset", - "pt-BR/cli/sandbox", - "pt-BR/cli/security", - "pt-BR/cli/sessions", - "pt-BR/cli/setup", - "pt-BR/cli/skills", - "pt-BR/cli/status", - "pt-BR/cli/system", - "pt-BR/cli/tui", - "pt-BR/cli/uninstall", - "pt-BR/cli/update", - "pt-BR/cli/voicecall" - ] - }, - { - "group": "RPC and API", - "pages": ["pt-BR/reference/rpc", "pt-BR/reference/device-models"] - }, - { - "group": "Templates", - "pages": [ - "pt-BR/reference/AGENTS.default", - "pt-BR/reference/templates/AGENTS", - "pt-BR/reference/templates/BOOT", - "pt-BR/reference/templates/BOOTSTRAP", - "pt-BR/reference/templates/HEARTBEAT", - "pt-BR/reference/templates/IDENTITY", - "pt-BR/reference/templates/SOUL", - "pt-BR/reference/templates/TOOLS", - "pt-BR/reference/templates/USER" - ] - }, - { - "group": "Technical reference", - "pages": [ - "pt-BR/concepts/typebox", - "pt-BR/concepts/markdown-formatting", - "pt-BR/concepts/typing-indicators", - "pt-BR/concepts/usage-tracking", - "pt-BR/concepts/timezone", - "pt-BR/token-use" - ] - }, - { - "group": "Project", - "pages": ["pt-BR/reference/credits"] - }, - { - "group": "Release notes", - "pages": ["pt-BR/reference/RELEASING", "pt-BR/reference/test"] - } - ] - }, - { - "tab": "Help", - "groups": [ - { - "group": "Help", - "pages": ["pt-BR/help/index", "pt-BR/help/troubleshooting", "pt-BR/help/faq"] - }, - { - "group": "Environment and debugging", - "pages": [ - "pt-BR/environment", - "pt-BR/debugging", - "pt-BR/testing", - "pt-BR/scripts", - "pt-BR/reference/session-management-compaction" - ] - }, - { - "group": "Developer workflows", - "pages": ["pt-BR/start/setup"] - }, - { - "group": "Docs meta", - "pages": ["pt-BR/start/hubs", "pt-BR/start/docs-directory"] + "group": "Documentação", + "pages": ["pt-BR/index"] } ] } diff --git a/docs/es/automation/auth-monitoring.md b/docs/es/automation/auth-monitoring.md deleted file mode 100644 index 877a1c2ce2..0000000000 --- a/docs/es/automation/auth-monitoring.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -summary: "Monitor OAuth expiry for model providers" -read_when: - - Setting up auth expiry monitoring or alerts - - Automating Claude Code / Codex OAuth refresh checks -title: "Auth Monitoring" ---- - -# Auth monitoring - -OpenClaw exposes OAuth expiry health via `openclaw models status`. Use that for -automation and alerting; scripts are optional extras for phone workflows. - -## Preferred: CLI check (portable) - -```bash -openclaw models status --check -``` - -Exit codes: - -- `0`: OK -- `1`: expired or missing credentials -- `2`: expiring soon (within 24h) - -This works in cron/systemd and requires no extra scripts. - -## Optional scripts (ops / phone workflows) - -These live under `scripts/` and are **optional**. They assume SSH access to the -gateway host and are tuned for systemd + Termux. - -- `scripts/claude-auth-status.sh` now uses `openclaw models status --json` as the - source of truth (falling back to direct file reads if the CLI is unavailable), - so keep `openclaw` on `PATH` for timers. -- `scripts/auth-monitor.sh`: cron/systemd timer target; sends alerts (ntfy or phone). -- `scripts/systemd/openclaw-auth-monitor.{service,timer}`: systemd user timer. -- `scripts/claude-auth-status.sh`: Claude Code + OpenClaw auth checker (full/json/simple). -- `scripts/mobile-reauth.sh`: guided re‑auth flow over SSH. -- `scripts/termux-quick-auth.sh`: one‑tap widget status + open auth URL. -- `scripts/termux-auth-widget.sh`: full guided widget flow. -- `scripts/termux-sync-widget.sh`: sync Claude Code creds → OpenClaw. - -If you don’t need phone automation or systemd timers, skip these scripts. diff --git a/docs/es/automation/cron-jobs.md b/docs/es/automation/cron-jobs.md deleted file mode 100644 index 8eb79881ec..0000000000 --- a/docs/es/automation/cron-jobs.md +++ /dev/null @@ -1,468 +0,0 @@ ---- -summary: "Cron jobs + wakeups for the Gateway scheduler" -read_when: - - Scheduling background jobs or wakeups - - Wiring automation that should run with or alongside heartbeats - - Deciding between heartbeat and cron for scheduled tasks -title: "Cron Jobs" ---- - -# Cron jobs (Gateway scheduler) - -> **Cron vs Heartbeat?** See [Cron vs Heartbeat](/automation/cron-vs-heartbeat) for guidance on when to use each. - -Cron is the Gateway’s built-in scheduler. It persists jobs, wakes the agent at -the right time, and can optionally deliver output back to a chat. - -If you want _“run this every morning”_ or _“poke the agent in 20 minutes”_, -cron is the mechanism. - -## TL;DR - -- Cron runs **inside the Gateway** (not inside the model). -- Jobs persist under `~/.openclaw/cron/` so restarts don’t lose schedules. -- Two execution styles: - - **Main session**: enqueue a system event, then run on the next heartbeat. - - **Isolated**: run a dedicated agent turn in `cron:`, with delivery (announce by default or none). -- Wakeups are first-class: a job can request “wake now” vs “next heartbeat”. - -## Quick start (actionable) - -Create a one-shot reminder, verify it exists, and run it immediately: - -```bash -openclaw cron add \ - --name "Reminder" \ - --at "2026-02-01T16:00:00Z" \ - --session main \ - --system-event "Reminder: check the cron docs draft" \ - --wake now \ - --delete-after-run - -openclaw cron list -openclaw cron run --force -openclaw cron runs --id -``` - -Schedule a recurring isolated job with delivery: - -```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" -``` - -## Tool-call equivalents (Gateway cron tool) - -For the canonical JSON shapes and examples, see [JSON schema for tool calls](/automation/cron-jobs#json-schema-for-tool-calls). - -## Where cron jobs are stored - -Cron jobs are persisted on the Gateway host at `~/.openclaw/cron/jobs.json` by default. -The Gateway loads the file into memory and writes it back on changes, so manual edits -are only safe when the Gateway is stopped. Prefer `openclaw cron add/edit` or the cron -tool call API for changes. - -## Beginner-friendly overview - -Think of a cron job as: **when** to run + **what** to do. - -1. **Choose a schedule** - - One-shot reminder → `schedule.kind = "at"` (CLI: `--at`) - - Repeating job → `schedule.kind = "every"` or `schedule.kind = "cron"` - - If your ISO timestamp omits a timezone, it is treated as **UTC**. - -2. **Choose where it runs** - - `sessionTarget: "main"` → run during the next heartbeat with main context. - - `sessionTarget: "isolated"` → run a dedicated agent turn in `cron:`. - -3. **Choose the payload** - - Main session → `payload.kind = "systemEvent"` - - Isolated session → `payload.kind = "agentTurn"` - -Optional: one-shot jobs (`schedule.kind = "at"`) delete after success by default. Set -`deleteAfterRun: false` to keep them (they will disable after success). - -## Concepts - -### Jobs - -A cron job is a stored record with: - -- a **schedule** (when it should run), -- a **payload** (what it should do), -- optional **delivery mode** (announce or none). -- optional **agent binding** (`agentId`): run the job under a specific agent; if - missing or unknown, the gateway falls back to the default agent. - -Jobs are identified by a stable `jobId` (used by CLI/Gateway APIs). -In agent tool calls, `jobId` is canonical; legacy `id` is accepted for compatibility. -One-shot jobs auto-delete after success by default; set `deleteAfterRun: false` to keep them. - -### Schedules - -Cron supports three schedule kinds: - -- `at`: one-shot timestamp via `schedule.at` (ISO 8601). -- `every`: fixed interval (ms). -- `cron`: 5-field cron expression with optional IANA timezone. - -Cron expressions use `croner`. If a timezone is omitted, the Gateway host’s -local timezone is used. - -### Main vs isolated execution - -#### Main session jobs (system events) - -Main jobs enqueue a system event and optionally wake the heartbeat runner. -They must use `payload.kind = "systemEvent"`. - -- `wakeMode: "next-heartbeat"` (default): event waits for the next scheduled heartbeat. -- `wakeMode: "now"`: event triggers an immediate heartbeat run. - -This is the best fit when you want the normal heartbeat prompt + main-session context. -See [Heartbeat](/gateway/heartbeat). - -#### Isolated jobs (dedicated cron sessions) - -Isolated jobs run a dedicated agent turn in session `cron:`. - -Key behaviors: - -- Prompt is prefixed with `[cron: ]` for traceability. -- Each run starts a **fresh session id** (no prior conversation carry-over). -- Default behavior: if `delivery` is omitted, isolated jobs announce a summary (`delivery.mode = "announce"`). -- `delivery.mode` (isolated-only) chooses what happens: - - `announce`: deliver a summary to the target channel and post a brief summary to the main session. - - `none`: internal only (no delivery, no main-session summary). -- `wakeMode` controls when the main-session summary posts: - - `now`: immediate heartbeat. - - `next-heartbeat`: waits for the next scheduled heartbeat. - -Use isolated jobs for noisy, frequent, or "background chores" that shouldn't spam -your main chat history. - -### Payload shapes (what runs) - -Two payload kinds are supported: - -- `systemEvent`: main-session only, routed through the heartbeat prompt. -- `agentTurn`: isolated-session only, runs a dedicated agent turn. - -Common `agentTurn` fields: - -- `message`: required text prompt. -- `model` / `thinking`: optional overrides (see below). -- `timeoutSeconds`: optional timeout override. - -Delivery config (isolated jobs only): - -- `delivery.mode`: `none` | `announce`. -- `delivery.channel`: `last` or a specific channel. -- `delivery.to`: channel-specific target (phone/chat/channel id). -- `delivery.bestEffort`: avoid failing the job if announce delivery fails. - -Announce delivery suppresses messaging tool sends for the run; use `delivery.channel`/`delivery.to` -to target the chat instead. When `delivery.mode = "none"`, no summary is posted to the main session. - -If `delivery` is omitted for isolated jobs, OpenClaw defaults to `announce`. - -#### Announce delivery flow - -When `delivery.mode = "announce"`, cron delivers directly via the outbound channel adapters. -The main agent is not spun up to craft or forward the message. - -Behavior details: - -- Content: delivery uses the isolated run's outbound payloads (text/media) with normal chunking and - channel formatting. -- Heartbeat-only responses (`HEARTBEAT_OK` with no real content) are not delivered. -- If the isolated run already sent a message to the same target via the message tool, delivery is - skipped to avoid duplicates. -- Missing or invalid delivery targets fail the job unless `delivery.bestEffort = true`. -- A short summary is posted to the main session only when `delivery.mode = "announce"`. -- The main-session summary respects `wakeMode`: `now` triggers an immediate heartbeat and - `next-heartbeat` waits for the next scheduled heartbeat. - -### Model and thinking overrides - -Isolated jobs (`agentTurn`) can override the model and thinking level: - -- `model`: Provider/model string (e.g., `anthropic/claude-sonnet-4-20250514`) or alias (e.g., `opus`) -- `thinking`: Thinking level (`off`, `minimal`, `low`, `medium`, `high`, `xhigh`; GPT-5.2 + Codex models only) - -Note: You can set `model` on main-session jobs too, but it changes the shared main -session model. We recommend model overrides only for isolated jobs to avoid -unexpected context shifts. - -Resolution priority: - -1. Job payload override (highest) -2. Hook-specific defaults (e.g., `hooks.gmail.model`) -3. Agent config default - -### Delivery (channel + target) - -Isolated jobs can deliver output to a channel via the top-level `delivery` config: - -- `delivery.mode`: `announce` (deliver a summary) or `none`. -- `delivery.channel`: `whatsapp` / `telegram` / `discord` / `slack` / `mattermost` (plugin) / `signal` / `imessage` / `last`. -- `delivery.to`: channel-specific recipient target. - -Delivery config is only valid for isolated jobs (`sessionTarget: "isolated"`). - -If `delivery.channel` or `delivery.to` is omitted, cron can fall back to the main session’s -“last route” (the last place the agent replied). - -Target format reminders: - -- Slack/Discord/Mattermost (plugin) targets should use explicit prefixes (e.g. `channel:`, `user:`) to avoid ambiguity. -- Telegram topics should use the `:topic:` form (see below). - -#### Telegram delivery targets (topics / forum threads) - -Telegram supports forum topics via `message_thread_id`. For cron delivery, you can encode -the topic/thread into the `to` field: - -- `-1001234567890` (chat id only) -- `-1001234567890:topic:123` (preferred: explicit topic marker) -- `-1001234567890:123` (shorthand: numeric suffix) - -Prefixed targets like `telegram:...` / `telegram:group:...` are also accepted: - -- `telegram:group:-1001234567890:topic:123` - -## JSON schema for tool calls - -Use these shapes when calling Gateway `cron.*` tools directly (agent tool calls or RPC). -CLI flags accept human durations like `20m`, but tool calls should use an ISO 8601 string -for `schedule.at` and milliseconds for `schedule.everyMs`. - -### cron.add params - -One-shot, main session job (system event): - -```json -{ - "name": "Reminder", - "schedule": { "kind": "at", "at": "2026-02-01T16:00:00Z" }, - "sessionTarget": "main", - "wakeMode": "now", - "payload": { "kind": "systemEvent", "text": "Reminder text" }, - "deleteAfterRun": true -} -``` - -Recurring, isolated job with delivery: - -```json -{ - "name": "Morning brief", - "schedule": { "kind": "cron", "expr": "0 7 * * *", "tz": "America/Los_Angeles" }, - "sessionTarget": "isolated", - "wakeMode": "next-heartbeat", - "payload": { - "kind": "agentTurn", - "message": "Summarize overnight updates." - }, - "delivery": { - "mode": "announce", - "channel": "slack", - "to": "channel:C1234567890", - "bestEffort": true - } -} -``` - -Notes: - -- `schedule.kind`: `at` (`at`), `every` (`everyMs`), or `cron` (`expr`, optional `tz`). -- `schedule.at` accepts ISO 8601 (timezone optional; treated as UTC when omitted). -- `everyMs` is milliseconds. -- `sessionTarget` must be `"main"` or `"isolated"` and must match `payload.kind`. -- Optional fields: `agentId`, `description`, `enabled`, `deleteAfterRun` (defaults to true for `at`), - `delivery`. -- `wakeMode` defaults to `"next-heartbeat"` when omitted. - -### cron.update params - -```json -{ - "jobId": "job-123", - "patch": { - "enabled": false, - "schedule": { "kind": "every", "everyMs": 3600000 } - } -} -``` - -Notes: - -- `jobId` is canonical; `id` is accepted for compatibility. -- Use `agentId: null` in the patch to clear an agent binding. - -### cron.run and cron.remove params - -```json -{ "jobId": "job-123", "mode": "force" } -``` - -```json -{ "jobId": "job-123" } -``` - -## Storage & history - -- Job store: `~/.openclaw/cron/jobs.json` (Gateway-managed JSON). -- Run history: `~/.openclaw/cron/runs/.jsonl` (JSONL, auto-pruned). -- Override store path: `cron.store` in config. - -## Configuration - -```json5 -{ - cron: { - enabled: true, // default true - store: "~/.openclaw/cron/jobs.json", - maxConcurrentRuns: 1, // default 1 - }, -} -``` - -Disable cron entirely: - -- `cron.enabled: false` (config) -- `OPENCLAW_SKIP_CRON=1` (env) - -## CLI quickstart - -One-shot reminder (UTC ISO, auto-delete after success): - -```bash -openclaw cron add \ - --name "Send reminder" \ - --at "2026-01-12T18:00:00Z" \ - --session main \ - --system-event "Reminder: submit expense report." \ - --wake now \ - --delete-after-run -``` - -One-shot reminder (main session, wake immediately): - -```bash -openclaw cron add \ - --name "Calendar check" \ - --at "20m" \ - --session main \ - --system-event "Next heartbeat: check calendar." \ - --wake now -``` - -Recurring isolated job (announce to WhatsApp): - -```bash -openclaw cron add \ - --name "Morning status" \ - --cron "0 7 * * *" \ - --tz "America/Los_Angeles" \ - --session isolated \ - --message "Summarize inbox + calendar for today." \ - --announce \ - --channel whatsapp \ - --to "+15551234567" -``` - -Recurring isolated job (deliver to a Telegram topic): - -```bash -openclaw cron add \ - --name "Nightly summary (topic)" \ - --cron "0 22 * * *" \ - --tz "America/Los_Angeles" \ - --session isolated \ - --message "Summarize today; send to the nightly topic." \ - --announce \ - --channel telegram \ - --to "-1001234567890:topic:123" -``` - -Isolated job with model and thinking override: - -```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 \ - --channel whatsapp \ - --to "+15551234567" -``` - -Agent selection (multi-agent setups): - -```bash -# Pin a job to agent "ops" (falls back to default if that agent is missing) -openclaw cron add --name "Ops sweep" --cron "0 6 * * *" --session isolated --message "Check ops queue" --agent ops - -# Switch or clear the agent on an existing job -openclaw cron edit --agent ops -openclaw cron edit --clear-agent -``` - -Manual run (debug): - -```bash -openclaw cron run --force -``` - -Edit an existing job (patch fields): - -```bash -openclaw cron edit \ - --message "Updated prompt" \ - --model "opus" \ - --thinking low -``` - -Run history: - -```bash -openclaw cron runs --id --limit 50 -``` - -Immediate system event without creating a job: - -```bash -openclaw system event --mode now --text "Next heartbeat: check battery." -``` - -## Gateway API surface - -- `cron.list`, `cron.status`, `cron.add`, `cron.update`, `cron.remove` -- `cron.run` (force or due), `cron.runs` - For immediate system events without a job, use [`openclaw system event`](/cli/system). - -## Troubleshooting - -### “Nothing runs” - -- Check cron is enabled: `cron.enabled` and `OPENCLAW_SKIP_CRON`. -- Check the Gateway is running continuously (cron runs inside the Gateway process). -- For `cron` schedules: confirm timezone (`--tz`) vs the host timezone. - -### Telegram delivers to the wrong place - -- For forum topics, use `-100…:topic:` so it’s explicit and unambiguous. -- If you see `telegram:...` prefixes in logs or stored “last route” targets, that’s normal; - cron delivery accepts them and still parses topic IDs correctly. diff --git a/docs/es/automation/cron-vs-heartbeat.md b/docs/es/automation/cron-vs-heartbeat.md deleted file mode 100644 index 423565d4f3..0000000000 --- a/docs/es/automation/cron-vs-heartbeat.md +++ /dev/null @@ -1,282 +0,0 @@ ---- -summary: "Guidance for choosing between heartbeat and cron jobs for automation" -read_when: - - Deciding how to schedule recurring tasks - - Setting up background monitoring or notifications - - Optimizing token usage for periodic checks -title: "Cron vs Heartbeat" ---- - -# Cron vs Heartbeat: When to Use Each - -Both heartbeats and cron jobs let you run tasks on a schedule. This guide helps you choose the right mechanism for your use case. - -## Quick Decision Guide - -| Use Case | Recommended | Why | -| ------------------------------------ | ------------------- | ---------------------------------------- | -| Check inbox every 30 min | Heartbeat | Batches with other checks, context-aware | -| Send daily report at 9am sharp | Cron (isolated) | Exact timing needed | -| Monitor calendar for upcoming events | Heartbeat | Natural fit for periodic awareness | -| Run weekly deep analysis | Cron (isolated) | Standalone task, can use different model | -| Remind me in 20 minutes | Cron (main, `--at`) | One-shot with precise timing | -| Background project health check | Heartbeat | Piggybacks on existing cycle | - -## Heartbeat: Periodic Awareness - -Heartbeats run in the **main session** at a regular interval (default: 30 min). They're designed for the agent to check on things and surface anything important. - -### When to use heartbeat - -- **Multiple periodic checks**: Instead of 5 separate cron jobs checking inbox, calendar, weather, notifications, and project status, a single heartbeat can batch all of these. -- **Context-aware decisions**: The agent has full main-session context, so it can make smart decisions about what's urgent vs. what can wait. -- **Conversational continuity**: Heartbeat runs share the same session, so the agent remembers recent conversations and can follow up naturally. -- **Low-overhead monitoring**: One heartbeat replaces many small polling tasks. - -### Heartbeat advantages - -- **Batches multiple checks**: One agent turn can review inbox, calendar, and notifications together. -- **Reduces API calls**: A single heartbeat is cheaper than 5 isolated cron jobs. -- **Context-aware**: The agent knows what you've been working on and can prioritize accordingly. -- **Smart suppression**: If nothing needs attention, the agent replies `HEARTBEAT_OK` and no message is delivered. -- **Natural timing**: Drifts slightly based on queue load, which is fine for most monitoring. - -### Heartbeat example: HEARTBEAT.md checklist - -```md -# Heartbeat checklist - -- Check email for urgent messages -- Review calendar for events in next 2 hours -- If a background task finished, summarize results -- If idle for 8+ hours, send a brief check-in -``` - -The agent reads this on each heartbeat and handles all items in one turn. - -### Configuring heartbeat - -```json5 -{ - agents: { - defaults: { - heartbeat: { - every: "30m", // interval - target: "last", // where to deliver alerts - activeHours: { start: "08:00", end: "22:00" }, // optional - }, - }, - }, -} -``` - -See [Heartbeat](/gateway/heartbeat) for full configuration. - -## Cron: Precise Scheduling - -Cron jobs run at **exact times** and can run in isolated sessions without affecting main context. - -### When to use cron - -- **Exact timing required**: "Send this at 9:00 AM every Monday" (not "sometime around 9"). -- **Standalone tasks**: Tasks that don't need conversational context. -- **Different model/thinking**: Heavy analysis that warrants a more powerful model. -- **One-shot reminders**: "Remind me in 20 minutes" with `--at`. -- **Noisy/frequent tasks**: Tasks that would clutter main session history. -- **External triggers**: Tasks that should run independently of whether the agent is otherwise active. - -### Cron advantages - -- **Exact timing**: 5-field cron expressions with timezone support. -- **Session isolation**: Runs in `cron:` without polluting main history. -- **Model overrides**: Use a cheaper or more powerful model per job. -- **Delivery control**: Isolated jobs default to `announce` (summary); choose `none` as needed. -- **Immediate delivery**: Announce mode posts directly without waiting for heartbeat. -- **No agent context needed**: Runs even if main session is idle or compacted. -- **One-shot support**: `--at` for precise future timestamps. - -### Cron example: Daily morning briefing - -```bash -openclaw cron add \ - --name "Morning briefing" \ - --cron "0 7 * * *" \ - --tz "America/New_York" \ - --session isolated \ - --message "Generate today's briefing: weather, calendar, top emails, news summary." \ - --model opus \ - --announce \ - --channel whatsapp \ - --to "+15551234567" -``` - -This runs at exactly 7:00 AM New York time, uses Opus for quality, and announces a summary directly to WhatsApp. - -### Cron example: One-shot reminder - -```bash -openclaw cron add \ - --name "Meeting reminder" \ - --at "20m" \ - --session main \ - --system-event "Reminder: standup meeting starts in 10 minutes." \ - --wake now \ - --delete-after-run -``` - -See [Cron jobs](/automation/cron-jobs) for full CLI reference. - -## Decision Flowchart - -``` -Does the task need to run at an EXACT time? - YES -> Use cron - NO -> Continue... - -Does the task need isolation from main session? - YES -> Use cron (isolated) - NO -> Continue... - -Can this task be batched with other periodic checks? - YES -> Use heartbeat (add to HEARTBEAT.md) - NO -> Use cron - -Is this a one-shot reminder? - YES -> Use cron with --at - NO -> Continue... - -Does it need a different model or thinking level? - YES -> Use cron (isolated) with --model/--thinking - NO -> Use heartbeat -``` - -## Combining Both - -The most efficient setup uses **both**: - -1. **Heartbeat** handles routine monitoring (inbox, calendar, notifications) in one batched turn every 30 minutes. -2. **Cron** handles precise schedules (daily reports, weekly reviews) and one-shot reminders. - -### Example: Efficient automation setup - -**HEARTBEAT.md** (checked every 30 min): - -```md -# Heartbeat checklist - -- Scan inbox for urgent emails -- Check calendar for events in next 2h -- Review any pending tasks -- Light check-in if quiet for 8+ hours -``` - -**Cron jobs** (precise timing): - -```bash -# Daily morning briefing at 7am -openclaw cron add --name "Morning brief" --cron "0 7 * * *" --session isolated --message "..." --announce - -# Weekly project review on Mondays at 9am -openclaw cron add --name "Weekly review" --cron "0 9 * * 1" --session isolated --message "..." --model opus - -# One-shot reminder -openclaw cron add --name "Call back" --at "2h" --session main --system-event "Call back the client" --wake now -``` - -## Lobster: Deterministic workflows with approvals - -Lobster is the workflow runtime for **multi-step tool pipelines** that need deterministic execution and explicit approvals. -Use it when the task is more than a single agent turn, and you want a resumable workflow with human checkpoints. - -### When Lobster fits - -- **Multi-step automation**: You need a fixed pipeline of tool calls, not a one-off prompt. -- **Approval gates**: Side effects should pause until you approve, then resume. -- **Resumable runs**: Continue a paused workflow without re-running earlier steps. - -### How it pairs with heartbeat and cron - -- **Heartbeat/cron** decide _when_ a run happens. -- **Lobster** defines _what steps_ happen once the run starts. - -For scheduled workflows, use cron or heartbeat to trigger an agent turn that calls Lobster. -For ad-hoc workflows, call Lobster directly. - -### Operational notes (from the code) - -- Lobster runs as a **local subprocess** (`lobster` CLI) in tool mode and returns a **JSON envelope**. -- If the tool returns `needs_approval`, you resume with a `resumeToken` and `approve` flag. -- The tool is an **optional plugin**; enable it additively via `tools.alsoAllow: ["lobster"]` (recommended). -- If you pass `lobsterPath`, it must be an **absolute path**. - -See [Lobster](/tools/lobster) for full usage and examples. - -## Main Session vs Isolated Session - -Both heartbeat and cron can interact with the main session, but differently: - -| | Heartbeat | Cron (main) | Cron (isolated) | -| ------- | ------------------------------- | ------------------------ | -------------------------- | -| Session | Main | Main (via system event) | `cron:` | -| History | Shared | Shared | Fresh each run | -| Context | Full | Full | None (starts clean) | -| Model | Main session model | Main session model | Can override | -| Output | Delivered if not `HEARTBEAT_OK` | Heartbeat prompt + event | Announce summary (default) | - -### When to use main session cron - -Use `--session main` with `--system-event` when you want: - -- The reminder/event to appear in main session context -- The agent to handle it during the next heartbeat with full context -- No separate isolated run - -```bash -openclaw cron add \ - --name "Check project" \ - --every "4h" \ - --session main \ - --system-event "Time for a project health check" \ - --wake now -``` - -### When to use isolated cron - -Use `--session isolated` when you want: - -- A clean slate without prior context -- Different model or thinking settings -- Announce summaries directly to a channel -- History that doesn't clutter main session - -```bash -openclaw cron add \ - --name "Deep analysis" \ - --cron "0 6 * * 0" \ - --session isolated \ - --message "Weekly codebase analysis..." \ - --model opus \ - --thinking high \ - --announce -``` - -## Cost Considerations - -| Mechanism | Cost Profile | -| --------------- | ------------------------------------------------------- | -| Heartbeat | One turn every N minutes; scales with HEARTBEAT.md size | -| Cron (main) | Adds event to next heartbeat (no isolated turn) | -| Cron (isolated) | Full agent turn per job; can use cheaper model | - -**Tips**: - -- Keep `HEARTBEAT.md` small to minimize token overhead. -- Batch similar checks into heartbeat instead of multiple cron jobs. -- Use `target: "none"` on heartbeat if you only want internal processing. -- Use isolated cron with a cheaper model for routine tasks. - -## Related - -- [Heartbeat](/gateway/heartbeat) - full heartbeat configuration -- [Cron jobs](/automation/cron-jobs) - full cron CLI and API reference -- [System](/cli/system) - system events + heartbeat controls diff --git a/docs/es/automation/gmail-pubsub.md b/docs/es/automation/gmail-pubsub.md deleted file mode 100644 index 734ae6f770..0000000000 --- a/docs/es/automation/gmail-pubsub.md +++ /dev/null @@ -1,256 +0,0 @@ ---- -summary: "Gmail Pub/Sub push wired into OpenClaw webhooks via gogcli" -read_when: - - Wiring Gmail inbox triggers to OpenClaw - - Setting up Pub/Sub push for agent wake -title: "Gmail PubSub" ---- - -# Gmail Pub/Sub -> OpenClaw - -Goal: Gmail watch -> Pub/Sub push -> `gog gmail watch serve` -> OpenClaw webhook. - -## Prereqs - -- `gcloud` installed and logged in ([install guide](https://docs.cloud.google.com/sdk/docs/install-sdk)). -- `gog` (gogcli) installed and authorized for the Gmail account ([gogcli.sh](https://gogcli.sh/)). -- OpenClaw hooks enabled (see [Webhooks](/automation/webhook)). -- `tailscale` logged in ([tailscale.com](https://tailscale.com/)). Supported setup uses Tailscale Funnel for the public HTTPS endpoint. - Other tunnel services can work, but are DIY/unsupported and require manual wiring. - Right now, Tailscale is what we support. - -Example hook config (enable Gmail preset mapping): - -```json5 -{ - hooks: { - enabled: true, - token: "OPENCLAW_HOOK_TOKEN", - path: "/hooks", - presets: ["gmail"], - }, -} -``` - -To deliver the Gmail summary to a chat surface, override the preset with a mapping -that sets `deliver` + optional `channel`/`to`: - -```json5 -{ - hooks: { - enabled: true, - token: "OPENCLAW_HOOK_TOKEN", - presets: ["gmail"], - mappings: [ - { - match: { path: "gmail" }, - action: "agent", - wakeMode: "now", - name: "Gmail", - sessionKey: "hook:gmail:{{messages[0].id}}", - messageTemplate: "New email from {{messages[0].from}}\nSubject: {{messages[0].subject}}\n{{messages[0].snippet}}\n{{messages[0].body}}", - model: "openai/gpt-5.2-mini", - deliver: true, - channel: "last", - // to: "+15551234567" - }, - ], - }, -} -``` - -If you want a fixed channel, set `channel` + `to`. Otherwise `channel: "last"` -uses the last delivery route (falls back to WhatsApp). - -To force a cheaper model for Gmail runs, set `model` in the mapping -(`provider/model` or alias). If you enforce `agents.defaults.models`, include it there. - -To set a default model and thinking level specifically for Gmail hooks, add -`hooks.gmail.model` / `hooks.gmail.thinking` in your config: - -```json5 -{ - hooks: { - gmail: { - model: "openrouter/meta-llama/llama-3.3-70b-instruct:free", - thinking: "off", - }, - }, -} -``` - -Notes: - -- Per-hook `model`/`thinking` in the mapping still overrides these defaults. -- Fallback order: `hooks.gmail.model` → `agents.defaults.model.fallbacks` → primary (auth/rate-limit/timeouts). -- If `agents.defaults.models` is set, the Gmail model must be in the allowlist. -- Gmail hook content is wrapped with external-content safety boundaries by default. - To disable (dangerous), set `hooks.gmail.allowUnsafeExternalContent: true`. - -To customize payload handling further, add `hooks.mappings` or a JS/TS transform module -under `hooks.transformsDir` (see [Webhooks](/automation/webhook)). - -## Wizard (recommended) - -Use the OpenClaw helper to wire everything together (installs deps on macOS via brew): - -```bash -openclaw webhooks gmail setup \ - --account openclaw@gmail.com -``` - -Defaults: - -- Uses Tailscale Funnel for the public push endpoint. -- Writes `hooks.gmail` config for `openclaw webhooks gmail run`. -- Enables the Gmail hook preset (`hooks.presets: ["gmail"]`). - -Path note: when `tailscale.mode` is enabled, OpenClaw automatically sets -`hooks.gmail.serve.path` to `/` and keeps the public path at -`hooks.gmail.tailscale.path` (default `/gmail-pubsub`) because Tailscale -strips the set-path prefix before proxying. -If you need the backend to receive the prefixed path, set -`hooks.gmail.tailscale.target` (or `--tailscale-target`) to a full URL like -`http://127.0.0.1:8788/gmail-pubsub` and match `hooks.gmail.serve.path`. - -Want a custom endpoint? Use `--push-endpoint ` or `--tailscale off`. - -Platform note: on macOS the wizard installs `gcloud`, `gogcli`, and `tailscale` -via Homebrew; on Linux install them manually first. - -Gateway auto-start (recommended): - -- When `hooks.enabled=true` and `hooks.gmail.account` is set, the Gateway starts - `gog gmail watch serve` on boot and auto-renews the watch. -- Set `OPENCLAW_SKIP_GMAIL_WATCHER=1` to opt out (useful if you run the daemon yourself). -- Do not run the manual daemon at the same time, or you will hit - `listen tcp 127.0.0.1:8788: bind: address already in use`. - -Manual daemon (starts `gog gmail watch serve` + auto-renew): - -```bash -openclaw webhooks gmail run -``` - -## One-time setup - -1. Select the GCP project **that owns the OAuth client** used by `gog`. - -```bash -gcloud auth login -gcloud config set project -``` - -Note: Gmail watch requires the Pub/Sub topic to live in the same project as the OAuth client. - -2. Enable APIs: - -```bash -gcloud services enable gmail.googleapis.com pubsub.googleapis.com -``` - -3. Create a topic: - -```bash -gcloud pubsub topics create gog-gmail-watch -``` - -4. Allow Gmail push to publish: - -```bash -gcloud pubsub topics add-iam-policy-binding gog-gmail-watch \ - --member=serviceAccount:gmail-api-push@system.gserviceaccount.com \ - --role=roles/pubsub.publisher -``` - -## Start the watch - -```bash -gog gmail watch start \ - --account openclaw@gmail.com \ - --label INBOX \ - --topic projects//topics/gog-gmail-watch -``` - -Save the `history_id` from the output (for debugging). - -## Run the push handler - -Local example (shared token auth): - -```bash -gog gmail watch serve \ - --account openclaw@gmail.com \ - --bind 127.0.0.1 \ - --port 8788 \ - --path /gmail-pubsub \ - --token \ - --hook-url http://127.0.0.1:18789/hooks/gmail \ - --hook-token OPENCLAW_HOOK_TOKEN \ - --include-body \ - --max-bytes 20000 -``` - -Notes: - -- `--token` protects the push endpoint (`x-gog-token` or `?token=`). -- `--hook-url` points to OpenClaw `/hooks/gmail` (mapped; isolated run + summary to main). -- `--include-body` and `--max-bytes` control the body snippet sent to OpenClaw. - -Recommended: `openclaw webhooks gmail run` wraps the same flow and auto-renews the watch. - -## Expose the handler (advanced, unsupported) - -If you need a non-Tailscale tunnel, wire it manually and use the public URL in the push -subscription (unsupported, no guardrails): - -```bash -cloudflared tunnel --url http://127.0.0.1:8788 --no-autoupdate -``` - -Use the generated URL as the push endpoint: - -```bash -gcloud pubsub subscriptions create gog-gmail-watch-push \ - --topic gog-gmail-watch \ - --push-endpoint "https:///gmail-pubsub?token=" -``` - -Production: use a stable HTTPS endpoint and configure Pub/Sub OIDC JWT, then run: - -```bash -gog gmail watch serve --verify-oidc --oidc-email -``` - -## Test - -Send a message to the watched inbox: - -```bash -gog gmail send \ - --account openclaw@gmail.com \ - --to openclaw@gmail.com \ - --subject "watch test" \ - --body "ping" -``` - -Check watch state and history: - -```bash -gog gmail watch status --account openclaw@gmail.com -gog gmail history --account openclaw@gmail.com --since -``` - -## Troubleshooting - -- `Invalid topicName`: project mismatch (topic not in the OAuth client project). -- `User not authorized`: missing `roles/pubsub.publisher` on the topic. -- Empty messages: Gmail push only provides `historyId`; fetch via `gog gmail history`. - -## Cleanup - -```bash -gog gmail watch stop --account openclaw@gmail.com -gcloud pubsub subscriptions delete gog-gmail-watch-push -gcloud pubsub topics delete gog-gmail-watch -``` diff --git a/docs/es/automation/poll.md b/docs/es/automation/poll.md deleted file mode 100644 index fab0b0e073..0000000000 --- a/docs/es/automation/poll.md +++ /dev/null @@ -1,69 +0,0 @@ ---- -summary: "Poll sending via gateway + CLI" -read_when: - - Adding or modifying poll support - - Debugging poll sends from the CLI or gateway -title: "Polls" ---- - -# Polls - -## Supported channels - -- WhatsApp (web channel) -- Discord -- MS Teams (Adaptive Cards) - -## CLI - -```bash -# WhatsApp -openclaw message poll --target +15555550123 \ - --poll-question "Lunch today?" --poll-option "Yes" --poll-option "No" --poll-option "Maybe" -openclaw message poll --target 123456789@g.us \ - --poll-question "Meeting time?" --poll-option "10am" --poll-option "2pm" --poll-option "4pm" --poll-multi - -# Discord -openclaw message poll --channel discord --target channel:123456789 \ - --poll-question "Snack?" --poll-option "Pizza" --poll-option "Sushi" -openclaw message poll --channel discord --target channel:123456789 \ - --poll-question "Plan?" --poll-option "A" --poll-option "B" --poll-duration-hours 48 - -# MS Teams -openclaw message poll --channel msteams --target conversation:19:abc@thread.tacv2 \ - --poll-question "Lunch?" --poll-option "Pizza" --poll-option "Sushi" -``` - -Options: - -- `--channel`: `whatsapp` (default), `discord`, or `msteams` -- `--poll-multi`: allow selecting multiple options -- `--poll-duration-hours`: Discord-only (defaults to 24 when omitted) - -## Gateway RPC - -Method: `poll` - -Params: - -- `to` (string, required) -- `question` (string, required) -- `options` (string[], required) -- `maxSelections` (number, optional) -- `durationHours` (number, optional) -- `channel` (string, optional, default: `whatsapp`) -- `idempotencyKey` (string, required) - -## Channel differences - -- WhatsApp: 2-12 options, `maxSelections` must be within option count, ignores `durationHours`. -- Discord: 2-10 options, `durationHours` clamped to 1-768 hours (default 24). `maxSelections > 1` enables multi-select; Discord does not support a strict selection count. -- MS Teams: Adaptive Card polls (OpenClaw-managed). No native poll API; `durationHours` is ignored. - -## Agent tool (Message) - -Use the `message` tool with `poll` action (`to`, `pollQuestion`, `pollOption`, optional `pollMulti`, `pollDurationHours`, `channel`). - -Note: Discord has no “pick exactly N” mode; `pollMulti` maps to multi-select. -Teams polls are rendered as Adaptive Cards and require the gateway to stay online -to record votes in `~/.openclaw/msteams-polls.json`. diff --git a/docs/es/automation/webhook.md b/docs/es/automation/webhook.md deleted file mode 100644 index 93a474b32e..0000000000 --- a/docs/es/automation/webhook.md +++ /dev/null @@ -1,163 +0,0 @@ ---- -summary: "Webhook ingress for wake and isolated agent runs" -read_when: - - Adding or changing webhook endpoints - - Wiring external systems into OpenClaw -title: "Webhooks" ---- - -# Webhooks - -Gateway can expose a small HTTP webhook endpoint for external triggers. - -## Enable - -```json5 -{ - hooks: { - enabled: true, - token: "shared-secret", - path: "/hooks", - }, -} -``` - -Notes: - -- `hooks.token` is required when `hooks.enabled=true`. -- `hooks.path` defaults to `/hooks`. - -## Auth - -Every request must include the hook token. Prefer headers: - -- `Authorization: Bearer ` (recommended) -- `x-openclaw-token: ` -- `?token=` (deprecated; logs a warning and will be removed in a future major release) - -## Endpoints - -### `POST /hooks/wake` - -Payload: - -```json -{ "text": "System line", "mode": "now" } -``` - -- `text` **required** (string): The description of the event (e.g., "New email received"). -- `mode` optional (`now` | `next-heartbeat`): Whether to trigger an immediate heartbeat (default `now`) or wait for the next periodic check. - -Effect: - -- Enqueues a system event for the **main** session -- If `mode=now`, triggers an immediate heartbeat - -### `POST /hooks/agent` - -Payload: - -```json -{ - "message": "Run this", - "name": "Email", - "sessionKey": "hook:email:msg-123", - "wakeMode": "now", - "deliver": true, - "channel": "last", - "to": "+15551234567", - "model": "openai/gpt-5.2-mini", - "thinking": "low", - "timeoutSeconds": 120 -} -``` - -- `message` **required** (string): The prompt or message for the agent to process. -- `name` optional (string): Human-readable name for the hook (e.g., "GitHub"), used as a prefix in session summaries. -- `sessionKey` optional (string): The key used to identify the agent's session. Defaults to a random `hook:`. Using a consistent key allows for a multi-turn conversation within the hook context. -- `wakeMode` optional (`now` | `next-heartbeat`): Whether to trigger an immediate heartbeat (default `now`) or wait for the next periodic check. -- `deliver` optional (boolean): If `true`, the agent's response will be sent to the messaging channel. Defaults to `true`. Responses that are only heartbeat acknowledgments are automatically skipped. -- `channel` optional (string): The messaging channel for delivery. One of: `last`, `whatsapp`, `telegram`, `discord`, `slack`, `mattermost` (plugin), `signal`, `imessage`, `msteams`. Defaults to `last`. -- `to` optional (string): The recipient identifier for the channel (e.g., phone number for WhatsApp/Signal, chat ID for Telegram, channel ID for Discord/Slack/Mattermost (plugin), conversation ID for MS Teams). Defaults to the last recipient in the main session. -- `model` optional (string): Model override (e.g., `anthropic/claude-3-5-sonnet` or an alias). Must be in the allowed model list if restricted. -- `thinking` optional (string): Thinking level override (e.g., `low`, `medium`, `high`). -- `timeoutSeconds` optional (number): Maximum duration for the agent run in seconds. - -Effect: - -- Runs an **isolated** agent turn (own session key) -- Always posts a summary into the **main** session -- If `wakeMode=now`, triggers an immediate heartbeat - -### `POST /hooks/` (mapped) - -Custom hook names are resolved via `hooks.mappings` (see configuration). A mapping can -turn arbitrary payloads into `wake` or `agent` actions, with optional templates or -code transforms. - -Mapping options (summary): - -- `hooks.presets: ["gmail"]` enables the built-in Gmail mapping. -- `hooks.mappings` lets you define `match`, `action`, and templates in config. -- `hooks.transformsDir` + `transform.module` loads a JS/TS module for custom logic. -- Use `match.source` to keep a generic ingest endpoint (payload-driven routing). -- TS transforms require a TS loader (e.g. `bun` or `tsx`) or precompiled `.js` at runtime. -- Set `deliver: true` + `channel`/`to` on mappings to route replies to a chat surface - (`channel` defaults to `last` and falls back to WhatsApp). -- `allowUnsafeExternalContent: true` disables the external content safety wrapper for that hook - (dangerous; only for trusted internal sources). -- `openclaw webhooks gmail setup` writes `hooks.gmail` config for `openclaw webhooks gmail run`. - See [Gmail Pub/Sub](/automation/gmail-pubsub) for the full Gmail watch flow. - -## Responses - -- `200` for `/hooks/wake` -- `202` for `/hooks/agent` (async run started) -- `401` on auth failure -- `400` on invalid payload -- `413` on oversized payloads - -## Examples - -```bash -curl -X POST http://127.0.0.1:18789/hooks/wake \ - -H 'Authorization: Bearer SECRET' \ - -H 'Content-Type: application/json' \ - -d '{"text":"New email received","mode":"now"}' -``` - -```bash -curl -X POST http://127.0.0.1:18789/hooks/agent \ - -H 'x-openclaw-token: SECRET' \ - -H 'Content-Type: application/json' \ - -d '{"message":"Summarize inbox","name":"Email","wakeMode":"next-heartbeat"}' -``` - -### Use a different model - -Add `model` to the agent payload (or mapping) to override the model for that run: - -```bash -curl -X POST http://127.0.0.1:18789/hooks/agent \ - -H 'x-openclaw-token: SECRET' \ - -H 'Content-Type: application/json' \ - -d '{"message":"Summarize inbox","name":"Email","model":"openai/gpt-5.2-mini"}' -``` - -If you enforce `agents.defaults.models`, make sure the override model is included there. - -```bash -curl -X POST http://127.0.0.1:18789/hooks/gmail \ - -H 'Authorization: Bearer SECRET' \ - -H 'Content-Type: application/json' \ - -d '{"source":"gmail","messages":[{"from":"Ada","subject":"Hello","snippet":"Hi"}]}' -``` - -## Security - -- Keep hook endpoints behind loopback, tailnet, or trusted reverse proxy. -- Use a dedicated hook token; do not reuse gateway auth tokens. -- Avoid including sensitive raw payloads in webhook logs. -- Hook payloads are treated as untrusted and wrapped with safety boundaries by default. - If you must disable this for a specific hook, set `allowUnsafeExternalContent: true` - in that hook's mapping (dangerous). diff --git a/docs/es/bedrock.md b/docs/es/bedrock.md deleted file mode 100644 index 57d2ebc6e9..0000000000 --- a/docs/es/bedrock.md +++ /dev/null @@ -1,176 +0,0 @@ ---- -summary: "Use Amazon Bedrock (Converse API) models with OpenClaw" -read_when: - - You want to use Amazon Bedrock models with OpenClaw - - You need AWS credential/region setup for model calls -title: "Amazon Bedrock" ---- - -# Amazon Bedrock - -OpenClaw can use **Amazon Bedrock** models via pi‑ai’s **Bedrock Converse** -streaming provider. Bedrock auth uses the **AWS SDK default credential chain**, -not an API key. - -## What pi‑ai supports - -- Provider: `amazon-bedrock` -- API: `bedrock-converse-stream` -- Auth: AWS credentials (env vars, shared config, or instance role) -- Region: `AWS_REGION` or `AWS_DEFAULT_REGION` (default: `us-east-1`) - -## Automatic model discovery - -If AWS credentials are detected, OpenClaw can automatically discover Bedrock -models that support **streaming** and **text output**. Discovery uses -`bedrock:ListFoundationModels` and is cached (default: 1 hour). - -Config options live under `models.bedrockDiscovery`: - -```json5 -{ - models: { - bedrockDiscovery: { - enabled: true, - region: "us-east-1", - providerFilter: ["anthropic", "amazon"], - refreshInterval: 3600, - defaultContextWindow: 32000, - defaultMaxTokens: 4096, - }, - }, -} -``` - -Notes: - -- `enabled` defaults to `true` when AWS credentials are present. -- `region` defaults to `AWS_REGION` or `AWS_DEFAULT_REGION`, then `us-east-1`. -- `providerFilter` matches Bedrock provider names (for example `anthropic`). -- `refreshInterval` is seconds; set to `0` to disable caching. -- `defaultContextWindow` (default: `32000`) and `defaultMaxTokens` (default: `4096`) - are used for discovered models (override if you know your model limits). - -## Setup (manual) - -1. Ensure AWS credentials are available on the **gateway host**: - -```bash -export AWS_ACCESS_KEY_ID="AKIA..." -export AWS_SECRET_ACCESS_KEY="..." -export AWS_REGION="us-east-1" -# Optional: -export AWS_SESSION_TOKEN="..." -export AWS_PROFILE="your-profile" -# Optional (Bedrock API key/bearer token): -export AWS_BEARER_TOKEN_BEDROCK="..." -``` - -2. Add a Bedrock provider and model to your config (no `apiKey` required): - -```json5 -{ - models: { - providers: { - "amazon-bedrock": { - baseUrl: "https://bedrock-runtime.us-east-1.amazonaws.com", - api: "bedrock-converse-stream", - auth: "aws-sdk", - models: [ - { - id: "anthropic.claude-opus-4-5-20251101-v1:0", - name: "Claude Opus 4.5 (Bedrock)", - reasoning: true, - input: ["text", "image"], - cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 }, - contextWindow: 200000, - maxTokens: 8192, - }, - ], - }, - }, - }, - agents: { - defaults: { - model: { primary: "amazon-bedrock/anthropic.claude-opus-4-5-20251101-v1:0" }, - }, - }, -} -``` - -## EC2 Instance Roles - -When running OpenClaw on an EC2 instance with an IAM role attached, the AWS SDK -will automatically use the instance metadata service (IMDS) for authentication. -However, OpenClaw's credential detection currently only checks for environment -variables, not IMDS credentials. - -**Workaround:** Set `AWS_PROFILE=default` to signal that AWS credentials are -available. The actual authentication still uses the instance role via IMDS. - -```bash -# Add to ~/.bashrc or your shell profile -export AWS_PROFILE=default -export AWS_REGION=us-east-1 -``` - -**Required IAM permissions** for the EC2 instance role: - -- `bedrock:InvokeModel` -- `bedrock:InvokeModelWithResponseStream` -- `bedrock:ListFoundationModels` (for automatic discovery) - -Or attach the managed policy `AmazonBedrockFullAccess`. - -**Quick setup:** - -```bash -# 1. Create IAM role and instance profile -aws iam create-role --role-name EC2-Bedrock-Access \ - --assume-role-policy-document '{ - "Version": "2012-10-17", - "Statement": [{ - "Effect": "Allow", - "Principal": {"Service": "ec2.amazonaws.com"}, - "Action": "sts:AssumeRole" - }] - }' - -aws iam attach-role-policy --role-name EC2-Bedrock-Access \ - --policy-arn arn:aws:iam::aws:policy/AmazonBedrockFullAccess - -aws iam create-instance-profile --instance-profile-name EC2-Bedrock-Access -aws iam add-role-to-instance-profile \ - --instance-profile-name EC2-Bedrock-Access \ - --role-name EC2-Bedrock-Access - -# 2. Attach to your EC2 instance -aws ec2 associate-iam-instance-profile \ - --instance-id i-xxxxx \ - --iam-instance-profile Name=EC2-Bedrock-Access - -# 3. On the EC2 instance, enable discovery -openclaw config set models.bedrockDiscovery.enabled true -openclaw config set models.bedrockDiscovery.region us-east-1 - -# 4. Set the workaround env vars -echo 'export AWS_PROFILE=default' >> ~/.bashrc -echo 'export AWS_REGION=us-east-1' >> ~/.bashrc -source ~/.bashrc - -# 5. Verify models are discovered -openclaw models list -``` - -## Notes - -- Bedrock requires **model access** enabled in your AWS account/region. -- Automatic discovery needs the `bedrock:ListFoundationModels` permission. -- If you use profiles, set `AWS_PROFILE` on the gateway host. -- OpenClaw surfaces the credential source in this order: `AWS_BEARER_TOKEN_BEDROCK`, - then `AWS_ACCESS_KEY_ID` + `AWS_SECRET_ACCESS_KEY`, then `AWS_PROFILE`, then the - default AWS SDK chain. -- Reasoning support depends on the model; check the Bedrock model card for - current capabilities. -- If you prefer a managed key flow, you can also place an OpenAI‑compatible - proxy in front of Bedrock and configure it as an OpenAI provider instead. diff --git a/docs/es/brave-search.md b/docs/es/brave-search.md deleted file mode 100644 index 2606479422..0000000000 --- a/docs/es/brave-search.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -summary: "Brave Search API setup for web_search" -read_when: - - You want to use Brave Search for web_search - - You need a BRAVE_API_KEY or plan details -title: "Brave Search" ---- - -# Brave Search API - -OpenClaw uses Brave Search as the default provider for `web_search`. - -## Get an API key - -1. Create a Brave Search API account at https://brave.com/search/api/ -2. In the dashboard, choose the **Data for Search** plan and generate an API key. -3. Store the key in config (recommended) or set `BRAVE_API_KEY` in the Gateway environment. - -## Config example - -```json5 -{ - tools: { - web: { - search: { - provider: "brave", - apiKey: "BRAVE_API_KEY_HERE", - maxResults: 5, - timeoutSeconds: 30, - }, - }, - }, -} -``` - -## Notes - -- The Data for AI plan is **not** compatible with `web_search`. -- Brave provides a free tier plus paid plans; check the Brave API portal for current limits. - -See [Web tools](/tools/web) for the full web_search configuration. diff --git a/docs/es/broadcast-groups.md b/docs/es/broadcast-groups.md deleted file mode 100644 index eb1b10ce7e..0000000000 --- a/docs/es/broadcast-groups.md +++ /dev/null @@ -1,442 +0,0 @@ ---- -summary: "Broadcast a WhatsApp message to multiple agents" -read_when: - - Configuring broadcast groups - - Debugging multi-agent replies in WhatsApp -status: experimental -title: "Broadcast Groups" ---- - -# Broadcast Groups - -**Status:** Experimental -**Version:** Added in 2026.1.9 - -## Overview - -Broadcast Groups enable multiple agents to process and respond to the same message simultaneously. This allows you to create specialized agent teams that work together in a single WhatsApp group or DM — all using one phone number. - -Current scope: **WhatsApp only** (web channel). - -Broadcast groups are evaluated after channel allowlists and group activation rules. In WhatsApp groups, this means broadcasts happen when OpenClaw would normally reply (for example: on mention, depending on your group settings). - -## Use Cases - -### 1. Specialized Agent Teams - -Deploy multiple agents with atomic, focused responsibilities: - -``` -Group: "Development Team" -Agents: - - CodeReviewer (reviews code snippets) - - DocumentationBot (generates docs) - - SecurityAuditor (checks for vulnerabilities) - - TestGenerator (suggests test cases) -``` - -Each agent processes the same message and provides its specialized perspective. - -### 2. Multi-Language Support - -``` -Group: "International Support" -Agents: - - Agent_EN (responds in English) - - Agent_DE (responds in German) - - Agent_ES (responds in Spanish) -``` - -### 3. Quality Assurance Workflows - -``` -Group: "Customer Support" -Agents: - - SupportAgent (provides answer) - - QAAgent (reviews quality, only responds if issues found) -``` - -### 4. Task Automation - -``` -Group: "Project Management" -Agents: - - TaskTracker (updates task database) - - TimeLogger (logs time spent) - - ReportGenerator (creates summaries) -``` - -## Configuration - -### Basic Setup - -Add a top-level `broadcast` section (next to `bindings`). Keys are WhatsApp peer ids: - -- group chats: group JID (e.g. `120363403215116621@g.us`) -- DMs: E.164 phone number (e.g. `+15551234567`) - -```json -{ - "broadcast": { - "120363403215116621@g.us": ["alfred", "baerbel", "assistant3"] - } -} -``` - -**Result:** When OpenClaw would reply in this chat, it will run all three agents. - -### Processing Strategy - -Control how agents process messages: - -#### Parallel (Default) - -All agents process simultaneously: - -```json -{ - "broadcast": { - "strategy": "parallel", - "120363403215116621@g.us": ["alfred", "baerbel"] - } -} -``` - -#### Sequential - -Agents process in order (one waits for previous to finish): - -```json -{ - "broadcast": { - "strategy": "sequential", - "120363403215116621@g.us": ["alfred", "baerbel"] - } -} -``` - -### Complete Example - -```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"] - } -} -``` - -## How It Works - -### Message Flow - -1. **Incoming message** arrives in a WhatsApp group -2. **Broadcast check**: System checks if peer ID is in `broadcast` -3. **If in broadcast list**: - - All listed agents process the message - - Each agent has its own session key and isolated context - - Agents process in parallel (default) or sequentially -4. **If not in broadcast list**: - - Normal routing applies (first matching binding) - -Note: broadcast groups do not bypass channel allowlists or group activation rules (mentions/commands/etc). They only change _which agents run_ when a message is eligible for processing. - -### Session Isolation - -Each agent in a broadcast group maintains completely separate: - -- **Session keys** (`agent:alfred:whatsapp:group:120363...` vs `agent:baerbel:whatsapp:group:120363...`) -- **Conversation history** (agent doesn't see other agents' messages) -- **Workspace** (separate sandboxes if configured) -- **Tool access** (different allow/deny lists) -- **Memory/context** (separate IDENTITY.md, SOUL.md, etc.) -- **Group context buffer** (recent group messages used for context) is shared per peer, so all broadcast agents see the same context when triggered - -This allows each agent to have: - -- Different personalities -- Different tool access (e.g., read-only vs. read-write) -- Different models (e.g., opus vs. sonnet) -- Different skills installed - -### Example: Isolated Sessions - -In group `120363403215116621@g.us` with agents `["alfred", "baerbel"]`: - -**Alfred's context:** - -``` -Session: agent:alfred:whatsapp:group:120363403215116621@g.us -History: [user message, alfred's previous responses] -Workspace: /Users/pascal/openclaw-alfred/ -Tools: read, write, exec -``` - -**Bärbel's context:** - -``` -Session: agent:baerbel:whatsapp:group:120363403215116621@g.us -History: [user message, baerbel's previous responses] -Workspace: /Users/pascal/openclaw-baerbel/ -Tools: read only -``` - -## Best Practices - -### 1. Keep Agents Focused - -Design each agent with a single, clear responsibility: - -```json -{ - "broadcast": { - "DEV_GROUP": ["formatter", "linter", "tester"] - } -} -``` - -✅ **Good:** Each agent has one job -❌ **Bad:** One generic "dev-helper" agent - -### 2. Use Descriptive Names - -Make it clear what each agent does: - -```json -{ - "agents": { - "security-scanner": { "name": "Security Scanner" }, - "code-formatter": { "name": "Code Formatter" }, - "test-generator": { "name": "Test Generator" } - } -} -``` - -### 3. Configure Different Tool Access - -Give agents only the tools they need: - -```json -{ - "agents": { - "reviewer": { - "tools": { "allow": ["read", "exec"] } // Read-only - }, - "fixer": { - "tools": { "allow": ["read", "write", "edit", "exec"] } // Read-write - } - } -} -``` - -### 4. Monitor Performance - -With many agents, consider: - -- Using `"strategy": "parallel"` (default) for speed -- Limiting broadcast groups to 5-10 agents -- Using faster models for simpler agents - -### 5. Handle Failures Gracefully - -Agents fail independently. One agent's error doesn't block others: - -``` -Message → [Agent A ✓, Agent B ✗ error, Agent C ✓] -Result: Agent A and C respond, Agent B logs error -``` - -## Compatibility - -### Providers - -Broadcast groups currently work with: - -- ✅ WhatsApp (implemented) -- 🚧 Telegram (planned) -- 🚧 Discord (planned) -- 🚧 Slack (planned) - -### Routing - -Broadcast groups work alongside existing routing: - -```json -{ - "bindings": [ - { - "match": { "channel": "whatsapp", "peer": { "kind": "group", "id": "GROUP_A" } }, - "agentId": "alfred" - } - ], - "broadcast": { - "GROUP_B": ["agent1", "agent2"] - } -} -``` - -- `GROUP_A`: Only alfred responds (normal routing) -- `GROUP_B`: agent1 AND agent2 respond (broadcast) - -**Precedence:** `broadcast` takes priority over `bindings`. - -## Troubleshooting - -### Agents Not Responding - -**Check:** - -1. Agent IDs exist in `agents.list` -2. Peer ID format is correct (e.g., `120363403215116621@g.us`) -3. Agents are not in deny lists - -**Debug:** - -```bash -tail -f ~/.openclaw/logs/gateway.log | grep broadcast -``` - -### Only One Agent Responding - -**Cause:** Peer ID might be in `bindings` but not `broadcast`. - -**Fix:** Add to broadcast config or remove from bindings. - -### Performance Issues - -**If slow with many agents:** - -- Reduce number of agents per group -- Use lighter models (sonnet instead of opus) -- Check sandbox startup time - -## Examples - -### Example 1: Code Review Team - -```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"] } } - ] - } -} -``` - -**User sends:** Code snippet -**Responses:** - -- code-formatter: "Fixed indentation and added type hints" -- security-scanner: "⚠️ SQL injection vulnerability in line 12" -- test-coverage: "Coverage is 45%, missing tests for error cases" -- docs-checker: "Missing docstring for function `process_data`" - -### Example 2: Multi-Language Support - -```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 Reference - -### Config Schema - -```typescript -interface OpenClawConfig { - broadcast?: { - strategy?: "parallel" | "sequential"; - [peerId: string]: string[]; - }; -} -``` - -### Fields - -- `strategy` (optional): How to process agents - - `"parallel"` (default): All agents process simultaneously - - `"sequential"`: Agents process in array order -- `[peerId]`: WhatsApp group JID, E.164 number, or other peer ID - - Value: Array of agent IDs that should process messages - -## Limitations - -1. **Max agents:** No hard limit, but 10+ agents may be slow -2. **Shared context:** Agents don't see each other's responses (by design) -3. **Message ordering:** Parallel responses may arrive in any order -4. **Rate limits:** All agents count toward WhatsApp rate limits - -## Future Enhancements - -Planned features: - -- [ ] Shared context mode (agents see each other's responses) -- [ ] Agent coordination (agents can signal each other) -- [ ] Dynamic agent selection (choose agents based on message content) -- [ ] Agent priorities (some agents respond before others) - -## See Also - -- [Multi-Agent Configuration](/multi-agent-sandbox-tools) -- [Routing Configuration](/concepts/channel-routing) -- [Session Management](/concepts/sessions) diff --git a/docs/es/channels/bluebubbles.md b/docs/es/channels/bluebubbles.md deleted file mode 100644 index b40fc375da..0000000000 --- a/docs/es/channels/bluebubbles.md +++ /dev/null @@ -1,338 +0,0 @@ ---- -summary: "iMessage via BlueBubbles macOS server (REST send/receive, typing, reactions, pairing, advanced actions)." -read_when: - - Setting up BlueBubbles channel - - Troubleshooting webhook pairing - - Configuring iMessage on macOS -title: "BlueBubbles" ---- - -# BlueBubbles (macOS REST) - -Status: bundled plugin that talks to the BlueBubbles macOS server over HTTP. **Recommended for iMessage integration** due to its richer API and easier setup compared to the legacy imsg channel. - -## Overview - -- Runs on macOS via the BlueBubbles helper app ([bluebubbles.app](https://bluebubbles.app)). -- Recommended/tested: macOS Sequoia (15). macOS Tahoe (26) works; edit is currently broken on Tahoe, and group icon updates may report success but not sync. -- OpenClaw talks to it through its REST API (`GET /api/v1/ping`, `POST /message/text`, `POST /chat/:id/*`). -- Incoming messages arrive via webhooks; outgoing replies, typing indicators, read receipts, and tapbacks are REST calls. -- Attachments and stickers are ingested as inbound media (and surfaced to the agent when possible). -- Pairing/allowlist works the same way as other channels (`/start/pairing` etc) with `channels.bluebubbles.allowFrom` + pairing codes. -- Reactions are surfaced as system events just like Slack/Telegram so agents can "mention" them before replying. -- Advanced features: edit, unsend, reply threading, message effects, group management. - -## Quick start - -1. Install the BlueBubbles server on your Mac (follow the instructions at [bluebubbles.app/install](https://bluebubbles.app/install)). -2. In the BlueBubbles config, enable the web API and set a password. -3. Run `openclaw onboard` and select BlueBubbles, or configure manually: - ```json5 - { - channels: { - bluebubbles: { - enabled: true, - serverUrl: "http://192.168.1.100:1234", - password: "example-password", - webhookPath: "/bluebubbles-webhook", - }, - }, - } - ``` -4. Point BlueBubbles webhooks to your gateway (example: `https://your-gateway-host:3000/bluebubbles-webhook?password=`). -5. Start the gateway; it will register the webhook handler and start pairing. - -## Keeping Messages.app alive (VM / headless setups) - -Some macOS VM / always-on setups can end up with Messages.app going “idle” (incoming events stop until the app is opened/foregrounded). A simple workaround is to **poke Messages every 5 minutes** using an AppleScript + LaunchAgent. - -### 1) Save the AppleScript - -Save this as: - -- `~/Scripts/poke-messages.scpt` - -Example script (non-interactive; does not steal focus): - -```applescript -try - tell application "Messages" - if not running then - launch - end if - - -- Touch the scripting interface to keep the process responsive. - set _chatCount to (count of chats) - end tell -on error - -- Ignore transient failures (first-run prompts, locked session, etc). -end try -``` - -### 2) Install a LaunchAgent - -Save this as: - -- `~/Library/LaunchAgents/com.user.poke-messages.plist` - -```xml - - - - - 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 - - -``` - -Notes: - -- This runs **every 300 seconds** and **on login**. -- The first run may trigger macOS **Automation** prompts (`osascript` → Messages). Approve them in the same user session that runs the LaunchAgent. - -Load it: - -```bash -launchctl unload ~/Library/LaunchAgents/com.user.poke-messages.plist 2>/dev/null || true -launchctl load ~/Library/LaunchAgents/com.user.poke-messages.plist -``` - -## Onboarding - -BlueBubbles is available in the interactive setup wizard: - -``` -openclaw onboard -``` - -The wizard prompts for: - -- **Server URL** (required): BlueBubbles server address (e.g., `http://192.168.1.100:1234`) -- **Password** (required): API password from BlueBubbles Server settings -- **Webhook path** (optional): Defaults to `/bluebubbles-webhook` -- **DM policy**: pairing, allowlist, open, or disabled -- **Allow list**: Phone numbers, emails, or chat targets - -You can also add BlueBubbles via CLI: - -``` -openclaw channels add bluebubbles --http-url http://192.168.1.100:1234 --password -``` - -## Access control (DMs + groups) - -DMs: - -- Default: `channels.bluebubbles.dmPolicy = "pairing"`. -- Unknown senders receive a pairing code; messages are ignored until approved (codes expire after 1 hour). -- Approve via: - - `openclaw pairing list bluebubbles` - - `openclaw pairing approve bluebubbles ` -- Pairing is the default token exchange. Details: [Pairing](/start/pairing) - -Groups: - -- `channels.bluebubbles.groupPolicy = open | allowlist | disabled` (default: `allowlist`). -- `channels.bluebubbles.groupAllowFrom` controls who can trigger in groups when `allowlist` is set. - -### Mention gating (groups) - -BlueBubbles supports mention gating for group chats, matching iMessage/WhatsApp behavior: - -- Uses `agents.list[].groupChat.mentionPatterns` (or `messages.groupChat.mentionPatterns`) to detect mentions. -- When `requireMention` is enabled for a group, the agent only responds when mentioned. -- Control commands from authorized senders bypass mention gating. - -Per-group configuration: - -```json5 -{ - channels: { - bluebubbles: { - groupPolicy: "allowlist", - groupAllowFrom: ["+15555550123"], - groups: { - "*": { requireMention: true }, // default for all groups - "iMessage;-;chat123": { requireMention: false }, // override for specific group - }, - }, - }, -} -``` - -### Command gating - -- Control commands (e.g., `/config`, `/model`) require authorization. -- Uses `allowFrom` and `groupAllowFrom` to determine command authorization. -- Authorized senders can run control commands even without mentioning in groups. - -## Typing + read receipts - -- **Typing indicators**: Sent automatically before and during response generation. -- **Read receipts**: Controlled by `channels.bluebubbles.sendReadReceipts` (default: `true`). -- **Typing indicators**: OpenClaw sends typing start events; BlueBubbles clears typing automatically on send or timeout (manual stop via DELETE is unreliable). - -```json5 -{ - channels: { - bluebubbles: { - sendReadReceipts: false, // disable read receipts - }, - }, -} -``` - -## Advanced actions - -BlueBubbles supports advanced message actions when enabled in config: - -```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 - }, - }, - }, -} -``` - -Available actions: - -- **react**: Add/remove tapback reactions (`messageId`, `emoji`, `remove`) -- **edit**: Edit a sent message (`messageId`, `text`) -- **unsend**: Unsend a message (`messageId`) -- **reply**: Reply to a specific message (`messageId`, `text`, `to`) -- **sendWithEffect**: Send with iMessage effect (`text`, `to`, `effectId`) -- **renameGroup**: Rename a group chat (`chatGuid`, `displayName`) -- **setGroupIcon**: Set a group chat's icon/photo (`chatGuid`, `media`) — flaky on macOS 26 Tahoe (API may return success but the icon does not sync). -- **addParticipant**: Add someone to a group (`chatGuid`, `address`) -- **removeParticipant**: Remove someone from a group (`chatGuid`, `address`) -- **leaveGroup**: Leave a group chat (`chatGuid`) -- **sendAttachment**: Send media/files (`to`, `buffer`, `filename`, `asVoice`) - - Voice memos: set `asVoice: true` with **MP3** or **CAF** audio to send as an iMessage voice message. BlueBubbles converts MP3 → CAF when sending voice memos. - -### Message IDs (short vs full) - -OpenClaw may surface _short_ message IDs (e.g., `1`, `2`) to save tokens. - -- `MessageSid` / `ReplyToId` can be short IDs. -- `MessageSidFull` / `ReplyToIdFull` contain the provider full IDs. -- Short IDs are in-memory; they can expire on restart or cache eviction. -- Actions accept short or full `messageId`, but short IDs will error if no longer available. - -Use full IDs for durable automations and storage: - -- Templates: `{{MessageSidFull}}`, `{{ReplyToIdFull}}` -- Context: `MessageSidFull` / `ReplyToIdFull` in inbound payloads - -See [Configuration](/gateway/configuration) for template variables. - -## Block streaming - -Control whether responses are sent as a single message or streamed in blocks: - -```json5 -{ - channels: { - bluebubbles: { - blockStreaming: true, // enable block streaming (off by default) - }, - }, -} -``` - -## Media + limits - -- Inbound attachments are downloaded and stored in the media cache. -- Media cap via `channels.bluebubbles.mediaMaxMb` (default: 8 MB). -- Outbound text is chunked to `channels.bluebubbles.textChunkLimit` (default: 4000 chars). - -## Configuration reference - -Full configuration: [Configuration](/gateway/configuration) - -Provider options: - -- `channels.bluebubbles.enabled`: Enable/disable the channel. -- `channels.bluebubbles.serverUrl`: BlueBubbles REST API base URL. -- `channels.bluebubbles.password`: API password. -- `channels.bluebubbles.webhookPath`: Webhook endpoint path (default: `/bluebubbles-webhook`). -- `channels.bluebubbles.dmPolicy`: `pairing | allowlist | open | disabled` (default: `pairing`). -- `channels.bluebubbles.allowFrom`: DM allowlist (handles, emails, E.164 numbers, `chat_id:*`, `chat_guid:*`). -- `channels.bluebubbles.groupPolicy`: `open | allowlist | disabled` (default: `allowlist`). -- `channels.bluebubbles.groupAllowFrom`: Group sender allowlist. -- `channels.bluebubbles.groups`: Per-group config (`requireMention`, etc.). -- `channels.bluebubbles.sendReadReceipts`: Send read receipts (default: `true`). -- `channels.bluebubbles.blockStreaming`: Enable block streaming (default: `false`; required for streaming replies). -- `channels.bluebubbles.textChunkLimit`: Outbound chunk size in chars (default: 4000). -- `channels.bluebubbles.chunkMode`: `length` (default) splits only when exceeding `textChunkLimit`; `newline` splits on blank lines (paragraph boundaries) before length chunking. -- `channels.bluebubbles.mediaMaxMb`: Inbound media cap in MB (default: 8). -- `channels.bluebubbles.historyLimit`: Max group messages for context (0 disables). -- `channels.bluebubbles.dmHistoryLimit`: DM history limit. -- `channels.bluebubbles.actions`: Enable/disable specific actions. -- `channels.bluebubbles.accounts`: Multi-account configuration. - -Related global options: - -- `agents.list[].groupChat.mentionPatterns` (or `messages.groupChat.mentionPatterns`). -- `messages.responsePrefix`. - -## Addressing / delivery targets - -Prefer `chat_guid` for stable routing: - -- `chat_guid:iMessage;-;+15555550123` (preferred for groups) -- `chat_id:123` -- `chat_identifier:...` -- Direct handles: `+15555550123`, `user@example.com` - - If a direct handle does not have an existing DM chat, OpenClaw will create one via `POST /api/v1/chat/new`. This requires the BlueBubbles Private API to be enabled. - -## Security - -- Webhook requests are authenticated by comparing `guid`/`password` query params or headers against `channels.bluebubbles.password`. Requests from `localhost` are also accepted. -- Keep the API password and webhook endpoint secret (treat them like credentials). -- Localhost trust means a same-host reverse proxy can unintentionally bypass the password. If you proxy the gateway, require auth at the proxy and configure `gateway.trustedProxies`. See [Gateway security](/gateway/security#reverse-proxy-configuration). -- Enable HTTPS + firewall rules on the BlueBubbles server if exposing it outside your LAN. - -## Troubleshooting - -- If typing/read events stop working, check the BlueBubbles webhook logs and verify the gateway path matches `channels.bluebubbles.webhookPath`. -- Pairing codes expire after one hour; use `openclaw pairing list bluebubbles` and `openclaw pairing approve bluebubbles `. -- Reactions require the BlueBubbles private API (`POST /api/v1/message/react`); ensure the server version exposes it. -- Edit/unsend require macOS 13+ and a compatible BlueBubbles server version. On macOS 26 (Tahoe), edit is currently broken due to private API changes. -- Group icon updates can be flaky on macOS 26 (Tahoe): the API may return success but the new icon does not sync. -- OpenClaw auto-hides known-broken actions based on the BlueBubbles server's macOS version. If edit still appears on macOS 26 (Tahoe), disable it manually with `channels.bluebubbles.actions.edit=false`. -- For status/health info: `openclaw status --all` or `openclaw status --deep`. - -For general channel workflow reference, see [Channels](/channels) and the [Plugins](/plugins) guide. diff --git a/docs/es/channels/discord.md b/docs/es/channels/discord.md deleted file mode 100644 index c520c16fdd..0000000000 --- a/docs/es/channels/discord.md +++ /dev/null @@ -1,476 +0,0 @@ ---- -summary: "Discord bot support status, capabilities, and configuration" -read_when: - - Working on Discord channel features -title: "Discord" ---- - -# Discord (Bot API) - -Status: ready for DM and guild text channels via the official Discord bot gateway. - -## Quick setup (beginner) - -1. Create a Discord bot and copy the bot token. -2. In the Discord app settings, enable **Message Content Intent** (and **Server Members Intent** if you plan to use allowlists or name lookups). -3. Set the token for OpenClaw: - - Env: `DISCORD_BOT_TOKEN=...` - - Or config: `channels.discord.token: "..."`. - - If both are set, config takes precedence (env fallback is default-account only). -4. Invite the bot to your server with message permissions (create a private server if you just want DMs). -5. Start the gateway. -6. DM access is pairing by default; approve the pairing code on first contact. - -Minimal config: - -```json5 -{ - channels: { - discord: { - enabled: true, - token: "YOUR_BOT_TOKEN", - }, - }, -} -``` - -## Goals - -- Talk to OpenClaw via Discord DMs or guild channels. -- Direct chats collapse into the agent's main session (default `agent:main:main`); guild channels stay isolated as `agent::discord:channel:` (display names use `discord:#`). -- Group DMs are ignored by default; enable via `channels.discord.dm.groupEnabled` and optionally restrict by `channels.discord.dm.groupChannels`. -- Keep routing deterministic: replies always go back to the channel they arrived on. - -## How it works - -1. Create a Discord application → Bot, enable the intents you need (DMs + guild messages + message content), and grab the bot token. -2. Invite the bot to your server with the permissions required to read/send messages where you want to use it. -3. Configure OpenClaw with `channels.discord.token` (or `DISCORD_BOT_TOKEN` as a fallback). -4. Run the gateway; it auto-starts the Discord channel when a token is available (config first, env fallback) and `channels.discord.enabled` is not `false`. - - If you prefer env vars, set `DISCORD_BOT_TOKEN` (a config block is optional). -5. Direct chats: use `user:` (or a `<@id>` mention) when delivering; all turns land in the shared `main` session. Bare numeric IDs are ambiguous and rejected. -6. Guild channels: use `channel:` for delivery. Mentions are required by default and can be set per guild or per channel. -7. Direct chats: secure by default via `channels.discord.dm.policy` (default: `"pairing"`). Unknown senders get a pairing code (expires after 1 hour); approve via `openclaw pairing approve discord `. - - To keep old “open to anyone” behavior: set `channels.discord.dm.policy="open"` and `channels.discord.dm.allowFrom=["*"]`. - - To hard-allowlist: set `channels.discord.dm.policy="allowlist"` and list senders in `channels.discord.dm.allowFrom`. - - To ignore all DMs: set `channels.discord.dm.enabled=false` or `channels.discord.dm.policy="disabled"`. -8. Group DMs are ignored by default; enable via `channels.discord.dm.groupEnabled` and optionally restrict by `channels.discord.dm.groupChannels`. -9. Optional guild rules: set `channels.discord.guilds` keyed by guild id (preferred) or slug, with per-channel rules. -10. Optional native commands: `commands.native` defaults to `"auto"` (on for Discord/Telegram, off for Slack). Override with `channels.discord.commands.native: true|false|"auto"`; `false` clears previously registered commands. Text commands are controlled by `commands.text` and must be sent as standalone `/...` messages. Use `commands.useAccessGroups: false` to bypass access-group checks for commands. - - Full command list + config: [Slash commands](/tools/slash-commands) -11. Optional guild context history: set `channels.discord.historyLimit` (default 20, falls back to `messages.groupChat.historyLimit`) to include the last N guild messages as context when replying to a mention. Set `0` to disable. -12. Reactions: the agent can trigger reactions via the `discord` tool (gated by `channels.discord.actions.*`). - - Reaction removal semantics: see [/tools/reactions](/tools/reactions). - - The `discord` tool is only exposed when the current channel is Discord. -13. Native commands use isolated session keys (`agent::discord:slash:`) rather than the shared `main` session. - -Note: Name → id resolution uses guild member search and requires Server Members Intent; if the bot can’t search members, use ids or `<@id>` mentions. -Note: Slugs are lowercase with spaces replaced by `-`. Channel names are slugged without the leading `#`. -Note: Guild context `[from:]` lines include `author.tag` + `id` to make ping-ready replies easy. - -## Config writes - -By default, Discord is allowed to write config updates triggered by `/config set|unset` (requires `commands.config: true`). - -Disable with: - -```json5 -{ - channels: { discord: { configWrites: false } }, -} -``` - -## How to create your own bot - -This is the “Discord Developer Portal” setup for running OpenClaw in a server (guild) channel like `#help`. - -### 1) Create the Discord app + bot user - -1. Discord Developer Portal → **Applications** → **New Application** -2. In your app: - - **Bot** → **Add Bot** - - Copy the **Bot Token** (this is what you put in `DISCORD_BOT_TOKEN`) - -### 2) Enable the gateway intents OpenClaw needs - -Discord blocks “privileged intents” unless you explicitly enable them. - -In **Bot** → **Privileged Gateway Intents**, enable: - -- **Message Content Intent** (required to read message text in most guilds; without it you’ll see “Used disallowed intents” or the bot will connect but not react to messages) -- **Server Members Intent** (recommended; required for some member/user lookups and allowlist matching in guilds) - -You usually do **not** need **Presence Intent**. Setting the bot's own presence (`setPresence` action) uses gateway OP3 and does not require this intent; it is only needed if you want to receive presence updates about other guild members. - -### 3) Generate an invite URL (OAuth2 URL Generator) - -In your app: **OAuth2** → **URL Generator** - -**Scopes** - -- ✅ `bot` -- ✅ `applications.commands` (required for native commands) - -**Bot Permissions** (minimal baseline) - -- ✅ View Channels -- ✅ Send Messages -- ✅ Read Message History -- ✅ Embed Links -- ✅ Attach Files -- ✅ Add Reactions (optional but recommended) -- ✅ Use External Emojis / Stickers (optional; only if you want them) - -Avoid **Administrator** unless you’re debugging and fully trust the bot. - -Copy the generated URL, open it, pick your server, and install the bot. - -### 4) Get the ids (guild/user/channel) - -Discord uses numeric ids everywhere; OpenClaw config prefers ids. - -1. Discord (desktop/web) → **User Settings** → **Advanced** → enable **Developer Mode** -2. Right-click: - - Server name → **Copy Server ID** (guild id) - - Channel (e.g. `#help`) → **Copy Channel ID** - - Your user → **Copy User ID** - -### 5) Configure OpenClaw - -#### Token - -Set the bot token via env var (recommended on servers): - -- `DISCORD_BOT_TOKEN=...` - -Or via config: - -```json5 -{ - channels: { - discord: { - enabled: true, - token: "YOUR_BOT_TOKEN", - }, - }, -} -``` - -Multi-account support: use `channels.discord.accounts` with per-account tokens and optional `name`. See [`gateway/configuration`](/gateway/configuration#telegramaccounts--discordaccounts--slackaccounts--signalaccounts--imessageaccounts) for the shared pattern. - -#### Allowlist + channel routing - -Example “single server, only allow me, only allow #help”: - -```json5 -{ - channels: { - discord: { - enabled: true, - dm: { enabled: false }, - guilds: { - YOUR_GUILD_ID: { - users: ["YOUR_USER_ID"], - requireMention: true, - channels: { - help: { allow: true, requireMention: true }, - }, - }, - }, - retry: { - attempts: 3, - minDelayMs: 500, - maxDelayMs: 30000, - jitter: 0.1, - }, - }, - }, -} -``` - -Notes: - -- `requireMention: true` means the bot only replies when mentioned (recommended for shared channels). -- `agents.list[].groupChat.mentionPatterns` (or `messages.groupChat.mentionPatterns`) also count as mentions for guild messages. -- Multi-agent override: set per-agent patterns on `agents.list[].groupChat.mentionPatterns`. -- If `channels` is present, any channel not listed is denied by default. -- Use a `"*"` channel entry to apply defaults across all channels; explicit channel entries override the wildcard. -- Threads inherit parent channel config (allowlist, `requireMention`, skills, prompts, etc.) unless you add the thread channel id explicitly. -- Owner hint: when a per-guild or per-channel `users` allowlist matches the sender, OpenClaw treats that sender as the owner in the system prompt. For a global owner across channels, set `commands.ownerAllowFrom`. -- Bot-authored messages are ignored by default; set `channels.discord.allowBots=true` to allow them (own messages remain filtered). -- Warning: If you allow replies to other bots (`channels.discord.allowBots=true`), prevent bot-to-bot reply loops with `requireMention`, `channels.discord.guilds.*.channels..users` allowlists, and/or clear guardrails in `AGENTS.md` and `SOUL.md`. - -### 6) Verify it works - -1. Start the gateway. -2. In your server channel, send: `@Krill hello` (or whatever your bot name is). -3. If nothing happens: check **Troubleshooting** below. - -### Troubleshooting - -- First: run `openclaw doctor` and `openclaw channels status --probe` (actionable warnings + quick audits). -- **“Used disallowed intents”**: enable **Message Content Intent** (and likely **Server Members Intent**) in the Developer Portal, then restart the gateway. -- **Bot connects but never replies in a guild channel**: - - Missing **Message Content Intent**, or - - The bot lacks channel permissions (View/Send/Read History), or - - Your config requires mentions and you didn’t mention it, or - - Your guild/channel allowlist denies the channel/user. -- **`requireMention: false` but still no replies**: -- `channels.discord.groupPolicy` defaults to **allowlist**; set it to `"open"` or add a guild entry under `channels.discord.guilds` (optionally list channels under `channels.discord.guilds..channels` to restrict). - - If you only set `DISCORD_BOT_TOKEN` and never create a `channels.discord` section, the runtime - defaults `groupPolicy` to `open`. Add `channels.discord.groupPolicy`, - `channels.defaults.groupPolicy`, or a guild/channel allowlist to lock it down. -- `requireMention` must live under `channels.discord.guilds` (or a specific channel). `channels.discord.requireMention` at the top level is ignored. -- **Permission audits** (`channels status --probe`) only check numeric channel IDs. If you use slugs/names as `channels.discord.guilds.*.channels` keys, the audit can’t verify permissions. -- **DMs don’t work**: `channels.discord.dm.enabled=false`, `channels.discord.dm.policy="disabled"`, or you haven’t been approved yet (`channels.discord.dm.policy="pairing"`). -- **Exec approvals in Discord**: Discord supports a **button UI** for exec approvals in DMs (Allow once / Always allow / Deny). `/approve ...` is only for forwarded approvals and won’t resolve Discord’s button prompts. If you see `❌ Failed to submit approval: Error: unknown approval id` or the UI never shows up, check: - - `channels.discord.execApprovals.enabled: true` in your config. - - Your Discord user ID is listed in `channels.discord.execApprovals.approvers` (the UI is only sent to approvers). - - Use the buttons in the DM prompt (**Allow once**, **Always allow**, **Deny**). - - See [Exec approvals](/tools/exec-approvals) and [Slash commands](/tools/slash-commands) for the broader approvals and command flow. - -## Capabilities & limits - -- DMs and guild text channels (threads are treated as separate channels; voice not supported). -- Typing indicators sent best-effort; message chunking uses `channels.discord.textChunkLimit` (default 2000) and splits tall replies by line count (`channels.discord.maxLinesPerMessage`, default 17). -- Optional newline chunking: set `channels.discord.chunkMode="newline"` to split on blank lines (paragraph boundaries) before length chunking. -- File uploads supported up to the configured `channels.discord.mediaMaxMb` (default 8 MB). -- Mention-gated guild replies by default to avoid noisy bots. -- Reply context is injected when a message references another message (quoted content + ids). -- Native reply threading is **off by default**; enable with `channels.discord.replyToMode` and reply tags. - -## Retry policy - -Outbound Discord API calls retry on rate limits (429) using Discord `retry_after` when available, with exponential backoff and jitter. Configure via `channels.discord.retry`. See [Retry policy](/concepts/retry). - -## Config - -```json5 -{ - channels: { - discord: { - enabled: true, - token: "abc.123", - groupPolicy: "allowlist", - guilds: { - "*": { - channels: { - general: { allow: true }, - }, - }, - }, - mediaMaxMb: 8, - actions: { - reactions: true, - stickers: true, - emojiUploads: true, - stickerUploads: true, - polls: true, - permissions: true, - messages: true, - threads: true, - pins: true, - search: true, - memberInfo: true, - roleInfo: true, - roles: false, - channelInfo: true, - channels: true, - voiceStatus: true, - events: true, - moderation: false, - presence: false, - }, - replyToMode: "off", - dm: { - enabled: true, - policy: "pairing", // pairing | allowlist | open | disabled - allowFrom: ["123456789012345678", "steipete"], - groupEnabled: false, - groupChannels: ["openclaw-dm"], - }, - guilds: { - "*": { requireMention: true }, - "123456789012345678": { - slug: "friends-of-openclaw", - requireMention: false, - reactionNotifications: "own", - users: ["987654321098765432", "steipete"], - channels: { - general: { allow: true }, - help: { - allow: true, - requireMention: true, - users: ["987654321098765432"], - skills: ["search", "docs"], - systemPrompt: "Keep answers short.", - }, - }, - }, - }, - }, - }, -} -``` - -Ack reactions are controlled globally via `messages.ackReaction` + -`messages.ackReactionScope`. Use `messages.removeAckAfterReply` to clear the -ack reaction after the bot replies. - -- `dm.enabled`: set `false` to ignore all DMs (default `true`). -- `dm.policy`: DM access control (`pairing` recommended). `"open"` requires `dm.allowFrom=["*"]`. -- `dm.allowFrom`: DM allowlist (user ids or names). Used by `dm.policy="allowlist"` and for `dm.policy="open"` validation. The wizard accepts usernames and resolves them to ids when the bot can search members. -- `dm.groupEnabled`: enable group DMs (default `false`). -- `dm.groupChannels`: optional allowlist for group DM channel ids or slugs. -- `groupPolicy`: controls guild channel handling (`open|disabled|allowlist`); `allowlist` requires channel allowlists. -- `guilds`: per-guild rules keyed by guild id (preferred) or slug. -- `guilds."*"`: default per-guild settings applied when no explicit entry exists. -- `guilds..slug`: optional friendly slug used for display names. -- `guilds..users`: optional per-guild user allowlist (ids or names). -- `guilds..tools`: optional per-guild tool policy overrides (`allow`/`deny`/`alsoAllow`) used when the channel override is missing. -- `guilds..toolsBySender`: optional per-sender tool policy overrides at the guild level (applies when the channel override is missing; `"*"` wildcard supported). -- `guilds..channels..allow`: allow/deny the channel when `groupPolicy="allowlist"`. -- `guilds..channels..requireMention`: mention gating for the channel. -- `guilds..channels..tools`: optional per-channel tool policy overrides (`allow`/`deny`/`alsoAllow`). -- `guilds..channels..toolsBySender`: optional per-sender tool policy overrides within the channel (`"*"` wildcard supported). -- `guilds..channels..users`: optional per-channel user allowlist. -- `guilds..channels..skills`: skill filter (omit = all skills, empty = none). -- `guilds..channels..systemPrompt`: extra system prompt for the channel. Discord channel topics are injected as **untrusted** context (not system prompt). -- `guilds..channels..enabled`: set `false` to disable the channel. -- `guilds..channels`: channel rules (keys are channel slugs or ids). -- `guilds..requireMention`: per-guild mention requirement (overridable per channel). -- `guilds..reactionNotifications`: reaction system event mode (`off`, `own`, `all`, `allowlist`). -- `textChunkLimit`: outbound text chunk size (chars). Default: 2000. -- `chunkMode`: `length` (default) splits only when exceeding `textChunkLimit`; `newline` splits on blank lines (paragraph boundaries) before length chunking. -- `maxLinesPerMessage`: soft max line count per message. Default: 17. -- `mediaMaxMb`: clamp inbound media saved to disk. -- `historyLimit`: number of recent guild messages to include as context when replying to a mention (default 20; falls back to `messages.groupChat.historyLimit`; `0` disables). -- `dmHistoryLimit`: DM history limit in user turns. Per-user overrides: `dms[""].historyLimit`. -- `retry`: retry policy for outbound Discord API calls (attempts, minDelayMs, maxDelayMs, jitter). -- `pluralkit`: resolve PluralKit proxied messages so system members appear as distinct senders. -- `actions`: per-action tool gates; omit to allow all (set `false` to disable). - - `reactions` (covers react + read reactions) - - `stickers`, `emojiUploads`, `stickerUploads`, `polls`, `permissions`, `messages`, `threads`, `pins`, `search` - - `memberInfo`, `roleInfo`, `channelInfo`, `voiceStatus`, `events` - - `channels` (create/edit/delete channels + categories + permissions) - - `roles` (role add/remove, default `false`) - - `moderation` (timeout/kick/ban, default `false`) - - `presence` (bot status/activity, default `false`) -- `execApprovals`: Discord-only exec approval DMs (button UI). Supports `enabled`, `approvers`, `agentFilter`, `sessionFilter`. - -Reaction notifications use `guilds..reactionNotifications`: - -- `off`: no reaction events. -- `own`: reactions on the bot's own messages (default). -- `all`: all reactions on all messages. -- `allowlist`: reactions from `guilds..users` on all messages (empty list disables). - -### PluralKit (PK) support - -Enable PK lookups so proxied messages resolve to the underlying system + member. -When enabled, OpenClaw uses the member identity for allowlists and labels the -sender as `Member (PK:System)` to avoid accidental Discord pings. - -```json5 -{ - channels: { - discord: { - pluralkit: { - enabled: true, - token: "pk_live_...", // optional; required for private systems - }, - }, - }, -} -``` - -Allowlist notes (PK-enabled): - -- Use `pk:` in `dm.allowFrom`, `guilds..users`, or per-channel `users`. -- Member display names are also matched by name/slug. -- Lookups use the **original** Discord message ID (the pre-proxy message), so - the PK API only resolves it within its 30-minute window. -- If PK lookups fail (e.g., private system without a token), proxied messages - are treated as bot messages and are dropped unless `channels.discord.allowBots=true`. - -### Tool action defaults - -| Action group | Default | Notes | -| -------------- | -------- | ---------------------------------- | -| reactions | enabled | React + list reactions + emojiList | -| stickers | enabled | Send stickers | -| emojiUploads | enabled | Upload emojis | -| stickerUploads | enabled | Upload stickers | -| polls | enabled | Create polls | -| permissions | enabled | Channel permission snapshot | -| messages | enabled | Read/send/edit/delete | -| threads | enabled | Create/list/reply | -| pins | enabled | Pin/unpin/list | -| search | enabled | Message search (preview feature) | -| memberInfo | enabled | Member info | -| roleInfo | enabled | Role list | -| channelInfo | enabled | Channel info + list | -| channels | enabled | Channel/category management | -| voiceStatus | enabled | Voice state lookup | -| events | enabled | List/create scheduled events | -| roles | disabled | Role add/remove | -| moderation | disabled | Timeout/kick/ban | -| presence | disabled | Bot status/activity (setPresence) | - -- `replyToMode`: `off` (default), `first`, or `all`. Applies only when the model includes a reply tag. - -## Reply tags - -To request a threaded reply, the model can include one tag in its output: - -- `[[reply_to_current]]` — reply to the triggering Discord message. -- `[[reply_to:]]` — reply to a specific message id from context/history. - Current message ids are appended to prompts as `[message_id: …]`; history entries already include ids. - -Behavior is controlled by `channels.discord.replyToMode`: - -- `off`: ignore tags. -- `first`: only the first outbound chunk/attachment is a reply. -- `all`: every outbound chunk/attachment is a reply. - -Allowlist matching notes: - -- `allowFrom`/`users`/`groupChannels` accept ids, names, tags, or mentions like `<@id>`. -- Prefixes like `discord:`/`user:` (users) and `channel:` (group DMs) are supported. -- Use `*` to allow any sender/channel. -- When `guilds..channels` is present, channels not listed are denied by default. -- When `guilds..channels` is omitted, all channels in the allowlisted guild are allowed. -- To allow **no channels**, set `channels.discord.groupPolicy: "disabled"` (or keep an empty allowlist). -- The configure wizard accepts `Guild/Channel` names (public + private) and resolves them to IDs when possible. -- On startup, OpenClaw resolves channel/user names in allowlists to IDs (when the bot can search members) - and logs the mapping; unresolved entries are kept as typed. - -Native command notes: - -- The registered commands mirror OpenClaw’s chat commands. -- Native commands honor the same allowlists as DMs/guild messages (`channels.discord.dm.allowFrom`, `channels.discord.guilds`, per-channel rules). -- Slash commands may still be visible in Discord UI to users who aren’t allowlisted; OpenClaw enforces allowlists on execution and replies “not authorized”. - -## Tool actions - -The agent can call `discord` with actions like: - -- `react` / `reactions` (add or list reactions) -- `sticker`, `poll`, `permissions` -- `readMessages`, `sendMessage`, `editMessage`, `deleteMessage` -- Read/search/pin tool payloads include normalized `timestampMs` (UTC epoch ms) and `timestampUtc` alongside raw Discord `timestamp`. -- `threadCreate`, `threadList`, `threadReply` -- `pinMessage`, `unpinMessage`, `listPins` -- `searchMessages`, `memberInfo`, `roleInfo`, `roleAdd`, `roleRemove`, `emojiList` -- `channelInfo`, `channelList`, `voiceStatus`, `eventList`, `eventCreate` -- `timeout`, `kick`, `ban` -- `setPresence` (bot activity and online status) - -Discord message ids are surfaced in the injected context (`[discord message id: …]` and history lines) so the agent can target them. -Emoji can be unicode (e.g., `✅`) or custom emoji syntax like `<:party_blob:1234567890>`. - -## Safety & ops - -- Treat the bot token like a password; prefer the `DISCORD_BOT_TOKEN` env var on supervised hosts or lock down the config file permissions. -- Only grant the bot permissions it needs (typically Read/Send Messages). -- If the bot is stuck or rate limited, restart the gateway (`openclaw gateway --force`) after confirming no other processes own the Discord session. diff --git a/docs/es/channels/feishu.md b/docs/es/channels/feishu.md deleted file mode 100644 index e378afaba8..0000000000 --- a/docs/es/channels/feishu.md +++ /dev/null @@ -1,507 +0,0 @@ ---- -summary: "Feishu bot overview, features, and configuration" -read_when: - - You want to connect a Feishu/Lark bot - - You are configuring the Feishu channel -title: Feishu ---- - -# Feishu bot - -Feishu (Lark) is a team chat platform used by companies for messaging and collaboration. This plugin connects OpenClaw to a Feishu/Lark bot using the platform’s WebSocket event subscription so messages can be received without exposing a public webhook URL. - ---- - -## Plugin required - -Install the Feishu plugin: - -```bash -openclaw plugins install @openclaw/feishu -``` - -Local checkout (when running from a git repo): - -```bash -openclaw plugins install ./extensions/feishu -``` - ---- - -## Quickstart - -There are two ways to add the Feishu channel: - -### Method 1: onboarding wizard (recommended) - -If you just installed OpenClaw, run the wizard: - -```bash -openclaw onboard -``` - -The wizard guides you through: - -1. Creating a Feishu app and collecting credentials -2. Configuring app credentials in OpenClaw -3. Starting the gateway - -✅ **After configuration**, check gateway status: - -- `openclaw gateway status` -- `openclaw logs --follow` - -### Method 2: CLI setup - -If you already completed initial install, add the channel via CLI: - -```bash -openclaw channels add -``` - -Choose **Feishu**, then enter the App ID and App Secret. - -✅ **After configuration**, manage the gateway: - -- `openclaw gateway status` -- `openclaw gateway restart` -- `openclaw logs --follow` - ---- - -## Step 1: Create a Feishu app - -### 1. Open Feishu Open Platform - -Visit [Feishu Open Platform](https://open.feishu.cn/app) and sign in. - -Lark (global) tenants should use https://open.larksuite.com/app and set `domain: "lark"` in the Feishu config. - -### 2. Create an app - -1. Click **Create enterprise app** -2. Fill in the app name + description -3. Choose an app icon - -![Create enterprise app](../images/feishu-step2-create-app.png) - -### 3. Copy credentials - -From **Credentials & Basic Info**, copy: - -- **App ID** (format: `cli_xxx`) -- **App Secret** - -❗ **Important:** keep the App Secret private. - -![Get credentials](../images/feishu-step3-credentials.png) - -### 4. Configure permissions - -On **Permissions**, click **Batch import** and paste: - -```json -{ - "scopes": { - "tenant": [ - "aily:file:read", - "aily:file:write", - "application:application.app_message_stats.overview:readonly", - "application:application:self_manage", - "application:bot.menu:write", - "contact:user.employee_id:readonly", - "corehr:file:download", - "event:ip_list", - "im:chat.access_event.bot_p2p_chat:read", - "im:chat.members:bot_access", - "im:message", - "im:message.group_at_msg:readonly", - "im:message.p2p_msg:readonly", - "im:message:readonly", - "im:message:send_as_bot", - "im:resource" - ], - "user": ["aily:file:read", "aily:file:write", "im:chat.access_event.bot_p2p_chat:read"] - } -} -``` - -![Configure permissions](../images/feishu-step4-permissions.png) - -### 5. Enable bot capability - -In **App Capability** > **Bot**: - -1. Enable bot capability -2. Set the bot name - -![Enable bot capability](../images/feishu-step5-bot-capability.png) - -### 6. Configure event subscription - -⚠️ **Important:** before setting event subscription, make sure: - -1. You already ran `openclaw channels add` for Feishu -2. The gateway is running (`openclaw gateway status`) - -In **Event Subscription**: - -1. Choose **Use long connection to receive events** (WebSocket) -2. Add the event: `im.message.receive_v1` - -⚠️ If the gateway is not running, the long-connection setup may fail to save. - -![Configure event subscription](../images/feishu-step6-event-subscription.png) - -### 7. Publish the app - -1. Create a version in **Version Management & Release** -2. Submit for review and publish -3. Wait for admin approval (enterprise apps usually auto-approve) - ---- - -## Step 2: Configure OpenClaw - -### Configure with the wizard (recommended) - -```bash -openclaw channels add -``` - -Choose **Feishu** and paste your App ID + App Secret. - -### Configure via config file - -Edit `~/.openclaw/openclaw.json`: - -```json5 -{ - channels: { - feishu: { - enabled: true, - dmPolicy: "pairing", - accounts: { - main: { - appId: "cli_xxx", - appSecret: "xxx", - botName: "My AI assistant", - }, - }, - }, - }, -} -``` - -### Configure via environment variables - -```bash -export FEISHU_APP_ID="cli_xxx" -export FEISHU_APP_SECRET="xxx" -``` - -### Lark (global) domain - -If your tenant is on Lark (international), set the domain to `lark` (or a full domain string). You can set it at `channels.feishu.domain` or per account (`channels.feishu.accounts..domain`). - -```json5 -{ - channels: { - feishu: { - domain: "lark", - accounts: { - main: { - appId: "cli_xxx", - appSecret: "xxx", - }, - }, - }, - }, -} -``` - ---- - -## Step 3: Start + test - -### 1. Start the gateway - -```bash -openclaw gateway -``` - -### 2. Send a test message - -In Feishu, find your bot and send a message. - -### 3. Approve pairing - -By default, the bot replies with a pairing code. Approve it: - -```bash -openclaw pairing approve feishu -``` - -After approval, you can chat normally. - ---- - -## Overview - -- **Feishu bot channel**: Feishu bot managed by the gateway -- **Deterministic routing**: replies always return to Feishu -- **Session isolation**: DMs share a main session; groups are isolated -- **WebSocket connection**: long connection via Feishu SDK, no public URL needed - ---- - -## Access control - -### Direct messages - -- **Default**: `dmPolicy: "pairing"` (unknown users get a pairing code) -- **Approve pairing**: - ```bash - openclaw pairing list feishu - openclaw pairing approve feishu - ``` -- **Allowlist mode**: set `channels.feishu.allowFrom` with allowed Open IDs - -### Group chats - -**1. Group policy** (`channels.feishu.groupPolicy`): - -- `"open"` = allow everyone in groups (default) -- `"allowlist"` = only allow `groupAllowFrom` -- `"disabled"` = disable group messages - -**2. Mention requirement** (`channels.feishu.groups..requireMention`): - -- `true` = require @mention (default) -- `false` = respond without mentions - ---- - -## Group configuration examples - -### Allow all groups, require @mention (default) - -```json5 -{ - channels: { - feishu: { - groupPolicy: "open", - // Default requireMention: true - }, - }, -} -``` - -### Allow all groups, no @mention required - -```json5 -{ - channels: { - feishu: { - groups: { - oc_xxx: { requireMention: false }, - }, - }, - }, -} -``` - -### Allow specific users in groups only - -```json5 -{ - channels: { - feishu: { - groupPolicy: "allowlist", - groupAllowFrom: ["ou_xxx", "ou_yyy"], - }, - }, -} -``` - ---- - -## Get group/user IDs - -### Group IDs (chat_id) - -Group IDs look like `oc_xxx`. - -**Method 1 (recommended)** - -1. Start the gateway and @mention the bot in the group -2. Run `openclaw logs --follow` and look for `chat_id` - -**Method 2** - -Use the Feishu API debugger to list group chats. - -### User IDs (open_id) - -User IDs look like `ou_xxx`. - -**Method 1 (recommended)** - -1. Start the gateway and DM the bot -2. Run `openclaw logs --follow` and look for `open_id` - -**Method 2** - -Check pairing requests for user Open IDs: - -```bash -openclaw pairing list feishu -``` - ---- - -## Common commands - -| Command | Description | -| --------- | ----------------- | -| `/status` | Show bot status | -| `/reset` | Reset the session | -| `/model` | Show/switch model | - -> Note: Feishu does not support native command menus yet, so commands must be sent as text. - -## Gateway management commands - -| Command | Description | -| -------------------------- | ----------------------------- | -| `openclaw gateway status` | Show gateway status | -| `openclaw gateway install` | Install/start gateway service | -| `openclaw gateway stop` | Stop gateway service | -| `openclaw gateway restart` | Restart gateway service | -| `openclaw logs --follow` | Tail gateway logs | - ---- - -## Troubleshooting - -### Bot does not respond in group chats - -1. Ensure the bot is added to the group -2. Ensure you @mention the bot (default behavior) -3. Check `groupPolicy` is not set to `"disabled"` -4. Check logs: `openclaw logs --follow` - -### Bot does not receive messages - -1. Ensure the app is published and approved -2. Ensure event subscription includes `im.message.receive_v1` -3. Ensure **long connection** is enabled -4. Ensure app permissions are complete -5. Ensure the gateway is running: `openclaw gateway status` -6. Check logs: `openclaw logs --follow` - -### App Secret leak - -1. Reset the App Secret in Feishu Open Platform -2. Update the App Secret in your config -3. Restart the gateway - -### Message send failures - -1. Ensure the app has `im:message:send_as_bot` permission -2. Ensure the app is published -3. Check logs for detailed errors - ---- - -## Advanced configuration - -### Multiple accounts - -```json5 -{ - channels: { - feishu: { - accounts: { - main: { - appId: "cli_xxx", - appSecret: "xxx", - botName: "Primary bot", - }, - backup: { - appId: "cli_yyy", - appSecret: "yyy", - botName: "Backup bot", - enabled: false, - }, - }, - }, - }, -} -``` - -### Message limits - -- `textChunkLimit`: outbound text chunk size (default: 2000 chars) -- `mediaMaxMb`: media upload/download limit (default: 30MB) - -### Streaming - -Feishu does not support message editing, so block streaming is enabled by default (`blockStreaming: true`). The bot waits for the full reply before sending. - ---- - -## Configuration reference - -Full configuration: [Gateway configuration](/gateway/configuration) - -Key options: - -| Setting | Description | Default | -| ------------------------------------------------- | ------------------------------- | --------- | -| `channels.feishu.enabled` | Enable/disable channel | `true` | -| `channels.feishu.domain` | API domain (`feishu` or `lark`) | `feishu` | -| `channels.feishu.accounts..appId` | App ID | - | -| `channels.feishu.accounts..appSecret` | App Secret | - | -| `channels.feishu.accounts..domain` | Per-account API domain override | `feishu` | -| `channels.feishu.dmPolicy` | DM policy | `pairing` | -| `channels.feishu.allowFrom` | DM allowlist (open_id list) | - | -| `channels.feishu.groupPolicy` | Group policy | `open` | -| `channels.feishu.groupAllowFrom` | Group allowlist | - | -| `channels.feishu.groups..requireMention` | Require @mention | `true` | -| `channels.feishu.groups..enabled` | Enable group | `true` | -| `channels.feishu.textChunkLimit` | Message chunk size | `2000` | -| `channels.feishu.mediaMaxMb` | Media size limit | `30` | -| `channels.feishu.blockStreaming` | Disable streaming | `true` | - ---- - -## dmPolicy reference - -| Value | Behavior | -| ------------- | --------------------------------------------------------------- | -| `"pairing"` | **Default.** Unknown users get a pairing code; must be approved | -| `"allowlist"` | Only users in `allowFrom` can chat | -| `"open"` | Allow all users (requires `"*"` in allowFrom) | -| `"disabled"` | Disable DMs | - ---- - -## Supported message types - -### Receive - -- ✅ Text -- ✅ Images -- ✅ Files -- ✅ Audio -- ✅ Video -- ✅ Stickers - -### Send - -- ✅ Text -- ✅ Images -- ✅ Files -- ✅ Audio -- ⚠️ Rich text (partial support) diff --git a/docs/es/channels/googlechat.md b/docs/es/channels/googlechat.md deleted file mode 100644 index 07c7dd7dc6..0000000000 --- a/docs/es/channels/googlechat.md +++ /dev/null @@ -1,250 +0,0 @@ ---- -summary: "Google Chat app support status, capabilities, and configuration" -read_when: - - Working on Google Chat channel features -title: "Google Chat" ---- - -# Google Chat (Chat API) - -Status: ready for DMs + spaces via Google Chat API webhooks (HTTP only). - -## Quick setup (beginner) - -1. Create a Google Cloud project and enable the **Google Chat API**. - - Go to: [Google Chat API Credentials](https://console.cloud.google.com/apis/api/chat.googleapis.com/credentials) - - Enable the API if it is not already enabled. -2. Create a **Service Account**: - - Press **Create Credentials** > **Service Account**. - - Name it whatever you want (e.g., `openclaw-chat`). - - Leave permissions blank (press **Continue**). - - Leave principals with access blank (press **Done**). -3. Create and download the **JSON Key**: - - In the list of service accounts, click on the one you just created. - - Go to the **Keys** tab. - - Click **Add Key** > **Create new key**. - - Select **JSON** and press **Create**. -4. Store the downloaded JSON file on your gateway host (e.g., `~/.openclaw/googlechat-service-account.json`). -5. Create a Google Chat app in the [Google Cloud Console Chat Configuration](https://console.cloud.google.com/apis/api/chat.googleapis.com/hangouts-chat): - - Fill in the **Application info**: - - **App name**: (e.g. `OpenClaw`) - - **Avatar URL**: (e.g. `https://openclaw.ai/logo.png`) - - **Description**: (e.g. `Personal AI Assistant`) - - Enable **Interactive features**. - - Under **Functionality**, check **Join spaces and group conversations**. - - Under **Connection settings**, select **HTTP endpoint URL**. - - Under **Triggers**, select **Use a common HTTP endpoint URL for all triggers** and set it to your gateway's public URL followed by `/googlechat`. - - _Tip: Run `openclaw status` to find your gateway's public URL._ - - Under **Visibility**, check **Make this Chat app available to specific people and groups in <Your Domain>**. - - Enter your email address (e.g. `user@example.com`) in the text box. - - Click **Save** at the bottom. -6. **Enable the app status**: - - After saving, **refresh the page**. - - Look for the **App status** section (usually near the top or bottom after saving). - - Change the status to **Live - available to users**. - - Click **Save** again. -7. Configure OpenClaw with the service account path + webhook audience: - - Env: `GOOGLE_CHAT_SERVICE_ACCOUNT_FILE=/path/to/service-account.json` - - Or config: `channels.googlechat.serviceAccountFile: "/path/to/service-account.json"`. -8. Set the webhook audience type + value (matches your Chat app config). -9. Start the gateway. Google Chat will POST to your webhook path. - -## Add to Google Chat - -Once the gateway is running and your email is added to the visibility list: - -1. Go to [Google Chat](https://chat.google.com/). -2. Click the **+** (plus) icon next to **Direct Messages**. -3. In the search bar (where you usually add people), type the **App name** you configured in the Google Cloud Console. - - **Note**: The bot will _not_ appear in the "Marketplace" browse list because it is a private app. You must search for it by name. -4. Select your bot from the results. -5. Click **Add** or **Chat** to start a 1:1 conversation. -6. Send "Hello" to trigger the assistant! - -## Public URL (Webhook-only) - -Google Chat webhooks require a public HTTPS endpoint. For security, **only expose the `/googlechat` path** to the internet. Keep the OpenClaw dashboard and other sensitive endpoints on your private network. - -### Option A: Tailscale Funnel (Recommended) - -Use Tailscale Serve for the private dashboard and Funnel for the public webhook path. This keeps `/` private while exposing only `/googlechat`. - -1. **Check what address your gateway is bound to:** - - ```bash - ss -tlnp | grep 18789 - ``` - - Note the IP address (e.g., `127.0.0.1`, `0.0.0.0`, or your Tailscale IP like `100.x.x.x`). - -2. **Expose the dashboard to the tailnet only (port 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. **Expose only the webhook path publicly:** - - ```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. **Authorize the node for Funnel access:** - If prompted, visit the authorization URL shown in the output to enable Funnel for this node in your tailnet policy. - -5. **Verify the configuration:** - ```bash - tailscale serve status - tailscale funnel status - ``` - -Your public webhook URL will be: -`https://..ts.net/googlechat` - -Your private dashboard stays tailnet-only: -`https://..ts.net:8443/` - -Use the public URL (without `:8443`) in the Google Chat app config. - -> Note: This configuration persists across reboots. To remove it later, run `tailscale funnel reset` and `tailscale serve reset`. - -### Option B: Reverse Proxy (Caddy) - -If you use a reverse proxy like Caddy, only proxy the specific path: - -```caddy -your-domain.com { - reverse_proxy /googlechat* localhost:18789 -} -``` - -With this config, any request to `your-domain.com/` will be ignored or returned as 404, while `your-domain.com/googlechat` is safely routed to OpenClaw. - -### Option C: Cloudflare Tunnel - -Configure your tunnel's ingress rules to only route the webhook path: - -- **Path**: `/googlechat` -> `http://localhost:18789/googlechat` -- **Default Rule**: HTTP 404 (Not Found) - -## How it works - -1. Google Chat sends webhook POSTs to the gateway. Each request includes an `Authorization: Bearer ` header. -2. OpenClaw verifies the token against the configured `audienceType` + `audience`: - - `audienceType: "app-url"` → audience is your HTTPS webhook URL. - - `audienceType: "project-number"` → audience is the Cloud project number. -3. Messages are routed by space: - - DMs use session key `agent::googlechat:dm:`. - - Spaces use session key `agent::googlechat:group:`. -4. DM access is pairing by default. Unknown senders receive a pairing code; approve with: - - `openclaw pairing approve googlechat ` -5. Group spaces require @-mention by default. Use `botUser` if mention detection needs the app’s user name. - -## Targets - -Use these identifiers for delivery and allowlists: - -- Direct messages: `users/` or `users/` (email addresses are accepted). -- Spaces: `spaces/`. - -## Config highlights - -```json5 -{ - channels: { - googlechat: { - enabled: true, - serviceAccountFile: "/path/to/service-account.json", - audienceType: "app-url", - audience: "https://gateway.example.com/googlechat", - webhookPath: "/googlechat", - botUser: "users/1234567890", // optional; helps mention detection - dm: { - policy: "pairing", - allowFrom: ["users/1234567890", "name@example.com"], - }, - groupPolicy: "allowlist", - groups: { - "spaces/AAAA": { - allow: true, - requireMention: true, - users: ["users/1234567890"], - systemPrompt: "Short answers only.", - }, - }, - actions: { reactions: true }, - typingIndicator: "message", - mediaMaxMb: 20, - }, - }, -} -``` - -Notes: - -- Service account credentials can also be passed inline with `serviceAccount` (JSON string). -- Default webhook path is `/googlechat` if `webhookPath` isn’t set. -- Reactions are available via the `reactions` tool and `channels action` when `actions.reactions` is enabled. -- `typingIndicator` supports `none`, `message` (default), and `reaction` (reaction requires user OAuth). -- Attachments are downloaded through the Chat API and stored in the media pipeline (size capped by `mediaMaxMb`). - -## Troubleshooting - -### 405 Method Not Allowed - -If Google Cloud Logs Explorer shows errors like: - -``` -status code: 405, reason phrase: HTTP error response: HTTP/1.1 405 Method Not Allowed -``` - -This means the webhook handler isn't registered. Common causes: - -1. **Channel not configured**: The `channels.googlechat` section is missing from your config. Verify with: - - ```bash - openclaw config get channels.googlechat - ``` - - If it returns "Config path not found", add the configuration (see [Config highlights](#config-highlights)). - -2. **Plugin not enabled**: Check plugin status: - - ```bash - openclaw plugins list | grep googlechat - ``` - - If it shows "disabled", add `plugins.entries.googlechat.enabled: true` to your config. - -3. **Gateway not restarted**: After adding config, restart the gateway: - ```bash - openclaw gateway restart - ``` - -Verify the channel is running: - -```bash -openclaw channels status -# Should show: Google Chat default: enabled, configured, ... -``` - -### Other issues - -- Check `openclaw channels status --probe` for auth errors or missing audience config. -- If no messages arrive, confirm the Chat app's webhook URL + event subscriptions. -- If mention gating blocks replies, set `botUser` to the app's user resource name and verify `requireMention`. -- Use `openclaw logs --follow` while sending a test message to see if requests reach the gateway. - -Related docs: - -- [Gateway configuration](/gateway/configuration) -- [Security](/gateway/security) -- [Reactions](/tools/reactions) diff --git a/docs/es/channels/grammy.md b/docs/es/channels/grammy.md deleted file mode 100644 index 1b73394ef7..0000000000 --- a/docs/es/channels/grammy.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -summary: "Telegram Bot API integration via grammY with setup notes" -read_when: - - Working on Telegram or grammY pathways -title: grammY ---- - -# grammY Integration (Telegram Bot API) - -# Why grammY - -- TS-first Bot API client with built-in long-poll + webhook helpers, middleware, error handling, rate limiter. -- Cleaner media helpers than hand-rolling fetch + FormData; supports all Bot API methods. -- Extensible: proxy support via custom fetch, session middleware (optional), type-safe context. - -# What we shipped - -- **Single client path:** fetch-based implementation removed; grammY is now the sole Telegram client (send + gateway) with the grammY throttler enabled by default. -- **Gateway:** `monitorTelegramProvider` builds a grammY `Bot`, wires mention/allowlist gating, media download via `getFile`/`download`, and delivers replies with `sendMessage/sendPhoto/sendVideo/sendAudio/sendDocument`. Supports long-poll or webhook via `webhookCallback`. -- **Proxy:** optional `channels.telegram.proxy` uses `undici.ProxyAgent` through grammY’s `client.baseFetch`. -- **Webhook support:** `webhook-set.ts` wraps `setWebhook/deleteWebhook`; `webhook.ts` hosts the callback with health + graceful shutdown. Gateway enables webhook mode when `channels.telegram.webhookUrl` + `channels.telegram.webhookSecret` are set (otherwise it long-polls). -- **Sessions:** direct chats collapse into the agent main session (`agent::`); groups use `agent::telegram:group:`; replies route back to the same channel. -- **Config knobs:** `channels.telegram.botToken`, `channels.telegram.dmPolicy`, `channels.telegram.groups` (allowlist + mention defaults), `channels.telegram.allowFrom`, `channels.telegram.groupAllowFrom`, `channels.telegram.groupPolicy`, `channels.telegram.mediaMaxMb`, `channels.telegram.linkPreview`, `channels.telegram.proxy`, `channels.telegram.webhookSecret`, `channels.telegram.webhookUrl`. -- **Draft streaming:** optional `channels.telegram.streamMode` uses `sendMessageDraft` in private topic chats (Bot API 9.3+). This is separate from channel block streaming. -- **Tests:** grammy mocks cover DM + group mention gating and outbound send; more media/webhook fixtures still welcome. - -Open questions - -- Optional grammY plugins (throttler) if we hit Bot API 429s. -- Add more structured media tests (stickers, voice notes). -- Make webhook listen port configurable (currently fixed to 8787 unless wired through the gateway). diff --git a/docs/es/channels/imessage.md b/docs/es/channels/imessage.md deleted file mode 100644 index 5542b3190c..0000000000 --- a/docs/es/channels/imessage.md +++ /dev/null @@ -1,299 +0,0 @@ ---- -summary: "Legacy iMessage support via imsg (JSON-RPC over stdio). New setups should use BlueBubbles." -read_when: - - Setting up iMessage support - - Debugging iMessage send/receive -title: iMessage ---- - -# iMessage (legacy: imsg) - -> **Recommended:** Use [BlueBubbles](/channels/bluebubbles) for new iMessage setups. -> -> The `imsg` channel is a legacy external-CLI integration and may be removed in a future release. - -Status: legacy external CLI integration. Gateway spawns `imsg rpc` (JSON-RPC over stdio). - -## Quick setup (beginner) - -1. Ensure Messages is signed in on this Mac. -2. Install `imsg`: - - `brew install steipete/tap/imsg` -3. Configure OpenClaw with `channels.imessage.cliPath` and `channels.imessage.dbPath`. -4. Start the gateway and approve any macOS prompts (Automation + Full Disk Access). - -Minimal config: - -```json5 -{ - channels: { - imessage: { - enabled: true, - cliPath: "/usr/local/bin/imsg", - dbPath: "/Users//Library/Messages/chat.db", - }, - }, -} -``` - -## What it is - -- iMessage channel backed by `imsg` on macOS. -- Deterministic routing: replies always go back to iMessage. -- DMs share the agent's main session; groups are isolated (`agent::imessage:group:`). -- If a multi-participant thread arrives with `is_group=false`, you can still isolate it by `chat_id` using `channels.imessage.groups` (see “Group-ish threads” below). - -## Config writes - -By default, iMessage is allowed to write config updates triggered by `/config set|unset` (requires `commands.config: true`). - -Disable with: - -```json5 -{ - channels: { imessage: { configWrites: false } }, -} -``` - -## Requirements - -- macOS with Messages signed in. -- Full Disk Access for OpenClaw + `imsg` (Messages DB access). -- Automation permission when sending. -- `channels.imessage.cliPath` can point to any command that proxies stdin/stdout (for example, a wrapper script that SSHes to another Mac and runs `imsg rpc`). - -## Setup (fast path) - -1. Ensure Messages is signed in on this Mac. -2. Configure iMessage and start the gateway. - -### Dedicated bot macOS user (for isolated identity) - -If you want the bot to send from a **separate iMessage identity** (and keep your personal Messages clean), use a dedicated Apple ID + a dedicated macOS user. - -1. Create a dedicated Apple ID (example: `my-cool-bot@icloud.com`). - - Apple may require a phone number for verification / 2FA. -2. Create a macOS user (example: `openclawhome`) and sign into it. -3. Open Messages in that macOS user and sign into iMessage using the bot Apple ID. -4. Enable Remote Login (System Settings → General → Sharing → Remote Login). -5. Install `imsg`: - - `brew install steipete/tap/imsg` -6. Set up SSH so `ssh @localhost true` works without a password. -7. Point `channels.imessage.accounts.bot.cliPath` at an SSH wrapper that runs `imsg` as the bot user. - -First-run note: sending/receiving may require GUI approvals (Automation + Full Disk Access) in the _bot macOS user_. If `imsg rpc` looks stuck or exits, log into that user (Screen Sharing helps), run a one-time `imsg chats --limit 1` / `imsg send ...`, approve prompts, then retry. - -Example wrapper (`chmod +x`). Replace `` with your actual macOS username: - -```bash -#!/usr/bin/env bash -set -euo pipefail - -# Run an interactive SSH once first to accept host keys: -# ssh @localhost true -exec /usr/bin/ssh -o BatchMode=yes -o ConnectTimeout=5 -T @localhost \ - "/usr/local/bin/imsg" "$@" -``` - -Example config: - -```json5 -{ - channels: { - imessage: { - enabled: true, - accounts: { - bot: { - name: "Bot", - enabled: true, - cliPath: "/path/to/imsg-bot", - dbPath: "/Users//Library/Messages/chat.db", - }, - }, - }, - }, -} -``` - -For single-account setups, use flat options (`channels.imessage.cliPath`, `channels.imessage.dbPath`) instead of the `accounts` map. - -### Remote/SSH variant (optional) - -If you want iMessage on another Mac, set `channels.imessage.cliPath` to a wrapper that runs `imsg` on the remote macOS host over SSH. OpenClaw only needs stdio. - -Example wrapper: - -```bash -#!/usr/bin/env bash -exec ssh -T gateway-host imsg "$@" -``` - -**Remote attachments:** When `cliPath` points to a remote host via SSH, attachment paths in the Messages database reference files on the remote machine. OpenClaw can automatically fetch these over SCP by setting `channels.imessage.remoteHost`: - -```json5 -{ - channels: { - imessage: { - cliPath: "~/imsg-ssh", // SSH wrapper to remote Mac - remoteHost: "user@gateway-host", // for SCP file transfer - includeAttachments: true, - }, - }, -} -``` - -If `remoteHost` is not set, OpenClaw attempts to auto-detect it by parsing the SSH command in your wrapper script. Explicit configuration is recommended for reliability. - -#### Remote Mac via Tailscale (example) - -If the Gateway runs on a Linux host/VM but iMessage must run on a Mac, Tailscale is the simplest bridge: the Gateway talks to the Mac over the tailnet, runs `imsg` via SSH, and SCPs attachments back. - -Architecture: - -``` -┌──────────────────────────────┐ SSH (imsg rpc) ┌──────────────────────────┐ -│ Gateway host (Linux/VM) │──────────────────────────────────▶│ Mac with Messages + imsg │ -│ - openclaw gateway │ SCP (attachments) │ - Messages signed in │ -│ - channels.imessage.cliPath │◀──────────────────────────────────│ - Remote Login enabled │ -└──────────────────────────────┘ └──────────────────────────┘ - ▲ - │ Tailscale tailnet (hostname or 100.x.y.z) - ▼ - user@gateway-host -``` - -Concrete config example (Tailscale hostname): - -```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", - }, - }, -} -``` - -Example wrapper (`~/.openclaw/scripts/imsg-ssh`): - -```bash -#!/usr/bin/env bash -exec ssh -T bot@mac-mini.tailnet-1234.ts.net imsg "$@" -``` - -Notes: - -- Ensure the Mac is signed in to Messages, and Remote Login is enabled. -- Use SSH keys so `ssh bot@mac-mini.tailnet-1234.ts.net` works without prompts. -- `remoteHost` should match the SSH target so SCP can fetch attachments. - -Multi-account support: use `channels.imessage.accounts` with per-account config and optional `name`. See [`gateway/configuration`](/gateway/configuration#telegramaccounts--discordaccounts--slackaccounts--signalaccounts--imessageaccounts) for the shared pattern. Don't commit `~/.openclaw/openclaw.json` (it often contains tokens). - -## Access control (DMs + groups) - -DMs: - -- Default: `channels.imessage.dmPolicy = "pairing"`. -- Unknown senders receive a pairing code; messages are ignored until approved (codes expire after 1 hour). -- Approve via: - - `openclaw pairing list imessage` - - `openclaw pairing approve imessage ` -- Pairing is the default token exchange for iMessage DMs. Details: [Pairing](/start/pairing) - -Groups: - -- `channels.imessage.groupPolicy = open | allowlist | disabled`. -- `channels.imessage.groupAllowFrom` controls who can trigger in groups when `allowlist` is set. -- Mention gating uses `agents.list[].groupChat.mentionPatterns` (or `messages.groupChat.mentionPatterns`) because iMessage has no native mention metadata. -- Multi-agent override: set per-agent patterns on `agents.list[].groupChat.mentionPatterns`. - -## How it works (behavior) - -- `imsg` streams message events; the gateway normalizes them into the shared channel envelope. -- Replies always route back to the same chat id or handle. - -## Group-ish threads (`is_group=false`) - -Some iMessage threads can have multiple participants but still arrive with `is_group=false` depending on how Messages stores the chat identifier. - -If you explicitly configure a `chat_id` under `channels.imessage.groups`, OpenClaw treats that thread as a “group” for: - -- session isolation (separate `agent::imessage:group:` session key) -- group allowlisting / mention gating behavior - -Example: - -```json5 -{ - channels: { - imessage: { - groupPolicy: "allowlist", - groupAllowFrom: ["+15555550123"], - groups: { - "42": { requireMention: false }, - }, - }, - }, -} -``` - -This is useful when you want an isolated personality/model for a specific thread (see [Multi-agent routing](/concepts/multi-agent)). For filesystem isolation, see [Sandboxing](/gateway/sandboxing). - -## Media + limits - -- Optional attachment ingestion via `channels.imessage.includeAttachments`. -- Media cap via `channels.imessage.mediaMaxMb`. - -## Limits - -- Outbound text is chunked to `channels.imessage.textChunkLimit` (default 4000). -- Optional newline chunking: set `channels.imessage.chunkMode="newline"` to split on blank lines (paragraph boundaries) before length chunking. -- Media uploads are capped by `channels.imessage.mediaMaxMb` (default 16). - -## Addressing / delivery targets - -Prefer `chat_id` for stable routing: - -- `chat_id:123` (preferred) -- `chat_guid:...` -- `chat_identifier:...` -- direct handles: `imessage:+1555` / `sms:+1555` / `user@example.com` - -List chats: - -``` -imsg chats --limit 20 -``` - -## Configuration reference (iMessage) - -Full configuration: [Configuration](/gateway/configuration) - -Provider options: - -- `channels.imessage.enabled`: enable/disable channel startup. -- `channels.imessage.cliPath`: path to `imsg`. -- `channels.imessage.dbPath`: Messages DB path. -- `channels.imessage.remoteHost`: SSH host for SCP attachment transfer when `cliPath` points to a remote Mac (e.g., `user@gateway-host`). Auto-detected from SSH wrapper if not set. -- `channels.imessage.service`: `imessage | sms | auto`. -- `channels.imessage.region`: SMS region. -- `channels.imessage.dmPolicy`: `pairing | allowlist | open | disabled` (default: pairing). -- `channels.imessage.allowFrom`: DM allowlist (handles, emails, E.164 numbers, or `chat_id:*`). `open` requires `"*"`. iMessage has no usernames; use handles or chat targets. -- `channels.imessage.groupPolicy`: `open | allowlist | disabled` (default: allowlist). -- `channels.imessage.groupAllowFrom`: group sender allowlist. -- `channels.imessage.historyLimit` / `channels.imessage.accounts.*.historyLimit`: max group messages to include as context (0 disables). -- `channels.imessage.dmHistoryLimit`: DM history limit in user turns. Per-user overrides: `channels.imessage.dms[""].historyLimit`. -- `channels.imessage.groups`: per-group defaults + allowlist (use `"*"` for global defaults). -- `channels.imessage.includeAttachments`: ingest attachments into context. -- `channels.imessage.mediaMaxMb`: inbound/outbound media cap (MB). -- `channels.imessage.textChunkLimit`: outbound chunk size (chars). -- `channels.imessage.chunkMode`: `length` (default) or `newline` to split on blank lines (paragraph boundaries) before length chunking. - -Related global options: - -- `agents.list[].groupChat.mentionPatterns` (or `messages.groupChat.mentionPatterns`). -- `messages.responsePrefix`. diff --git a/docs/es/channels/index.md b/docs/es/channels/index.md deleted file mode 100644 index 844af27505..0000000000 --- a/docs/es/channels/index.md +++ /dev/null @@ -1,46 +0,0 @@ ---- -summary: "Messaging platforms OpenClaw can connect to" -read_when: - - You want to choose a chat channel for OpenClaw - - You need a quick overview of supported messaging platforms -title: "Chat Channels" ---- - -# Chat Channels - -OpenClaw can talk to you on any chat app you already use. Each channel connects via the Gateway. -Text is supported everywhere; media and reactions vary by channel. - -## Supported channels - -- [WhatsApp](/channels/whatsapp) — Most popular; uses Baileys and requires QR pairing. -- [Telegram](/channels/telegram) — Bot API via grammY; supports groups. -- [Discord](/channels/discord) — Discord Bot API + Gateway; supports servers, channels, and DMs. -- [Slack](/channels/slack) — Bolt SDK; workspace apps. -- [Feishu](/channels/feishu) — Feishu/Lark bot via WebSocket (plugin, installed separately). -- [Google Chat](/channels/googlechat) — Google Chat API app via HTTP webhook. -- [Mattermost](/channels/mattermost) — Bot API + WebSocket; channels, groups, DMs (plugin, installed separately). -- [Signal](/channels/signal) — signal-cli; privacy-focused. -- [BlueBubbles](/channels/bluebubbles) — **Recommended for iMessage**; uses the BlueBubbles macOS server REST API with full feature support (edit, unsend, effects, reactions, group management — edit currently broken on macOS 26 Tahoe). -- [iMessage (legacy)](/channels/imessage) — Legacy macOS integration via imsg CLI (deprecated, use BlueBubbles for new setups). -- [Microsoft Teams](/channels/msteams) — Bot Framework; enterprise support (plugin, installed separately). -- [LINE](/channels/line) — LINE Messaging API bot (plugin, installed separately). -- [Nextcloud Talk](/channels/nextcloud-talk) — Self-hosted chat via Nextcloud Talk (plugin, installed separately). -- [Matrix](/channels/matrix) — Matrix protocol (plugin, installed separately). -- [Nostr](/channels/nostr) — Decentralized DMs via NIP-04 (plugin, installed separately). -- [Tlon](/channels/tlon) — Urbit-based messenger (plugin, installed separately). -- [Twitch](/channels/twitch) — Twitch chat via IRC connection (plugin, installed separately). -- [Zalo](/channels/zalo) — Zalo Bot API; Vietnam's popular messenger (plugin, installed separately). -- [Zalo Personal](/channels/zalouser) — Zalo personal account via QR login (plugin, installed separately). -- [WebChat](/web/webchat) — Gateway WebChat UI over WebSocket. - -## Notes - -- Channels can run simultaneously; configure multiple and OpenClaw will route per chat. -- Fastest setup is usually **Telegram** (simple bot token). WhatsApp requires QR pairing and - stores more state on disk. -- Group behavior varies by channel; see [Groups](/concepts/groups). -- DM pairing and allowlists are enforced for safety; see [Security](/gateway/security). -- Telegram internals: [grammY notes](/channels/grammy). -- Troubleshooting: [Channel troubleshooting](/channels/troubleshooting). -- Model providers are documented separately; see [Model Providers](/providers/models). diff --git a/docs/es/channels/line.md b/docs/es/channels/line.md deleted file mode 100644 index f68ae5aa1e..0000000000 --- a/docs/es/channels/line.md +++ /dev/null @@ -1,186 +0,0 @@ ---- -summary: "LINE Messaging API plugin setup, config, and usage" -read_when: - - You want to connect OpenClaw to LINE - - You need LINE webhook + credential setup - - You want LINE-specific message options -title: LINE ---- - -# LINE (plugin) - -LINE connects to OpenClaw via the LINE Messaging API. The plugin runs as a webhook -receiver on the gateway and uses your channel access token + channel secret for -authentication. - -Status: supported via plugin. Direct messages, group chats, media, locations, Flex -messages, template messages, and quick replies are supported. Reactions and threads -are not supported. - -## Plugin required - -Install the LINE plugin: - -```bash -openclaw plugins install @openclaw/line -``` - -Local checkout (when running from a git repo): - -```bash -openclaw plugins install ./extensions/line -``` - -## Setup - -1. Create a LINE Developers account and open the Console: - https://developers.line.biz/console/ -2. Create (or pick) a Provider and add a **Messaging API** channel. -3. Copy the **Channel access token** and **Channel secret** from the channel settings. -4. Enable **Use webhook** in the Messaging API settings. -5. Set the webhook URL to your gateway endpoint (HTTPS required): - -``` -https://gateway-host/line/webhook -``` - -The gateway responds to LINE’s webhook verification (GET) and inbound events (POST). -If you need a custom path, set `channels.line.webhookPath` or -`channels.line.accounts..webhookPath` and update the URL accordingly. - -## Configure - -Minimal config: - -```json5 -{ - channels: { - line: { - enabled: true, - channelAccessToken: "LINE_CHANNEL_ACCESS_TOKEN", - channelSecret: "LINE_CHANNEL_SECRET", - dmPolicy: "pairing", - }, - }, -} -``` - -Env vars (default account only): - -- `LINE_CHANNEL_ACCESS_TOKEN` -- `LINE_CHANNEL_SECRET` - -Token/secret files: - -```json5 -{ - channels: { - line: { - tokenFile: "/path/to/line-token.txt", - secretFile: "/path/to/line-secret.txt", - }, - }, -} -``` - -Multiple accounts: - -```json5 -{ - channels: { - line: { - accounts: { - marketing: { - channelAccessToken: "...", - channelSecret: "...", - webhookPath: "/line/marketing", - }, - }, - }, - }, -} -``` - -## Access control - -Direct messages default to pairing. Unknown senders get a pairing code and their -messages are ignored until approved. - -```bash -openclaw pairing list line -openclaw pairing approve line -``` - -Allowlists and policies: - -- `channels.line.dmPolicy`: `pairing | allowlist | open | disabled` -- `channels.line.allowFrom`: allowlisted LINE user IDs for DMs -- `channels.line.groupPolicy`: `allowlist | open | disabled` -- `channels.line.groupAllowFrom`: allowlisted LINE user IDs for groups -- Per-group overrides: `channels.line.groups..allowFrom` - -LINE IDs are case-sensitive. Valid IDs look like: - -- User: `U` + 32 hex chars -- Group: `C` + 32 hex chars -- Room: `R` + 32 hex chars - -## Message behavior - -- Text is chunked at 5000 characters. -- Markdown formatting is stripped; code blocks and tables are converted into Flex - cards when possible. -- Streaming responses are buffered; LINE receives full chunks with a loading - animation while the agent works. -- Media downloads are capped by `channels.line.mediaMaxMb` (default 10). - -## Channel data (rich messages) - -Use `channelData.line` to send quick replies, locations, Flex cards, or template -messages. - -```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", - }, - }, - }, -} -``` - -The LINE plugin also ships a `/card` command for Flex message presets: - -``` -/card info "Welcome" "Thanks for joining!" -``` - -## Troubleshooting - -- **Webhook verification fails:** ensure the webhook URL is HTTPS and the - `channelSecret` matches the LINE console. -- **No inbound events:** confirm the webhook path matches `channels.line.webhookPath` - and that the gateway is reachable from LINE. -- **Media download errors:** raise `channels.line.mediaMaxMb` if media exceeds the - default limit. diff --git a/docs/es/channels/location.md b/docs/es/channels/location.md deleted file mode 100644 index 103f57663c..0000000000 --- a/docs/es/channels/location.md +++ /dev/null @@ -1,56 +0,0 @@ ---- -summary: "Inbound channel location parsing (Telegram + WhatsApp) and context fields" -read_when: - - Adding or modifying channel location parsing - - Using location context fields in agent prompts or tools -title: "Channel Location Parsing" ---- - -# Channel location parsing - -OpenClaw normalizes shared locations from chat channels into: - -- human-readable text appended to the inbound body, and -- structured fields in the auto-reply context payload. - -Currently supported: - -- **Telegram** (location pins + venues + live locations) -- **WhatsApp** (locationMessage + liveLocationMessage) -- **Matrix** (`m.location` with `geo_uri`) - -## Text formatting - -Locations are rendered as friendly lines without brackets: - -- Pin: - - `📍 48.858844, 2.294351 ±12m` -- Named place: - - `📍 Eiffel Tower — Champ de Mars, Paris (48.858844, 2.294351 ±12m)` -- Live share: - - `🛰 Live location: 48.858844, 2.294351 ±12m` - -If the channel includes a caption/comment, it is appended on the next line: - -``` -📍 48.858844, 2.294351 ±12m -Meet here -``` - -## Context fields - -When a location is present, these fields are added to `ctx`: - -- `LocationLat` (number) -- `LocationLon` (number) -- `LocationAccuracy` (number, meters; optional) -- `LocationName` (string; optional) -- `LocationAddress` (string; optional) -- `LocationSource` (`pin | place | live`) -- `LocationIsLive` (boolean) - -## Channel notes - -- **Telegram**: venues map to `LocationName/LocationAddress`; live locations use `live_period`. -- **WhatsApp**: `locationMessage.comment` and `liveLocationMessage.caption` are appended as the caption line. -- **Matrix**: `geo_uri` is parsed as a pin location; altitude is ignored and `LocationIsLive` is always false. diff --git a/docs/es/channels/matrix.md b/docs/es/channels/matrix.md deleted file mode 100644 index a196a68b67..0000000000 --- a/docs/es/channels/matrix.md +++ /dev/null @@ -1,233 +0,0 @@ ---- -summary: "Matrix support status, capabilities, and configuration" -read_when: - - Working on Matrix channel features -title: "Matrix" ---- - -# Matrix (plugin) - -Matrix is an open, decentralized messaging protocol. OpenClaw connects as a Matrix **user** -on any homeserver, so you need a Matrix account for the bot. Once it is logged in, you can DM -the bot directly or invite it to rooms (Matrix "groups"). Beeper is a valid client option too, -but it requires E2EE to be enabled. - -Status: supported via plugin (@vector-im/matrix-bot-sdk). Direct messages, rooms, threads, media, reactions, -polls (send + poll-start as text), location, and E2EE (with crypto support). - -## Plugin required - -Matrix ships as a plugin and is not bundled with the core install. - -Install via CLI (npm registry): - -```bash -openclaw plugins install @openclaw/matrix -``` - -Local checkout (when running from a git repo): - -```bash -openclaw plugins install ./extensions/matrix -``` - -If you choose Matrix during configure/onboarding and a git checkout is detected, -OpenClaw will offer the local install path automatically. - -Details: [Plugins](/plugin) - -## Setup - -1. Install the Matrix plugin: - - From npm: `openclaw plugins install @openclaw/matrix` - - From a local checkout: `openclaw plugins install ./extensions/matrix` -2. Create a Matrix account on a homeserver: - - Browse hosting options at [https://matrix.org/ecosystem/hosting/](https://matrix.org/ecosystem/hosting/) - - Or host it yourself. -3. Get an access token for the bot account: - - Use the Matrix login API with `curl` at your home server: - - ```bash - curl --request POST \ - --url https://matrix.example.org/_matrix/client/v3/login \ - --header 'Content-Type: application/json' \ - --data '{ - "type": "m.login.password", - "identifier": { - "type": "m.id.user", - "user": "your-user-name" - }, - "password": "your-password" - }' - ``` - - - Replace `matrix.example.org` with your homeserver URL. - - Or set `channels.matrix.userId` + `channels.matrix.password`: OpenClaw calls the same - login endpoint, stores the access token in `~/.openclaw/credentials/matrix/credentials.json`, - and reuses it on next start. - -4. Configure credentials: - - Env: `MATRIX_HOMESERVER`, `MATRIX_ACCESS_TOKEN` (or `MATRIX_USER_ID` + `MATRIX_PASSWORD`) - - Or config: `channels.matrix.*` - - If both are set, config takes precedence. - - With access token: user ID is fetched automatically via `/whoami`. - - When set, `channels.matrix.userId` should be the full Matrix ID (example: `@bot:example.org`). -5. Restart the gateway (or finish onboarding). -6. Start a DM with the bot or invite it to a room from any Matrix client - (Element, Beeper, etc.; see https://matrix.org/ecosystem/clients/). Beeper requires E2EE, - so set `channels.matrix.encryption: true` and verify the device. - -Minimal config (access token, user ID auto-fetched): - -```json5 -{ - channels: { - matrix: { - enabled: true, - homeserver: "https://matrix.example.org", - accessToken: "syt_***", - dm: { policy: "pairing" }, - }, - }, -} -``` - -E2EE config (end to end encryption enabled): - -```json5 -{ - channels: { - matrix: { - enabled: true, - homeserver: "https://matrix.example.org", - accessToken: "syt_***", - encryption: true, - dm: { policy: "pairing" }, - }, - }, -} -``` - -## Encryption (E2EE) - -End-to-end encryption is **supported** via the Rust crypto SDK. - -Enable with `channels.matrix.encryption: true`: - -- If the crypto module loads, encrypted rooms are decrypted automatically. -- Outbound media is encrypted when sending to encrypted rooms. -- On first connection, OpenClaw requests device verification from your other sessions. -- Verify the device in another Matrix client (Element, etc.) to enable key sharing. -- If the crypto module cannot be loaded, E2EE is disabled and encrypted rooms will not decrypt; - OpenClaw logs a warning. -- If you see missing crypto module errors (for example, `@matrix-org/matrix-sdk-crypto-nodejs-*`), - allow build scripts for `@matrix-org/matrix-sdk-crypto-nodejs` and run - `pnpm rebuild @matrix-org/matrix-sdk-crypto-nodejs` or fetch the binary with - `node node_modules/@matrix-org/matrix-sdk-crypto-nodejs/download-lib.js`. - -Crypto state is stored per account + access token in -`~/.openclaw/matrix/accounts//__//crypto/` -(SQLite database). Sync state lives alongside it in `bot-storage.json`. -If the access token (device) changes, a new store is created and the bot must be -re-verified for encrypted rooms. - -**Device verification:** -When E2EE is enabled, the bot will request verification from your other sessions on startup. -Open Element (or another client) and approve the verification request to establish trust. -Once verified, the bot can decrypt messages in encrypted rooms. - -## Routing model - -- Replies always go back to Matrix. -- DMs share the agent's main session; rooms map to group sessions. - -## Access control (DMs) - -- Default: `channels.matrix.dm.policy = "pairing"`. Unknown senders get a pairing code. -- Approve via: - - `openclaw pairing list matrix` - - `openclaw pairing approve matrix ` -- Public DMs: `channels.matrix.dm.policy="open"` plus `channels.matrix.dm.allowFrom=["*"]`. -- `channels.matrix.dm.allowFrom` accepts full Matrix user IDs (example: `@user:server`). The wizard resolves display names to user IDs when directory search finds a single exact match. - -## Rooms (groups) - -- Default: `channels.matrix.groupPolicy = "allowlist"` (mention-gated). Use `channels.defaults.groupPolicy` to override the default when unset. -- Allowlist rooms with `channels.matrix.groups` (room IDs or aliases; names are resolved to IDs when directory search finds a single exact match): - -```json5 -{ - channels: { - matrix: { - groupPolicy: "allowlist", - groups: { - "!roomId:example.org": { allow: true }, - "#alias:example.org": { allow: true }, - }, - groupAllowFrom: ["@owner:example.org"], - }, - }, -} -``` - -- `requireMention: false` enables auto-reply in that room. -- `groups."*"` can set defaults for mention gating across rooms. -- `groupAllowFrom` restricts which senders can trigger the bot in rooms (full Matrix user IDs). -- Per-room `users` allowlists can further restrict senders inside a specific room (use full Matrix user IDs). -- The configure wizard prompts for room allowlists (room IDs, aliases, or names) and resolves names only on an exact, unique match. -- On startup, OpenClaw resolves room/user names in allowlists to IDs and logs the mapping; unresolved entries are ignored for allowlist matching. -- Invites are auto-joined by default; control with `channels.matrix.autoJoin` and `channels.matrix.autoJoinAllowlist`. -- To allow **no rooms**, set `channels.matrix.groupPolicy: "disabled"` (or keep an empty allowlist). -- Legacy key: `channels.matrix.rooms` (same shape as `groups`). - -## Threads - -- Reply threading is supported. -- `channels.matrix.threadReplies` controls whether replies stay in threads: - - `off`, `inbound` (default), `always` -- `channels.matrix.replyToMode` controls reply-to metadata when not replying in a thread: - - `off` (default), `first`, `all` - -## Capabilities - -| Feature | Status | -| --------------- | ------------------------------------------------------------------------------------- | -| Direct messages | ✅ Supported | -| Rooms | ✅ Supported | -| Threads | ✅ Supported | -| Media | ✅ Supported | -| E2EE | ✅ Supported (crypto module required) | -| Reactions | ✅ Supported (send/read via tools) | -| Polls | ✅ Send supported; inbound poll starts are converted to text (responses/ends ignored) | -| Location | ✅ Supported (geo URI; altitude ignored) | -| Native commands | ✅ Supported | - -## Configuration reference (Matrix) - -Full configuration: [Configuration](/gateway/configuration) - -Provider options: - -- `channels.matrix.enabled`: enable/disable channel startup. -- `channels.matrix.homeserver`: homeserver URL. -- `channels.matrix.userId`: Matrix user ID (optional with access token). -- `channels.matrix.accessToken`: access token. -- `channels.matrix.password`: password for login (token stored). -- `channels.matrix.deviceName`: device display name. -- `channels.matrix.encryption`: enable E2EE (default: false). -- `channels.matrix.initialSyncLimit`: initial sync limit. -- `channels.matrix.threadReplies`: `off | inbound | always` (default: inbound). -- `channels.matrix.textChunkLimit`: outbound text chunk size (chars). -- `channels.matrix.chunkMode`: `length` (default) or `newline` to split on blank lines (paragraph boundaries) before length chunking. -- `channels.matrix.dm.policy`: `pairing | allowlist | open | disabled` (default: pairing). -- `channels.matrix.dm.allowFrom`: DM allowlist (full Matrix user IDs). `open` requires `"*"`. The wizard resolves names to IDs when possible. -- `channels.matrix.groupPolicy`: `allowlist | open | disabled` (default: allowlist). -- `channels.matrix.groupAllowFrom`: allowlisted senders for group messages (full Matrix user IDs). -- `channels.matrix.allowlistOnly`: force allowlist rules for DMs + rooms. -- `channels.matrix.groups`: group allowlist + per-room settings map. -- `channels.matrix.rooms`: legacy group allowlist/config. -- `channels.matrix.replyToMode`: reply-to mode for threads/tags. -- `channels.matrix.mediaMaxMb`: inbound/outbound media cap (MB). -- `channels.matrix.autoJoin`: invite handling (`always | allowlist | off`, default: always). -- `channels.matrix.autoJoinAllowlist`: allowed room IDs/aliases for auto-join. -- `channels.matrix.actions`: per-action tool gating (reactions/messages/pins/memberInfo/channelInfo). diff --git a/docs/es/channels/mattermost.md b/docs/es/channels/mattermost.md deleted file mode 100644 index 8958f5b5b7..0000000000 --- a/docs/es/channels/mattermost.md +++ /dev/null @@ -1,138 +0,0 @@ ---- -summary: "Mattermost bot setup and OpenClaw config" -read_when: - - Setting up Mattermost - - Debugging Mattermost routing -title: "Mattermost" ---- - -# Mattermost (plugin) - -Status: supported via plugin (bot token + WebSocket events). Channels, groups, and DMs are supported. -Mattermost is a self-hostable team messaging platform; see the official site at -[mattermost.com](https://mattermost.com) for product details and downloads. - -## Plugin required - -Mattermost ships as a plugin and is not bundled with the core install. - -Install via CLI (npm registry): - -```bash -openclaw plugins install @openclaw/mattermost -``` - -Local checkout (when running from a git repo): - -```bash -openclaw plugins install ./extensions/mattermost -``` - -If you choose Mattermost during configure/onboarding and a git checkout is detected, -OpenClaw will offer the local install path automatically. - -Details: [Plugins](/plugin) - -## Quick setup - -1. Install the Mattermost plugin. -2. Create a Mattermost bot account and copy the **bot token**. -3. Copy the Mattermost **base URL** (e.g., `https://chat.example.com`). -4. Configure OpenClaw and start the gateway. - -Minimal config: - -```json5 -{ - channels: { - mattermost: { - enabled: true, - botToken: "mm-token", - baseUrl: "https://chat.example.com", - dmPolicy: "pairing", - }, - }, -} -``` - -## Environment variables (default account) - -Set these on the gateway host if you prefer env vars: - -- `MATTERMOST_BOT_TOKEN=...` -- `MATTERMOST_URL=https://chat.example.com` - -Env vars apply only to the **default** account (`default`). Other accounts must use config values. - -## Chat modes - -Mattermost responds to DMs automatically. Channel behavior is controlled by `chatmode`: - -- `oncall` (default): respond only when @mentioned in channels. -- `onmessage`: respond to every channel message. -- `onchar`: respond when a message starts with a trigger prefix. - -Config example: - -```json5 -{ - channels: { - mattermost: { - chatmode: "onchar", - oncharPrefixes: [">", "!"], - }, - }, -} -``` - -Notes: - -- `onchar` still responds to explicit @mentions. -- `channels.mattermost.requireMention` is honored for legacy configs but `chatmode` is preferred. - -## Access control (DMs) - -- Default: `channels.mattermost.dmPolicy = "pairing"` (unknown senders get a pairing code). -- Approve via: - - `openclaw pairing list mattermost` - - `openclaw pairing approve mattermost ` -- Public DMs: `channels.mattermost.dmPolicy="open"` plus `channels.mattermost.allowFrom=["*"]`. - -## Channels (groups) - -- Default: `channels.mattermost.groupPolicy = "allowlist"` (mention-gated). -- Allowlist senders with `channels.mattermost.groupAllowFrom` (user IDs or `@username`). -- Open channels: `channels.mattermost.groupPolicy="open"` (mention-gated). - -## Targets for outbound delivery - -Use these target formats with `openclaw message send` or cron/webhooks: - -- `channel:` for a channel -- `user:` for a DM -- `@username` for a DM (resolved via the Mattermost API) - -Bare IDs are treated as channels. - -## Multi-account - -Mattermost supports multiple accounts under `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" }, - }, - }, - }, -} -``` - -## Troubleshooting - -- No replies in channels: ensure the bot is in the channel and mention it (oncall), use a trigger prefix (onchar), or set `chatmode: "onmessage"`. -- Auth errors: check the bot token, base URL, and whether the account is enabled. -- Multi-account issues: env vars only apply to the `default` account. diff --git a/docs/es/channels/msteams.md b/docs/es/channels/msteams.md deleted file mode 100644 index a18e8063d0..0000000000 --- a/docs/es/channels/msteams.md +++ /dev/null @@ -1,768 +0,0 @@ ---- -summary: "Microsoft Teams bot support status, capabilities, and configuration" -read_when: - - Working on MS Teams channel features -title: "Microsoft Teams" ---- - -# Microsoft Teams (plugin) - -> "Abandon all hope, ye who enter here." - -Updated: 2026-01-21 - -Status: text + DM attachments are supported; channel/group file sending requires `sharePointSiteId` + Graph permissions (see [Sending files in group chats](#sending-files-in-group-chats)). Polls are sent via Adaptive Cards. - -## Plugin required - -Microsoft Teams ships as a plugin and is not bundled with the core install. - -**Breaking change (2026.1.15):** MS Teams moved out of core. If you use it, you must install the plugin. - -Explainable: keeps core installs lighter and lets MS Teams dependencies update independently. - -Install via CLI (npm registry): - -```bash -openclaw plugins install @openclaw/msteams -``` - -Local checkout (when running from a git repo): - -```bash -openclaw plugins install ./extensions/msteams -``` - -If you choose Teams during configure/onboarding and a git checkout is detected, -OpenClaw will offer the local install path automatically. - -Details: [Plugins](/plugin) - -## Quick setup (beginner) - -1. Install the Microsoft Teams plugin. -2. Create an **Azure Bot** (App ID + client secret + tenant ID). -3. Configure OpenClaw with those credentials. -4. Expose `/api/messages` (port 3978 by default) via a public URL or tunnel. -5. Install the Teams app package and start the gateway. - -Minimal config: - -```json5 -{ - channels: { - msteams: { - enabled: true, - appId: "", - appPassword: "", - tenantId: "", - webhook: { port: 3978, path: "/api/messages" }, - }, - }, -} -``` - -Note: group chats are blocked by default (`channels.msteams.groupPolicy: "allowlist"`). To allow group replies, set `channels.msteams.groupAllowFrom` (or use `groupPolicy: "open"` to allow any member, mention-gated). - -## Goals - -- Talk to OpenClaw via Teams DMs, group chats, or channels. -- Keep routing deterministic: replies always go back to the channel they arrived on. -- Default to safe channel behavior (mentions required unless configured otherwise). - -## Config writes - -By default, Microsoft Teams is allowed to write config updates triggered by `/config set|unset` (requires `commands.config: true`). - -Disable with: - -```json5 -{ - channels: { msteams: { configWrites: false } }, -} -``` - -## Access control (DMs + groups) - -**DM access** - -- Default: `channels.msteams.dmPolicy = "pairing"`. Unknown senders are ignored until approved. -- `channels.msteams.allowFrom` accepts AAD object IDs, UPNs, or display names. The wizard resolves names to IDs via Microsoft Graph when credentials allow. - -**Group access** - -- Default: `channels.msteams.groupPolicy = "allowlist"` (blocked unless you add `groupAllowFrom`). Use `channels.defaults.groupPolicy` to override the default when unset. -- `channels.msteams.groupAllowFrom` controls which senders can trigger in group chats/channels (falls back to `channels.msteams.allowFrom`). -- Set `groupPolicy: "open"` to allow any member (still mention‑gated by default). -- To allow **no channels**, set `channels.msteams.groupPolicy: "disabled"`. - -Example: - -```json5 -{ - channels: { - msteams: { - groupPolicy: "allowlist", - groupAllowFrom: ["user@org.com"], - }, - }, -} -``` - -**Teams + channel allowlist** - -- Scope group/channel replies by listing teams and channels under `channels.msteams.teams`. -- Keys can be team IDs or names; channel keys can be conversation IDs or names. -- When `groupPolicy="allowlist"` and a teams allowlist is present, only listed teams/channels are accepted (mention‑gated). -- The configure wizard accepts `Team/Channel` entries and stores them for you. -- On startup, OpenClaw resolves team/channel and user allowlist names to IDs (when Graph permissions allow) - and logs the mapping; unresolved entries are kept as typed. - -Example: - -```json5 -{ - channels: { - msteams: { - groupPolicy: "allowlist", - teams: { - "My Team": { - channels: { - General: { requireMention: true }, - }, - }, - }, - }, - }, -} -``` - -## How it works - -1. Install the Microsoft Teams plugin. -2. Create an **Azure Bot** (App ID + secret + tenant ID). -3. Build a **Teams app package** that references the bot and includes the RSC permissions below. -4. Upload/install the Teams app into a team (or personal scope for DMs). -5. Configure `msteams` in `~/.openclaw/openclaw.json` (or env vars) and start the gateway. -6. The gateway listens for Bot Framework webhook traffic on `/api/messages` by default. - -## Azure Bot Setup (Prerequisites) - -Before configuring OpenClaw, you need to create an Azure Bot resource. - -### Step 1: Create Azure Bot - -1. Go to [Create Azure Bot](https://portal.azure.com/#create/Microsoft.AzureBot) -2. Fill in the **Basics** tab: - - | Field | Value | - | ------------------ | -------------------------------------------------------- | - | **Bot handle** | Your bot name, e.g., `openclaw-msteams` (must be unique) | - | **Subscription** | Select your Azure subscription | - | **Resource group** | Create new or use existing | - | **Pricing tier** | **Free** for dev/testing | - | **Type of App** | **Single Tenant** (recommended - see note below) | - | **Creation type** | **Create new Microsoft App ID** | - -> **Deprecation notice:** Creation of new multi-tenant bots was deprecated after 2025-07-31. Use **Single Tenant** for new bots. - -3. Click **Review + create** → **Create** (wait ~1-2 minutes) - -### Step 2: Get Credentials - -1. Go to your Azure Bot resource → **Configuration** -2. Copy **Microsoft App ID** → this is your `appId` -3. Click **Manage Password** → go to the App Registration -4. Under **Certificates & secrets** → **New client secret** → copy the **Value** → this is your `appPassword` -5. Go to **Overview** → copy **Directory (tenant) ID** → this is your `tenantId` - -### Step 3: Configure Messaging Endpoint - -1. In Azure Bot → **Configuration** -2. Set **Messaging endpoint** to your webhook URL: - - Production: `https://your-domain.com/api/messages` - - Local dev: Use a tunnel (see [Local Development](#local-development-tunneling) below) - -### Step 4: Enable Teams Channel - -1. In Azure Bot → **Channels** -2. Click **Microsoft Teams** → Configure → Save -3. Accept the Terms of Service - -## Local Development (Tunneling) - -Teams can't reach `localhost`. Use a tunnel for local development: - -**Option A: ngrok** - -```bash -ngrok http 3978 -# Copy the https URL, e.g., https://abc123.ngrok.io -# Set messaging endpoint to: https://abc123.ngrok.io/api/messages -``` - -**Option B: Tailscale Funnel** - -```bash -tailscale funnel 3978 -# Use your Tailscale funnel URL as the messaging endpoint -``` - -## Teams Developer Portal (Alternative) - -Instead of manually creating a manifest ZIP, you can use the [Teams Developer Portal](https://dev.teams.microsoft.com/apps): - -1. Click **+ New app** -2. Fill in basic info (name, description, developer info) -3. Go to **App features** → **Bot** -4. Select **Enter a bot ID manually** and paste your Azure Bot App ID -5. Check scopes: **Personal**, **Team**, **Group Chat** -6. Click **Distribute** → **Download app package** -7. In Teams: **Apps** → **Manage your apps** → **Upload a custom app** → select the ZIP - -This is often easier than hand-editing JSON manifests. - -## Testing the Bot - -**Option A: Azure Web Chat (verify webhook first)** - -1. In Azure Portal → your Azure Bot resource → **Test in Web Chat** -2. Send a message - you should see a response -3. This confirms your webhook endpoint works before Teams setup - -**Option B: Teams (after app installation)** - -1. Install the Teams app (sideload or org catalog) -2. Find the bot in Teams and send a DM -3. Check gateway logs for incoming activity - -## Setup (minimal text-only) - -1. **Install the Microsoft Teams plugin** - - From npm: `openclaw plugins install @openclaw/msteams` - - From a local checkout: `openclaw plugins install ./extensions/msteams` - -2. **Bot registration** - - Create an Azure Bot (see above) and note: - - App ID - - Client secret (App password) - - Tenant ID (single-tenant) - -3. **Teams app manifest** - - Include a `bot` entry with `botId = `. - - Scopes: `personal`, `team`, `groupChat`. - - `supportsFiles: true` (required for personal scope file handling). - - Add RSC permissions (below). - - Create icons: `outline.png` (32x32) and `color.png` (192x192). - - Zip all three files together: `manifest.json`, `outline.png`, `color.png`. - -4. **Configure OpenClaw** - - ```json - { - "msteams": { - "enabled": true, - "appId": "", - "appPassword": "", - "tenantId": "", - "webhook": { "port": 3978, "path": "/api/messages" } - } - } - ``` - - You can also use environment variables instead of config keys: - - `MSTEAMS_APP_ID` - - `MSTEAMS_APP_PASSWORD` - - `MSTEAMS_TENANT_ID` - -5. **Bot endpoint** - - Set the Azure Bot Messaging Endpoint to: - - `https://:3978/api/messages` (or your chosen path/port). - -6. **Run the gateway** - - The Teams channel starts automatically when the plugin is installed and `msteams` config exists with credentials. - -## History context - -- `channels.msteams.historyLimit` controls how many recent channel/group messages are wrapped into the prompt. -- Falls back to `messages.groupChat.historyLimit`. Set `0` to disable (default 50). -- DM history can be limited with `channels.msteams.dmHistoryLimit` (user turns). Per-user overrides: `channels.msteams.dms[""].historyLimit`. - -## Current Teams RSC Permissions (Manifest) - -These are the **existing resourceSpecific permissions** in our Teams app manifest. They only apply inside the team/chat where the app is installed. - -**For channels (team scope):** - -- `ChannelMessage.Read.Group` (Application) - receive all channel messages without @mention -- `ChannelMessage.Send.Group` (Application) -- `Member.Read.Group` (Application) -- `Owner.Read.Group` (Application) -- `ChannelSettings.Read.Group` (Application) -- `TeamMember.Read.Group` (Application) -- `TeamSettings.Read.Group` (Application) - -**For group chats:** - -- `ChatMessage.Read.Chat` (Application) - receive all group chat messages without @mention - -## Example Teams Manifest (redacted) - -Minimal, valid example with the required fields. Replace IDs and URLs. - -```json -{ - "$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.23/MicrosoftTeams.schema.json", - "manifestVersion": "1.23", - "version": "1.0.0", - "id": "00000000-0000-0000-0000-000000000000", - "name": { "short": "OpenClaw" }, - "developer": { - "name": "Your Org", - "websiteUrl": "https://example.com", - "privacyUrl": "https://example.com/privacy", - "termsOfUseUrl": "https://example.com/terms" - }, - "description": { "short": "OpenClaw in Teams", "full": "OpenClaw in Teams" }, - "icons": { "outline": "outline.png", "color": "color.png" }, - "accentColor": "#5B6DEF", - "bots": [ - { - "botId": "11111111-1111-1111-1111-111111111111", - "scopes": ["personal", "team", "groupChat"], - "isNotificationOnly": false, - "supportsCalling": false, - "supportsVideo": false, - "supportsFiles": true - } - ], - "webApplicationInfo": { - "id": "11111111-1111-1111-1111-111111111111" - }, - "authorization": { - "permissions": { - "resourceSpecific": [ - { "name": "ChannelMessage.Read.Group", "type": "Application" }, - { "name": "ChannelMessage.Send.Group", "type": "Application" }, - { "name": "Member.Read.Group", "type": "Application" }, - { "name": "Owner.Read.Group", "type": "Application" }, - { "name": "ChannelSettings.Read.Group", "type": "Application" }, - { "name": "TeamMember.Read.Group", "type": "Application" }, - { "name": "TeamSettings.Read.Group", "type": "Application" }, - { "name": "ChatMessage.Read.Chat", "type": "Application" } - ] - } - } -} -``` - -### Manifest caveats (must-have fields) - -- `bots[].botId` **must** match the Azure Bot App ID. -- `webApplicationInfo.id` **must** match the Azure Bot App ID. -- `bots[].scopes` must include the surfaces you plan to use (`personal`, `team`, `groupChat`). -- `bots[].supportsFiles: true` is required for file handling in personal scope. -- `authorization.permissions.resourceSpecific` must include channel read/send if you want channel traffic. - -### Updating an existing app - -To update an already-installed Teams app (e.g., to add RSC permissions): - -1. Update your `manifest.json` with the new settings -2. **Increment the `version` field** (e.g., `1.0.0` → `1.1.0`) -3. **Re-zip** the manifest with icons (`manifest.json`, `outline.png`, `color.png`) -4. Upload the new zip: - - **Option A (Teams Admin Center):** Teams Admin Center → Teams apps → Manage apps → find your app → Upload new version - - **Option B (Sideload):** In Teams → Apps → Manage your apps → Upload a custom app -5. **For team channels:** Reinstall the app in each team for new permissions to take effect -6. **Fully quit and relaunch Teams** (not just close the window) to clear cached app metadata - -## Capabilities: RSC only vs Graph - -### With **Teams RSC only** (app installed, no Graph API permissions) - -Works: - -- Read channel message **text** content. -- Send channel message **text** content. -- Receive **personal (DM)** file attachments. - -Does NOT work: - -- Channel/group **image or file contents** (payload only includes HTML stub). -- Downloading attachments stored in SharePoint/OneDrive. -- Reading message history (beyond the live webhook event). - -### With **Teams RSC + Microsoft Graph Application permissions** - -Adds: - -- Downloading hosted contents (images pasted into messages). -- Downloading file attachments stored in SharePoint/OneDrive. -- Reading channel/chat message history via Graph. - -### RSC vs Graph API - -| Capability | RSC Permissions | Graph API | -| ----------------------- | -------------------- | ----------------------------------- | -| **Real-time messages** | Yes (via webhook) | No (polling only) | -| **Historical messages** | No | Yes (can query history) | -| **Setup complexity** | App manifest only | Requires admin consent + token flow | -| **Works offline** | No (must be running) | Yes (query anytime) | - -**Bottom line:** RSC is for real-time listening; Graph API is for historical access. For catching up on missed messages while offline, you need Graph API with `ChannelMessage.Read.All` (requires admin consent). - -## Graph-enabled media + history (required for channels) - -If you need images/files in **channels** or want to fetch **message history**, you must enable Microsoft Graph permissions and grant admin consent. - -1. In Entra ID (Azure AD) **App Registration**, add Microsoft Graph **Application permissions**: - - `ChannelMessage.Read.All` (channel attachments + history) - - `Chat.Read.All` or `ChatMessage.Read.All` (group chats) -2. **Grant admin consent** for the tenant. -3. Bump the Teams app **manifest version**, re-upload, and **reinstall the app in Teams**. -4. **Fully quit and relaunch Teams** to clear cached app metadata. - -## Known Limitations - -### Webhook timeouts - -Teams delivers messages via HTTP webhook. If processing takes too long (e.g., slow LLM responses), you may see: - -- Gateway timeouts -- Teams retrying the message (causing duplicates) -- Dropped replies - -OpenClaw handles this by returning quickly and sending replies proactively, but very slow responses may still cause issues. - -### Formatting - -Teams markdown is more limited than Slack or Discord: - -- Basic formatting works: **bold**, _italic_, `code`, links -- Complex markdown (tables, nested lists) may not render correctly -- Adaptive Cards are supported for polls and arbitrary card sends (see below) - -## Configuration - -Key settings (see `/gateway/configuration` for shared channel patterns): - -- `channels.msteams.enabled`: enable/disable the channel. -- `channels.msteams.appId`, `channels.msteams.appPassword`, `channels.msteams.tenantId`: bot credentials. -- `channels.msteams.webhook.port` (default `3978`) -- `channels.msteams.webhook.path` (default `/api/messages`) -- `channels.msteams.dmPolicy`: `pairing | allowlist | open | disabled` (default: pairing) -- `channels.msteams.allowFrom`: allowlist for DMs (AAD object IDs, UPNs, or display names). The wizard resolves names to IDs during setup when Graph access is available. -- `channels.msteams.textChunkLimit`: outbound text chunk size. -- `channels.msteams.chunkMode`: `length` (default) or `newline` to split on blank lines (paragraph boundaries) before length chunking. -- `channels.msteams.mediaAllowHosts`: allowlist for inbound attachment hosts (defaults to Microsoft/Teams domains). -- `channels.msteams.mediaAuthAllowHosts`: allowlist for attaching Authorization headers on media retries (defaults to Graph + Bot Framework hosts). -- `channels.msteams.requireMention`: require @mention in channels/groups (default true). -- `channels.msteams.replyStyle`: `thread | top-level` (see [Reply Style](#reply-style-threads-vs-posts)). -- `channels.msteams.teams..replyStyle`: per-team override. -- `channels.msteams.teams..requireMention`: per-team override. -- `channels.msteams.teams..tools`: default per-team tool policy overrides (`allow`/`deny`/`alsoAllow`) used when a channel override is missing. -- `channels.msteams.teams..toolsBySender`: default per-team per-sender tool policy overrides (`"*"` wildcard supported). -- `channels.msteams.teams..channels..replyStyle`: per-channel override. -- `channels.msteams.teams..channels..requireMention`: per-channel override. -- `channels.msteams.teams..channels..tools`: per-channel tool policy overrides (`allow`/`deny`/`alsoAllow`). -- `channels.msteams.teams..channels..toolsBySender`: per-channel per-sender tool policy overrides (`"*"` wildcard supported). -- `channels.msteams.sharePointSiteId`: SharePoint site ID for file uploads in group chats/channels (see [Sending files in group chats](#sending-files-in-group-chats)). - -## Routing & Sessions - -- Session keys follow the standard agent format (see [/concepts/session](/concepts/session)): - - Direct messages share the main session (`agent::`). - - Channel/group messages use conversation id: - - `agent::msteams:channel:` - - `agent::msteams:group:` - -## Reply Style: Threads vs Posts - -Teams recently introduced two channel UI styles over the same underlying data model: - -| Style | Description | Recommended `replyStyle` | -| ------------------------ | --------------------------------------------------------- | ------------------------ | -| **Posts** (classic) | Messages appear as cards with threaded replies underneath | `thread` (default) | -| **Threads** (Slack-like) | Messages flow linearly, more like Slack | `top-level` | - -**The problem:** The Teams API does not expose which UI style a channel uses. If you use the wrong `replyStyle`: - -- `thread` in a Threads-style channel → replies appear nested awkwardly -- `top-level` in a Posts-style channel → replies appear as separate top-level posts instead of in-thread - -**Solution:** Configure `replyStyle` per-channel based on how the channel is set up: - -```json -{ - "msteams": { - "replyStyle": "thread", - "teams": { - "19:abc...@thread.tacv2": { - "channels": { - "19:xyz...@thread.tacv2": { - "replyStyle": "top-level" - } - } - } - } - } -} -``` - -## Attachments & Images - -**Current limitations:** - -- **DMs:** Images and file attachments work via Teams bot file APIs. -- **Channels/groups:** Attachments live in M365 storage (SharePoint/OneDrive). The webhook payload only includes an HTML stub, not the actual file bytes. **Graph API permissions are required** to download channel attachments. - -Without Graph permissions, channel messages with images will be received as text-only (the image content is not accessible to the bot). -By default, OpenClaw only downloads media from Microsoft/Teams hostnames. Override with `channels.msteams.mediaAllowHosts` (use `["*"]` to allow any host). -Authorization headers are only attached for hosts in `channels.msteams.mediaAuthAllowHosts` (defaults to Graph + Bot Framework hosts). Keep this list strict (avoid multi-tenant suffixes). - -## Sending files in group chats - -Bots can send files in DMs using the FileConsentCard flow (built-in). However, **sending files in group chats/channels** requires additional setup: - -| Context | How files are sent | Setup needed | -| ------------------------ | -------------------------------------------- | ----------------------------------------------- | -| **DMs** | FileConsentCard → user accepts → bot uploads | Works out of the box | -| **Group chats/channels** | Upload to SharePoint → share link | Requires `sharePointSiteId` + Graph permissions | -| **Images (any context)** | Base64-encoded inline | Works out of the box | - -### Why group chats need SharePoint - -Bots don't have a personal OneDrive drive (the `/me/drive` Graph API endpoint doesn't work for application identities). To send files in group chats/channels, the bot uploads to a **SharePoint site** and creates a sharing link. - -### Setup - -1. **Add Graph API permissions** in Entra ID (Azure AD) → App Registration: - - `Sites.ReadWrite.All` (Application) - upload files to SharePoint - - `Chat.Read.All` (Application) - optional, enables per-user sharing links - -2. **Grant admin consent** for the tenant. - -3. **Get your SharePoint site 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. **Configure OpenClaw:** - ```json5 - { - channels: { - msteams: { - // ... other config ... - sharePointSiteId: "contoso.sharepoint.com,guid1,guid2", - }, - }, - } - ``` - -### Sharing behavior - -| Permission | Sharing behavior | -| --------------------------------------- | --------------------------------------------------------- | -| `Sites.ReadWrite.All` only | Organization-wide sharing link (anyone in org can access) | -| `Sites.ReadWrite.All` + `Chat.Read.All` | Per-user sharing link (only chat members can access) | - -Per-user sharing is more secure as only the chat participants can access the file. If `Chat.Read.All` permission is missing, the bot falls back to organization-wide sharing. - -### Fallback behavior - -| Scenario | Result | -| ------------------------------------------------- | -------------------------------------------------- | -| Group chat + file + `sharePointSiteId` configured | Upload to SharePoint, send sharing link | -| Group chat + file + no `sharePointSiteId` | Attempt OneDrive upload (may fail), send text only | -| Personal chat + file | FileConsentCard flow (works without SharePoint) | -| Any context + image | Base64-encoded inline (works without SharePoint) | - -### Files stored location - -Uploaded files are stored in a `/OpenClawShared/` folder in the configured SharePoint site's default document library. - -## Polls (Adaptive Cards) - -OpenClaw sends Teams polls as Adaptive Cards (there is no native Teams poll API). - -- CLI: `openclaw message poll --channel msteams --target conversation: ...` -- Votes are recorded by the gateway in `~/.openclaw/msteams-polls.json`. -- The gateway must stay online to record votes. -- Polls do not auto-post result summaries yet (inspect the store file if needed). - -## Adaptive Cards (arbitrary) - -Send any Adaptive Card JSON to Teams users or conversations using the `message` tool or CLI. - -The `card` parameter accepts an Adaptive Card JSON object. When `card` is provided, the message text is optional. - -**Agent tool:** - -```json -{ - "action": "send", - "channel": "msteams", - "target": "user:", - "card": { - "type": "AdaptiveCard", - "version": "1.5", - "body": [{ "type": "TextBlock", "text": "Hello!" }] - } -} -``` - -**CLI:** - -```bash -openclaw message send --channel msteams \ - --target "conversation:19:abc...@thread.tacv2" \ - --card '{"type":"AdaptiveCard","version":"1.5","body":[{"type":"TextBlock","text":"Hello!"}]}' -``` - -See [Adaptive Cards documentation](https://adaptivecards.io/) for card schema and examples. For target format details, see [Target formats](#target-formats) below. - -## Target formats - -MSTeams targets use prefixes to distinguish between users and conversations: - -| Target type | Format | Example | -| ------------------- | -------------------------------- | --------------------------------------------------- | -| User (by ID) | `user:` | `user:40a1a0ed-4ff2-4164-a219-55518990c197` | -| User (by name) | `user:` | `user:John Smith` (requires Graph API) | -| Group/channel | `conversation:` | `conversation:19:abc123...@thread.tacv2` | -| Group/channel (raw) | `` | `19:abc123...@thread.tacv2` (if contains `@thread`) | - -**CLI examples:** - -```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 an Adaptive Card to a conversation -openclaw message send --channel msteams --target "conversation:19:abc...@thread.tacv2" \ - --card '{"type":"AdaptiveCard","version":"1.5","body":[{"type":"TextBlock","text":"Hello"}]}' -``` - -**Agent tool examples:** - -```json -{ - "action": "send", - "channel": "msteams", - "target": "user:John Smith", - "message": "Hello!" -} -``` - -```json -{ - "action": "send", - "channel": "msteams", - "target": "conversation:19:abc...@thread.tacv2", - "card": { - "type": "AdaptiveCard", - "version": "1.5", - "body": [{ "type": "TextBlock", "text": "Hello" }] - } -} -``` - -Note: Without the `user:` prefix, names default to group/team resolution. Always use `user:` when targeting people by display name. - -## Proactive messaging - -- Proactive messages are only possible **after** a user has interacted, because we store conversation references at that point. -- See `/gateway/configuration` for `dmPolicy` and allowlist gating. - -## Team and Channel IDs (Common Gotcha) - -The `groupId` query parameter in Teams URLs is **NOT** the team ID used for configuration. Extract IDs from the URL path instead: - -**Team URL:** - -``` -https://teams.microsoft.com/l/team/19%3ABk4j...%40thread.tacv2/conversations?groupId=... - └────────────────────────────┘ - Team ID (URL-decode this) -``` - -**Channel URL:** - -``` -https://teams.microsoft.com/l/channel/19%3A15bc...%40thread.tacv2/ChannelName?groupId=... - └─────────────────────────┘ - Channel ID (URL-decode this) -``` - -**For config:** - -- Team ID = path segment after `/team/` (URL-decoded, e.g., `19:Bk4j...@thread.tacv2`) -- Channel ID = path segment after `/channel/` (URL-decoded) -- **Ignore** the `groupId` query parameter - -## Private Channels - -Bots have limited support in private channels: - -| Feature | Standard Channels | Private Channels | -| ---------------------------- | ----------------- | ---------------------- | -| Bot installation | Yes | Limited | -| Real-time messages (webhook) | Yes | May not work | -| RSC permissions | Yes | May behave differently | -| @mentions | Yes | If bot is accessible | -| Graph API history | Yes | Yes (with permissions) | - -**Workarounds if private channels don't work:** - -1. Use standard channels for bot interactions -2. Use DMs - users can always message the bot directly -3. Use Graph API for historical access (requires `ChannelMessage.Read.All`) - -## Troubleshooting - -### Common issues - -- **Images not showing in channels:** Graph permissions or admin consent missing. Reinstall the Teams app and fully quit/reopen Teams. -- **No responses in channel:** mentions are required by default; set `channels.msteams.requireMention=false` or configure per team/channel. -- **Version mismatch (Teams still shows old manifest):** remove + re-add the app and fully quit Teams to refresh. -- **401 Unauthorized from webhook:** Expected when testing manually without Azure JWT - means endpoint is reachable but auth failed. Use Azure Web Chat to test properly. - -### Manifest upload errors - -- **"Icon file cannot be empty":** The manifest references icon files that are 0 bytes. Create valid PNG icons (32x32 for `outline.png`, 192x192 for `color.png`). -- **"webApplicationInfo.Id already in use":** The app is still installed in another team/chat. Find and uninstall it first, or wait 5-10 minutes for propagation. -- **"Something went wrong" on upload:** Upload via https://admin.teams.microsoft.com instead, open browser DevTools (F12) → Network tab, and check the response body for the actual error. -- **Sideload failing:** Try "Upload an app to your org's app catalog" instead of "Upload a custom app" - this often bypasses sideload restrictions. - -### RSC permissions not working - -1. Verify `webApplicationInfo.id` matches your bot's App ID exactly -2. Re-upload the app and reinstall in the team/chat -3. Check if your org admin has blocked RSC permissions -4. Confirm you're using the right scope: `ChannelMessage.Read.Group` for teams, `ChatMessage.Read.Chat` for group chats - -## References - -- [Create Azure Bot](https://learn.microsoft.com/en-us/azure/bot-service/bot-service-quickstart-registration) - Azure Bot setup guide -- [Teams Developer Portal](https://dev.teams.microsoft.com/apps) - create/manage Teams apps -- [Teams app manifest schema](https://learn.microsoft.com/en-us/microsoftteams/platform/resources/schema/manifest-schema) -- [Receive channel messages with RSC](https://learn.microsoft.com/en-us/microsoftteams/platform/bots/how-to/conversations/channel-messages-with-rsc) -- [RSC permissions reference](https://learn.microsoft.com/en-us/microsoftteams/platform/graph-api/rsc/resource-specific-consent) -- [Teams bot file handling](https://learn.microsoft.com/en-us/microsoftteams/platform/bots/how-to/bots-filesv4) (channel/group requires Graph) -- [Proactive messaging](https://learn.microsoft.com/en-us/microsoftteams/platform/bots/how-to/conversations/send-proactive-messages) diff --git a/docs/es/channels/nextcloud-talk.md b/docs/es/channels/nextcloud-talk.md deleted file mode 100644 index edca54bc44..0000000000 --- a/docs/es/channels/nextcloud-talk.md +++ /dev/null @@ -1,136 +0,0 @@ ---- -summary: "Nextcloud Talk support status, capabilities, and configuration" -read_when: - - Working on Nextcloud Talk channel features -title: "Nextcloud Talk" ---- - -# Nextcloud Talk (plugin) - -Status: supported via plugin (webhook bot). Direct messages, rooms, reactions, and markdown messages are supported. - -## Plugin required - -Nextcloud Talk ships as a plugin and is not bundled with the core install. - -Install via CLI (npm registry): - -```bash -openclaw plugins install @openclaw/nextcloud-talk -``` - -Local checkout (when running from a git repo): - -```bash -openclaw plugins install ./extensions/nextcloud-talk -``` - -If you choose Nextcloud Talk during configure/onboarding and a git checkout is detected, -OpenClaw will offer the local install path automatically. - -Details: [Plugins](/plugin) - -## Quick setup (beginner) - -1. Install the Nextcloud Talk plugin. -2. On your Nextcloud server, create a bot: - ```bash - ./occ talk:bot:install "OpenClaw" "" "" --feature reaction - ``` -3. Enable the bot in the target room settings. -4. Configure OpenClaw: - - Config: `channels.nextcloud-talk.baseUrl` + `channels.nextcloud-talk.botSecret` - - Or env: `NEXTCLOUD_TALK_BOT_SECRET` (default account only) -5. Restart the gateway (or finish onboarding). - -Minimal config: - -```json5 -{ - channels: { - "nextcloud-talk": { - enabled: true, - baseUrl: "https://cloud.example.com", - botSecret: "shared-secret", - dmPolicy: "pairing", - }, - }, -} -``` - -## Notes - -- Bots cannot initiate DMs. The user must message the bot first. -- Webhook URL must be reachable by the Gateway; set `webhookPublicUrl` if behind a proxy. -- Media uploads are not supported by the bot API; media is sent as URLs. -- The webhook payload does not distinguish DMs vs rooms; set `apiUser` + `apiPassword` to enable room-type lookups (otherwise DMs are treated as rooms). - -## Access control (DMs) - -- Default: `channels.nextcloud-talk.dmPolicy = "pairing"`. Unknown senders get a pairing code. -- Approve via: - - `openclaw pairing list nextcloud-talk` - - `openclaw pairing approve nextcloud-talk ` -- Public DMs: `channels.nextcloud-talk.dmPolicy="open"` plus `channels.nextcloud-talk.allowFrom=["*"]`. -- `allowFrom` matches Nextcloud user IDs only; display names are ignored. - -## Rooms (groups) - -- Default: `channels.nextcloud-talk.groupPolicy = "allowlist"` (mention-gated). -- Allowlist rooms with `channels.nextcloud-talk.rooms`: - -```json5 -{ - channels: { - "nextcloud-talk": { - rooms: { - "room-token": { requireMention: true }, - }, - }, - }, -} -``` - -- To allow no rooms, keep the allowlist empty or set `channels.nextcloud-talk.groupPolicy="disabled"`. - -## Capabilities - -| Feature | Status | -| --------------- | ------------- | -| Direct messages | Supported | -| Rooms | Supported | -| Threads | Not supported | -| Media | URL-only | -| Reactions | Supported | -| Native commands | Not supported | - -## Configuration reference (Nextcloud Talk) - -Full configuration: [Configuration](/gateway/configuration) - -Provider options: - -- `channels.nextcloud-talk.enabled`: enable/disable channel startup. -- `channels.nextcloud-talk.baseUrl`: Nextcloud instance URL. -- `channels.nextcloud-talk.botSecret`: bot shared secret. -- `channels.nextcloud-talk.botSecretFile`: secret file path. -- `channels.nextcloud-talk.apiUser`: API user for room lookups (DM detection). -- `channels.nextcloud-talk.apiPassword`: API/app password for room lookups. -- `channels.nextcloud-talk.apiPasswordFile`: API password file path. -- `channels.nextcloud-talk.webhookPort`: webhook listener port (default: 8788). -- `channels.nextcloud-talk.webhookHost`: webhook host (default: 0.0.0.0). -- `channels.nextcloud-talk.webhookPath`: webhook path (default: /nextcloud-talk-webhook). -- `channels.nextcloud-talk.webhookPublicUrl`: externally reachable webhook URL. -- `channels.nextcloud-talk.dmPolicy`: `pairing | allowlist | open | disabled`. -- `channels.nextcloud-talk.allowFrom`: DM allowlist (user IDs). `open` requires `"*"`. -- `channels.nextcloud-talk.groupPolicy`: `allowlist | open | disabled`. -- `channels.nextcloud-talk.groupAllowFrom`: group allowlist (user IDs). -- `channels.nextcloud-talk.rooms`: per-room settings and allowlist. -- `channels.nextcloud-talk.historyLimit`: group history limit (0 disables). -- `channels.nextcloud-talk.dmHistoryLimit`: DM history limit (0 disables). -- `channels.nextcloud-talk.dms`: per-DM overrides (historyLimit). -- `channels.nextcloud-talk.textChunkLimit`: outbound text chunk size (chars). -- `channels.nextcloud-talk.chunkMode`: `length` (default) or `newline` to split on blank lines (paragraph boundaries) before length chunking. -- `channels.nextcloud-talk.blockStreaming`: disable block streaming for this channel. -- `channels.nextcloud-talk.blockStreamingCoalesce`: block streaming coalesce tuning. -- `channels.nextcloud-talk.mediaMaxMb`: inbound media cap (MB). diff --git a/docs/es/channels/nostr.md b/docs/es/channels/nostr.md deleted file mode 100644 index 3368933d6c..0000000000 --- a/docs/es/channels/nostr.md +++ /dev/null @@ -1,233 +0,0 @@ ---- -summary: "Nostr DM channel via NIP-04 encrypted messages" -read_when: - - You want OpenClaw to receive DMs via Nostr - - You're setting up decentralized messaging -title: "Nostr" ---- - -# Nostr - -**Status:** Optional plugin (disabled by default). - -Nostr is a decentralized protocol for social networking. This channel enables OpenClaw to receive and respond to encrypted direct messages (DMs) via NIP-04. - -## Install (on demand) - -### Onboarding (recommended) - -- The onboarding wizard (`openclaw onboard`) and `openclaw channels add` list optional channel plugins. -- Selecting Nostr prompts you to install the plugin on demand. - -Install defaults: - -- **Dev channel + git checkout available:** uses the local plugin path. -- **Stable/Beta:** downloads from npm. - -You can always override the choice in the prompt. - -### Manual install - -```bash -openclaw plugins install @openclaw/nostr -``` - -Use a local checkout (dev workflows): - -```bash -openclaw plugins install --link /extensions/nostr -``` - -Restart the Gateway after installing or enabling plugins. - -## Quick setup - -1. Generate a Nostr keypair (if needed): - -```bash -# Using nak -nak key generate -``` - -2. Add to config: - -```json -{ - "channels": { - "nostr": { - "privateKey": "${NOSTR_PRIVATE_KEY}" - } - } -} -``` - -3. Export the key: - -```bash -export NOSTR_PRIVATE_KEY="nsec1..." -``` - -4. Restart the Gateway. - -## Configuration reference - -| Key | Type | Default | Description | -| ------------ | -------- | ------------------------------------------- | ----------------------------------- | -| `privateKey` | string | required | Private key in `nsec` or hex format | -| `relays` | string[] | `['wss://relay.damus.io', 'wss://nos.lol']` | Relay URLs (WebSocket) | -| `dmPolicy` | string | `pairing` | DM access policy | -| `allowFrom` | string[] | `[]` | Allowed sender pubkeys | -| `enabled` | boolean | `true` | Enable/disable channel | -| `name` | string | - | Display name | -| `profile` | object | - | NIP-01 profile metadata | - -## Profile metadata - -Profile data is published as a NIP-01 `kind:0` event. You can manage it from the Control UI (Channels -> Nostr -> Profile) or set it directly in config. - -Example: - -```json -{ - "channels": { - "nostr": { - "privateKey": "${NOSTR_PRIVATE_KEY}", - "profile": { - "name": "openclaw", - "displayName": "OpenClaw", - "about": "Personal assistant DM bot", - "picture": "https://example.com/avatar.png", - "banner": "https://example.com/banner.png", - "website": "https://example.com", - "nip05": "openclaw@example.com", - "lud16": "openclaw@example.com" - } - } - } -} -``` - -Notes: - -- Profile URLs must use `https://`. -- Importing from relays merges fields and preserves local overrides. - -## Access control - -### DM policies - -- **pairing** (default): unknown senders get a pairing code. -- **allowlist**: only pubkeys in `allowFrom` can DM. -- **open**: public inbound DMs (requires `allowFrom: ["*"]`). -- **disabled**: ignore inbound DMs. - -### Allowlist example - -```json -{ - "channels": { - "nostr": { - "privateKey": "${NOSTR_PRIVATE_KEY}", - "dmPolicy": "allowlist", - "allowFrom": ["npub1abc...", "npub1xyz..."] - } - } -} -``` - -## Key formats - -Accepted formats: - -- **Private key:** `nsec...` or 64-char hex -- **Pubkeys (`allowFrom`):** `npub...` or hex - -## Relays - -Defaults: `relay.damus.io` and `nos.lol`. - -```json -{ - "channels": { - "nostr": { - "privateKey": "${NOSTR_PRIVATE_KEY}", - "relays": ["wss://relay.damus.io", "wss://relay.primal.net", "wss://nostr.wine"] - } - } -} -``` - -Tips: - -- Use 2-3 relays for redundancy. -- Avoid too many relays (latency, duplication). -- Paid relays can improve reliability. -- Local relays are fine for testing (`ws://localhost:7777`). - -## Protocol support - -| NIP | Status | Description | -| ------ | --------- | ------------------------------------- | -| NIP-01 | Supported | Basic event format + profile metadata | -| NIP-04 | Supported | Encrypted DMs (`kind:4`) | -| NIP-17 | Planned | Gift-wrapped DMs | -| NIP-44 | Planned | Versioned encryption | - -## Testing - -### Local relay - -```bash -# Start strfry -docker run -p 7777:7777 ghcr.io/hoytech/strfry -``` - -```json -{ - "channels": { - "nostr": { - "privateKey": "${NOSTR_PRIVATE_KEY}", - "relays": ["ws://localhost:7777"] - } - } -} -``` - -### Manual test - -1. Note the bot pubkey (npub) from logs. -2. Open a Nostr client (Damus, Amethyst, etc.). -3. DM the bot pubkey. -4. Verify the response. - -## Troubleshooting - -### Not receiving messages - -- Verify the private key is valid. -- Ensure relay URLs are reachable and use `wss://` (or `ws://` for local). -- Confirm `enabled` is not `false`. -- Check Gateway logs for relay connection errors. - -### Not sending responses - -- Check relay accepts writes. -- Verify outbound connectivity. -- Watch for relay rate limits. - -### Duplicate responses - -- Expected when using multiple relays. -- Messages are deduplicated by event ID; only the first delivery triggers a response. - -## Security - -- Never commit private keys. -- Use environment variables for keys. -- Consider `allowlist` for production bots. - -## Limitations (MVP) - -- Direct messages only (no group chats). -- No media attachments. -- NIP-04 only (NIP-17 gift-wrap planned). diff --git a/docs/es/channels/signal.md b/docs/es/channels/signal.md deleted file mode 100644 index fc211f1538..0000000000 --- a/docs/es/channels/signal.md +++ /dev/null @@ -1,202 +0,0 @@ ---- -summary: "Signal support via signal-cli (JSON-RPC + SSE), setup, and number model" -read_when: - - Setting up Signal support - - Debugging Signal send/receive -title: "Signal" ---- - -# Signal (signal-cli) - -Status: external CLI integration. Gateway talks to `signal-cli` over HTTP JSON-RPC + SSE. - -## Quick setup (beginner) - -1. Use a **separate Signal number** for the bot (recommended). -2. Install `signal-cli` (Java required). -3. Link the bot device and start the daemon: - - `signal-cli link -n "OpenClaw"` -4. Configure OpenClaw and start the gateway. - -Minimal config: - -```json5 -{ - channels: { - signal: { - enabled: true, - account: "+15551234567", - cliPath: "signal-cli", - dmPolicy: "pairing", - allowFrom: ["+15557654321"], - }, - }, -} -``` - -## What it is - -- Signal channel via `signal-cli` (not embedded libsignal). -- Deterministic routing: replies always go back to Signal. -- DMs share the agent's main session; groups are isolated (`agent::signal:group:`). - -## Config writes - -By default, Signal is allowed to write config updates triggered by `/config set|unset` (requires `commands.config: true`). - -Disable with: - -```json5 -{ - channels: { signal: { configWrites: false } }, -} -``` - -## The number model (important) - -- The gateway connects to a **Signal device** (the `signal-cli` account). -- If you run the bot on **your personal Signal account**, it will ignore your own messages (loop protection). -- For "I text the bot and it replies," use a **separate bot number**. - -## Setup (fast path) - -1. Install `signal-cli` (Java required). -2. Link a bot account: - - `signal-cli link -n "OpenClaw"` then scan the QR in Signal. -3. Configure Signal and start the gateway. - -Example: - -```json5 -{ - channels: { - signal: { - enabled: true, - account: "+15551234567", - cliPath: "signal-cli", - dmPolicy: "pairing", - allowFrom: ["+15557654321"], - }, - }, -} -``` - -Multi-account support: use `channels.signal.accounts` with per-account config and optional `name`. See [`gateway/configuration`](/gateway/configuration#telegramaccounts--discordaccounts--slackaccounts--signalaccounts--imessageaccounts) for the shared pattern. - -## External daemon mode (httpUrl) - -If you want to manage `signal-cli` yourself (slow JVM cold starts, container init, or shared CPUs), run the daemon separately and point OpenClaw at it: - -```json5 -{ - channels: { - signal: { - httpUrl: "http://127.0.0.1:8080", - autoStart: false, - }, - }, -} -``` - -This skips auto-spawn and the startup wait inside OpenClaw. For slow starts when auto-spawning, set `channels.signal.startupTimeoutMs`. - -## Access control (DMs + groups) - -DMs: - -- Default: `channels.signal.dmPolicy = "pairing"`. -- Unknown senders receive a pairing code; messages are ignored until approved (codes expire after 1 hour). -- Approve via: - - `openclaw pairing list signal` - - `openclaw pairing approve signal ` -- Pairing is the default token exchange for Signal DMs. Details: [Pairing](/start/pairing) -- UUID-only senders (from `sourceUuid`) are stored as `uuid:` in `channels.signal.allowFrom`. - -Groups: - -- `channels.signal.groupPolicy = open | allowlist | disabled`. -- `channels.signal.groupAllowFrom` controls who can trigger in groups when `allowlist` is set. - -## How it works (behavior) - -- `signal-cli` runs as a daemon; the gateway reads events via SSE. -- Inbound messages are normalized into the shared channel envelope. -- Replies always route back to the same number or group. - -## Media + limits - -- Outbound text is chunked to `channels.signal.textChunkLimit` (default 4000). -- Optional newline chunking: set `channels.signal.chunkMode="newline"` to split on blank lines (paragraph boundaries) before length chunking. -- Attachments supported (base64 fetched from `signal-cli`). -- Default media cap: `channels.signal.mediaMaxMb` (default 8). -- Use `channels.signal.ignoreAttachments` to skip downloading media. -- Group history context uses `channels.signal.historyLimit` (or `channels.signal.accounts.*.historyLimit`), falling back to `messages.groupChat.historyLimit`. Set `0` to disable (default 50). - -## Typing + read receipts - -- **Typing indicators**: OpenClaw sends typing signals via `signal-cli sendTyping` and refreshes them while a reply is running. -- **Read receipts**: when `channels.signal.sendReadReceipts` is true, OpenClaw forwards read receipts for allowed DMs. -- Signal-cli does not expose read receipts for groups. - -## Reactions (message tool) - -- Use `message action=react` with `channel=signal`. -- Targets: sender E.164 or UUID (use `uuid:` from pairing output; bare UUID works too). -- `messageId` is the Signal timestamp for the message you’re reacting to. -- Group reactions require `targetAuthor` or `targetAuthorUuid`. - -Examples: - -``` -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=✅ -``` - -Config: - -- `channels.signal.actions.reactions`: enable/disable reaction actions (default true). -- `channels.signal.reactionLevel`: `off | ack | minimal | extensive`. - - `off`/`ack` disables agent reactions (message tool `react` will error). - - `minimal`/`extensive` enables agent reactions and sets the guidance level. -- Per-account overrides: `channels.signal.accounts..actions.reactions`, `channels.signal.accounts..reactionLevel`. - -## Delivery targets (CLI/cron) - -- DMs: `signal:+15551234567` (or plain E.164). -- UUID DMs: `uuid:` (or bare UUID). -- Groups: `signal:group:`. -- Usernames: `username:` (if supported by your Signal account). - -## Configuration reference (Signal) - -Full configuration: [Configuration](/gateway/configuration) - -Provider options: - -- `channels.signal.enabled`: enable/disable channel startup. -- `channels.signal.account`: E.164 for the bot account. -- `channels.signal.cliPath`: path to `signal-cli`. -- `channels.signal.httpUrl`: full daemon URL (overrides host/port). -- `channels.signal.httpHost`, `channels.signal.httpPort`: daemon bind (default 127.0.0.1:8080). -- `channels.signal.autoStart`: auto-spawn daemon (default true if `httpUrl` unset). -- `channels.signal.startupTimeoutMs`: startup wait timeout in ms (cap 120000). -- `channels.signal.receiveMode`: `on-start | manual`. -- `channels.signal.ignoreAttachments`: skip attachment downloads. -- `channels.signal.ignoreStories`: ignore stories from the daemon. -- `channels.signal.sendReadReceipts`: forward read receipts. -- `channels.signal.dmPolicy`: `pairing | allowlist | open | disabled` (default: pairing). -- `channels.signal.allowFrom`: DM allowlist (E.164 or `uuid:`). `open` requires `"*"`. Signal has no usernames; use phone/UUID ids. -- `channels.signal.groupPolicy`: `open | allowlist | disabled` (default: allowlist). -- `channels.signal.groupAllowFrom`: group sender allowlist. -- `channels.signal.historyLimit`: max group messages to include as context (0 disables). -- `channels.signal.dmHistoryLimit`: DM history limit in user turns. Per-user overrides: `channels.signal.dms[""].historyLimit`. -- `channels.signal.textChunkLimit`: outbound chunk size (chars). -- `channels.signal.chunkMode`: `length` (default) or `newline` to split on blank lines (paragraph boundaries) before length chunking. -- `channels.signal.mediaMaxMb`: inbound/outbound media cap (MB). - -Related global options: - -- `agents.list[].groupChat.mentionPatterns` (Signal does not support native mentions). -- `messages.groupChat.mentionPatterns` (global fallback). -- `messages.responsePrefix`. diff --git a/docs/es/channels/slack.md b/docs/es/channels/slack.md deleted file mode 100644 index a9dbc24667..0000000000 --- a/docs/es/channels/slack.md +++ /dev/null @@ -1,548 +0,0 @@ ---- -summary: "Slack setup for socket or HTTP webhook mode" -read_when: "Setting up Slack or debugging Slack socket/HTTP mode" -title: "Slack" ---- - -# Slack - -## Socket mode (default) - -### Quick setup (beginner) - -1. Create a Slack app and enable **Socket Mode**. -2. Create an **App Token** (`xapp-...`) and **Bot Token** (`xoxb-...`). -3. Set tokens for OpenClaw and start the gateway. - -Minimal config: - -```json5 -{ - channels: { - slack: { - enabled: true, - appToken: "xapp-...", - botToken: "xoxb-...", - }, - }, -} -``` - -### Setup - -1. Create a Slack app (From scratch) in https://api.slack.com/apps. -2. **Socket Mode** → toggle on. Then go to **Basic Information** → **App-Level Tokens** → **Generate Token and Scopes** with scope `connections:write`. Copy the **App Token** (`xapp-...`). -3. **OAuth & Permissions** → add bot token scopes (use the manifest below). Click **Install to Workspace**. Copy the **Bot User OAuth Token** (`xoxb-...`). -4. Optional: **OAuth & Permissions** → add **User Token Scopes** (see the read-only list below). Reinstall the app and copy the **User OAuth Token** (`xoxp-...`). -5. **Event Subscriptions** → enable events and subscribe to: - - `message.*` (includes edits/deletes/thread broadcasts) - - `app_mention` - - `reaction_added`, `reaction_removed` - - `member_joined_channel`, `member_left_channel` - - `channel_rename` - - `pin_added`, `pin_removed` -6. Invite the bot to channels you want it to read. -7. Slash Commands → create `/openclaw` if you use `channels.slack.slashCommand`. If you enable native commands, add one slash command per built-in command (same names as `/help`). Native defaults to off for Slack unless you set `channels.slack.commands.native: true` (global `commands.native` is `"auto"` which leaves Slack off). -8. App Home → enable the **Messages Tab** so users can DM the bot. - -Use the manifest below so scopes and events stay in sync. - -Multi-account support: use `channels.slack.accounts` with per-account tokens and optional `name`. See [`gateway/configuration`](/gateway/configuration#telegramaccounts--discordaccounts--slackaccounts--signalaccounts--imessageaccounts) for the shared pattern. - -### OpenClaw config (minimal) - -Set tokens via env vars (recommended): - -- `SLACK_APP_TOKEN=xapp-...` -- `SLACK_BOT_TOKEN=xoxb-...` - -Or via config: - -```json5 -{ - channels: { - slack: { - enabled: true, - appToken: "xapp-...", - botToken: "xoxb-...", - }, - }, -} -``` - -### User token (optional) - -OpenClaw can use a Slack user token (`xoxp-...`) for read operations (history, -pins, reactions, emoji, member info). By default this stays read-only: reads -prefer the user token when present, and writes still use the bot token unless -you explicitly opt in. Even with `userTokenReadOnly: false`, the bot token stays -preferred for writes when it is available. - -User tokens are configured in the config file (no env var support). For -multi-account, set `channels.slack.accounts..userToken`. - -Example with bot + app + user tokens: - -```json5 -{ - channels: { - slack: { - enabled: true, - appToken: "xapp-...", - botToken: "xoxb-...", - userToken: "xoxp-...", - }, - }, -} -``` - -Example with userTokenReadOnly explicitly set (allow user token writes): - -```json5 -{ - channels: { - slack: { - enabled: true, - appToken: "xapp-...", - botToken: "xoxb-...", - userToken: "xoxp-...", - userTokenReadOnly: false, - }, - }, -} -``` - -#### Token usage - -- Read operations (history, reactions list, pins list, emoji list, member info, - search) prefer the user token when configured, otherwise the bot token. -- Write operations (send/edit/delete messages, add/remove reactions, pin/unpin, - file uploads) use the bot token by default. If `userTokenReadOnly: false` and - no bot token is available, OpenClaw falls back to the user token. - -### History context - -- `channels.slack.historyLimit` (or `channels.slack.accounts.*.historyLimit`) controls how many recent channel/group messages are wrapped into the prompt. -- Falls back to `messages.groupChat.historyLimit`. Set `0` to disable (default 50). - -## HTTP mode (Events API) - -Use HTTP webhook mode when your Gateway is reachable by Slack over HTTPS (typical for server deployments). -HTTP mode uses the Events API + Interactivity + Slash Commands with a shared request URL. - -### Setup - -1. Create a Slack app and **disable Socket Mode** (optional if you only use HTTP). -2. **Basic Information** → copy the **Signing Secret**. -3. **OAuth & Permissions** → install the app and copy the **Bot User OAuth Token** (`xoxb-...`). -4. **Event Subscriptions** → enable events and set the **Request URL** to your gateway webhook path (default `/slack/events`). -5. **Interactivity & Shortcuts** → enable and set the same **Request URL**. -6. **Slash Commands** → set the same **Request URL** for your command(s). - -Example request URL: -`https://gateway-host/slack/events` - -### OpenClaw config (minimal) - -```json5 -{ - channels: { - slack: { - enabled: true, - mode: "http", - botToken: "xoxb-...", - signingSecret: "your-signing-secret", - webhookPath: "/slack/events", - }, - }, -} -``` - -Multi-account HTTP mode: set `channels.slack.accounts..mode = "http"` and provide a unique -`webhookPath` per account so each Slack app can point to its own URL. - -### Manifest (optional) - -Use this Slack app manifest to create the app quickly (adjust the name/command if you want). Include the -user scopes if you plan to configure a user token. - -```json -{ - "display_information": { - "name": "OpenClaw", - "description": "Slack connector for OpenClaw" - }, - "features": { - "bot_user": { - "display_name": "OpenClaw", - "always_online": false - }, - "app_home": { - "messages_tab_enabled": true, - "messages_tab_read_only_enabled": false - }, - "slash_commands": [ - { - "command": "/openclaw", - "description": "Send a message to OpenClaw", - "should_escape": false - } - ] - }, - "oauth_config": { - "scopes": { - "bot": [ - "chat:write", - "channels:history", - "channels:read", - "groups:history", - "groups:read", - "groups:write", - "im:history", - "im:read", - "im:write", - "mpim:history", - "mpim:read", - "mpim:write", - "users:read", - "app_mentions:read", - "reactions:read", - "reactions:write", - "pins:read", - "pins:write", - "emoji:read", - "commands", - "files:read", - "files:write" - ], - "user": [ - "channels:history", - "channels:read", - "groups:history", - "groups:read", - "im:history", - "im:read", - "mpim:history", - "mpim:read", - "users:read", - "reactions:read", - "pins:read", - "emoji:read", - "search:read" - ] - } - }, - "settings": { - "socket_mode_enabled": true, - "event_subscriptions": { - "bot_events": [ - "app_mention", - "message.channels", - "message.groups", - "message.im", - "message.mpim", - "reaction_added", - "reaction_removed", - "member_joined_channel", - "member_left_channel", - "channel_rename", - "pin_added", - "pin_removed" - ] - } - } -} -``` - -If you enable native commands, add one `slash_commands` entry per command you want to expose (matching the `/help` list). Override with `channels.slack.commands.native`. - -## Scopes (current vs optional) - -Slack's Conversations API is type-scoped: you only need the scopes for the -conversation types you actually touch (channels, groups, im, mpim). See -https://docs.slack.dev/apis/web-api/using-the-conversations-api/ for the overview. - -### Bot token scopes (required) - -- `chat:write` (send/update/delete messages via `chat.postMessage`) - https://docs.slack.dev/reference/methods/chat.postMessage -- `im:write` (open DMs via `conversations.open` for user DMs) - https://docs.slack.dev/reference/methods/conversations.open -- `channels:history`, `groups:history`, `im:history`, `mpim:history` - https://docs.slack.dev/reference/methods/conversations.history -- `channels:read`, `groups:read`, `im:read`, `mpim:read` - https://docs.slack.dev/reference/methods/conversations.info -- `users:read` (user lookup) - https://docs.slack.dev/reference/methods/users.info -- `reactions:read`, `reactions:write` (`reactions.get` / `reactions.add`) - https://docs.slack.dev/reference/methods/reactions.get - https://docs.slack.dev/reference/methods/reactions.add -- `pins:read`, `pins:write` (`pins.list` / `pins.add` / `pins.remove`) - https://docs.slack.dev/reference/scopes/pins.read - https://docs.slack.dev/reference/scopes/pins.write -- `emoji:read` (`emoji.list`) - https://docs.slack.dev/reference/scopes/emoji.read -- `files:write` (uploads via `files.uploadV2`) - https://docs.slack.dev/messaging/working-with-files/#upload - -### User token scopes (optional, read-only by default) - -Add these under **User Token Scopes** if you configure `channels.slack.userToken`. - -- `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` - -### Not needed today (but likely future) - -- `mpim:write` (only if we add group-DM open/DM start via `conversations.open`) -- `groups:write` (only if we add private-channel management: create/rename/invite/archive) -- `chat:write.public` (only if we want to post to channels the bot isn't in) - https://docs.slack.dev/reference/scopes/chat.write.public -- `users:read.email` (only if we need email fields from `users.info`) - https://docs.slack.dev/changelog/2017-04-narrowing-email-access -- `files:read` (only if we start listing/reading file metadata) - -## Config - -Slack uses Socket Mode only (no HTTP webhook server). Provide both tokens: - -```json -{ - "slack": { - "enabled": true, - "botToken": "xoxb-...", - "appToken": "xapp-...", - "groupPolicy": "allowlist", - "dm": { - "enabled": true, - "policy": "pairing", - "allowFrom": ["U123", "U456", "*"], - "groupEnabled": false, - "groupChannels": ["G123"], - "replyToMode": "all" - }, - "channels": { - "C123": { "allow": true, "requireMention": true }, - "#general": { - "allow": true, - "requireMention": true, - "users": ["U123"], - "skills": ["search", "docs"], - "systemPrompt": "Keep answers short." - } - }, - "reactionNotifications": "own", - "reactionAllowlist": ["U123"], - "replyToMode": "off", - "actions": { - "reactions": true, - "messages": true, - "pins": true, - "memberInfo": true, - "emojiList": true - }, - "slashCommand": { - "enabled": true, - "name": "openclaw", - "sessionPrefix": "slack:slash", - "ephemeral": true - }, - "textChunkLimit": 4000, - "mediaMaxMb": 20 - } -} -``` - -Tokens can also be supplied via env vars: - -- `SLACK_BOT_TOKEN` -- `SLACK_APP_TOKEN` - -Ack reactions are controlled globally via `messages.ackReaction` + -`messages.ackReactionScope`. Use `messages.removeAckAfterReply` to clear the -ack reaction after the bot replies. - -## Limits - -- Outbound text is chunked to `channels.slack.textChunkLimit` (default 4000). -- Optional newline chunking: set `channels.slack.chunkMode="newline"` to split on blank lines (paragraph boundaries) before length chunking. -- Media uploads are capped by `channels.slack.mediaMaxMb` (default 20). - -## Reply threading - -By default, OpenClaw replies in the main channel. Use `channels.slack.replyToMode` to control automatic threading: - -| Mode | Behavior | -| ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `off` | **Default.** Reply in main channel. Only thread if the triggering message was already in a thread. | -| `first` | First reply goes to thread (under the triggering message), subsequent replies go to main channel. Useful for keeping context visible while avoiding thread clutter. | -| `all` | All replies go to thread. Keeps conversations contained but may reduce visibility. | - -The mode applies to both auto-replies and agent tool calls (`slack sendMessage`). - -### Per-chat-type threading - -You can configure different threading behavior per chat type by setting `channels.slack.replyToModeByChatType`: - -```json5 -{ - channels: { - slack: { - replyToMode: "off", // default for channels - replyToModeByChatType: { - direct: "all", // DMs always thread - group: "first", // group DMs/MPIM thread first reply - }, - }, - }, -} -``` - -Supported chat types: - -- `direct`: 1:1 DMs (Slack `im`) -- `group`: group DMs / MPIMs (Slack `mpim`) -- `channel`: standard channels (public/private) - -Precedence: - -1. `replyToModeByChatType.` -2. `replyToMode` -3. Provider default (`off`) - -Legacy `channels.slack.dm.replyToMode` is still accepted as a fallback for `direct` when no chat-type override is set. - -Examples: - -Thread DMs only: - -```json5 -{ - channels: { - slack: { - replyToMode: "off", - replyToModeByChatType: { direct: "all" }, - }, - }, -} -``` - -Thread group DMs but keep channels in the root: - -```json5 -{ - channels: { - slack: { - replyToMode: "off", - replyToModeByChatType: { group: "first" }, - }, - }, -} -``` - -Make channels thread, keep DMs in the root: - -```json5 -{ - channels: { - slack: { - replyToMode: "first", - replyToModeByChatType: { direct: "off", group: "off" }, - }, - }, -} -``` - -### Manual threading tags - -For fine-grained control, use these tags in agent responses: - -- `[[reply_to_current]]` — reply to the triggering message (start/continue thread). -- `[[reply_to:]]` — reply to a specific message id. - -## Sessions + routing - -- DMs share the `main` session (like WhatsApp/Telegram). -- Channels map to `agent::slack:channel:` sessions. -- Slash commands use `agent::slack:slash:` sessions (prefix configurable via `channels.slack.slashCommand.sessionPrefix`). -- If Slack doesn’t provide `channel_type`, OpenClaw infers it from the channel ID prefix (`D`, `C`, `G`) and defaults to `channel` to keep session keys stable. -- Native command registration uses `commands.native` (global default `"auto"` → Slack off) and can be overridden per-workspace with `channels.slack.commands.native`. Text commands require standalone `/...` messages and can be disabled with `commands.text: false`. Slack slash commands are managed in the Slack app and are not removed automatically. Use `commands.useAccessGroups: false` to bypass access-group checks for commands. -- Full command list + config: [Slash commands](/tools/slash-commands) - -## DM security (pairing) - -- Default: `channels.slack.dm.policy="pairing"` — unknown DM senders get a pairing code (expires after 1 hour). -- Approve via: `openclaw pairing approve slack `. -- To allow anyone: set `channels.slack.dm.policy="open"` and `channels.slack.dm.allowFrom=["*"]`. -- `channels.slack.dm.allowFrom` accepts user IDs, @handles, or emails (resolved at startup when tokens allow). The wizard accepts usernames and resolves them to ids during setup when tokens allow. - -## Group policy - -- `channels.slack.groupPolicy` controls channel handling (`open|disabled|allowlist`). -- `allowlist` requires channels to be listed in `channels.slack.channels`. -- If you only set `SLACK_BOT_TOKEN`/`SLACK_APP_TOKEN` and never create a `channels.slack` section, - the runtime defaults `groupPolicy` to `open`. Add `channels.slack.groupPolicy`, - `channels.defaults.groupPolicy`, or a channel allowlist to lock it down. -- The configure wizard accepts `#channel` names and resolves them to IDs when possible - (public + private); if multiple matches exist, it prefers the active channel. -- On startup, OpenClaw resolves channel/user names in allowlists to IDs (when tokens allow) - and logs the mapping; unresolved entries are kept as typed. -- To allow **no channels**, set `channels.slack.groupPolicy: "disabled"` (or keep an empty allowlist). - -Channel options (`channels.slack.channels.` or `channels.slack.channels.`): - -- `allow`: allow/deny the channel when `groupPolicy="allowlist"`. -- `requireMention`: mention gating for the channel. -- `tools`: optional per-channel tool policy overrides (`allow`/`deny`/`alsoAllow`). -- `toolsBySender`: optional per-sender tool policy overrides within the channel (keys are sender ids/@handles/emails; `"*"` wildcard supported). -- `allowBots`: allow bot-authored messages in this channel (default: false). -- `users`: optional per-channel user allowlist. -- `skills`: skill filter (omit = all skills, empty = none). -- `systemPrompt`: extra system prompt for the channel (combined with topic/purpose). -- `enabled`: set `false` to disable the channel. - -## Delivery targets - -Use these with cron/CLI sends: - -- `user:` for DMs -- `channel:` for channels - -## Tool actions - -Slack tool actions can be gated with `channels.slack.actions.*`: - -| Action group | Default | Notes | -| ------------ | ------- | ---------------------- | -| reactions | enabled | React + list reactions | -| messages | enabled | Read/send/edit/delete | -| pins | enabled | Pin/unpin/list | -| memberInfo | enabled | Member info | -| emojiList | enabled | Custom emoji list | - -## Security notes - -- Writes default to the bot token so state-changing actions stay scoped to the - app's bot permissions and identity. -- Setting `userTokenReadOnly: false` allows the user token to be used for write - operations when a bot token is unavailable, which means actions run with the - installing user's access. Treat the user token as highly privileged and keep - action gates and allowlists tight. -- If you enable user-token writes, make sure the user token includes the write - scopes you expect (`chat:write`, `reactions:write`, `pins:write`, - `files:write`) or those operations will fail. - -## Notes - -- Mention gating is controlled via `channels.slack.channels` (set `requireMention` to `true`); `agents.list[].groupChat.mentionPatterns` (or `messages.groupChat.mentionPatterns`) also count as mentions. -- Multi-agent override: set per-agent patterns on `agents.list[].groupChat.mentionPatterns`. -- Reaction notifications follow `channels.slack.reactionNotifications` (use `reactionAllowlist` with mode `allowlist`). -- Bot-authored messages are ignored by default; enable via `channels.slack.allowBots` or `channels.slack.channels..allowBots`. -- Warning: If you allow replies to other bots (`channels.slack.allowBots=true` or `channels.slack.channels..allowBots=true`), prevent bot-to-bot reply loops with `requireMention`, `channels.slack.channels..users` allowlists, and/or clear guardrails in `AGENTS.md` and `SOUL.md`. -- For the Slack tool, reaction removal semantics are in [/tools/reactions](/tools/reactions). -- Attachments are downloaded to the media store when permitted and under the size limit. diff --git a/docs/es/channels/telegram.md b/docs/es/channels/telegram.md deleted file mode 100644 index 45f6d30f4b..0000000000 --- a/docs/es/channels/telegram.md +++ /dev/null @@ -1,750 +0,0 @@ ---- -summary: "Telegram bot support status, capabilities, and configuration" -read_when: - - Working on Telegram features or webhooks -title: "Telegram" ---- - -# Telegram (Bot API) - -Status: production-ready for bot DMs + groups via grammY. Long-polling by default; webhook optional. - -## Quick setup (beginner) - -1. Create a bot with **@BotFather** ([direct link](https://t.me/BotFather)). Confirm the handle is exactly `@BotFather`, then copy the token. -2. Set the token: - - Env: `TELEGRAM_BOT_TOKEN=...` - - Or config: `channels.telegram.botToken: "..."`. - - If both are set, config takes precedence (env fallback is default-account only). -3. Start the gateway. -4. DM access is pairing by default; approve the pairing code on first contact. - -Minimal config: - -```json5 -{ - channels: { - telegram: { - enabled: true, - botToken: "123:abc", - dmPolicy: "pairing", - }, - }, -} -``` - -## What it is - -- A Telegram Bot API channel owned by the Gateway. -- Deterministic routing: replies go back to Telegram; the model never chooses channels. -- DMs share the agent's main session; groups stay isolated (`agent::telegram:group:`). - -## Setup (fast path) - -### 1) Create a bot token (BotFather) - -1. Open Telegram and chat with **@BotFather** ([direct link](https://t.me/BotFather)). Confirm the handle is exactly `@BotFather`. -2. Run `/newbot`, then follow the prompts (name + username ending in `bot`). -3. Copy the token and store it safely. - -Optional BotFather settings: - -- `/setjoingroups` — allow/deny adding the bot to groups. -- `/setprivacy` — control whether the bot sees all group messages. - -### 2) Configure the token (env or config) - -Example: - -```json5 -{ - channels: { - telegram: { - enabled: true, - botToken: "123:abc", - dmPolicy: "pairing", - groups: { "*": { requireMention: true } }, - }, - }, -} -``` - -Env option: `TELEGRAM_BOT_TOKEN=...` (works for the default account). -If both env and config are set, config takes precedence. - -Multi-account support: use `channels.telegram.accounts` with per-account tokens and optional `name`. See [`gateway/configuration`](/gateway/configuration#telegramaccounts--discordaccounts--slackaccounts--signalaccounts--imessageaccounts) for the shared pattern. - -3. Start the gateway. Telegram starts when a token is resolved (config first, env fallback). -4. DM access defaults to pairing. Approve the code when the bot is first contacted. -5. For groups: add the bot, decide privacy/admin behavior (below), then set `channels.telegram.groups` to control mention gating + allowlists. - -## Token + privacy + permissions (Telegram side) - -### Token creation (BotFather) - -- `/newbot` creates the bot and returns the token (keep it secret). -- If a token leaks, revoke/regenerate it via @BotFather and update your config. - -### Group message visibility (Privacy Mode) - -Telegram bots default to **Privacy Mode**, which limits which group messages they receive. -If your bot must see _all_ group messages, you have two options: - -- Disable privacy mode with `/setprivacy` **or** -- Add the bot as a group **admin** (admin bots receive all messages). - -**Note:** When you toggle privacy mode, Telegram requires removing + re‑adding the bot -to each group for the change to take effect. - -### Group permissions (admin rights) - -Admin status is set inside the group (Telegram UI). Admin bots always receive all -group messages, so use admin if you need full visibility. - -## How it works (behavior) - -- Inbound messages are normalized into the shared channel envelope with reply context and media placeholders. -- Group replies require a mention by default (native @mention or `agents.list[].groupChat.mentionPatterns` / `messages.groupChat.mentionPatterns`). -- Multi-agent override: set per-agent patterns on `agents.list[].groupChat.mentionPatterns`. -- Replies always route back to the same Telegram chat. -- Long-polling uses grammY runner with per-chat sequencing; overall concurrency is capped by `agents.defaults.maxConcurrent`. -- Telegram Bot API does not support read receipts; there is no `sendReadReceipts` option. - -## Draft streaming - -OpenClaw can stream partial replies in Telegram DMs using `sendMessageDraft`. - -Requirements: - -- Threaded Mode enabled for the bot in @BotFather (forum topic mode). -- Private chat threads only (Telegram includes `message_thread_id` on inbound messages). -- `channels.telegram.streamMode` not set to `"off"` (default: `"partial"`, `"block"` enables chunked draft updates). - -Draft streaming is DM-only; Telegram does not support it in groups or channels. - -## Formatting (Telegram HTML) - -- Outbound Telegram text uses `parse_mode: "HTML"` (Telegram’s supported tag subset). -- Markdown-ish input is rendered into **Telegram-safe HTML** (bold/italic/strike/code/links); block elements are flattened to text with newlines/bullets. -- Raw HTML from models is escaped to avoid Telegram parse errors. -- If Telegram rejects the HTML payload, OpenClaw retries the same message as plain text. - -## Commands (native + custom) - -OpenClaw registers native commands (like `/status`, `/reset`, `/model`) with Telegram’s bot menu on startup. -You can add custom commands to the menu via config: - -```json5 -{ - channels: { - telegram: { - customCommands: [ - { command: "backup", description: "Git backup" }, - { command: "generate", description: "Create an image" }, - ], - }, - }, -} -``` - -## Troubleshooting - -- `setMyCommands failed` in logs usually means outbound HTTPS/DNS is blocked to `api.telegram.org`. -- If you see `sendMessage` or `sendChatAction` failures, check IPv6 routing and DNS. - -More help: [Channel troubleshooting](/channels/troubleshooting). - -Notes: - -- Custom commands are **menu entries only**; OpenClaw does not implement them unless you handle them elsewhere. -- Command names are normalized (leading `/` stripped, lowercased) and must match `a-z`, `0-9`, `_` (1–32 chars). -- Custom commands **cannot override native commands**. Conflicts are ignored and logged. -- If `commands.native` is disabled, only custom commands are registered (or cleared if none). - -## Limits - -- Outbound text is chunked to `channels.telegram.textChunkLimit` (default 4000). -- Optional newline chunking: set `channels.telegram.chunkMode="newline"` to split on blank lines (paragraph boundaries) before length chunking. -- Media downloads/uploads are capped by `channels.telegram.mediaMaxMb` (default 5). -- Telegram Bot API requests time out after `channels.telegram.timeoutSeconds` (default 500 via grammY). Set lower to avoid long hangs. -- Group history context uses `channels.telegram.historyLimit` (or `channels.telegram.accounts.*.historyLimit`), falling back to `messages.groupChat.historyLimit`. Set `0` to disable (default 50). -- DM history can be limited with `channels.telegram.dmHistoryLimit` (user turns). Per-user overrides: `channels.telegram.dms[""].historyLimit`. - -## Group activation modes - -By default, the bot only responds to mentions in groups (`@botname` or patterns in `agents.list[].groupChat.mentionPatterns`). To change this behavior: - -### Via config (recommended) - -```json5 -{ - channels: { - telegram: { - groups: { - "-1001234567890": { requireMention: false }, // always respond in this group - }, - }, - }, -} -``` - -**Important:** Setting `channels.telegram.groups` creates an **allowlist** - only listed groups (or `"*"`) will be accepted. -Forum topics inherit their parent group config (allowFrom, requireMention, skills, prompts) unless you add per-topic overrides under `channels.telegram.groups..topics.`. - -To allow all groups with always-respond: - -```json5 -{ - channels: { - telegram: { - groups: { - "*": { requireMention: false }, // all groups, always respond - }, - }, - }, -} -``` - -To keep mention-only for all groups (default behavior): - -```json5 -{ - channels: { - telegram: { - groups: { - "*": { requireMention: true }, // or omit groups entirely - }, - }, - }, -} -``` - -### Via command (session-level) - -Send in the group: - -- `/activation always` - respond to all messages -- `/activation mention` - require mentions (default) - -**Note:** Commands update session state only. For persistent behavior across restarts, use config. - -### Getting the group chat ID - -Forward any message from the group to `@userinfobot` or `@getidsbot` on Telegram to see the chat ID (negative number like `-1001234567890`). - -**Tip:** For your own user ID, DM the bot and it will reply with your user ID (pairing message), or use `/whoami` once commands are enabled. - -**Privacy note:** `@userinfobot` is a third-party bot. If you prefer, add the bot to the group, send a message, and use `openclaw logs --follow` to read `chat.id`, or use the Bot API `getUpdates`. - -## Config writes - -By default, Telegram is allowed to write config updates triggered by channel events or `/config set|unset`. - -This happens when: - -- A group is upgraded to a supergroup and Telegram emits `migrate_to_chat_id` (chat ID changes). OpenClaw can migrate `channels.telegram.groups` automatically. -- You run `/config set` or `/config unset` in a Telegram chat (requires `commands.config: true`). - -Disable with: - -```json5 -{ - channels: { telegram: { configWrites: false } }, -} -``` - -## Topics (forum supergroups) - -Telegram forum topics include a `message_thread_id` per message. OpenClaw: - -- Appends `:topic:` to the Telegram group session key so each topic is isolated. -- Sends typing indicators and replies with `message_thread_id` so responses stay in the topic. -- General topic (thread id `1`) is special: message sends omit `message_thread_id` (Telegram rejects it), but typing indicators still include it. -- Exposes `MessageThreadId` + `IsForum` in template context for routing/templating. -- Topic-specific configuration is available under `channels.telegram.groups..topics.` (skills, allowlists, auto-reply, system prompts, disable). -- Topic configs inherit group settings (requireMention, allowlists, skills, prompts, enabled) unless overridden per topic. - -Private chats can include `message_thread_id` in some edge cases. OpenClaw keeps the DM session key unchanged, but still uses the thread id for replies/draft streaming when it is present. - -## Inline Buttons - -Telegram supports inline keyboards with callback buttons. - -```json5 -{ - channels: { - telegram: { - capabilities: { - inlineButtons: "allowlist", - }, - }, - }, -} -``` - -For per-account configuration: - -```json5 -{ - channels: { - telegram: { - accounts: { - main: { - capabilities: { - inlineButtons: "allowlist", - }, - }, - }, - }, - }, -} -``` - -Scopes: - -- `off` — inline buttons disabled -- `dm` — only DMs (group targets blocked) -- `group` — only groups (DM targets blocked) -- `all` — DMs + groups -- `allowlist` — DMs + groups, but only senders allowed by `allowFrom`/`groupAllowFrom` (same rules as control commands) - -Default: `allowlist`. -Legacy: `capabilities: ["inlineButtons"]` = `inlineButtons: "all"`. - -### Sending buttons - -Use the message tool with the `buttons` parameter: - -```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" }], - ], -} -``` - -When a user clicks a button, the callback data is sent back to the agent as a message with the format: -`callback_data: value` - -### Configuration options - -Telegram capabilities can be configured at two levels (object form shown above; legacy string arrays still supported): - -- `channels.telegram.capabilities`: Global default capability config applied to all Telegram accounts unless overridden. -- `channels.telegram.accounts..capabilities`: Per-account capabilities that override the global defaults for that specific account. - -Use the global setting when all Telegram bots/accounts should behave the same. Use per-account configuration when different bots need different behaviors (for example, one account only handles DMs while another is allowed in groups). - -## Access control (DMs + groups) - -### DM access - -- Default: `channels.telegram.dmPolicy = "pairing"`. Unknown senders receive a pairing code; messages are ignored until approved (codes expire after 1 hour). -- Approve via: - - `openclaw pairing list telegram` - - `openclaw pairing approve telegram ` -- Pairing is the default token exchange used for Telegram DMs. Details: [Pairing](/start/pairing) -- `channels.telegram.allowFrom` accepts numeric user IDs (recommended) or `@username` entries. It is **not** the bot username; use the human sender’s ID. The wizard accepts `@username` and resolves it to the numeric ID when possible. - -#### Finding your Telegram user ID - -Safer (no third-party bot): - -1. Start the gateway and DM your bot. -2. Run `openclaw logs --follow` and look for `from.id`. - -Alternate (official Bot API): - -1. DM your bot. -2. Fetch updates with your bot token and read `message.from.id`: - ```bash - curl "https://api.telegram.org/bot/getUpdates" - ``` - -Third-party (less private): - -- DM `@userinfobot` or `@getidsbot` and use the returned user id. - -### Group access - -Two independent controls: - -**1. Which groups are allowed** (group allowlist via `channels.telegram.groups`): - -- No `groups` config = all groups allowed -- With `groups` config = only listed groups or `"*"` are allowed -- Example: `"groups": { "-1001234567890": {}, "*": {} }` allows all groups - -**2. Which senders are allowed** (sender filtering via `channels.telegram.groupPolicy`): - -- `"open"` = all senders in allowed groups can message -- `"allowlist"` = only senders in `channels.telegram.groupAllowFrom` can message -- `"disabled"` = no group messages accepted at all - Default is `groupPolicy: "allowlist"` (blocked unless you add `groupAllowFrom`). - -Most users want: `groupPolicy: "allowlist"` + `groupAllowFrom` + specific groups listed in `channels.telegram.groups` - -## Long-polling vs webhook - -- Default: long-polling (no public URL required). -- Webhook mode: set `channels.telegram.webhookUrl` and `channels.telegram.webhookSecret` (optionally `channels.telegram.webhookPath`). - - The local listener binds to `0.0.0.0:8787` and serves `POST /telegram-webhook` by default. - - If your public URL is different, use a reverse proxy and point `channels.telegram.webhookUrl` at the public endpoint. - -## Reply threading - -Telegram supports optional threaded replies via tags: - -- `[[reply_to_current]]` -- reply to the triggering message. -- `[[reply_to:]]` -- reply to a specific message id. - -Controlled by `channels.telegram.replyToMode`: - -- `first` (default), `all`, `off`. - -## Audio messages (voice vs file) - -Telegram distinguishes **voice notes** (round bubble) from **audio files** (metadata card). -OpenClaw defaults to audio files for backward compatibility. - -To force a voice note bubble in agent replies, include this tag anywhere in the reply: - -- `[[audio_as_voice]]` — send audio as a voice note instead of a file. - -The tag is stripped from the delivered text. Other channels ignore this tag. - -For message tool sends, set `asVoice: true` with a voice-compatible audio `media` URL -(`message` is optional when media is present): - -```json5 -{ - action: "send", - channel: "telegram", - to: "123456789", - media: "https://example.com/voice.ogg", - asVoice: true, -} -``` - -## Stickers - -OpenClaw supports receiving and sending Telegram stickers with intelligent caching. - -### Receiving stickers - -When a user sends a sticker, OpenClaw handles it based on the sticker type: - -- **Static stickers (WEBP):** Downloaded and processed through vision. The sticker appears as a `` placeholder in the message content. -- **Animated stickers (TGS):** Skipped (Lottie format not supported for processing). -- **Video stickers (WEBM):** Skipped (video format not supported for processing). - -Template context field available when receiving stickers: - -- `Sticker` — object with: - - `emoji` — emoji associated with the sticker - - `setName` — name of the sticker set - - `fileId` — Telegram file ID (send the same sticker back) - - `fileUniqueId` — stable ID for cache lookup - - `cachedDescription` — cached vision description when available - -### Sticker cache - -Stickers are processed through the AI's vision capabilities to generate descriptions. Since the same stickers are often sent repeatedly, OpenClaw caches these descriptions to avoid redundant API calls. - -**How it works:** - -1. **First encounter:** The sticker image is sent to the AI for vision analysis. The AI generates a description (e.g., "A cartoon cat waving enthusiastically"). -2. **Cache storage:** The description is saved along with the sticker's file ID, emoji, and set name. -3. **Subsequent encounters:** When the same sticker is seen again, the cached description is used directly. The image is not sent to the AI. - -**Cache location:** `~/.openclaw/telegram/sticker-cache.json` - -**Cache entry format:** - -```json -{ - "fileId": "CAACAgIAAxkBAAI...", - "fileUniqueId": "AgADBAADb6cxG2Y", - "emoji": "👋", - "setName": "CoolCats", - "description": "A cartoon cat waving enthusiastically", - "cachedAt": "2026-01-15T10:30:00.000Z" -} -``` - -**Benefits:** - -- Reduces API costs by avoiding repeated vision calls for the same sticker -- Faster response times for cached stickers (no vision processing delay) -- Enables sticker search functionality based on cached descriptions - -The cache is populated automatically as stickers are received. There is no manual cache management required. - -### Sending stickers - -The agent can send and search stickers using the `sticker` and `sticker-search` actions. These are disabled by default and must be enabled in config: - -```json5 -{ - channels: { - telegram: { - actions: { - sticker: true, - }, - }, - }, -} -``` - -**Send a sticker:** - -```json5 -{ - action: "sticker", - channel: "telegram", - to: "123456789", - fileId: "CAACAgIAAxkBAAI...", -} -``` - -Parameters: - -- `fileId` (required) — the Telegram file ID of the sticker. Obtain this from `Sticker.fileId` when receiving a sticker, or from a `sticker-search` result. -- `replyTo` (optional) — message ID to reply to. -- `threadId` (optional) — message thread ID for forum topics. - -**Search for stickers:** - -The agent can search cached stickers by description, emoji, or set name: - -```json5 -{ - action: "sticker-search", - channel: "telegram", - query: "cat waving", - limit: 5, -} -``` - -Returns matching stickers from the cache: - -```json5 -{ - ok: true, - count: 2, - stickers: [ - { - fileId: "CAACAgIAAxkBAAI...", - emoji: "👋", - description: "A cartoon cat waving enthusiastically", - setName: "CoolCats", - }, - ], -} -``` - -The search uses fuzzy matching across description text, emoji characters, and set names. - -**Example with threading:** - -```json5 -{ - action: "sticker", - channel: "telegram", - to: "-1001234567890", - fileId: "CAACAgIAAxkBAAI...", - replyTo: 42, - threadId: 123, -} -``` - -## Streaming (drafts) - -Telegram can stream **draft bubbles** while the agent is generating a response. -OpenClaw uses Bot API `sendMessageDraft` (not real messages) and then sends the -final reply as a normal message. - -Requirements (Telegram Bot API 9.3+): - -- **Private chats with topics enabled** (forum topic mode for the bot). -- Incoming messages must include `message_thread_id` (private topic thread). -- Streaming is ignored for groups/supergroups/channels. - -Config: - -- `channels.telegram.streamMode: "off" | "partial" | "block"` (default: `partial`) - - `partial`: update the draft bubble with the latest streaming text. - - `block`: update the draft bubble in larger blocks (chunked). - - `off`: disable draft streaming. -- Optional (only for `streamMode: "block"`): - - `channels.telegram.draftChunk: { minChars?, maxChars?, breakPreference? }` - - defaults: `minChars: 200`, `maxChars: 800`, `breakPreference: "paragraph"` (clamped to `channels.telegram.textChunkLimit`). - -Note: draft streaming is separate from **block streaming** (channel messages). -Block streaming is off by default and requires `channels.telegram.blockStreaming: true` -if you want early Telegram messages instead of draft updates. - -Reasoning stream (Telegram only): - -- `/reasoning stream` streams reasoning into the draft bubble while the reply is - generating, then sends the final answer without reasoning. -- If `channels.telegram.streamMode` is `off`, reasoning stream is disabled. - More context: [Streaming + chunking](/concepts/streaming). - -## Retry policy - -Outbound Telegram API calls retry on transient network/429 errors with exponential backoff and jitter. Configure via `channels.telegram.retry`. See [Retry policy](/concepts/retry). - -## Agent tool (messages + reactions) - -- Tool: `telegram` with `sendMessage` action (`to`, `content`, optional `mediaUrl`, `replyToMessageId`, `messageThreadId`). -- Tool: `telegram` with `react` action (`chatId`, `messageId`, `emoji`). -- Tool: `telegram` with `deleteMessage` action (`chatId`, `messageId`). -- Reaction removal semantics: see [/tools/reactions](/tools/reactions). -- Tool gating: `channels.telegram.actions.reactions`, `channels.telegram.actions.sendMessage`, `channels.telegram.actions.deleteMessage` (default: enabled), and `channels.telegram.actions.sticker` (default: disabled). - -## Reaction notifications - -**How reactions work:** -Telegram reactions arrive as **separate `message_reaction` events**, not as properties in message payloads. When a user adds a reaction, OpenClaw: - -1. Receives the `message_reaction` update from Telegram API -2. Converts it to a **system event** with format: `"Telegram reaction added: {emoji} by {user} on msg {id}"` -3. Enqueues the system event using the **same session key** as regular messages -4. When the next message arrives in that conversation, system events are drained and prepended to the agent's context - -The agent sees reactions as **system notifications** in the conversation history, not as message metadata. - -**Configuration:** - -- `channels.telegram.reactionNotifications`: Controls which reactions trigger notifications - - `"off"` — ignore all reactions - - `"own"` — notify when users react to bot messages (best-effort; in-memory) (default) - - `"all"` — notify for all reactions - -- `channels.telegram.reactionLevel`: Controls agent's reaction capability - - `"off"` — agent cannot react to messages - - `"ack"` — bot sends acknowledgment reactions (👀 while processing) (default) - - `"minimal"` — agent can react sparingly (guideline: 1 per 5-10 exchanges) - - `"extensive"` — agent can react liberally when appropriate - -**Forum groups:** Reactions in forum groups include `message_thread_id` and use session keys like `agent:main:telegram:group:{chatId}:topic:{threadId}`. This ensures reactions and messages in the same topic stay together. - -**Example config:** - -```json5 -{ - channels: { - telegram: { - reactionNotifications: "all", // See all reactions - reactionLevel: "minimal", // Agent can react sparingly - }, - }, -} -``` - -**Requirements:** - -- Telegram bots must explicitly request `message_reaction` in `allowed_updates` (configured automatically by OpenClaw) -- For webhook mode, reactions are included in the webhook `allowed_updates` -- For polling mode, reactions are included in the `getUpdates` `allowed_updates` - -## Delivery targets (CLI/cron) - -- Use a chat id (`123456789`) or a username (`@name`) as the target. -- Example: `openclaw message send --channel telegram --target 123456789 --message "hi"`. - -## Troubleshooting - -**Bot doesn’t respond to non-mention messages in a group:** - -- If you set `channels.telegram.groups.*.requireMention=false`, Telegram’s Bot API **privacy mode** must be disabled. - - BotFather: `/setprivacy` → **Disable** (then remove + re-add the bot to the group) -- `openclaw channels status` shows a warning when config expects unmentioned group messages. -- `openclaw channels status --probe` can additionally check membership for explicit numeric group IDs (it can’t audit wildcard `"*"` rules). -- Quick test: `/activation always` (session-only; use config for persistence) - -**Bot not seeing group messages at all:** - -- If `channels.telegram.groups` is set, the group must be listed or use `"*"` -- Check Privacy Settings in @BotFather → "Group Privacy" should be **OFF** -- Verify bot is actually a member (not just an admin with no read access) -- Check gateway logs: `openclaw logs --follow` (look for "skipping group message") - -**Bot responds to mentions but not `/activation always`:** - -- The `/activation` command updates session state but doesn't persist to config -- For persistent behavior, add group to `channels.telegram.groups` with `requireMention: false` - -**Commands like `/status` don't work:** - -- Make sure your Telegram user ID is authorized (via pairing or `channels.telegram.allowFrom`) -- Commands require authorization even in groups with `groupPolicy: "open"` - -**Long-polling aborts immediately on Node 22+ (often with proxies/custom fetch):** - -- Node 22+ is stricter about `AbortSignal` instances; foreign signals can abort `fetch` calls right away. -- Upgrade to a OpenClaw build that normalizes abort signals, or run the gateway on Node 20 until you can upgrade. - -**Bot starts, then silently stops responding (or logs `HttpError: Network request ... failed`):** - -- Some hosts resolve `api.telegram.org` to IPv6 first. If your server does not have working IPv6 egress, grammY can get stuck on IPv6-only requests. -- Fix by enabling IPv6 egress **or** forcing IPv4 resolution for `api.telegram.org` (for example, add an `/etc/hosts` entry using the IPv4 A record, or prefer IPv4 in your OS DNS stack), then restart the gateway. -- Quick check: `dig +short api.telegram.org A` and `dig +short api.telegram.org AAAA` to confirm what DNS returns. - -## Configuration reference (Telegram) - -Full configuration: [Configuration](/gateway/configuration) - -Provider options: - -- `channels.telegram.enabled`: enable/disable channel startup. -- `channels.telegram.botToken`: bot token (BotFather). -- `channels.telegram.tokenFile`: read token from file path. -- `channels.telegram.dmPolicy`: `pairing | allowlist | open | disabled` (default: pairing). -- `channels.telegram.allowFrom`: DM allowlist (ids/usernames). `open` requires `"*"`. -- `channels.telegram.groupPolicy`: `open | allowlist | disabled` (default: allowlist). -- `channels.telegram.groupAllowFrom`: group sender allowlist (ids/usernames). -- `channels.telegram.groups`: per-group defaults + allowlist (use `"*"` for global defaults). - - `channels.telegram.groups..requireMention`: mention gating default. - - `channels.telegram.groups..skills`: skill filter (omit = all skills, empty = none). - - `channels.telegram.groups..allowFrom`: per-group sender allowlist override. - - `channels.telegram.groups..systemPrompt`: extra system prompt for the group. - - `channels.telegram.groups..enabled`: disable the group when `false`. - - `channels.telegram.groups..topics..*`: per-topic overrides (same fields as group). - - `channels.telegram.groups..topics..requireMention`: per-topic mention gating override. -- `channels.telegram.capabilities.inlineButtons`: `off | dm | group | all | allowlist` (default: allowlist). -- `channels.telegram.accounts..capabilities.inlineButtons`: per-account override. -- `channels.telegram.replyToMode`: `off | first | all` (default: `first`). -- `channels.telegram.textChunkLimit`: outbound chunk size (chars). -- `channels.telegram.chunkMode`: `length` (default) or `newline` to split on blank lines (paragraph boundaries) before length chunking. -- `channels.telegram.linkPreview`: toggle link previews for outbound messages (default: true). -- `channels.telegram.streamMode`: `off | partial | block` (draft streaming). -- `channels.telegram.mediaMaxMb`: inbound/outbound media cap (MB). -- `channels.telegram.retry`: retry policy for outbound Telegram API calls (attempts, minDelayMs, maxDelayMs, jitter). -- `channels.telegram.network.autoSelectFamily`: override Node autoSelectFamily (true=enable, false=disable). Defaults to disabled on Node 22 to avoid Happy Eyeballs timeouts. -- `channels.telegram.proxy`: proxy URL for Bot API calls (SOCKS/HTTP). -- `channels.telegram.webhookUrl`: enable webhook mode (requires `channels.telegram.webhookSecret`). -- `channels.telegram.webhookSecret`: webhook secret (required when webhookUrl is set). -- `channels.telegram.webhookPath`: local webhook path (default `/telegram-webhook`). -- `channels.telegram.actions.reactions`: gate Telegram tool reactions. -- `channels.telegram.actions.sendMessage`: gate Telegram tool message sends. -- `channels.telegram.actions.deleteMessage`: gate Telegram tool message deletes. -- `channels.telegram.actions.sticker`: gate Telegram sticker actions — send and search (default: false). -- `channels.telegram.reactionNotifications`: `off | own | all` — control which reactions trigger system events (default: `own` when not set). -- `channels.telegram.reactionLevel`: `off | ack | minimal | extensive` — control agent's reaction capability (default: `minimal` when not set). - -Related global options: - -- `agents.list[].groupChat.mentionPatterns` (mention gating patterns). -- `messages.groupChat.mentionPatterns` (global fallback). -- `commands.native` (defaults to `"auto"` → on for Telegram/Discord, off for Slack), `commands.text`, `commands.useAccessGroups` (command behavior). Override with `channels.telegram.commands.native`. -- `messages.responsePrefix`, `messages.ackReaction`, `messages.ackReactionScope`, `messages.removeAckAfterReply`. diff --git a/docs/es/channels/tlon.md b/docs/es/channels/tlon.md deleted file mode 100644 index 3b632a9274..0000000000 --- a/docs/es/channels/tlon.md +++ /dev/null @@ -1,132 +0,0 @@ ---- -summary: "Tlon/Urbit support status, capabilities, and configuration" -read_when: - - Working on Tlon/Urbit channel features -title: "Tlon" ---- - -# Tlon (plugin) - -Tlon is a decentralized messenger built on Urbit. OpenClaw connects to your Urbit ship and can -respond to DMs and group chat messages. Group replies require an @ mention by default and can -be further restricted via allowlists. - -Status: supported via plugin. DMs, group mentions, thread replies, and text-only media fallback -(URL appended to caption). Reactions, polls, and native media uploads are not supported. - -## Plugin required - -Tlon ships as a plugin and is not bundled with the core install. - -Install via CLI (npm registry): - -```bash -openclaw plugins install @openclaw/tlon -``` - -Local checkout (when running from a git repo): - -```bash -openclaw plugins install ./extensions/tlon -``` - -Details: [Plugins](/plugin) - -## Setup - -1. Install the Tlon plugin. -2. Gather your ship URL and login code. -3. Configure `channels.tlon`. -4. Restart the gateway. -5. DM the bot or mention it in a group channel. - -Minimal config (single account): - -```json5 -{ - channels: { - tlon: { - enabled: true, - ship: "~sampel-palnet", - url: "https://your-ship-host", - code: "lidlut-tabwed-pillex-ridrup", - }, - }, -} -``` - -## Group channels - -Auto-discovery is enabled by default. You can also pin channels manually: - -```json5 -{ - channels: { - tlon: { - groupChannels: ["chat/~host-ship/general", "chat/~host-ship/support"], - }, - }, -} -``` - -Disable auto-discovery: - -```json5 -{ - channels: { - tlon: { - autoDiscoverChannels: false, - }, - }, -} -``` - -## Access control - -DM allowlist (empty = allow all): - -```json5 -{ - channels: { - tlon: { - dmAllowlist: ["~zod", "~nec"], - }, - }, -} -``` - -Group authorization (restricted by default): - -```json5 -{ - channels: { - tlon: { - defaultAuthorizedShips: ["~zod"], - authorization: { - channelRules: { - "chat/~host-ship/general": { - mode: "restricted", - allowedShips: ["~zod", "~nec"], - }, - "chat/~host-ship/announcements": { - mode: "open", - }, - }, - }, - }, - }, -} -``` - -## Delivery targets (CLI/cron) - -Use these with `openclaw message send` or cron delivery: - -- DM: `~sampel-palnet` or `dm/~sampel-palnet` -- Group: `chat/~host-ship/channel` or `group:~host-ship/channel` - -## Notes - -- Group replies require a mention (e.g. `~your-bot-ship`) to respond. -- Thread replies: if the inbound message is in a thread, OpenClaw replies in-thread. -- Media: `sendMedia` falls back to text + URL (no native upload). diff --git a/docs/es/channels/troubleshooting.md b/docs/es/channels/troubleshooting.md deleted file mode 100644 index 929b0c776c..0000000000 --- a/docs/es/channels/troubleshooting.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -summary: "Channel-specific troubleshooting shortcuts (Discord/Telegram/WhatsApp)" -read_when: - - A channel connects but messages don’t flow - - Investigating channel misconfiguration (intents, permissions, privacy mode) -title: "Channel Troubleshooting" ---- - -# Channel troubleshooting - -Start with: - -```bash -openclaw doctor -openclaw channels status --probe -``` - -`channels status --probe` prints warnings when it can detect common channel misconfigurations, and includes small live checks (credentials, some permissions/membership). - -## Channels - -- Discord: [/channels/discord#troubleshooting](/channels/discord#troubleshooting) -- Telegram: [/channels/telegram#troubleshooting](/channels/telegram#troubleshooting) -- WhatsApp: [/channels/whatsapp#troubleshooting-quick](/channels/whatsapp#troubleshooting-quick) - -## Telegram quick fixes - -- Logs show `HttpError: Network request for 'sendMessage' failed` or `sendChatAction` → check IPv6 DNS. If `api.telegram.org` resolves to IPv6 first and the host lacks IPv6 egress, force IPv4 or enable IPv6. See [/channels/telegram#troubleshooting](/channels/telegram#troubleshooting). -- Logs show `setMyCommands failed` → check outbound HTTPS and DNS reachability to `api.telegram.org` (common on locked-down VPS or proxies). diff --git a/docs/es/channels/twitch.md b/docs/es/channels/twitch.md deleted file mode 100644 index 7901c04278..0000000000 --- a/docs/es/channels/twitch.md +++ /dev/null @@ -1,379 +0,0 @@ ---- -summary: "Twitch chat bot configuration and setup" -read_when: - - Setting up Twitch chat integration for OpenClaw -title: "Twitch" ---- - -# Twitch (plugin) - -Twitch chat support via IRC connection. OpenClaw connects as a Twitch user (bot account) to receive and send messages in channels. - -## Plugin required - -Twitch ships as a plugin and is not bundled with the core install. - -Install via CLI (npm registry): - -```bash -openclaw plugins install @openclaw/twitch -``` - -Local checkout (when running from a git repo): - -```bash -openclaw plugins install ./extensions/twitch -``` - -Details: [Plugins](/plugin) - -## Quick setup (beginner) - -1. Create a dedicated Twitch account for the bot (or use an existing account). -2. Generate credentials: [Twitch Token Generator](https://twitchtokengenerator.com/) - - Select **Bot Token** - - Verify scopes `chat:read` and `chat:write` are selected - - Copy the **Client ID** and **Access Token** -3. Find your Twitch user ID: https://www.streamweasels.com/tools/convert-twitch-username-to-user-id/ -4. Configure the token: - - Env: `OPENCLAW_TWITCH_ACCESS_TOKEN=...` (default account only) - - Or config: `channels.twitch.accessToken` - - If both are set, config takes precedence (env fallback is default-account only). -5. Start the gateway. - -**⚠️ Important:** Add access control (`allowFrom` or `allowedRoles`) to prevent unauthorized users from triggering the bot. `requireMention` defaults to `true`. - -Minimal config: - -```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/ - }, - }, -} -``` - -## What it is - -- A Twitch channel owned by the Gateway. -- Deterministic routing: replies always go back to Twitch. -- Each account maps to an isolated session key `agent::twitch:`. -- `username` is the bot's account (who authenticates), `channel` is which chat room to join. - -## Setup (detailed) - -### Generate credentials - -Use [Twitch Token Generator](https://twitchtokengenerator.com/): - -- Select **Bot Token** -- Verify scopes `chat:read` and `chat:write` are selected -- Copy the **Client ID** and **Access Token** - -No manual app registration needed. Tokens expire after several hours. - -### Configure the bot - -**Env var (default account only):** - -```bash -OPENCLAW_TWITCH_ACCESS_TOKEN=oauth:abc123... -``` - -**Or config:** - -```json5 -{ - channels: { - twitch: { - enabled: true, - username: "openclaw", - accessToken: "oauth:abc123...", - clientId: "xyz789...", - channel: "vevisk", - }, - }, -} -``` - -If both env and config are set, config takes precedence. - -### Access control (recommended) - -```json5 -{ - channels: { - twitch: { - allowFrom: ["123456789"], // (recommended) Your Twitch user ID only - }, - }, -} -``` - -Prefer `allowFrom` for a hard allowlist. Use `allowedRoles` instead if you want role-based access. - -**Available roles:** `"moderator"`, `"owner"`, `"vip"`, `"subscriber"`, `"all"`. - -**Why user IDs?** Usernames can change, allowing impersonation. User IDs are permanent. - -Find your Twitch user ID: https://www.streamweasels.com/tools/convert-twitch-username-%20to-user-id/ (Convert your Twitch username to ID) - -## Token refresh (optional) - -Tokens from [Twitch Token Generator](https://twitchtokengenerator.com/) cannot be automatically refreshed - regenerate when expired. - -For automatic token refresh, create your own Twitch application at [Twitch Developer Console](https://dev.twitch.tv/console) and add to config: - -```json5 -{ - channels: { - twitch: { - clientSecret: "your_client_secret", - refreshToken: "your_refresh_token", - }, - }, -} -``` - -The bot automatically refreshes tokens before expiration and logs refresh events. - -## Multi-account support - -Use `channels.twitch.accounts` with per-account tokens. See [`gateway/configuration`](/gateway/configuration) for the shared pattern. - -Example (one bot account in two channels): - -```json5 -{ - channels: { - twitch: { - accounts: { - channel1: { - username: "openclaw", - accessToken: "oauth:abc123...", - clientId: "xyz789...", - channel: "vevisk", - }, - channel2: { - username: "openclaw", - accessToken: "oauth:def456...", - clientId: "uvw012...", - channel: "secondchannel", - }, - }, - }, - }, -} -``` - -**Note:** Each account needs its own token (one token per channel). - -## Access control - -### Role-based restrictions - -```json5 -{ - channels: { - twitch: { - accounts: { - default: { - allowedRoles: ["moderator", "vip"], - }, - }, - }, - }, -} -``` - -### Allowlist by User ID (most secure) - -```json5 -{ - channels: { - twitch: { - accounts: { - default: { - allowFrom: ["123456789", "987654321"], - }, - }, - }, - }, -} -``` - -### Role-based access (alternative) - -`allowFrom` is a hard allowlist. When set, only those user IDs are allowed. -If you want role-based access, leave `allowFrom` unset and configure `allowedRoles` instead: - -```json5 -{ - channels: { - twitch: { - accounts: { - default: { - allowedRoles: ["moderator"], - }, - }, - }, - }, -} -``` - -### Disable @mention requirement - -By default, `requireMention` is `true`. To disable and respond to all messages: - -```json5 -{ - channels: { - twitch: { - accounts: { - default: { - requireMention: false, - }, - }, - }, - }, -} -``` - -## Troubleshooting - -First, run diagnostic commands: - -```bash -openclaw doctor -openclaw channels status --probe -``` - -### Bot doesn't respond to messages - -**Check access control:** Ensure your user ID is in `allowFrom`, or temporarily remove -`allowFrom` and set `allowedRoles: ["all"]` to test. - -**Check the bot is in the channel:** The bot must join the channel specified in `channel`. - -### Token issues - -**"Failed to connect" or authentication errors:** - -- Verify `accessToken` is the OAuth access token value (typically starts with `oauth:` prefix) -- Check token has `chat:read` and `chat:write` scopes -- If using token refresh, verify `clientSecret` and `refreshToken` are set - -### Token refresh not working - -**Check logs for refresh events:** - -``` -Using env token source for mybot -Access token refreshed for user 123456 (expires in 14400s) -``` - -If you see "token refresh disabled (no refresh token)": - -- Ensure `clientSecret` is provided -- Ensure `refreshToken` is provided - -## Config - -**Account config:** - -- `username` - Bot username -- `accessToken` - OAuth access token with `chat:read` and `chat:write` -- `clientId` - Twitch Client ID (from Token Generator or your app) -- `channel` - Channel to join (required) -- `enabled` - Enable this account (default: `true`) -- `clientSecret` - Optional: For automatic token refresh -- `refreshToken` - Optional: For automatic token refresh -- `expiresIn` - Token expiry in seconds -- `obtainmentTimestamp` - Token obtained timestamp -- `allowFrom` - User ID allowlist -- `allowedRoles` - Role-based access control (`"moderator" | "owner" | "vip" | "subscriber" | "all"`) -- `requireMention` - Require @mention (default: `true`) - -**Provider options:** - -- `channels.twitch.enabled` - Enable/disable channel startup -- `channels.twitch.username` - Bot username (simplified single-account config) -- `channels.twitch.accessToken` - OAuth access token (simplified single-account config) -- `channels.twitch.clientId` - Twitch Client ID (simplified single-account config) -- `channels.twitch.channel` - Channel to join (simplified single-account config) -- `channels.twitch.accounts.` - Multi-account config (all account fields above) - -Full example: - -```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"], - }, - }, - }, - }, -} -``` - -## Tool actions - -The agent can call `twitch` with action: - -- `send` - Send a message to a channel - -Example: - -```json5 -{ - action: "twitch", - params: { - message: "Hello Twitch!", - to: "#mychannel", - }, -} -``` - -## Safety & ops - -- **Treat tokens like passwords** - Never commit tokens to git -- **Use automatic token refresh** for long-running bots -- **Use user ID allowlists** instead of usernames for access control -- **Monitor logs** for token refresh events and connection status -- **Scope tokens minimally** - Only request `chat:read` and `chat:write` -- **If stuck**: Restart the gateway after confirming no other process owns the session - -## Limits - -- **500 characters** per message (auto-chunked at word boundaries) -- Markdown is stripped before chunking -- No rate limiting (uses Twitch's built-in rate limits) diff --git a/docs/es/channels/whatsapp.md b/docs/es/channels/whatsapp.md deleted file mode 100644 index 1741ee1b7e..0000000000 --- a/docs/es/channels/whatsapp.md +++ /dev/null @@ -1,404 +0,0 @@ ---- -summary: "WhatsApp (web channel) integration: login, inbox, replies, media, and ops" -read_when: - - Working on WhatsApp/web channel behavior or inbox routing -title: "WhatsApp" ---- - -# WhatsApp (web channel) - -Status: WhatsApp Web via Baileys only. Gateway owns the session(s). - -## Quick setup (beginner) - -1. Use a **separate phone number** if possible (recommended). -2. Configure WhatsApp in `~/.openclaw/openclaw.json`. -3. Run `openclaw channels login` to scan the QR code (Linked Devices). -4. Start the gateway. - -Minimal config: - -```json5 -{ - channels: { - whatsapp: { - dmPolicy: "allowlist", - allowFrom: ["+15551234567"], - }, - }, -} -``` - -## Goals - -- Multiple WhatsApp accounts (multi-account) in one Gateway process. -- Deterministic routing: replies return to WhatsApp, no model routing. -- Model sees enough context to understand quoted replies. - -## Config writes - -By default, WhatsApp is allowed to write config updates triggered by `/config set|unset` (requires `commands.config: true`). - -Disable with: - -```json5 -{ - channels: { whatsapp: { configWrites: false } }, -} -``` - -## Architecture (who owns what) - -- **Gateway** owns the Baileys socket and inbox loop. -- **CLI / macOS app** talk to the gateway; no direct Baileys use. -- **Active listener** is required for outbound sends; otherwise send fails fast. - -## Getting a phone number (two modes) - -WhatsApp requires a real mobile number for verification. VoIP and virtual numbers are usually blocked. There are two supported ways to run OpenClaw on WhatsApp: - -### Dedicated number (recommended) - -Use a **separate phone number** for OpenClaw. Best UX, clean routing, no self-chat quirks. Ideal setup: **spare/old Android phone + eSIM**. Leave it on Wi‑Fi and power, and link it via QR. - -**WhatsApp Business:** You can use WhatsApp Business on the same device with a different number. Great for keeping your personal WhatsApp separate — install WhatsApp Business and register the OpenClaw number there. - -**Sample config (dedicated number, single-user allowlist):** - -```json5 -{ - channels: { - whatsapp: { - dmPolicy: "allowlist", - allowFrom: ["+15551234567"], - }, - }, -} -``` - -**Pairing mode (optional):** -If you want pairing instead of allowlist, set `channels.whatsapp.dmPolicy` to `pairing`. Unknown senders get a pairing code; approve with: -`openclaw pairing approve whatsapp ` - -### Personal number (fallback) - -Quick fallback: run OpenClaw on **your own number**. Message yourself (WhatsApp “Message yourself”) for testing so you don’t spam contacts. Expect to read verification codes on your main phone during setup and experiments. **Must enable self-chat mode.** -When the wizard asks for your personal WhatsApp number, enter the phone you will message from (the owner/sender), not the assistant number. - -**Sample config (personal number, self-chat):** - -```json -{ - "whatsapp": { - "selfChatMode": true, - "dmPolicy": "allowlist", - "allowFrom": ["+15551234567"] - } -} -``` - -Self-chat replies default to `[{identity.name}]` when set (otherwise `[openclaw]`) -if `messages.responsePrefix` is unset. Set it explicitly to customize or disable -the prefix (use `""` to remove it). - -### Number sourcing tips - -- **Local eSIM** from your country's mobile carrier (most reliable) - - Austria: [hot.at](https://www.hot.at) - - UK: [giffgaff](https://www.giffgaff.com) — free SIM, no contract -- **Prepaid SIM** — cheap, just needs to receive one SMS for verification - -**Avoid:** TextNow, Google Voice, most "free SMS" services — WhatsApp blocks these aggressively. - -**Tip:** The number only needs to receive one verification SMS. After that, WhatsApp Web sessions persist via `creds.json`. - -## Why Not Twilio? - -- Early OpenClaw builds supported Twilio’s WhatsApp Business integration. -- WhatsApp Business numbers are a poor fit for a personal assistant. -- Meta enforces a 24‑hour reply window; if you haven’t responded in the last 24 hours, the business number can’t initiate new messages. -- High-volume or “chatty” usage triggers aggressive blocking, because business accounts aren’t meant to send dozens of personal assistant messages. -- Result: unreliable delivery and frequent blocks, so support was removed. - -## Login + credentials - -- Login command: `openclaw channels login` (QR via Linked Devices). -- Multi-account login: `openclaw channels login --account ` (`` = `accountId`). -- Default account (when `--account` is omitted): `default` if present, otherwise the first configured account id (sorted). -- Credentials stored in `~/.openclaw/credentials/whatsapp//creds.json`. -- Backup copy at `creds.json.bak` (restored on corruption). -- Legacy compatibility: older installs stored Baileys files directly in `~/.openclaw/credentials/`. -- Logout: `openclaw channels logout` (or `--account `) deletes WhatsApp auth state (but keeps shared `oauth.json`). -- Logged-out socket => error instructs re-link. - -## Inbound flow (DM + group) - -- WhatsApp events come from `messages.upsert` (Baileys). -- Inbox listeners are detached on shutdown to avoid accumulating event handlers in tests/restarts. -- Status/broadcast chats are ignored. -- Direct chats use E.164; groups use group JID. -- **DM policy**: `channels.whatsapp.dmPolicy` controls direct chat access (default: `pairing`). - - Pairing: unknown senders get a pairing code (approve via `openclaw pairing approve whatsapp `; codes expire after 1 hour). - - Open: requires `channels.whatsapp.allowFrom` to include `"*"`. - - Your linked WhatsApp number is implicitly trusted, so self messages skip ⁠`channels.whatsapp.dmPolicy` and `channels.whatsapp.allowFrom` checks. - -### Personal-number mode (fallback) - -If you run OpenClaw on your **personal WhatsApp number**, enable `channels.whatsapp.selfChatMode` (see sample above). - -Behavior: - -- Outbound DMs never trigger pairing replies (prevents spamming contacts). -- Inbound unknown senders still follow `channels.whatsapp.dmPolicy`. -- Self-chat mode (allowFrom includes your number) avoids auto read receipts and ignores mention JIDs. -- Read receipts sent for non-self-chat DMs. - -## Read receipts - -By default, the gateway marks inbound WhatsApp messages as read (blue ticks) once they are accepted. - -Disable globally: - -```json5 -{ - channels: { whatsapp: { sendReadReceipts: false } }, -} -``` - -Disable per account: - -```json5 -{ - channels: { - whatsapp: { - accounts: { - personal: { sendReadReceipts: false }, - }, - }, - }, -} -``` - -Notes: - -- Self-chat mode always skips read receipts. - -## WhatsApp FAQ: sending messages + pairing - -**Will OpenClaw message random contacts when I link WhatsApp?** -No. Default DM policy is **pairing**, so unknown senders only get a pairing code and their message is **not processed**. OpenClaw only replies to chats it receives, or to sends you explicitly trigger (agent/CLI). - -**How does pairing work on WhatsApp?** -Pairing is a DM gate for unknown senders: - -- First DM from a new sender returns a short code (message is not processed). -- Approve with: `openclaw pairing approve whatsapp ` (list with `openclaw pairing list whatsapp`). -- Codes expire after 1 hour; pending requests are capped at 3 per channel. - -**Can multiple people use different OpenClaw instances on one WhatsApp number?** -Yes, by routing each sender to a different agent via `bindings` (peer `kind: "dm"`, sender E.164 like `+15551234567`). Replies still come from the **same WhatsApp account**, and direct chats collapse to each agent’s main session, so use **one agent per person**. DM access control (`dmPolicy`/`allowFrom`) is global per WhatsApp account. See [Multi-Agent Routing](/concepts/multi-agent). - -**Why do you ask for my phone number in the wizard?** -The wizard uses it to set your **allowlist/owner** so your own DMs are permitted. It’s not used for auto-sending. If you run on your personal WhatsApp number, use that same number and enable `channels.whatsapp.selfChatMode`. - -## Message normalization (what the model sees) - -- `Body` is the current message body with envelope. -- Quoted reply context is **always appended**: - ``` - [Replying to +1555 id:ABC123] - > - [/Replying] - ``` -- Reply metadata also set: - - `ReplyToId` = stanzaId - - `ReplyToBody` = quoted body or media placeholder - - `ReplyToSender` = E.164 when known -- Media-only inbound messages use placeholders: - - `` - -## Groups - -- Groups map to `agent::whatsapp:group:` sessions. -- Group policy: `channels.whatsapp.groupPolicy = open|disabled|allowlist` (default `allowlist`). -- Activation modes: - - `mention` (default): requires @mention or regex match. - - `always`: always triggers. -- `/activation mention|always` is owner-only and must be sent as a standalone message. -- Owner = `channels.whatsapp.allowFrom` (or self E.164 if unset). -- **History injection** (pending-only): - - Recent _unprocessed_ messages (default 50) inserted under: - `[Chat messages since your last reply - for context]` (messages already in the session are not re-injected) - - Current message under: - `[Current message - respond to this]` - - Sender suffix appended: `[from: Name (+E164)]` -- Group metadata cached 5 min (subject + participants). - -## Reply delivery (threading) - -- WhatsApp Web sends standard messages (no quoted reply threading in the current gateway). -- Reply tags are ignored on this channel. - -## Acknowledgment reactions (auto-react on receipt) - -WhatsApp can automatically send emoji reactions to incoming messages immediately upon receipt, before the bot generates a reply. This provides instant feedback to users that their message was received. - -**Configuration:** - -```json -{ - "whatsapp": { - "ackReaction": { - "emoji": "👀", - "direct": true, - "group": "mentions" - } - } -} -``` - -**Options:** - -- `emoji` (string): Emoji to use for acknowledgment (e.g., "👀", "✅", "📨"). Empty or omitted = feature disabled. -- `direct` (boolean, default: `true`): Send reactions in direct/DM chats. -- `group` (string, default: `"mentions"`): Group chat behavior: - - `"always"`: React to all group messages (even without @mention) - - `"mentions"`: React only when bot is @mentioned - - `"never"`: Never react in groups - -**Per-account override:** - -```json -{ - "whatsapp": { - "accounts": { - "work": { - "ackReaction": { - "emoji": "✅", - "direct": false, - "group": "always" - } - } - } - } -} -``` - -**Behavior notes:** - -- Reactions are sent **immediately** upon message receipt, before typing indicators or bot replies. -- In groups with `requireMention: false` (activation: always), `group: "mentions"` will react to all messages (not just @mentions). -- Fire-and-forget: reaction failures are logged but don't prevent the bot from replying. -- Participant JID is automatically included for group reactions. -- WhatsApp ignores `messages.ackReaction`; use `channels.whatsapp.ackReaction` instead. - -## Agent tool (reactions) - -- Tool: `whatsapp` with `react` action (`chatJid`, `messageId`, `emoji`, optional `remove`). -- Optional: `participant` (group sender), `fromMe` (reacting to your own message), `accountId` (multi-account). -- Reaction removal semantics: see [/tools/reactions](/tools/reactions). -- Tool gating: `channels.whatsapp.actions.reactions` (default: enabled). - -## Limits - -- Outbound text is chunked to `channels.whatsapp.textChunkLimit` (default 4000). -- Optional newline chunking: set `channels.whatsapp.chunkMode="newline"` to split on blank lines (paragraph boundaries) before length chunking. -- Inbound media saves are capped by `channels.whatsapp.mediaMaxMb` (default 50 MB). -- Outbound media items are capped by `agents.defaults.mediaMaxMb` (default 5 MB). - -## Outbound send (text + media) - -- Uses active web listener; error if gateway not running. -- Text chunking: 4k max per message (configurable via `channels.whatsapp.textChunkLimit`, optional `channels.whatsapp.chunkMode`). -- Media: - - Image/video/audio/document supported. - - Audio sent as PTT; `audio/ogg` => `audio/ogg; codecs=opus`. - - Caption only on first media item. - - Media fetch supports HTTP(S) and local paths. - - Animated GIFs: WhatsApp expects MP4 with `gifPlayback: true` for inline looping. - - CLI: `openclaw message send --media --gif-playback` - - Gateway: `send` params include `gifPlayback: true` - -## Voice notes (PTT audio) - -WhatsApp sends audio as **voice notes** (PTT bubble). - -- Best results: OGG/Opus. OpenClaw rewrites `audio/ogg` to `audio/ogg; codecs=opus`. -- `[[audio_as_voice]]` is ignored for WhatsApp (audio already ships as voice note). - -## Media limits + optimization - -- Default outbound cap: 5 MB (per media item). -- Override: `agents.defaults.mediaMaxMb`. -- Images are auto-optimized to JPEG under cap (resize + quality sweep). -- Oversize media => error; media reply falls back to text warning. - -## Heartbeats - -- **Gateway heartbeat** logs connection health (`web.heartbeatSeconds`, default 60s). -- **Agent heartbeat** can be configured per agent (`agents.list[].heartbeat`) or globally - via `agents.defaults.heartbeat` (fallback when no per-agent entries are set). - - Uses the configured heartbeat prompt (default: `Read HEARTBEAT.md if it exists (workspace context). Follow it strictly. Do not infer or repeat old tasks from prior chats. If nothing needs attention, reply HEARTBEAT_OK.`) + `HEARTBEAT_OK` skip behavior. - - Delivery defaults to the last used channel (or configured target). - -## Reconnect behavior - -- Backoff policy: `web.reconnect`: - - `initialMs`, `maxMs`, `factor`, `jitter`, `maxAttempts`. -- If maxAttempts reached, web monitoring stops (degraded). -- Logged-out => stop and require re-link. - -## Config quick map - -- `channels.whatsapp.dmPolicy` (DM policy: pairing/allowlist/open/disabled). -- `channels.whatsapp.selfChatMode` (same-phone setup; bot uses your personal WhatsApp number). -- `channels.whatsapp.allowFrom` (DM allowlist). WhatsApp uses E.164 phone numbers (no usernames). -- `channels.whatsapp.mediaMaxMb` (inbound media save cap). -- `channels.whatsapp.ackReaction` (auto-reaction on message receipt: `{emoji, direct, group}`). -- `channels.whatsapp.accounts..*` (per-account settings + optional `authDir`). -- `channels.whatsapp.accounts..mediaMaxMb` (per-account inbound media cap). -- `channels.whatsapp.accounts..ackReaction` (per-account ack reaction override). -- `channels.whatsapp.groupAllowFrom` (group sender allowlist). -- `channels.whatsapp.groupPolicy` (group policy). -- `channels.whatsapp.historyLimit` / `channels.whatsapp.accounts..historyLimit` (group history context; `0` disables). -- `channels.whatsapp.dmHistoryLimit` (DM history limit in user turns). Per-user overrides: `channels.whatsapp.dms[""].historyLimit`. -- `channels.whatsapp.groups` (group allowlist + mention gating defaults; use `"*"` to allow all) -- `channels.whatsapp.actions.reactions` (gate WhatsApp tool reactions). -- `agents.list[].groupChat.mentionPatterns` (or `messages.groupChat.mentionPatterns`) -- `messages.groupChat.historyLimit` -- `channels.whatsapp.messagePrefix` (inbound prefix; per-account: `channels.whatsapp.accounts..messagePrefix`; deprecated: `messages.messagePrefix`) -- `messages.responsePrefix` (outbound prefix) -- `agents.defaults.mediaMaxMb` -- `agents.defaults.heartbeat.every` -- `agents.defaults.heartbeat.model` (optional override) -- `agents.defaults.heartbeat.target` -- `agents.defaults.heartbeat.to` -- `agents.defaults.heartbeat.session` -- `agents.list[].heartbeat.*` (per-agent overrides) -- `session.*` (scope, idle, store, mainKey) -- `web.enabled` (disable channel startup when false) -- `web.heartbeatSeconds` -- `web.reconnect.*` - -## Logs + troubleshooting - -- Subsystems: `whatsapp/inbound`, `whatsapp/outbound`, `web-heartbeat`, `web-reconnect`. -- Log file: `/tmp/openclaw/openclaw-YYYY-MM-DD.log` (configurable). -- Troubleshooting guide: [Gateway troubleshooting](/gateway/troubleshooting). - -## Troubleshooting (quick) - -**Not linked / QR login required** - -- Symptom: `channels status` shows `linked: false` or warns “Not linked”. -- Fix: run `openclaw channels login` on the gateway host and scan the QR (WhatsApp → Settings → Linked Devices). - -**Linked but disconnected / reconnect loop** - -- Symptom: `channels status` shows `running, disconnected` or warns “Linked but disconnected”. -- Fix: `openclaw doctor` (or restart the gateway). If it persists, relink via `channels login` and inspect `openclaw logs --follow`. - -**Bun runtime** - -- Bun is **not recommended**. WhatsApp (Baileys) and Telegram are unreliable on Bun. - Run the gateway with **Node**. (See Getting Started runtime note.) diff --git a/docs/es/channels/zalo.md b/docs/es/channels/zalo.md deleted file mode 100644 index 0f247190c3..0000000000 --- a/docs/es/channels/zalo.md +++ /dev/null @@ -1,189 +0,0 @@ ---- -summary: "Zalo bot support status, capabilities, and configuration" -read_when: - - Working on Zalo features or webhooks -title: "Zalo" ---- - -# Zalo (Bot API) - -Status: experimental. Direct messages only; groups coming soon per Zalo docs. - -## Plugin required - -Zalo ships as a plugin and is not bundled with the core install. - -- Install via CLI: `openclaw plugins install @openclaw/zalo` -- Or select **Zalo** during onboarding and confirm the install prompt -- Details: [Plugins](/plugin) - -## Quick setup (beginner) - -1. Install the Zalo plugin: - - From a source checkout: `openclaw plugins install ./extensions/zalo` - - From npm (if published): `openclaw plugins install @openclaw/zalo` - - Or pick **Zalo** in onboarding and confirm the install prompt -2. Set the token: - - Env: `ZALO_BOT_TOKEN=...` - - Or config: `channels.zalo.botToken: "..."`. -3. Restart the gateway (or finish onboarding). -4. DM access is pairing by default; approve the pairing code on first contact. - -Minimal config: - -```json5 -{ - channels: { - zalo: { - enabled: true, - botToken: "12345689:abc-xyz", - dmPolicy: "pairing", - }, - }, -} -``` - -## What it is - -Zalo is a Vietnam-focused messaging app; its Bot API lets the Gateway run a bot for 1:1 conversations. -It is a good fit for support or notifications where you want deterministic routing back to Zalo. - -- A Zalo Bot API channel owned by the Gateway. -- Deterministic routing: replies go back to Zalo; the model never chooses channels. -- DMs share the agent's main session. -- Groups are not yet supported (Zalo docs state "coming soon"). - -## Setup (fast path) - -### 1) Create a bot token (Zalo Bot Platform) - -1. Go to **https://bot.zaloplatforms.com** and sign in. -2. Create a new bot and configure its settings. -3. Copy the bot token (format: `12345689:abc-xyz`). - -### 2) Configure the token (env or config) - -Example: - -```json5 -{ - channels: { - zalo: { - enabled: true, - botToken: "12345689:abc-xyz", - dmPolicy: "pairing", - }, - }, -} -``` - -Env option: `ZALO_BOT_TOKEN=...` (works for the default account only). - -Multi-account support: use `channels.zalo.accounts` with per-account tokens and optional `name`. - -3. Restart the gateway. Zalo starts when a token is resolved (env or config). -4. DM access defaults to pairing. Approve the code when the bot is first contacted. - -## How it works (behavior) - -- Inbound messages are normalized into the shared channel envelope with media placeholders. -- Replies always route back to the same Zalo chat. -- Long-polling by default; webhook mode available with `channels.zalo.webhookUrl`. - -## Limits - -- Outbound text is chunked to 2000 characters (Zalo API limit). -- Media downloads/uploads are capped by `channels.zalo.mediaMaxMb` (default 5). -- Streaming is blocked by default due to the 2000 char limit making streaming less useful. - -## Access control (DMs) - -### DM access - -- Default: `channels.zalo.dmPolicy = "pairing"`. Unknown senders receive a pairing code; messages are ignored until approved (codes expire after 1 hour). -- Approve via: - - `openclaw pairing list zalo` - - `openclaw pairing approve zalo ` -- Pairing is the default token exchange. Details: [Pairing](/start/pairing) -- `channels.zalo.allowFrom` accepts numeric user IDs (no username lookup available). - -## Long-polling vs webhook - -- Default: long-polling (no public URL required). -- Webhook mode: set `channels.zalo.webhookUrl` and `channels.zalo.webhookSecret`. - - The webhook secret must be 8-256 characters. - - Webhook URL must use HTTPS. - - Zalo sends events with `X-Bot-Api-Secret-Token` header for verification. - - Gateway HTTP handles webhook requests at `channels.zalo.webhookPath` (defaults to the webhook URL path). - -**Note:** getUpdates (polling) and webhook are mutually exclusive per Zalo API docs. - -## Supported message types - -- **Text messages**: Full support with 2000 character chunking. -- **Image messages**: Download and process inbound images; send images via `sendPhoto`. -- **Stickers**: Logged but not fully processed (no agent response). -- **Unsupported types**: Logged (e.g., messages from protected users). - -## Capabilities - -| Feature | Status | -| --------------- | ------------------------------ | -| Direct messages | ✅ Supported | -| Groups | ❌ Coming soon (per Zalo docs) | -| Media (images) | ✅ Supported | -| Reactions | ❌ Not supported | -| Threads | ❌ Not supported | -| Polls | ❌ Not supported | -| Native commands | ❌ Not supported | -| Streaming | ⚠️ Blocked (2000 char limit) | - -## Delivery targets (CLI/cron) - -- Use a chat id as the target. -- Example: `openclaw message send --channel zalo --target 123456789 --message "hi"`. - -## Troubleshooting - -**Bot doesn't respond:** - -- Check that the token is valid: `openclaw channels status --probe` -- Verify the sender is approved (pairing or allowFrom) -- Check gateway logs: `openclaw logs --follow` - -**Webhook not receiving events:** - -- Ensure webhook URL uses HTTPS -- Verify secret token is 8-256 characters -- Confirm the gateway HTTP endpoint is reachable on the configured path -- Check that getUpdates polling is not running (they're mutually exclusive) - -## Configuration reference (Zalo) - -Full configuration: [Configuration](/gateway/configuration) - -Provider options: - -- `channels.zalo.enabled`: enable/disable channel startup. -- `channels.zalo.botToken`: bot token from Zalo Bot Platform. -- `channels.zalo.tokenFile`: read token from file path. -- `channels.zalo.dmPolicy`: `pairing | allowlist | open | disabled` (default: pairing). -- `channels.zalo.allowFrom`: DM allowlist (user IDs). `open` requires `"*"`. The wizard will ask for numeric IDs. -- `channels.zalo.mediaMaxMb`: inbound/outbound media cap (MB, default 5). -- `channels.zalo.webhookUrl`: enable webhook mode (HTTPS required). -- `channels.zalo.webhookSecret`: webhook secret (8-256 chars). -- `channels.zalo.webhookPath`: webhook path on the gateway HTTP server. -- `channels.zalo.proxy`: proxy URL for API requests. - -Multi-account options: - -- `channels.zalo.accounts..botToken`: per-account token. -- `channels.zalo.accounts..tokenFile`: per-account token file. -- `channels.zalo.accounts..name`: display name. -- `channels.zalo.accounts..enabled`: enable/disable account. -- `channels.zalo.accounts..dmPolicy`: per-account DM policy. -- `channels.zalo.accounts..allowFrom`: per-account allowlist. -- `channels.zalo.accounts..webhookUrl`: per-account webhook URL. -- `channels.zalo.accounts..webhookSecret`: per-account webhook secret. -- `channels.zalo.accounts..webhookPath`: per-account webhook path. -- `channels.zalo.accounts..proxy`: per-account proxy URL. diff --git a/docs/es/channels/zalouser.md b/docs/es/channels/zalouser.md deleted file mode 100644 index 5a1b555b82..0000000000 --- a/docs/es/channels/zalouser.md +++ /dev/null @@ -1,140 +0,0 @@ ---- -summary: "Zalo personal account support via zca-cli (QR login), capabilities, and configuration" -read_when: - - Setting up Zalo Personal for OpenClaw - - Debugging Zalo Personal login or message flow -title: "Zalo Personal" ---- - -# Zalo Personal (unofficial) - -Status: experimental. This integration automates a **personal Zalo account** via `zca-cli`. - -> **Warning:** This is an unofficial integration and may result in account suspension/ban. Use at your own risk. - -## Plugin required - -Zalo Personal ships as a plugin and is not bundled with the core install. - -- Install via CLI: `openclaw plugins install @openclaw/zalouser` -- Or from a source checkout: `openclaw plugins install ./extensions/zalouser` -- Details: [Plugins](/plugin) - -## Prerequisite: zca-cli - -The Gateway machine must have the `zca` binary available in `PATH`. - -- Verify: `zca --version` -- If missing, install zca-cli (see `extensions/zalouser/README.md` or the upstream zca-cli docs). - -## Quick setup (beginner) - -1. Install the plugin (see above). -2. Login (QR, on the Gateway machine): - - `openclaw channels login --channel zalouser` - - Scan the QR code in the terminal with the Zalo mobile app. -3. Enable the channel: - -```json5 -{ - channels: { - zalouser: { - enabled: true, - dmPolicy: "pairing", - }, - }, -} -``` - -4. Restart the Gateway (or finish onboarding). -5. DM access defaults to pairing; approve the pairing code on first contact. - -## What it is - -- Uses `zca listen` to receive inbound messages. -- Uses `zca msg ...` to send replies (text/media/link). -- Designed for “personal account” use cases where Zalo Bot API is not available. - -## Naming - -Channel id is `zalouser` to make it explicit this automates a **personal Zalo user account** (unofficial). We keep `zalo` reserved for a potential future official Zalo API integration. - -## Finding IDs (directory) - -Use the directory CLI to discover peers/groups and their IDs: - -```bash -openclaw directory self --channel zalouser -openclaw directory peers list --channel zalouser --query "name" -openclaw directory groups list --channel zalouser --query "work" -``` - -## Limits - -- Outbound text is chunked to ~2000 characters (Zalo client limits). -- Streaming is blocked by default. - -## Access control (DMs) - -`channels.zalouser.dmPolicy` supports: `pairing | allowlist | open | disabled` (default: `pairing`). -`channels.zalouser.allowFrom` accepts user IDs or names. The wizard resolves names to IDs via `zca friend find` when available. - -Approve via: - -- `openclaw pairing list zalouser` -- `openclaw pairing approve zalouser ` - -## Group access (optional) - -- Default: `channels.zalouser.groupPolicy = "open"` (groups allowed). Use `channels.defaults.groupPolicy` to override the default when unset. -- Restrict to an allowlist with: - - `channels.zalouser.groupPolicy = "allowlist"` - - `channels.zalouser.groups` (keys are group IDs or names) -- Block all groups: `channels.zalouser.groupPolicy = "disabled"`. -- The configure wizard can prompt for group allowlists. -- On startup, OpenClaw resolves group/user names in allowlists to IDs and logs the mapping; unresolved entries are kept as typed. - -Example: - -```json5 -{ - channels: { - zalouser: { - groupPolicy: "allowlist", - groups: { - "123456789": { allow: true }, - "Work Chat": { allow: true }, - }, - }, - }, -} -``` - -## Multi-account - -Accounts map to zca profiles. Example: - -```json5 -{ - channels: { - zalouser: { - enabled: true, - defaultAccount: "default", - accounts: { - work: { enabled: true, profile: "work" }, - }, - }, - }, -} -``` - -## Troubleshooting - -**`zca` not found:** - -- Install zca-cli and ensure it’s on `PATH` for the Gateway process. - -**Login doesn’t stick:** - -- `openclaw channels status --probe` -- Re-login: `openclaw channels logout --channel zalouser && openclaw channels login --channel zalouser` diff --git a/docs/es/cli/acp.md b/docs/es/cli/acp.md deleted file mode 100644 index 46b78cce6f..0000000000 --- a/docs/es/cli/acp.md +++ /dev/null @@ -1,170 +0,0 @@ ---- -summary: "Run the ACP bridge for IDE integrations" -read_when: - - Setting up ACP-based IDE integrations - - Debugging ACP session routing to the Gateway -title: "acp" ---- - -# acp - -Run the ACP (Agent Client Protocol) bridge that talks to a OpenClaw Gateway. - -This command speaks ACP over stdio for IDEs and forwards prompts to the Gateway -over WebSocket. It keeps ACP sessions mapped to Gateway session keys. - -## Usage - -```bash -openclaw acp - -# Remote Gateway -openclaw acp --url wss://gateway-host:18789 --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 client (debug) - -Use the built-in ACP client to sanity-check the bridge without an IDE. -It spawns the ACP bridge and lets you type prompts interactively. - -```bash -openclaw acp client - -# Point the spawned bridge at a remote Gateway -openclaw acp client --server-args --url wss://gateway-host:18789 --token - -# Override the server command (default: openclaw) -openclaw acp client --server "node" --server-args openclaw.mjs acp --url ws://127.0.0.1:19001 -``` - -## How to use this - -Use ACP when an IDE (or other client) speaks Agent Client Protocol and you want -it to drive a OpenClaw Gateway session. - -1. Ensure the Gateway is running (local or remote). -2. Configure the Gateway target (config or flags). -3. Point your IDE to run `openclaw acp` over stdio. - -Example config (persisted): - -```bash -openclaw config set gateway.remote.url wss://gateway-host:18789 -openclaw config set gateway.remote.token -``` - -Example direct run (no config write): - -```bash -openclaw acp --url wss://gateway-host:18789 --token -``` - -## Selecting agents - -ACP does not pick agents directly. It routes by the Gateway session key. - -Use agent-scoped session keys to target a specific agent: - -```bash -openclaw acp --session agent:main:main -openclaw acp --session agent:design:main -openclaw acp --session agent:qa:bug-123 -``` - -Each ACP session maps to a single Gateway session key. One agent can have many -sessions; ACP defaults to an isolated `acp:` session unless you override -the key or label. - -## Zed editor setup - -Add a custom ACP agent in `~/.config/zed/settings.json` (or use Zed’s Settings UI): - -```json -{ - "agent_servers": { - "OpenClaw ACP": { - "type": "custom", - "command": "openclaw", - "args": ["acp"], - "env": {} - } - } -} -``` - -To target a specific Gateway or agent: - -```json -{ - "agent_servers": { - "OpenClaw ACP": { - "type": "custom", - "command": "openclaw", - "args": [ - "acp", - "--url", - "wss://gateway-host:18789", - "--token", - "", - "--session", - "agent:design:main" - ], - "env": {} - } - } -} -``` - -In Zed, open the Agent panel and select “OpenClaw ACP” to start a thread. - -## Session mapping - -By default, ACP sessions get an isolated Gateway session key with an `acp:` prefix. -To reuse a known session, pass a session key or label: - -- `--session `: use a specific Gateway session key. -- `--session-label