Skip to content

Protocolo ACP

源码版本v2026.7.20

Responsabilidad

ACP (Agent Client Protocol) es el protocolo estándar de comunicación entre un editor/IDE y un agent. acp_adapter/ expone a Hermes como server ACP, de modo que los clientes compatibles (Zed, extensiones de VS Code, etc.) puedan conducir Hermes directamente: gestionar sesiones (session), leer/escribir recursos (ficheros/imágenes), aprobar ediciones, trazar provenance y aislar herramientas (tool) por permisos. Así Hermes no vive solo en plataformas de mensajes, también se incrusta en flujos de desarrollo.

Motivo de diseño

Hermes nació para plataformas de mensajería — el gateway conecta Telegram/Discord con conversaciones largas. Pero un IDE es otra cosa: el directorio de trabajo lo abre el editor y el cwd debe seguirlo; una modificación de fichero no puede ejecutarse porque el agent lo diga, hay que pasársela al usuario para que la revise; entre sesiones hace falta trazabilidad de «esta sesión se comprimió a partir de cuál». ACP traduce estas restricciones propias del IDE a los primitivos que Hermes ya tiene. No reescribe el bucle del agent: enchufa el flujo de mensajes ACP a run_conversation, convierte los recursos ACP en content parts de OpenAI, y transforma las llamadas a herramienta que escriben ficheros en EditProposal con revisión humana. El principio es «adaptar, no reescribir».

Archivos clave

Flujo de datos

  1. El cliente ACP (editor) descubre y arranca el server ACP de Hermes a partir de acp_registry/agent.json (acp_adapter/__main__.py).
  2. El cliente inicia una sesión → SessionManager:175 crea un SessionState, alinea cwd (acp_adapter/session.py:29) y expande toolsets (acp_adapter/session.py:129).
  3. El cliente envía mensajes/recursos → la conversión de recursos:201 traduce el recurso ACP (fichero/imagen, sujeto al límite de tamaño de acp_adapter/server.py:96) a partes de contenido OpenAI y las entrega a run_conversation:588.
  4. Cuando el agent quiere modificar ficheros, la llamada a herramienta pasa por build_edit_proposal:178 y se convierte en un EditProposal, que el requester de aprobación (acp_adapter/edit_approval.py:51) eleva al usuario para confirmar.
  5. La ejecución de herramientas está sujeta a los permisos de acp_adapter/permissions.py; cada operación anota provenance vía acp_adapter/provenance.py:22.
  6. La salida en streaming y los eventos (acp_adapter/events.py) se devuelven al cliente.

acp_registry/agent.json es la tarjeta de visita del cliente la primera vez que ve Hermes: versión, distribución (uvx), comando de arranque. Este contrato debe estar alineado con el binario real; si no, el cliente instala una versión equivocada y no arranca.

La traducción de cwd es el lugar donde más fácilmente se pisa la calle en ACP: un cliente Windows lanza Hermes en WSL pero el workspace es E:\Projects o una UNC \\wsl.localhost\.... _translate_acp_cwd lo normaliza a POSIX, si no todas las operaciones con Path del agent se desalinean.

La propuesta de edición es un dataclass frozen; la clave está en old_text_proposal_for_write_file lee primero el contenido existente, así el diff que se muestra al usuario ve «antes/después» en lugar de un cambio a ciegas:

python
@dataclass(frozen=True)
class EditProposal:
    tool_name: str
    path: str
    old_text: str | None
    new_text: str
    arguments: dict[str, Any]

El requester de aprobación se vincula con ContextVar, no con una variable global; varias sesiones ACP concurrentes tienen cada una su requester y no se interfieren. .env / id_rsa van por defecto a ask y no a workspace_session, para que la política de «todo el workspace es de confianza» no los abra por error.

Provenance es específico del escenario IDE: en mensajería la sesión es una línea recta, pero en IDE se comprime, se bifurca, se reanuda. build_session_provenance recorre parent_session_id hacia arriba, cuenta las capas con end_reason == 'compression', marca sessionKind y compressionDepth, y pone el session id interno de Hermes junto al session id ACP externo en _meta.hermes.sessionProvenance.

Límites y fallos

  • Versión de handshake no coincide: agent.json fija hermes-agent[acp]==0.19.0. Si Hermes sube a 0.20 pero el cliente cachea el manifiesto viejo, el server arrancado y el schema del cliente se desincronizan y el InitializeResponse carece de campos — el handshake revienta.
  • Traducción cwd en WSL que se cuela: si translate_cwd_for_wsl_backend no cubre una nueva forma de ruta Windows, el agent recibe un cwd desalineado y todas las operaciones con Path se desplazan sin error inmediato; solo revienta en el primer write_file con un «directorio no encontrado».
  • Deadlock del requester de aprobación: la aprobación va por ContextVar + callback de usuario; si el event loop del cliente se cuelga y no manda el ACK, la espera tras build_edit_proposal se queda colgada. Que el cancel del protocolo ACP llegue a ese punto depende de que la ruta de interrupción de events.py lo cubra.
  • Cadena de provenance rota: si al bifurcar por compresión (compression) se escribe mal parent_session_id, build_session_provenance llega al punto de corte y devuelve root; el cliente enseña la continuación como si fuera una sesión nueva y el historial parece «perdido».

Resumen

ACP incrusta a Hermes en el flujo de trabajo del editor: gestión de sesiones, lectura/escritura de recursos, aprobación de ediciones, aislamiento de permisos y trazabilidad de origen. El núcleo es server.py (adaptación de protocolo) + session.py (sesión) + edit_approval.py (ediciones con revisión humana). Complementa a la capa de gateway: el gateway conecta plataformas de mensajes; ACP conecta IDEs.

Sitio de aprendizaje comunitario no oficial. Basado en el código fuente de NousResearch/hermes-agent (licencia MIT).