Skip to content

Latest commit

Β 

History

History
418 lines (310 loc) Β· 14.7 KB

File metadata and controls

418 lines (310 loc) Β· 14.7 KB

Channels Reference

This document is the canonical reference for channel configuration in ZeroClaw.

For encrypted Matrix rooms, also read the dedicated runbook:

Quick Paths

FAQ: Matrix setup passes but no reply

This is the most common symptom (same class as issue #499). Check these in order:

  1. Allowlist mismatch: allowed_users does not include the sender (or is empty).
  2. Wrong room target: bot is not joined to the configured room_id / alias target room.
  3. Token/account mismatch: token is valid but belongs to another Matrix account.
  4. E2EE device identity gap: whoami does not return device_id and config does not provide one.
  5. Key sharing/trust gap: room keys were not shared to the bot device, so encrypted events cannot be decrypted.
  6. Stale runtime state: config changed but zeroclaw daemon was not restarted.

1. Configuration Namespace

All channel settings live under channels_config in ~/.zeroclaw/config.toml.

[channels_config]
cli = true

Each channel is enabled by creating its sub-table (for example, [channels_config.telegram]).

In-Chat Runtime Model Switching (Telegram / Discord)

When running zeroclaw channel start (or daemon mode), Telegram and Discord now support sender-scoped runtime switching:

  • /models β€” show available providers and current selection
  • /models <provider> β€” switch provider for the current sender session
  • /model β€” show current model and cached model IDs (if available)
  • /model <model-id> β€” switch model for the current sender session

Notes:

  • Switching clears only that sender's in-memory conversation history to avoid cross-model context contamination.
  • Model cache previews come from zeroclaw models refresh --provider <ID>.
  • These are runtime chat commands, not CLI subcommands.

Inbound Image Marker Protocol

ZeroClaw supports multimodal input through inline message markers:

  • Syntax: [IMAGE:<source>]
  • <source> can be:
    • Local file path
    • Data URI (data:image/...;base64,...)
    • Remote URL only when [multimodal].allow_remote_fetch = true

Operational notes:

  • Marker parsing applies to user-role messages before provider calls.
  • Provider capability is enforced at runtime: if the selected provider does not support vision, the request fails with a structured capability error (capability=vision).
  • Linq webhook media parts with image/* MIME type are automatically converted to this marker format.

Channel Matrix

Build Feature Toggle (channel-matrix)

Matrix support is controlled at compile time by the channel-matrix Cargo feature.

  • Default builds include Matrix support (default = ["hardware", "channel-matrix"]).
  • For faster local iteration when Matrix is not needed:
cargo check --no-default-features --features hardware
  • To explicitly enable Matrix support in custom feature sets:
cargo check --no-default-features --features hardware,channel-matrix

If [channels_config.matrix] is present but the binary was built without channel-matrix, zeroclaw channel list, zeroclaw channel doctor, and zeroclaw channel start will log that Matrix is intentionally skipped for this build.


2. Delivery Modes at a Glance

Channel Receive mode Public inbound port required?
CLI local stdin/stdout No
Telegram polling No
Discord gateway/websocket No
Slack events API No (token-based channel flow)
Mattermost polling No
Matrix sync API (supports E2EE) No
Signal signal-cli HTTP bridge No (local bridge endpoint)
WhatsApp webhook (Cloud API) or websocket (Web mode) Cloud API: Yes (public HTTPS callback), Web mode: No
Webhook gateway endpoint (/webhook) Usually yes
Email IMAP polling + SMTP send No
IRC IRC socket No
Lark/Feishu websocket (default) or webhook Webhook mode only
DingTalk stream mode No
QQ bot gateway No
iMessage local integration No

3. Allowlist Semantics

For channels with inbound sender allowlists:

  • Empty allowlist: deny all inbound messages.
  • "*": allow all inbound senders (use for temporary verification only).
  • Explicit list: allow only listed senders.

Field names differ by channel:

  • allowed_users (Telegram/Discord/Slack/Mattermost/Matrix/IRC/Lark/DingTalk/QQ)
  • allowed_from (Signal)
  • allowed_numbers (WhatsApp)
  • allowed_senders (Email)
  • allowed_contacts (iMessage)

4. Per-Channel Config Examples

4.1 Telegram

[channels_config.telegram]
bot_token = "123456:telegram-token"
allowed_users = ["*"]
stream_mode = "off"               # optional: off | partial
draft_update_interval_ms = 1000   # optional: edit throttle for partial streaming
mention_only = false              # optional: require @mention in groups
interrupt_on_new_message = false  # optional: cancel in-flight same-sender same-chat request

Telegram notes:

  • interrupt_on_new_message = true preserves interrupted user turns in conversation history, then restarts generation on the newest message.
  • Interruption scope is strict: same sender in the same chat. Messages from different chats are processed independently.

4.2 Discord

[channels_config.discord]
bot_token = "discord-bot-token"
guild_id = "123456789012345678"   # optional
allowed_users = ["*"]
listen_to_bots = false
mention_only = false

4.3 Slack

[channels_config.slack]
bot_token = "xoxb-..."
app_token = "xapp-..."             # optional
channel_id = "C1234567890"         # optional
allowed_users = ["*"]

4.4 Mattermost

[channels_config.mattermost]
url = "https://mm.example.com"
bot_token = "mattermost-token"
channel_id = "channel-id"          # required for listening
allowed_users = ["*"]

4.5 Matrix

[channels_config.matrix]
homeserver = "https://matrix.example.com"
access_token = "syt_..."
user_id = "@zeroclaw:matrix.example.com"   # optional, recommended for E2EE
device_id = "DEVICEID123"                  # optional, recommended for E2EE
room_id = "!room:matrix.example.com"       # or room alias (#ops:matrix.example.com)
allowed_users = ["*"]

See Matrix E2EE Guide for encrypted-room troubleshooting.

4.6 Signal

[channels_config.signal]
http_url = "http://127.0.0.1:8686"
account = "+1234567890"
group_id = "dm"                    # optional: "dm" / group id / omitted
allowed_from = ["*"]
ignore_attachments = false
ignore_stories = true

4.7 WhatsApp

ZeroClaw supports two WhatsApp backends:

  • Cloud API mode (phone_number_id + access_token + verify_token)
  • WhatsApp Web mode (session_path, requires build flag --features whatsapp-web)

Cloud API mode:

[channels_config.whatsapp]
access_token = "EAAB..."
phone_number_id = "123456789012345"
verify_token = "your-verify-token"
app_secret = "your-app-secret"     # optional but recommended
allowed_numbers = ["*"]

WhatsApp Web mode:

[channels_config.whatsapp]
session_path = "~/.zeroclaw/state/whatsapp-web/session.db"
pair_phone = "15551234567"         # optional; omit to use QR flow
pair_code = ""                     # optional custom pair code
allowed_numbers = ["*"]

Notes:

  • Build with cargo build --features whatsapp-web (or equivalent run command).
  • Keep session_path on persistent storage to avoid relinking after restart.
  • Reply routing uses the originating chat JID, so direct and group replies work correctly.

4.8 Webhook Channel Config (Gateway)

channels_config.webhook enables webhook-specific gateway behavior.

[channels_config.webhook]
port = 8080
secret = "optional-shared-secret"

Run with gateway/daemon and verify /health.

4.9 Email

[channels_config.email]
imap_host = "imap.example.com"
imap_port = 993
imap_folder = "INBOX"
smtp_host = "smtp.example.com"
smtp_port = 465
smtp_tls = true
username = "[email protected]"
password = "email-password"
from_address = "[email protected]"
poll_interval_secs = 60
allowed_senders = ["*"]

4.10 IRC

[channels_config.irc]
server = "irc.libera.chat"
port = 6697
nickname = "zeroclaw-bot"
username = "zeroclaw"              # optional
channels = ["#zeroclaw"]
allowed_users = ["*"]
server_password = ""                # optional
nickserv_password = ""              # optional
sasl_password = ""                  # optional
verify_tls = true

4.11 Lark / Feishu

[channels_config.lark]
app_id = "cli_xxx"
app_secret = "xxx"
encrypt_key = ""                    # optional
verification_token = ""             # optional
allowed_users = ["*"]
use_feishu = false
receive_mode = "websocket"          # or "webhook"
port = 8081                          # required for webhook mode

Interactive onboarding support:

zeroclaw onboard --interactive

The wizard now includes a dedicated Lark/Feishu step with:

  • region selection (Feishu (CN) vs Lark (International))
  • credential verification against official Open Platform auth endpoint
  • receive mode selection (websocket or webhook)
  • optional webhook verification token prompt (recommended for stronger callback authenticity checks)

4.12 DingTalk

[channels_config.dingtalk]
client_id = "ding-app-key"
client_secret = "ding-app-secret"
allowed_users = ["*"]

4.13 QQ

[channels_config.qq]
app_id = "qq-app-id"
app_secret = "qq-app-secret"
allowed_users = ["*"]

4.14 iMessage

[channels_config.imessage]
allowed_contacts = ["*"]

5. Validation Workflow

  1. Configure one channel with permissive allowlist ("*") for initial verification.
  2. Run:
zeroclaw onboard --channels-only
zeroclaw daemon
  1. Send a message from an expected sender.
  2. Confirm a reply arrives.
  3. Tighten allowlist from "*" to explicit IDs.

6. Troubleshooting Checklist

If a channel appears connected but does not respond:

  1. Confirm the sender identity is allowed by the correct allowlist field.
  2. Confirm bot account membership/permissions in target room/channel.
  3. Confirm tokens/secrets are valid (and not expired/revoked).
  4. Confirm transport mode assumptions:
    • polling/websocket channels do not need public inbound HTTP
    • webhook channels do need reachable HTTPS callback
  5. Restart zeroclaw daemon after config changes.

For Matrix encrypted rooms specifically, use:


7. Operations Appendix: Log Keywords Matrix

Use this appendix for fast triage. Match log keywords first, then follow the troubleshooting steps above.

7.1 Recommended capture command

RUST_LOG=info zeroclaw daemon 2>&1 | tee /tmp/zeroclaw.log

Then filter channel/gateway events:

rg -n "Matrix|Telegram|Discord|Slack|Mattermost|Signal|WhatsApp|Email|IRC|Lark|DingTalk|QQ|iMessage|Webhook|Channel" /tmp/zeroclaw.log

7.2 Keyword table

Component Startup / healthy signal Authorization / policy signal Transport / failure signal
Telegram Telegram channel listening for messages... Telegram: ignoring message from unauthorized user: Telegram poll error: / Telegram parse error: / Telegram polling conflict (409):
Discord Discord: connected and identified Discord: ignoring message from unauthorized user: Discord: received Reconnect (op 7) / Discord: received Invalid Session (op 9)
Slack Slack channel listening on # Slack: ignoring message from unauthorized user: Slack poll error: / Slack parse error:
Mattermost Mattermost channel listening on Mattermost: ignoring message from unauthorized user: Mattermost poll error: / Mattermost parse error:
Matrix Matrix channel listening on room / Matrix room ... is encrypted; E2EE decryption is enabled via matrix-sdk. Matrix whoami failed; falling back to configured session hints for E2EE session restore: / Matrix whoami failed while resolving listener user_id; using configured user_id hint: Matrix sync error: ... retrying...
Signal Signal channel listening via SSE on (allowlist checks are enforced by allowed_from) Signal SSE returned ... / Signal SSE connect error:
WhatsApp (channel) WhatsApp channel active (webhook mode). / WhatsApp Web connected successfully WhatsApp: ignoring message from unauthorized number: / WhatsApp Web: message from ... not in allowed list WhatsApp send failed: / WhatsApp Web stream error:
Webhook / WhatsApp (gateway) WhatsApp webhook verified successfully Webhook: rejected β€” not paired / invalid bearer token / Webhook: rejected request β€” invalid or missing X-Webhook-Secret / WhatsApp webhook verification failed β€” token mismatch Webhook JSON parse error:
Email Email polling every ... / Email sent to ... Blocked email from ... Email poll failed: / Email poll task panicked:
IRC IRC channel connecting to ... / IRC registered as ... (allowlist checks are enforced by allowed_users) IRC SASL authentication failed (...) / IRC server does not support SASL... / IRC nickname ... is in use, trying ...
Lark / Feishu Lark: WS connected / Lark event callback server listening on Lark WS: ignoring ... (not in allowed_users) / Lark: ignoring message from unauthorized user: Lark: ping failed, reconnecting / Lark: heartbeat timeout, reconnecting / Lark: WS read error:
DingTalk DingTalk: connected and listening for messages... DingTalk: ignoring message from unauthorized user: DingTalk WebSocket error: / DingTalk: message channel closed
QQ QQ: connected and identified QQ: ignoring C2C message from unauthorized user: / QQ: ignoring group message from unauthorized user: QQ: received Reconnect (op 7) / QQ: received Invalid Session (op 9) / QQ: message channel closed
iMessage iMessage channel listening (AppleScript bridge)... (contact allowlist enforced by allowed_contacts) iMessage poll error:

7.3 Runtime supervisor keywords

If a specific channel task crashes or exits, the channel supervisor in channels/mod.rs emits:

  • Channel <name> exited unexpectedly; restarting
  • Channel <name> error: ...; restarting
  • Channel message worker crashed:

These messages indicate automatic restart behavior is active, and you should inspect preceding logs for root cause.