Telegram (Bot API)
Estado: listo para producción en mensajes directos + grupos de bots vía grammY. Long polling es el modo predeterminado; el modo webhook es opcional.
- Emparejamiento — La política predeterminada de mensajes directos para Telegram es emparejamiento.
- Solución de problemas de canales — Diagnóstico y playbooks de reparación entre canales.
- Configuración del gateway — Patrones y ejemplos completos de configuración de canales.
Configuración rápida
Paso 1: Crea el token del bot en BotFather
Abre Telegram y chatea con **@BotFather** (confirma que el handle es exactamente `@BotFather`).
Ejecuta `/newbot`, sigue las indicaciones y guarda el token.
Paso 2: Configura el token y la política de mensajes directos
{
channels: {
telegram: {
enabled: true,
botToken: "123:abc",
dmPolicy: "pairing",
groups: { "*": { requireMention: true } },
},
},
}
Variable de entorno alternativa: `TELEGRAM_BOT_TOKEN=...` (solo cuenta predeterminada).
Telegram **no** usa `openclaw channels login telegram`; configura el token en config/env, luego inicia el gateway.
Paso 3: 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 expiran después de 1 hora.
Paso 4: Añade el bot a un grupo
Añade el bot a tu grupo, luego establece `channels.telegram.groups` y `groupPolicy` según tu modelo de acceso.
Nota: El orden de resolución de tokens tiene en cuenta la cuenta. En la práctica, los valores de configuración tienen prioridad sobre la alternativa de variable de entorno, y
TELEGRAM_BOT_TOKENsolo aplica a la cuenta predeterminada.
Configuración del lado de Telegram
Modo de privacidad y visibilidad en grupos
Los bots de Telegram usan por defecto el **Modo de privacidad**, que limita qué mensajes de grupo reciben.
Si el bot debe ver todos los mensajes del grupo, puedes:
- desactivar el modo de privacidad vía `/setprivacy`, o
- hacer al bot administrador del grupo.
Al cambiar el modo de privacidad, elimina y vuelve a añadir el bot en cada grupo para que Telegram aplique el cambio.
Permisos de 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 cual es útil para comportamiento siempre activo en grupos.
Toggles útiles de BotFather
- `/setjoingroups` para permitir/denegar añadir 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 a mensajes directos:
- `pairing` (predeterminado)
- `allowlist` (requiere al menos un ID de remitente en `allowFrom`)
- `open` (requiere que `allowFrom` incluya `"*"`)
- `disabled`
`channels.telegram.allowFrom` acepta IDs numéricos de usuario de Telegram. Los prefijos `telegram:` / `tg:` se aceptan y normalizan.
`dmPolicy: "allowlist"` con `allowFrom` vacío bloquea todos los mensajes directos y es rechazado por la validación de configuración.
El asistente de onboarding acepta entrada `@username` y lo resuelve a IDs numéricos.
Si actualizaste y tu configuración contiene entradas de `@username` en la lista de permitidos, ejecuta `openclaw doctor --fix` para resolverlas (mejor esfuerzo; requiere un token de bot de Telegram).
Si previamente dependías de archivos de lista de permitidos del almacén de emparejamiento, `openclaw doctor --fix` puede recuperar entradas en `channels.telegram.allowFrom` en flujos de lista de permitidos (por ejemplo cuando `dmPolicy: "allowlist"` no tiene IDs explícitos aún).
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 vez de depender de aprobaciones de emparejamiento previas).
### Encontrar tu ID de usuario de Telegram
Método 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 Bot API:
curl "https://api.telegram.org/bot<bot_token>/getUpdates"
Método de terceros (menos privado): `@userinfobot` o `@getidsbot`.
Política de grupo y listas de permitidos
Se aplican dos controles juntos:
1. **Qué grupos están permitidos** (`channels.telegram.groups`)
- sin configuración de `groups`:
- con `groupPolicy: "open"`: cualquier grupo puede pasar las verificaciones de ID de grupo
- con `groupPolicy: "allowlist"` (predeterminado): los grupos están bloqueados hasta que añadas entradas en `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 el filtrado de remitentes en grupo. Si no está establecido, 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 grupo o supergrupo de Telegram en `groupAllowFrom`. Los IDs de chat negativos pertenecen a `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 en grupo **no** hereda aprobaciones del almacén de emparejamiento de mensajes directos.
El emparejamiento permanece solo para mensajes directos. Para grupos, establece `groupAllowFrom` o `allowFrom` por grupo/tema.
Nota de runtime: si `channels.telegram` está completamente ausente, el runtime por defecto usa `groupPolicy="allowlist"` con fallo cerrado a menos que `channels.defaults.groupPolicy` esté explícitamente establecido.
Ejemplo: permitir a 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"],
},
},
},
},
}
> **Advertencia:**
Error común:
groupAllowFromno es una lista de grupos de Telegram permitidos.- Pon IDs de chat de grupo o supergrupo de Telegram negativos como `-1001234567890` en `channels.telegram.groups`. - Pon IDs de usuario de Telegram como `8734062810` en `groupAllowFrom` cuando quieras limitar qué personas dentro de un grupo permitido pueden activar el bot. - Usa `groupAllowFrom: ["*"]` solo cuando quieras que cualquier miembro de un grupo permitido pueda hablar con el bot.
Comportamiento de menciones
Las respuestas de grupo requieren mención por defecto.
La mención puede venir de:
- mención nativa `@botusername`, o
- patrones de mención en:
- `agents.list[].groupChat.mentionPatterns`
- `messages.groupChat.mentionPatterns`
Toggles de comando a nivel de sesión:
- `/activation always`
- `/activation mention`
Estos actualizan solo 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 del grupo a `@userinfobot` / `@getidsbot`
- o lee `chat.id` de `openclaw logs --follow`
- o inspecciona Bot API `getUpdates`
Comportamiento en runtime
- Telegram es propiedad del proceso del gateway.
- El enrutamiento es determinístico: las entradas de Telegram se responden en Telegram (el modelo no elige canales).
- Los mensajes entrantes se normalizan en el sobre de canal compartido con metadatos de respuesta y placeholders de medios.
- Las sesiones de grupo están aisladas por ID de grupo. Los temas de foro añaden
:topic:<threadId>para mantener los temas aislados. - Los mensajes directos pueden llevar
message_thread_id; OpenClaw los enruta con claves de sesión conscientes de hilos y preserva el ID del hilo para las respuestas. - Long polling usa el runner de grammY con secuenciación por chat/hilo. La concurrencia general del sink del runner usa
agents.defaults.maxConcurrent. - La Bot API de Telegram no tiene soporte de acuse de lectura (
sendReadReceiptsno aplica).
Referencia de funcionalidades
Vista previa de streaming 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` (por defecto: `partial`)
- `progress` se mapea a `partial` en Telegram (compat con nombres entre canales)
- `channels.telegram.streamMode` legacy y valores boolean `streaming` se auto-mapean
Para respuestas solo de texto:
- MD: OpenClaw mantiene el mismo mensaje de vista previa y realiza una edición final en su lugar (sin segundo mensaje)
- grupo/tema: OpenClaw mantiene el mismo mensaje de vista previa y realiza una edición final en su lugar (sin segundo mensaje)
Para respuestas complejas (p. ej., payloads de medios), OpenClaw recurre a la entrega final normal y luego limpia el mensaje de vista previa.
La transmisión de vista previa es separada de la transmisión por bloques. Cuando la transmisión por bloques está habilitada explícitamente para Telegram, OpenClaw omite la transmisión de vista previa para evitar doble transmisión.
Si el transporte nativo de borrador no está disponible/es rechazado, OpenClaw recurre automáticamente a `sendMessage` + `editMessageText`.
Stream de razonamiento exclusivo de Telegram:
- `/reasoning stream` envía el razonamiento a la vista previa en vivo mientras genera
- la respuesta final se envía sin texto de razonamiento
Formato y respaldo HTML
El texto saliente usa `parse_mode: "HTML"` de Telegram.
- El texto tipo Markdown se renderiza a HTML seguro para Telegram.
- El HTML sin procesar del modelo se escapa para reducir fallos de parseo de Telegram.
- Si Telegram rechaza el HTML parseado, OpenClaw reintenta como texto plano.
Las vistas previas de enlaces están activadas por defecto y pueden desactivarse con `channels.telegram.linkPreview: false`.
Comandos nativos y comandos personalizados
El registro del menú de comandos de Telegram se maneja al iniciar con `setMyCommands`.
Valores predeterminados de comandos nativos:
- `commands.native: "auto"` activa los comandos nativos para Telegram
Añade entradas de menú de comandos personalizados:
{
channels: {
telegram: {
customCommands: [
{ command: "backup", description: "Git backup" },
{ command: "generate", description: "Create an image" },
],
},
},
}
Reglas:
- los nombres se normalizan (eliminar `/` inicial, minúsculas)
- patrón válido: `a-z`, `0-9`, `_`, longitud `1..32`
- los comandos personalizados no pueden sobrescribir comandos nativos
- los conflictos/duplicados se omiten y registran
Botones inline
Configura el alcance del teclado inline:
{
channels: {
telegram: {
capabilities: {
inlineButtons: "allowlist",
},
},
},
}
Alcances:
- `off`
- `dm`
- `group`
- `all`
- `allowlist` (predeterminado)
Legacy `capabilities: ["inlineButtons"]` se mapea 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`, opcional `mediaUrl`, `replyToMessageId`, `messageThreadId`)
- `react` (`chatId`, `messageId`, `emoji`)
- `deleteMessage` (`chatId`, `messageId`)
- `editMessage` (`chatId`, `messageId`, `content`)
- `createForumTopic` (`chatId`, `name`, opcional `iconColor`, `iconCustomEmojiId`)
Las acciones de mensajes del canal exponen aliases ergonómicos (`send`, `react`, `delete`, `edit`, `sticker`, `sticker-search`, `topic-create`).
Controles de puertas:
- `channels.telegram.actions.sendMessage`
- `channels.telegram.actions.deleteMessage`
- `channels.telegram.actions.reactions`
- `channels.telegram.actions.sticker` (por defecto: desactivado)
Etiquetas de hilos de respuesta
Telegram admite etiquetas de hilos de respuesta explícitas en la salida generada:
- `[[reply_to_current]]` responde al mensaje que lo activó
- `[[reply_to:<id>]]` responde a un ID de mensaje específico de Telegram
`channels.telegram.replyToMode` controla el manejo:
- `off` (predeterminado)
- `first`
- `all`
Nota: `off` desactiva el hilo de respuesta implícito. Las etiquetas explícitas `[[reply_to_*]]` se respetan igualmente.
Temas de foro y comportamiento de hilos
Supergrupos de foro:
- las claves de sesión de tema añaden `:topic:<threadId>`
- las respuestas y escritura se dirigen al hilo del tema
- ruta de configuración de tema:
`channels.telegram.groups.<chatId>.topics.<threadId>`
Caso especial del tema general (`threadId=1`):
- los envíos de mensajes omiten `message_thread_id` (Telegram rechaza `sendMessage(...thread_id=1)`)
- las acciones de escritura sí incluyen `message_thread_id`
Herencia de tema: las entradas de tema heredan la configuración del grupo a menos que se sobrescriban (`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 estableciendo `agentId` en la configuración del tema. Esto le da a cada tema su propio espacio de trabajo, memoria y sesión aislados.
Audio, video y stickers
### Mensajes de audio
Telegram distingue notas de voz de archivos de audio.
- por defecto: comportamiento de archivo de audio
- etiqueta `[[audio_as_voice]]` en la respuesta del agente para forzar envío como nota de voz
### Mensajes de video
Telegram distingue archivos de video de notas de video.
Las notas de video no admiten subtítulos; el texto proporcionado se envía por separado.
### Stickers
Manejo de stickers entrantes:
- WEBP estático: descargado y procesado (placeholder `<media:sticker>`)
- TGS animado: omitido
- WEBM de video: omitido
Activa acciones de sticker:
{
channels: {
telegram: {
actions: {
sticker: true,
},
},
},
}
Notificaciones de reacciones
Las reacciones de Telegram llegan como actualizaciones `message_reaction` (separadas de los payloads de mensajes).
Configuración:
- `channels.telegram.reactionNotifications`: `off | own | all` (por defecto: `own`)
- `channels.telegram.reactionLevel`: `off | ack | minimal | extensive` (por defecto: `minimal`)
Long polling vs webhook
Por defecto: long polling.
Modo webhook:
- establece `channels.telegram.webhookUrl`
- establece `channels.telegram.webhookSecret` (obligatorio cuando se establece la URL de webhook)
- opcional `channels.telegram.webhookPath` (por defecto `/telegram-webhook`)
- opcional `channels.telegram.webhookHost` (por defecto `127.0.0.1`)
- opcional `channels.telegram.webhookPort` (por defecto `8787`)
Límites, reintentos y destinos CLI
- `channels.telegram.textChunkLimit` por defecto es 4000.
- `channels.telegram.chunkMode="newline"` prefiere límites de párrafo (líneas en blanco) antes de dividir por longitud.
- `channels.telegram.mediaMaxMb` (por defecto 100) limita el tamaño de medios entrantes y salientes de Telegram.
- el historial de contexto de grupo usa `channels.telegram.historyLimit` o `messages.groupChat.historyLimit` (por defecto 50); `0` desactiva.
El destino de envío CLI puede ser ID numérico de chat o username:
openclaw message send --channel telegram --target 123456789 --message "hi"
openclaw message send --channel telegram --target @name --message "hi"
Aprobaciones de ejecución en Telegram
Telegram admite aprobaciones de ejecución en mensajes directos del aprobador y puede opcionalmente publicar solicitudes de aprobación en el chat o tema de origen.
Ruta de configuración:
- `channels.telegram.execApprovals.enabled`
- `channels.telegram.execApprovals.approvers`
- `channels.telegram.execApprovals.target` (`dm` | `channel` | `both`, por defecto: `dm`)
Los aprobadores deben ser IDs numéricos de usuario de Telegram.
Documentación relacionada: [Aprobaciones de ejecución](/docs/tools/exec-approvals)
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` -> Disable
- luego elimina + vuelve a añadir el bot al grupo
- `openclaw channels status` advierte cuando la configuración espera mensajes de grupo sin mención.
- verificación rápida de sesión: `/activation always`.
El bot no ve mensajes de grupo en absoluto
- cuando `channels.telegram.groups` existe, el grupo debe estar listado (o incluir `"*"`)
- verifica la membresía del bot en el grupo
- revisa los registros: `openclaw logs --follow` para razones de omisión
Los comandos funcionan parcialmente o no funcionan
- autoriza tu identidad de remitente (emparejamiento y/o `allowFrom` numérico)
- la autorización de comandos sigue aplicando incluso cuando la política de grupo es `open`
Inestabilidad de polling o red
- Node 22+ + fetch/proxy personalizado puede activar comportamiento de abort inmediato si los tipos de AbortSignal no coinciden.
- Algunos hosts resuelven `api.telegram.org` a IPv6 primero; el egreso IPv6 roto puede causar fallos intermitentes en la API de Telegram.
- En hosts VPS con egreso/TLS directo inestable, enruta las llamadas a la API de Telegram a través de `channels.telegram.proxy`:
channels:
telegram:
proxy: socks5://<user>:<password>@proxy-host:1080
Para más ayuda: Solución de problemas de canales.
Referencia de configuración de Telegram
Referencia principal:
-
channels.telegram.enabled: activar/desactivar el inicio del canal. -
channels.telegram.botToken: token del bot (BotFather). -
channels.telegram.dmPolicy:pairing | allowlist | open | disabled(por defecto: pairing). -
channels.telegram.allowFrom: lista de permitidos para mensajes directos (IDs numéricos de usuario de Telegram). -
channels.telegram.groupPolicy:open | allowlist | disabled(por defecto: allowlist). -
channels.telegram.groupAllowFrom: lista de permitidos de remitentes en grupo (IDs numéricos de usuario de Telegram). -
channels.telegram.groups: valores predeterminados por grupo + lista de permitidos (usa"*"para valores predeterminados globales). -
channels.telegram.replyToMode:off | first | all(por defecto:off). -
channels.telegram.streaming:off | partial | block | progress(vista previa de streaming en vivo; por defecto:partial). -
channels.telegram.mediaMaxMb: límite de medios entrantes/salientes de Telegram (MB, por defecto: 100). -
channels.telegram.capabilities.inlineButtons:off | dm | group | all | allowlist(por defecto: allowlist).