Arquitectura recomendada
Usuario / Webhook / n8n
│
▼
HTTPS público
Cloudflare / App / Middleware propio
│ agrega auth, rate-limit, logs
▼
Red privada / Docker network / localhost
Hermes API Server
│
▼
Agente + tools + sesiones persistentes
Hermes queda como motor interno. La capa pública controla autenticación, validación, límites de uso y formato de respuesta.
Qué habilita
- Chat estilo OpenAI en
/v1/chat/completions. - Responses API en
/v1/responsespara flujos stateful. - Sesiones nativas en
/api/sessions. - Runs largos en
/v1/runscon eventos SSE. - Tools ejecutadas en el servidor, no en el cliente.
- Monitoreo por
/health,/v1/capabilitiesy/v1/toolsets.
Configuración base del gateway
Usa placeholders genéricos. Cada cliente debe tener su propio puerto, token, perfil y ruta de persistencia.
config.yaml
platforms:
api_server:
enabled: true
host: "127.0.0.1" # o 0.0.0.0 SOLO dentro de Docker privado
port: 8642
platform_toolsets:
api_server:
- clarify
- crm-tools
- knowledge-search
tools:
api_server:
disabled:
- terminal
- process
- execute_code
- write_file
- patch
- cronjob
- delegate_task
- web_search
- browser_navigate
.env
API_SERVER_KEY="generar-con-openssl-rand-hex-32"
API_SERVER_HOST="127.0.0.1"
API_SERVER_PORT="8642"
API_SERVER_CORS_ORIGINS="https://app.cliente.com"
API_SERVER_MODEL_NAME="agente-ventas"
# Provider LLM
NAN_API_KEY="..."
HERMES_MODEL="qwen3.6"
# Tools internas
CRM_TOOL_BASE_URL="http://app-interna:3000"
AGENT_TOOLS_SECRET="otro-secreto-fuerte"
Si corres en Docker, el bind 0.0.0.0 es aceptable solo si el puerto no se publica al host y la comunicación ocurre por red interna.
Sesiones persistentes
La continuidad puede manejarse de dos formas complementarias:
X-Hermes-Session-Id: conserva el hilo técnico de conversación.X-Hermes-Session-Key: identificador estable por usuario, canal o proceso./api/sessions: crear, listar, leer, actualizar, bifurcar y borrar sesiones.
curl -X POST http://localhost:8642/v1/chat/completions \
-H "Authorization: Bearer $API_SERVER_KEY" \
-H "Content-Type: application/json" \
-H "X-Hermes-Session-Id: lead-123" \
-H "X-Hermes-Session-Key: cliente:whatsapp:573001112233" \
-d '{
"model": "agente-ventas",
"messages": [{"role":"user","content":"Quiero cotizar"}]
}'
Persistencia recomendada
En producción, monta el directorio de perfiles en un volumen persistente:
/data/hermes/profiles
├── ventas/state.db
├── ventas/response_store.db
├── ventas/sessions/
├── soporte/state.db
└── soporte/sessions/
Checklist mínimo: crear sesión, enviar mensaje, leer mensajes, reiniciar contenedor y volver a leer la sesión. Si sobrevive, está listo para clientes.
Patrones de integración reutilizables
Landing page
El widget web llama a /api/chat en tu backend. El backend agrega el Bearer token y reenvía a Hermes.
CRM / Inbox
El CRM genera session keys por contacto y guarda resumen, etapa, tags, intención y próximos pasos.
n8n / Webhooks
El workflow llama al middleware, no al API Server directo. Ideal para clasificación, enriquecimiento y tareas internas.
Middleware mínimo en Node/Next.js
export async function POST(request) {
const { message, userId } = await request.json();
const response = await fetch(`${process.env.HERMES_URL}/v1/chat/completions`, {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.HERMES_API_KEY}`,
"Content-Type": "application/json",
"X-Hermes-Session-Key": `web:${userId}`,
},
body: JSON.stringify({
model: process.env.HERMES_MODEL,
messages: [{ role: "user", content: message }],
stream: false,
}),
});
if (!response.ok) return Response.json({ error: "agent_unavailable" }, { status: 502 });
const data = await response.json();
return Response.json({ answer: data.choices?.[0]?.message?.content ?? "" });
}
Reglas no negociables
- No poner
API_SERVER_KEYen frontend, HTML, JavaScript público ni n8n compartido. - No publicar el puerto del gateway directo a Internet.
- No activar tools peligrosas si el agente atiende usuarios externos.
- No reutilizar la misma API key entre clientes.
- No guardar secretos en repositorios ni documentación comercial.
Checklist de hardening
- Clave fuerte con
openssl rand -hex 32. - Proxy HTTPS con rate limiting.
- CORS restringido al dominio del cliente.
- Logs saneados sin tokens ni payloads sensibles.
- Healthcheck interno y alerta si cae el gateway.
- Volumen persistente para
state.dby sesiones. - Backups del directorio de perfiles.
Validación antes de entregar
| Prueba | Comando / criterio | Resultado esperado |
|---|---|---|
| Health simple | GET /health | 200 OK |
| Auth obligatoria | GET /v1/models sin token | 401 |
| Modelo | GET /v1/models con token | 200 + modelo esperado |
| Capabilities | GET /v1/capabilities | Lista endpoints y features activos |
| Tools | GET /v1/toolsets | Solo toolsets permitidos activos |
| Chat | POST /v1/chat/completions | Respuesta útil, streaming opcional |
| Sesiones | Crear → chatear → leer mensajes → reiniciar → leer | Persistencia confirmada |
| Exposición | ss -lntp / firewall / Docker ports | Puerto no abierto públicamente |
Referencia completa del API Server
¿Qué es el API Server? Es el adaptador HTTP de Hermes Agent. Mantiene compatibilidad OpenAI-compatible, sesiones nativas, ejecución de herramientas en servidor y runs estructurados para procesos largos.
Esta sección conserva los puntos operativos importantes de la guía base, adaptados a un documento genérico para clientes y equipos técnicos.
Reglas duras del servidor
- El gateway se niega a arrancar si
API_SERVER_KEYno está configurada. - Si el bind es accesible por red, rechaza claves placeholder o débiles.
- Límite de body: 10 MB.
- Los headers de sesión deben tener longitud acotada para evitar abuso.
- Los logs no deben imprimir tokens, claves, teléfonos ni payloads sensibles.
Endpoints disponibles
| Grupo | Endpoint | Uso |
|---|---|---|
| Health | GET /health | Health check simple del gateway. |
| Health | GET /health/detailed | Estado enriquecido; en algunas versiones requiere Bearer auth. |
| Metadata | GET /v1/models | Modelo o perfil disponible para ese gateway. |
| Metadata | GET /v1/capabilities | Features, endpoints, auth y runtime activos. |
| Metadata | GET /v1/skills | Skills cargadas por el agente. |
| Metadata | GET /v1/toolsets | Toolsets disponibles y cuáles están habilitados. |
| Chat | POST /v1/chat/completions | Chat compatible con OpenAI, con o sin streaming. |
| Responses | POST /v1/responses | Responses API stateful para flujos más estructurados. |
| Responses | GET /v1/responses/{id} | Recuperar respuesta almacenada. |
| Responses | DELETE /v1/responses/{id} | Borrar respuesta almacenada. |
| Sesiones | GET /api/sessions | Listar sesiones persistidas. |
| Sesiones | POST /api/sessions | Crear sesión vacía. |
| Sesiones | GET /api/sessions/{id} | Leer metadata de una sesión. |
| Sesiones | PATCH /api/sessions/{id} | Actualizar título o cierre de una sesión. |
| Sesiones | DELETE /api/sessions/{id} | Borrar una sesión. |
| Sesiones | GET /api/sessions/{id}/messages | Leer historial de mensajes. |
| Sesiones | POST /api/sessions/{id}/fork | Bifurcar una sesión. |
| Sesiones | POST /api/sessions/{id}/chat | Chatear dentro de sesión existente. |
| Sesiones | POST /api/sessions/{id}/chat/stream | Chatear con streaming dentro de sesión. |
| Runs | POST /v1/runs | Crear run largo; devuelve run_id. |
| Runs | GET /v1/runs/{id} | Consultar estado del run. |
| Runs | GET /v1/runs/{id}/events | Eventos SSE de progreso. |
| Runs | POST /v1/runs/{id}/approval | Resolver aprobación pendiente. |
| Runs | POST /v1/runs/{id}/stop | Detener run en curso. |
Autenticación y headers especiales
Todas las rutas operativas deben usar Authorization: Bearer <API_SERVER_KEY>. El servidor compara el token con una comparación segura tipo hmac.compare_digest(); un fallo debe devolver un 401 con error tipo Invalid API key.
| Header | Uso |
|---|---|
Authorization | Bearer token obligatorio para rutas protegidas. |
X-Hermes-Session-Id | Continuar una sesión técnica específica. |
X-Hermes-Session-Key | Identificador estable por usuario, canal, formulario o proceso. |
Idempotency-Key | Evitar repetir respuestas no-streaming si el cliente reintenta. |
Origin | Validación CORS cuando aplique. |
Ejemplo con Python requests
import requests
BASE = "http://localhost:8642"
API_KEY = "usar-variable-de-entorno"
response = requests.post(
f"{BASE}/v1/chat/completions",
headers={
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json",
"X-Hermes-Session-Key": "lead:web:123",
},
json={
"model": "agente-ventas",
"messages": [
{"role": "user", "content": "Resume este lead y clasifica urgencia."}
],
},
timeout=60,
)
print(response.json()["choices"][0]["message"]["content"])
Ejemplo con SDK oficial de OpenAI
from openai import OpenAI
client = OpenAI(
base_url="http://localhost:8642/v1",
api_key="usar-variable-de-entorno",
default_headers={
"X-Hermes-Session-Key": "cliente:crm:123"
},
)
response = client.chat.completions.create(
model="agente-ventas",
messages=[
{"role": "system", "content": "Eres un asistente comercial claro y breve."},
{"role": "user", "content": "¿Qué información falta para cotizar?"},
],
)
print(response.choices[0].message.content)
Casos de uso reusable
Chatbot embebido
Un widget en una landing llama a un proxy propio que reenvía a Hermes con sesión por visitante.
Clasificación automática de leads
Un formulario dispara un análisis de intención, urgencia, presupuesto y próximo paso.
Asistente de contenido
Genera titulares, estructura de posts, CTAs o respuestas para canales comerciales.
GitHub / CI
Un webhook puede iniciar un run para revisar cambios, resumir diffs o proponer checklist.
Panel de salud
Un monitor consulta health y capabilities para alertar si el agente no está disponible.
Operación interna
n8n o un backend dispara tareas controladas sin exponer herramientas peligrosas al usuario final.
Systemd y operación
En VPS tradicional, evita procesos sueltos tipo nohup. Usa unidades systemd o contenedores supervisados por Docker/Coolify.
systemctl --user start hermes-gateway-default.service
systemctl --user restart hermes-gateway-default.service
systemctl --user stop hermes-gateway-default.service
Si el gateway habilita jobs o cron internos, audita rutas como /api/jobs y evita que cualquier cliente con API key pueda crear tareas no deseadas.
Diagnóstico rápido
| Síntoma | Causa probable | Solución |
|---|---|---|
Connection refused | Gateway detenido o puerto incorrecto. | Reiniciar servicio y validar puerto/bind. |
Invalid API key | Token mal copiado o env no recargado. | Validar API_SERVER_KEY y redeploy/restart. |
| No respeta sesión | Falta API key o header de sesión inconsistente. | Enviar X-Hermes-Session-Id y/o X-Hermes-Session-Key. |
CORS blocked | Origen no permitido o llamada directa desde navegador. | Usar proxy backend y restringir CORS. |
| Respuesta vacía | Mensaje vacío o solo system prompt. | Enviar al menos un mensaje user con contenido. |
| Tool call no ejecuta | Toolset no habilitado para api_server. | Revisar platform_toolsets.api_server. |
Handoff para clientes
Cuando se entrega una implementación, documenta solo lo operativo y no expongas detalles sensibles.
- URL pública del middleware, no del gateway privado.
- Casos de uso habilitados: chat, lead scoring, soporte, contenido, etc.
- Qué datos guarda la sesión y por cuánto tiempo.
- Cómo apagar/encender automatizaciones.
- Qué evento escala a humano.
- Plan de monitoreo y soporte.
Plantilla de decisión rápida
Usar API Server si necesitas integrar un agente con apps, webhooks o workflows manteniendo el agente en tu infraestructura.
Usar proxy siempre que haya un navegador, un cliente externo o una integración de terceros.
No usar directo si no puedes proteger secretos, rate limits, logs y persistencia.