--- title: Telegram Orchestrator url: https://blog.guigpap.com/fr/workflows/telegram-orchestrator/ url_md: https://blog.guigpap.com/fr/workflows/telegram-orchestrator.md category: tooling date: '2026-01-20' maturite: production techno: - n8n - telegram - claude application: - automation - operations --- # Telegram Orchestrator > Bot Telegram central, hub de routage 124 nodes orchestrant 13 sub-workflows callback et 4 service handlers ## 1. Quoi ? — Définition et contexte Le **Telegram Orchestrator** est le workflow N8N qui sert de point d'entrée pour toutes les interactions humaines avec l'infrastructure VPS. Il reçoit chaque message et chaque callback Telegram, vérifie l'authentification, route vers le bon handler, et délègue les tâches longues à 13 sub-workflows callback + 4 service handlers extraits. > **Note - Fire-and-forget vs wait-for-result** > > Les sub-workflows callback (SW-1 à SW-13) sont **fire-and-forget** : l'orchestrateur déclenche, ne lit pas le retour, et reste libre de traiter d'autres messages. Les service handlers (Docker, Odoo, N8N, General) sont **wait-for-result** : l'orchestrateur attend la réponse pour la formater et l'envoyer à l'utilisateur. ### Composants au plus haut niveau | Composant | Rôle | |-----------|------| | **Telegram Bot** | Interface utilisateur (messages, boutons inline, ForceReply) | | **IA Router** | Détection d'intent via Claude (5 services : docker, n8n, odoo, content, general) | | **Command Router** | Parsing `/menu`, `/docker`, `/n8n`, `/odoo`, `/help`, `/notif`, `/todo`, `/triage`, `/projet`, `/note`, `/blog`, `/research`, `/new`, `/conv`, `/endconv`, `/model`, `/plan`, `/templates`, `/mcp` | | **13 sub-workflows callback** | Auth, menus, n8n actions, photos, conversations, file provider, etc. | | **4 service handlers** | Docker, Odoo, N8N, General (chat Claude) | | **Binary Content Handler** | Photos (via Vision OCR), notes vocales, vCard, PDF, vidéos | | **Conversation Agent + Plan Engine** | Conversations multi-tours et plans d'action | ### Architecture visuelle ```mermaid flowchart TD Message["Telegram · message ou callback"] subgraph Orchestrateur["Telegram Orchestrator · 124 nodes"] direction TB ExtractUser["Extract User ID"] CheckBan["Check User Banned?"] RouteUpdate["Route by Update Type"] Parse["Parse Callback / Message Type"] RouteService["Route by Service"] end subgraph CB["Sub-workflows callback · fire-and-forget"] direction TB SW1["SW-1 File Provider · 20n"] SW2["SW-2 Docker Response Sender · 7n"] SW3["SW-3 New User Notifier · 7n"] SW4["SW-4 Auth Callback · 26n"] SW5["SW-5 N8N Action Response · 21n"] SW7["SW-7a Menu Renderer · 12n"] SW8["SW-8 Free Text Handler · 10n"] SW9["SW-9 Notif Mode Handler · 10n"] SW10["SW-10 Content Action · 10n"] SW11["SW-11 Conv Callback · 87n"] SW12["SW-12 Odoo Project Picker · 10n"] SW13["SW-13 Photo Action · 19n"] end subgraph SH["Service handlers · wait-for-result"] direction TB SHDocker["Service Handler Docker"] SHOdoo["Service Handler Odoo · 33n"] SHN8N["Service Handler N8N · 6n"] SHN8NEx["SH-N8N Action Executor · 37n"] SHGeneral["Service Handler General · 10n"] end subgraph Conv["Conversation system"] direction TB ConvMgr["Conversation Manager"] ConvAgent["Conversation Agent"] Plan["Plan Engine"] end Binary["Binary Content Handler · 21n"] Vision["Vision OCR · 14n"] Message --> ExtractUser --> CheckBan --> RouteUpdate RouteUpdate --> Parse --> RouteService Parse --> SW1 Parse --> SW4 Parse --> SW5 Parse --> SW9 Parse --> SW10 Parse --> SW11 Parse --> SW13 RouteService --> SW7 RouteService --> SW8 RouteService --> SW12 RouteService --> SHDocker RouteService --> SHOdoo RouteService --> SHN8N --> SHN8NEx RouteService --> SHGeneral RouteService --> Binary --> Vision RouteService --> ConvAgent ConvAgent --> Plan ConvMgr --> ConvAgent SHDocker --> SW2 RouteUpdate --> SW3 ``` ### Les 21 commandes | Catégorie | Commandes | |-----------|-----------| | **Menu** | `/menu`, `/start`, `/docker`, `/n8n`, `/odoo`, `/help`, `/notif`, `/todo`, `/triage` | | **Contenu** | `/note`, `/blog`, `/research` | | **Conversation** | `/new`, `/conv`, `/endconv`, `/model`, `/plan`, `/templates`, `/mcp` | | **Projet** | `/projet` (sous-commandes `list`, `create`, `status` avec picker paginé) | --- ## 2. Pourquoi ? — Enjeux et motivations ### Problèmes résolus | Problème | Sans orchestrator | Avec orchestrator | |----------|-------------------|-------------------| | **Accès SSH distant** | Connexion SSH pour chaque action | Message Telegram depuis le mobile | | **Commandes complexes** | Mémoriser les commandes Docker | Langage naturel + menus | | **Sécurité** | SSH exposé | Bot authentifié + whitelist | | **Réactivité** | Pas de notification des problèmes | Alertes + actions immédiates | ### Pourquoi un refactoring en sub-workflows (#273-#294) ? L'orchestrateur initial avait grossi à **224 nodes** au point de rendre l'UI N8N lente et l'édition risquée (déplacer un node pouvait casser des connexions hors écran). Trois vagues de refactoring ont ramené le parent à 124 nodes en extrayant les chemins fire-and-forget : | Vague | Issue | Effet | |-------|-------|-------| | **Phase 1** | #273 | 224 → 142 nodes (5 SWs) | | **Phase 2** | #273 | 142 → 98 nodes (5 SWs supplémentaires) | | **Conv Mgr** | #278 | 47→21 + 32 (Conversation Command Handlers) | | **SH-N8N** | #279 | Service Handler N8N 40→6 + SH-N8N Action Executor 37 | | **Photo routing** | #176 | +9 nodes pour photo conv-routing + SW-13 | | **MCP menu** | #294 | Conv Agent 16→21 + SW-11 72→87 | Le contrat de chaque SW est strict : entrée passthrough ou typée, sortie ignorée par le parent (pour les fire-and-forget), pas d'effet de bord sur le runtime principal. ### Fonctionnalités clés | Fonction | Description | |----------|-------------| | **Authentification** | Whitelist d'utilisateurs, approbation admin, ban list | | **Intent detection** | Claude analyse le langage naturel (5 services) | | **Menus interactifs** | Boutons inline pour actions fréquentes | | **Multi-service** | Docker, N8N, Odoo, Content depuis une interface unique | | **Voice + Photo** | Transcription audio + extraction d'images | | **Conversations** | Multi-tours avec mémoire Redis et tool calls | | **Plans d'action** | Multi-étapes avec escalade hybride | | **MCP** | Outils n8n natifs activables par conversation | --- ## 3. Comment ? — Mise en œuvre technique ### Authentification | Étape | Action | |-------|--------| | 1. Extract user ID | Récupère `userId`, `chatId`, `firstName` du message ou callback | | 2. Check banned | Lookup Data Table `Telegram Banned Users` | | 3. Check authorized | Lookup Data Table `Telegram Authorized users` | | 4. Pending approval | Si non autorisé : Data Table `Telegram Pending Approvals` + alerte admin | ```mermaid flowchart TD Msg["Message reçu"] IsBanned["Check Banned"] IsAuth["Check Authorized"] Process["Process request"] Pending["Insert Pending Approval"] Alert["Alert Admin · SW-3"] Approve["Callback approve / deny"] AuthSW["SW-4 Auth Callback Handler · 26n"] Msg --> IsBanned IsBanned -->|Yes| Ignore["Ignore"] IsBanned -->|No| IsAuth IsAuth -->|Authorized| Process IsAuth -->|Unauthorized| Pending --> Alert Alert --> Approve --> AuthSW ``` ### IA Router (Claude) Quand un message texte n'est pas une commande exacte et qu'aucune conversation n'est active, l'IA Router détecte l'intent via Claude (cli-ollama) : ```javascript const prompt = `Tu es un système de détection d'intent pour un assistant Telegram. Retourne UNIQUEMENT un JSON valide (pas de markdown, pas de backticks). Format: { "intent": "", "service": "", "action": "", "params": {}, "confidence": <0.0-1.0> } Services: - odoo: factures, devis, contacts, clients, projets, CRM - n8n: workflows, automatisations, executions - docker: containers (restart, status, logs) - general: conversation, questions générales Message utilisateur: ${text}`; ``` | Confidence | Comportement | |------------|--------------| | ≥ 0.7 | Route directement vers le service | | 0.5 - 0.7 | Demande confirmation (boutons) | | < 0.5 | Route vers `general` | Fallback chain : `claude-sonnet-yolo` (prioritaire) → `claude-haiku-yolo` (si quota) → keyword routing (si API down). ### Service Handlers Quatre service handlers spécialisés, chacun avec une responsabilité étroite : #### Service Handler Docker | Action | Commande | Protection | |--------|----------|------------| | `status` | `docker compose ps --format json` | Tous | | `logs` | `docker compose logs --tail 100` | Tous | | `restart` | `docker compose restart` | Sauf security-stack | | `update` | `docker compose pull && up -d` | Sauf security-stack | > **Danger - Protection security-stack** > > Le security-stack (Caddy + CrowdSec) est protégé contre les actions destructrices. Un restart accidentel couperait l'accès à tous les services. #### Service Handler N8N (refactoring #279) Le SH-N8N parent ne fait plus que la vérification admin + délégation. Toute la logique d'exécution N8N est dans **SH-N8N Action Executor** (37 nodes). | Action | Description | |--------|-------------| | `list_workflows` | Liste workflows avec pagination | | `toggle_workflow` | Active / désactive un workflow | | `list_executions` | Dernières exécutions (filtres) | | `execute_trigger` | Déclencher un workflow whitelisté | Trigger whitelist : seuls les workflows présents dans `n8n_trigger_whitelist` peuvent être déclenchés manuellement (rate limit : 1/min/workflow). #### Service Handler Odoo (refactoring #187) 33 nodes après extension `/projet`. Couvre contacts, factures, devis, CRM, projets. Le sub-workflow `Odoo Project Picker` (SW-12) gère la pagination des projets quand la liste dépasse l'inline keyboard. #### Service Handler General 10 nodes pour `/help` et le chat Claude générique (questions ouvertes hors service spécifique). ### Binary Content Handler Le Binary Content Handler (21 nodes) traite les médias : | Type | Pipeline | |------|----------| | **Photo** | Vision OCR (sub-workflow 14n, classification + extraction structurée) | | **Voice** | Voice Transcription (Groq ≤30s, ElevenLabs >30s) | | **vCard** | Ingress Contacts → Odoo `res.partner` | | **PDF / vidéo** | Extraction métadonnées + résumé | Vision OCR retourne un contrat `{status, docType, extracted, text}`. Selon le `docType` : | docType | Routing | |---------|---------| | `business_card` | Création contact Odoo via Ingress Contacts (fire-and-forget) | | `invoice` / `screenshot` / `handwritten` / `general_document` | Affichage + bouton `[Discuter]` qui lance une conversation | | `not_document` | Bascule vers IA Router pour traitement conversationnel | | `error` | Notification d'erreur via Notification Hub | ### Convention de callbacks ``` # Navigation menu_
→ Menu (main, docker, n8n, odoo, help, notif, todo) # Docker menu_docker_stacks_ → Liste stacks pour action docker__ → Exécute action sur stack # N8N (admin) menu_n8n_workflows → Liste workflows n8n_wf_ → Toggle workflow n8n_run_ → Exécuter workflow # Conversations conv_switch_ → Changer de conversation active conv_delete_ → Archiver plan_exec_ → Exécuter un plan plan_modify_ → Modifier un plan plan_cancel_ → Annuler un plan # User management approve_ → Approuver utilisateur (admin) deny_ → Refuser utilisateur (admin) # Photos (#176) photo_discuss_ → Lance une conversation autour de la photo photo_dismiss_ → Ignore la photo # Notifications hub notif__ → approve / retry / details / ignore ``` > **Caution - Ordre des conditions Parse Callback** > > Les conditions du Parse Callback doivent aller du plus spécifique au plus général. Une condition `startsWith('menu_')` qui précède `startsWith('menu_n8n')` capturerait toutes les routes N8N. Toujours tester les préfixes longs avant les préfixes courts. ### Best Practice : `__rl` resource locator Les nodes Execute Workflow MUST utiliser le format `__rl` pour `workflowId`, sinon ils échouent silencieusement au runtime : ```json { "workflowId": { "__rl": true, "value": "", "mode": "id" }, "options": {} } ``` Le format plat `{"mode": "id", "workflowId": ""}` produit "No information about the workflow to execute found" sans surface l'erreur. --- ## 4. Et si ? — Perspectives et limites ### Limites actuelles | Limite | Impact | Mitigation | |--------|--------|------------| | **Latence Claude** | 2-5s pour intent detection | Cache des intents fréquents à concevoir | | **Pas de multi-langue** | Prompts en français uniquement | Suffisant pour usage personnel | | **Rate limiting Telegram** | 30 messages/seconde max | Non atteint en usage normal | | **Photos non-document = 2 appels LLM** | Detection + analyse générique | Acceptable pour le contexte conversation | ### Scénarios d'évolution **Si l'équipe passe en multi-utilisateurs** : - Permissions granulaires par handler (actuellement : admin / non-admin) - Logs d'audit des actions par utilisateur - Notifications de groupe pour les actions critiques **Si besoin d'extension fonctionnelle** : - Ajouter un service au Switch du Service Router (nouveau case) - Ou activer un serveur MCP via la commande `/mcp` dans une conversation - Le système est extensible par design — chaque ajout est isolé dans son sub-workflow **Si la latence devient critique** : - Pre-fetch des Data Tables fréquentes en cache N8N memory - Pipelining des appels Odoo (déjà partiellement fait) - Migration des fire-and-forget vers une queue Bull dédiée --- ## Pages liées ### Infrastructure - [N8N en mode Queue](/fr/infrastructure/n8n-queue-mode/) — Backend automation - [AI Stack](/fr/infrastructure/ai-stack/) — cli-ollama pour intent detection ### Workflows - [Système conversationnel](/fr/workflows/systeme-conversationnel/) — Conversations multi-tours, plans, MCP - [Content Pipeline](/fr/workflows/content-pipeline/) — Capture de notes et articles - [Voice Transcription](/fr/workflows/voice-transcription/) — Transcription vocale - [Docker Updates](/fr/workflows/docker-updates/) — Approbations DIUN via callbacks - [Notification Hub](/fr/workflows/notification-hub/) — Routage notifications + callbacks - [Error Handler](/fr/workflows/error-handler/) — Capture des erreurs orchestrateur ### Référence - [Glossaire](/fr/reference/glossary/) — Webhook, Callback, Intent, Sub-workflow ## Metadonnees agent - Cet article est issu du blog GuiGPaP Lab. - Contexte global du blog: https://blog.guigpap.com/llms.txt - Contact auteur: https://odoo.guigpap.com/mon-cv - Licence: CC-BY-SA 4.0