From 3eb48cbea710b870b59786b22d65f15e950fd9b9 Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Tue, 13 Jan 2026 07:15:57 +0000 Subject: [PATCH] docs: complete channels rename sweep --- docs/automation/cron-jobs.md | 18 ++--- docs/automation/gmail-pubsub.md | 6 +- docs/broadcast-groups.md | 8 +-- docs/cli/gateway.md | 2 +- docs/cli/index.md | 2 +- docs/concepts/agent.md | 2 +- docs/concepts/group-messages.md | 36 +++++----- docs/concepts/groups.md | 10 +-- docs/concepts/messages.md | 28 ++++---- docs/concepts/multi-agent.md | 44 ++++++------ docs/concepts/queue.md | 8 +-- docs/concepts/session-tool.md | 26 +++---- docs/concepts/session.md | 10 +-- docs/concepts/streaming.md | 30 ++++---- docs/concepts/typing-indicators.md | 2 +- docs/gateway/configuration-examples.md | 8 +-- docs/gateway/configuration.md | 72 +++++++++---------- docs/gateway/health.md | 12 ++-- docs/gateway/heartbeat.md | 6 +- docs/gateway/index.md | 4 +- docs/gateway/security.md | 14 ++-- docs/gateway/troubleshooting.md | 12 ++-- docs/index.md | 2 +- docs/logging.md | 4 +- docs/nodes/images.md | 6 +- docs/platforms/exe-dev.md | 2 +- docs/platforms/mac/peekaboo.md | 4 +- docs/platforms/mac/release.md | 10 +-- docs/platforms/mac/xpc.md | 4 +- docs/platforms/macos.md | 2 +- docs/refactor/channel-plugin.md | 34 ++++----- docs/reference/AGENTS.default.md | 2 +- .../session-management-compaction.md | 4 +- docs/start/faq.md | 6 +- docs/start/pairing.md | 10 +-- docs/start/wizard.md | 4 +- docs/tools/index.md | 6 +- docs/tools/reactions.md | 8 +-- docs/tools/subagents.md | 6 +- docs/web/control-ui.md | 2 +- docs/web/tui.md | 2 +- docs/web/webchat.md | 4 +- 42 files changed, 241 insertions(+), 241 deletions(-) diff --git a/docs/automation/cron-jobs.md b/docs/automation/cron-jobs.md index e56d2b5a7..a7c006c7d 100644 --- a/docs/automation/cron-jobs.md +++ b/docs/automation/cron-jobs.md @@ -80,7 +80,7 @@ Key behaviors: - Prompt is prefixed with `[cron: ]` for traceability. - A summary is posted to the main session (prefix `Cron`, configurable). - `wakeMode: "now"` triggers an immediate heartbeat after posting the summary. -- If `payload.deliver: true`, output is delivered to a provider; otherwise it stays internal. +- If `payload.deliver: true`, output is delivered to a channel; otherwise it stays internal. Use isolated jobs for noisy, frequent, or "background chores" that shouldn't spam your main chat history. @@ -94,9 +94,9 @@ Common `agentTurn` fields: - `message`: required text prompt. - `model` / `thinking`: optional overrides (see below). - `timeoutSeconds`: optional timeout override. -- `deliver`: `true` to send output to a provider target. -- `provider`: `last` or a specific provider. -- `to`: provider-specific target (phone/chat/channel id). +- `deliver`: `true` to send output to a channel target. +- `channel`: `last` or a specific channel. +- `to`: channel-specific target (phone/chat/channel id). - `bestEffortDeliver`: avoid failing the job if delivery fails. Isolation options (only for `session=isolated`): @@ -116,12 +116,12 @@ Resolution priority: 2. Hook-specific defaults (e.g., `hooks.gmail.model`) 3. Agent config default -### Delivery (provider + target) -Isolated jobs can deliver output to a provider. The job payload can specify: -- `provider`: `whatsapp` / `telegram` / `discord` / `slack` / `signal` / `imessage` / `last` -- `to`: provider-specific recipient target +### Delivery (channel + target) +Isolated jobs can deliver output to a channel. The job payload can specify: +- `channel`: `whatsapp` / `telegram` / `discord` / `slack` / `signal` / `imessage` / `last` +- `to`: channel-specific recipient target -If `provider` or `to` is omitted, cron can fall back to the main session’s “last route” +If `channel` or `to` is omitted, cron can fall back to the main session’s “last route” (the last place the agent replied). Target format reminders: diff --git a/docs/automation/gmail-pubsub.md b/docs/automation/gmail-pubsub.md index 221ddb944..3c74672d4 100644 --- a/docs/automation/gmail-pubsub.md +++ b/docs/automation/gmail-pubsub.md @@ -32,7 +32,7 @@ Example hook config (enable Gmail preset mapping): ``` To deliver the Gmail summary to a chat surface, override the preset with a mapping -that sets `deliver` + optional `provider`/`to`: +that sets `deliver` + optional `channel`/`to`: ```json5 { @@ -51,7 +51,7 @@ that sets `deliver` + optional `provider`/`to`: "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, - provider: "last" + channel: "last" // to: "+15551234567" } ] @@ -59,7 +59,7 @@ that sets `deliver` + optional `provider`/`to`: } ``` -If you want a fixed channel, set `provider` + `to`. Otherwise `provider: "last"` +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 diff --git a/docs/broadcast-groups.md b/docs/broadcast-groups.md index c2f478a02..2a7b1df0d 100644 --- a/docs/broadcast-groups.md +++ b/docs/broadcast-groups.md @@ -15,9 +15,9 @@ status: experimental 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 provider). +Current scope: **WhatsApp only** (web channel). -Broadcast groups are evaluated after provider allowlists and group activation rules. In WhatsApp groups, this means broadcasts happen when Clawdbot would normally reply (for example: on mention, depending on your group settings). +Broadcast groups are evaluated after channel allowlists and group activation rules. In WhatsApp groups, this means broadcasts happen when Clawdbot would normally reply (for example: on mention, depending on your group settings). ## Use Cases @@ -152,7 +152,7 @@ Agents process in order (one waits for previous to finish): 4. **If not in broadcast list**: - Normal routing applies (first matching binding) -Note: broadcast groups do not bypass provider allowlists or group activation rules (mentions/commands/etc). They only change *which agents run* when a message is eligible for processing. +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 @@ -272,7 +272,7 @@ Broadcast groups work alongside existing routing: ```json { "bindings": [ - { "match": { "provider": "whatsapp", "peer": { "kind": "group", "id": "GROUP_A" } }, "agentId": "alfred" } + { "match": { "channel": "whatsapp", "peer": { "kind": "group", "id": "GROUP_A" } }, "agentId": "alfred" } ], "broadcast": { "GROUP_B": ["agent1", "agent2"] diff --git a/docs/cli/gateway.md b/docs/cli/gateway.md index b312f63a8..b7140c4c6 100644 --- a/docs/cli/gateway.md +++ b/docs/cli/gateway.md @@ -8,7 +8,7 @@ read_when: # Gateway CLI -The Gateway is Clawdbot’s WebSocket server (providers, nodes, sessions, hooks). +The Gateway is Clawdbot’s WebSocket server (channels, nodes, sessions, hooks). Subcommands in this page live under `clawdbot gateway …`. diff --git a/docs/cli/index.md b/docs/cli/index.md index 474361de7..490688c1f 100644 --- a/docs/cli/index.md +++ b/docs/cli/index.md @@ -29,7 +29,7 @@ This page describes the current CLI behavior. If commands change, update this do Clawdbot uses a lobster palette for CLI output. -- `accent` (#FF5A2D): headings, provider labels, primary highlights. +- `accent` (#FF5A2D): headings, labels, primary highlights. - `accentBright` (#FF7A3D): command names, emphasis. - `accentDim` (#D14A22): secondary highlight text. - `info` (#FF8A5B): informational values. diff --git a/docs/concepts/agent.md b/docs/concepts/agent.md index f071d939e..f68aa1bf9 100644 --- a/docs/concepts/agent.md +++ b/docs/concepts/agent.md @@ -92,7 +92,7 @@ Tune the boundary via `agents.defaults.blockStreamingBreak` (`text_end` vs `mess Control soft block chunking with `agents.defaults.blockStreamingChunk` (defaults to 800–1200 chars; prefers paragraph breaks, then newlines; sentences last). Coalesce streamed chunks with `agents.defaults.blockStreamingCoalesce` to reduce -single-line spam (idle-based merging before send). Non-Telegram providers require +single-line spam (idle-based merging before send). Non-Telegram channels require explicit `*.blockStreaming: true` to enable block replies. Verbose tool summaries are emitted at tool start (no debounce); Control UI streams tool output via agent events when available. diff --git a/docs/concepts/group-messages.md b/docs/concepts/group-messages.md index 7b409aef7..f26a9252d 100644 --- a/docs/concepts/group-messages.md +++ b/docs/concepts/group-messages.md @@ -3,7 +3,7 @@ summary: "Behavior and config for WhatsApp group message handling (mentionPatter read_when: - Changing group message rules or mentions --- -# Group messages (web provider) +# Group messages (WhatsApp web channel) Goal: let Clawd sit in WhatsApp groups, wake up only when pinged, and keep that thread separate from the personal DM session. @@ -18,27 +18,27 @@ Note: `agents.list[].groupChat.mentionPatterns` is now used by Telegram/Discord/ - Ephemeral/view-once: we unwrap those before extracting text/mentions, so pings inside them still trigger. - Group system prompt: on the first turn of a group session (and whenever `/activation` changes the mode) we inject a short blurb into the system prompt like `You are replying inside the WhatsApp group "". Group members: Alice (+44...), Bob (+43...), … Activation: trigger-only … Address the specific sender noted in the message context.` If metadata isn’t available we still tell the agent it’s a group chat. -## Config for Clawd UK (+447700900123) +## Config example (WhatsApp) Add a `groupChat` block to `~/.clawdbot/clawdbot.json` so display-name pings work even when WhatsApp strips the visual `@` in the text body: ```json5 { - "whatsapp": { - "groups": { - "*": { "requireMention": true } + channels: { + whatsapp: { + groups: { + "*": { requireMention: true } + } } }, - "agents": { - "list": [ + agents: { + list: [ { - "id": "main", - "groupChat": { - "historyLimit": 50, - "mentionPatterns": [ - "@?clawd", - "@?clawd\\s*uk", + id: "main", + groupChat: { + historyLimit: 50, + mentionPatterns: [ "@?clawdbot", - "\\+?447700900123" + "\\+?15555550123" ] } } @@ -48,8 +48,8 @@ Add a `groupChat` block to `~/.clawdbot/clawdbot.json` so display-name pings wor ``` Notes: -- The regexes are case-insensitive; they cover `@clawd`, `@clawd uk`, `clawdbot`, and the raw number with or without `+`/spaces. -- WhatsApp still sends canonical mentions via `mentionedJids` when someone taps the contact, so the number fallback is rarely needed but is a good safety net. +- The regexes are case-insensitive; they cover a display-name ping like `@clawdbot` and the raw number with or without `+`/spaces. +- WhatsApp still sends canonical mentions via `mentionedJids` when someone taps the contact, so the number fallback is rarely needed but is a useful safety net. ### Activation command (owner-only) @@ -60,8 +60,8 @@ Use the group chat command: Only the owner number (from `channels.whatsapp.allowFrom`, or the bot’s own E.164 when unset) can change this. Send `/status` as a standalone message in the group to see the current activation mode. ## How to use -1) Add Clawd UK (`+447700900123`) to the group. -2) Say `@clawd …` (or `@clawd uk`, `@clawdbot`, or include the number). Only allowlisted senders can trigger it unless you set `groupPolicy: "open"`. +1) Add your WhatsApp account (the one running Clawdbot) to the group. +2) Say `@clawdbot …` (or include the number). Only allowlisted senders can trigger it unless you set `groupPolicy: "open"`. 3) The agent prompt will include recent group context plus the trailing `[from: …]` marker so it can address the right person. 4) Session-level directives (`/verbose on`, `/think high`, `/new` or `/reset`, `/compact`) apply only to that group’s session; send them as standalone messages so they register. Your personal DM session remains independent. diff --git a/docs/concepts/groups.md b/docs/concepts/groups.md index ace3e965f..cc6e82797 100644 --- a/docs/concepts/groups.md +++ b/docs/concepts/groups.md @@ -41,17 +41,17 @@ If you want... | Only you can trigger in groups | `groupPolicy: "allowlist"`, `groupAllowFrom: ["+1555..."]` | ## Session keys -- Group sessions use `agent:::group:` session keys (rooms/channels use `agent:::channel:`). +- Group sessions use `agent:::group:` session keys (rooms/channels use `agent:::channel:`). - Telegram forum topics add `:topic:` to the group id so each topic has its own session. - Direct chats use the main session (or per-sender if configured). - Heartbeats are skipped for group sessions. ## Display labels -- UI labels use `displayName` when available, formatted as `:`. +- UI labels use `displayName` when available, formatted as `:`. - `#room` is reserved for rooms/channels; group chats use `g-` (lowercase, spaces -> `-`, keep `#@+._-`). ## Group policy -Control how group/room messages are handled per provider: +Control how group/room messages are handled per channel: ```json5 { @@ -107,7 +107,7 @@ Notes: Quick mental model (evaluation order for group messages): 1) `groupPolicy` (open/disabled/allowlist) -2) group allowlists (`*.groups`, `*.groupAllowFrom`, provider-specific allowlist) +2) group allowlists (`*.groups`, `*.groupAllowFrom`, channel-specific allowlist) 3) mention gating (`requireMention`, `/activation`) ## Mention gating (default) @@ -155,7 +155,7 @@ Notes: - Per-agent override: `agents.list[].groupChat.mentionPatterns` (useful when multiple agents share a group). - Mention gating is only enforced when mention detection is possible (native mentions or `mentionPatterns` are configured). - Discord defaults live in `channels.discord.guilds."*"` (overridable per guild/channel). -- Group history context is wrapped uniformly across providers; use `messages.groupChat.historyLimit` for the global default and `.historyLimit` (or `.accounts.*.historyLimit`) for overrides. Set `0` to disable. +- Group history context is wrapped uniformly across channels; use `messages.groupChat.historyLimit` for the global default and `channels..historyLimit` (or `channels..accounts.*.historyLimit`) for overrides. Set `0` to disable. ## Group allowlists When `channels.whatsapp.groups`, `channels.telegram.groups`, or `channels.imessage.groups` is configured, the keys act as a group allowlist. Use `"*"` to allow all groups while still setting default mention behavior. diff --git a/docs/concepts/messages.md b/docs/concepts/messages.md index ef16ea1ca..959c62ca6 100644 --- a/docs/concepts/messages.md +++ b/docs/concepts/messages.md @@ -17,20 +17,20 @@ Inbound message -> routing/bindings -> session key -> queue (if a run is active) -> agent run (streaming + tools) - -> outbound replies (provider limits + chunking) + -> outbound replies (channel limits + chunking) ``` Key knobs live in configuration: - `messages.*` for prefixes, queueing, and group behavior. - `agents.defaults.*` for block streaming and chunking defaults. -- Provider overrides (`channels.whatsapp.*`, `channels.telegram.*`, etc.) for caps and streaming toggles. +- Channel overrides (`channels.whatsapp.*`, `channels.telegram.*`, etc.) for caps and streaming toggles. See [Configuration](/gateway/configuration) for full schema. ## Inbound dedupe -Providers can redeliver the same message after reconnects. Clawdbot keeps a -short-lived cache keyed by provider/account/peer/session/message id so duplicate +Channels can redeliver the same message after reconnects. Clawdbot keeps a +short-lived cache keyed by channel/account/peer/session/message id so duplicate deliveries do not trigger another agent run. ## Sessions and devices @@ -40,7 +40,7 @@ Sessions are owned by the gateway, not by clients. - Groups/channels get their own session keys. - The session store and transcripts live on the gateway host. -Multiple devices/providers can map to the same session, but history is not fully +Multiple devices/channels can map to the same session, but history is not fully synced back to every client. Recommendation: use one primary device for long conversations to avoid divergent context. The Control UI and TUI always show the gateway-backed session transcript, so they are the source of truth. @@ -50,20 +50,20 @@ Details: [Session management](/concepts/session). ## Inbound bodies and history context Clawdbot separates the **prompt body** from the **command body**: -- `Body`: prompt text sent to the agent. This may include provider envelopes and +- `Body`: prompt text sent to the agent. This may include channel envelopes and optional history wrappers. - `CommandBody`: raw user text for directive/command parsing. - `RawBody`: legacy alias for `CommandBody` (kept for compatibility). -When a provider supplies history, it uses a shared wrapper: +When a channel supplies history, it uses a shared wrapper: - `[Chat messages since your last reply - for context]` - `[Current message - respond to this]` Directive stripping only applies to the **current message** section so history -remains intact. Providers that wrap history should set `CommandBody` (or +remains intact. Channels that wrap history should set `CommandBody` (or `RawBody`) to the original message text and keep `Body` as the combined prompt. History buffers are configurable via `messages.groupChat.historyLimit` (global -default) and per-provider overrides like `channels.slack.historyLimit` or +default) and per-channel overrides like `channels.slack.historyLimit` or `channels.telegram.accounts..historyLimit` (set `0` to disable). ## Queueing and followups @@ -71,7 +71,7 @@ default) and per-provider overrides like `channels.slack.historyLimit` or If a run is already active, inbound messages can be queued, steered into the current run, or collected for a followup turn. -- Configure via `messages.queue` (and `messages.queue.byProvider`). +- Configure via `messages.queue` (and `messages.queue.byChannel`). - Modes: `interrupt`, `steer`, `followup`, `collect`, plus backlog variants. Details: [Queueing](/concepts/queue). @@ -79,7 +79,7 @@ Details: [Queueing](/concepts/queue). ## Streaming, chunking, and batching Block streaming sends partial replies as the model produces text blocks. -Chunking respects provider text limits and avoids splitting fenced code. +Chunking respects channel text limits and avoids splitting fenced code. Key settings: - `agents.defaults.blockStreamingDefault` (`on|off`, default off) @@ -87,7 +87,7 @@ Key settings: - `agents.defaults.blockStreamingChunk` (`minChars|maxChars|breakPreference`) - `agents.defaults.blockStreamingCoalesce` (idle-based batching) - `agents.defaults.humanDelay` (human-like pause between block replies) -- Provider overrides: `*.blockStreaming` and `*.blockStreamingCoalesce` (non-Telegram providers require explicit `*.blockStreaming: true`) +- Channel overrides: `*.blockStreaming` and `*.blockStreamingCoalesce` (non-Telegram channels require explicit `*.blockStreaming: true`) Details: [Streaming + chunking](/concepts/streaming). @@ -104,6 +104,6 @@ Details: [Thinking + reasoning directives](/tools/thinking) and [Token use](/tok Outbound message formatting is centralized in `messages`: - `messages.responsePrefix` (outbound prefix) and `channels.whatsapp.messagePrefix` (WhatsApp inbound prefix) -- Reply threading via `replyToMode` and per-provider defaults +- Reply threading via `replyToMode` and per-channel defaults -Details: [Configuration](/gateway/configuration#messages) and provider docs. +Details: [Configuration](/gateway/configuration#messages) and channel docs. diff --git a/docs/concepts/multi-agent.md b/docs/concepts/multi-agent.md index 7c8967510..003db7f8c 100644 --- a/docs/concepts/multi-agent.md +++ b/docs/concepts/multi-agent.md @@ -1,5 +1,5 @@ --- -summary: "Multi-agent routing: isolated agents, provider accounts, and bindings" +summary: "Multi-agent routing: isolated agents, channel accounts, and bindings" title: Multi-Agent Routing read_when: "You want multiple isolated agents (workspaces + auth) in one gateway process." status: active @@ -7,7 +7,7 @@ status: active # Multi-Agent Routing -Goal: multiple *isolated* agents (separate workspace + `agentDir` + sessions), plus multiple provider accounts (e.g. two WhatsApps) in one running Gateway. Inbound is routed to an agent via bindings. +Goal: multiple *isolated* agents (separate workspace + `agentDir` + sessions), plus multiple channel accounts (e.g. two WhatsApps) in one running Gateway. Inbound is routed to an agent via bindings. ## What is “one agent”? @@ -64,7 +64,7 @@ clawdbot agents list --bindings With **multiple agents**, each `agentId` becomes a **fully isolated persona**: -- **Different phone numbers/accounts** (per provider `accountId`). +- **Different phone numbers/accounts** (per channel `accountId`). - **Different personalities** (per-agent workspace files like `AGENTS.md` and `SOUL.md`). - **Separate auth + sessions** (no cross-talk unless explicitly enabled). @@ -87,8 +87,8 @@ Example: ] }, bindings: [ - { agentId: "alex", match: { provider: "whatsapp", peer: { kind: "dm", id: "+15551230001" } } }, - { agentId: "mia", match: { provider: "whatsapp", peer: { kind: "dm", id: "+15551230002" } } } + { agentId: "alex", match: { channel: "whatsapp", peer: { kind: "dm", id: "+15551230001" } } }, + { agentId: "mia", match: { channel: "whatsapp", peer: { kind: "dm", id: "+15551230002" } } } ], channels: { whatsapp: { @@ -110,21 +110,21 @@ Bindings are **deterministic** and **most-specific wins**: 1. `peer` match (exact DM/group/channel id) 2. `guildId` (Discord) 3. `teamId` (Slack) -4. `accountId` match for a provider -5. provider-level match (`accountId: "*"`) +4. `accountId` match for a channel +5. channel-level match (`accountId: "*"`) 6. fallback to default agent (`agents.list[].default`, else first list entry, default: `main`) ## Multiple accounts / phone numbers -Providers that support **multiple accounts** (e.g. WhatsApp) use `accountId` to identify +Channels that support **multiple accounts** (e.g. WhatsApp) use `accountId` to identify each login. Each `accountId` can be routed to a different agent, so one server can host multiple phone numbers without mixing sessions. ## Concepts - `agentId`: one “brain” (workspace, per-agent auth, per-agent session store). -- `accountId`: one provider account instance (e.g. WhatsApp account `"personal"` vs `"biz"`). -- `binding`: routes inbound messages to an `agentId` by `(provider, accountId, peer)` and optionally guild/team ids. +- `accountId`: one channel account instance (e.g. WhatsApp account `"personal"` vs `"biz"`). +- `binding`: routes inbound messages to an `agentId` by `(channel, accountId, peer)` and optionally guild/team ids. - Direct chats collapse to `agent::` (per-agent “main”; `session.mainKey`). ## Example: two WhatsApps → two agents @@ -153,14 +153,14 @@ multiple phone numbers without mixing sessions. // Deterministic routing: first match wins (most-specific first). bindings: [ - { agentId: "home", match: { provider: "whatsapp", accountId: "personal" } }, - { agentId: "work", match: { provider: "whatsapp", accountId: "biz" } }, + { agentId: "home", match: { channel: "whatsapp", accountId: "personal" } }, + { agentId: "work", match: { channel: "whatsapp", accountId: "biz" } }, // Optional per-peer override (example: send a specific group to work agent). { agentId: "work", match: { - provider: "whatsapp", + channel: "whatsapp", accountId: "personal", peer: { kind: "group", id: "1203630...@g.us" }, }, @@ -194,7 +194,7 @@ multiple phone numbers without mixing sessions. ## Example: WhatsApp daily chat + Telegram deep work -Split by provider: route WhatsApp to a fast everyday agent and Telegram to an Opus agent. +Split by channel: route WhatsApp to a fast everyday agent and Telegram to an Opus agent. ```json5 { @@ -215,17 +215,17 @@ Split by provider: route WhatsApp to a fast everyday agent and Telegram to an Op ] }, bindings: [ - { agentId: "chat", match: { provider: "whatsapp" } }, - { agentId: "opus", match: { provider: "telegram" } } + { agentId: "chat", match: { channel: "whatsapp" } }, + { agentId: "opus", match: { channel: "telegram" } } ] } ``` Notes: -- If you have multiple accounts for a provider, add `accountId` to the binding (for example `{ provider: "whatsapp", accountId: "personal" }`). -- To route a single DM/group to Opus while keeping the rest on chat, add a `match.peer` binding for that peer; peer matches always win over provider-wide rules. +- If you have multiple accounts for a channel, add `accountId` to the binding (for example `{ channel: "whatsapp", accountId: "personal" }`). +- To route a single DM/group to Opus while keeping the rest on chat, add a `match.peer` binding for that peer; peer matches always win over channel-wide rules. -## Example: same provider, one peer to Opus +## Example: same channel, one peer to Opus Keep WhatsApp on the fast agent, but route one DM to Opus: @@ -238,13 +238,13 @@ Keep WhatsApp on the fast agent, but route one DM to Opus: ] }, bindings: [ - { agentId: "opus", match: { provider: "whatsapp", peer: { kind: "dm", id: "+15551234567" } } }, - { agentId: "chat", match: { provider: "whatsapp" } } + { agentId: "opus", match: { channel: "whatsapp", peer: { kind: "dm", id: "+15551234567" } } }, + { agentId: "chat", match: { channel: "whatsapp" } } ] } ``` -Peer bindings always win, so keep them above the provider-wide rule. +Peer bindings always win, so keep them above the channel-wide rule. ## Per-Agent Sandbox and Tool Configuration diff --git a/docs/concepts/queue.md b/docs/concepts/queue.md index d5485a0ae..31b1f344b 100644 --- a/docs/concepts/queue.md +++ b/docs/concepts/queue.md @@ -18,7 +18,7 @@ We now serialize command-based auto-replies (WhatsApp Web listener) through a ti - When verbose logging is enabled, queued commands emit a short notice if they waited more than ~2s before starting. - Typing indicators (`onReplyStart`) still fire immediately on enqueue so user experience is unchanged while we wait our turn. -## Queue modes (per provider) +## Queue modes (per channel) Inbound messages can steer the current run, wait for a followup turn, or do both: - `steer`: inject immediately into the current run (cancels pending tool calls after the next tool boundary). If not streaming, falls back to followup. - `followup`: enqueue for the next agent turn after the current run ends. @@ -30,12 +30,12 @@ Inbound messages can steer the current run, wait for a followup turn, or do both Steer-backlog means you can get a followup response after the steered run, so streaming surfaces can look like duplicates. Prefer `collect`/`steer` if you want one response per inbound message. -Send `/queue collect` as a standalone command (per-session) or set `messages.queue.byProvider.discord: "collect"`. +Send `/queue collect` as a standalone command (per-session) or set `messages.queue.byChannel.discord: "collect"`. Defaults (when unset in config): - All surfaces → `collect` -Configure globally or per provider via `messages.queue`: +Configure globally or per channel via `messages.queue`: ```json5 { @@ -45,7 +45,7 @@ Configure globally or per provider via `messages.queue`: debounceMs: 1000, cap: 20, drop: "summarize", - byProvider: { discord: "collect" } + byChannel: { discord: "collect" } } } } diff --git a/docs/concepts/session-tool.md b/docs/concepts/session-tool.md index 947292d02..9c93b0619 100644 --- a/docs/concepts/session-tool.md +++ b/docs/concepts/session-tool.md @@ -16,7 +16,7 @@ Goal: small, hard-to-misuse tool set so agents can list sessions, fetch history, ## Key Model - Main direct chat bucket is always the literal key `"main"` (resolved to the current agent’s main key). -- Group chats use `agent:::group:` or `agent:::channel:` (pass the full key). +- Group chats use `agent:::group:` or `agent:::channel:` (pass the full key). - Cron jobs use `cron:`. - Hooks use `hook:` unless explicitly set. - Node bridge uses `node-` unless explicitly set. @@ -40,14 +40,14 @@ Behavior: Row shape (JSON): - `key`: session key (string) - `kind`: `main | group | cron | hook | node | other` -- `provider`: `whatsapp | telegram | discord | signal | imessage | webchat | internal | unknown` +- `channel`: `whatsapp | telegram | discord | signal | imessage | webchat | internal | unknown` - `displayName` (group display label if available) - `updatedAt` (ms) - `sessionId` - `model`, `contextTokens`, `totalTokens` - `thinkingLevel`, `verboseLevel`, `systemSent`, `abortedLastRun` - `sendPolicy` (session override if set) -- `lastProvider`, `lastTo` +- `lastChannel`, `lastTo` - `transcriptPath` (best-effort path derived from store dir + sessionId) - `messages?` (only when `messageLimit > 0`) @@ -85,17 +85,17 @@ Behavior: - Max turns is `session.agentToAgent.maxPingPongTurns` (0–5, default 5). - Once the loop ends, Clawdbot runs the **agent‑to‑agent announce step** (target agent only): - Reply exactly `ANNOUNCE_SKIP` to stay silent. - - Any other reply is sent to the target provider. + - Any other reply is sent to the target channel. - Announce step includes the original request + round‑1 reply + latest ping‑pong reply. -## Provider Field -- For groups, `provider` is the provider recorded on the session entry. -- For direct chats, `provider` maps from `lastProvider`. -- For cron/hook/node, `provider` is `internal`. -- If missing, `provider` is `unknown`. +## Channel Field +- For groups, `channel` is the channel recorded on the session entry. +- For direct chats, `channel` maps from `lastChannel`. +- For cron/hook/node, `channel` is `internal`. +- If missing, `channel` is `unknown`. ## Security / Send Policy -Policy-based blocking by provider/chat type (not per session id). +Policy-based blocking by channel/chat type (not per session id). ```json { @@ -103,7 +103,7 @@ Policy-based blocking by provider/chat type (not per session id). "sendPolicy": { "rules": [ { - "match": { "provider": "discord", "chatType": "group" }, + "match": { "channel": "discord", "chatType": "group" }, "action": "deny" } ], @@ -122,7 +122,7 @@ Enforcement points: - auto-reply delivery logic ## sessions_spawn -Spawn a sub-agent run in an isolated session and announce the result back to the requester chat provider. +Spawn a sub-agent run in an isolated session and announce the result back to the requester chat channel. Parameters: - `task` (required) @@ -143,7 +143,7 @@ Behavior: - Sub-agents default to the full tool set **minus session tools** (configurable via `tools.subagents.tools`). - Sub-agents are not allowed to call `sessions_spawn` (no sub-agent → sub-agent spawning). - Always non-blocking: returns `{ status: "accepted", runId, childSessionKey }` immediately. -- After completion, Clawdbot runs a sub-agent **announce step** and posts the result to the requester chat provider. +- After completion, Clawdbot runs a sub-agent **announce step** and posts the result to the requester chat channel. - Reply exactly `ANNOUNCE_SKIP` during the announce step to stay silent. - Sub-agent sessions are auto-archived after `agents.defaults.subagents.archiveAfterMinutes` (default: 60). - Announce replies include a stats line (runtime, tokens, sessionKey/sessionId, transcript path, and optional cost). diff --git a/docs/concepts/session.md b/docs/concepts/session.md index 5aae678e9..27880e0df 100644 --- a/docs/concepts/session.md +++ b/docs/concepts/session.md @@ -18,7 +18,7 @@ All session state is **owned by the gateway** (the “master” Clawdbot). UI cl - Store file: `~/.clawdbot/agents//sessions/sessions.json` (per agent). - Transcripts: `~/.clawdbot/agents//sessions/.jsonl` (Telegram topic sessions use `.../-topic-.jsonl`). - The store is a map `sessionKey -> { sessionId, updatedAt, ... }`. Deleting entries is safe; they are recreated on demand. -- Group entries may include `displayName`, `provider`, `subject`, `room`, and `space` to label sessions in UIs. +- Group entries may include `displayName`, `channel`, `subject`, `room`, and `space` to label sessions in UIs. - Clawdbot does **not** read legacy Pi/Tau session folders. ## Session pruning @@ -33,11 +33,11 @@ the workspace is writable. See [Memory](/concepts/memory) and ## Mapping transports → session keys - Direct chats collapse to the per-agent primary key: `agent::`. - - Multiple phone numbers and providers can map to the same agent main key; they act as transports into one conversation. -- Group chats isolate state: `agent:::group:` (rooms/channels use `agent:::channel:`). + - Multiple phone numbers and channels can map to the same agent main key; they act as transports into one conversation. +- Group chats isolate state: `agent:::group:` (rooms/channels use `agent:::channel:`). - Telegram forum topics append `:topic:` to the group id for isolation. - Legacy `group:` keys are still recognized for migration. - - Inbound contexts may still use `group:`; the provider is inferred from `Provider` and normalized to the canonical `agent:::group:` form. +- Inbound contexts may still use `group:`; the channel is inferred from `Provider` and normalized to the canonical `agent:::group:` form. - Other sources: - Cron jobs: `cron:` - Webhooks: `hook:` (unless explicitly set by the hook) @@ -56,7 +56,7 @@ Block delivery for specific session types without listing individual ids. session: { sendPolicy: { rules: [ - { action: "deny", match: { provider: "discord", chatType: "group" } }, + { action: "deny", match: { channel: "discord", chatType: "group" } }, { action: "deny", match: { keyPrefix: "cron:" } } ], default: "allow" diff --git a/docs/concepts/streaming.md b/docs/concepts/streaming.md index 94036428d..ae4fecc85 100644 --- a/docs/concepts/streaming.md +++ b/docs/concepts/streaming.md @@ -1,19 +1,19 @@ --- summary: "Streaming + chunking behavior (block replies, draft streaming, limits)" read_when: - - Explaining how streaming or chunking works on providers - - Changing block streaming or provider chunking behavior + - Explaining how streaming or chunking works on channels + - Changing block streaming or channel chunking behavior - Debugging duplicate/early block replies or draft streaming --- # Streaming + chunking Clawdbot has two separate “streaming” layers: -- **Block streaming (providers):** emit completed **blocks** as the assistant writes. These are normal provider messages (not token deltas). +- **Block streaming (channels):** emit completed **blocks** as the assistant writes. These are normal channel messages (not token deltas). - **Token-ish streaming (Telegram only):** update a **draft bubble** with partial text while generating; final message is sent at the end. -There is **no real token streaming** to external provider messages today. Telegram draft streaming is the only partial-stream surface. +There is **no real token streaming** to external channel messages today. Telegram draft streaming is the only partial-stream surface. -## Block streaming (provider messages) +## Block streaming (channel messages) Block streaming sends assistant output in coarse chunks as it becomes available. @@ -24,20 +24,20 @@ Model output │ └─ chunker emits blocks as buffer grows └─ (blockStreamingBreak=message_end) └─ chunker flushes at message_end - └─ provider send (block replies) + └─ channel send (block replies) ``` Legend: - `text_delta/events`: model stream events (may be sparse for non-streaming models). - `chunker`: `EmbeddedBlockChunker` applying min/max bounds + break preference. -- `provider send`: actual outbound messages (block replies). +- `channel send`: actual outbound messages (block replies). **Controls:** - `agents.defaults.blockStreamingDefault`: `"on"`/`"off"` (default off). -- Provider overrides: `*.blockStreaming` (and per-account variants) to force `"on"`/`"off"` per provider. +- Channel overrides: `*.blockStreaming` (and per-account variants) to force `"on"`/`"off"` per channel. - `agents.defaults.blockStreamingBreak`: `"text_end"` or `"message_end"`. - `agents.defaults.blockStreamingChunk`: `{ minChars, maxChars, breakPreference? }`. - `agents.defaults.blockStreamingCoalesce`: `{ minChars?, maxChars?, idleMs? }` (merge streamed blocks before send). -- Provider hard cap: `*.textChunkLimit` (e.g., `channels.whatsapp.textChunkLimit`). +- Channel hard cap: `*.textChunkLimit` (e.g., `channels.whatsapp.textChunkLimit`). - Discord soft cap: `channels.discord.maxLinesPerMessage` (default 17) splits tall replies to avoid UI clipping. **Boundary semantics:** @@ -54,7 +54,7 @@ Block chunking is implemented by `EmbeddedBlockChunker`: - **Break preference:** `paragraph` → `newline` → `sentence` → `whitespace` → hard break. - **Code fences:** never split inside fences; when forced at `maxChars`, close + reopen the fence to keep Markdown valid. -`maxChars` is clamped to the provider `textChunkLimit`, so you can’t exceed per-provider caps. +`maxChars` is clamped to the channel `textChunkLimit`, so you can’t exceed per-channel caps. ## Coalescing (merge streamed blocks) @@ -68,7 +68,7 @@ progressive output. (final flush always sends remaining text). - Joiner is derived from `blockStreamingChunk.breakPreference` (`paragraph` → `\n\n`, `newline` → `\n`, `sentence` → space). -- Provider overrides are available via `*.blockStreamingCoalesce` (including per-account configs). +- Channel overrides are available via `*.blockStreamingCoalesce` (including per-account configs). - Default coalesce `minChars` is bumped to 1500 for Signal/Slack/Discord unless overridden. ## Human-like pacing between blocks @@ -84,11 +84,11 @@ more natural. ## “Stream chunks or everything” This maps to: -- **Stream chunks:** `blockStreamingDefault: "on"` + `blockStreamingBreak: "text_end"` (emit as you go). Non-Telegram providers also need `*.blockStreaming: true`. +- **Stream chunks:** `blockStreamingDefault: "on"` + `blockStreamingBreak: "text_end"` (emit as you go). Non-Telegram channels also need `*.blockStreaming: true`. - **Stream everything at end:** `blockStreamingBreak: "message_end"` (flush once, possibly multiple chunks if very long). - **No block streaming:** `blockStreamingDefault: "off"` (only final reply). -**Provider note:** For non-Telegram providers, block streaming is **off unless** +**Channel note:** For non-Telegram channels, block streaming is **off unless** `*.blockStreaming` is explicitly set to `true`. Telegram can stream drafts (`channels.telegram.streamMode`) without block replies. @@ -97,14 +97,14 @@ Config location reminder: the `blockStreaming*` defaults live under ## Telegram draft streaming (token-ish) -Telegram is the only provider with draft streaming: +Telegram is the only channel with draft streaming: - Uses Bot API `sendMessageDraft` in **private chats with topics**. - `channels.telegram.streamMode: "partial" | "block" | "off"`. - `partial`: draft updates with the latest stream text. - `block`: draft updates in chunked blocks (same chunker rules). - `off`: no draft streaming. - Draft chunk config (only for `streamMode: "block"`): `channels.telegram.draftChunk` (defaults: `minChars: 200`, `maxChars: 800`). -- Draft streaming is separate from block streaming; block replies are off by default and only enabled by `*.blockStreaming: true` on non-Telegram providers. +- Draft streaming is separate from block streaming; block replies are off by default and only enabled by `*.blockStreaming: true` on non-Telegram channels. - Final reply is still a normal message. - `/reasoning stream` writes reasoning into the draft bubble (Telegram only). diff --git a/docs/concepts/typing-indicators.md b/docs/concepts/typing-indicators.md index 9143eb8ef..973f6fee5 100644 --- a/docs/concepts/typing-indicators.md +++ b/docs/concepts/typing-indicators.md @@ -5,7 +5,7 @@ read_when: --- # Typing indicators -Typing indicators are sent to the chat provider while a run is active. Use +Typing indicators are sent to the chat channel while a run is active. Use `agents.defaults.typingMode` to control **when** typing starts and `typingIntervalSeconds` to control **how often** it refreshes. diff --git a/docs/gateway/configuration-examples.md b/docs/gateway/configuration-examples.md index 9d19cdfe1..2b3999779 100644 --- a/docs/gateway/configuration-examples.md +++ b/docs/gateway/configuration-examples.md @@ -110,7 +110,7 @@ Save to `~/.clawdbot/clawdbot.json` and you can DM the bot from that number. debounceMs: 1000, cap: 20, drop: "summarize", - byProvider: { + byChannel: { whatsapp: "collect", telegram: "collect", discord: "collect", @@ -143,12 +143,12 @@ Save to `~/.clawdbot/clawdbot.json` and you can DM the bot from that number. sendPolicy: { default: "allow", rules: [ - { action: "deny", match: { provider: "discord", chatType: "group" } } + { action: "deny", match: { channel: "discord", chatType: "group" } } ] } }, - // Providers + // Channels channels: { whatsapp: { dmPolicy: "pairing", @@ -345,7 +345,7 @@ Save to `~/.clawdbot/clawdbot.json` and you can DM the bot from that number. messageTemplate: "From: {{messages[0].from}}\nSubject: {{messages[0].subject}}", textTemplate: "{{messages[0].snippet}}", deliver: true, - provider: "last", + channel: "last", to: "+15555550123", thinking: "low", timeoutSeconds: 300, diff --git a/docs/gateway/configuration.md b/docs/gateway/configuration.md index 0944c87da..219547f3a 100644 --- a/docs/gateway/configuration.md +++ b/docs/gateway/configuration.md @@ -376,7 +376,7 @@ Controls how WhatsApp direct chats (DMs) are handled: - `"open"`: allow all inbound DMs (**requires** `channels.whatsapp.allowFrom` to include `"*"`) - `"disabled"`: ignore all inbound DMs -Pairing codes expire after 1 hour; the bot only sends a pairing code when a new request is created. Pending DM pairing requests are capped at **3 per provider** by default. +Pairing codes expire after 1 hour; the bot only sends a pairing code when a new request is created. Pending DM pairing requests are capped at **3 per channel** by default. Pairing approvals: - `clawdbot pairing list whatsapp` @@ -428,7 +428,7 @@ Notes: ### `channels.telegram.accounts` / `channels.discord.accounts` / `channels.slack.accounts` / `channels.signal.accounts` / `channels.imessage.accounts` -Run multiple accounts per provider (each account has its own `accountId` and optional `name`): +Run multiple accounts per channel (each account has its own `accountId` and optional `name`): ```json5 { @@ -452,7 +452,7 @@ Run multiple accounts per provider (each account has its own `accountId` and opt Notes: - `default` is used when `accountId` is omitted (CLI + routing). - Env tokens only apply to the **default** account. -- Base provider settings (group policy, mention gating, etc.) apply to all accounts unless overridden per account. +- Base channel settings (group policy, mention gating, etc.) apply to all accounts unless overridden per account. - Use `bindings[].match.accountId` to route each account to a different agents.defaults. ### Group chat mention gating (`agents.list[].groupChat` + `messages.groupChat`) @@ -477,7 +477,7 @@ Group messages default to **require mention** (either metadata mention or regex } ``` -`messages.groupChat.historyLimit` sets the global default for group history context. Providers can override with `channels..historyLimit` (or `channels..accounts.*.historyLimit` for multi-account). Set `0` to disable history wrapping. +`messages.groupChat.historyLimit` sets the global default for group history context. Channels can override with `channels..historyLimit` (or `channels..accounts.*.historyLimit` for multi-account). Set `0` to disable history wrapping. Per-agent override (takes precedence when set, even `[]`): ```json5 @@ -491,7 +491,7 @@ Per-agent override (takes precedence when set, even `[]`): } ``` -Mention gating defaults live per provider (`channels.whatsapp.groups`, `channels.telegram.groups`, `channels.imessage.groups`, `channels.discord.guilds`). When `*.groups` is set, it also acts as a group allowlist; include `"*"` to allow all groups. +Mention gating defaults live per channel (`channels.whatsapp.groups`, `channels.telegram.groups`, `channels.imessage.groups`, `channels.discord.guilds`). When `*.groups` is set, it also acts as a group allowlist; include `"*"` to allow all groups. To respond **only** to specific text triggers (ignoring native @-mentions): ```json5 @@ -517,7 +517,7 @@ To respond **only** to specific text triggers (ignoring native @-mentions): } ``` -### Group policy (per provider) +### Group policy (per channel) Use `channels.*.groupPolicy` to control whether group/room messages are accepted at all: @@ -602,17 +602,17 @@ Inbound messages are routed to an agent via bindings. - `deny`: array of denied tool names (deny wins) - `agents.defaults`: shared agent defaults (model, workspace, sandbox, etc.). - `bindings[]`: routes inbound messages to an `agentId`. - - `match.provider` (required) + - `match.channel` (required) - `match.accountId` (optional; `*` = any account; omitted = default account) - `match.peer` (optional; `{ kind: dm|group|channel, id }`) - - `match.guildId` / `match.teamId` (optional; provider-specific) + - `match.guildId` / `match.teamId` (optional; channel-specific) Deterministic match order: 1) `match.peer` 2) `match.guildId` 3) `match.teamId` 4) `match.accountId` (exact, no peer/guild/team) -5) `match.accountId: "*"` (provider-wide, no peer/guild/team) +5) `match.accountId: "*"` (channel-wide, no peer/guild/team) 6) default agent (`agents.list[].default`, else first list entry, else `"main"`) Within each match tier, the first matching entry in `bindings` wins. @@ -700,8 +700,8 @@ Example: two WhatsApp accounts → two agents: ] }, bindings: [ - { agentId: "home", match: { provider: "whatsapp", accountId: "personal" } }, - { agentId: "work", match: { provider: "whatsapp", accountId: "biz" } } + { agentId: "home", match: { channel: "whatsapp", accountId: "personal" } }, + { agentId: "work", match: { channel: "whatsapp", accountId: "biz" } } ], channels: { whatsapp: { @@ -741,7 +741,7 @@ Controls how inbound messages behave when an agent run is already active. debounceMs: 1000, cap: 20, drop: "summarize", // old | new | summarize - byProvider: { + byChannel: { whatsapp: "collect", telegram: "collect", discord: "collect", @@ -784,9 +784,9 @@ Notes: - `commands.restart: true` enables `/restart` and the gateway tool restart action. - `commands.useAccessGroups: false` allows commands to bypass access-group allowlists/policies. -### `web` (WhatsApp web provider) +### `web` (WhatsApp web channel runtime) -WhatsApp runs through the gateway’s web provider. It starts automatically when a linked session exists. +WhatsApp runs through the gateway’s web channel (Baileys Web). It starts automatically when a linked session exists. Set `web.enabled: false` to keep it off by default. ```json5 @@ -1483,8 +1483,8 @@ Example (tuned): Block streaming: - `agents.defaults.blockStreamingDefault`: `"on"`/`"off"` (default off). -- Provider overrides: `*.blockStreaming` (and per-account variants) to force block streaming on/off. - Non-Telegram providers require an explicit `*.blockStreaming: true` to enable block replies. +- Channel overrides: `*.blockStreaming` (and per-account variants) to force block streaming on/off. + Non-Telegram channels require an explicit `*.blockStreaming: true` to enable block replies. - `agents.defaults.blockStreamingBreak`: `"text_end"` or `"message_end"` (default: text_end). - `agents.defaults.blockStreamingChunk`: soft chunking for streamed blocks. Defaults to 800–1200 chars, prefers paragraph breaks (`\n\n`), then newlines, then sentences. @@ -1496,9 +1496,9 @@ Block streaming: ``` - `agents.defaults.blockStreamingCoalesce`: merge streamed blocks before sending. Defaults to `{ idleMs: 1000 }` and inherits `minChars` from `blockStreamingChunk` - with `maxChars` capped to the provider text limit. Signal/Slack/Discord default + with `maxChars` capped to the channel text limit. Signal/Slack/Discord default to `minChars: 1500` unless overridden. - Provider overrides: `channels.whatsapp.blockStreamingCoalesce`, `channels.telegram.blockStreamingCoalesce`, + Channel overrides: `channels.whatsapp.blockStreamingCoalesce`, `channels.telegram.blockStreamingCoalesce`, `channels.discord.blockStreamingCoalesce`, `channels.slack.blockStreamingCoalesce`, `channels.signal.blockStreamingCoalesce`, `channels.imessage.blockStreamingCoalesce`, `channels.msteams.blockStreamingCoalesce` (and per-account variants). - `agents.defaults.humanDelay`: randomized pause between **block replies** after the first. @@ -1532,8 +1532,8 @@ Z.AI models are available as `zai/` (e.g. `zai/glm-4.7`) and require `30m`. Set `0m` to disable. - `model`: optional override model for heartbeat runs (`provider/model`). - `includeReasoning`: when `true`, heartbeats will also deliver the separate `Reasoning:` message when available (same shape as `/reasoning on`). Default: `false`. -- `target`: optional delivery provider (`last`, `whatsapp`, `telegram`, `discord`, `slack`, `signal`, `imessage`, `none`). Default: `last`. -- `to`: optional recipient override (provider-specific id, e.g. E.164 for WhatsApp, chat id for Telegram). +- `target`: optional delivery channel (`last`, `whatsapp`, `telegram`, `discord`, `slack`, `signal`, `imessage`, `none`). Default: `last`. +- `to`: optional recipient override (channel-specific id, e.g. E.164 for WhatsApp, chat id for Telegram). - `prompt`: optional override for the heartbeat body (default: `Read HEARTBEAT.md if exists. Consider outstanding tasks. Checkup sometimes on your human during (user local) day time.`). Overrides are sent verbatim; include a `Read HEARTBEAT.md if exists` line if you still want the file read. - `ackMaxChars`: max chars allowed after `HEARTBEAT_OK` before delivery (default: 300). @@ -1606,7 +1606,7 @@ Tool groups (shorthands) work in **global** and **per-agent** tool policies: `tools.elevated` controls elevated (host) exec access: - `enabled`: allow elevated mode (default true) -- `allowFrom`: per-provider allowlists (empty = disabled) +- `allowFrom`: per-channel allowlists (empty = disabled) - `whatsapp`: E.164 numbers - `telegram`: chat ids or usernames - `discord`: user ids or usernames (falls back to `channels.discord.dm.allowFrom` if omitted) @@ -2082,12 +2082,12 @@ Controls session scoping, idle expiry, reset triggers, and where the session sto // Max ping-pong reply turns between requester/target (0–5). maxPingPongTurns: 5 }, - sendPolicy: { - rules: [ - { action: "deny", match: { provider: "discord", chatType: "group" } } - ], - default: "allow" - } + sendPolicy: { + rules: [ + { action: "deny", match: { channel: "discord", chatType: "group" } } + ], + default: "allow" + } } } ``` @@ -2097,7 +2097,7 @@ Fields: - Sandbox note: `agents.defaults.sandbox.mode: "non-main"` uses this key to detect the main session. Any session key that does not match `mainKey` (groups/channels) is sandboxed. - `agentToAgent.maxPingPongTurns`: max reply-back turns between requester/target (0–5, default 5). - `sendPolicy.default`: `allow` or `deny` fallback when no rule matches. -- `sendPolicy.rules[]`: match by `provider`, `chatType` (`direct|group|room`), or `keyPrefix` (e.g. `cron:`). First deny wins; otherwise allow. +- `sendPolicy.rules[]`: match by `channel`, `chatType` (`direct|group|room`), or `keyPrefix` (e.g. `cron:`). First deny wins; otherwise allow. ### `skills` (skills config) @@ -2349,8 +2349,8 @@ Hot-applied (no full gateway restart): - `browser` (browser control server restart) - `cron` (cron service restart + concurrency update) - `agents.defaults.heartbeat` (heartbeat runner restart) -- `web` (WhatsApp web provider restart) -- `telegram`, `discord`, `signal`, `imessage` (provider restarts) +- `web` (WhatsApp web channel restart) +- `telegram`, `discord`, `signal`, `imessage` (channel restarts) - `agent`, `models`, `routing`, `messages`, `session`, `whatsapp`, `logging`, `skills`, `ui`, `talk`, `identity`, `wizard` (dynamic reads) Requires full Gateway restart: @@ -2409,7 +2409,7 @@ Defaults: messageTemplate: "From: {{messages[0].from}}\nSubject: {{messages[0].subject}}\n{{messages[0].snippet}}", deliver: true, - provider: "last", + channel: "last", model: "openai/gpt-5.2-mini", }, ], @@ -2424,7 +2424,7 @@ Requests must include the hook token: Endpoints: - `POST /hooks/wake` → `{ text, mode?: "now"|"next-heartbeat" }` -- `POST /hooks/agent` → `{ message, name?, sessionKey?, wakeMode?, deliver?, provider?, to?, model?, thinking?, timeoutSeconds? }` +- `POST /hooks/agent` → `{ message, name?, sessionKey?, wakeMode?, deliver?, channel?, to?, model?, thinking?, timeoutSeconds? }` - `POST /hooks/` → resolved via `hooks.mappings` `/hooks/agent` always posts a summary into the main session (and can optionally trigger an immediate heartbeat via `wakeMode: "now"`). @@ -2434,8 +2434,8 @@ Mapping notes: - `match.source` matches a payload field (e.g. `{ source: "gmail" }`) so you can use a generic `/hooks/ingest` path. - Templates like `{{messages[0].subject}}` read from the payload. - `transform` can point to a JS/TS module that returns a hook action. -- `deliver: true` sends the final reply to a provider; `provider` defaults to `last` (falls back to WhatsApp). -- If there is no prior delivery route, set `provider` + `to` explicitly (required for Telegram/Discord/Slack/Signal/iMessage/MS Teams). +- `deliver: true` sends the final reply to a channel; `channel` defaults to `last` (falls back to WhatsApp). +- If there is no prior delivery route, set `channel` + `to` explicitly (required for Telegram/Discord/Slack/Signal/iMessage/MS Teams). - `model` overrides the LLM for this hook run (`provider/model` or alias; must be allowed if `agents.defaults.models` is set). Gmail helper config (used by `clawdbot hooks gmail setup` / `run`): @@ -2574,9 +2574,9 @@ Template placeholders are expanded in `tools.audio.transcription.args` (and any | `{{Body}}` | Full inbound message body | | `{{RawBody}}` | Raw inbound message body (no history/sender wrappers; best for command parsing) | | `{{BodyStripped}}` | Body with group mentions stripped (best default for agents) | -| `{{From}}` | Sender identifier (E.164 for WhatsApp; may differ per provider) | +| `{{From}}` | Sender identifier (E.164 for WhatsApp; may differ per channel) | | `{{To}}` | Destination identifier | -| `{{MessageSid}}` | Provider message id (when available) | +| `{{MessageSid}}` | Channel message id (when available) | | `{{SessionId}}` | Current session UUID | | `{{IsNewSession}}` | `"true"` when a new session was created | | `{{MediaUrl}}` | Inbound media pseudo-URL (if present) | diff --git a/docs/gateway/health.md b/docs/gateway/health.md index de7935d6c..970ac5776 100644 --- a/docs/gateway/health.md +++ b/docs/gateway/health.md @@ -1,16 +1,16 @@ --- -summary: "Health check steps for provider connectivity" +summary: "Health check steps for channel connectivity" read_when: - - Diagnosing web provider health + - Diagnosing WhatsApp channel health --- # Health Checks (CLI) -Short guide to verify provider connectivity without guessing. +Short guide to verify channel connectivity without guessing. ## Quick checks -- `clawdbot status` — local summary: gateway reachability/mode, update hint, link provider auth age, sessions + recent activity. +- `clawdbot status` — local summary: gateway reachability/mode, update hint, linked channel auth age, sessions + recent activity. - `clawdbot status --all` — full local diagnosis (read-only, color, safe to paste for debugging). -- `clawdbot status --deep` — also probes the running Gateway (per-provider probes when supported). +- `clawdbot status --deep` — also probes the running Gateway (per-channel probes when supported). - `clawdbot health --json` — asks the running Gateway for a full health snapshot (WS-only; no direct Baileys socket). - Send `/status` as a standalone message in WhatsApp/WebChat to get a status reply without invoking the agent. - Logs: tail `/tmp/clawdbot/clawdbot-*.log` and filter for `web-heartbeat`, `web-reconnect`, `web-auto-reply`, `web-inbound`. @@ -26,4 +26,4 @@ Short guide to verify provider connectivity without guessing. - No inbound messages → confirm linked phone is online and the sender is allowed (`channels.whatsapp.allowFrom`); for group chats, ensure allowlist + mention rules match (`channels.whatsapp.groups`, `agents.list[].groupChat.mentionPatterns`). ## Dedicated "health" command -`clawdbot health --json` asks the running Gateway for its health snapshot (no direct provider sockets from the CLI). It reports linked creds/auth age when available, per-provider probe summaries, session-store summary, and a probe duration. It exits non-zero if the Gateway is unreachable or the probe fails/timeouts. Use `--timeout ` to override the 10s default. +`clawdbot health --json` asks the running Gateway for its health snapshot (no direct channel sockets from the CLI). It reports linked creds/auth age when available, per-channel probe summaries, session-store summary, and a probe duration. It exits non-zero if the Gateway is unreachable or the probe fails/timeouts. Use `--timeout ` to override the 10s default. diff --git a/docs/gateway/heartbeat.md b/docs/gateway/heartbeat.md index 4ee9d8f0a..88157a641 100644 --- a/docs/gateway/heartbeat.md +++ b/docs/gateway/heartbeat.md @@ -76,7 +76,7 @@ and logged; a message that is only `HEARTBEAT_OK` is dropped. model: "anthropic/claude-opus-4-5", includeReasoning: false, // default: false (deliver separate Reasoning: message when available) target: "last", // last | whatsapp | telegram | discord | slack | signal | imessage | none - to: "+15551234567", // optional provider-specific override + to: "+15551234567", // optional channel-specific override prompt: "Read HEARTBEAT.md if exists. Consider outstanding tasks. Checkup sometimes on your human during (user local) day time.", ackMaxChars: 300 // max chars allowed after HEARTBEAT_OK } @@ -91,8 +91,8 @@ and logged; a message that is only `HEARTBEAT_OK` is dropped. - `model`: optional model override for heartbeat runs (`provider/model`). - `includeReasoning`: when enabled, also deliver the separate `Reasoning:` message when available (same shape as `/reasoning on`). - `target`: - - `last` (default): deliver to the last used external provider. - - explicit provider: `whatsapp` / `telegram` / `discord` / `slack` / `signal` / `imessage`. + - `last` (default): deliver to the last used external channel. + - explicit channel: `whatsapp` / `telegram` / `discord` / `slack` / `signal` / `imessage`. - `none`: run the heartbeat but **do not deliver** externally. - `to`: optional recipient override (E.164 for WhatsApp, chat id for Telegram, etc.). - `prompt`: overrides the default prompt body (not merged). diff --git a/docs/gateway/index.md b/docs/gateway/index.md index 85bda83f6..1e5d09f15 100644 --- a/docs/gateway/index.md +++ b/docs/gateway/index.md @@ -125,7 +125,7 @@ CLAWDBOT_CONFIG_PATH=~/.clawdbot/b.json CLAWDBOT_STATE_DIR=~/.clawdbot-b clawdbo - `status` — short summary. - `system-presence` — current presence list. - `system-event` — post a presence/system note (structured). -- `send` — send a message via the active provider(s). +- `send` — send a message via the active channel(s). - `agent` — run an agent turn (streams events back on same connection). - `node.list` — list paired + currently-connected bridge nodes (includes `caps`, `deviceFamily`, `modelIdentifier`, `paired`, `connected`, and advertised `commands`). - `node.describe` — describe a node (capabilities + supported `node.invoke` commands; works for paired nodes and for currently-connected unpaired nodes). @@ -268,7 +268,7 @@ Windows installs should use **WSL2** and follow the Linux systemd section above. ## Operational checks - Liveness: open WS and send `req:connect` → expect `res` with `payload.type="hello-ok"` (with snapshot). -- Readiness: call `health` → expect `ok: true` and a linked provider in the `providers` payload (when applicable). +- Readiness: call `health` → expect `ok: true` and a linked channel in `linkChannel` (when applicable). - Debug: subscribe to `tick` and `presence` events; ensure `status` shows linked/auth age; presence entries show Gateway host and connected clients. ## Safety guarantees diff --git a/docs/gateway/security.md b/docs/gateway/security.md index d91f07812..153fc0c59 100644 --- a/docs/gateway/security.md +++ b/docs/gateway/security.md @@ -45,18 +45,18 @@ Plugins run **in-process** with the Gateway. Treat them as trusted code: ## DM access model (pairing / allowlist / open / disabled) -All current DM-capable providers support a DM policy (`dmPolicy` or `*.dm.policy`) that gates inbound DMs **before** the message is processed: +All current DM-capable channels support a DM policy (`dmPolicy` or `*.dm.policy`) that gates inbound DMs **before** the message is processed: -- `pairing` (default): unknown senders receive a short pairing code and the bot ignores their message until approved. Codes expire after 1 hour; repeated DMs won’t resend a code until a new request is created. Pending requests are capped at **3 per provider** by default. +- `pairing` (default): unknown senders receive a short pairing code and the bot ignores their message until approved. Codes expire after 1 hour; repeated DMs won’t resend a code until a new request is created. Pending requests are capped at **3 per channel** by default. - `allowlist`: unknown senders are blocked (no pairing handshake). -- `open`: allow anyone to DM (public). **Requires** the provider allowlist to include `"*"` (explicit opt-in). +- `open`: allow anyone to DM (public). **Requires** the channel allowlist to include `"*"` (explicit opt-in). - `disabled`: ignore inbound DMs entirely. Approve via CLI: ```bash -clawdbot pairing list -clawdbot pairing approve +clawdbot pairing list +clawdbot pairing approve ``` Details + files on disk: [Pairing](/start/pairing) @@ -66,8 +66,8 @@ Details + files on disk: [Pairing](/start/pairing) Clawdbot has two separate “who can trigger me?” layers: - **DM allowlist** (`allowFrom` / `channels.discord.dm.allowFrom` / `channels.slack.dm.allowFrom`): who is allowed to talk to the bot in direct messages. - - When `dmPolicy="pairing"`, approvals are written to `~/.clawdbot/credentials/-allowFrom.json` (merged with config allowlists). -- **Group allowlist** (provider-specific): which groups/channels/guilds the bot will accept messages from at all. + - When `dmPolicy="pairing"`, approvals are written to `~/.clawdbot/credentials/-allowFrom.json` (merged with config allowlists). +- **Group allowlist** (channel-specific): which groups/channels/guilds the bot will accept messages from at all. - Common patterns: - `channels.whatsapp.groups`, `channels.telegram.groups`, `channels.imessage.groups`: per-group defaults like `requireMention`; when set, it also acts as a group allowlist (include `"*"` to keep allow-all behavior). - `groupPolicy="allowlist"` + `groupAllowFrom`: restrict who can trigger the bot *inside* a group session (WhatsApp/Telegram/Signal/iMessage/Microsoft Teams). diff --git a/docs/gateway/troubleshooting.md b/docs/gateway/troubleshooting.md index c5285c4f0..6e076782f 100644 --- a/docs/gateway/troubleshooting.md +++ b/docs/gateway/troubleshooting.md @@ -75,7 +75,7 @@ managers (pnpm/npm) because the daemon does not load your shell init. Runtime variables like `DISPLAY` should live in `~/.clawdbot/.env` (loaded early by the gateway). -WhatsApp + Telegram providers require **Node**; Bun is unsupported. If your +WhatsApp + Telegram channels require **Node**; Bun is unsupported. If your service was installed with Bun or a version-managed Node path, run `clawdbot doctor` to migrate to a system Node install. @@ -174,7 +174,7 @@ Look for `AllowFrom: ...` in the output. **Check 2:** For group chats, is mention required? ```bash -# The message must match mentionPatterns or explicit mentions; defaults live in provider groups/guilds. +# The message must match mentionPatterns or explicit mentions; defaults live in channel groups/guilds. # Multi-agent: `agents.list[].groupChat.mentionPatterns` overrides global patterns. grep -n "agents\\|groupChat\\|mentionPatterns\\|channels\\.whatsapp\\.groups\\|channels\\.telegram\\.groups\\|channels\\.imessage\\.groups\\|channels\\.discord\\.guilds" \ "${CLAWDBOT_CONFIG_PATH:-$HOME/.clawdbot/clawdbot.json}" @@ -193,17 +193,17 @@ If `dmPolicy` is `pairing`, unknown senders should receive a code and their mess **Check 1:** Is a pending request already waiting? ```bash -clawdbot pairing list +clawdbot pairing list ``` -Pending DM pairing requests are capped at **3 per provider** by default. If the list is full, new requests won’t generate a code until one is approved or expires. +Pending DM pairing requests are capped at **3 per channel** by default. If the list is full, new requests won’t generate a code until one is approved or expires. **Check 2:** Did the request get created but no reply was sent? ```bash clawdbot logs --follow | grep "pairing request" ``` -**Check 3:** Confirm `dmPolicy` isn’t `open`/`allowlist` for that provider. +**Check 3:** Confirm `dmPolicy` isn’t `open`/`allowlist` for that channel. ### Image + Mention Not Working @@ -250,7 +250,7 @@ Or use the `process` tool to background long commands. ```bash # Check local status (creds, sessions, queued events) clawdbot status -# Probe the running gateway + providers (WA connect + Telegram + Discord APIs) +# Probe the running gateway + channels (WA connect + Telegram + Discord APIs) clawdbot status --deep # View recent connection events diff --git a/docs/index.md b/docs/index.md index 1b799ab1c..f2e7c8b2e 100644 --- a/docs/index.md +++ b/docs/index.md @@ -62,7 +62,7 @@ WhatsApp / Telegram / Discord └─ Android node via Bridge + pairing ``` -Most operations flow through the **Gateway** (`clawdbot gateway`), a single long-running process that owns provider connections and the WebSocket control plane. +Most operations flow through the **Gateway** (`clawdbot gateway`), a single long-running process that owns channel connections and the WebSocket control plane. ## Network model diff --git a/docs/logging.md b/docs/logging.md index 81f130f46..69cf5d704 100644 --- a/docs/logging.md +++ b/docs/logging.md @@ -68,9 +68,9 @@ clawdbot doctor The Control UI’s **Logs** tab tails the same file using `logs.tail`. See [/web/control-ui](/web/control-ui) for how to open it. -### Provider-only logs +### Channel-only logs -To filter provider activity (WhatsApp/Telegram/etc), use: +To filter channel activity (WhatsApp/Telegram/etc), use: ```bash clawdbot channels logs --channel whatsapp diff --git a/docs/nodes/images.md b/docs/nodes/images.md index b58b3c500..ff3664f7a 100644 --- a/docs/nodes/images.md +++ b/docs/nodes/images.md @@ -5,7 +5,7 @@ read_when: --- # Image & Media Support — 2025-12-05 -Clawdbot is now **web-only** (Baileys). This document captures the current media handling rules for send, gateway, and agent replies. +The WhatsApp channel runs via **Baileys Web**. This document captures the current media handling rules for send, gateway, and agent replies. ## Goals - Send media with optional captions via `clawdbot message send --media`. @@ -15,9 +15,9 @@ Clawdbot is now **web-only** (Baileys). This document captures the current media ## CLI Surface - `clawdbot message send --media [--message ]` - `--media` optional; caption can be empty for media-only sends. - - `--dry-run` prints the resolved payload; `--json` emits `{ provider, to, messageId, mediaUrl, caption }`. + - `--dry-run` prints the resolved payload; `--json` emits `{ channel, to, messageId, mediaUrl, caption }`. -## Web Provider Behavior +## WhatsApp Web channel behavior - Input: local file path **or** HTTP(S) URL. - Flow: load into a Buffer, detect media kind, and build the correct payload: - **Images:** resize & recompress to JPEG (max side 2048px) targeting `agents.defaults.mediaMaxMb` (default 5 MB), capped at 6 MB. diff --git a/docs/platforms/exe-dev.md b/docs/platforms/exe-dev.md index fb3d6d036..6692d9ab4 100644 --- a/docs/platforms/exe-dev.md +++ b/docs/platforms/exe-dev.md @@ -96,7 +96,7 @@ It can set up: - `~/clawd` workspace bootstrap - `~/.clawdbot/clawdbot.json` config - model auth profiles -- provider config/login +- model provider config/login - Linux systemd **user** service (daemon) If you’re doing OAuth on a headless VM: do OAuth on a normal machine first, then copy the auth profile to the VM (see [FAQ](/start/faq)). diff --git a/docs/platforms/mac/peekaboo.md b/docs/platforms/mac/peekaboo.md index bfd9017f5..17bc88b96 100644 --- a/docs/platforms/mac/peekaboo.md +++ b/docs/platforms/mac/peekaboo.md @@ -42,8 +42,8 @@ export PEEKABOO_BRIDGE_SOCKET=/path/to/bridge.sock ## Security & permissions -- The bridge validates **caller code signatures**; TeamID `Y5PE65HELJ` is - allowed by default (Peekaboo’s signing team), plus the Clawdbot app’s TeamID. +- The bridge validates **caller code signatures**; an allowlist of TeamIDs is + enforced (Peekaboo host TeamID + Clawdbot app TeamID). - Requests time out after ~10 seconds. - If required permissions are missing, the bridge returns a clear error message rather than launching System Settings. diff --git a/docs/platforms/mac/release.md b/docs/platforms/mac/release.md index 0380a17df..82d6dbf72 100644 --- a/docs/platforms/mac/release.md +++ b/docs/platforms/mac/release.md @@ -10,8 +10,8 @@ read_when: This app now ships Sparkle auto-updates. Release builds must be Developer ID–signed, zipped, and published with a signed appcast entry. ## Prereqs -- Developer ID Application cert installed (`Developer ID Application: Peter Steinberger (Y5PE65HELJ)` is expected). -- Sparkle private key path set in the environment as `SPARKLE_PRIVATE_KEY_FILE`; key lives in `/Users/steipete/Library/CloudStorage/Dropbox/Backup/Sparkle` (same key as Trimmy; public key baked into Info.plist). +- Developer ID Application cert installed (example: `Developer ID Application: ()`). +- Sparkle private key path set in the environment as `SPARKLE_PRIVATE_KEY_FILE` (path to your Sparkle ed25519 private key; public key baked into Info.plist). - Notary credentials (keychain profile or API key) for `xcrun notarytool` if you want Gatekeeper-safe DMG/zip distribution. - We use a Keychain profile named `clawdbot-notary`, created from App Store Connect API key env vars in your shell profile: - `APP_STORE_CONNECT_API_KEY_P8`, `APP_STORE_CONNECT_KEY_ID`, `APP_STORE_CONNECT_ISSUER_ID` @@ -32,7 +32,7 @@ BUNDLE_ID=com.clawdbot.mac \ APP_VERSION=2026.1.11-4 \ APP_BUILD="$(git rev-list --count HEAD)" \ BUILD_CONFIG=release \ -SIGN_IDENTITY="Developer ID Application: Peter Steinberger (Y5PE65HELJ)" \ +SIGN_IDENTITY="Developer ID Application: ()" \ scripts/package-mac-app.sh # Zip for distribution (includes resource forks for Sparkle delta support) @@ -50,7 +50,7 @@ BUNDLE_ID=com.clawdbot.mac \ APP_VERSION=2026.1.11-4 \ APP_BUILD="$(git rev-list --count HEAD)" \ BUILD_CONFIG=release \ -SIGN_IDENTITY="Developer ID Application: Peter Steinberger (Y5PE65HELJ)" \ +SIGN_IDENTITY="Developer ID Application: ()" \ scripts/package-mac-dist.sh # Optional: ship dSYM alongside the release @@ -60,7 +60,7 @@ ditto -c -k --keepParent apps/macos/.build/release/Clawdbot.app.dSYM dist/Clawdb ## Appcast entry Use the release note generator so Sparkle renders formatted HTML notes: ```bash -SPARKLE_PRIVATE_KEY_FILE=/Users/steipete/Library/CloudStorage/Dropbox/Backup/Sparkle/ed25519-private-key scripts/make_appcast.sh dist/Clawdbot-2026.1.11-4.zip https://raw.githubusercontent.com/clawdbot/clawdbot/main/appcast.xml +SPARKLE_PRIVATE_KEY_FILE=/path/to/ed25519-private-key scripts/make_appcast.sh dist/Clawdbot-2026.1.11-4.zip https://raw.githubusercontent.com/clawdbot/clawdbot/main/appcast.xml ``` Generates HTML release notes from `CHANGELOG.md` (via [`scripts/changelog-to-html.sh`](https://github.com/clawdbot/clawdbot/blob/main/scripts/changelog-to-html.sh)) and embeds them in the appcast entry. Commit the updated `appcast.xml` alongside the release assets (zip + dSYM) when publishing. diff --git a/docs/platforms/mac/xpc.md b/docs/platforms/mac/xpc.md index 1b240b181..348756e23 100644 --- a/docs/platforms/mac/xpc.md +++ b/docs/platforms/mac/xpc.md @@ -20,14 +20,14 @@ read_when: ### PeekabooBridge (UI automation) - UI automation uses a separate UNIX socket named `bridge.sock` and the PeekabooBridge JSON protocol. - Host preference order (client-side): Peekaboo.app → Claude.app → Clawdbot.app → local execution. -- Security: bridge hosts require TeamID `Y5PE65HELJ`; DEBUG-only same-UID escape hatch is guarded by `PEEKABOO_ALLOW_UNSIGNED_SOCKET_CLIENTS=1` (Peekaboo convention). +- Security: bridge hosts require an allowed TeamID; DEBUG-only same-UID escape hatch is guarded by `PEEKABOO_ALLOW_UNSIGNED_SOCKET_CLIENTS=1` (Peekaboo convention). - See: [PeekabooBridge usage](/platforms/mac/peekaboo) for details. ### Mach/XPC - Not required for automation; `node.invoke` + PeekabooBridge cover current needs. ## Operational flows -- Restart/rebuild: `SIGN_IDENTITY="Apple Development: Peter Steinberger (2ZAC4GM7GD)" scripts/restart-mac.sh` +- Restart/rebuild: `SIGN_IDENTITY="Apple Development: ()" scripts/restart-mac.sh` - Kills existing instances - Swift build + package - Writes/bootstraps/kickstarts the LaunchAgent diff --git a/docs/platforms/macos.md b/docs/platforms/macos.md index abb3bd2d7..b6dc46e4e 100644 --- a/docs/platforms/macos.md +++ b/docs/platforms/macos.md @@ -70,7 +70,7 @@ Query parameters: - `message` (required) - `sessionKey` (optional) - `thinking` (optional) -- `deliver` / `to` / `provider` (optional) +- `deliver` / `to` / `channel` (optional) - `timeoutSeconds` (optional) - `key` (optional unattended mode key) diff --git a/docs/refactor/channel-plugin.md b/docs/refactor/channel-plugin.md index 955226e1a..c5cd8bc1d 100644 --- a/docs/refactor/channel-plugin.md +++ b/docs/refactor/channel-plugin.md @@ -30,7 +30,7 @@ Each `ChannelPlugin` bundles: - `status`: defaultRuntime + probe/audit/buildAccountSnapshot + buildChannelSummary + logSelfId + collectStatusIssues. - `gateway`: startAccount/stopAccount with runtime context (`getStatus`/`setStatus`), plus optional `loginWithQrStart/loginWithQrWait` for gateway-owned QR login flows. - `security`: dmPolicy + allowFrom hints used by `doctor security`. -- `heartbeat`: optional readiness checks + heartbeat recipient resolution when providers own targeting. +- `heartbeat`: optional readiness checks + heartbeat recipient resolution when channels own targeting. - `auth`: optional login hook used by `clawdbot channels login`. - `reload`: `configPrefixes` that map to hot restarts. - `onboarding`: optional CLI onboarding adapter (wizard UI hooks per channel). @@ -58,7 +58,7 @@ Each `ChannelPlugin` bundles: - `channels.status` summary objects come from `status.buildChannelSummary` (no per-channel branching in the handler). - `channels.status` warnings flow through `status.collectStatusIssues` per plugin. - CLI list uses `meta.showConfigured` to decide whether to show configured state. -- CLI provider options and prompt provider lists are generated from `listProviderPlugins()` (avoid hardcoded arrays). +- CLI channel options and prompt channel lists are generated from `listChannelPlugins()` (avoid hardcoded arrays). - Channel selection (`resolveMessageChannelSelection`) inspects `config.isEnabled` + `config.isConfigured` per plugin instead of hardcoded checks. - Pairing flows (CLI + store) use `plugin.pairing` (`idLabel`, `normalizeAllowEntry`, `notifyApproval`) via `src/channels/plugins/pairing.ts`. - CLI channel remove/disable delegates to `config.setAccountEnabled` + `config.deleteAccount` per plugin. @@ -72,39 +72,39 @@ Each `ChannelPlugin` bundles: - Outbound delivery results accept `meta` for channel-specific fields to avoid core type churn in new plugins. - Agent gateway routing sets `deliveryTargetMode` and uses `resolveOutboundTarget` for implicit fallback targets when `to` is missing. - Elevated tool allowlists (`tools.elevated.allowFrom`) are a record keyed by channel id (no schema update needed when adding channels). -- Block streaming defaults live on the plugin (`capabilities.blockStreaming`, `streaming.blockStreamingCoalesceDefaults`) instead of hardcoded provider checks. +- Block streaming defaults live on the plugin (`capabilities.blockStreaming`, `streaming.blockStreamingCoalesceDefaults`) instead of hardcoded channel checks. - Channel logout routes through `channels.logout` using `gateway.logoutAccount` on each plugin (clients should call the generic method). - Gateway message-channel normalization uses `src/channels/registry.ts` for cheap validation/normalization without plugin init cycles. - Group mention gating now flows through `plugin.groups.resolveRequireMention` (Discord/Slack/Telegram/WhatsApp/iMessage) instead of branching in reply handlers. -- Command authorization uses `config.resolveAllowFrom` + `config.formatAllowFrom`, with `commands.enforceOwnerForCommands` and `commands.skipWhenConfigEmpty` driving provider-specific behavior. +- Command authorization uses `config.resolveAllowFrom` + `config.formatAllowFrom`, with `commands.enforceOwnerForCommands` and `commands.skipWhenConfigEmpty` driving channel-specific behavior. - Security warnings (`doctor security`) use `plugin.security.resolveDmPolicy` + `plugin.security.collectWarnings`; supply `policyPath` + `allowFromPath` for accurate config hints. -- Reply threading uses `plugin.threading.resolveReplyToMode` and `plugin.threading.allowTagsWhenOff` rather than provider switches in reply helpers. +- Reply threading uses `plugin.threading.resolveReplyToMode` and `plugin.threading.allowTagsWhenOff` rather than channel switches in reply helpers. - Tool auto-threading context flows through `plugin.threading.buildToolContext` (e.g., Slack threadTs injection). -- Messaging tool dedupe now relies on `plugin.messaging.normalizeTarget` for provider-specific target normalization. +- Messaging tool dedupe now relies on `plugin.messaging.normalizeTarget` for channel-specific target normalization. - Message tool + CLI action dispatch now use `plugin.actions.listActions` + `plugin.actions.handleAction`; use `plugin.actions.supportsAction` for dispatch-only gating when you still want fallback send/poll. - Session announce targets can opt into `meta.preferSessionLookupForAnnounceTarget` when session keys are insufficient (e.g., WhatsApp). -- Onboarding provider setup is delegated to adapter modules under `src/providers/plugins/onboarding/*`, keeping `setupProviders` provider-agnostic. -- Onboarding registry now reads `plugin.onboarding` from each provider (no standalone onboarding map). +- Onboarding channel setup is delegated to adapter modules under `src/channels/plugins/onboarding/*`, keeping `setupChannels` channel-agnostic. +- Onboarding registry now reads `plugin.onboarding` from each channel (no standalone onboarding map). - Channel login flows (`clawdbot channels login`) route through `plugin.auth.login` when available. -- `clawdbot status` reports `linkProvider` (derived from `status.buildProviderSummary().linked`) instead of a hardcoded `web` provider field. -- Gateway `web.login.*` methods use `plugin.gatewayMethods` ownership to pick the provider (no hardcoded `normalizeProviderId("web")` in the handler). +- `clawdbot status` reports `linkChannel` (derived from `status.buildChannelSummary().linked`) instead of a hardcoded `web` field. +- Gateway `web.login.*` methods use `plugin.gatewayMethods` ownership to pick the channel (no hardcoded `normalizeChannelId("web")` in the handler). ## CLI Commands (inline references) - Add/remove channels: `clawdbot channels add ` / `clawdbot channels remove `. - Inspect channel state: `clawdbot channels list`, `clawdbot channels status`. - Link/unlink channels: `clawdbot channels login --channel ` / `clawdbot channels logout --channel `. -- Pairing approvals: `clawdbot pairing list `, `clawdbot pairing approve `. +- Pairing approvals: `clawdbot pairing list `, `clawdbot pairing approve `. -## Adding a Provider (checklist) -1) Create `src/providers/plugins/.ts` exporting `ProviderPlugin`. -2) Register in `src/providers/plugins/index.ts` and update `src/providers/registry.ts` (ids/aliases/meta) if needed. -3) Add a dock entry in `src/providers/dock.ts` for any shared behavior (capabilities, allowFrom format/resolve, mention stripping, threading, streaming chunk defaults). +## Adding a Channel (checklist) +1) Create `src/channels/plugins/.ts` exporting `ChannelPlugin`. +2) Register in `src/channels/plugins/index.ts` and update `src/channels/registry.ts` (ids/aliases/meta) if needed. +3) Add a dock entry in `src/channels/dock.ts` for any shared behavior (capabilities, allowFrom format/resolve, mention stripping, threading, streaming chunk defaults). 4) Add `reload.configPrefixes` for hot reload when config changes. -5) Delegate to existing provider modules (send/probe/monitor) or create them. +5) Delegate to existing channel modules (send/probe/monitor) or create them. 6) If you changed the gateway protocol: run `pnpm protocol:check` (updates `dist/protocol.schema.json` + `apps/macos/Sources/ClawdbotProtocol/GatewayModels.swift`). 7) Update docs/tests for any behavior changes. ## Cleanup Expectations -- Keep plugin files small; move heavy logic into provider modules. +- Keep plugin files small; move heavy logic into channel modules. - Prefer shared helpers over V2 copies. - Update docs when behavior/inputs change. diff --git a/docs/reference/AGENTS.default.md b/docs/reference/AGENTS.default.md index d10ce080d..ad4fe5731 100644 --- a/docs/reference/AGENTS.default.md +++ b/docs/reference/AGENTS.default.md @@ -81,7 +81,7 @@ git commit -m "Add Clawd workspace" ## What Clawdbot Does - Runs WhatsApp gateway + Pi coding agent so the assistant can read/write chats, fetch context, and run skills via the host Mac. - macOS app manages permissions (screen recording, notifications, microphone) and exposes the `clawdbot` CLI via its bundled binary. -- Direct chats collapse into the agent's `main` session by default; groups stay isolated as `agent:::group:` (rooms/channels: `agent:::channel:`); heartbeats keep background tasks alive. +- Direct chats collapse into the agent's `main` session by default; groups stay isolated as `agent:::group:` (rooms/channels: `agent:::channel:`); heartbeats keep background tasks alive. ## Core Skills (enable in Settings → Skills) - **mcporter** — Tool server runtime/CLI for managing external skill backends. diff --git a/docs/reference/session-management-compaction.md b/docs/reference/session-management-compaction.md index d81a1ea44..776441227 100644 --- a/docs/reference/session-management-compaction.md +++ b/docs/reference/session-management-compaction.md @@ -67,8 +67,8 @@ A `sessionKey` identifies *which conversation bucket* you’re in (routing + iso Common patterns: - Main/direct chat (per agent): `agent::` (default `main`) -- Group: `agent:::group:` -- Room/channel (Discord/Slack): `agent:::channel:` or `...:room:` +- Group: `agent:::group:` +- Room/channel (Discord/Slack): `agent:::channel:` or `...:room:` - Cron: `cron:` - Webhook: `hook:` (unless overridden) diff --git a/docs/start/faq.md b/docs/start/faq.md index 1c9e12055..810156a59 100644 --- a/docs/start/faq.md +++ b/docs/start/faq.md @@ -1256,7 +1256,7 @@ If you run the gateway manually, `clawdbot gateway --force` can reclaim the port ### What’s the fastest way to get more details when something fails? -Start the Gateway with `--verbose` to get more console detail. Then inspect the log file for provider auth, model routing, and RPC errors. +Start the Gateway with `--verbose` to get more console detail. Then inspect the log file for channel auth, model routing, and RPC errors. ## Media & attachments @@ -1280,8 +1280,8 @@ Treat inbound DMs as untrusted input. Defaults are designed to reduce risk: - Default behavior on DM‑capable channels is **pairing**: - Unknown senders receive a pairing code; the bot does not process their message. - - Approve with: `clawdbot pairing approve ` - - Pending requests are capped at **3 per provider**; check `clawdbot pairing list ` if a code didn’t arrive. + - Approve with: `clawdbot pairing approve ` + - Pending requests are capped at **3 per channel**; check `clawdbot pairing list ` if a code didn’t arrive. - Opening DMs publicly requires explicit opt‑in (`dmPolicy: "open"` and allowlist `"*"`). Run `clawdbot doctor` to surface risky DM policies. diff --git a/docs/start/pairing.md b/docs/start/pairing.md index 263182848..4c811d580 100644 --- a/docs/start/pairing.md +++ b/docs/start/pairing.md @@ -18,14 +18,14 @@ Security context: [Security](/gateway/security) ## 1) DM pairing (inbound chat access) -When a provider is configured with DM policy `pairing`, unknown senders get a short code and their message is **not processed** until you approve. +When a channel is configured with DM policy `pairing`, unknown senders get a short code and their message is **not processed** until you approve. Default DM policies are documented in: [Security](/gateway/security) Pairing codes: - 8 characters, uppercase, no ambiguous chars (`0O1I`). - **Expire after 1 hour**. The bot only sends the pairing message when a new request is created (roughly once per hour per sender). -- Pending DM pairing requests are capped at **3 per provider** by default; additional requests are ignored until one expires or is approved. +- Pending DM pairing requests are capped at **3 per channel** by default; additional requests are ignored until one expires or is approved. ### Approve a sender @@ -39,8 +39,8 @@ Supported channels: `telegram`, `whatsapp`, `signal`, `imessage`, `discord`, `sl ### Where the state lives Stored under `~/.clawdbot/credentials/`: -- Pending requests: `-pairing.json` -- Approved allowlist store: `-allowFrom.json` +- Pending requests: `-pairing.json` +- Approved allowlist store: `-allowFrom.json` Treat these as sensitive (they gate access to your assistant). @@ -72,7 +72,7 @@ Full protocol + design notes: [Gateway pairing](/gateway/pairing) - Security model + prompt injection: [Security](/gateway/security) - Updating safely (run doctor): [Updating](/install/updating) -- Provider configs: +- Channel configs: - Telegram: [Telegram](/channels/telegram) - WhatsApp: [WhatsApp](/channels/whatsapp) - Signal: [Signal](/channels/signal) diff --git a/docs/start/wizard.md b/docs/start/wizard.md index 2690c40af..8ae65c4fa 100644 --- a/docs/start/wizard.md +++ b/docs/start/wizard.md @@ -105,13 +105,13 @@ Tip: `--json` does **not** imply non-interactive mode. Use `--non-interactive` ( - Disable auth only if you fully trust every local process. - Non‑loopback binds still require auth. -5) **Providers** +5) **Channels** - WhatsApp: optional QR login. - Telegram: bot token. - Discord: bot token. - Signal: optional `signal-cli` install + account config. - iMessage: local `imsg` CLI path + DB access. - - DM security: default is pairing. First DM sends a code; approve via `clawdbot pairing approve ` or use allowlists. + - DM security: default is pairing. First DM sends a code; approve via `clawdbot pairing approve ` or use allowlists. 6) **Daemon install** - macOS: LaunchAgent diff --git a/docs/tools/index.md b/docs/tools/index.md index e0a867745..87ef3d7f1 100644 --- a/docs/tools/index.md +++ b/docs/tools/index.md @@ -14,7 +14,7 @@ and the agent should rely on them directly. ## Disabling tools You can globally allow/deny tools via `tools.allow` / `tools.deny` in `clawdbot.json` -(deny wins). This prevents disallowed tools from being sent to providers. +(deny wins). This prevents disallowed tools from being sent to model providers. ```json5 { @@ -228,7 +228,7 @@ Notes: - Uses the image model directly (independent of the main chat model). ### `message` -Send messages and provider actions across Discord/Slack/Telegram/WhatsApp/Signal/iMessage/MS Teams. +Send messages and channel actions across Discord/Slack/Telegram/WhatsApp/Signal/iMessage/MS Teams. Core actions: - `send` (text + optional media) @@ -248,7 +248,7 @@ Core actions: - `timeout` / `kick` / `ban` Notes: -- `send` routes WhatsApp via the Gateway; other providers go direct. +- `send` routes WhatsApp via the Gateway; other channels go direct. - `poll` uses the Gateway for WhatsApp and MS Teams; Discord polls go direct. - When a message tool call is bound to an active chat session, sends are constrained to that session’s target to avoid cross-context leaks. diff --git a/docs/tools/reactions.md b/docs/tools/reactions.md index 5d4b9b61f..166c3fc20 100644 --- a/docs/tools/reactions.md +++ b/docs/tools/reactions.md @@ -1,17 +1,17 @@ --- -summary: "Reaction semantics shared across providers" +summary: "Reaction semantics shared across channels" read_when: - - Working on reactions in any provider + - Working on reactions in any channel --- # Reaction tooling -Shared reaction semantics across providers: +Shared reaction semantics across channels: - `emoji` is required when adding a reaction. - `emoji=""` removes the bot's reaction(s) when supported. - `remove: true` removes the specified emoji when supported (requires `emoji`). -Provider notes: +Channel notes: - **Discord/Slack**: empty `emoji` removes all of the bot's reactions on the message; `remove: true` removes just that emoji. - **Telegram**: empty `emoji` removes the bot's reactions; `remove: true` also removes reactions but still requires a non-empty `emoji` for tool validation. diff --git a/docs/tools/subagents.md b/docs/tools/subagents.md index ce0cbb15f..4647bcf37 100644 --- a/docs/tools/subagents.md +++ b/docs/tools/subagents.md @@ -7,7 +7,7 @@ read_when: # Sub-agents -Sub-agents are background agent runs spawned from an existing agent run. They run in their own session (`agent::subagent:`) and, when finished, **announce** their result back to the requester chat provider. +Sub-agents are background agent runs spawned from an existing agent run. They run in their own session (`agent::subagent:`) and, when finished, **announce** their result back to the requester chat channel. Primary goals: - Parallelize “research / long task / slow tool” work without blocking the main run. @@ -19,7 +19,7 @@ Primary goals: Use `sessions_spawn`: - Starts a sub-agent run (`deliver: false`, global lane: `subagent`) -- Then runs an announce step and posts the announce reply to the requester chat provider +- Then runs an announce step and posts the announce reply to the requester chat channel - Default model: inherits the caller unless you set `agents.defaults.subagents.model` (or per-agent `agents.list[].subagents.model`); an explicit `sessions_spawn.model` still wins. Tool params: @@ -48,7 +48,7 @@ Auto-archive: Sub-agents report back via an announce step: - The announce step runs inside the sub-agent session (not the requester session). - If the sub-agent replies exactly `ANNOUNCE_SKIP`, nothing is posted. -- Otherwise the announce reply is posted to the requester chat provider via the gateway `send` method. +- Otherwise the announce reply is posted to the requester chat channel via the gateway `send` method. Announce payloads include a stats line at the end: - Runtime (e.g., `runtime 5m12s`) diff --git a/docs/web/control-ui.md b/docs/web/control-ui.md index 758d58f4e..fa13fb3e4 100644 --- a/docs/web/control-ui.md +++ b/docs/web/control-ui.md @@ -30,7 +30,7 @@ The onboarding wizard generates a gateway token by default, so paste it here on ## What it can do (today) - Chat with the model via Gateway WS (`chat.history`, `chat.send`, `chat.abort`) - Stream tool calls + live tool output cards in Chat (agent events) -- Connections: WhatsApp/Telegram status + QR login + Telegram config (`providers.status`, `web.login.*`, `config.set`) +- Connections: WhatsApp/Telegram status + QR login + Telegram config (`channels.status`, `web.login.*`, `config.set`) - Instances: presence list + refresh (`system-presence`) - Sessions: list + per-session thinking/verbose overrides (`sessions.list`, `sessions.patch`) - Cron jobs: list/add/run/enable/disable + run history (`cron.*`) diff --git a/docs/web/tui.md b/docs/web/tui.md index 9bc383b86..155f2ba89 100644 --- a/docs/web/tui.md +++ b/docs/web/tui.md @@ -28,7 +28,7 @@ Use SSH tunneling or Tailscale to reach the Gateway WS. - `--token `: Gateway token (if required). - `--password `: Gateway password (if required). - `--session `: Session key (default: `main`, or `global` when scope is global). -- `--deliver`: Deliver assistant replies to the provider (default off). +- `--deliver`: Deliver assistant replies to the channel (default off). - `--thinking `: Override thinking level for sends. - `--timeout-ms `: Agent timeout in ms (defaults to `agents.defaults.timeoutSeconds`). - `--history-limit `: History entries to load (default 200). diff --git a/docs/web/webchat.md b/docs/web/webchat.md index 3f0ae351a..9343ebb51 100644 --- a/docs/web/webchat.md +++ b/docs/web/webchat.md @@ -10,7 +10,7 @@ Status: the macOS/iOS SwiftUI chat UI talks directly to the Gateway WebSocket. ## What it is - A native chat UI for the gateway (no embedded browser and no local static server). -- Uses the same sessions and routing rules as other providers. +- Uses the same sessions and routing rules as other channels. - Deterministic routing: replies always go back to WebChat. ## Quick start @@ -30,7 +30,7 @@ Status: the macOS/iOS SwiftUI chat UI talks directly to the Gateway WebSocket. ## Configuration reference (WebChat) Full configuration: [Configuration](/gateway/configuration) -Provider options: +Channel options: - No dedicated `webchat.*` block. WebChat uses the gateway endpoint + auth settings below. Related global options: