03 Publicar y detectar
Publica el agente seleccionado con un punto ciego conocido de política y usa después la evaluación operativa y feedback real para detectarlo.
Punto de partida
El Módulo 02 está completado. Registra el config_id ganador seleccionado en la ejecución real de la Arena y expórtalo desde la raíz del laboratorio (ClickHouse_Demos/workshops/agent_arena):
source .env
export WINNER_CONFIG_ID="${WINNER_CONFIG_ID:-qwen3.7-flash__P2_fewshot}"La ejecución verificada del taller eligió qwen3.7-flash__P2_fewshot; conserva el ganador de tu grupo si es distinto. Usarás el mismo modelo y prompt que mediste, no un agente especial diseñado para fallar.
Si tu ganador es Qwen, debes desactivar OpenRouter Settings → Privacy → Data Policies → Zero Data Retention → Non-frontier. La ruta disponible de Alibaba se rechaza cuando se impone ZDR para non-frontier. Revisa tus requisitos de privacidad antes de cambiar este ajuste para datos reales.
Por qué un evaluator que aprueba puede omitir el valor para el usuario
Un evaluator online solo mide la dimensión para la que fue diseñado. Aquí, sql-execution-success responde una pregunta operativa importante: ¿el agente produjo un SQL que ClickHouse pudo ejecutar? No sabe si el SQL sigue la definición de negocio actual de cliente activo.
Esto crea una carencia realista de monitorización:
| Señal | Pregunta que responde | Valor esperado en este incidente |
|---|---|---|
sql-execution-success | ¿El SQL generado se ejecutó correctamente? | true |
user-thumbs | ¿Esta respuesta satisfizo la necesidad del usuario? | false |
La evaluación operativa detecta SQL roto, timeouts y errores de ejecución. La evaluación semántica o de usuario pregunta si una respuesta ejecutable es útil y concuerda con el significado de negocio. Ninguna sustituye a la otra. Un pulgar hacia abajo es una señal de priorización, no verdad de referencia; una persona lo investigará en el Módulo 04.
Objetivo
Crear una traza real chat_turn en la que el evaluator operativo aprueba, pero el usuario valora negativamente la respuesta. Registra la traza y los dos recuentos discrepantes para la investigación humana.
Paso 1 — Demostrar que el incidente preparado es reproducible
Ejecuta el preflight desde la raíz del laboratorio antes de iniciar el servidor de demostración:
source .env
export WINNER_CONFIG_ID="${WINNER_CONFIG_ID:-qwen3.7-flash__P2_fewshot}"
.venv/bin/python -m schema.gen_schema_context
.venv/bin/python -m scripts.check_online_eval_scenario \
--config-id "$WINNER_CONFIG_ID"El comando ejecuta ambas definiciones y plantea tres paráfrasis a la configuración seleccionada. Debe mostrar valores distintos para stale_count y current_count, tres líneas classification_N=policy-v1 y lo siguiente:
Si una paráfrasis devuelve ok/unknown, el preflight reintenta una sola vez esa misma paráfrasis y configuración. No reintenta policy-v2 ni fallos del proveedor, modelo o agente; un segundo ok/unknown sigue bloqueando el proceso.
OK: seeded online-evaluation incident is reproducibleSi los recuentos coinciden o alguna clasificación no es policy-v1, detente: el contraste no sería visible en esta ejecución de datos y modelo.
La definición de negocio actual es este SQL exacto:
SELECT uniqExact(customer_id) FROM v_orders
WHERE order_ts >= now() - INTERVAL 30 DAY
AND status NOT IN ('cancelled', 'returned')La definición antigua policy-v1 cuenta, en cambio, los clientes registrados durante los últimos 90 días. Por tanto, el SQL generado en este módulo es válido respecto de las instrucciones explícitas de policy-v1. El objetivo no es demostrar que el modelo carece de inteligencia, sino que el contexto de política publicado está obsoleto y el evaluator de ejecución SQL es demasiado estrecho para detectarlo.
Paso 2 — Aprovisionar el evaluator operativo
El aprovisionamiento es idempotente, por lo que se puede repetir con seguridad:
source .env
.venv/bin/python -m scripts.provision_online_evaluators --operationalLa salida debe mencionar el evaluator sql-execution-success y la regla habilitada agent-arena-sql-execution-online.
Paso 3 — Iniciar la versión preparada con la política obsoleta
En el primer terminal, desde la raíz del laboratorio, inicia el servidor seleccionando explícitamente la política antigua y déjalo activo:
source .env
AGENT_ARENA_POLICY_VERSION=policy-v1 \
.venv/bin/uvicorn serving.api:app --port 8100No omitas AGENT_ARENA_POLICY_VERSION. De lo contrario, el servicio usa de forma predeterminada la policy-v2 actual, que excluye correctamente pedidos cancelados y devueltos.
Paso 4 — Preguntar y valorar mediante Chat
En otro terminal, inicia el dashboard si aún no está activo:
scripts/arena.sh serveAbre http://localhost:5174, selecciona la pestaña Chat y $WINNER_CONFIG_ID, y pregunta:
How many active customers do we have?Lee el SQL generado y el resultado. Debe seguir la definición preparada de altas durante 90 días de policy-v1. Haz clic en 👎 y espera a que la interfaz muestre feedback sent.
Esta traza raíz de Chat es el único incidente autoritativo que puntuarás y entregarás al Módulo 04.
Paso 5 — Encontrar y verificar la traza de Chat
En Langfuse, abre Tracing y filtra por user-thumbs = false. Abre la raíz chat_turn más reciente cuya pregunta sea How many active customers do we have?, cuya configuración coincida con $WINNER_CONFIG_ID y cuyos metadatos muestren policyversion=policy-v1. Copia su ID y URL, y configura localmente el ID:
export CHAT_TRACE_ID="<paste the Chat trace ID>"
.venv/bin/python -m scripts.verify_online_scores "$CHAT_TRACE_ID" \
sql-execution-success=true user-thumbs=falseVerifica que user-thumbs sea un Boolean false, no una puntuación numérica ni de texto. El código del servicio llama al campo de metadatos policy_version; el adaptador OpenTelemetry lo sanea y emite en Langfuse como policyversion.
Paso 6 — Reproducir con un curl sin valoración
La llamada a la API sin procesar es una reproducción y un diagnóstico obligatorios desde línea de comandos. Crea una traza separada, pero no es el incidente de feedback y no debe valorarse:
source .env
export WINNER_CONFIG_ID="${WINNER_CONFIG_ID:-qwen3.7-flash__P2_fewshot}"
ASK_BODY=$(.venv/bin/python -c \
'import json,sys; print(json.dumps({"question": sys.argv[1], "config_id": sys.argv[2]}))' \
"How many active customers do we have?" "$WINNER_CONFIG_ID")
CURL_RESPONSE=$(curl -fsS http://localhost:8100/ask \
-H 'content-type: application/json' -d "$ASK_BODY")
printf '%s\n' "$CURL_RESPONSE" | .venv/bin/python -m json.tool
CURL_TRACE_ID=$(printf '%s\n' "$CURL_RESPONSE" | .venv/bin/python -c \
'import json,sys; data=json.load(sys.stdin); assert data.get("policy_version") == "policy-v1"; assert data.get("outcome") == "ok"; trace_id=data.get("trace_id"); assert isinstance(trace_id, str) and trace_id; print(trace_id)')La respuesta debe incluir outcome: "ok", un trace_id no vacío y policy_version: "policy-v1".
Espera al evaluator asíncrono y verifica solo su puntuación operativa:
.venv/bin/python -m scripts.verify_online_scores "$CURL_TRACE_ID" \
sql-execution-success=trueNo llames a /feedback para CURL_TRACE_ID ni lo incluyas en la hoja de trabajo. Es solo un diagnóstico reproducible de la API; CHAT_TRACE_ID sigue siendo la traza de entrega.
Paso 7 — Comparar con la política actual
Ejecuta el SQL de la política actual mediante el mismo cliente de ClickHouse de solo lectura que usa el agente y compara su único resultado con el resultado obsoleto de CURL_RESPONSE:
.venv/bin/python - <<'PY'
from arena.config import load_config
from agents.chclient import ROClickHouseClient
sql = """SELECT uniqExact(customer_id) FROM v_orders
WHERE order_ts >= now() - INTERVAL 30 DAY
AND status NOT IN ('cancelled', 'returned')"""
result = ROClickHouseClient(load_config().clickhouse).query(sql)
print(result.rows[0][0])
PYEsta es la consulta exacta que acabas de ejecutar:
SELECT uniqExact(customer_id) FROM v_orders
WHERE order_ts >= now() - INTERVAL 30 DAY
AND status NOT IN ('cancelled', 'returned')El recuento diferente es el fallo visible para el usuario. El SQL se ejecutó, pero respondió a una definición de negocio equivocada. Registra ese recuento junto a las pruebas de la traza autoritativa de Chat.
Hoja de trabajo de investigación
Conserva esta entrega para el Módulo 04:
| Prueba | Tu valor |
|---|---|
config_id ganador | |
| ID de la traza autoritativa de Chat | |
| URL de la traza autoritativa de Chat | |
Recuento obsoleto de policy-v1 | |
Recuento actual de policy-v2 | |
sql-execution-success | true |
user-thumbs | false |
Cómo verificar que has terminado
- El preflight mostró recuentos obsoleto y actual distintos, y clasificó las tres preguntas preparadas como
policy-v1. - El servicio se ejecutó con
AGENT_ARENA_POLICY_VERSION=policy-v1y/askdevolvióoutcome: "ok". - La traza autoritativa de Chat tiene
sql-execution-success=trueyuser-thumbs=falseen Langfuse. - El diagnóstico curl obligatorio devolvió
outcome: "ok", produjo unCURL_TRACE_IDdistinto y no se valoró ni entregó. - Registraste el ID y la URL de la traza autoritativa de Chat y ambos recuentos sin compartir credenciales.
- Puedes explicar por qué una ejecución SQL correcta no demostró corrección semántica.
Continúa con el Módulo 04 — Investigar para convertir esta señal en un diagnóstico revisado por una persona.
02 Medir offline
Usa evaluators, datasets y trazas de Langfuse para saber hasta qué punto es bueno el ganador, por pregunta y nivel.
04 Investigar
Convierte una señal negativa del usuario en un diagnóstico y una corrección revisados por una persona sin confundir el feedback con la verdad de referencia.