Un agente no se vuelve potente porque tenga un buen prompt. Se vuelve potente cuando puede llamar trabajo que vive fuera de su propio runtime sin romper la experiencia del usuario. Ese fue el problema real: queriamos hablar con Codex desde Telegram usando a Nexo como puerta de entrada, sin convertir todo en una maraña de scripts frágiles y respuestas duplicadas.
- OpenClaw sirve como frontdesk; el bridge extiende sus manos hacia herramientas que viven en otra maquina.
- La mejor primera version no es la mas sofisticada, sino la mas operable: plugin, webhook interno, cola en disco y worker local.
- Codex puede responder end-to-end; Claude y Antigravity conviene tratarlos primero como handoff explicito hasta tener roundtrip real.
La idea que cambia el juego
Si tienes un agente principal en Telegram, tarde o temprano aparece una friccion: el canal esta en el servidor, pero parte de tu stack valioso vive en otra maquina. Puede ser Codex en tu Mac, una app que solo corre bien en tu escritorio o una herramienta local que no quieres exponer a Internet. Ahí nace la necesidad de un bridge.
La trampa es intentar resolverlo con polling, con scripts pegados con cinta o con un bot que finge hablar con todo cuando en realidad solo reenvia texto. Nosotros queriamos algo mejor: un canal unificado, respuestas honestas, trazabilidad minima y una base que pudiera crecer sin avergonzarnos despues.
Que queriamos lograr de verdad
- Escribirle a Nexo en Telegram usando prefijos claros como codex, ag o claude.
- Hacer que OpenClaw detecte ese prefijo y derive la consulta sin responder dos veces.
- Permitir roundtrip real con Codex local en la Mac.
- Dejar a Claude y Antigravity como handoff asistido hasta tener una integracion bidireccional seria.
- Mantener el bridge dentro de la red privada del servidor, sin exponer un webhook publico.
Dicho de otra forma: queriamos un solo canal de conversacion para varias herramientas muy distintas, pero sin inventar capacidades. Ese detalle importa mas de lo que parece. Muchas integraciones agenticas fallan porque prometen simetria donde solo hay dos caminos distintos: respuesta automatica o derivacion humana.
La arquitectura minima que si aguanta una prueba real
La arquitectura final no nacio como un diagrama bonito. Nacio de una pregunta incomoda: si mañana se cae la Mac, se reinicia el gateway o llega un mensaje duplicado, ¿el sistema sigue siendo entendible? Esa pregunta elimina muchisimas decisiones aparentemente sofisticadas.
Lo que dejamos fue una estructura de cinco capas: Telegram como canal, un plugin dentro de OpenClaw para detectar prefijos, un bridge HTTP local en el servidor, una cola basada en archivos para trabajos que deben cruzar a la Mac y un worker local que reclama, ejecuta y responde.
| Capa | Responsabilidad | Decision practica |
|---|---|---|
| Telegram | Canal de entrada | El usuario no cambia de interfaz ni aprende un flujo nuevo. |
| Plugin OpenClaw | Routing por prefijo y supresion de respuesta | El frontdesk sigue siendo Nexo. |
| Bridge interno | Validacion, deduplicacion, routing y observabilidad | Solo escucha en loopback. |
| Cola en disco | Persistir jobs para targets locales | Mas simple y depurable que meter Redis demasiado pronto. |
| Worker local | Ejecutar herramientas locales y responder | Aprovecha la Mac sin exponerla. |
Paso 1: interceptar el mensaje correcto dentro de OpenClaw
El primer paso real no fue escribir el worker. Fue decidir donde debía nacer la inteligencia del routing. La respuesta correcta era el gateway de OpenClaw, no un cron leyendo conversaciones despues. Si la orden entra por Telegram, el mejor lugar para detectar codex ayudame con esto es el mismo runtime que ya esta recibiendo el mensaje.
Por eso construimos un plugin pequeño que escucha message_received y message_sending. En message_received decide si el mensaje empieza por un prefijo conocido. Si no lo hace, Nexo trabaja normal. Si sí lo hace, el plugin construye un payload corto y lo envia al bridge interno.
Ese plugin tambien resuelve un problema de experiencia enorme: evitar que Nexo responda por su cuenta y ademas responda Codex despues. La cancelacion no se hace a ciegas. Solo se bloquea la respuesta normal cuando el bridge devolvio una fase valida: accepted, processing o responded.
Paso 2: diseñar un bridge pequeño, pero serio
El bridge es un proceso Node minimalista. No le pedimos que piense; le pedimos que haga cuatro cosas bien: autenticar, deduplicar, enrutar y observar. Cuando un componente hace solo eso, se vuelve mucho mas confiable.
El endpoint principal corre en 127.0.0.1:8788. Eso parece un detalle menor, pero es una decision de seguridad muy concreta. No queriamos un webhook publico para conectar Telegram con herramientas locales. Queriamos que el unico cliente del bridge fuera el plugin de OpenClaw dentro del mismo host.
A nivel de payload, el bridge solo necesita unas pocas piezas: conversationId, threadId, messageId, remitente, contenido y target. Todo lo demas es tentacion de sobrecargar el sistema con contexto que no aporta.
Paso 3: aceptar que no todo target es igual
Uno de los mejores cambios de arquitectura fue separar targets server-side de targets locales. Parece obvio despues, pero cambia todo. Codex local, Claude local y Antigravity local no viven en el mismo lugar ni tienen el mismo tipo de integracion. Meterlos en una sola ruta generica era una receta para el caos.
Entonces el bridge opera con dos allowlists muy claras: SERVER_TARGETS y LOCAL_TARGETS. Si el target es local, no intenta resolverlo inline. Lo escribe a disco como job. Si el target fuera server-side, podria resolverlo directamente con OpenClaw u otra herramienta local al servidor.
Esa separacion tambien nos obligo a ser honestos con el contrato de producto. Hoy codex-local devuelve una respuesta automatica completa. En cambio, claude-local y antigravity-local quedan como handoff asistido: abren la ruta correcta en la Mac, preparan el prompt y avisan claramente que la consulta fue derivada.
Paso 4: por que elegimos una cola en disco y no Redis
Si llevas tiempo construyendo sistemas, seguro ya escuchaste la objecion: una cola en disco no es elegante. Es verdad. Pero una cola en disco puede ser la decision correcta cuando el objetivo es lanzar una primera version operable, inspeccionable por SSH y facil de recuperar sin añadir otra pieza de infraestructura.
Nosotros queriamos tres carpetas y un comportamiento legible: queue/, processing/ y done/. Con eso podiamos ver exactamente donde estaba cada trabajo, reclamarlo desde la Mac, dejar trazabilidad de resultado y construir un reaper despues.
La pregunta que manda aqui no es si Redis es mejor en abstracto. Es esta: ¿cuanta concurrencia y cuanta opacidad puedes aceptar en la primera version? Para un canal personal de alta importancia y bajo volumen, disco gano por operacion.
Paso 5: construir el worker local como un operador remoto
El worker local corre en macOS y se mantiene vivo con un LaunchAgent. Su bucle es sencillo: reclama un job por SSH, lo mueve a processing/, ejecuta la herramienta adecuada y devuelve la respuesta por Telegram usando openclaw message send sobre el servidor.
Ese detalle de responder via OpenClaw importa muchisimo. No queriamos que la Mac hablara a Telegram por fuera del ecosistema. Queríamos que la respuesta volviera por la misma cuenta, el mismo chat y, si aplica, el mismo hilo. Por eso propagamos tambien threadId en el camino de vuelta.
En Codex, el worker construye un prompt corto y lo ejecuta con el binario local. En Claude y Antigravity no fingimos roundtrip: dejamos un mensaje de handoff claro. Esta honestidad evita una clase entera de bugs sociales, que son los peores: el sistema parece capaz de algo que todavia no puede hacer.
Paso 6: endurecer los fallos que aparecen en la vida real
La version inicial funcionaba, pero las mejores funciones no se prueban cuando todo sale bien. Se prueban cuando algo muere a mitad del camino. Ahí aparecieron cuatro problemas: jobs huérfanos en processing/, respuestas locales sin threadId, handoffs que parecian integraciones completas y un entorno de launchd demasiado pobre para wrappers basados en /usr/bin/env.
La solucion fue concreta. Añadimos un reaper que reencola trabajos atascados despues de N minutos. Propagamos threadId tambien al enviar la respuesta por Telegram. Cambiamos la UX textual de Claude y Antigravity para nombrarlos como handoff. Y fijamos un PATH explicito en el plist y en el runtime del worker.
Ese tipo de hardening es mucho menos vistoso que una demo, pero es lo que convierte una idea buena en una feature que no te abandona en el peor momento.
- Reaper sobre
processing/para reinyectar jobs huérfanos. - Heartbeat remoto del worker para saber si la Mac sigue viva.
- Métricas minimas por target: accepted, responded, errored, requeued.
- Healthcheck compuesto con estado de cola, worker y ultimo exito de codex-local.
Paso 7: observabilidad suficiente para no operar a ciegas
No hacia falta meter Prometheus para la primera version. Sí hacia falta responder rapido a preguntas operativas: ¿el bridge sigue vivo?, ¿el worker local sigue corriendo?, ¿hay jobs atorados?, ¿Codex respondio al menos una vez en la ultima ventana razonable?
Por eso el bridge persiste dos archivos simples: uno para métricas y otro para heartbeat del worker. Encima de eso expone /healthz, que resume cola, jobs vencidos, estado del worker y ultimo exito de codex-local. Con eso puedes saber si estás roto antes de que un usuario te lo diga.
| Señal | Que responde | Por que importa |
|---|---|---|
| bridgeOk | Si el proceso HTTP sigue vivo | Es la primera bifurcacion de cualquier incidente. |
| worker.ok | Si el worker local envio heartbeat reciente | Sin worker no hay agentes locales. |
| staleProcessingCount | Si quedaron jobs atascados | Detecta caidas despues de reclamar trabajo. |
| lastCodexLocalSuccessAt | Ultima respuesta exitosa de Codex | Da una prueba de vida mas util que solo un ping. |
Paso 8: empaquetarlo para que otra persona pueda usarlo
Una cosa es tener una funcionalidad andando en tu servidor. Otra muy distinta es convertirla en un paquete compartible. Ahí aparece una disciplina nueva: documentar arquitectura, instalacion, operacion y seguridad sin filtrar ningun secreto de tu instalacion.
Eso obliga a crear ejemplos sanitizados: .env.example, snippet de configuracion del plugin, README de arquitectura, guia de instalacion, documento de seguridad y una pieza separada que explique como construirlo desde cero. Esa es la diferencia entre un experimento privado y un paquete open source con cara y ojos.
La mejor prueba de calidad para este paso es una sola: si alguien puede entender el sistema, instalarlo con placeholders y reproducir la primera version sin tocar tus secretos, la documentacion ya esta cumpliendo su trabajo.
Lo que haria despues
La siguiente iteracion natural no es hacerla mas bonita. Es endurecer los bordes. Añadir una deduplicacion secundaria ademas de messageId, pinnear mejor trust de plugins en OpenClaw, medir SLA real por target y, si Claude o Antigravity exponen una superficie estable, convertir el handoff en roundtrip verdadero.
Tambien hay una pregunta de producto muy buena escondida aqui: cuando ya tienes este bridge, no solo conectas herramientas. Conectas contextos de trabajo. Telegram deja de ser solo un chat y se vuelve la puerta desde la que coordinas un stack entero de agentes y utilidades personales.
Fuentes para seguir profundizando
- OpenClaw plugins Base oficial para la capa de plugins y su integracion en el runtime.
- OpenClaw plugin manifest Referencia del manifiesto y configuracion del plugin.
- Node.js child_process.execFile Referencia oficial del mecanismo usado para ejecutar herramientas locales y server-side.
- Telegram Bot API changelog Referencia para threading, topics y evolucion del canal.
Preguntas que suelen aparecer
Por que no usar un cron cada cinco minutos para leer conversaciones?
Porque introduce latencia, duplicados y una experiencia mala. El plugin en tiempo real intercepta el mensaje en el punto correcto y reduce ambiguedad operacional.
Por que no usar Redis desde el inicio?
Porque la primera version necesitaba ser simple, visible y recuperable. Redis puede ser el siguiente paso si sube la concurrencia o el volumen.
Claude y Antigravity ya responden automaticamente?
No todavia. Hoy se comportan como handoff asistido y eso debe presentarse de forma explicita para no romper expectativas.
Que parte de esta arquitectura mas importa mantener sana?
La frontera entre Nexo como frontdesk, el bridge como router y el worker como ejecutor. Cuando mezclas esas capas, empiezan los problemas de latencia, duplicados y trazabilidad.
Que leer despues
Guia definitiva para entender OpenClaw
El mapa completo del sistema donde este bridge encaja de forma natural.
AbrirComo crear tu primer agente util
La base conceptual para que este tipo de integracion no termine en teatro agentico.
AbrirComo evitar la alucinacion operacional
Porque una integracion buena no solo conecta herramientas: tambien evita prometer acciones que no ocurrieron.
AbrirConversa con la academia y deja criterio publico.
Ahora el acceso vive arriba a la derecha, como debe ser. Desde ahi puedes entrar, comentar y abrir el bot flotante para resolver dudas puntuales sin romper la lectura.
Los comentarios se moderan cuando hace falta, los aportes utiles se votan y el bot flotante responde corto, con contexto del articulo y limites claros de uso.