Mainstream messaging

Telegram

Listo para producción para mensajes directos y grupos de bots mediante grammY. El sondeo largo es el modo predeterminado; el modo Webhook es opcional.

Configuración rápida

  • Crea el token del bot en BotFather

    Abre Telegram y chatea con @BotFather (confirma que el identificador sea exactamente @BotFather).

    Ejecuta /newbot, sigue las indicaciones y guarda el token.

  • Configura el token y la política de mensajes directos

    {
    channels: {
    telegram: {
      enabled: true,
      botToken: "123:abc",
      dmPolicy: "pairing",
      groups: { "*": { requireMention: true } },
    },
    },
    }
    

    Reserva de entorno: TELEGRAM_BOT_TOKEN=... (solo cuenta predeterminada). Telegram no usa openclaw channels login telegram; configura el token en config/env y luego inicia el Gateway.

  • Inicia el Gateway y aprueba el primer mensaje directo

    openclaw gateway
    openclaw pairing list telegram
    openclaw pairing approve telegram <CODE>
    

    Los códigos de emparejamiento caducan después de 1 hora.

  • Agrega el bot a un grupo

    Agrega el bot a tu grupo y luego configura channels.telegram.groups y groupPolicy para que coincidan con tu modelo de acceso.

  • Ajustes del lado de Telegram

    Modo de privacidad y visibilidad de grupos

    Los bots de Telegram usan Modo de privacidad de forma predeterminada, lo que limita los mensajes de grupo que reciben.

    Si el bot debe ver todos los mensajes del grupo:

    • desactiva el modo de privacidad mediante /setprivacy, o
    • convierte el bot en administrador del grupo.

    Al cambiar el modo de privacidad, elimina y vuelve a agregar el bot en cada grupo para que Telegram aplique el cambio.

    Permisos de grupo

    El estado de administrador se controla en los ajustes del grupo de Telegram.

    Los bots administradores reciben todos los mensajes del grupo, lo cual es útil para comportamiento de grupo siempre activo.

    Conmutadores útiles de BotFather
    • /setjoingroups para permitir/denegar que se agregue a grupos
    • /setprivacy para el comportamiento de visibilidad en grupos

    Control de acceso y activación

    Política de mensajes directos

    channels.telegram.dmPolicy controla el acceso por mensaje directo:

    • pairing (predeterminado)
    • allowlist (requiere al menos un ID de remitente en allowFrom)
    • open (requiere que allowFrom incluya "*")
    • disabled

    dmPolicy: "open" con allowFrom: ["*"] permite que cualquier cuenta de Telegram que encuentre o adivine el nombre de usuario del bot le dé órdenes al bot. Úsalo solo para bots intencionalmente públicos con herramientas estrictamente restringidas; los bots de un solo propietario deben usar allowlist con IDs de usuario numéricos.

    channels.telegram.allowFrom acepta IDs numéricos de usuario de Telegram. Se aceptan y normalizan los prefijos telegram: / tg:. En configuraciones de varias cuentas, un channels.telegram.allowFrom restrictivo de nivel superior se trata como un límite de seguridad: las entradas allowFrom: ["*"] de nivel de cuenta no hacen pública esa cuenta a menos que la lista de permitidos efectiva de la cuenta aún contenga un comodín explícito después de la fusión. dmPolicy: "allowlist" con allowFrom vacío bloquea todos los mensajes directos y la validación de configuración lo rechaza. La configuración solo solicita IDs numéricos de usuario. Si actualizaste y tu configuración contiene entradas @username en la lista de permitidos, ejecuta openclaw doctor --fix para resolverlas (mejor esfuerzo; requiere un token de bot de Telegram). Si antes dependías de archivos de lista de permitidos del almacén de emparejamientos, openclaw doctor --fix puede recuperar entradas en channels.telegram.allowFrom en flujos de lista de permitidos (por ejemplo, cuando dmPolicy: "allowlist" aún no tiene IDs explícitos).

    Para bots de un solo propietario, prefiere dmPolicy: "allowlist" con IDs numéricos explícitos en allowFrom para mantener la política de acceso duradera en la configuración (en lugar de depender de aprobaciones de emparejamiento anteriores).

    Confusión común: aprobar el emparejamiento por mensaje directo no significa "este remitente está autorizado en todas partes". El emparejamiento concede acceso por mensaje directo. Si todavía no existe propietario de comandos, el primer emparejamiento aprobado también configura commands.ownerAllowFrom para que los comandos solo para propietario y las aprobaciones de ejecución tengan una cuenta de operador explícita. La autorización de remitentes en grupos sigue viniendo de listas de permitidos explícitas en la configuración. Si quieres "estoy autorizado una vez y funcionan tanto los mensajes directos como los comandos de grupo", coloca tu ID numérico de usuario de Telegram en channels.telegram.allowFrom; para comandos solo para propietario, asegúrate de que commands.ownerAllowFrom contenga telegram:<your user id>.

    Encontrar tu ID de usuario de Telegram

    Más seguro (sin bot de terceros):

    1. Envía un mensaje directo a tu bot.
    2. Ejecuta openclaw logs --follow.
    3. Lee from.id.

    Método oficial de la Bot API:

    curl "https://api.telegram.org/bot<bot_token>/getUpdates"
    

    Método de terceros (menos privado): @userinfobot o @getidsbot.

    Política de grupos y listas de permitidos

    Dos controles se aplican juntos:

    1. Qué grupos están permitidos (channels.telegram.groups)

      • sin configuración de groups:
        • con groupPolicy: "open": cualquier grupo puede superar las comprobaciones de ID de grupo
        • con groupPolicy: "allowlist" (predeterminado): los grupos se bloquean hasta que agregues entradas de groups (o "*")
      • groups configurado: actúa como lista de permitidos (IDs explícitos o "*")
    2. Qué remitentes están permitidos en grupos (channels.telegram.groupPolicy)

      • open
      • allowlist (predeterminado)
      • disabled

    groupAllowFrom se usa para filtrar remitentes de grupo. Si no está configurado, Telegram recurre a allowFrom. Las entradas de groupAllowFrom deben ser IDs numéricos de usuario de Telegram (los prefijos telegram: / tg: se normalizan). No pongas IDs de chat de grupos o supergrupos de Telegram en groupAllowFrom. Los IDs de chat negativos van bajo channels.telegram.groups. Las entradas no numéricas se ignoran para la autorización de remitentes. Límite de seguridad (2026.2.25+): la autenticación de remitentes de grupo no hereda las aprobaciones del almacén de emparejamientos de mensajes directos. El emparejamiento sigue siendo solo para mensajes directos. Para grupos, configura groupAllowFrom o allowFrom por grupo/tema. Si groupAllowFrom no está configurado, Telegram recurre a allowFrom de la configuración, no al almacén de emparejamientos. Patrón práctico para bots de un solo propietario: establece tu ID de usuario en channels.telegram.allowFrom, deja groupAllowFrom sin configurar y permite los grupos de destino bajo channels.telegram.groups. Nota de tiempo de ejecución: si channels.telegram falta por completo, el tiempo de ejecución usa de forma predeterminada groupPolicy="allowlist" con cierre seguro, salvo que channels.defaults.groupPolicy esté configurado explícitamente.

    Ejemplo: permitir cualquier miembro en un grupo específico:

    {
    channels: {
    telegram: {
      groups: {
        "-1001234567890": {
          groupPolicy: "open",
          requireMention: false,
        },
      },
    },
    },
    }
    

    Ejemplo: permitir solo usuarios específicos dentro de un grupo específico:

    {
    channels: {
    telegram: {
      groups: {
        "-1001234567890": {
          requireMention: true,
          allowFrom: ["8734062810", "745123456"],
        },
      },
    },
    },
    }
    

    Comportamiento de menciones

    Las respuestas de grupo requieren mención de forma predeterminada.

    La mención puede venir de:

    • una mención nativa @botusername, o
    • patrones de mención en:
      • agents.list[].groupChat.mentionPatterns
      • messages.groupChat.mentionPatterns

    Conmutadores de comandos a nivel de sesión:

    • /activation always
    • /activation mention

    Estos solo actualizan el estado de la sesión. Usa la configuración para persistencia.

    Ejemplo de configuración persistente:

    {
    channels: {
    telegram: {
      groups: {
        "*": { requireMention: false },
      },
    },
    },
    }
    

    Obtener el ID del chat de grupo:

    • reenvía un mensaje de grupo a @userinfobot / @getidsbot
    • o lee chat.id desde openclaw logs --follow
    • o inspecciona getUpdates de la Bot API

    Comportamiento en tiempo de ejecución

    • Telegram es propiedad del proceso de Gateway.
    • El enrutamiento es determinista: las entradas de Telegram responden de vuelta a Telegram (el modelo no elige canales).
    • Los mensajes entrantes se normalizan en el sobre de canal compartido con metadatos de respuesta y marcadores de posición de medios.
    • Las sesiones de grupo se aíslan por ID de grupo. Los temas de foro agregan :topic:<threadId> para mantener los temas aislados.
    • Los mensajes directos pueden llevar message_thread_id; OpenClaw conserva el ID de hilo para respuestas, pero mantiene los mensajes directos en la sesión plana de forma predeterminada. Configura channels.telegram.dm.threadReplies: "inbound", channels.telegram.direct.<chatId>.threadReplies: "inbound", requireTopic: true o una configuración de tema coincidente cuando quieras intencionalmente aislamiento de sesiones por tema en mensajes directos.
    • El sondeo largo usa grammY runner con secuenciación por chat/por hilo. La concurrencia general del destino del runner usa agents.defaults.maxConcurrent.
    • El sondeo largo está protegido dentro de cada proceso de Gateway para que solo un sondeador activo pueda usar un token de bot a la vez. Si aún ves conflictos 409 de getUpdates, es probable que otro Gateway de OpenClaw, script o sondeador externo esté usando el mismo token.
    • Los reinicios del monitor de sondeo largo se activan de forma predeterminada después de 120 segundos sin actividad completada de getUpdates. Aumenta channels.telegram.pollingStallThresholdMs solo si tu despliegue todavía ve reinicios falsos por bloqueo de sondeo durante trabajos de larga duración. El valor está en milisegundos y se permite de 30000 a 600000; se admiten anulaciones por cuenta.
    • La Telegram Bot API no tiene soporte para confirmaciones de lectura (sendReadReceipts no se aplica).

    Referencia de funciones

    Vista previa de transmisión en vivo (ediciones de mensajes)

    OpenClaw puede transmitir respuestas parciales en tiempo real:

    • chats directos: mensaje de vista previa + editMessageText
    • grupos/temas: mensaje de vista previa + editMessageText

    Requisito:

    • channels.telegram.streaming es off | partial | block | progress (predeterminado: partial)
    • progress mantiene un borrador de estado editable para el progreso de herramientas, lo limpia al finalizar y envía la respuesta final como un mensaje normal
    • streaming.preview.toolProgress controla si las actualizaciones de herramientas/progreso reutilizan el mismo mensaje de vista previa editado (predeterminado: true cuando la transmisión de vista previa está activa)
    • streaming.preview.commandText controla el detalle de comando/ejecución dentro de esas líneas de progreso de herramientas: raw (predeterminado, conserva el comportamiento publicado) o status (solo etiqueta de herramienta)
    • se detectan los valores heredados channels.telegram.streamMode y booleanos de streaming; ejecuta openclaw doctor --fix para migrarlos a channels.telegram.streaming.mode

    Las actualizaciones de vista previa de progreso de herramientas son las líneas cortas de estado que se muestran mientras se ejecutan herramientas, por ejemplo ejecución de comandos, lecturas de archivos, actualizaciones de planificación o resúmenes de parches. Telegram las mantiene habilitadas de forma predeterminada para coincidir con el comportamiento publicado de OpenClaw desde v2026.4.22 y versiones posteriores. Para mantener la vista previa editada para el texto de respuesta pero ocultar las líneas de progreso de herramientas, configura:

    {
      "channels": {
        "telegram": {
          "streaming": {
            "mode": "partial",
            "preview": {
              "toolProgress": false
            }
          }
        }
      }
    }
    

    Para mantener visible el progreso de herramientas pero ocultar el texto de comando/ejecución, configura:

    {
      "channels": {
        "telegram": {
          "streaming": {
            "mode": "partial",
            "preview": {
              "commandText": "status"
            }
          }
        }
      }
    }
    

    Usa el modo progress cuando quieras mostrar el progreso visible de las herramientas sin editar la respuesta final en ese mismo mensaje. Coloca la política de texto del comando bajo streaming.progress:

    {
      "channels": {
        "telegram": {
          "streaming": {
            "mode": "progress",
            "progress": {
              "toolProgress": true,
              "commandText": "status"
            }
          }
        }
      }
    }
    

    Usa streaming.mode: "off" solo cuando quieras entrega únicamente final: las ediciones de vista previa de Telegram se deshabilitan y la charla genérica de herramientas/progreso se suprime en lugar de enviarse como mensajes de estado independientes. Las solicitudes de aprobación, las cargas multimedia y los errores aún se enrutan mediante la entrega final normal. Usa streaming.preview.toolProgress: false cuando solo quieras conservar las ediciones de vista previa de la respuesta mientras ocultas las líneas de estado de progreso de herramientas.

    Para respuestas de solo texto:

    • vistas previas breves en DM/grupo/tema: OpenClaw conserva el mismo mensaje de vista previa y realiza la edición final en el mismo lugar
    • finales de texto largos que se dividen en varios mensajes de Telegram reutilizan la vista previa existente como el primer fragmento final cuando es posible, y luego envían solo los fragmentos restantes
    • los finales en modo de progreso limpian el borrador de estado y usan la entrega final normal en lugar de editar el borrador para convertirlo en la respuesta
    • si la edición final falla antes de confirmar el texto completado, OpenClaw usa la entrega final normal y limpia la vista previa obsoleta

    Para respuestas complejas (por ejemplo, cargas multimedia), OpenClaw recurre a la entrega final normal y luego limpia el mensaje de vista previa.

    El streaming de vista previa es independiente del streaming por bloques. Cuando el streaming por bloques se habilita explícitamente para Telegram, OpenClaw omite el stream de vista previa para evitar el doble streaming.

    Stream de razonamiento solo para Telegram:

    • /reasoning stream envía el razonamiento a la vista previa en vivo mientras se genera
    • la vista previa de razonamiento se elimina después de la entrega final; usa /reasoning on cuando el razonamiento deba permanecer visible
    • la respuesta final se envía sin texto de razonamiento
    Formato y alternativa HTML

    El texto saliente usa Telegram parse_mode: "HTML".

    • El texto similar a Markdown se representa como HTML seguro para Telegram.
    • El HTML sin procesar del modelo se escapa para reducir fallos de análisis de Telegram.
    • Si Telegram rechaza el HTML analizado, OpenClaw reintenta como texto plano.

    Las vistas previas de enlaces están habilitadas de forma predeterminada y se pueden deshabilitar con channels.telegram.linkPreview: false.

    Comandos nativos y comandos personalizados

    El registro del menú de comandos de Telegram se gestiona al inicio con setMyCommands.

    Valores predeterminados de comandos nativos:

    • commands.native: "auto" habilita comandos nativos para Telegram

    Añade entradas personalizadas al menú de comandos:

    {
    channels: {
    telegram: {
      customCommands: [
        { command: "backup", description: "Git backup" },
        { command: "generate", description: "Create an image" },
      ],
    },
    },
    }
    

    Reglas:

    • los nombres se normalizan (se elimina el / inicial, minúsculas)
    • patrón válido: a-z, 0-9, _, longitud 1..32
    • los comandos personalizados no pueden anular comandos nativos
    • los conflictos/duplicados se omiten y se registran

    Notas:

    • los comandos personalizados son solo entradas de menú; no implementan comportamiento automáticamente
    • los comandos de plugin/skill aún pueden funcionar al escribirse aunque no se muestren en el menú de Telegram

    Si los comandos nativos están deshabilitados, los integrados se eliminan. Los comandos personalizados/de plugin aún pueden registrarse si están configurados.

    Fallos comunes de configuración:

    • setMyCommands failed con BOT_COMMANDS_TOO_MUCH significa que el menú de Telegram aún se desbordó después de recortarlo; reduce los comandos de plugin/skill/personalizados o deshabilita channels.telegram.commands.native.
    • fallos de deleteWebhook, deleteMyCommands o setMyCommands con 404: Not Found mientras los comandos directos de curl de la API de bot funcionan pueden significar que channels.telegram.apiRoot se configuró con el endpoint completo /bot&lt;TOKEN&gt;. apiRoot debe ser solo la raíz de la API de bot, y openclaw doctor --fix elimina un /bot&lt;TOKEN&gt; final accidental.
    • getMe returned 401 significa que Telegram rechazó el token de bot configurado. Actualiza botToken, tokenFile o TELEGRAM_BOT_TOKEN con el token actual de BotFather; OpenClaw se detiene antes del sondeo, por lo que esto no se informa como un fallo de limpieza de webhook.
    • setMyCommands failed con errores de red/fetch normalmente significa que el DNS/HTTPS saliente hacia api.telegram.org está bloqueado.

    Comandos de emparejamiento de dispositivo (plugin device-pair)

    Cuando el plugin device-pair está instalado:

    1. /pair genera el código de configuración
    2. pega el código en la app de iOS
    3. /pair pending lista las solicitudes pendientes (incluidos rol/alcances)
    4. aprueba la solicitud:
      • /pair approve <requestId> para aprobación explícita
      • /pair approve cuando solo hay una solicitud pendiente
      • /pair approve latest para la más reciente

    El código de configuración transporta un token de arranque de vida corta. La transferencia de arranque integrada mantiene el token del nodo principal en scopes: []; cualquier token de operador transferido permanece limitado a operator.approvals, operator.read, operator.talk.secrets y operator.write. Las comprobaciones de alcance de arranque llevan prefijo de rol, por lo que esa lista de permitidos de operador solo satisface solicitudes de operador; los roles que no son de operador aún necesitan alcances bajo su propio prefijo de rol.

    Si un dispositivo reintenta con detalles de autenticación cambiados (por ejemplo, rol/alcances/clave pública), la solicitud pendiente anterior queda reemplazada y la nueva solicitud usa un requestId diferente. Vuelve a ejecutar /pair pending antes de aprobar.

    Más detalles: Emparejamiento.

    Botones en línea

    Configura el alcance del teclado en línea:

    {
    channels: {
    telegram: {
      capabilities: {
        inlineButtons: "allowlist",
      },
    },
    },
    }
    

    Anulación por cuenta:

    {
    channels: {
    telegram: {
      accounts: {
        main: {
          capabilities: {
            inlineButtons: "allowlist",
          },
        },
      },
    },
    },
    }
    

    Alcances:

    • off
    • dm
    • group
    • all
    • allowlist (predeterminado)

    El valor heredado capabilities: ["inlineButtons"] se asigna a inlineButtons: "all".

    Ejemplo de acción de mensaje:

    {
    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" }],
    ],
    }
    

    Los clics de callback se pasan al agente como texto: callback_data: <value>

    Acciones de mensajes de Telegram para agentes y automatización

    Las acciones de herramienta de Telegram incluyen:

    • sendMessage (to, content, mediaUrl opcional, replyToMessageId, messageThreadId)
    • react (chatId, messageId, emoji)
    • deleteMessage (chatId, messageId)
    • editMessage (chatId, messageId, content)
    • createForumTopic (chatId, name, iconColor opcional, iconCustomEmojiId)

    Las acciones de mensaje de canal exponen alias ergonómicos (send, react, delete, edit, sticker, sticker-search, topic-create).

    Controles de restricción:

    • channels.telegram.actions.sendMessage
    • channels.telegram.actions.deleteMessage
    • channels.telegram.actions.reactions
    • channels.telegram.actions.sticker (predeterminado: deshabilitado)

    Nota: edit y topic-create están habilitados actualmente de forma predeterminada y no tienen interruptores channels.telegram.actions.* separados. Los envíos en tiempo de ejecución usan la instantánea activa de configuración/secretos (inicio/recarga), por lo que las rutas de acción no realizan una nueva resolución ad hoc de SecretRef por cada envío.

    Semántica de eliminación de reacciones: /tools/reactions

    Etiquetas de hilos de respuesta

    Telegram admite etiquetas explícitas de hilos de respuesta en la salida generada:

    • [[reply_to_current]] responde al mensaje que activó la acción
    • [[reply_to:<id>]] responde a un ID de mensaje específico de Telegram

    channels.telegram.replyToMode controla el manejo:

    • off (predeterminado)
    • first
    • all

    Cuando los hilos de respuesta están habilitados y el texto o pie de foto original de Telegram está disponible, OpenClaw incluye automáticamente un extracto de cita nativa de Telegram. Telegram limita el texto de cita nativa a 1024 unidades de código UTF-16, por lo que los mensajes más largos se citan desde el inicio y recurren a una respuesta simple si Telegram rechaza la cita.

    Nota: off deshabilita los hilos de respuesta implícitos. Las etiquetas explícitas [[reply_to_*]] se siguen respetando.

    Temas de foro y comportamiento de hilos

    Supergrupos de foro:

    • las claves de sesión de tema añaden :topic:<threadId>
    • las respuestas y la indicación de escritura apuntan al hilo del tema
    • ruta de configuración del tema: channels.telegram.groups.<chatId>.topics.<threadId>

    Caso especial del tema general (threadId=1):

    • los envíos de mensaje omiten message_thread_id (Telegram rechaza sendMessage(...thread_id=1))
    • las acciones de escritura aún incluyen message_thread_id

    Herencia de temas: las entradas de tema heredan la configuración del grupo salvo que se anule (requireMention, allowFrom, skills, systemPrompt, enabled, groupPolicy). agentId es solo de tema y no hereda de los valores predeterminados del grupo.

    Enrutamiento de agente por tema: Cada tema puede enrutarse a un agente diferente definiendo agentId en la configuración del tema. Esto da a cada tema su propio espacio de trabajo, memoria y sesión aislados. Ejemplo:

    {
      channels: {
        telegram: {
          groups: {
            "-1001234567890": {
              topics: {
                "1": { agentId: "main" },      // Tema general → agente principal
                "3": { agentId: "zu" },        // Tema de desarrollo → agente zu
                "5": { agentId: "coder" }      // Revisión de código → agente coder
              }
            }
          }
        }
      }
    }
    

    Cada tema tiene entonces su propia clave de sesión: agent:zu:telegram:group:-1001234567890:topic:3

    Vinculación persistente de temas ACP: Los temas de foro pueden fijar sesiones de arnés ACP mediante vinculaciones ACP tipadas de nivel superior (bindings[] con type: "acp" y match.channel: "telegram", peer.kind: "group", y un id calificado por tema como -1001234567890:topic:42). Actualmente está limitado a temas de foro en grupos/supergrupos. Consulta Agentes ACP.

    Generación de ACP ligada a hilo desde chat: /acp spawn <agent> --thread here|auto vincula el tema actual a una nueva sesión ACP; los seguimientos se enrutan allí directamente. OpenClaw fija la confirmación de generación en el tema. Requiere que channels.telegram.threadBindings.spawnSessions permanezca habilitado (predeterminado: true).

    El contexto de plantilla expone MessageThreadId e IsForum. Los chats de DM con message_thread_id mantienen el enrutamiento de DM y los metadatos de respuesta en sesiones planas de forma predeterminada; solo usan claves de sesión con reconocimiento de hilos cuando se configuran con threadReplies: "inbound", threadReplies: "always", requireTopic: true o una configuración de tema coincidente. Usa channels.telegram.dm.threadReplies de nivel superior para el valor predeterminado de la cuenta, o direct.<chatId>.threadReplies para un DM.

    Audio, video y stickers

    Mensajes de audio

    Telegram distingue las notas de voz de los archivos de audio.

    • predeterminado: comportamiento de archivo de audio
    • etiqueta [[audio_as_voice]] en la respuesta del agente para forzar el envío como nota de voz
    • las transcripciones de notas de voz entrantes se enmarcan como texto generado por máquina y no confiable en el contexto del agente; la detección de menciones sigue usando la transcripción sin procesar, por lo que los mensajes de voz protegidos por mención siguen funcionando.

    Ejemplo de acción de mensaje:

    {
    action: "send",
    channel: "telegram",
    to: "123456789",
    media: "https://example.com/voice.ogg",
    asVoice: true,
    }
    

    Mensajes de video

    Telegram distingue los archivos de video de las notas de video.

    Ejemplo de acción de mensaje:

    {
    action: "send",
    channel: "telegram",
    to: "123456789",
    media: "https://example.com/video.mp4",
    asVideoNote: true,
    }
    

    Las notas de video no admiten subtítulos; el texto de mensaje proporcionado se envía por separado.

    Stickers

    Manejo de stickers entrantes:

    • WEBP estático: se descarga y procesa (marcador de posición <media:sticker>)
    • TGS animado: se omite
    • WEBM de video: se omite

    Campos de contexto de sticker:

    • Sticker.emoji
    • Sticker.setName
    • Sticker.fileId
    • Sticker.fileUniqueId
    • Sticker.cachedDescription

    Archivo de caché de stickers:

    • ~/.openclaw/telegram/sticker-cache.json

    Los stickers se describen una vez (cuando es posible) y se almacenan en caché para reducir llamadas de visión repetidas.

    Habilitar acciones de sticker:

    {
    channels: {
    telegram: {
      actions: {
        sticker: true,
      },
    },
    },
    }
    

    Acción para enviar sticker:

    {
    action: "sticker",
    channel: "telegram",
    to: "123456789",
    fileId: "CAACAgIAAxkBAAI...",
    }
    

    Buscar stickers en caché:

    {
    action: "sticker-search",
    channel: "telegram",
    query: "cat waving",
    limit: 5,
    }
    
    Notificaciones de reacciones

    Las reacciones de Telegram llegan como actualizaciones message_reaction (separadas de las cargas útiles de mensaje).

    Cuando está habilitado, OpenClaw encola eventos del sistema como:

    • Telegram reaction added: 👍 by Alice (@alice) on msg 42

    Configuración:

    • channels.telegram.reactionNotifications: off | own | all (predeterminado: own)
    • channels.telegram.reactionLevel: off | ack | minimal | extensive (predeterminado: minimal)

    Notas:

    • own significa solo reacciones de usuarios a mensajes enviados por el bot (mejor esfuerzo mediante la caché de mensajes enviados).
    • Los eventos de reacción siguen respetando los controles de acceso de Telegram (dmPolicy, allowFrom, groupPolicy, groupAllowFrom); los remitentes no autorizados se descartan.
    • Telegram no proporciona IDs de hilo en las actualizaciones de reacción.
      • los grupos que no son foro se enrutan a la sesión de chat grupal
      • los grupos de foro se enrutan a la sesión de tema general del grupo (:topic:1), no al tema exacto de origen

    allowed_updates para polling/Webhook incluye message_reaction automáticamente.

    Reacciones de confirmación

    ackReaction envía un emoji de confirmación mientras OpenClaw procesa un mensaje entrante.

    Orden de resolución:

    • channels.telegram.accounts.<accountId>.ackReaction
    • channels.telegram.ackReaction
    • messages.ackReaction
    • alternativa de emoji de identidad del agente (agents.list[].identity.emoji, si no, "👀")

    Notas:

    • Telegram espera emoji unicode (por ejemplo "👀").
    • Usa "" para deshabilitar la reacción para un canal o cuenta.
    Escrituras de configuración desde eventos y comandos de Telegram

    Las escrituras de configuración del canal están habilitadas de forma predeterminada (configWrites !== false).

    Las escrituras activadas por Telegram incluyen:

    • eventos de migración de grupo (migrate_to_chat_id) para actualizar channels.telegram.groups
    • /config set y /config unset (requiere habilitación de comandos)

    Deshabilitar:

    {
    channels: {
    telegram: {
      configWrites: false,
    },
    },
    }
    
    Long polling frente a Webhook

    El valor predeterminado es long polling. Para el modo Webhook, define channels.telegram.webhookUrl y channels.telegram.webhookSecret; webhookPath, webhookHost, webhookPort son opcionales (valores predeterminados /telegram-webhook, 127.0.0.1, 8787).

    En modo long polling, OpenClaw conserva su marca de agua de reinicio solo después de que una actualización se despacha correctamente. Si un controlador falla, esa actualización sigue siendo reintentable en el mismo proceso y no se escribe como completada para la deduplicación de reinicio.

    El listener local se enlaza a 127.0.0.1:8787. Para ingreso público, coloca un proxy inverso delante del puerto local o define webhookHost: "0.0.0.0" intencionadamente.

    El modo Webhook valida las protecciones de solicitud, el token secreto de Telegram y el cuerpo JSON antes de devolver 200 a Telegram. Luego OpenClaw procesa la actualización de forma asíncrona mediante los mismos carriles de bot por chat/por tema que usa long polling, por lo que los turnos lentos del agente no retienen el ACK de entrega de Telegram.

    Límites, reintentos y destinos de CLI
    • channels.telegram.textChunkLimit tiene un valor predeterminado de 4000.
    • channels.telegram.chunkMode="newline" prefiere límites de párrafo (líneas en blanco) antes de dividir por longitud.
    • channels.telegram.mediaMaxMb (predeterminado 100) limita el tamaño de medios de Telegram entrantes y salientes.
    • channels.telegram.mediaGroupFlushMs (predeterminado 500) controla cuánto tiempo se almacenan en búfer los álbumes/grupos de medios de Telegram antes de que OpenClaw los despache como un mensaje entrante. Auméntalo si las partes del álbum llegan tarde; redúcelo para disminuir la latencia de respuesta del álbum.
    • channels.telegram.timeoutSeconds anula el tiempo de espera del cliente de la API de Telegram (si no está definido, se aplica el valor predeterminado de grammY). Los clientes de bot limitan los valores configurados por debajo de la protección de solicitud de texto/escritura saliente de 60 segundos para que grammY no aborte la entrega de respuestas visibles antes de que puedan ejecutarse la protección de transporte y la alternativa de OpenClaw. Long polling sigue usando una protección de solicitud getUpdates de 45 segundos para que los polls inactivos no se abandonen indefinidamente.
    • channels.telegram.pollingStallThresholdMs tiene un valor predeterminado de 120000; ajústalo entre 30000 y 600000 solo para reinicios por atasco de polling con falsos positivos.
    • el historial de contexto de grupo usa channels.telegram.historyLimit o messages.groupChat.historyLimit (predeterminado 50); 0 lo deshabilita.
    • el contexto suplementario de respuesta/cita/reenvío se pasa actualmente tal como se recibe.
    • las listas de permitidos de Telegram controlan principalmente quién puede activar el agente, no una frontera completa de redacción de contexto suplementario.
    • Controles de historial de DM:
      • channels.telegram.dmHistoryLimit
      • channels.telegram.dms["<user_id>"].historyLimit
    • la configuración channels.telegram.retry se aplica a los helpers de envío de Telegram (CLI/herramientas/acciones) para errores de API saliente recuperables. La entrega de la respuesta final entrante también usa un reintento acotado de envío seguro para fallos de preconexión de Telegram, pero no reintenta envolturas de red ambiguas posteriores al envío que podrían duplicar mensajes visibles.

    Los destinos de envío de CLI y de herramienta de mensajes pueden ser un ID numérico de chat, un nombre de usuario o un destino de tema de foro:

    openclaw message send --channel telegram --target 123456789 --message "hi"
    openclaw message send --channel telegram --target @name --message "hi"
    openclaw message send --channel telegram --target -1001234567890:topic:42 --message "hi topic"
    

    Los polls de Telegram usan openclaw message poll y admiten temas de foro:

    openclaw message poll --channel telegram --target 123456789 \
    --poll-question "Ship it?" --poll-option "Yes" --poll-option "No"
    openclaw message poll --channel telegram --target -1001234567890:topic:42 \
    --poll-question "Pick a time" --poll-option "10am" --poll-option "2pm" \
    --poll-duration-seconds 300 --poll-public
    

    Flags de poll solo de Telegram:

    • --poll-duration-seconds (5-600)
    • --poll-anonymous
    • --poll-public
    • --thread-id para temas de foro (o usa un destino :topic:)

    El envío de Telegram también admite:

    • --presentation con bloques buttons para teclados inline cuando channels.telegram.capabilities.inlineButtons lo permite
    • --pin o --delivery '{"pin":true}' para solicitar entrega fijada cuando el bot puede fijar en ese chat
    • --force-document para enviar imágenes y GIFs salientes como documentos en lugar de subidas de foto comprimida o medios animados

    Control de acciones:

    • channels.telegram.actions.sendMessage=false deshabilita los mensajes salientes de Telegram, incluidos los polls
    • channels.telegram.actions.poll=false deshabilita la creación de polls de Telegram mientras deja habilitados los envíos normales
    Aprobaciones de exec en Telegram

    Telegram admite aprobaciones de exec en DM de aprobadores y, opcionalmente, puede publicar prompts en el chat o tema de origen. Los aprobadores deben ser IDs numéricos de usuario de Telegram.

    Ruta de configuración:

    • channels.telegram.execApprovals.enabled (se habilita automáticamente cuando al menos un aprobador se puede resolver)
    • channels.telegram.execApprovals.approvers (recurre a IDs numéricos de propietarios de commands.ownerAllowFrom)
    • channels.telegram.execApprovals.target: dm (predeterminado) | channel | both
    • agentFilter, sessionFilter

    channels.telegram.allowFrom, groupAllowFrom y defaultTo controlan quién puede hablar con el bot y dónde envía respuestas normales. No convierten a alguien en aprobador de exec. El primer emparejamiento de DM aprobado inicializa commands.ownerAllowFrom cuando aún no existe ningún propietario de comandos, por lo que la configuración de un solo propietario sigue funcionando sin duplicar IDs en execApprovals.approvers.

    La entrega en canal muestra el texto del comando en el chat; habilita channel o both solo en grupos/temas de confianza. Cuando el prompt llega a un tema de foro, OpenClaw conserva el tema para el prompt de aprobación y el seguimiento. Las aprobaciones de exec caducan después de 30 minutos de forma predeterminada.

    Los botones de aprobación inline también requieren que channels.telegram.capabilities.inlineButtons permita la superficie de destino (dm, group o all). Los IDs de aprobación con prefijo plugin: se resuelven mediante aprobaciones de Plugin; los demás se resuelven primero mediante aprobaciones de exec.

    Consulta Aprobaciones de exec.

    Controles de respuesta de error

    Cuando el agente encuentra un error de entrega o de proveedor, Telegram puede responder con el texto de error o suprimirlo. Dos claves de configuración controlan este comportamiento:

    Clave Valores Predeterminado Descripción
    channels.telegram.errorPolicy reply, silent reply reply envía un mensaje de error amigable al chat. silent suprime por completo las respuestas de error.
    channels.telegram.errorCooldownMs número (ms) 60000 Tiempo mínimo entre respuestas de error al mismo chat. Evita spam de errores durante interrupciones.

    Se admiten anulaciones por cuenta, por grupo y por tema (la misma herencia que otras claves de configuración de Telegram).

    {
      channels: {
        telegram: {
          errorPolicy: "reply",
          errorCooldownMs: 120000,
          groups: {
            "-1001234567890": {
              errorPolicy: "silent", // suppress errors in this group
            },
          },
        },
      },
    }
    

    Solución de problemas

    El bot no responde a mensajes de grupo sin mención
    • Si requireMention=false, el modo de privacidad de Telegram debe permitir visibilidad completa.
      • BotFather: /setprivacy -> Desactivar
      • luego elimina y vuelve a añadir el bot al grupo
    • openclaw channels status advierte cuando la configuración espera mensajes de grupo sin mención.
    • openclaw channels status --probe puede comprobar IDs numéricos explícitos de grupos; el comodín "*" no puede comprobarse por pertenencia.
    • prueba rápida de sesión: /activation always.
    El bot no ve ningún mensaje del grupo
    • cuando existe channels.telegram.groups, el grupo debe estar en la lista (o incluir "*")
    • verifica la pertenencia del bot al grupo
    • revisa los registros: openclaw logs --follow para ver motivos de omisión
    Los comandos funcionan parcialmente o no funcionan
    • autoriza la identidad de tu remitente (emparejamiento o allowFrom numérico, o ambos)
    • la autorización de comandos sigue aplicándose incluso cuando la política de grupo es open
    • setMyCommands failed con BOT_COMMANDS_TOO_MUCH significa que el menú nativo tiene demasiadas entradas; reduce los comandos de Plugin/Skill/personalizados o desactiva los menús nativos
    • Las llamadas de inicio deleteMyCommands / setMyCommands y las llamadas de escritura sendChatAction están acotadas y se reintentan una vez mediante la reserva de transporte de Telegram cuando una solicitud agota el tiempo de espera. Los errores persistentes de red/fetch suelen indicar problemas de alcanzabilidad DNS/HTTPS hacia api.telegram.org
    El inicio informa de un token no autorizado
    • getMe returned 401 es un fallo de autenticación de Telegram para el token de bot configurado.
    • Vuelve a copiar o regenera el token del bot en BotFather y luego actualiza channels.telegram.botToken, channels.telegram.tokenFile, channels.telegram.accounts.<id>.botToken o TELEGRAM_BOT_TOKEN para la cuenta predeterminada.
    • deleteWebhook 401 Unauthorized durante el inicio también es un fallo de autenticación; tratarlo como "no existe ningún Webhook" solo aplazaría el mismo fallo por token incorrecto a llamadas de API posteriores.
    Inestabilidad de polling o red
    • Node 22+ + fetch/proxy personalizado puede desencadenar un comportamiento de cancelación inmediata si los tipos de AbortSignal no coinciden.
    • Algunos hosts resuelven api.telegram.org primero a IPv6; una salida IPv6 defectuosa puede causar fallos intermitentes de la API de Telegram.
    • Si los registros incluyen TypeError: fetch failed o Network request for 'getUpdates' failed!, OpenClaw ahora reintenta estos casos como errores de red recuperables.
    • Durante el inicio de polling, OpenClaw reutiliza la prueba getMe de inicio correcta para grammY, de modo que el ejecutor no necesita un segundo getMe antes del primer getUpdates.
    • Si deleteWebhook falla con un error de red transitorio durante el inicio de polling, OpenClaw continúa con long polling en lugar de hacer otra llamada previa de plano de control antes del polling. Un Webhook aún activo aparece como un conflicto de getUpdates; entonces OpenClaw reconstruye el transporte de Telegram y vuelve a intentar la limpieza del Webhook.
    • Si los sockets de Telegram se reciclan con una cadencia fija corta, comprueba si channels.telegram.timeoutSeconds es bajo; los clientes de bot limitan los valores configurados por debajo de las protecciones de solicitudes salientes y getUpdates, pero versiones anteriores podían cancelar cada sondeo o respuesta cuando esto se establecía por debajo de esas protecciones.
    • Si los registros incluyen Polling stall detected, OpenClaw reinicia el polling y reconstruye el transporte de Telegram tras 120 segundos sin vivacidad de long-poll completada de forma predeterminada.
    • openclaw channels status --probe y openclaw doctor advierten cuando una cuenta de polling en ejecución no ha completado getUpdates tras el periodo de gracia de inicio, cuando una cuenta de Webhook en ejecución no ha completado setWebhook tras el periodo de gracia de inicio, o cuando la última actividad correcta de transporte de polling está obsoleta.
    • Aumenta channels.telegram.pollingStallThresholdMs solo cuando las llamadas getUpdates de larga duración están sanas, pero tu host sigue informando falsos reinicios por bloqueo de polling. Los bloqueos persistentes suelen apuntar a problemas de proxy, DNS, IPv6 o salida TLS entre el host y api.telegram.org.
    • Telegram también respeta las variables de entorno de proxy del proceso para el transporte de Bot API, incluidas HTTP_PROXY, HTTPS_PROXY, ALL_PROXY y sus variantes en minúsculas. NO_PROXY / no_proxy todavía pueden omitir api.telegram.org.
    • Si el proxy gestionado de OpenClaw está configurado mediante OPENCLAW_PROXY_URL para un entorno de servicio y no existe ninguna variable de entorno de proxy estándar, Telegram también usa esa URL para el transporte de Bot API.
    • En hosts VPS con salida directa/TLS inestable, enruta las llamadas de la API de Telegram mediante channels.telegram.proxy:
    channels:
    telegram:
    proxy: socks5://<user>:<password>@proxy-host:1080
    
    • Node 22+ usa autoSelectFamily=true de forma predeterminada (excepto WSL2). El orden de resultados DNS de Telegram respeta OPENCLAW_TELEGRAM_DNS_RESULT_ORDER, luego channels.telegram.network.dnsResultOrder, luego el valor predeterminado del proceso como NODE_OPTIONS=--dns-result-order=ipv4first; si ninguno aplica, Node 22+ recurre a ipv4first.
    • Si tu host es WSL2 o funciona explícitamente mejor con comportamiento solo IPv4, fuerza la selección de familia:
    channels:
    telegram:
    network:
      autoSelectFamily: false
    
    • Las respuestas de rango de referencia RFC 2544 (198.18.0.0/15) ya están permitidas para descargas de medios de Telegram de forma predeterminada. Si una IP falsa de confianza o un proxy transparente reescribe api.telegram.org a alguna otra dirección privada/interna/de uso especial durante las descargas de medios, puedes optar por la omisión exclusiva de Telegram:
    channels:
    telegram:
    network:
      dangerouslyAllowPrivateNetwork: true
    
    • La misma opción está disponible por cuenta en channels.telegram.accounts.<accountId>.network.dangerouslyAllowPrivateNetwork.
    • Si tu proxy resuelve hosts de medios de Telegram en 198.18.x.x, deja primero desactivada la marca peligrosa. Los medios de Telegram ya permiten el rango de referencia RFC 2544 de forma predeterminada.
    • Sobrescrituras de entorno (temporales):
      • OPENCLAW_TELEGRAM_DISABLE_AUTO_SELECT_FAMILY=1
      • OPENCLAW_TELEGRAM_ENABLE_AUTO_SELECT_FAMILY=1
      • OPENCLAW_TELEGRAM_DNS_RESULT_ORDER=ipv4first
    • Valida las respuestas DNS:
    dig +short api.telegram.org A
    dig +short api.telegram.org AAAA
    

    Más ayuda: Solución de problemas de canales.

    Referencia de configuración

    Referencia principal: Referencia de configuración - Telegram.

    Campos de Telegram de alta señal
    • inicio/autenticación: enabled, botToken, tokenFile, accounts.* (tokenFile debe apuntar a un archivo normal; los symlinks se rechazan)
    • control de acceso: dmPolicy, allowFrom, groupPolicy, groupAllowFrom, groups, groups.*.topics.*, bindings[] de nivel superior (type: "acp")
    • aprobaciones de ejecución: execApprovals, accounts.*.execApprovals
    • comandos/menú: commands.native, commands.nativeSkills, customCommands
    • hilos/respuestas: replyToMode, dm.threadReplies, direct.*.threadReplies
    • streaming: streaming (vista previa), streaming.preview.toolProgress, blockStreaming
    • formato/entrega: textChunkLimit, chunkMode, linkPreview, responsePrefix
    • medios/red: mediaMaxMb, mediaGroupFlushMs, timeoutSeconds, pollingStallThresholdMs, retry, network.autoSelectFamily, network.dangerouslyAllowPrivateNetwork, proxy
    • raíz de API personalizada: apiRoot (solo raíz de Bot API; no incluyas /bot&lt;TOKEN&gt;)
    • Webhook: webhookUrl, webhookSecret, webhookPath, webhookHost
    • acciones/capacidades: capabilities.inlineButtons, actions.sendMessage|editMessage|deleteMessage|reactions|sticker
    • reacciones: reactionNotifications, reactionLevel
    • errores: errorPolicy, errorCooldownMs
    • escrituras/historial: configWrites, historyLimit, dmHistoryLimit, dms.*.historyLimit

    Relacionado