Publicar una versión nueva de la IA solo si pasa el examen
Un freno que revisa la última corrida de la suite golden antes de cada publish.
Publicar un agente copia el borrador a lo que corre en producción. Configurar el agente que conversa explica ese mecanismo. Esta receta resuelve otra tarea: automatizar un publish sin que se te escape una regresión. El freno que la plataforma ya trae hace ese trabajo. Lee la última corrida de la suite golden de Agent Evals. Si está roja o vencida, rechaza el publish antes de tocar nada.
Trampa
force: true publica igual, y queda firmado en la auditoría
El freno se puede saltar. Con force: true el publish sigue adelante aunque la suite esté en rojo, y esa decisión queda en el registro de auditoría con quién la tomó. No lo mandes por defecto en un pipeline automatizado.
Antes de empezar
- Un agente con al menos una suite golden habilitada. Sin una, el freno no tiene nada que revisar y el publish nunca lo bloquea.
ai_agents:readpara consultar el freno;ai_agents:writepara publicar.- Armar la suite y correrla es trabajo de la aplicación. Configurar el agente que conversa documenta el resto del ciclo de vida del agente.
1. Consultar el freno antes de publicar
curl https://api.vitrinadev.com/api/v1/ai-agents/c7a013c7-87e8-4892-9703-ec24c476600b/publish-gate \
-H "Authorization: Bearer $VITRINA_KEY"Una suite recién creada, sin ninguna corrida todavía, responde así:
{
"data": {
"status": "stale",
"suite": { "id": "6bb940c3-f6d0-4138-9785-1fe5c30902ff", "name": "Golden capture", "kind": "golden" },
"suite_run": null,
"failing": [],
"reasons": ["no_completed_run"]
}
}status toma cinco valores. none significa que no hay suite golden habilitada. Ahí el freno nunca bloquea. pending es una corrida en curso, y solo advierte. stale, como en esta captura, es un veredicto que no dice nada sobre el borrador actual. O no hay ninguna corrida completa todavía, o la que existe es más vieja que el último cambio guardado. blocked y ready se ven en el paso siguiente, después de correr la suite.
2. Publicar contra un freno en rojo
Publicar con la suite en stale o en blocked no publica. Responde 409, con el mismo objeto del freno adentro: no hace falta una segunda llamada para saber por qué.
curl -X POST https://api.vitrinadev.com/api/v1/ai-agents/c7a013c7-87e8-4892-9703-ec24c476600b/publish \
-H "Authorization: Bearer $VITRINA_KEY" \
-H "Content-Type: application/json" \
-d '{}'{
"error": "Publish is blocked by this agent's golden eval suite",
"code": "evals_stale",
"gate": {
"status": "stale",
"suite": { "id": "6bb940c3-f6d0-4138-9785-1fe5c30902ff", "name": "Golden capture", "kind": "golden" },
"reasons": ["no_completed_run"]
}
}Con una corrida completa y roja, la forma cambia: code pasa a evals_blocked, y gate.failing trae cada escenario que reprobó, con su propio run_id para revisarlo.
{
"error": "Publish is blocked by this agent's golden eval suite",
"code": "evals_blocked",
"gate": {
"status": "blocked",
"suite_run": { "summary": { "total": 1, "passed": 0, "failed": 1, "pass_rate": 0, "hard_fails": 1 } },
"failing": [
{
"display_id": "SC-6",
"name": "No inventa horarios de atención",
"run_id": "8e91c363-4001-4ebe-b6d4-b4f3756fb455",
"status": "failed",
"hard_fails": ["Inventó un horario de atención que no existe en la base de conocimiento"]
}
],
"reasons": ["hard_fails", "pass_rate_below_min"]
}
}evals_stale y evals_blocked son dos preguntas distintas. stale dice «esto no prueba nada sobre lo que estás por publicar»; blocked dice «esto prueba que lo que estás por publicar falla». Un pipeline automatizado debería tratarlas distinto: ante stale, correr la suite de nuevo antes de nada; ante blocked, mirar failing antes de decidir.
3. Publicar de todos modos, con nombre y apellido
curl -X POST https://api.vitrinadev.com/api/v1/ai-agents/c7a013c7-87e8-4892-9703-ec24c476600b/publish \
-H "Authorization: Bearer $VITRINA_KEY" \
-H "Content-Type: application/json" \
-d '{ "force": true }'{
"data": {
"id": "c7a013c7-87e8-4892-9703-ec24c476600b",
"name": "Asistente de ventas",
"system_prompt": "Eres el asistente de ventas de una tienda. Responde con calidez y ofrece agendar una visita cuando corresponda.",
"published_version_id": null,
"updated_at": "2026-09-23T11:44:49.034Z"
}
}200, el borrador queda en vivo, y la auditoría registra quién forzó el publish y sobre qué motivos del freno lo hizo. skip_eval: true es un campo distinto: no toca el freno, solo evita que el publish dispare una corrida de verificación después.
4. Volver atrás sin pasar por el freno otra vez
GET /ai-agents/{id}/versions guarda una fila por cada publish, incluidos los forzados:
curl https://api.vitrinadev.com/api/v1/ai-agents/c7a013c7-87e8-4892-9703-ec24c476600b/versions \
-H "Authorization: Bearer $VITRINA_KEY"{
"data": [
{ "id": "9a5af431-1faf-4f7e-b024-d112d86bed66", "version_number": 2, "label": "Published draft" },
{ "id": "0c15bf74-5ab1-455a-85c3-63a743de0043", "version_number": 1, "label": "Initial config (pre-publish)" }
]
}curl -X POST https://api.vitrinadev.com/api/v1/ai-agents/c7a013c7-87e8-4892-9703-ec24c476600b/versions/1/rollback \
-H "Authorization: Bearer $VITRINA_KEY"{ "data": { "system_prompt": "", "restore": { "recovered": [], "warnings": [] } } }rollback responde 200 aquí aunque la suite golden sigue en blocked sobre el borrador actual. El freno se evalúa al armar un borrador nuevo, no al devolver uno que ya estuvo en vivo.
Cuando falla
Un 403 en publish-gate significa que la key no tiene ai_agents:read. Un 404 en cualquiera de estas rutas no es un problema de permisos: el id del agente no existe en este workspace. La API responde igual para «no existe» y para «no es tuyo».
En la aplicación: la suite golden se arma y se corre desde Configuración → Agentes de IA → Evals, y el mismo semáforo se ve antes de apretar publicar. Guía completa en Manual de plataforma → Publicar solo si pasa el examen.

El examen prueba lo que el agente sabe responder. Enseñar tu negocio a la IA sin escribirlo dos veces resuelve de dónde sale ese conocimiento.