Hive ACP: Mi Alternativa a OpenClaw para Conectar Agentes de IA a Telegram
por Hugo Hernández Valdez

Introducción
Si trabajas con agentes de IA para programación, probablemente los usas desde la terminal. Funciona bien cuando estás frente a la computadora, pero cuando necesitas revisar algo desde el teléfono o delegar una tarea mientras estás fuera, la terminal no es una opción.
Existen herramientas que resuelven esto — OpenClaw es probablemente la más conocida, un agente autónomo open source que se conecta a Telegram, WhatsApp y otras plataformas. Pero yo quería construir algo propio — un sistema que entendiera mi workflow, que pudiera extender con mis propias herramientas, y que no dependiera de un framework ajeno para funcionar. No quería ser usuario de una solución, quería ser el autor.
Después de dos intentos fallidos — una interfaz 3D demasiado ambiciosa y un prototipo frágil — construí hive-acp, un bridge que conecta un agente de IA a Telegram usando los protocolos ACP y MCP. Cada conversación tiene su propio agente aislado, con persistencia de contexto y herramientas que el agente invoca por sí mismo.
Este artículo cubre las decisiones técnicas, la arquitectura, y las lecciones aprendidas durante el desarrollo.
El Problema
Los agentes de IA para desarrollo son poderosos, pero están atados a la terminal:
- Accesibilidad: Solo puedes usarlos frente a la computadora
- Concurrencia: Un solo proceso, una sola conversación a la vez
- Persistencia: Si el proceso muere, el contexto se pierde
- Herramientas: El agente no puede interactuar con la plataforma de chat (enviar archivos, reaccionar)
Mi workflow involucraba abrir la terminal, iniciar una sesión, trabajar, y perder todo el contexto al cerrar. Si quería revisar algo desde el teléfono, no había forma.
Podría haber usado OpenClaw u otra herramienta existente, pero ninguna me daba lo que buscaba: control total sobre la arquitectura, la posibilidad de agregar mis propios conectores, y un sistema de herramientas que yo definiera. Quería entender cada capa del sistema, no consumir una API opaca.
Los Intentos Anteriores
Intento 1: The Hive (Starfield)
La primera idea fue una interfaz tipo StarCraft para gestionar agentes. Un monorepo con Three.js, React, Hono y SQLite. 30 agentes simultáneos con modelos 3D, áreas con polígonos coloreados, streaming SSE, PWA instalable.
El problema: el 90% del esfuerzo se iba en la interfaz 3D y el 10% en la comunicación con los agentes. Cada cambio en una capa rompía las otras dos. Lo abandoné después de semanas.
Intento 2: Bot de Telegram directo
Simplifiqué a un solo archivo JavaScript que conectaba Telegram con el agente. Funcionaba para un usuario, pero se caía con mensajes concurrentes, no tenía persistencia, y las dependencias tenían 9 vulnerabilidades (incluyendo request, deprecated desde 2020).
Probó que la idea tenía sentido, pero no era confiable.
La Solución: ACP + MCP
Lo que cambió todo fue entender dos protocolos que ya existían:
ACP (Agent Client Protocol) — JSON-RPC 2.0 sobre stdio para comunicarse con el agente como proceso hijo. Simple, predecible, sin protocolos custom.
MCP (Model Context Protocol) — Estándar para exponer herramientas a agentes. Se definen tools con schemas JSON, se exponen por WebSocket, y el agente los descubre y usa automáticamente.
La combinación resuelve los problemas: ACP como canal limpio para hablar con el agente, MCP para darle capacidades sobre la plataforma de chat. Y lo más importante — yo controlo ambos lados.
Arquitectura Técnica
Stack Tecnológico
- TypeScript (ESM)
- grammy (SDK de Telegram, 0 vulnerabilidades)
- pino (logging estructurado JSON)
- ws (WebSocket para MCP server)
- dotenv (configuración por entorno)
¿Por qué TypeScript?
- Tipos nativos: grammy y el protocolo JSON-RPC se benefician de tipado estricto
- Ecosistema: Las mejores librerías de Telegram están en JS/TS
- Velocidad de desarrollo: Iteración rápida con
tsx watch - Compatibilidad: ACP funciona sobre stdio, que es agnóstico al lenguaje
Arquitectura: Pool Multi-Agente
La decisión más importante del diseño: cada conversación tiene su propio proceso del agente, completamente aislado.
El diseño tiene tres componentes principales:
-
TelegramAdapter: Recibe mensajes de Telegram (texto, fotos, documentos), construye prompts con metadata, y envía respuestas con fallback de formato (Markdown, HTML, plaintext).
-
AcpPool: Gestiona un
AcpClientpor chat. Lazy initialization — el proceso se crea al primer mensaje. Cleanup automático después de 30 minutos de inactividad. Health checks cada minuto para detectar procesos muertos. -
MCP Server: WebSocket que expone herramientas al agente. Cada adapter registra una
ToolCategorycon sus tools y su funciónexecute.
Persistencia de Contexto
Cuando un proceso se evicta por inactividad, el pool le pide al agente que genere un resumen de la conversación y lo guarda en disco como markdown:
private async evict(chatId: number, entry: PoolEntry): Promise<void> {
const summary = await entry.client.summarize();
if (summary) {
this.saveSummary(chatId, summary);
}
entry.client.stop();
this.pool.delete(chatId);
}
Cuando el usuario vuelve a escribir, el pool crea un nuevo proceso e inyecta el resumen como contexto inicial:
const summary = this.loadSummary(chatId);
if (summary) {
await client.prompt([{
type: "text",
text: `[CONTEXT FROM PREVIOUS SESSION]\n${summary}\n[END CONTEXT]`,
}]);
}
El agente retoma el hilo sin que el usuario note la interrupción. Los resúmenes se almacenan en .state/summaries/<chatId>.md.
Health Checks
Cada minuto, el pool verifica que los procesos sigan vivos. Solo se hace ping a clients que llevan más de 2 minutos sin actividad — para no interferir con prompts en ejecución:
if (now - entry.lastUsed > 2 * 60 * 1000) {
const alive = await entry.client.ping();
if (!alive) {
entry.client.stop();
this.pool.delete(chatId);
}
}
Si el ping falla (timeout de 10 segundos), el client se mata y se remueve del pool. El siguiente mensaje del usuario crea uno nuevo automáticamente.
Sistema de Tools
El agente tiene acceso a 5 herramientas vía MCP, organizadas en dos categorías:
Cada adapter define una ToolCategory — un objeto con la lista de tools y una función execute:
export function createTelegramTools(
adapter: TelegramAdapter,
workspace: string,
): ToolCategory {
return {
name: "telegram",
tools: [
{
name: "telegram_send_file",
description: "Send a file from the workspace to the active chat.",
inputSchema: {
type: "object",
properties: {
file_path: { type: "string", description: "Path to the file" },
},
required: ["file_path"],
},
},
],
async execute(toolName, args) {
// El MCP server llama aquí cuando el agente invoca un tool
},
};
}
Agregar un nuevo adapter (Slack, Discord) es crear dos archivos y registrarlos en index.ts. Sin tocar nada más.
Logging Estructurado
Todos los logs son JSON estructurado con campos queryables:
{
"level": "info",
"time": "2026-04-23T21:27:00.000Z",
"module": "acp",
"chatId": 123456,
"msg": "creating new client"
}
Listo para CloudWatch, Datadog, Loki, o cualquier herramienta de observabilidad.
Ejemplos de Uso
Gestión de Proyectos desde el Teléfono
Usuario: "revisa el estado del proyecto defensa"
Agente: [lee archivos del workspace, analiza estructura]
Agente: "El proyecto tiene 12 archivos, último commit hace 2 horas..."
Usuario: "mándame el package.json"
Agente: [ejecuta telegram_send_file]
> package.json enviado al chat
Usuario: "guarda el contexto de esta conversación"
Agente: [genera resumen, ejecuta context_save]
> Contexto guardado
Múltiples Usuarios Simultáneos
Cada usuario tiene su propio agente aislado. No comparten estado ni interfieren entre sí:
Chat 1 (Hugo): "analiza el código de src/index.ts"
Chat 2 (María): "crea un archivo README.md"
> Dos procesos independientes, sin conflictos
Comparativa
| Métrica | Prototipo anterior | Hive ACP |
|---|---|---|
| Paquetes | 219 | 36 |
| Vulnerabilidades | 9 | 0 |
| Líneas de código | ~200 (un archivo) | ~800 (12 archivos) |
| Agentes simultáneos | 1 (compartido) | 1 por chat (aislado) |
| Persistencia de contexto | No | Sí |
| Health checks | No | Sí |
| Logging estructurado | No | JSON |
Estructura del Proyecto
src/
├── index.ts # Entry point y boot sequence
├── acp/
│ ├── client.ts # Cliente ACP JSON-RPC (stdio)
│ └── pool.ts # Pool con eviction, health checks, contexto
├── adapters/
│ ├── chat/telegram/
│ │ ├── adapter.ts # Telegram - ACP (grammy)
│ │ └── tools.ts # Tools MCP de Telegram
│ └── context/
│ └── tools.ts # Tools MCP de contexto
├── mcp/
│ ├── bridge.ts # Bridge stdio - WebSocket
│ ├── handler.ts # Handler del protocolo MCP
│ └── types.ts # Interfaces ToolCategory / ToolDefinition
└── utils/
├── env.ts # Loader de dotenv
├── logger.ts # Logger pino JSON estructurado
└── pkg.ts # Lector de package.json
Lecciones Aprendidas
-
Los protocolos estándar ganan: Inventar protocolos custom es tentador pero caro. ACP y MCP ya resolvieron los problemas difíciles de comunicación con agentes. Usarlos ahorró semanas de trabajo.
-
Construir lo tuyo tiene valor: Usar una herramienta existente habría sido más rápido, pero no habría aprendido cómo funciona la comunicación con agentes por dentro. Entender cada capa me permite extender el sistema de formas que una solución cerrada no permitiría.
-
La extensibilidad sale de la buena separación: No diseñé el sistema de adapters pensando en Slack. Salió natural de separar responsabilidades. Cuando el código está bien organizado, la extensibilidad es un efecto secundario.
-
Menos es más: Starfield tenía miles de líneas para una interfaz 3D que nadie necesitaba. Un bot de Telegram que puedo usar desde el teléfono es infinitamente más práctico que un dashboard 3D que solo funciona en desktop.
-
El contexto es lo más valioso: La persistencia de resúmenes transformó la experiencia. Sin ella, cada reconexión era empezar de cero. Con ella, el agente retoma conversaciones de días anteriores.
Mejoras Futuras
- Más adapters: Slack y Discord son los candidatos obvios
- Correlation IDs: Para trazar un mensaje desde Telegram hasta la respuesta del agente
- Métricas de duración: Cuánto tarda cada prompt en responder
- Rate limiting: Limitar procesos simultáneos para evitar sobrecarga
- Resúmenes incrementales: Acumular contexto entre sesiones en vez de reemplazarlo
Conclusiones
Hive ACP resuelve un problema específico: usar un agente de IA para desarrollo desde cualquier lugar, no solo desde la terminal. No reemplaza la experiencia de terminal para sesiones largas de coding, pero la complementa para revisiones rápidas, delegación de tareas, y gestión de proyectos en movimiento.
Más allá de la herramienta en sí, el proceso de construirla — incluyendo los dos fracasos — me enseñó más sobre arquitectura de agentes que cualquier tutorial. A veces la mejor forma de entender un sistema es construirlo desde cero.
El código es open source en github.com/gouh/hive-acp.
