Mainstream messaging

Telegram

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

Configuración rápida

  • Crear el token del bot en BotFather

    Ambos flujos terminan con un token que se pega en OpenClaw; elija uno:

    • Flujo de chat: abra Telegram, inicie un chat con @BotFather (confirme que el identificador sea exactamente @BotFather), ejecute /newbot, siga las indicaciones y guarde el token.
    • Flujo web: abra la aplicación web de BotFather, que funciona en todos los clientes de Telegram, incluido web.telegram.org; cree el bot en la interfaz y copie su token.
  • Configurar el token y la política de mensajes directos

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

    Alternativa mediante variable de entorno: TELEGRAM_BOT_TOKEN (solo para la cuenta predeterminada; las cuentas con nombre deben usar botToken o tokenFile). Telegram no utiliza openclaw channels login telegram; establezca el token en la configuración o el entorno y, después, inicie el Gateway.

  • Iniciar el Gateway y aprobar el primer mensaje directo

    bash
    openclaw gatewayopenclaw pairing list telegramopenclaw pairing approve telegram <CODE>

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

  • Añadir el bot a un grupo

    Añada el bot al grupo y, después, obtenga los dos ID necesarios para el acceso al grupo:

    • su ID de usuario de Telegram, para allowFrom / groupAllowFrom
    • el ID del chat de grupo de Telegram, como clave en channels.telegram.groups

    Obtenga el ID del chat de grupo mediante openclaw logs --follow, un bot de ID reenviados o getUpdates de la API de bots. Una vez permitido el grupo, /whoami@<bot_username> confirma los ID de usuario y grupo.

    Los ID negativos de supergrupos que comienzan por -100 son ID de chats de grupo. Se colocan en channels.telegram.groups, no en groupAllowFrom.

  • Configuración en Telegram

    Modo de privacidad y visibilidad en grupos

    Los bots de Telegram utilizan de forma predeterminada Privacy Mode, que limita los mensajes de grupo que reciben.

    Para ver todos los mensajes del grupo:

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

    Después de cambiar el modo de privacidad, elimine el bot y vuelva a añadirlo en cada grupo para que Telegram aplique el cambio.

    Permisos del grupo

    El estado de administrador se controla en la configuración del grupo de Telegram. Los bots administradores reciben todos los mensajes del grupo, lo que resulta útil para un comportamiento siempre activo en grupos.

    Opciones útiles de BotFather
    • /setjoingroups — permitir o denegar que se añada el bot a grupos
    • /setprivacy — comportamiento de visibilidad en grupos

    La misma configuración está disponible en la aplicación web de BotFather si se prefiere una interfaz a los comandos de chat.

    Miniaplicación del panel

    Ejecute /dashboard en un mensaje directo con el bot para abrir el panel de OpenClaw dentro de Telegram.

    Requisitos:

    • gateway.tailscale.mode: "serve" o "funnel" para la URL HTTPS publicada de la miniaplicación.
    • Su ID numérico de usuario de Telegram debe estar en el valor efectivo de allowFrom de la cuenta seleccionada o en commands.ownerAllowFrom.
    • Utilice un mensaje directo. En los grupos, /dashboard responde con open this in a DM with the bot y no envía ningún botón.
    • Instalaciones con Docker: los modos Serve/Funnel requieren que el Gateway se vincule a la interfaz de bucle invertido junto a tailscaled, algo que las redes de puente con puertos publicados no pueden satisfacer. Ejecute el contenedor del Gateway con network_mode: host y monte en el contenedor el socket tailscaled del host (/var/run/tailscale), además de la CLI tailscale.

    La miniaplicación es una ruta v1 exclusiva de Tailscale y no admite el iframe de Telegram Web.

    Control de acceso y activación

    Identidad del bot en grupos

    En grupos y temas de foros, una mención explícita del identificador configurado del bot (por ejemplo, @my_bot) se dirige al agente de OpenClaw seleccionado, aunque el nombre de la identidad del agente sea distinto del nombre de usuario de Telegram. La política de silencio del grupo sigue aplicándose al tráfico no relacionado, pero el identificador del bot nunca se considera «otra persona».

    Política de mensajes directos

    channels.telegram.dmPolicy controla el acceso a los mensajes directos:

    • 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 envíe comandos. Úselo solo para bots deliberadamente públicos con herramientas muy restringidas; los bots de un solo propietario deben usar allowlist con ID numéricos de usuario.

    channels.telegram.allowFrom acepta ID numéricos de usuarios de Telegram. Se aceptan y normalizan los prefijos telegram: / tg:. En configuraciones con varias cuentas, un valor restrictivo de nivel superior para channels.telegram.allowFrom constituye un límite de seguridad: un valor allowFrom: ["*"] a nivel de cuenta no hace pública esa cuenta a menos que la lista de permitidos efectiva combinada siga conteniendo un comodín explícito. dmPolicy: "allowlist" con allowFrom vacío bloquea todos los mensajes directos y la validación de la configuración lo rechaza. La configuración solo solicita ID numéricos de usuario. Si la configuración contiene entradas de la lista de permitidos @username procedentes de una configuración anterior, ejecute openclaw doctor --fix para resolverlas como ID numéricos (en la medida de lo posible; requiere un token de bot de Telegram). Si anteriormente se dependía de archivos de listas de permitidos del almacén de emparejamientos, openclaw doctor --fix puede recuperar las entradas en channels.telegram.allowFrom para los flujos de listas de permitidos (por ejemplo, cuando dmPolicy: "allowlist" todavía no tiene ID explícitos).

    Para los bots de un solo propietario, es preferible usar dmPolicy: "allowlist" con ID numéricos allowFrom explícitos en lugar de depender de aprobaciones de emparejamiento anteriores.

    Confusión habitual: aprobar el emparejamiento de mensajes directos no significa que «este remitente esté autorizado en todas partes». El emparejamiento solo concede acceso a los mensajes directos. Si todavía no existe un propietario de comandos, el primer emparejamiento aprobado también establece commands.ownerAllowFrom, lo que proporciona una cuenta de operador explícita para los comandos exclusivos del propietario y las aprobaciones de ejecución. La autorización de remitentes de grupos sigue procediendo de las listas de permitidos explícitas de la configuración. Para autorizar una misma identidad tanto en mensajes directos como en comandos de grupo, coloque su ID numérico de usuario de Telegram en channels.telegram.allowFrom y, para los comandos exclusivos del propietario, asegúrese de que commands.ownerAllowFrom contenga telegram:<your user id>.

    Cómo encontrar su ID de usuario de Telegram

    Método más seguro (sin bots de terceros): envíe un mensaje directo a su bot, ejecute openclaw logs --follow y consulte from.id.

    Método oficial mediante la API de bots:

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

    Terceros (menos privado): @userinfobot o @getidsbot.

    Política de grupos y listas de permitidos

    Se aplican conjuntamente dos controles:

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

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

      • open / allowlist (predeterminado) / disabled

    groupAllowFrom filtra los remitentes de grupos; si no está establecido, Telegram recurre a allowFrom (no al almacén de emparejamientos: la autorización de remitentes de grupos nunca hereda las aprobaciones del almacén de emparejamientos de mensajes directos, un límite de seguridad desde 2026.2.25). Las entradas de groupAllowFrom deben ser ID numéricos de usuarios de Telegram (los prefijos telegram: / tg: se normalizan); las entradas no numéricas se ignoran. No coloque aquí ID de chats de grupos o supergrupos; los ID de chat negativos se colocan en channels.telegram.groups. Patrón práctico para bots de un solo propietario: establezca su ID de usuario en channels.telegram.allowFrom, deje groupAllowFrom sin establecer y permita los grupos de destino en channels.telegram.groups. Si channels.telegram falta por completo en la configuración, en tiempo de ejecución se utiliza de forma predeterminada el valor de bloqueo seguro groupPolicy="allowlist", salvo que channels.defaults.groupPolicy se establezca explícitamente.

    Configuración de grupos exclusiva del propietario:

    json5
    {channels: {telegram: {  enabled: true,  dmPolicy: "pairing",  allowFrom: ["&lt;YOUR_TELEGRAM_USER_ID&gt;"],  groupPolicy: "allowlist",  groups: {    "&lt;GROUP_CHAT_ID&gt;": {      requireMention: true,    },  },},},}

    Realice la prueba desde el grupo con @<bot_username> ping. Los mensajes de grupo normales no activan el bot mientras requireMention: true.

    Permitir a cualquier miembro de un grupo específico:

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

    Permitir solo a usuarios específicos dentro de un grupo concreto:

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

    Comportamiento de las menciones

    Las respuestas en grupos requieren una mención de forma predeterminada. Una mención puede proceder de:

    • una mención nativa de @botusername, o
    • un patrón de mención en agents.entries.*.groupChat.mentionPatterns o messages.groupChat.mentionPatterns

    Opciones de sesión (solo afectan al estado y no se conservan): /activation always, /activation mention. Utilice la configuración para conservarlas:

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

    El contexto del historial del grupo está siempre activado y limitado por historyLimit. Establezca channels.telegram.historyLimit: 0 para desactivar la ventana del historial del grupo. openclaw doctor --fix elimina la clave retirada includeGroupHistoryContext.

    Cómo obtener el ID del chat de grupo: reenvíe un mensaje del grupo a @userinfobot / @getidsbot, consulte chat.id en openclaw logs --follow, inspeccione getUpdates de la API de bots o, una vez permitido el grupo, ejecute /whoami@<bot_username>.

    Comportamiento en tiempo de ejecución

    • Telegram se ejecuta dentro del proceso del Gateway.
    • El enrutamiento es determinista: las respuestas a mensajes entrantes de Telegram vuelven a Telegram (el modelo no elige los canales).
    • Los mensajes entrantes se normalizan en el contenedor compartido del canal con metadatos de respuesta, marcadores de posición de contenido multimedia y contexto persistente de la cadena de respuestas para las respuestas que el Gateway ha observado.
    • Las sesiones de grupo se aíslan por ID de grupo. Los temas del foro añaden :topic:<threadId>.
    • Los mensajes directos pueden incluir message_thread_id; OpenClaw lo conserva para las respuestas. Las sesiones de temas de mensajes directos solo se dividen cuando getMe de Telegram indica has_topics_enabled: true para el bot; de lo contrario, los mensajes directos permanecen en la sesión plana.
    • El sondeo largo utiliza el ejecutor de grammY con secuenciación por chat y por hilo. La concurrencia del receptor del ejecutor utiliza agents.defaults.maxConcurrent.
    • El inicio multicuenta limita las sondas getMe simultáneas para que las grandes flotas de bots no ejecuten a la vez la sonda de cada cuenta.
    • Cada proceso del Gateway protege el sondeo largo para que solo un sondeador activo pueda usar un token de bot a la vez. Los conflictos 409 persistentes de getUpdates indican que otro Gateway de OpenClaw, script o sondeador externo está usando el mismo token.
    • El supervisor del sondeo se reinicia tras 120 segundos sin que se complete la comprobación de actividad de getUpdates.
    • La API de bots de Telegram no admite confirmaciones de lectura (sendReadReceipts no se aplica).

    Referencia de funcionalidades

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

    OpenClaw transmite respuestas parciales en tiempo real en chats directos, grupos y temas: envía un mensaje de vista previa y luego ejecuta editMessageText repetidamente, finalizándolo en el mismo lugar.

    • channels.telegram.streaming es off | partial | block | progress (valor predeterminado: partial)
    • las vistas previas breves de la respuesta inicial se retrasan mediante antirrebote y luego se materializan tras una demora limitada si la ejecución sigue activa
    • progress mantiene un único borrador de estado editable para el progreso de las herramientas, muestra la etiqueta de estado estable cuando se produce actividad de respuesta antes que progreso de herramientas, lo borra al finalizar y envía la respuesta final como un mensaje normal
    • streaming.preview.toolProgress controla si las actualizaciones de herramientas o progreso reutilizan el mismo mensaje de vista previa editado (valor predeterminado: true cuando la transmisión de la vista previa está activa)
    • streaming.preview.commandText controla los detalles de comandos y ejecución dentro de esas líneas: raw (valor predeterminado) o status (solo la etiqueta de la herramienta)
    • streaming.progress.commentary (valor predeterminado: false) habilita el texto de comentarios o preámbulo del asistente en el borrador temporal de progreso
    • se detectan el valor heredado channels.telegram.streamMode, los valores booleanos de streaming y las claves retiradas de vista previa de borradores nativos; ejecute openclaw doctor --fix para migrarlos

    Las líneas de progreso de herramientas son las actualizaciones breves de estado que se muestran mientras se ejecutan herramientas (ejecución de comandos, lectura de archivos, actualizaciones de planificación, resúmenes de parches y preámbulos o comentarios de Codex en modo de servidor de aplicaciones). Telegram las mantiene activadas de forma predeterminada (coincide con el comportamiento publicado desde v2026.4.22+).

    Mantenga las ediciones de la vista previa de la respuesta, pero oculte las líneas de progreso de herramientas:

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

    Mantenga visible el progreso de herramientas, pero oculte el texto de comandos y ejecución:

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

    El modo progress muestra el progreso de las herramientas sin editar la respuesta final en ese mensaje. Coloque la política de texto de comandos en streaming.progress:

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

    streaming.mode: "off" desactiva las ediciones de vista previa y suprime los mensajes genéricos de herramientas o progreso en lugar de enviarlos como mensajes de estado independientes; las solicitudes de aprobación, el contenido multimedia y los errores siguen la entrega final normal. streaming.preview.toolProgress: false conserva únicamente las ediciones de la vista previa de la respuesta.

    Para las respuestas de solo texto: las vistas previas breves reciben la edición final en el mismo lugar; las respuestas finales largas que se dividen en varios mensajes reutilizan la vista previa como primer fragmento y luego envían solo el resto; las respuestas finales del modo de progreso borran el borrador de estado y usan la entrega final normal; si la edición final falla antes de que se confirme la finalización, OpenClaw recurre a la entrega final normal y elimina la vista previa obsoleta. Para respuestas complejas (cargas de contenido multimedia), OpenClaw siempre recurre a la entrega final normal y elimina la vista previa.

    La transmisión de vistas previas y la transmisión por bloques son mutuamente excluyentes: cuando la transmisión por bloques está habilitada explícitamente, OpenClaw omite la transmisión de la vista previa para evitar una transmisión doble.

    Razonamiento: /reasoning stream transmite el razonamiento a la vista previa en directo durante la generación y luego elimina la vista previa del razonamiento después de la entrega final (use /reasoning on para mantenerla visible). La respuesta final se envía sin el texto del razonamiento.

    Formato enriquecido de mensajes

    De forma predeterminada, el texto saliente utiliza mensajes HTML estándar de Telegram, legibles en los clientes actuales: negrita, cursiva, enlaces, código, contenido oculto y citas; no bloques exclusivos del formato enriquecido de la API de bots 10.2 (tablas nativas, detalles, contenido multimedia enriquecido y fórmulas).

    Habilite los mensajes enriquecidos de la API de bots 10.2:

    json5
    {channels: {telegram: {  richMessages: true,},},}

    Cuando se habilitan: se informa al agente de que los mensajes enriquecidos están disponibles para este bot o cuenta (con el contrato de creación compatible de Markdown e islas HTML); el texto Markdown se representa mediante la IR de Markdown de OpenClaw como bloques enriquecidos tipados de la API de bots 10.2 (encabezados, tablas, detalles, listas de comprobación, contenido multimedia enriquecido, fórmulas, mapas y collages); los pies del contenido multimedia siguen usando pies HTML de Telegram (los mensajes enriquecidos no sustituyen los pies y estos tienen un límite de 1024 caracteres).

    Esto evita que el texto del modelo contenga los signos especiales de Markdown enriquecido de Telegram, de modo que las divisas como $400-600K no se interpreten como fórmulas matemáticas. El texto enriquecido largo se divide automáticamente según los límites de Telegram. Las tablas que superan el límite de 20 columnas recurren a un bloque de código.

    Valor predeterminado: desactivado, por compatibilidad con los clientes; algunos clientes actuales de escritorio, web, Android y de terceros muestran como no compatibles los mensajes enriquecidos aceptados. Mantenga esta opción desactivada a menos que todos los clientes utilizados con el bot puedan representarlos. /status muestra si los mensajes enriquecidos están activados o desactivados en la sesión actual.

    Las vistas previas de enlaces están activadas de forma predeterminada. channels.telegram.linkPreview: false desactiva la detección automática de entidades en el texto enriquecido.

    Comandos nativos y comandos personalizados

    El menú de comandos de Telegram se registra al iniciar mediante setMyCommands. commands.native: "auto" habilita los comandos nativos para Telegram.

    Añada entradas personalizadas al menú de comandos:

    json5
    {channels: {telegram: {  customCommands: [    { command: "backup", description: "Copia de seguridad de Git" },    { command: "generate", description: "Crear una imagen" },  ],},},}

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

    Los comandos personalizados son únicamente entradas de menú: no implementan ningún comportamiento automáticamente. Los comandos de plugins o Skills pueden seguir funcionando al escribirlos aunque no aparezcan en el menú de Telegram. Si se desactivan los comandos nativos, se eliminan los integrados; los comandos personalizados o de plugins aún pueden registrarse si están configurados.

    Errores habituales de configuración:

    • setMyCommands failed con BOT_COMMANDS_TOO_MUCH después de un reintento de recorte significa que el menú sigue superando el límite; reduzca los comandos de plugins, Skills o personalizados, o desactive channels.telegram.commands.native.
    • Si deleteWebhook, deleteMyCommands o setMyCommands fallan con 404: Not Found mientras los comandos curl directos de la API de bots funcionan, suele significar que channels.telegram.apiRoot se configuró con el endpoint completo /bot&lt;TOKEN&gt;. apiRoot debe ser únicamente la raíz de la API de bots; openclaw doctor --fix elimina un /bot&lt;TOKEN&gt; final accidental.
    • getMe returned 401 significa que Telegram rechazó el token de bot configurado. Actualice botToken, tokenFile o TELEGRAM_BOT_TOKEN (cuenta predeterminada) con el token actual de BotFather; OpenClaw se detiene antes del sondeo, por lo que esto no se notifica como un fallo de limpieza del Webhook.
    • setMyCommands failed con errores de red o recuperación suele significar que el DNS o HTTPS saliente hacia api.telegram.org está bloqueado.

    Comandos de emparejamiento de dispositivos (plugin device-pair)

    Cuando está instalado:

    1. /pair genera un código de configuración
    2. pegue el código en la aplicación de iOS
    3. /pair pending muestra las solicitudes pendientes (incluidos el rol y los ámbitos)
    4. para aprobar: /pair approve <requestId>, /pair approve (única solicitud pendiente) o /pair approve latest

    Si un dispositivo vuelve a intentarlo con detalles de autenticación modificados (rol, ámbitos o clave pública), la solicitud pendiente anterior se sustituye por una nueva requestId; vuelva a ejecutar /pair pending antes de aprobarla.

    Más información: Emparejamiento.

    Botones integrados

    Configure el ámbito del teclado integrado:

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

    Reemplazo por cuenta:

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

    Ámbitos: off, dm, group, all, allowlist (valor predeterminado). El valor heredado capabilities: ["inlineButtons"] se asigna a "all".

    Ejemplo de acción de mensaje:

    json5
    {action: "send",channel: "telegram",to: "123456789",message: "Elija una opción:",buttons: [[  { text: "Sí", callback_data: "yes" },  { text: "No", callback_data: "no" },],[{ text: "Cancelar", callback_data: "cancel" }],],}

    Ejemplo de botón de Mini App:

    json5
    {action: "send",channel: "telegram",to: "123456789",message: "Abrir aplicación:",presentation: {blocks: [  {    type: "buttons",    buttons: [{ label: "Iniciar", web_app: { url: "https://example.com/app" } }],  },],},}

    Los botones web_app solo funcionan en chats privados entre un usuario y el bot.

    Los clics en devoluciones de llamada que ningún controlador interactivo de un plugin registrado reclame se envían al agente como texto: callback_data: <value>.

    Acciones de mensajes de Telegram para agentes y automatización

    Acciones:

    • sendMessage (to, content, mediaUrl opcional, replyToMessageId, messageThreadId)
    • react (chatId, messageId, emoji)
    • deleteMessage (chatId, messageId)
    • editMessage (chatId, messageId, content o caption, botones integrados presentation opcionales; las ediciones que solo afectan a botones actualizan el marcado de respuesta)
    • createForumTopic (chatId, name, iconColor opcional, iconCustomEmojiId)

    Alias ergonómicos: send, react, delete, edit, sticker, sticker-search, topic-create.

    Habilitación: channels.telegram.actions.sendMessage, deleteMessage, reactions, sticker (valor predeterminado: deshabilitado). edit, createForumTopic y editForumTopic están habilitados de forma predeterminada y no tienen un conmutador específico. Los envíos en tiempo de ejecución usan la instantánea activa de configuración y secretos obtenida al iniciar o recargar, por lo que las rutas de acción no vuelven a resolver los valores de SecretRef en cada envío.

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

    Etiquetas de hilos de respuesta

    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

    channels.telegram.replyToMode: off (valor predeterminado), first, all.

    Cuando los hilos de respuesta están habilitados y el texto o pie de foto original está disponible, OpenClaw añade automáticamente un fragmento de cita nativo. Telegram limita el texto de las citas nativas a 1024 unidades de código UTF-16; los mensajes más largos se citan desde el principio y se recurre a una respuesta simple si Telegram rechaza la cita.

    off solo deshabilita los hilos de respuesta implícitos; las etiquetas explícitas [[reply_to_*]] siguen respetándose.

    Temas de foros y comportamiento de los hilos

    Supergrupos con foro: las claves de sesión de los temas añaden :topic:<threadId>; las respuestas y el indicador de escritura se dirigen al hilo del tema; la ruta de configuración del tema es channels.telegram.groups.<chatId>.topics.<threadId>.

    El tema general (threadId=1) es un caso especial: los envíos de mensajes omiten message_thread_id (Telegram rechaza sendMessage(...thread_id=1) con "thread not found"), pero las acciones de escritura siguen incluyendo message_thread_id (se ha comprobado empíricamente que es necesario para que aparezca el indicador de escritura).

    Las entradas de temas heredan la configuración del grupo salvo que se sobrescriba (requireMention, allowFrom, skills, systemPrompt, enabled, groupPolicy). agentId solo se aplica al tema y no se hereda de los valores predeterminados del grupo. topics."*" establece los valores predeterminados de todos los temas de ese grupo; los ID de tema exactos siguen teniendo prioridad sobre "*".

    Enrutamiento de agentes por tema: cada tema puede dirigirse a un agente diferente mediante agentId en la configuración del tema, lo que le proporciona su propio espacio de trabajo, memoria y sesión:

    json5
    {  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          }        }      }    }  }}

    De este modo, cada tema tiene su propia clave de sesión, por ejemplo, agent:zu:telegram:group:-1001234567890:topic:3.

    Vinculación persistente de temas ACP: los temas de foros pueden fijar sesiones del arnés ACP mediante vinculaciones tipadas de nivel superior (bindings[] con type: "acp", match.channel: "telegram", peer.kind: "group" y un ID que incluya el tema, como -1001234567890:topic:42). Actualmente, el alcance se limita a los temas de foros de grupos y supergrupos. Consulte Agentes ACP.

    Creación de ACP vinculada al hilo desde el chat: /acp spawn <agent> --thread here|auto vincula el tema actual a una nueva sesión ACP; los mensajes posteriores se dirigen directamente a ella y OpenClaw fija la confirmación de creación en el tema. Se controla mediante session.threadBindings.spawnSessions (valor predeterminado: true).

    El contexto de plantilla expone MessageThreadId y IsForum. Los chats de mensajes directos con message_thread_id conservan los metadatos de respuesta, pero solo usan claves de sesión compatibles con hilos cuando getMe de Telegram informa de has_topics_enabled: true. Las sustituciones retiradas dm.threadReplies y direct.*.threadReplies ya no existen; el modo de hilos de BotFather es la única fuente de verdad. Ejecute openclaw doctor --fix para eliminar las claves de configuración obsoletas.

    Audio, vídeo y stickers

    Mensajes de audio

    Telegram distingue las notas de voz de los archivos de audio. Valor predeterminado: comportamiento de archivo de audio; incluya la 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 presentan en el contexto del agente como texto no fiable generado por una máquina, pero la detección de menciones sigue usando la transcripción sin procesar para que los mensajes de voz condicionados por menciones sigan funcionando.

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

    Mensajes de vídeo

    Telegram distingue los archivos de vídeo de las notas de vídeo. Las notas de vídeo no admiten pies de foto; el texto proporcionado en el mensaje se envía por separado.

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

    Ubicaciones y lugares

    Use la acción send existente con un objeto location independiente. Las coordenadas envían un marcador nativo; añadir tanto name como address envía una tarjeta de lugar nativa. Los envíos de ubicaciones no pueden combinarse con texto de mensaje ni contenido multimedia.

    json5
    {action: "send",channel: "telegram",to: "123456789",location: {latitude: 48.858844,longitude: 2.294351,accuracy: 12,name: "Torre Eiffel",address: "Campo de Marte, París",},}

    Stickers

    Entrantes: los archivos WEBP estáticos se descargan y procesan (marcador de posición <media:sticker>); los archivos TGS animados y WEBM de vídeo se omiten.

    Campos de contexto de stickers: Sticker.emoji, Sticker.setName, Sticker.fileId, Sticker.fileUniqueId, Sticker.cachedDescription. Las descripciones se almacenan en caché en el estado SQLite del plugin de OpenClaw para reducir las llamadas de visión repetidas.

    Habilite las acciones de stickers:

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

    Envío:

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

    Busque stickers almacenados en caché:

    json5
    {action: "sticker-search",channel: "telegram",query: "gato saludando",limit: 5,}
    Notificaciones de reacciones

    Las reacciones de Telegram llegan como actualizaciones message_reaction, separadas de las cargas útiles de los mensajes. Cuando se habilitan, OpenClaw pone en cola eventos del sistema como Telegram reaction added: 👍 by Alice (@alice) on msg 42.

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

    own significa que solo se incluyen las reacciones de usuarios a mensajes enviados por el bot (se aplica el mejor esfuerzo mediante una 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 ID de hilo en las actualizaciones de reacciones: los grupos que no son foros se dirigen a la sesión del chat grupal; los grupos con foro se dirigen a la sesión del tema general (:topic:1), no al tema exacto de origen.

    allowed_updates para sondeo o Webhook incluye message_reaction automáticamente.

    Reacciones de confirmación

    ackReaction envía un emoji de confirmación mientras OpenClaw procesa un mensaje entrante. messages.ackReactionScope determina cuándo se envía.

    Orden de resolución de emojis:

    • channels.telegram.accounts.<accountId>.ackReaction
    • channels.telegram.ackReaction
    • messages.ackReaction
    • emoji alternativo de la identidad del agente (agents.entries.*.identity.emoji; de lo contrario, "👀")

    Telegram espera un emoji Unicode (por ejemplo, "👀"); use "" para deshabilitar la reacción en un canal o una cuenta.

    Ámbito (messages.ackReactionScope, valor predeterminado "group-mentions"; actualmente no existe ninguna sustitución para cuentas ni canales de Telegram):

    all (mensajes directos y grupos, incluidos los eventos ambientales de sala), direct (solo mensajes directos), group-all (todos los mensajes de grupo excepto los eventos ambientales de sala, sin mensajes directos), group-mentions (grupos cuando se menciona al bot; sin mensajes directos — valor predeterminado), off / none (deshabilitado).

    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 grupos (migrate_to_chat_id, actualiza channels.telegram.groups) y /config set / /config unset (requiere habilitar los comandos).

    Para deshabilitarlas:

    json5
    {channels: {telegram: {  configWrites: false,},},}
    Sondeo prolongado frente a Webhook

    El valor predeterminado es el sondeo prolongado. Para el modo Webhook, establezca channels.telegram.webhookUrl y channels.telegram.webhookSecret; opcionalmente, webhookPath (valor predeterminado /telegram-webhook), webhookHost (valor predeterminado 127.0.0.1), webhookPort (valor predeterminado 8787) y webhookCertPath (certificado PEM autofirmado para configuraciones con IP directa o sin dominio).

    En el modo de sondeo prolongado, OpenClaw conserva su marca de reinicio solo después de que una actualización se distribuya correctamente; si un controlador falla, esa actualización puede volver a intentarse en el mismo proceso en lugar de marcarse como completada.

    El receptor local se vincula de forma predeterminada a 127.0.0.1:8787. Para el acceso público, coloque un proxy inverso delante del puerto local o establezca webhookHost: "0.0.0.0" de forma intencionada.

    El modo Webhook valida las protecciones de la solicitud, el token secreto de Telegram y el cuerpo JSON y, a continuación, confirma la actualización en su cola de entrada duradera antes de devolver una respuesta 200 vacía. La adopción duradera correcta incluye x-openclaw-delivery-accepted: durable; las respuestas de estado, enrutamiento, autenticación, validación y error de almacenamiento omiten este encabezado. Los proxies inversos y los controladores del host pueden exigir el encabezado para distinguir la adopción por parte de OpenClaw de una respuesta 200 vacía genérica sin deducir la aceptación a partir del tiempo de respuesta.

    Después de la escritura duradera, OpenClaw reclama y procesa las actualizaciones mediante el drenaje de entrada de canales del núcleo (carriles por chat y por tema, finalización al adoptar el turno y tiempo de espera por bloqueo previo a la adopción). Los turnos lentos del agente no retienen el ACK de entrega de Telegram.

    Límites y destinos de la CLI
    • channels.telegram.textChunkLimit tiene un valor predeterminado de 4000; streaming.chunkMode="newline" prioriza los límites de párrafo (líneas en blanco) antes de dividir por longitud.
    • channels.telegram.mediaMaxMb (valor predeterminado: 100) limita el tamaño de los archivos multimedia entrantes y salientes.
    • el historial de contexto de grupo usa channels.telegram.historyLimit o messages.groupChat.historyLimit (valor predeterminado: 50); 0 lo desactiva.
    • el contexto complementario de respuestas, citas y reenvíos se normaliza en una única ventana de contexto de conversación seleccionada cuando el Gateway ha observado los mensajes principales; la caché de mensajes observados reside en el estado SQLite del plugin de OpenClaw, y openclaw doctor --fix importa los archivos auxiliares heredados. Telegram solo incluye un reply_to_message superficial por actualización, por lo que las cadenas anteriores a la caché se limitan a esa carga útil.
    • las listas de permitidos de Telegram controlan principalmente quién puede activar el agente, no constituyen un límite completo de ocultación del contexto complementario.
    • historial de mensajes directos: channels.telegram.dmHistoryLimit, channels.telegram.dms["<user_id>"].historyLimit.

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

    bash
    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"

    Las encuestas usan openclaw message poll y admiten temas de foro:

    bash
    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

    Opciones de encuesta exclusivas de Telegram: --poll-duration-seconds (5-600), --poll-anonymous, --poll-public, --thread-id (o un destino :topic:). --poll-option se repite entre 2 y 12 veces (el límite de opciones de Telegram).

    El envío de Telegram también admite --presentation con bloques buttons para teclados en línea (cuando channels.telegram.capabilities.inlineButtons lo permite), --pin o --delivery '{"pin":true}' para solicitar la entrega fijada cuando el bot puede fijar mensajes en ese chat, y --force-document para enviar imágenes, GIF y vídeos salientes como documentos en lugar de cargas comprimidas, animadas o de vídeo.

    Control de acciones: channels.telegram.actions.sendMessage=false desactiva todos los mensajes salientes, incluidas las encuestas; channels.telegram.actions.poll=false desactiva la creación de encuestas, pero mantiene habilitados los envíos normales.

    Aprobaciones de ejecución en Telegram

    Telegram admite aprobaciones de ejecución en los mensajes directos de los aprobadores y, opcionalmente, puede publicar solicitudes en el chat o tema de origen. Los aprobadores deben ser ID numéricos de usuario de Telegram.

    • channels.telegram.execApprovals.enabled ("auto" las habilita cuando se puede resolver al menos un aprobador)
    • channels.telegram.execApprovals.approvers (recurre a los ID numéricos de propietarios de commands.ownerAllowFrom)
    • channels.telegram.execApprovals.target: dm (valor predeterminado) | channel | both
    • agentFilter, sessionFilter

    channels.telegram.allowFrom, groupAllowFrom y defaultTo controlan quién puede comunicarse con el bot y dónde envía este las respuestas normales; no convierten a nadie en aprobador de ejecución. El primer emparejamiento aprobado por mensaje directo inicializa commands.ownerAllowFrom cuando todavía no existe un propietario de comandos, por lo que las configuraciones con un único propietario funcionan sin duplicar ID en execApprovals.approvers.

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

    Los botones de aprobación en línea también requieren que channels.telegram.capabilities.inlineButtons permita la superficie de destino (dm, group o all). Los ID de aprobación con el prefijo plugin: se resuelven mediante las aprobaciones del plugin; los demás se resuelven primero mediante las aprobaciones de ejecución.

    Consulte Aprobaciones de ejecución.

    Controles de respuestas de error

    Cuando el agente encuentra un error de entrega o del proveedor, la política de errores controla si los mensajes de error llegan al chat de Telegram:

    Clave Valores Valor predeterminado Descripción
    channels.telegram.errorPolicy always, once, silent always always envía todos los mensajes de error al chat. once envía cada mensaje de error único una vez por cada intervalo de espera integrado. silent nunca envía mensajes de error al chat.

    Se admiten anulaciones por cuenta, grupo y tema (con la misma herencia que las demás claves de configuración de Telegram).

    json5
    {  channels: {    telegram: {      errorPolicy: "always",      groups: {        "-1001234567890": {          errorPolicy: "silent", // suprimir los errores en este grupo        },      },    },  },}

    Solución de problemas

    El bot no responde a los mensajes de grupo sin mención
    • Si requireMention=false, el modo de privacidad de Telegram debe permitir la visibilidad completa: BotFather /setprivacy -> Disable; después, elimine el bot del grupo y vuelva a añadirlo.
    • openclaw channels status muestra una advertencia cuando la configuración espera mensajes de grupo sin mención.
    • openclaw channels status --probe comprueba ID numéricos de grupo explícitos; no se puede comprobar la pertenencia con el comodín "*".
    • Prueba rápida de sesión: /activation always.
    El bot no recibe ningún mensaje de grupo
    • Cuando existe channels.telegram.groups, el grupo debe aparecer en la lista (o incluir "*").
    • Verifique que el bot pertenezca al grupo.
    • Revise openclaw logs --follow para conocer los motivos de omisión.
    Los comandos funcionan parcialmente o no funcionan
    • Autorice la identidad del remitente (mediante emparejamiento o el valor numérico allowFrom); la autorización de comandos sigue aplicándose incluso cuando la política del grupo es open.
    • setMyCommands failed con BOT_COMMANDS_TOO_MUCH significa que el menú nativo tiene demasiadas entradas; reduzca los comandos de plugins, Skills o personalizados, o desactive los menús nativos.
    • Las llamadas de inicio deleteMyCommands / setMyCommands y las llamadas de escritura sendChatAction tienen límites y vuelven a intentarse una vez mediante el transporte alternativo de Telegram cuando la solicitud agota el tiempo de espera. Los errores persistentes de red o recuperación suelen significar que no se puede acceder mediante DNS/HTTPS a 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. Vuelva a copiar o generar el token en BotFather y, a continuación, actualice channels.telegram.botToken, tokenFile, accounts.<id>.botToken o TELEGRAM_BOT_TOKEN (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 del token incorrecto hasta una llamada posterior a la API.
    Inestabilidad del sondeo o de la red
    • Node 22+ con una implementación personalizada de recuperación o proxy puede provocar cancelaciones inmediatas si los tipos de AbortSignal no coinciden.
    • Algunos hosts resuelven primero api.telegram.org como IPv6; una salida IPv6 defectuosa provoca fallos intermitentes de la API.
    • Los registros con TypeError: fetch failed o Network request for 'getUpdates' failed! se vuelven a intentar como errores de red recuperables.
    • Durante el inicio del sondeo, OpenClaw reutiliza para grammY la comprobación de inicio getMe completada correctamente, de modo que el ejecutor no necesite un segundo getMe antes del primer getUpdates.
    • Si deleteWebhook falla con un error de red transitorio durante el inicio del sondeo, OpenClaw continúa con el sondeo prolongado en lugar de realizar otra llamada al plano de control previa al sondeo. Un Webhook aún activo aparece entonces como un conflicto getUpdates; OpenClaw reconstruye el transporte y vuelve a intentar la limpieza del Webhook.
    • Polling stall detected en los registros significa que OpenClaw reinicia el sondeo y reconstruye el transporte después de 120 segundos sin completar la comprobación de actividad del sondeo prolongado de forma predeterminada.
    • openclaw channels status --probe y openclaw doctor muestran una advertencia cuando una cuenta de sondeo en ejecución no ha completado getUpdates después del período de gracia de inicio, una cuenta de Webhook en ejecución no ha completado setWebhook después del período de gracia de inicio, o la última actividad correcta del transporte de sondeo está obsoleta.
    • Telegram respeta las variables de entorno de proxy del proceso para el transporte de la API del bot: HTTP_PROXY, HTTPS_PROXY, ALL_PROXY y sus variantes en minúsculas. NO_PROXY / no_proxy aún pueden omitir api.telegram.org.
    • Si OPENCLAW_PROXY_URL está establecido 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 la API del bot.
    • En hosts VPS con salida directa o TLS inestables, enrute las llamadas a la API de Telegram mediante un proxy:
    yaml
    channels:telegram:proxy: socks5://<user>:<password>@proxy-host:1080
    • Node 22+ usa autoSelectFamily=true de forma predeterminada (excepto en WSL2). El orden de los resultados DNS de Telegram respeta OPENCLAW_TELEGRAM_DNS_RESULT_ORDER, después channels.telegram.network.dnsResultOrder y, por último, el valor predeterminado del proceso (por ejemplo, NODE_OPTIONS=--dns-result-order=ipv4first); si ninguno se aplica, recurre a ipv4first en Node 22+.
    • En WSL2, o cuando el comportamiento exclusivo de IPv4 funciona mejor, fuerce la selección de familia:
    yaml
    channels:telegram:network:  autoSelectFamily: false
    • Las respuestas del intervalo de referencia de RFC 2544 (198.18.0.0/15) ya se permiten de forma predeterminada para las descargas de contenido multimedia de Telegram. Si un proxy de IP falsa o transparente de confianza reescribe api.telegram.org como alguna otra dirección privada, interna o de uso especial durante las descargas de contenido multimedia, habilite la omisión exclusiva de Telegram:
    yaml
    channels:telegram:network:  dangerouslyAllowPrivateNetwork: true
    • La misma opción está disponible por cuenta en channels.telegram.accounts.<accountId>.network.dangerouslyAllowPrivateNetwork.
    • Si el proxy resuelve los hosts de contenido multimedia de Telegram dentro de 198.18.x.x, mantenga primero desactivada la opción peligrosa: ese intervalo ya se permite de forma predeterminada.
    • Anulaciones temporales del entorno: OPENCLAW_TELEGRAM_DISABLE_AUTO_SELECT_FAMILY=1, OPENCLAW_TELEGRAM_ENABLE_AUTO_SELECT_FAMILY=1, OPENCLAW_TELEGRAM_DNS_RESULT_ORDER=ipv4first.
    • Valide las respuestas DNS:
    bash
    dig +short api.telegram.org Adig +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 más relevantes
    • inicio/autenticación: enabled, botToken, tokenFile (debe ser un archivo normal; se rechazan los enlaces simbólicos), accounts.*
    • control de acceso: dmPolicy, allowFrom, groupPolicy, groupAllowFrom, groups, groups.*.topics.*, bindings[] de nivel superior (type: "acp")
    • valores predeterminados de los temas: groups.<chatId>.topics."*" se aplica a los temas del foro sin coincidencia; los ID de tema exactos lo anulan
    • aprobaciones de ejecución: execApprovals, accounts.*.execApprovals
    • comandos/menú: commands.native, commands.nativeSkills, customCommands
    • hilos/respuestas: replyToMode, threadBindings
    • transmisión: streaming (modos off | partial | block | progress), streaming.preview.toolProgress
    • formato/entrega: textChunkLimit, streaming.chunkMode, richMessages, markdown.tables (off | bullets | code | block), linkPreview, responsePrefix
    • contenido multimedia/red: mediaMaxMb, network.autoSelectFamily, network.dangerouslyAllowPrivateNetwork, proxy
    • raíz de API personalizada: apiRoot (solo la raíz de la API de bots; no incluya /bot&lt;TOKEN&gt;), trustedLocalFileRoots (raíces file_path absolutas de la API de bots autoalojada)
    • Webhook: webhookUrl, webhookSecret, webhookPath, webhookHost, webhookPort, webhookCertPath
    • acciones/capacidades: capabilities.inlineButtons, actions.sendMessage|editMessage|deleteMessage|reactions|sticker|createForumTopic|editForumTopic
    • reacciones: reactionNotifications, reactionLevel
    • errores: errorPolicy, silentErrorReplies
    • escrituras/historial: configWrites, historyLimit, dmHistoryLimit, dms.*.historyLimit

    Relacionado

    Was this useful?
    On this page

    On this page