fix: polish reply threading + tool dedupe (thanks @mneves75) (#326)

This commit is contained in:
Peter Steinberger
2026-01-08 00:50:29 +00:00
parent 33e2d53be3
commit 17d052bcda
16 changed files with 193 additions and 350 deletions

View File

@@ -582,8 +582,9 @@ Set `telegram.enabled: false` to disable automatic startup.
}
}
},
replyToMode: "first", // off | first | all
streamMode: "partial", // off | partial | block (draft streaming)
actions: { reactions: true }, // tool action gates (false disables)
actions: { reactions: true, sendMessage: true }, // tool action gates (false disables)
mediaMaxMb: 5,
retry: { // outbound retry policy
attempts: 3,
@@ -707,6 +708,7 @@ Slack runs in Socket Mode and requires both a bot token and app token:
},
reactionNotifications: "own", // off | own | all | allowlist
reactionAllowlist: ["U123"],
replyToMode: "off", // off | first | all
actions: {
reactions: true,
messages: true,

View File

@@ -167,6 +167,7 @@ Slack uses Socket Mode only (no HTTP webhook server). Provide both tokens:
},
"reactionNotifications": "own",
"reactionAllowlist": ["U123"],
"replyToMode": "off",
"actions": {
"reactions": true,
"messages": true,
@@ -193,6 +194,14 @@ Tokens can also be supplied via env vars:
Ack reactions are controlled globally via `messages.ackReaction` +
`messages.ackReactionScope`.
## Reply threading
Slack supports optional threaded replies via tags:
- `[[reply_to_current]]` — reply to the triggering message.
- `[[reply_to:<id>]]` — reply to a specific message id.
Controlled by `slack.replyToMode`:
- `off` (default), `first`, `all`.
## Sessions + routing
- DMs share the `main` session (like WhatsApp/Telegram).
- Channels map to `slack:channel:<channelId>` sessions.

View File

@@ -5,7 +5,7 @@ read_when:
---
# Telegram (Bot API)
Updated: 2026-01-07
Updated: 2026-01-08
Status: production-ready for bot DMs + groups via grammY. Long-polling by default; webhook optional.
@@ -139,7 +139,7 @@ Telegram supports optional threaded replies via tags:
- `[[reply_to:<id>]]` -- reply to a specific message id.
Controlled by `telegram.replyToMode`:
- `off` (default), `first`, `all`.
- `first` (default), `all`, `off`.
## Streaming (drafts)
Telegram can stream **draft bubbles** while the agent is generating a response.
@@ -166,10 +166,11 @@ More context: [Streaming + chunking](/concepts/streaming).
## Retry policy
Outbound Telegram API calls retry on transient network/429 errors with exponential backoff and jitter. Configure via `telegram.retry`. See [Retry policy](/concepts/retry).
## Agent tool (reactions)
## Agent tool (messages + reactions)
- Tool: `telegram` with `sendMessage` action (`to`, `content`, optional `mediaUrl`, `replyToMessageId`, `messageThreadId`).
- Tool: `telegram` with `react` action (`chatId`, `messageId`, `emoji`).
- Reaction removal semantics: see [/tools/reactions](/tools/reactions).
- Tool gating: `telegram.actions.reactions` (default: enabled).
- Tool gating: `telegram.actions.reactions` and `telegram.actions.sendMessage` (default: enabled).
## Delivery targets (CLI/cron)
- Use a chat id (`123456789`) or a username (`@name`) as the target.
@@ -215,7 +216,7 @@ Provider options:
- `telegram.groups.<id>.enabled`: disable the group when `false`.
- `telegram.groups.<id>.topics.<threadId>.*`: per-topic overrides (same fields as group).
- `telegram.groups.<id>.topics.<threadId>.requireMention`: per-topic mention gating override.
- `telegram.replyToMode`: `off | first | all`.
- `telegram.replyToMode`: `off | first | all` (default: `first`).
- `telegram.textChunkLimit`: outbound chunk size (chars).
- `telegram.streamMode`: `off | partial | block` (draft streaming).
- `telegram.mediaMaxMb`: inbound/outbound media cap (MB).
@@ -225,6 +226,7 @@ Provider options:
- `telegram.webhookSecret`: webhook secret (optional).
- `telegram.webhookPath`: local webhook path (default `/telegram-webhook`).
- `telegram.actions.reactions`: gate Telegram tool reactions.
- `telegram.actions.sendMessage`: gate Telegram tool message sends.
Related global options:
- `routing.groupChat.mentionPatterns` (mention gating patterns).

View File

@@ -1,130 +0,0 @@
---
summary: "Telegram Bot API integration: setup, forum topics, reply modes, and configuration"
read_when:
- Configuring Telegram bot integration
- Setting up forum topic threading
- Troubleshooting Telegram reply behavior
---
# Telegram Integration
CLAWDBOT connects to Telegram via the [Bot API](https://core.telegram.org/bots/api) using [grammY](https://grammy.dev/).
## Setup
1. Create a bot via [@BotFather](https://t.me/BotFather)
2. Copy the token
3. Add to your config:
```json
{
"telegram": {
"token": "123456789:ABCdefGHI..."
}
}
```
Or set `TELEGRAM_BOT_TOKEN` in your environment.
## Forum Topics (Supergroups)
Telegram supergroups can enable **Topics** (forum mode), which creates thread-like conversations within a single group. CLAWDBOT fully supports forum topics:
- **Automatic detection:** When a message arrives from a forum topic, CLAWDBOT automatically routes it to a topic-specific session
- **Thread isolation:** Each topic gets its own conversation context, so the agent maintains separate threads
- **Reply threading:** Replies are sent to the same topic via `message_thread_id`
### Session Routing
Forum topic messages create session keys in the format:
```
telegram:group:<chat_id>:topic:<topic_id>
```
This ensures conversations in different topics remain isolated even within the same supergroup.
## Reply Modes
The `replyToMode` setting controls how the bot replies to messages:
| Mode | Behavior |
|------|----------|
| `"first"` | Reply to the first message in a conversation (default) |
| `"all"` | Reply to every message |
| `"off"` | Send messages without reply threading |
Configure in your config:
```json
{
"telegram": {
"replyToMode": "first"
}
}
```
**Default:** `"first"` — This ensures replies appear threaded in the chat, making conversations easier to follow.
## Access Control
### DM Policy
Control who can DM your bot:
```json
{
"telegram": {
"dmPolicy": "pairing",
"allowFrom": ["123456789", "@username"]
}
}
```
- `"pairing"` (default): New users get a pairing code to request access
- `"allowlist"`: Only users in `allowFrom` can interact
- `"open"`: Anyone can DM the bot
- `"disabled"`: DMs are blocked
### Group Policy
Control group message handling:
```json
{
"telegram": {
"groupPolicy": "open",
"groupAllowFrom": ["*"],
"groups": ["-1001234567890"]
}
}
```
- `groupPolicy`: `"open"` (default), `"allowlist"`, or `"disabled"`
- `groups`: When set, acts as an allowlist of group IDs
## Mention Requirements
In groups, you can require the bot to be mentioned:
```json
{
"telegram": {
"requireMention": true
}
}
```
When `true`, the bot only responds to messages that @mention it or match configured mention patterns.
## Media Handling
Configure media size limits:
```json
{
"telegram": {
"mediaMaxMb": 10
}
}
```
Default: 5MB. Files exceeding this limit are rejected with a user-friendly message.

View File

@@ -241,9 +241,10 @@ Notes:
- The tool is only exposed when the current provider is WhatsApp.
### `telegram`
Send Telegram reactions.
Send Telegram messages or reactions.
Core actions:
- `sendMessage` (`to`, `content`, optional `mediaUrl`, `replyToMessageId`, `messageThreadId`)
- `react` (`chatId`, `messageId`, `emoji`, optional `remove`)
Notes: