Volver a la Biblioteca
A2A

Desplegando A2A en Hermes Agent: una pila de referencia con Docker Gateway

Última actualización: 23 de julio de 2026

Ejecutar A2A en producción significa tender un puente entre dos protocolos que nunca fueron diseñados para comunicarse entre sí — y hacerlo detrás de un gateway que gestiona autenticación, aislamiento de inquilinos y streaming sin perder tokens. Este stack de referencia resuelve los tres problemas que bloquean los despliegues A2A: traducción de protocolo (JSON-RPC 2.0 a chat completions compatibles con OpenAI), reconciliación de streaming (SSE de artefactos A2A a SSE de eventos de ejecución de Hermes) y seguridad multi-inquilino (Row-Level Security de PostgreSQL en cada consulta). Si necesitas que agentes en diferentes frameworks deleguen trabajo entre sí, el patrón aquí es la ruta de despliegue.

Conclusiones clave

  • 3 capas, 1 pila de Docker Compose — SilvaEngine Gateway gestiona el transporte y la autenticación, A2A Daemon Engine gestiona la lógica del protocolo y HermesAgentHandler actúa de puente hacia la API compatible con OpenAI de Hermes Agent. El repositorio docker-a2a-hermes-agent-gateway empaqueta los tres.
  • 5 superficies de protocolo en un solo puerto — JSON-RPC 2.0, GraphQL, flujo SSE, push SSE y descubrimiento de Agent Card, todo detrás de una única pasarela en el puerto 8765 con autenticación JWT o AWS Cognito.
  • Row-Level Security de PostgreSQL aplica el aislamiento entre tenants — la clave compuesta partition_key = "{endpoint_id}#{Part-Id}" se aplica a nivel de base de datos mediante políticas RLS en las cuatro tablas A2A, no solo en el código de la aplicación.
  • La restricción de mensaje único del A2A SDK v2 define la arquitectura de streaming — el puente emite fragmentos de tokens a SSE en tiempo real y un único Message acumulado al EventQueue del SDK tras completar el flujo, evitando InvalidAgentResponseError.
  • 15 comprobaciones de pruebas E2E en 5 scripts — desde pruebas de humo sin streaming hasta pipelines completos de streaming SSE con verificación de respaldo HTTP, todos ejecutables con pip install requests.

El Agent2Agent Protocol (A2A) define cómo los agentes de IA se descubren, delegan y transmiten tareas entre sí a través de JSON-RPC 2.0. Hermes Agent (de Nous Research) expone un API Server compatible con OpenAI en /v1/chat/completions y una interfaz de streaming SSE basada en runs en /v1/runs y /v1/runs/{id}/events. Los dos no hablan el mismo idioma. A2A envía message/send con partes estructuradas; Hermes recibe payloads de chat completion. A2A transmite artefactos de tarea vía SSE; Hermes transmite deltas de tokens mediante run events.

El repositorio docker-a2a-hermes-agent-gateway salva esa brecha en una sola imagen de contenedor y una pila de docker compose. Ejecuta el SilvaEngine Gateway con solo el módulo a2a_daemon_engine registrado, exponiendo la superficie completa del protocolo A2A y puentando las tareas A2A hacia una instancia del Hermes Agent API Server a través de HTTP + SSE. El estado persiste en un backend PostgreSQL incluido con Row-Level Security para el aislamiento entre tenants.

Este artículo mapea la arquitectura de tres capas, el ciclo de vida de la solicitud desde el cliente A2A hasta Hermes y de vuelta, los patrones de configuración y despliegue, y los aspectos operativos para ejecutar A2A en Hermes Agent en producción. Es un recorrido por un despliegue de referencia — el patrón general (puente A2A mediado por pasarela hacia cualquier framework de agentes) es el tema; la pila Docker es la implementación desarrollada.

La arquitectura de tres capas

La pila separa las responsabilidades en tres capas, cada una propiedad de un componente distinto:

A2A en Hermes Agent — pila de tres capas despliegue de referencia docker-a2a-hermes-agent-gateway 1 Cliente A2A Cualquier agente o aplicación que hable JSON-RPC 2.0 message/send · tasks/get · SSE 2 SilvaEngine Gateway Transporte · autenticación · enrutamiento · ciclo de vida del cliente SSE Auth JWT / Cognito Enrutamiento por Part-Id Registro de clientes SSE Limitación de tasa 3 A2A Daemon Engine Lógica de protocolo · máquina de estados de tarea · despacho de handlers Servicio de Agent Card Ciclo de vida de tarea HermesAgentHandler Streaming de doble vía Hermes Agent API Server Compatible con OpenAI · runs SSE /v1/chat/completions /v1/runs + /events PostgreSQL Persistencia · aislamiento RLS por tenant a2a_agents / tasks messages / settings La pasarela es el único servicio siempre activo — Hermes y PostgreSQL son hermanos controlados por perfil — ideabosque.com/library

La pasarela es el único servicio siempre activo. Tanto Hermes como PostgreSQL son hermanos controlados por perfiles — inclúyelos para una pila autónoma, o desactiva los perfiles y apunta HERMES_API_URL y PG_HOST a instancias externas. Esto es importante para producción: puedes ejecutar la pasarela en tu VPC y apuntarla a un Postgres gestionado (RDS, Cloud SQL) y a una instancia de Hermes ejecutándose en un nodo GPU en otra ubicación.

Capa 1: SilvaEngine Gateway — transporte y autenticación

El SilvaEngine Gateway es una pasarela FastAPI para acceso autenticado e en-proceso a módulos instalados. Expone rutas GraphQL y REST de los módulos a través de un manifiesto de rutas YAML configurable — añadir un módulo nuevo requiere solo cambios en el manifiesto, sin código Python de la pasarela. En esta pila, solo el A2A Daemon Engine está registrado.

La pasarela gestiona:

  • Autenticación — JWT local (HS256) o AWS Cognito (RS256 + JWKS), seleccionado por GATEWAY_AUTH_PROVIDER
  • Enrutamiento — el manifiesto YAML mapea rutas de URL a funciones de despacho de módulos
  • Ciclo de vida del cliente SSE — el sse_manager se resuelve por módulo y gestiona conexiones de cliente de larga duración
  • Limitación de tasa — limitación de tasa por IP en memoria (GATEWAY_RATE_LIMIT solicitudes por GATEWAY_RATE_WINDOW segundos)
  • Despacho por pool de hilos — las funciones síncronas de despacho de módulos se ejecutan en un pool de hilos configurable (GATEWAY_DISPATCH_WORKERS, 32 por defecto en la imagen Docker)

La pasarela construye partition_key = "{endpoint_id}#{Part-Id}" a partir del segmento de la ruta URL y de la cabecera Part-Id de la solicitud. Cada solicitud con ámbito de tenant requiere esa cabecera. El endpoint de la Agent Card en /{ep}/.well-known/agent-card.json es público (sin autenticación) según la especificación A2A, pero aún requiere Part-Id porque la tarjeta se resuelve por partición.

Capa 2: A2A Daemon Engine — lógica de protocolo

El a2a_daemon_engine no es un servicio autónomo. Se carga como un módulo registrado de la pasarela a través de deploy() en main.py, que declara tres puntos de entrada orientados a la pasarela:

Punto de entrada Ruta de la pasarela Método Propósito
a2a_core_graphql POST /{ep}/a2a_core_graphql POST CRUD GraphQL para agentes, tareas, mensajes, ajustes
a2a POST /{ep}/a2a POST Protocolo A2A JSON-RPC (message/send, tasks/get, tasks/cancel, tasks/list)
sse_message POST /{ep}/a2a_sse POST Mensaje A2A JSON-RPC + push a clientes SSE

La pasarela además expone GET /{ep}/a2a_sse para el flujo SSE. El daemon no escucha en su propio puerto ni ejecuta su propio servidor HTTP en producción. Todo el transporte, la autenticación y el ciclo de vida del cliente SSE son gestionados por la pasarela.

El daemon proporciona:

  • A2A SDK v1.0 — JSON-RPC sobre HTTP, construido sobre el patrón oficial del servidor del A2A SDK
  • Agent Card pública en /.well-known/agent-card.json con soporte de ETag y Last-Modified
  • Máquina de estados de tareasubmittedworkinginput-required | completed | failed | canceled
  • Persistencia de doble backend — DynamoDB (PynamoDB) o PostgreSQL (SQLAlchemy + Alembic). La imagen Docker fuerza PostgreSQL.
  • Aislamiento multi-tenant — claves de partición compuestas ({endpoint_id}#{part_id}) con Row-Level Security de PostgreSQL
  • Handlers LLM conectables — selección module_name / class_name por agente en el registro de agentes

Capa 3: HermesAgentHandler — el puente

El handler puente de Hermes (a2a_daemon_engine/handlers/a2a_hermes_handler.py) es el único código específico del framework. Implementa una interfaz ask_model(): aceptar partes de mensaje A2A y contexto, llamar al Hermes Agent API Server, convertir la respuesta de vuelta a partes de mensaje A2A y, para el streaming, reenviar los deltas de tokens al canal SSE.

El handler admite dos modos de ejecución:

Sin streaming se mapea a POST /v1/chat/completions en el Hermes API Server — el endpoint compatible con OpenAI. La solicitud transporta las partes de mensaje A2A convertidas como un payload de chat completion. Hermes procesa la solicitud y devuelve una única respuesta. El handler convierte la respuesta en un Message A2A con ROLE_AGENT y lo emite al EventQueue del SDK. El cliente recibe una única respuesta JSON-RPC con el texto completo del agente.

Con streaming se mapea a POST /v1/runs para crear un run, y luego abre una conexión SSE a GET /v1/runs/{id}/events. Hermes transmite eventos a medida que ocurren: deltas de tokens (message.delta), metadatos de razonamiento (reasoning.available), notificaciones de llamadas/resultado de herramientas, solicitudes de aprobación (approval.required) y eventos de ciclo de vida (run.created, run.completed, run.failed). El handler ejecuta un bucle de drenaje en un hilo en segundo plano. Cada evento message.delta se envía al gestor SSE de la pasarela para su entrega en tiempo real a los clientes conectados. Cuando llega run.completed, el texto acumulado se emite como un único Message A2A al EventQueue del SDK.

El ciclo de vida de la solicitud

Un único message/send con stream=true recorre ocho pasos:

1. Cliente        POST /{ep}/a2a  {jsonrpc, method:"message/send", params}
                  Headers: Authorization: Bearer *** Part-Id: 
2. Pasarela       auth (JWT local / Cognito) → coincidencia de ruta desde routes.yaml
                  → partition_key = "{ep}#{Part-Id}"
3. a2a_daemon     dispatch_a2a → A2ADaemonExecutor
                  → resolve_agent(): metadatos del agente (BD) > dict de ajustes > Config (env)
4. Handler        HermesAgentHandler (A2A_AI_AGENT_MODULE / _CLASS)
5. Hermes         POST {HERMES_API_URL}/v1/runs   (Bearer HERMES_API_KEY)
                  GET  {HERMES_API_URL}/v1/runs/{id}/events   (SSE)
6. Broadcast      fragmentos de tokens → suscriptores en GET /{ep}/a2a_sse
7. Persistencia   tarea + mensajes escritos en PostgreSQL (tablas a2a_*, ámbito RLS)
8. Respuesta      la respuesta acumulada también se devuelve en el resultado JSON-RPC HTTP

El paso 8 es importante: incluso con streaming, la respuesta HTTP transporta la respuesta completa. Un cliente que pierda frames SSE puede recurrir a la respuesta HTTP. El conjunto de pruebas E2E (test_hermes_sse_live.py) verifica explícitamente este respaldo en su paso 06.

Prioridad de resolución del agente

La resolución de configuración sigue una cadena de prioridad: metadatos del agente (BD) → dict de ajustes → valores por defecto de Config (variables de entorno). Las anulaciones por agente prevalecen sobre los valores por defecto globales. Dos agentes pueden apuntar a frameworks distintos — uno a Hermes para tareas de razonamiento intensivo, otro a un handler diferente para tareas de orquestación de flujos — y la superficie del protocolo A2A se ve idéntica para el agente que llama.

Para un agente respaldado por Hermes, los metadatos almacenados en la tabla a2a_agents se ven así:

{
  "module_name": "a2a_daemon_engine.handlers.a2a_hermes_handler",
  "class_name": "HermesAgentHandler",
  "hermes_api_url": "http://127.0.0.1:8642",
  "hermes_api_key": "hermes-local-key",
  "hermes_model": "hermes-agent",
  "hermes_timeout": 300.0
}

Los valores por defecto de las variables de entorno (HERMES_API_URL, HERMES_API_KEY, HERMES_MODEL) permiten que el puente alcance a Hermes sin un registro de agente en la BD — la función resolve_agent() en a2a_ai_agent_utility.py recurre a las variables de entorno cuando no existe un registro de agente. Esto significa que puedes iniciar la pila y enviar un message/send sin registrar ningún agente, y se enrutará a Hermes usando los valores por defecto del entorno.

Mapeo de estado A2A

El puente mapea los eventos SSE de Hermes a estados de tarea A2A. Esta tabla es el corazón del puente — toda integración de framework produce una tabla equivalente:

Evento SSE de Hermes Estado de tarea A2A Acción del puente
run.created (devuelve run_id) WORKING Registrar run_id para soporte de cancelación
message.delta WORKING Acumular token; emitir a SSE por fragmento
reasoning.available WORKING Metadatos de razonamiento — sin emisión de token
tool.call / tool.result WORKING Solo metadatos de ejecución de herramienta
approval.required INPUT_REQUIRED Emitir fragmento de aprobación; almacenar pending_approval
run.completed COMPLETED Establecer evento de stream; acumular texto final
run.failed FAILED Emitir fragmento de error; establecer estado FAILED
POST /v1/runs/{id}/stop CANCELED Cancelación externa vía tasks/cancel
POST /v1/runs/{id}/approval (continúa el run) Resuelto vía operation="approval_response"

El documento HERMES_INTEGRATION.md en el repositorio a2a_daemon_engine registra el formato exacto de los eventos de Hermes, las claves de configuración y los detalles del flujo de extremo a extremo.

Aprobación humana en el bucle a través de fronteras de agentes

Hermes soporta puertas de aprobación humana en el bucle — cuando un agente necesita permiso para ejecutar una acción sensible, se detiene y emite una solicitud de aprobación. El puente traduce esto al estado A2A INPUT_REQUIRED, que señala al agente que llama (o al operador humano) que se necesita entrada. La respuesta regresa a través de POST /v1/runs/{id}/approval, y el run continúa.

Aquí es donde el patrón de puente demuestra su valor. A2A define INPUT_REQUIRED como un estado de tarea de primera clase. Hermes tiene su propio mecanismo de aprobación. El puente mapea uno al otro, y el agente que llama — que puede ser a su vez un cliente A2A ejecutándose en un framework completamente distinto — ve una transición de estado de protocolo estándar, no un detalle específico de Hermes. Una cadena de delegación de agentes puede incluir un paso que requiera aprobación humana (una autorización de compra, una decisión de acceso a datos, una aprobación de presupuesto), y el protocolo A2A transporta esa puerta de forma transparente a través de las fronteras del framework.

La restricción del A2A SDK v2 y la solución de doble vía

El A2A SDK v2 (a2a-sdk==1.0.2) impone dos restricciones en la ruta on_message_send que dieron forma a la implementación del puente:

  1. Solo un Message. Emitir varios objetos Message al EventQueue del SDK lanza InvalidAgentResponseError: Multiple Message objects received.
  2. Sin TaskStatusUpdateEvent. Los eventos de estado lanzan InvalidAgentResponseError: Received TaskStatusUpdateEvent in message mode.

Un puente ingenuo emitiría un Message por cada delta de token — el patrón natural de streaming. El SDK lo rechaza. También rechaza los eventos de estado (WORKING, COMPLETED) en la ruta message/send.

La solución es un canal de salida de doble vía:

  • SSE (gestionado por la pasarela): Los fragmentos de tokens se envían a SSE en tiempo real. Los clientes conectados ven la salida de streaming a medida que ocurre. Los eventos de estado (WORKING, COMPLETED, FAILED) también van solo a SSE.
  • EventQueue del SDK: Tras completar el flujo, se emite un único Message acumulado que contiene el texto completo de la respuesta al EventQueue del SDK. Esto es lo que devuelve la respuesta JSON-RPC message/send.

El cliente obtiene streaming en tiempo real vía SSE y una respuesta JSON-RPC de mensaje único limpia vía el SDK. Ambos canales funcionan; ninguno viola las restricciones del SDK.

Superficies de protocolo en un solo puerto

La pasarela expone cinco superficies de protocolo en un solo puerto (8765 por defecto):

Protocolo Ruta Auth Propósito
GraphQL POST /{ep}/a2a_core_graphql Consultas/mutaciones A2A core (agentes, tareas, mensajes, ajustes)
JSON-RPC 2.0 POST /{ep}/a2a Protocolo A2A: message/send, tasks/get, tasks/cancel, tasks/list
SSE (flujo) GET /{ep}/a2a_sse Flujo de eventos de tarea A2A por partición y de larga duración
SSE (push) POST /{ep}/a2a_sse Mensaje JSON-RPC + push a clientes SSE conectados
Agent Card GET /{ep}/.well-known/agent-card.json Público Documento de descubrimiento A2A (la cabecera Part-Id sigue siendo obligatoria)

La forma de los params de message/send JSON-RPC usada por los harness de prueba:

{
  "message": {
    "role": "ROLE_USER",
    "parts": [{ "text": "Say hello from A2A" }]
  },
  "metadata": {
    "operation": "task_execution",
    "agent_uuid": "a2a-hermes-agent",
    "stream": true,
    "task_data": { "task_id": "my-task-001", "task_type": "hermes_test" },
    "system_prompt": "You are a concise assistant.",
    "conversation_history": []
  }
}

El campo metadata.operation selecciona la ruta de ejecución: task_execution para ejecuciones de agente con soporte de streaming, message_response para chat sin streaming. El agent_uuid apunta a un agente específico en el registro. El indicador stream activa la difusión SSE. El task_data.task_id es un id proporcionado por el llamador usado por tasks/get y tasks/cancel.

SSE es por partición, no por tarea. Cada tarea en {ep}#{Part-Id} se difunde a todos los suscriptores de esa partición. El orden de operaciones importa: conecta el listener SSE antes de enviar el mensaje, o se perderán los primeros fragmentos de tokens.

Persistencia y multi-tenencia

La imagen Docker fuerza db_backend=postgresql — no se admite DynamoDB. El daemon usa nombres de tabla literales y sin prefijo:

Tabla Contiene
a2a_agents Registros de agente + metadatos de handler/modelo por agente
a2a_tasks Ciclo de vida de tarea + estado
a2a_messages Turnos de mensaje por tarea
a2a_settings Dicts de ajustes por partición

Dado que los nombres no llevan prefijo, no compartas PG_DB con otro módulo que use los mismos nombres.

El aislamiento entre tenants usa Row-Level Security de PostgreSQL. La variable de sesión app.tenant_id se establece al partition_key de la solicitud ("{endpoint_id}#{Part-Id}"), y las políticas RLS limitan cada consulta a ese valor. Las tablas y políticas se crean automáticamente al iniciar la pasarela cuando initialize_tables=1. Esto significa que un filtro partition_key olvidado en el código de la aplicación no puede filtrar filas entre tenants — la base de datos aplica la frontera.

La implementación RLS reside en a2a_daemon_engine/utils/rls.py (set_rls_context y create_rls_policies) y en la migración 0005_enable_rls_policies. La función set_rls_context ejecuta un SET app.tenant_id por solicitud sobre la conexión, y create_rls_policies habilita y fuerza RLS con una política tenant_isolation en las cuatro tablas A2A. RLS es inerte en modo DynamoDB.

Despliegue con Docker Compose

La pila tiene un servicio siempre activo y dos hermanos opcionales controlados por perfiles:

Servicio Nombre del contenedor ¿Siempre activo? Perfil Propósito
a2a-gateway a2a-hermes-gateway SilvaEngine Gateway (rutas solo A2A) + puente de Hermes
postgres a2a-postgres Opcional postgres Backend de persistencia PostgreSQL incluido
hermes container-hermes Opcional hermes Hermes Agent incluido (API compatible con OpenAI + panel)

COMPOSE_PROFILES es el único interruptor para ambos hermanos:

Valor Servicios iniciados
vacío solo pasarela (Postgres externo + Hermes externo)
postgres pasarela + Postgres incluido
hermes pasarela + Hermes incluido (Postgres externo)
postgres,hermes pasarela + Postgres y Hermes incluidos (por defecto)

Cuando un hermano está incluido, mantén su referencia de host apuntando al nombre del servicio: PG_HOST=postgres y HERMES_API_URL=http://hermes:<API_SERVER_PORT>. Cuando un hermano es externo, apunta esos a tu propia instancia (p. ej. PG_HOST=host.docker.internal, HERMES_API_URL=http://host.docker.internal:8642).

Inicio rápido

cp .env.example .env

# Rellena: JWT_SECRET_KEY, ADMIN_PASSWORD, API_SERVER_KEY,
# HERMES_API_KEY (= API_SERVER_KEY), HERMES_MODEL_PROVIDER + clave del proveedor, HERMES_MODEL

mkdir -p www/hermes www/projects

DOCKER_BUILDKIT=1 docker compose build
docker compose up -d           # COMPOSE_PROFILES=postgres,hermes es el valor por defecto

docker compose ps              # espera (healthy)
curl -f http://localhost:8765/health

pip install requests
python test_hermes_hello.py    # prueba de humo de extremo a extremo

Tanto silvaengine_gateway como a2a_daemon_engine se instalan vía pip desde git en la imagen (sin montaje de código fuente del host). La imagen es genérica y completamente controlada por variables de entorno — no hay secretos integrados. Los módulos se clonan desde repositorios públicos de GitHub bajo ideabosque vía git+https — no se necesitan credenciales ni clave de despliegue SSH.

La trampa del comentario en línea en .env

El parser env_file de Docker Compose no elimina los comentarios en línea. Una línea como:

HERMES_API_KEY=hermes-local-key   # token para Hermes

establece HERMES_API_KEY a la cadena literal hermes-local-key # token para Hermes (comentario incluido), lo que rompe la autenticación de forma silenciosa. Las reglas: no pongas nada después del valor en ninguna línea KEY=value. Pon las notas en sus propias líneas de comentario # encima de la variable.

Verificación: 15 comprobaciones E2E en 5 scripts

La pila incluye harness de prueba en Python autónomos (única dependencia: requests). Cargan ./.env, resuelven o acuñan un JWT de la pasarela y hablan con la pila en ejecución:

Script Tipo Qué hace
test_hermes_hello.py Humo message/send sin streaming, imprime la respuesta
test_hermes_hello_sse.py Humo Un prompt transmitido vía SSE
test_hermes_gateway_live.py Suite E2E 9 comprobaciones: salud de Hermes, salud de la pasarela, agent card, ping GraphQL, message/send, tasks/get, tasks/list, tasks/cancel, ruta de fallo
test_hermes_sse_live.py Suite E2E 6 comprobaciones: salud x2, conexión SSE, fragmentos de tokens en vivo, estado COMPLETED, respaldo HTTP
test_hermes_chatbot.py Interactivo REPL contra la superficie A2A con streaming SSE en vivo

Todos los scripts no interactivos imprimen PASS/FAIL por paso y terminan con código distinto de cero en caso de fallo, así que funcionan como puertas de CI. El conjunto de pruebas unitarias (test_hermes_handler.py) ejecuta 24 pruebas con HTTP simulado vía httpx.MockTransport — no se necesitan servicios.

Patrones operativos

Cambios de ruta sin reconstrucciones

routes.yaml se monta por bind-mount como solo lectura en el contenedor. Edita el archivo del host y reinicia el proceso de la pasarela — no hace falta reconstrucción:

make restart

Tras un cambio en el upstream

Dado que silvaengine_gateway y a2a_daemon_engine se instalan vía pip desde git al compilar, un cambio en el upstream requiere una reconstrucción con --no-cache para que la capa git vuelva a clonar el @main más reciente:

DOCKER_BUILDKIT=1 docker compose build --no-cache
docker compose up -d --force-recreate

No hay fijación de versión — @main es un objetivo móvil. Fija un tag o commit en requirements-modules.txt si necesitas reproducibilidad.

Escalado más allá de un worker

El estado de tarea en memoria, los contadores de limitación de tasa y el registro de clientes SSE son por proceso. Con GATEWAY_WORKERS > 1, cambia a backends compartidos (GATEWAY_TASK_BACKEND=dynamodb, GATEWAY_RATE_LIMIT_BACKEND=dynamodb, más region_name y credenciales aws_*) y usa sesiones pegajosas para SSE. La configuración por defecto inicia un proceso Uvicorn.

Valores de seguridad por defecto a cambiar

  • JWT_SECRET_KEY=change-me-in-production — sustitúyelo por openssl rand -hex 32
  • ADMIN_PASSWORD=change-me — sustitúyelo por una contraseña real
  • POSTGRES_PASSWORD=silvaengine — sustitúyelo por una contraseña real
  • GATEWAY_CORS_ORIGINS=* permite cualquier origen sin credenciales. Establece una lista explícita si necesitas cookies/credenciales.
  • El Hermes incluido monta el socket de Docker del host (/var/run/docker.sock). Eso equivale a root en el host para cualquier cosa dentro de ese contenedor. Ejecuta el perfil hermes solo en un host que controles, y elimina el montaje si el agente no necesita lanzar contenedores.
  • El panel de Hermes está habilitado por defecto en el puerto 9119 con credenciales básicas de autenticación vacías. Establece HERMES_DASHBOARD_BASIC_AUTH_* o vincula el puerto a localhost antes de exponer el host.
  • RLS es la frontera entre tenants. Un llamador que pueda establecer un Part-Id arbitrario lee los datos de esa partición — trata Part-Id como una entrada relevante para la autorización en cualquier front-end que pongas delante de esto.

Lo que esto habilita

La pila de tres capas te da tres capacidades difíciles de ensamblar desde cero:

1. Conformidad con el protocolo A2A sin reescribir Hermes. Cualquier cliente A2A puede descubrir el agente respaldado por Hermes vía su Agent Card, enviar tareas vía message/send, transmitir respuestas vía SSE y seguir el ciclo de vida de la tarea a través de estados A2A estándar. El cliente no sabe que el agente remoto ejecuta Hermes — ve un endpoint A2A con una interfaz JSON-RPC.

2. Servicio de agente multi-tenant desde una sola pasarela. La cabecera Part-Id combinada con RLS de PostgreSQL significa que una instancia de pasarela sirve a múltiples tenants con aislamiento estricto a nivel de base de datos. Cada tenant obtiene su propio registro de agentes, historial de tareas y almacén de mensajes — todo en las mismas cuatro tablas, delimitadas por partition_key.

3. Aprobación humana en el bucle a través de fronteras de agentes. Las puertas de aprobación de Hermes se mapean a estados A2A INPUT_REQUIRED. Una cadena de delegación de agentes puede incluir un paso que requiera aprobación humana, y el protocolo A2A transporta esa transición de estado de vuelta al agente u operador de origen — independientemente del framework en el que se ejecute cada agente de la cadena.

La implementación de referencia también soporta despacho en AWS Lambda para A2A sin servidor, transporte gRPC experimental con streaming bidireccional y persistencia de doble backend (DynamoDB o PostgreSQL). El repositorio a2a_daemon_engine y su guía de integración con Hermes contienen la implementación completa, la referencia de configuración y los detalles del mapeo de estados. El repositorio SilvaEngine Gateway documenta el sistema de manifiesto de rutas, los proveedores de autenticación y la auto-inicialización de módulos.

Lecturas relacionadas


Un distribuidor de mercado medio necesita agentes de cotización que hablen con agentes de catálogo que hablen con agentes de inventario — cada uno respaldado por un framework distinto, cada uno propiedad de un equipo distinto. A2A da a esos agentes un protocolo compartido. Una capa de puente permite que Hermes Agent participe sin reescribir sus interioridades. El repositorio docker-a2a-hermes-agent-gateway empaqueta ese puente en una sola imagen de contenedor con persistencia PostgreSQL, multi-tenencia RLS y 15 comprobaciones de prueba E2E.

Solicita un build acotado

Una semana de descubrimiento. Obtienes un inventario de sistemas, un mapa de flujos de trabajo y un alcance fijo — tanto si construyes con nosotros como si no.

¿Quieres esto construido para tus sistemas?

Cada documento aquí viene de trabajo real de producción. Si tienes un sistema objetivo y un flujo en mente, podemos definir un proyecto en una semana.

Solicitar un proyecto

Descubrimiento de una semana. Obtienes un inventario de sistemas, mapa de flujos y alcance fijo — decidas o no construir con nosotros.