Telegram
Telegram funktioniert in beiden Modi:
| Modus | Was er tut |
|---|---|
| Notification | Einseitiges sendMessage von der Alarmpipeline. |
| IM bridge | Zweiseitiger Chat mit dem Agenten via getUpdates-Long-Poll. |
Dasselbe Bot-Token (8…:AA…, von @BotFather) treibt beide an — Telegram authentifiziert per Token-im-Pfad. Es gibt kein separates Signaturschema.
Entworfen für Benutzer außerhalb des Feishu- / DingTalk-Gebiets
Telegram ist der IM-Kanal, den Ongrid für Nicht-China-Teams und für hybride Bereitstellungen empfiehlt, wo die Operatoren zufällig auf Telegram leben. Der Provider wurde in ADR-031 hinzugefügt.
Notification-Modus
Ein notify.Sender POSTet {chat_id, text} an https://api.telegram.org/bot<TOKEN>/sendMessage. Die Credential ist das Bot-Token (im Pfad); die chat_id (numerisch) ist der Ziel-Chat.
// internal/pkg/notify/webhook.go
NewTelegramSender(name, endpoint, chatID, client)Wo endpoint die wörtliche …/bot<TOKEN>/sendMessage-URL ist und chatID der Ziel-Chat (eine numerische User-ID für eine DM, oder die negative Zahl, die Telegram für eine Gruppe gibt).
Setup:
- DM
@BotFather→/newbot→ Username auswählen → Token kopieren. - Bot zum Ziel-Chat (Gruppe / Channel) hinzufügen oder einmal DMen, damit er von Ihnen weiß.
- Die Chat-ID greifen. Der schnellste Weg: irgendeine Nachricht im Chat senden, dann
curl https://api.telegram.org/bot<TOKEN>/getUpdatesundresult[0].message.chat.idlesen. - In Ongrid: Settings → Channels → New → Provider =
telegram→ Endpoint =https://api.telegram.org/bot<TOKEN>/sendMessage, chat_id = die Zahl aus Schritt 3.
IM-Bridge-Modus (zweiseitig)
Eingehend wird vom ausgehenden HTTPS-Connection des Managers long-gepollt. Weil der Aufruf ausgehend ist, funktioniert Telegram hinter NAT, Firewalls und HTTPS-Proxies. setWebhook (die Alternative) würde erfordern, dass Telegram den Manager erreicht — das ist inkompatibel mit den meisten privaten Cloud-Bereitstellungen und unzuverlässig vom Festland China aus.
stream ist der einzige Modus
Der Validator lehnt alles andere ab:
telegram only supports stream mode
Webhook-Modus ist in der UI für Telegram nicht exponiert.
Credential-Mapping
Die im_apps-Zeile verwendet bestehende Spalten wieder — keine Schema-Änderungen:
im_apps-Spalte | Telegram-Bedeutung |
|---|---|
provider | "telegram" |
mode | "stream" (Validator pinnt das) |
app_id | Bot-Username (z. B. ongridbot). Display + Dedupe. |
app_secret | BotFather-Token (8…:AA…). Verschlüsselt at rest. |
allow_from | Erforderlich komma-getrennte numerische User-IDs. |
verify_token | Unbenutzt. |
encrypt_key | Unbenutzt. |
allow_from
Eine nicht-leere Liste numerischer Telegram-User-IDs, die mit dem Bot konversieren dürfen. Der Validator droppt nicht-numerische Tokens (sodass ein vertipptes alice als sauberer Required-Error landet, nicht als stillschweigend leere Allowlist) und lehnt negative Tokens ab (das sind Gruppen-/Supergruppen-Chat-IDs und gehören nicht in eine Sender-Allowlist).
telegram requires allow_from — at least one numeric Telegram user ID (the bot is publicly reachable; an empty allowlist would let anyone command the agent)
Wie man eine numerische User-ID findet:
- DM
@userinfobotund es antwortet mit Ihrer numerischen ID. - Oder eine Nachricht im Chat nach der Registrierung senden,
curl https://api.telegram.org/bot<TOKEN>/getUpdatesausführen undresult[0].message.from.idlesen.
telegram:- / tg:-Präfixe werden stillschweigend entfernt (OpenClaw-Kompatibilität), sodass telegram:123456789 und 123456789 derselbe Eintrag sind.
Stilles Droppen bei Miss
Nicht in der Allowlist befindliche Sender werden mit einem WARN-Log gedroppt:
telegram inbound from non-allowlisted sender — ignored
user_id=42 user_name=alice chat_id=42Es gibt keine Antwort. Es gibt keinen Platzhalter. Der Bot bestätigt nicht einmal, dass er existiert. Das spiegelt OpenClaw allowFrom — eine Antwort würde leaken, dass ein agent-gestützter Bot unter diesem Username lebt und Menschen versuchen lassen, ihn zu sondieren.
Setup
- DM
@BotFather→/newbot→ einen Namen und einen einzigartigen Username, der aufbotendet, wählen. Token kopieren. - (Optional)
@BotFather → /setprivacy → Disable, wenn Sie möchten, dass der Bot Nachrichten in Gruppen sieht (Default ist nur-Mention). - Ihre numerische User-ID via
@userinfobotfinden. - In Ongrid: Settings → IM bridge → New → Provider =
telegram→ Mode =stream→ App ID = der Bot-Username → App secret = das BotFather-Token →allow_from= Ihre numerische ID (und die Ihrer Teamkollegen). Save und Enable. - Den Bot von einem in der Allowlist befindlichen Account DMen. Der Bot antwortet mit einem Platzhalter und editiert ihn dann in place, während der Agent argumentiert.
Die Proxy-Story
Der Telegram-API-Host (api.telegram.org) ist auf den meisten Netzwerken erreichbar, aber vom Festland China aus blockiert. Der Provider verwendet einen Zero-Value http.Client, sodass er HTTPS_PROXY / HTTP_PROXY / NO_PROXY aus der Umgebung des Managers ehrt — derselbe Proxy, der getUpdates trägt, trägt sendMessage.
In docker-compose-Bereitstellungen persistieren Sie den Proxy in docker-compose.override.yml:
services:
manager:
environment:
HTTPS_PROXY: http://your-proxy:8080
NO_PROXY: localhost,127.0.0.1,manager,mysql,prometheus,loki,tempo,grafana,qdrantDen Proxy nicht in die Haupt-docker-compose.yml setzen
Die Haupt-docker-compose.yml wird mit jedem Release ausgeliefert. Eine Override-Datei ist per-Umgebung und überlebt make package / Install-Skript-Reruns.
Eigenheiten, die zu kennen sich lohnt
message is not modified ist harmlos
Telegram gibt HTTP 400 (message is not modified) zurück, wenn ein editMessageText-Payload exakt mit dem aktuellen Nachrichtentext übereinstimmt. Progressives Streaming kann denselben Chunk auf einem gedrosselten Tick oder auf dem finalen Flush wiederholen. Der Client schluckt genau diese Fehlerzeichenkette und gibt nil zurück — alles andere (400, 403, 5xx) propagiert weiter. Siehe EditMessageText.
Nur ein Poller pro Bot
Telegram lehnt parallele getUpdates-Aufrufe ab. Der StreamSupervisor erzwingt einen Client pro im_app-Zeile. Wenn Sie eine Telegram-App-Zeile duplizieren, wird nur eine erfolgreich pollen — die andere wird 409 Conflict sehen und zurückfallen.
Rate-Limit-Retries
429 Too Many Requests wird bis zu 3-mal wiederholt. Das Warten ehrt Telegrams parameters.retry_after, gecappt auf 60s. 5xx-Fehler wiederholen mit 1s / 2s / 4s Backoff. Hartes 4xx (400/401/403) wiederholt nicht — es blubbert zum Supervisor und deutet wahrscheinlich auf ein Token-/Chat-ID-Problem hin. Siehe maxCallRetries.
Long-Poll-Timeout
Der serverseitige Long-Poll wartet 25s (pollTimeoutSec) mit einem 10s-Buffer auf der Client-Seite. Langsame Netzwerke sehen einfach längere Poll-Zyklen; der Supervisor macht keine Busy-Wait-Reconnects.
Nur Text
Sticker, Fotos, Sprachnachrichten und Dateien werden stillschweigend gedroppt. Nur message.text-Events treiben einen Agent-Turn. Der Bridge ist absichtlich S1 (Text rein / Text raus); rich media ist eine zukünftige Erweiterung.