La pasarela alojada es la de código abierto, OpenWAF Egress, ejecutada por OpenWAF Cloud en https://egress.openwaf.dev, con los agentes, los destinos y las claves gestionados por organización en lugar de con un fichero de configuración.
URL de la pasarela
https://egress.openwaf.dev/v1/agent/<nombre del agente>/proxy/<id del destino>/<ruta del proveedor>
Authorization: Bearer OWE_TOKEN_…<ruta del proveedor> y la cadena de consulta se añaden a la URL base del destino: …/proxy/openrouter/chat/completions va a https://openrouter.ai/api/v1/chat/completions. Las base_urls de cada agente dan la URL de cada destino al que puede llamar.
Frente a una pasarela en tu equipo:
- El agente se identifica por su token, y la URL tiene que nombrar al agente de ese token; ni
/v1/proxy/<destino>/…ni la cabeceraX-OpenWAF-Agentse usan. - El token del agente nunca se reenvía al proveedor; en su lugar, la cabecera de autenticación del destino lleva la clave del proveedor.
- Un destino sin clave de proveedor se rechaza en lugar de llamarlo sin clave.
- Además de la comprobación previa, la dirección a la que se conecta de verdad se vuelve a comprobar contra los rangos privados y reservados.
- Los cambios de agentes, destinos y claves llegan a la pasarela en segundos; una clave de proveedor se guarda en caché hasta cinco minutos.
Las comprobaciones, los detectores, los límites del cuerpo y los plazos son los de la pasarela de código abierto: mira el modelo de seguridad y los límites fijos.
Errores de la pasarela
Los errores de la propia pasarela son JSON con un código en error y un message (en inglés); las respuestas del proveedor llegan sin cambios.
| Estado | error | Causa |
|---|---|---|
| 401 | token_required | No hay cabecera Authorization |
| 401 | invalid_token | Token desconocido o rotado, o el agente está desactivado o borrado |
| 401 | unauthorized_agent | La URL no nombra al agente del token |
| 403 | egress_blocked | El destino no está entre los permitidos del agente (otro agente de la organización sí puede llamarlo) |
| 403 | ssrf_blocked | El destino resuelve a una dirección privada o reservada |
| 403 | injection_detected | Un detector de inyección de prompt ha saltado con el cuerpo (Bloquear la inyección de prompts activado) |
| 403 | data_leak_blocked | Un patrón de fuga de datos ha saltado con el cuerpo (Bloquear fugas de datos activado) |
| 404 | unknown_target | Ningún agente de la organización puede llamar a ese id de destino, o no existe |
| 413 | body_too_large | Más de 8 MiB, o más de 1 MiB de texto que inspeccionar |
| 502 | credential_resolution_failed | El destino no tiene clave de proveedor, o no se pudo leer |
| 502 | upstream_error | No se pudo llegar al proveedor |
| 503 | policy_unavailable | La pasarela no tiene una política vigente para la petición; reinténtalo más tarde |
Las respuestas 403 y 413 aparecen en peticiones bloqueadas. La página de solución de problemas explica cada código con detalle.
API de gestión
Todas las rutas cuelgan de https://dash.openwaf.dev/v1/orgs/{org}, con un token de API (Authorization: Bearer owf_…) o la sesión del panel. Leer necesita cualquier rol de toda la organización; escribir, admin de toda la organización. Los miembros y tokens limitados a un cliente o a una zona reciben 403. Las escrituras admiten un X-Change-Reason opcional; no son configuración versionada y rechazan dry_run. Los SDK de TypeScript y Python incluyen todas las rutas salvo el flujo.
| Ruta | Qué hace |
|---|---|
GET /egress | {enabled, gateway_url, credentials_available}: si Egress IA está activado en la organización; se puede leer aunque no lo esté |
GET /egress/targets | El catálogo y después los destinos propios, cada uno con los metadatos de su clave (credential: huella, updated_at, updated_by, o null) |
POST /egress/targets | Añade un destino propio: id, name, base_url, auth_header, auth_prefix |
DELETE /egress/targets/{target} | Borra un destino propio y su clave |
PUT /egress/targets/{target}/credential | Pone o reemplaza la clave: {"secret": "…"}; responde el destino con la huella de la clave |
DELETE /egress/targets/{target}/credential | Quita la clave |
GET /egress/agents, GET /egress/agents/{id} | Agentes, con base_urls por destino permitido y token_prefix |
POST /egress/agents | Crea un agente: name, description, allowed_targets, enforce_injection, block_dlp, disabled; responde {agent, token} |
PATCH /egress/agents/{id} | Cambia description, allowed_targets (se sustituye entera), enforce_injection, block_dlp o disabled |
POST /egress/agents/{id}/rotate-token | Token nuevo; responde {agent, token} |
DELETE /egress/agents/{id} | Borra un agente |
GET /egress/events | Peticiones bloqueadas, las más recientes primero, con los filtros de los eventos de seguridad |
GET /egress/events/stream | Peticiones bloqueadas como Server-Sent Events |
Leer y borrar agentes, destinos y claves funciona aunque Egress IA esté desactivado en la organización; las demás escrituras, y los eventos, responden 403 feature_disabled. Las respuestas que llevan un token o ponen una clave van con Cache-Control: no-store.
Límites y formatos
| Elemento | Regla |
|---|---|
| Nombre del agente | ^[a-z0-9][a-z0-9-]{0,62}$, único en la organización, no se puede cambiar |
| Descripción | Hasta 500 caracteres |
| Destinos permitidos | De 1 a 32 ids de destino por agente |
| Token | OWE_TOKEN_ y 32 bytes aleatorios en base64url, se enseña una vez; solo se guardan su SHA-256 y su prefijo (OWE_TOKEN_ y 6 caracteres) |
| Id de destino propio | ^[a-z][a-z0-9-]{1,31}$, que no sea un id del catálogo |
| Nombre de destino propio | Hasta 100 caracteres |
| URL de destino propio | https://, puerto 443, nombre DNS público, sin IP, credenciales, query ni fragmento |
| Cabecera y prefijo | Un nombre de cabecera de hasta 64 caracteres; un prefijo de hasta 32 caracteres imprimibles |
| Clave de proveedor | De 1 a 8192 caracteres, sin espacios ni caracteres de control |
Errores de la API
| Estado | code | Cuándo |
|---|---|---|
| 403 | feature_disabled | Egress IA no está activado en la organización |
| 403 | forbidden | El rol no basta, o el miembro o el token está limitado a un cliente o a una zona |
| 404 | not_found | No hay ese agente o destino en la organización |
| 409 | conflict | Ya existe un agente o un destino propio con ese nombre o id |
| 409 | target_in_use | Se intenta borrar un destino propio que algún agente aún permite |
| 422 | invalid | Un campo incumple las reglas de arriba (field lo nombra), o se intenta borrar un destino del catálogo |
| 502 | credential_store | El almacén de credenciales no aceptó el cambio; vuelve a intentarlo |
| 503 | unavailable | Ahora mismo no se pueden guardar claves de proveedor (credentials_available es false) |
Catálogo
| Id | Proveedor | URL base | Cabecera de la clave |
|---|---|---|---|
openrouter | OpenRouter | https://openrouter.ai/api/v1 | Authorization: Bearer |
openai | OpenAI | https://api.openai.com/v1 | Authorization: Bearer |
anthropic | Anthropic | https://api.anthropic.com/v1 | x-api-key |
huggingface | Hugging Face | https://router.huggingface.co/v1 | Authorization: Bearer |
groq | Groq | https://api.groq.com/openai/v1 | Authorization: Bearer |
mistral | Mistral AI | https://api.mistral.ai/v1 | Authorization: Bearer |
gemini | Google Gemini (compatible con OpenAI) | https://generativelanguage.googleapis.com/v1beta/openai | Authorization: Bearer |
deepseek | DeepSeek | https://api.deepseek.com/v1 | Authorization: Bearer |
together | Together AI | https://api.together.xyz/v1 | Authorization: Bearer |
fireworks | Fireworks AI | https://api.fireworks.ai/inference/v1 | Authorization: Bearer |
cohere | Cohere | https://api.cohere.com/v2 | Authorization: Bearer |
perplexity | Perplexity | https://api.perplexity.ai | Authorization: Bearer |
xai | xAI | https://api.x.ai/v1 | Authorization: Bearer |
Herramientas MCP
egress_status y egress_events leen; egress_create_agent, egress_update_agent, egress_rotate_token, egress_delete_agent, egress_add_target, egress_remove_target y egress_remove_credential escriben, con confirm=false para comprobar primero y sin expected_version. No hay herramienta para poner una clave de proveedor. Mira las herramientas MCP.