# Modul-26-Telegram-Gateway **Status:** FREIGEGEBEN (2026-08-21) **Port:** 55026 (nur Docker-intern, kein öffentlicher Port) **Container:** `Modul-26-Telegram-Gateway` **Image:** `telegram-gateway:0.1.0` **Netzwerk:** `trading-modules` ## Zweck Dünner, **tool-loser** Adapter zwischen Telegram und M17 Hermes-Agent. Ermöglicht die Bedienung von Hermes vom Handy über einen eigenen Telegram-Bot. **KEINE Trading-Tools**, kein M09/M07/M08/M15-Control-Zugriff. Safety bleibt deterministisch in M17. ## Architektur ``` Telegram Bot API │ Polling (getUpdates) — KEIN Webhook, kein öffentlicher Port ▼ Modul-26-Telegram-Gateway (Port 55026 intern) │ Auth-Allowlist, Rate-Limit, Audit — NUR HTTP-Calls an M17, KEINE Tools ▼ Modul-17-Hermes-Agent (POST /tasks llm=true) │ Tool-Whitelist + Task-Gates (deterministisch, UNVERÄNDERT) ▼ LLM (Cloud deepseek-v4-flash:cloud Standard / Local llama3.1:8b explizit) ``` ## Sicherheitsmodell - **Allowlist:** Nur explizit erlaubte User-/Chat-IDs (`TELEGRAM_ALLOWED_IDS`, kommagetrennt). Unbekannte User werden **hart abgelehnt** (kein Task, Log-Eintrag, Status `REJECTED`/`UNAUTHORIZED`). - **Rate-Limit:** Sliding-Window pro User/Chat (Default 10/min). Überschreitung → `REJECTED`/`RATE_LIMITED`. - **Idempotenz:** `update_id` als PK in `telegram_message`. Bereits verarbeitete Updates werden übersprungen. - **Secrets:** Bot-Token NUR via ENV/Secret (`TELEGRAM_BOT_TOKEN`), nie im Code. Keine Secrets in DB/Logs/Doku. - **Prompt-Injection:** M17 behandelt externe Eingaben als untrusted data. Tool-Whitelist + Task-Gates hart im Code. - **Doppelte Barriere:** Gateway ist tool-los (nur HTTP-Calls an M17) + M17-Whitelist deterministisch. ## Commands | Command | M17 task_type | Beschreibung | |---------|---------------|--------------| | `/status` | — | Hermes-Health (synchron) | | `/research` | research | Markt-/Regime-Analyse | | `/analytics` | analytics | Portfolio-/Strategie-Analyse | | `/backtest` | backtest | Backtest starten | | `/optimize` | optimization | Optimierung starten | | `/monitoring` | monitoring | Monitoring-Status | | `/tasks` | — | Letzte Tasks (synchron) | | `/help` | — | Hilfe | | Freitext | research | Wird als Research-Analyse behandelt | ## Asynchrone Task-Abwicklung Lange Tasks (Cloud 5-23s, explizit lokale Analyse bis zu Minuten) laufen asynchron: 1. Sofortige Bestätigung an denselben Chat ("⏳ *task* gestartet…"). 2. Task wird in Background-Thread an M17 gesendet (`POST /tasks` mit `llm=true`). 3. Ergebnis wird später an denselben Chat zurückgesendet. ### Ergebnis-/Fehlerbehandlung - **SUCCEEDED:** M26 sendet die finale Hermes-Analyse (`analysis`) + kompakte Tool-Liste. Tool-Fehler (z.B. 404/keine Marktdaten) **brechen den Flow nicht ab** — die finale Analyse mit Einschränkungen wird trotzdem verständlich an Telegram gesendet, einzelne Tools als `[FAILED]` gelistet. - **FAILED:** M26 sendet eine **klare Fehlermeldung** (`🔴 *task* fehlgeschlagen (Status: FAILED)` + Fehlercode + Details) — NICHT irreführend "✅ abgeschlossen". ## Prompt-/UX-Fix (2026-08-21) Hermes (M17 System-Prompt) formuliert **NIEMALS**, dass eine Order „an einen Execution-Agenten delegiert" oder „zur Ausführung weitergeleitet" wird — es gibt keinen solchen Ausführungspfad. Stattdessen stellt Hermes klar: > **„Hermes kann keine Orders ausführen. Es kann nur analysieren, Research durchführen und DRAFT-Vorschläge erstellen."** Wenn eine Order gewünscht ist, antwortet Hermes mit dieser Klarstellung + Analyse-/DRAFT-Vorschlag. Keine Safety-Logik wurde geändert (Tool-Whitelist + Task-Gates unverändert). ## Audit DB-Tabelle `telegram_message` (Migration `001_telegram_gateway.sql`): - `update_id` (PK), `chat_id`, `user_id`, `username`, `text`, `command` - `task_id`, `run_id`, `status`, `error_code`, `created_at` Nachvollziehbarkeit: **update_id → task_id → run_id → LLM-run → Tool-Calls** (via M17 hermes_llm_run + hermes_tool_call). ## API (Port 55026 intern) - `GET /health` — Liveness - `GET /health/ready` — Readiness (Telegram-Token + Allowlist) - `GET /messages/recent` — Letzte Messages (Audit) - `GET /messages/{update_id}` — Einzelne Message - `POST /messages/test` — Test-Nachricht an konfigurierte Destination ## Konfiguration (ENV) | Variable | Beschreibung | |----------|--------------| | `TELEGRAM_BOT_TOKEN` | Bot-Token (Secret, NUR ENV) | | `TELEGRAM_ALLOWED_IDS` | Kommagetrennte erlaubte User-/Chat-IDs | | `TELEGRAM_API_BASE` | Telegram API-Base (Default `https://api.telegram.org`; für E2E Fake-Server) | | `M17_BASE_URL` | M17 Hermes-Agent (Default `http://Modul-17-Hermes-Agent:55017`) | | `PG_HOST/PORT/USER/PASSWORD/DB` | PostgreSQL (Modul-01) | ## E2E-Tests `tests/e2e_m26.py` (20/20 grün, 2026-08-21): 1. Unknown user reject 2. /status 3. /research (+ Ergebnis) 4. /analytics (+ Ergebnis) 5. /backtest (+ Ergebnis) 6. /optimize (+ Ergebnis) 7. /monitoring (+ Ergebnis) 8. /tasks 9. /help 10. Freitext → research (+ Ergebnis) 11. Safety: place_order im Prompt → keine Order 12. Rate-Limit 13. Audit: update_id → task_id → run_id Test-Infrastruktur: `tests/fake_telegram.py` (Fake-Telegram Bot API Server mit Steuer-API für E2E). ## Wichtige Hinweise - **M20 bleibt reserviert für Universe-Scheduler** — M26 ist separat. - **M14 NICHT verändern** — M26 nutzt nur das FAIL-SAFE-Muster als Vorlage, koppelt nicht an M14. - **M17 Safety-Gates unverändert** — M26 fügt nur einen dünnen Adapter hinzu. - **Kein öffentlicher Port** — nur `expose` im Compose.