diff --git a/CHANGELOG.md b/CHANGELOG.md index bb3086bcb..a86388a44 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ - Agents: add human-delay pacing between block replies (modes: off/natural/custom, per-agent configurable). (#446) — thanks @tony-freedomology. - Onboarding/Models: add catalog-backed default model picker to onboarding + configure. (#611) — thanks @jonasjancarik. - Agents/OpenCode Zen: update fallback models + defaults, keep legacy alias mappings. (#669) — thanks @magimetal. +- Providers: unify group history context wrappers across providers with per-provider/per-account `historyLimit` overrides (fallback to `messages.groupChat.historyLimit`). Set `0` to disable. ### Fixes - Auto-reply: prefer `RawBody` for command/directive parsing (WhatsApp + Discord) and prevent fallback runs from clobbering concurrent session updates. (#643) — thanks @mcinteerj. diff --git a/docs/concepts/messages.md b/docs/concepts/messages.md index 8ea4e92c7..8050a14e1 100644 --- a/docs/concepts/messages.md +++ b/docs/concepts/messages.md @@ -41,6 +41,25 @@ gateway-backed session transcript, so they are the source of truth. 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 + 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: +- `[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 +`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 `slack.historyLimit` or +`telegram.accounts..historyLimit` (set `0` to disable). + ## Queueing and followups If a run is already active, inbound messages can be queued, steered into the diff --git a/docs/gateway/configuration.md b/docs/gateway/configuration.md index 975c52c49..f6dd9c1e1 100644 --- a/docs/gateway/configuration.md +++ b/docs/gateway/configuration.md @@ -343,6 +343,8 @@ 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 `.historyLimit` (or `.accounts.*.historyLimit` for multi-account). Set `0` to disable history wrapping. + Per-agent override (takes precedence when set, even `[]`): ```json5 { @@ -674,6 +676,7 @@ Multi-account support lives under `telegram.accounts` (see the multi-account sec } } }, + historyLimit: 50, // include last N group messages as context (0 disables) replyToMode: "first", // off | first | all streamMode: "partial", // off | partial | block (draft streaming; separate from block streaming) draftChunk: { // optional; only for streamMode=block @@ -808,6 +811,7 @@ Slack runs in Socket Mode and requires both a bot token and app token: systemPrompt: "Short answers only." } }, + historyLimit: 50, // include last N channel/group messages as context (0 disables) allowBots: false, reactionNotifications: "own", // off | own | all | allowlist reactionAllowlist: ["U123"], @@ -860,7 +864,8 @@ Signal reactions can emit system events (shared reaction tooling): { signal: { reactionNotifications: "own", // off | own | all | allowlist - reactionAllowlist: ["+15551234567", "uuid:123e4567-e89b-12d3-a456-426614174000"] + reactionAllowlist: ["+15551234567", "uuid:123e4567-e89b-12d3-a456-426614174000"], + historyLimit: 50 // include last N group messages as context (0 disables) } } ``` @@ -883,6 +888,7 @@ Clawdbot spawns `imsg rpc` (JSON-RPC over stdio). No daemon or port required. dbPath: "~/Library/Messages/chat.db", dmPolicy: "pairing", // pairing | allowlist | open | disabled allowFrom: ["+15555550123", "user@example.com", "chat_id:123"], + historyLimit: 50, // include last N group messages as context (0 disables) includeAttachments: false, mediaMaxMb: 16, service: "auto", diff --git a/docs/providers/discord.md b/docs/providers/discord.md index e2b8cb563..1777fcf53 100644 --- a/docs/providers/discord.md +++ b/docs/providers/discord.md @@ -30,7 +30,7 @@ Status: ready for DM and guild text channels via the official Discord bot gatewa 9. Optional guild rules: set `discord.guilds` keyed by guild id (preferred) or slug, with per-channel rules. 10. Optional native commands: set `commands.native: true` to register native commands in Discord; set `commands.native: false` to clear previously registered native commands. Text commands are controlled by `commands.text` and must be sent as standalone `/...` messages. Use `commands.useAccessGroups: false` to bypass access-group checks for commands. - Full command list + config: [Slash commands](/tools/slash-commands) -11. Optional guild context history: set `discord.historyLimit` (default 20) to include the last N guild messages as context when replying to a mention. Set `0` to disable. +11. Optional guild context history: set `discord.historyLimit` (default 20, falls back to `messages.groupChat.historyLimit`) to include the last N guild messages as context when replying to a mention. Set `0` to disable. 12. Reactions: the agent can trigger reactions via the `discord` tool (gated by `discord.actions.*`). - Reaction removal semantics: see [/tools/reactions](/tools/reactions). - The `discord` tool is only exposed when the current provider is Discord. @@ -250,7 +250,7 @@ ack reaction after the bot replies. - `textChunkLimit`: outbound text chunk size (chars). Default: 2000. - `maxLinesPerMessage`: soft max line count per message. Default: 17. - `mediaMaxMb`: clamp inbound media saved to disk. -- `historyLimit`: number of recent guild messages to include as context when replying to a mention (default 20, `0` disables). +- `historyLimit`: number of recent guild messages to include as context when replying to a mention (default 20; falls back to `messages.groupChat.historyLimit`; `0` disables). - `retry`: retry policy for outbound Discord API calls (attempts, minDelayMs, maxDelayMs, jitter). - `actions`: per-action tool gates; omit to allow all (set `false` to disable). - `reactions` (covers react + read reactions) diff --git a/docs/providers/imessage.md b/docs/providers/imessage.md index fd8a82865..8a3202428 100644 --- a/docs/providers/imessage.md +++ b/docs/providers/imessage.md @@ -154,6 +154,7 @@ Provider options: - `imessage.allowFrom`: DM allowlist (handles or `chat_id:*`). `open` requires `"*"`. - `imessage.groupPolicy`: `open | allowlist | disabled` (default: open). - `imessage.groupAllowFrom`: group sender allowlist. +- `imessage.historyLimit` / `imessage.accounts.*.historyLimit`: max group messages to include as context (0 disables). - `imessage.groups`: per-group defaults + allowlist (use `"*"` for global defaults). - `imessage.includeAttachments`: ingest attachments into context. - `imessage.mediaMaxMb`: inbound/outbound media cap (MB). diff --git a/docs/providers/msteams.md b/docs/providers/msteams.md index 1a7e6fd59..7e12a16af 100644 --- a/docs/providers/msteams.md +++ b/docs/providers/msteams.md @@ -150,6 +150,10 @@ This is often easier than hand-editing JSON manifests. 5. **Run the gateway** - The Teams provider starts automatically when `msteams` config exists and credentials are set. +## History context +- `msteams.historyLimit` controls how many recent channel/group messages are wrapped into the prompt. +- Falls back to `messages.groupChat.historyLimit`. Set `0` to disable (default 50). + ## Current Teams RSC Permissions (Manifest) These are the **existing resourceSpecific permissions** in our Teams app manifest. They only apply inside the team/chat where the app is installed. diff --git a/docs/providers/signal.md b/docs/providers/signal.md index 41f1fc538..b33de0262 100644 --- a/docs/providers/signal.md +++ b/docs/providers/signal.md @@ -64,6 +64,7 @@ Groups: - Attachments supported (base64 fetched from `signal-cli`). - Default media cap: `signal.mediaMaxMb` (default 8). - Use `signal.ignoreAttachments` to skip downloading media. +- Group history context uses `signal.historyLimit` (or `signal.accounts.*.historyLimit`), falling back to `messages.groupChat.historyLimit`. Set `0` to disable (default 50). ## Delivery targets (CLI/cron) - DMs: `signal:+15551234567` (or plain E.164). @@ -88,6 +89,7 @@ Provider options: - `signal.allowFrom`: DM allowlist (E.164 or `uuid:`). `open` requires `"*"`. - `signal.groupPolicy`: `open | allowlist | disabled` (default: open). - `signal.groupAllowFrom`: group sender allowlist. +- `signal.historyLimit`: max group messages to include as context (0 disables). - `signal.textChunkLimit`: outbound chunk size (chars). - `signal.mediaMaxMb`: inbound/outbound media cap (MB). diff --git a/docs/providers/slack.md b/docs/providers/slack.md index 20eea4f41..2b180a922 100644 --- a/docs/providers/slack.md +++ b/docs/providers/slack.md @@ -24,6 +24,10 @@ Use the manifest below so scopes and events stay in sync. Multi-account support: use `slack.accounts` with per-account tokens and optional `name`. See [`gateway/configuration`](/gateway/configuration#telegramaccounts--discordaccounts--slackaccounts--signalaccounts--imessageaccounts) for the shared pattern. +## History context +- `slack.historyLimit` (or `slack.accounts.*.historyLimit`) controls how many recent channel/group messages are wrapped into the prompt. +- Falls back to `messages.groupChat.historyLimit`. Set `0` to disable (default 50). + ## Manifest (optional) Use this Slack app manifest to create the app quickly (adjust the name/command if you want). diff --git a/docs/providers/telegram.md b/docs/providers/telegram.md index 0d1e0660e..ee72954f4 100644 --- a/docs/providers/telegram.md +++ b/docs/providers/telegram.md @@ -78,6 +78,7 @@ group messages, so use admin if you need full visibility. ## Limits - Outbound text is chunked to `telegram.textChunkLimit` (default 4000). - Media downloads/uploads are capped by `telegram.mediaMaxMb` (default 5). +- Group history context uses `telegram.historyLimit` (or `telegram.accounts.*.historyLimit`), falling back to `messages.groupChat.historyLimit`. Set `0` to disable (default 50). ## Group activation modes diff --git a/docs/providers/whatsapp.md b/docs/providers/whatsapp.md index dc05b6874..02a91d334 100644 --- a/docs/providers/whatsapp.md +++ b/docs/providers/whatsapp.md @@ -193,6 +193,7 @@ Behavior: - `whatsapp.accounts..mediaMaxMb` (per-account inbound media cap). - `whatsapp.groupAllowFrom` (group sender allowlist). - `whatsapp.groupPolicy` (group policy). +- `whatsapp.historyLimit` / `whatsapp.accounts..historyLimit` (group history context; `0` disables). - `whatsapp.groups` (group allowlist + mention gating defaults; use `"*"` to allow all) - `whatsapp.actions.reactions` (gate WhatsApp tool reactions). - `agents.list[].groupChat.mentionPatterns` (or `messages.groupChat.mentionPatterns`)