Telegram (Bot API)
Status: Produktionsreif für Bot-DMs und Gruppen via grammY. Standardmäßig Long-Polling; Webhook optional.
Schnellstart (Einsteiger)
- Erstelle einen Bot mit @BotFather (Direktlink). Bestätige, dass der Handle exakt
@BotFatherist, und kopiere dann den Token. - Setze den Token:
- Umgebungsvariable:
TELEGRAM_BOT_TOKEN=... - Oder Config:
channels.telegram.botToken: "...". - Wenn beides gesetzt ist, hat die Config Vorrang (Umgebungsvariable gilt nur für den Standard-Account).
- Umgebungsvariable:
- Starte den Gateway.
- DM-Zugriff nutzt standardmäßig Pairing; genehmige den Pairing-Code beim ersten Kontakt.
Minimale Config:
{
channels: {
telegram: {
enabled: true,
botToken: "123:abc",
dmPolicy: "pairing",
},
},
}
Was ist das
- Ein Telegram Bot API Channel, der vom Gateway verwaltet wird.
- Deterministisches Routing: Antworten gehen zurück zu Telegram; das Modell wählt nie selbst Channels aus.
- DMs teilen sich die Haupt-Session des Agents; Gruppen bleiben isoliert (
agent:<agentId>:telegram:group:<chatId>).
Setup (schneller Weg)
1) Bot-Token erstellen (BotFather)
- Öffne Telegram und chatte mit @BotFather (Direktlink). Bestätige, dass der Handle exakt
@BotFatherist. - Führe
/newbotaus und folge den Anweisungen (Name + Username, der aufbotendet). - Kopiere den Token und bewahre ihn sicher auf.
Optionale BotFather-Einstellungen:
/setjoingroups— erlaube/verbiete das Hinzufügen des Bots zu Gruppen./setprivacy— steuere, ob der Bot alle Gruppennachrichten sieht.
2) Token konfigurieren (Umgebungsvariable oder Config)
Beispiel:
{
channels: {
telegram: {
enabled: true,
botToken: "123:abc",
dmPolicy: "pairing",
groups: { "*": { requireMention: true } },
},
},
}
Umgebungsvariable: TELEGRAM_BOT_TOKEN=... (funktioniert für den Standard-Account).
Wenn sowohl Umgebungsvariable als auch Config gesetzt sind, hat die Config Vorrang.
Multi-Account-Unterstützung: Nutze channels.telegram.accounts mit Token pro Account und optionalem name. Siehe gateway/configuration für das gemeinsame Muster.
- Starte den Gateway. Telegram startet, wenn ein Token aufgelöst wird (Config zuerst, Umgebungsvariable als Fallback).
- DM-Zugriff nutzt standardmäßig Pairing. Genehmige den Code, wenn der Bot zum ersten Mal kontaktiert wird.
- Für Gruppen: Füge den Bot hinzu, entscheide über Privacy/Admin-Verhalten (siehe unten), und setze dann
channels.telegram.groups, um Mention-Gating und Allowlists zu steuern.
Token + Privacy + Berechtigungen (Telegram-Seite)
Token-Erstellung (BotFather)
/newboterstellt den Bot und gibt den Token zurück (halte ihn geheim).- Wenn ein Token geleakt ist, widerrufe/regeneriere ihn über @BotFather und aktualisiere deine Config.
Gruppennachrichten-Sichtbarkeit (Privacy Mode)
Telegram-Bots nutzen standardmäßig den Privacy Mode, der einschränkt, welche Gruppennachrichten sie empfangen. Wenn dein Bot alle Gruppennachrichten sehen muss, hast du zwei Optionen:
- Deaktiviere den Privacy Mode mit
/setprivacyoder - Füge den Bot als Gruppen-Admin hinzu (Admin-Bots empfangen alle Nachrichten).
Hinweis: Wenn du den Privacy Mode umschaltest, verlangt Telegram, dass du den Bot aus jeder Gruppe entfernst und wieder hinzufügst, damit die Änderung wirksam wird.
Gruppenberechtigungen (Admin-Rechte)
Der Admin-Status wird innerhalb der Gruppe gesetzt (Telegram UI). Admin-Bots empfangen immer alle Gruppennachrichten, also nutze Admin, wenn du volle Sichtbarkeit brauchst.
Wie es funktioniert (Verhalten)
- Eingehende Nachrichten werden in den gemeinsamen Channel-Envelope normalisiert, mit Antwort-Kontext und Media-Platzhaltern.
- Gruppenantworten erfordern standardmäßig eine Erwähnung (natives @mention oder
agents.list[].groupChat.mentionPatterns/messages.groupChat.mentionPatterns). - Multi-Agent-Override: Setze Agent-spezifische Patterns auf
agents.list[].groupChat.mentionPatterns. - Antworten werden immer zurück zum selben Telegram-Chat geroutet.
- Long-Polling nutzt grammY Runner mit Chat-spezifischer Sequenzierung; die Gesamt-Concurrency ist durch
agents.defaults.maxConcurrentbegrenzt. - Die Telegram Bot API unterstützt keine Lesebestätigungen; es gibt keine
sendReadReceipts-Option.
Draft Streaming
OpenClaw kann partielle Antworten in Telegram-DMs streamen, indem es sendMessageDraft nutzt.
Voraussetzungen:
- Threaded Mode für den Bot in @BotFather aktiviert (Forum-Topic-Modus).
- Nur private Chat-Threads (Telegram fügt
message_thread_idzu eingehenden Nachrichten hinzu). channels.telegram.streamModenicht auf"off"gesetzt (Standard:"partial","block"aktiviert chunked Draft-Updates).
Draft Streaming funktioniert nur in DMs; Telegram unterstützt es nicht in Gruppen oder Channels.
Formatierung (Telegram HTML)
- Ausgehender Telegram-Text nutzt
parse_mode: "HTML"(Telegrams unterstützte Tag-Teilmenge). - Markdown-ähnliche Eingabe wird in Telegram-sicheres HTML gerendert (fett/kursiv/durchgestrichen/code/links); Block-Elemente werden zu Text mit Zeilenumbrüchen/Bullets geflacht.
- Rohes HTML von Modellen wird escaped, um Telegram-Parse-Fehler zu vermeiden.
- Wenn Telegram die HTML-Payload ablehnt, versucht OpenClaw die gleiche Nachricht als Plain Text erneut.
Befehle (native + custom)
OpenClaw registriert native Befehle (wie /status, /reset, /model) beim Start im Telegram-Bot-Menü.
Du kannst custom Befehle über die Config zum Menü hinzufügen:
{
channels: {
telegram: {
customCommands: [
{ command: "backup", description: "Git backup" },
{ command: "generate", description: "Create an image" },
],
},
},
}
Troubleshooting
setMyCommands failedin den Logs bedeutet normalerweise, dass ausgehende HTTPS/DNS zuapi.telegram.orgblockiert ist.- Wenn du
sendMessage- odersendChatAction-Fehler siehst, prüfe IPv6-Routing und DNS.
Mehr Hilfe: Channel Troubleshooting.
Hinweise:
- Custom Befehle sind nur Menü-Einträge; OpenClaw implementiert sie nicht, außer du behandelst sie anderswo.
- Befehlsnamen werden normalisiert (führendes
/entfernt, kleingeschrieben) und müssena-z,0-9,_entsprechen (1–32 Zeichen). - Custom Befehle können native Befehle nicht überschreiben. Konflikte werden ignoriert und geloggt.
- Wenn
commands.nativedeaktiviert ist, werden nur custom Befehle registriert (oder gelöscht, wenn keine vorhanden sind).
Limits
- Ausgehender Text wird in Chunks von
channels.telegram.textChunkLimitaufgeteilt (Standard 4000). - Optionales Newline-Chunking: Setze
channels.telegram.chunkMode="newline", um bei Leerzeilen (Absatzgrenzen) zu splitten, bevor nach Länge gechunkt wird. - Media-Downloads/-Uploads sind durch
channels.telegram.mediaMaxMbbegrenzt (Standard 5). - Telegram Bot API Requests haben ein Timeout nach
channels.telegram.timeoutSeconds(Standard 500 via grammY). Setze einen niedrigeren Wert, um lange Hänger zu vermeiden. - Gruppen-History-Context nutzt
channels.telegram.historyLimit(oderchannels.telegram.accounts.*.historyLimit), mit Fallback aufmessages.groupChat.historyLimit. Setze0zum Deaktivieren (Standard 50). - DM-History kann mit
channels.telegram.dmHistoryLimit(User-Turns) begrenzt werden. Pro-User-Overrides:channels.telegram.dms["<user_id>"].historyLimit.
Gruppen-Aktivierungsmodi
Standardmäßig antwortet der Bot nur auf Erwähnungen in Gruppen (@botname oder Patterns in agents.list[].groupChat.mentionPatterns). Um dieses Verhalten zu ändern:
Via Config (empfohlen)
{
channels: {
telegram: {
groups: {
"-1001234567890": { requireMention: false }, // immer antworten in dieser Gruppe
},
},
},
}
Wichtig: Das Setzen von channels.telegram.groups erstellt eine Allowlist - nur gelistete Gruppen (oder "*") werden akzeptiert.
Forum-Topics erben die Config ihrer Parent-Gruppe (allowFrom, requireMention, skills, prompts), außer du fügst Topic-spezifische Overrides unter channels.telegram.groups.<groupId>.topics.<topicId> hinzu.
Um alle Gruppen mit Always-Respond zu erlauben:
{
channels: {
telegram: {
groups: {
"*": { requireMention: false }, // alle Gruppen, immer antworten
},
},
},
}
Um Mention-Only für alle Gruppen beizubehalten (Standardverhalten):
{
channels: {
telegram: {
groups: {
"*": { requireMention: true }, // oder groups komplett weglassen
},
},
},
}
Via Befehl (Session-Level)
Sende in der Gruppe:
/activation always- auf alle Nachrichten antworten/activation mention- Erwähnungen erforderlich (Standard)
Hinweis: Befehle aktualisieren nur den Session-State. Für persistentes Verhalten über Neustarts hinweg nutze die Config.
Gruppen-Chat-ID herausfinden
Leite eine beliebige Nachricht aus der Gruppe an @userinfobot oder @getidsbot auf Telegram weiter, um die Chat-ID zu sehen (negative Zahl wie -1001234567890).
Tipp: Für deine eigene User-ID schreibe dem Bot eine DM und er antwortet mit deiner User-ID (Pairing-Nachricht), oder nutze /whoami, sobald Befehle aktiviert sind.
Privacy-Hinweis: @userinfobot ist ein Drittanbieter-Bot. Wenn du das bevorzugst, füge den Bot zur Gruppe hinzu, sende eine Nachricht und nutze openclaw logs --follow, um chat.id zu lesen, oder verwende die Bot API getUpdates.
Config Writes
Standardmäßig darf Telegram Config-Updates schreiben, die durch Channel-Events oder /config set|unset ausgelöst werden.
Das passiert, wenn:
- Eine Gruppe zu einer Supergroup aufgewertet wird und Telegram
migrate_to_chat_idsendet (Chat-ID ändert sich). OpenClaw kannchannels.telegram.groupsautomatisch migrieren. - Du
/config setoder/config unsetin einem Telegram-Chat ausführst (erfordertcommands.config: true).
Deaktivieren mit:
{
channels: { telegram: { configWrites: false } },
}
Topics (Forum-Supergroups)
Telegram-Forum-Topics enthalten eine message_thread_id pro Nachricht. OpenClaw:
- Hängt
:topic:<threadId>an den Telegram-Gruppen-Session-Key an, sodass jedes Topic isoliert ist. - Sendet Typing-Indikatoren und Antworten mit
message_thread_id, sodass Antworten im Topic bleiben. - General Topic (Thread-ID
1) ist speziell: Nachrichten werden ohnemessage_thread_idgesendet (Telegram lehnt es ab), aber Typing-Indikatoren enthalten es trotzdem. - Stellt
MessageThreadId+IsForumim Template-Context für Routing/Templating bereit. - Topic-spezifische Konfiguration ist verfügbar unter
channels.telegram.groups.<chatId>.topics.<threadId>(skills, allowlists, auto-reply, system prompts, disable). - Topic-Configs erben Gruppen-Einstellungen (requireMention, allowlists, skills, prompts, enabled), außer sie werden pro Topic überschrieben.
Private Chats können in einigen Edge Cases message_thread_id enthalten. OpenClaw behält den DM-Session-Key unverändert, nutzt aber trotzdem die Thread-ID für Antworten/Draft-Streaming, wenn sie vorhanden ist.
Inline Buttons
Telegram unterstützt Inline-Keyboards mit Callback-Buttons.
{
channels: {
telegram: {
capabilities: {
inlineButtons: "allowlist",
},
},
},
}
Für Account-spezifische Konfiguration:
{
channels: {
telegram: {
accounts: {
main: {
capabilities: {
inlineButtons: "allowlist",
},
},
},
},
},
}
Scopes:
off— Inline-Buttons deaktiviertdm— nur DMs (Gruppen-Targets blockiert)group— nur Gruppen (DM-Targets blockiert)all— DMs + Gruppenallowlist— DMs + Gruppen, aber nur Sender, die durchallowFrom/groupAllowFromerlaubt sind (gleiche Regeln wie Control-Befehle)
Standard: allowlist.
Legacy: capabilities: ["inlineButtons"] = inlineButtons: "all".
Buttons senden
Nutze das Message-Tool mit dem buttons-Parameter:
{
action: "send",
channel: "telegram",
to: "123456789",
message: "Choose an option:",
buttons: [
[
{ text: "Yes", callback_data: "yes" },
{ text: "No", callback_data: "no" },
],
[{ text: "Cancel", callback_data: "cancel" }],
],
}
Wenn ein User einen Button klickt, werden die Callback-Daten als Nachricht an den Agent zurückgesendet, im Format:
callback_data: value
Konfigurationsoptionen
Telegram-Capabilities können auf zwei Ebenen konfiguriert werden (Objekt-Form oben gezeigt; Legacy-String-Arrays werden noch unterstützt):
channels.telegram.capabilities: Globale Standard-Capability-Config, die auf alle Telegram-Accounts angewendet wird, außer sie wird überschrieben.channels.telegram.accounts.<account>.capabilities: Account-spezifische Capabilities, die die globalen Standards für diesen Account überschreiben.
Nutze die globale Einstellung, wenn alle Telegram-Bots/Accounts sich gleich verhalten sollen. Nutze Account-spezifische Konfiguration, wenn verschiedene Bots unterschiedliches Verhalten brauchen (z.B. ein Account behandelt nur DMs, während ein anderer in Gruppen erlaubt ist).
Zugriffskontrolle (DMs + Gruppen)
DM-Zugriff
- Standard:
channels.telegram.dmPolicy = "pairing". Unbekannte Sender erhalten einen Pairing-Code; Nachrichten werden ignoriert, bis sie genehmigt sind (Codes laufen nach 1 Stunde ab). - Genehmigen via:
openclaw pairing list telegramopenclaw pairing approve telegram <CODE>
- Pairing ist der Standard-Token-Austausch für Telegram-DMs. Details: Pairing
channels.telegram.allowFromakzeptiert numerische User-IDs (empfohlen) oder@username-Einträge. Es ist nicht der Bot-Username; nutze die ID des menschlichen Senders. Der Wizard akzeptiert@usernameund löst es zur numerischen ID auf, wenn möglich.
Deine Telegram-User-ID herausfinden
Sicherer (kein Drittanbieter-Bot):
- Starte den Gateway und schreibe deinem Bot eine DM.
- Führe
openclaw logs --followaus und suche nachfrom.id.
Alternative (offizielle Bot API):
- Schreibe deinem Bot eine DM.
- Hole Updates mit deinem Bot-Token und lies
message.from.id:curl "https://api.telegram.org/bot<bot_token>/getUpdates"
Drittanbieter (weniger privat):
- Schreibe
@userinfobotoder@getidsboteine DM und nutze die zurückgegebene User-ID.
Gruppen-Zugriff
Zwei unabhängige Kontrollen:
1. Welche Gruppen erlaubt sind (Gruppen-Allowlist via channels.telegram.groups):
- Keine
groups-Config = alle Gruppen erlaubt - Mit
groups-Config = nur gelistete Gruppen oder"*"sind erlaubt - Beispiel:
"groups": { "-1001234567890": {}, "*": {} }erlaubt alle Gruppen
2. Welche Sender erlaubt sind (Sender-Filterung via channels.telegram.groupPolicy):
"open"= alle Sender in erlaubten Gruppen können Nachrichten senden"allowlist"= nur Sender inchannels.telegram.groupAllowFromkönnen Nachrichten senden"disabled"= keine Gruppennachrichten werden akzeptiert Standard istgroupPolicy: "allowlist"(blockiert, außer du fügstgroupAllowFromhinzu).
Die meisten User wollen: groupPolicy: "allowlist" + groupAllowFrom + spezifische Gruppen in channels.telegram.groups gelistet
Long-Polling vs Webhook
- Standard: Long-Polling (keine öffentliche URL erforderlich).
- Webhook-Modus: Setze
channels.telegram.webhookUrlundchannels.telegram.webhookSecret(optionalchannels.telegram.webhookPath).- Der lokale Listener bindet an
0.0.0.0:8787und bedientPOST /telegram-webhookstandardmäßig. - Wenn deine öffentliche URL anders ist, nutze einen Reverse Proxy und zeige
channels.telegram.webhookUrlauf den öffentlichen Endpoint.
- Der lokale Listener bindet an
Reply Threading
Telegram unterstützt optionale Thread-Antworten via Tags:
[[reply_to_current]]— antworte auf die auslösende Nachricht.[[reply_to:<id>]]— antworte auf eine spezifische Nachrichten-ID.
Gesteuert durch channels.telegram.replyToMode:
first(Standard),all,off.
Audio-Nachrichten (Voice vs File)
Telegram unterscheidet Voice Notes (runde Blase) von Audio-Dateien (Metadaten-Karte). OpenClaw nutzt standardmäßig Audio-Dateien für Rückwärtskompatibilität.
Um eine Voice-Note-Blase in Agent-Antworten zu erzwingen, füge dieses Tag irgendwo in die Antwort ein:
[[audio_as_voice]]— sende Audio als Voice Note statt als Datei.
Das Tag wird aus dem gelieferten Text entfernt. Andere Channels ignorieren dieses Tag.
Für Message-Tool-Sends setze asVoice: true mit einer Voice-kompatiblen Audio-media-URL
(message ist optional, wenn Media vorhanden ist):
{
action: "send",
channel: "telegram",
to: "123456789",
media: "https://example.com/voice.ogg",
asVoice: true,
}
Stickers
OpenClaw unterstützt das Empfangen und Senden von Telegram-Stickern mit intelligentem Caching.
Sticker empfangen
Wenn ein User einen Sticker sendet, behandelt OpenClaw ihn basierend auf dem Sticker-Typ:
- Statische Sticker (WEBP): Heruntergeladen und durch Vision verarbeitet. Der Sticker erscheint als
<media:sticker>-Platzhalter im Nachrichteninhalt. - Animierte Sticker (TGS): Übersprungen (Lottie-Format wird nicht für die Verarbeitung unterstützt).
- Video-Sticker (WEBM): Übersprungen (Video-Format wird nicht für die Verarbeitung unterstützt).
Template-Context-Feld verfügbar beim Empfangen von Stickern:
Sticker— Objekt mit:emoji— Emoji, das mit dem Sticker assoziiert istsetName— Name des Sticker-SetsfileId— Telegram-File-ID (sende den gleichen Sticker zurück)fileUniqueId— stabile ID für Cache-LookupcachedDescription— gecachte Vision-Beschreibung, wenn verfügbar
Sticker-Cache
Sticker werden durch die Vision-Fähigkeiten der AI verarbeitet, um Beschreibungen zu generieren. Da die gleichen Sticker oft wiederholt gesendet werden, cached OpenClaw diese Beschreibungen, um redundante API-Calls zu vermeiden.
Wie es funktioniert:
- Erste Begegnung: Das Sticker-Bild wird zur Vision-Analyse an die AI gesendet. Die AI generiert eine Beschreibung (z.B. “Eine Cartoon-Katze, die enthusiastisch winkt”).
- Cache-Speicherung: Die Beschreibung wird zusammen mit der File-ID, dem Emoji und dem Set-Namen des Stickers gespeichert.
- Nachfolgende Begegnungen: Wenn der gleiche Sticker wieder gesehen wird, wird die gecachte Beschreibung direkt genutzt. Das Bild wird nicht an die AI gesendet.
Cache-Speicherort: ~/.openclaw/telegram/sticker-cache.json
Cache-Entry-Format:
{
"fileId": "CAACAgIAAxkBAAI...",
"fileUniqueId": "AgADBAADb6cxG2Y",
"emoji": "👋",
"setName": "CoolCats",
"description": "A cartoon cat waving enthusiastically",
"cachedAt": "2026-01-15T10:30:00.000Z"
}
Vorteile:
- Reduziert API-Kosten durch Vermeidung wiederholter Vision-Calls für den gleichen Sticker
- Schnellere Antwortzeiten für gecachte Sticker (keine Vision-Verarbeitungsverzögerung)
- Ermöglicht Sticker-Suchfunktionalität basierend auf gecachten Beschreibungen
Der Cache wird automatisch gefüllt, wenn Sticker empfangen werden. Es ist kein manuelles Cache-Management erforderlich.
Sticker senden
Der Agent kann Sticker senden und suchen, indem er die sticker- und sticker-search-Actions nutzt. Diese sind standardmäßig deaktiviert und müssen in der Config aktiviert werden:
{
channels: {
telegram: {
actions: {
sticker: true,
},
},
},
}
Einen Sticker senden:
{
action: "sticker",
channel: "telegram",
to: "123456789",
fileId: "CAACAgIAAxkBAAI...",
}
Parameter:
fileId(erforderlich) — die Telegram-File-ID des Stickers. Erhalte diese vonSticker.fileIdbeim Empfangen eines Stickers oder von einemsticker-search-Ergebnis.replyTo(optional) — Nachrichten-ID, auf die geantwortet werden soll.threadId(optional) — Message-Thread-ID für Forum-Topics.
Nach Stickern suchen:
Der Agent kann gecachte Sticker nach Beschreibung, Emoji oder Set-Namen durchsuchen:
{
action: "sticker-search",
channel: "telegram",
query: "cat waving",
limit: 5,
}
Gibt passende Sticker aus dem Cache zurück:
{
ok: true,
count: 2,
stickers: [
{
fileId: "CAACAgIAAxkBAAI...",
emoji: "👋",
description: "A cartoon cat waving enthusiastically",
setName: "CoolCats",
},
],
}
Die Suche nutzt Fuzzy-Matching über Beschreibungstext, Emoji-Zeichen und Set-Namen.
Beispiel mit Threading:
{
action: "sticker",
channel: "telegram",
to: "-1001234567890",
fileId: "CAACAgIAAxkBAAI...",
replyTo: 42,
threadId: 123,
}
Streaming (Drafts)
Telegram kann Draft-Bubbles streamen, während der Agent eine Antwort generiert.
OpenClaw nutzt Bot API sendMessageDraft (keine echten Nachrichten) und sendet dann die
finale Antwort als normale Nachricht.
Voraussetzungen (Telegram Bot API 9.3+):
- Private Chats mit aktivierten Topics (Forum-Topic-Modus für den Bot).
- Eingehende Nachrichten müssen
message_thread_identhalten (privater Topic-Thread). - Streaming wird für Gruppen/Supergroups/Channels ignoriert.
Config:
channels.telegram.streamMode: "off" | "partial" | "block"(Standard:partial)partial: aktualisiere die Draft-Bubble mit dem neuesten Streaming-Text.block: aktualisiere die Draft-Bubble in größeren Blöcken (gechunkt).off: deaktiviere Draft-Streaming.
- Optional (nur für
streamMode: "block"):channels.telegram.draftChunk: { minChars?, maxChars?, breakPreference? }- Standards:
minChars: 200,maxChars: 800,breakPreference: "paragraph"(begrenzt aufchannels.telegram.textChunkLimit).
- Standards:
Hinweis: Draft-Streaming ist getrennt von Block-Streaming (Channel-Nachrichten).
Block-Streaming ist standardmäßig aus und erfordert channels.telegram.blockStreaming: true,
wenn du frühe Telegram-Nachrichten statt Draft-Updates willst.
Reasoning Stream (nur Telegram):
/reasoning streamstreamt Reasoning in die Draft-Bubble, während die Antwort generiert wird, und sendet dann die finale Antwort ohne Reasoning.- Wenn
channels.telegram.streamModeaufoffist, ist Reasoning Stream deaktiviert. Mehr Kontext: Streaming + chunking.
Retry Policy
Ausgehende Telegram API Calls werden bei transienten Netzwerk-/429-Fehlern mit exponentiellem Backoff und Jitter wiederholt. Konfiguriere via channels.telegram.retry. Siehe Retry Policy.
Agent Tool (Nachrichten + Reaktionen)
- Tool:
telegrammitsendMessage-Action (to,content, optionalmediaUrl,replyToMessageId,messageThreadId). - Tool:
telegrammitreact-Action (chatId,messageId,emoji). - Tool:
telegrammitdeleteMessage-Action (chatId,messageId). - Reaktions-Entfernungs-Semantik: siehe /tools/reactions.
- Tool-Gating:
channels.telegram.actions.reactions,channels.telegram.actions.sendMessage,channels.telegram.actions.deleteMessage(Standard: aktiviert), undchannels.telegram.actions.sticker(Standard: deaktiviert).
Reaktions-Benachrichtigungen
Wie Reaktionen funktionieren:
Telegram-Reaktionen kommen als separate message_reaction-Events, nicht als Properties in Nachrichten-Payloads. Wenn ein User eine Reaktion hinzufügt, macht OpenClaw Folgendes:
- Empfängt das
message_reaction-Update von der Telegram API - Konvertiert es zu einem System-Event mit Format:
"Telegram reaction added: {emoji} by {user} on msg {id}" - Reiht das System-Event mit dem gleichen Session-Key wie reguläre Nachrichten ein
- Wenn die nächste Nachricht in dieser Konversation ankommt, werden System-Events geleert und dem Context des Agents vorangestellt
Der Agent sieht Reaktionen als System-Benachrichtigungen in der Konversations-History, nicht als Nachrichten-Metadaten.
Konfiguration:
-
channels.telegram.reactionNotifications: Steuert, welche Reaktionen Benachrichtigungen auslösen"off"— ignoriere alle Reaktionen"own"— benachrichtige, wenn User auf Bot-Nachrichten reagieren (Best-Effort; in-memory) (Standard)"all"— benachrichtige für alle Reaktionen
-
channels.telegram.reactionLevel: Steuert die Reaktions-Fähigkeit des Agents"off"— Agent kann nicht auf Nachrichten reagieren"ack"— Bot sendet Bestätigungs-Reaktionen (👀 während der Verarbeitung) (Standard)"minimal"— Agent kann sparsam reagieren (Richtlinie: 1 pro 5-10 Austausche)"extensive"— Agent kann liberal reagieren, wenn angemessen
Forum-Gruppen: Reaktionen in Forum-Gruppen enthalten message_thread_id und nutzen Session-Keys wie agent:main:telegram:group:{chatId}:topic:{threadId}. Das stellt sicher, dass Reaktionen und Nachrichten im gleichen Topic zusammenbleiben.
Beispiel-Config:
{
channels: {
telegram: {
reactionNotifications: "all", // Alle Reaktionen sehen
reactionLevel: "minimal", // Agent kann sparsam reagieren
},
},
}
Voraussetzungen:
- Telegram-Bots müssen explizit
message_reactioninallowed_updatesanfordern (wird automatisch von OpenClaw konfiguriert) - Für Webhook-Modus sind Reaktionen in den Webhook-
allowed_updatesenthalten - Für Polling-Modus sind Reaktionen in den
getUpdates-allowed_updatesenthalten
Delivery Targets (CLI/Cron)
- Nutze eine Chat-ID (
123456789) oder einen Username (@name) als Target. - Beispiel:
openclaw message send --channel telegram --target 123456789 --message "hi".
Troubleshooting
Bot antwortet nicht auf Nicht-Erwähnungs-Nachrichten in einer Gruppe:
- Wenn du
channels.telegram.groups.*.requireMention=falsesetzt, muss der Privacy Mode der Telegram Bot API deaktiviert sein.- BotFather:
/setprivacy→ Disable (dann entferne den Bot aus der Gruppe und füge ihn wieder hinzu)
- BotFather:
openclaw channels statuszeigt eine Warnung, wenn die Config unerwähnte Gruppennachrichten erwartet.openclaw channels status --probekann zusätzlich die Mitgliedschaft für explizite numerische Gruppen-IDs prüfen (es kann keine Wildcard-"*"-Regeln prüfen).- Schnelltest:
/activation always(nur Session; nutze Config für Persistenz)
Bot sieht überhaupt keine Gruppennachrichten:
- Wenn
channels.telegram.groupsgesetzt ist, muss die Gruppe gelistet sein oder"*"nutzen - Prüfe Privacy-Einstellungen in @BotFather → “Group Privacy” sollte OFF sein
- Verifiziere, dass der Bot tatsächlich Mitglied ist (nicht nur Admin ohne Lesezugriff)
- Prüfe Gateway-Logs:
openclaw logs --follow(suche nach “skipping group message”)
Bot antwortet auf Erwähnungen, aber nicht auf /activation always:
- Der
/activation-Befehl aktualisiert den Session-State, persistiert aber nicht in die Config - Für persistentes Verhalten füge die Gruppe zu
channels.telegram.groupsmitrequireMention: falsehinzu
Befehle wie /status funktionieren nicht:
- Stelle sicher, dass deine Telegram-User-ID autorisiert ist (via Pairing oder
channels.telegram.allowFrom) - Befehle erfordern Autorisierung, auch in Gruppen mit
groupPolicy: "open"
Long-Polling bricht sofort ab auf Node 22+ (oft mit Proxies/custom fetch):
- Node 22+ ist strenger bei
AbortSignal-Instanzen; fremde Signals könnenfetch-Calls sofort abbrechen. - Upgrade auf einen OpenClaw-Build, der Abort-Signals normalisiert, oder führe den Gateway auf Node 20 aus, bis du upgraden kannst.
Bot startet, hört dann still auf zu antworten (oder loggt HttpError: Network request ... failed):
- Einige Hosts lösen
api.telegram.orgzuerst zu IPv6 auf. Wenn dein Server keinen funktionierenden IPv6-Egress hat, kann grammY bei IPv6-only-Requests hängen bleiben. - Behebe das, indem du IPv6-Egress aktivierst oder IPv4-Auflösung für
api.telegram.orgerzwingst (z.B. füge einen/etc/hosts-Eintrag mit dem IPv4-A-Record hinzu, oder bevorzuge IPv4 in deinem OS-DNS-Stack), dann starte den Gateway neu. - Schnellcheck:
dig +short api.telegram.org Aunddig +short api.telegram.org AAAA, um zu bestätigen, was DNS zurückgibt.
Konfigurationsreferenz (Telegram)
Vollständige Konfiguration: Configuration
Provider-Optionen:
channels.telegram.enabled: Channel-Start aktivieren/deaktivieren.channels.telegram.botToken: Bot-Token (BotFather).channels.telegram.tokenFile: Token aus Dateipfad lesen.channels.telegram.dmPolicy:pairing | allowlist | open | disabled(Standard: pairing).channels.telegram.allowFrom: DM-Allowlist (IDs/Usernames).openerfordert"*".channels.telegram.groupPolicy:open | allowlist | disabled(Standard: allowlist).channels.telegram.groupAllowFrom: Gruppen-Sender-Allowlist (IDs/Usernames).channels.telegram.groups: Pro-Gruppen-Standards + Allowlist (nutze"*"für globale Standards).channels.telegram.groups.<id>.requireMention: Mention-Gating-Standard.channels.telegram.groups.<id>.skills: Skill-Filter (weglassen = alle Skills, leer = keine).channels.telegram.groups.<id>.allowFrom: Pro-Gruppen-Sender-Allowlist-Override.channels.telegram.groups.<id>.systemPrompt: Extra-System-Prompt für die Gruppe.channels.telegram.groups.<id>.enabled: Gruppe deaktivieren, wennfalse.channels.telegram.groups.<id>.topics.<threadId>.*: Pro-Topic-Overrides (gleiche Felder wie Gruppe).channels.telegram.groups.<id>.topics.<threadId>.requireMention: Pro-Topic-Mention-Gating-Override.
channels.telegram.capabilities.inlineButtons:off | dm | group | all | allowlist(Standard: allowlist).channels.telegram.accounts.<account>.capabilities.inlineButtons: Pro-Account-Override.channels.telegram.replyToMode:off | first | all(Standard:first).channels.telegram.textChunkLimit: Ausgehende Chunk-Größe (Zeichen).channels.telegram.chunkMode:length(Standard) odernewline, um bei Leerzeilen (Absatzgrenzen) zu splitten, bevor nach Länge gechunkt wird.channels.telegram.linkPreview: Link-Vorschauen für ausgehende Nachrichten umschalten (Standard: true).channels.telegram.streamMode:off | partial | block(Draft-Streaming).channels.telegram.mediaMaxMb: Eingehende/ausgehende Media-Begrenzung (MB).channels.telegram.retry: Retry-Policy für ausgehende Telegram API Calls (attempts, minDelayMs, maxDelayMs, jitter).channels.telegram.network.autoSelectFamily: Node autoSelectFamily überschreiben (true=aktivieren, false=deaktivieren). Standardmäßig deaktiviert auf Node 22, um Happy-Eyeballs-Timeouts zu vermeiden.channels.telegram.proxy: Proxy-URL für Bot API Calls (SOCKS/HTTP).channels.telegram.webhookUrl: Webhook-Modus aktivieren (erfordertchannels.telegram.webhookSecret).channels.telegram.webhookSecret: Webhook-Secret (erforderlich, wenn webhookUrl gesetzt ist).channels.telegram.webhookPath: Lokaler Webhook-Pfad (Standard/telegram-webhook).channels.telegram.actions.reactions: Telegram-Tool-Reaktionen gaten.channels.telegram.actions.sendMessage: Telegram-Tool-Nachrichten-Sends gaten.channels.telegram.actions.deleteMessage: Telegram-Tool-Nachrichten-Deletes gaten.channels.telegram.actions.sticker: Telegram-Sticker-Actions gaten — senden und suchen (Standard: false).channels.telegram.reactionNotifications:off | own | all— steuere, welche Reaktionen System-Events auslösen (Standard:own, wenn nicht gesetzt).channels.telegram.reactionLevel:off | ack | minimal | extensive— steuere die Reaktions-Fähigkeit des Agents (Standard:minimal, wenn nicht gesetzt).
Verwandte globale Optionen:
agents.list[].groupChat.mentionPatterns(Mention-Gating-Patterns).messages.groupChat.mentionPatterns(globaler Fallback).commands.native(Standard:"auto"→ on für Telegram/Discord, off für Slack),commands.text,commands.useAccessGroups(Befehls-Verhalten). Override mitchannels.telegram.commands.native.messages.responsePrefix,messages.ackReaction,messages.ackReactionScope,messages.removeAckAfterReply.