Files
goclaw/docs/telegram-trigger-words.md
ba621391c2 feat(telegram): trigger-words, channel posts, message edit & topic posting (#1383)
- Fix image_generation nil-pointer crash on codex agents: the sentinel now
  carries a name-only Function so the many sites reading td.Function.Name never
  nil-deref; codex_build still branches on Type.
- Agent-declared trigger words in IDENTITY.md wake the bot in groups without an
  @mention (whole-word, Cyrillic-aware; text + caption), cached per-agent 60s.
- channel_post support with a synthetic sender + a recover() guard so a
  malformed update can't crash the gateway.
- message tool action=edit (editMessageText + editMessageCaption fallback),
  targeting the replied-to message via reply_to_message_id.
- message tool topic=<name> posts into a named forum topic; topics learned from
  forum_topic_created into channel_contacts and resolved by name.

Co-authored-by: skensel <skensel@MacBook-Pro-skensel.local>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-09 12:28:18 +07:00

70 lines
2.7 KiB
Markdown

# Telegram trigger words (wake an agent by name)
In group chats a Telegram bot normally only reacts when it is `@mentioned`,
addressed with a `/command@bot`, or replied to. **Trigger words** let an agent
also wake up when a message names it by an alias — without an explicit mention.
Trigger words are a property of the **agent**, not the channel, so they travel
with the agent across every channel it serves. They are declared in the agent's
`IDENTITY.md` context file.
## How to configure
Add a `Trigger words:` line to the agent's `IDENTITY.md` (comma-separated):
```markdown
# IDENTITY.md — Who Am I?
- **Name:** Rex
- **Trigger words:** Alice, Boss, Chief
- **Creature:** an AI assistant that keeps a team's chats in order
- **Purpose:** answer questions and run tasks for the team
- **Emoji:** 🤖
```
The plain `Key: Value` form works too:
```markdown
Name: Rex
Trigger words: Alice, Boss, Chief
Emoji: 🤖
```
With the config above, in a group the bot wakes on messages like
`Alice, what's the status?` or `hey boss` — no `@mention` required. It keeps
ignoring unrelated chatter.
Edits to `IDENTITY.md` take effect within ~60s (the channel caches the parsed
list per agent); no restart needed.
## Matching rules
- **Whole word, case-insensitive.** `Boss` matches `boss` and `BOSS`, and
matches even with surrounding punctuation (`boss!`, `hey, boss`). It does
**not** match substrings — `bosses` or `bossy` will not trigger.
- **Unicode-aware.** Matching tokenizes on Unicode letters/digits rather than an
ASCII `\b`, so aliases in any script (Cyrillic, CJK, accented Latin, …) match
as whole words.
- Both the message text and a media **caption** are checked.
## Requirements
- **Groups only.** DMs already respond to every message, so trigger words only
affect group (and channel) chats.
- **Disable the bot's Group Privacy in BotFather** (`/mybots` → Bot Settings →
Group Privacy → Turn off), then re-add the bot to the group — otherwise
Telegram never delivers plain (non-mention) group messages to the bot, and the
gate has nothing to evaluate. Making the bot a group admin has the same effect.
- The group's pairing/policy gate still applies: a trigger word is treated like
an `@mention`, so an unpaired group under `group_policy: pairing` still gets a
pairing prompt rather than an answer.
## Implementation
- `bootstrap.ParseTriggerWords` extracts the list from `IDENTITY.md`.
- `internal/channels/telegram/wake_words.go` normalizes the list and does the
whole-word, Unicode-aware match.
- The channel loads the agent's list via `GetAgentContextFiles` (tenant-scoped)
and caches it per agent; the group gate in `handlers.go` treats a match as a
mention.