ACP (Agent Client Protocol) (Español)
¿Qué es ACP?
Sección titulada «¿Qué es ACP?»ACP (Agent Client Protocol) es un transporte de «CLI como backend» para OmniRoute. En lugar de interceptar llamadas a las API HTTP de proveedores de IA, ACP inicia agentes CLI como procesos secundarios y envía las instrucciones mediante su interfaz nativa.
¿Por qué usar ACP?
Sección titulada «¿Por qué usar ACP?»| Ventaja | Descripción |
|---|---|
| No requiere claves de API | Usa la autenticación existente de tu CLI |
| Protocolo nativo | Usa el formato nativo de entrada/salida de cada CLI |
| Detección automática | Detecta las CLI instaladas en tu sistema |
| 15 agentes integrados | Preconfigurados para herramientas CLI populares |
| Agentes personalizados | Añade tus propias herramientas CLI mediante la configuración |
| Gestión de procesos | Gestiona el ciclo de vida (iniciar, enviar, finalizar) |
Agentes CLI compatibles
Sección titulada «Agentes CLI compatibles»ACP admite 15 agentes CLI integrados de forma predeterminada:
| ID del agente | Nombre para mostrar | Binario | Protocolo |
|---|---|---|---|
codex |
OpenAI Codex CLI | codex |
stdio |
claude |
Claude Code CLI | claude |
stdio |
goose |
Goose CLI | goose |
stdio |
openclaw |
OpenClaw | openclaw |
stdio |
aider |
Aider | aider |
stdio |
opencode |
OpenCode | opencode |
stdio |
cline |
Cline | cline |
stdio |
qwen |
Qwen Code | qwen --acp |
stdio |
forge |
ForgeCode | forge |
stdio |
amazon-q |
Amazon Q Developer | q |
stdio |
interpreter |
Open Interpreter | interpreter |
stdio |
cursor-cli |
Cursor CLI | cursor |
stdio |
warp |
Warp AI | warp |
stdio |
gemini |
Gemini CLI | gemini |
stdio |
zcode |
ZCode | zcode |
stdio |
Agentes personalizados
Sección titulada «Agentes personalizados»Puedes añadir tus propios agentes CLI mediante la configuración. Los agentes personalizados admiten las mismas funciones que los agentes integrados.
Inicio rápido
Sección titulada «Inicio rápido»Paso 1: Instala un agente CLI
Sección titulada «Paso 1: Instala un agente CLI»# Ejemplo: instala Claude Code CLInpm install -g @anthropic-ai/claude-code
# Verifica la instalaciónclaude --versionPaso 2: Detección automática de ACP
Sección titulada «Paso 2: Detección automática de ACP»ACP detecta automáticamente los agentes CLI instalados en tu sistema. ¡No se necesita ninguna configuración!
Paso 3: Usa el transporte ACP
Sección titulada «Paso 3: Usa el transporte ACP»Una vez detectado, ACP puede usarse como transporte para cualquier proveedor compatible. OmniRoute usará ACP automáticamente cuando la CLI esté disponible.
Cómo funciona ACP
Sección titulada «Cómo funciona ACP»Arquitectura
Sección titulada «Arquitectura»┌─────────────────┐│ OmniRoute ││ (proxy HTTP) │└────────┬────────┘ │ │ spawn() ▼┌─────────────────┐│ Proceso secund. ││ (agente CLI) ││ ││ stdin ◄──────┤ Enviar instrucción│ stdout ──────►│ Recibir respuesta│ stderr ──────►│ Recibir errores└─────────────────┘Ciclo de vida del proceso
Sección titulada «Ciclo de vida del proceso»- Inicio — ACP crea un proceso secundario para el agente CLI
- Envío — ACP escribe las instrucciones en el stdin del proceso
- Recepción — ACP lee las respuestas de stdout/stderr
- Detección de inactividad — ACP espera 2 segundos de inactividad antes de considerar que la respuesta está completa
- Finalización — ACP termina el proceso (SIGTERM y, después de 5 s, SIGKILL)
Protocolo de comunicación
Sección titulada «Protocolo de comunicación»ACP usa stdio (entrada/salida estándar) para comunicarse con los agentes CLI. El protocolo es:
- Enviar instrucción — Escribir en stdin con un salto de línea
- Esperar la respuesta — Leer de stdout hasta que quede inactivo (2 s sin salida)
- Tiempo de espera — 120 segundos de forma predeterminada (configurable)
Referencia de la API
Sección titulada «Referencia de la API»Funciones del registro
Sección titulada «Funciones del registro»detectInstalledAgents()
Sección titulada «detectInstalledAgents()»Detecta todos los agentes de CLI instalados en el sistema. Los resultados se almacenan en caché durante 60 segundos.
import { detectInstalledAgents } from "@/lib/acp";
const agents = detectInstalledAgents();// Devuelve: CliAgentInfo[]
interface CliAgentInfo { id: string; // p. ej., "codex", "claude" name: string; // Nombre para mostrar binary: string; // Nombre del binario que se iniciará versionCommand: string; // Comando de detección de versión version: string | null; // Versión detectada (null si no está instalado) installed: boolean; // Indica si el agente está instalado providerAlias: string; // ID del proveedor en OmniRoute spawnArgs: string[]; // Argumentos que se pasarán al iniciarlo protocol: "stdio" | "http"; // Protocolo de comunicación isCustom?: boolean; // Indica si es un agente personalizado definido por el usuario}getAvailableAgents()
Sección titulada «getAvailableAgents()»Obtiene únicamente los agentes que están instalados y disponibles para ACP.
import { getAvailableAgents } from "@/lib/acp";
const available = getAvailableAgents();// Devuelve: CliAgentInfo[] (solo agentes instalados)getAgentById(id)
Sección titulada «getAgentById(id)»Obtiene un agente específico por su ID.
import { getAgentById } from "@/lib/acp";
const agent = getAgentById("claude");// Devuelve: CliAgentInfo | undefinedsetCustomAgents(agents)
Sección titulada «setCustomAgents(agents)»Establece las definiciones de agentes personalizados desde la configuración.
import { setCustomAgents } from "@/lib/acp";
setCustomAgents([ { id: "my-custom-cli", name: "My Custom CLI", binary: "mycli", versionCommand: "mycli --version", providerAlias: "my-provider", spawnArgs: [], protocol: "stdio", },]);Funciones del gestor
Sección titulada «Funciones del gestor»acpManager.spawn(agentId, binary, args, env)
Sección titulada «acpManager.spawn(agentId, binary, args, env)»Inicia un nuevo proceso de agente de CLI.
import { acpManager } from "@/lib/acp";
const session = acpManager.spawn("claude", "claude", ["--print", "--output-format", "json"], { /* variables de entorno personalizadas */});// Devuelve: AcpSessionID de agente permitidos: ["claude", "codex", "gemini", "qwen"]
acpManager.sendPrompt(sessionId, prompt, timeoutMs)
Sección titulada «acpManager.sendPrompt(sessionId, prompt, timeoutMs)»Envía una instrucción a un agente de CLI y recopila la respuesta.
import { acpManager } from "@/lib/acp";
const response = await acpManager.sendPrompt( "acp-claude-1234567890-abc123", "What is 2+2?", 120000 // Tiempo de espera de 2 minutos);// Devuelve: Promise<string>acpManager.kill(sessionId)
Sección titulada «acpManager.kill(sessionId)»Finaliza una sesión y libera sus recursos.
import { acpManager } from "@/lib/acp";
const killed = acpManager.kill("acp-claude-1234567890-abc123");// Devuelve: booleanacpManager.getActiveSessions()
Sección titulada «acpManager.getActiveSessions()»Obtiene todas las sesiones activas.
import { acpManager } from "@/lib/acp";
const sessions = acpManager.getActiveSessions();// Devuelve: AcpSession[]acpManager.killAll()
Sección titulada «acpManager.killAll()»Finaliza todas las sesiones.
import { acpManager } from "@/lib/acp";
acpManager.killAll();Interfaz de sesión
Sección titulada «Interfaz de sesión»interface AcpSession { id: string; // ID único de la sesión agentId: string; // ID del agente (p. ej., "claude") process: ChildProcess; // Identificador del proceso secundario alive: boolean; // Indica si el proceso está activo stdoutBuffer: string; // Búfer acumulado de stdout stderrBuffer: string; // Búfer acumulado de stderr createdAt: Date; // Marca de tiempo de creación}Eventos
Sección titulada «Eventos»AcpManager extiende EventEmitter y emite los siguientes eventos:
Se emite cuando el agente de CLI escribe en stdout.
acpManager.on("stdout", ({ sessionId, data }) => { console.log(`[${sessionId}] stdout: ${data}`);});Se emite cuando el agente de CLI escribe en stderr.
acpManager.on("stderr", ({ sessionId, data }) => { console.error(`[${sessionId}] stderr: ${data}`);});Se emite cuando finaliza el proceso del agente de CLI.
acpManager.on("exit", ({ sessionId, code, signal }) => { console.log(`[${sessionId}] exited with code ${code}, signal ${signal}`);});Se emite cuando se produce un error en el proceso del agente de CLI.
acpManager.on("error", ({ sessionId, error }) => { console.error(`[${sessionId}] error: ${error}`);});Configuración
Sección titulada «Configuración»Variables de entorno
Sección titulada «Variables de entorno»ACP hereda todas las variables de entorno del proceso principal y puede ampliarse con variables de entorno personalizadas:
acpManager.spawn("claude", "claude", [], { ANTHROPIC_API_KEY: "sk-...", DEBUG: "true",});Argumentos de inicio
Sección titulada «Argumentos de inicio»Cada agente tiene argumentos de inicio predeterminados definidos en el registro. Puede sobrescribirlos:
acpManager.spawn("claude", "claude", ["--print", "--verbose"], {});Tiempos de espera
Sección titulada «Tiempos de espera»El tiempo de espera predeterminado de las solicitudes es de 120 segundos (2 minutos). Puede sobrescribirlo:
await acpManager.sendPrompt(sessionId, prompt, 300000); // 5 minutosCaché de detección
Sección titulada «Caché de detección»La detección de agentes se almacena en caché durante 60 segundos para evitar análisis costosos del sistema de archivos. Para forzar una actualización:
import { refreshAgentCache } from "@/lib/acp";
refreshAgentCache();Seguridad
Sección titulada «Seguridad»Prevención de inyección de comandos
Sección titulada «Prevención de inyección de comandos»ACP valida los comandos de versión para prevenir ataques de inyección de comandos:
const DISALLOWED_VERSION_COMMAND_CHARS = /[;&|<>`$\r\n]/;Los comandos de versión que contienen estos caracteres se rechazan:
;— Separador de comandos&— Proceso en segundo plano|— Tubería<,>— Redirección`— Sustitución de comandos$— Expansión de variables\r,\n— Saltos de línea
Validación del nombre del binario
Sección titulada «Validación del nombre del binario»ACP valida que el binario del comando de versión coincida con el nombre de binario esperado (a menos que sea un agente personalizado).
Aislamiento de procesos
Sección titulada «Aislamiento de procesos»Cada sesión de ACP se ejecuta en su propio proceso secundario. El proceso finaliza cuando termina la sesión o se agota el tiempo de espera.
Rendimiento
Sección titulada «Rendimiento»Rendimiento de la detección
Sección titulada «Rendimiento de la detección»- Primera llamada: ~50-200ms (ejecuta el comando
versionpara cada agente) - Llamadas almacenadas en caché: <1ms (devuelve el resultado desde la caché)
- TTL de la caché: 60 segundos
Rendimiento de las solicitudes
Sección titulada «Rendimiento de las solicitudes»- Inicio: ~50-100ms
- Envío de la solicitud: ~10-50ms
- Espera de la respuesta: Depende del agente de CLI (normalmente entre 1 y 30 segundos)
- Finalización: ~5 segundos (SIGTERM) + inmediata (SIGKILL)
Uso de recursos
Sección titulada «Uso de recursos»- Memoria por sesión: ~10-50MB (depende del agente de CLI)
- CPU: Mínimo (limitado por E/S)
- Disco: Ninguno
Solución de problemas
Sección titulada «Solución de problemas»Error “Unknown agent”
Sección titulada «Error “Unknown agent”»Problema: acpManager.spawn() genera Unknown agent: <id>
Solución: Solo se permiten estos agentes en spawn():
claudecodexgeminiqwen
Los demás agentes deben iniciarse manualmente o mediante definiciones de agentes personalizados.
Error “Session not alive”
Sección titulada «Error “Session not alive”»Problema: acpManager.sendPrompt() genera Session ${sessionId} is not alive
Solución: Es posible que la sesión haya finalizado o se haya cerrado. Compruebe el estado de la sesión:
const session = acpManager.getSession(sessionId);if (!session?.alive) { // Volver a iniciar la sesión acpManager.spawn("claude", "claude", [], {});}Error “ACP timeout”
Sección titulada «Error “ACP timeout”»Problema: acpManager.sendPrompt() genera ACP timeout after 120000ms
Solución: Aumente el tiempo de espera:
await acpManager.sendPrompt(sessionId, prompt, 300000); // 5 minutosCLI no detectada
Sección titulada «CLI no detectada»Problema: detectInstalledAgents() no encuentra su CLI
Soluciones:
- Compruebe PATH: Asegúrese de que la CLI esté en la variable PATH de su sistema
- Compruebe el comando de versión: Ejecute
claude --versionmanualmente - Compruebe los permisos: Asegúrese de que la CLI sea ejecutable
- Agente personalizado: Añada una definición de agente personalizado para las CLI no estándar
Permiso denegado
Sección titulada «Permiso denegado»Problema: ACP no puede ejecutar la CLI
Soluciones:
- Compruebe los permisos del archivo:
chmod +x /usr/local/bin/claude - Compruebe la propiedad: Asegúrese de que OmniRoute tenga permisos de lectura y ejecución
- Compruebe SELinux/AppArmor: Pueden bloquear el inicio de procesos
Ejemplos
Sección titulada «Ejemplos»Ejemplo 1: Iniciar y usar Claude Code
Sección titulada «Ejemplo 1: Iniciar y usar Claude Code»import { acpManager, detectInstalledAgents } from "@/lib/acp";
// Detectar los agentes instaladosconst agents = detectInstalledAgents();const claude = agents.find((a) => a.id === "claude");
if (claude?.installed) { // Iniciar una nueva sesión const session = acpManager.spawn("claude", claude.binary, ["--print", "--output-format", "json"]);
// Enviar una instrucción const response = await acpManager.sendPrompt( session.id, "Explain quantum computing in 100 words" );
console.log("Claude's response:", response);
// Limpiar acpManager.kill(session.id);}Ejemplo 2: Detección automática con alternativa
Sección titulada «Ejemplo 2: Detección automática con alternativa»import { acpManager, getAvailableAgents } from "@/lib/acp";
const available = getAvailableAgents();
// Probar primero Claude y, como alternativa, Codexlet agentId = "claude";if (!available.find((a) => a.id === "claude")) { if (available.find((a) => a.id === "codex")) { agentId = "codex"; } else { throw new Error("No ACP-compatible CLI agent found"); }}
const agent = available.find((a) => a.id === agentId)!;const session = acpManager.spawn(agentId, agent.binary, agent.spawnArgs);
const response = await acpManager.sendPrompt(session.id, "Hello!");
acpManager.kill(session.id);Ejemplo 3: Agente personalizado
Sección titulada «Ejemplo 3: Agente personalizado»import { setCustomAgents, detectInstalledAgents } from "@/lib/acp";
// Registrar un agente CLI personalizadosetCustomAgents([ { id: "my-llm-cli", name: "My LLM CLI", binary: "myllm", versionCommand: "myllm --version", providerAlias: "my-llm-provider", spawnArgs: ["--format", "json"], protocol: "stdio", },]);
// Ahora detectInstalledAgents() incluirá "my-llm-cli"const agents = detectInstalledAgents();¿Qué sigue?
Sección titulada «¿Qué sigue?»- Referencia de la API — Endpoints de la API REST
- Referencia de proveedores — Los 352 proveedores
- Servidor MCP — Integración con Model Context Protocol
- Servidor A2A — Protocolo de agente a agente
- Agente en la nube — Agentes basados en la nube
Referencia
Sección titulada «Referencia»- Proyecto AionUi — Inspiración para la detección automática de ACP
- Código fuente de ACP — Detalles de implementación
manager.ts— Gestión del ciclo de vida de los procesosregistry.ts— Detección y registro de agentesindex.ts— Exportaciones de la API pública
HagiCode
HagiCode es un espacio de trabajo de programación con agentes, flujos estructurados, ejecución multiagente y vistas de Hero Dungeon.
Convierte ideas en software útil con un flujo de trabajo con agentes más inteligente, rápido y ameno.

- SmartLos flujos estructurados convierten la intención en un itinerario ejecutable desde la idea hasta la entrega.
- EfficientLos flujos multiagente permiten avanzar en paralelo con la investigación, implementación y revisión.
- FunHero Dungeon hace que las largas sesiones de programación sean visuales y colaborativas.