De error de producción a eval: el flywheel que alimenta el dataset
Resumen
Las evals iniciales arman el dataset. El flywheel lo alimenta: captura el fallo con traza, triage semanal a casos dorados, dataset vivo versionado y CI que bloquea el merge. Un error visto una vez se convierte en un test que corre siempre. Distinto de armar la suite y de calibrar el juez.

Qué resuelve
Esta pieza se queda en la decisión práctica: qué instalar, qué riesgo agrega y cómo aplicarlo sin romper operación.
Las evals prácticas arman el dataset inicial de 20–50 casos. Esta guía cubre qué pasa después, cuando el agente ya está en producción y el dataset se queda viejo. LangSmith lo dice en una línea: add real traces to a dataset so a failure you saw once becomes a test you run every time. Langfuse llama al mismo ciclo AI engineering loop: trazar, monitorear, construir datasets, experimentar, evaluar. OpenAI, al deprecar su Evals platform (read-only 31 oct 2026, apagado 30 nov 2026), recomienda Datasets como espacio dinámico que crece cuando aparece un edge case.
Esto no es observabilidad (detectar el fallo). No es calibrar el juez (cómo puntuar). Es el cómo el fallo entra al dataset y cierra el merge.
Fuentes verificadas el 6 de septiembre de 2026.
Una línea
Un error de producción sin traza es anécdota. Con traza, triage y CI, es un caso dorado.
El contrato del flywheel
Cuatro piezas, en este orden. Si saltas una, el resto es teatro.
| Pieza | Qué entra | Qué sale | Qué no es |
|---|---|---|---|
| Captura | run/trace con input, tools, output, ids | artefacto reproducible | un screenshot de Slack |
| Triage | cola semanal de fallos | caso dorado o descarte con razón | “el modelo alucinó” sin etiqueta |
| Dataset vivo | ejemplo versionado + split | tag prod que CI corre | un CSV que nadie toca |
| Gate | experiment + umbral | RegressionError / job rojo | un dashboard que “se mira” |
Langfuse distingue online (scores en tráfico vivo, sin referencia) y offline (dataset curado, antes de shippear). El flywheel conecta las dos: el online alimenta el offline; el offline bloquea el deploy.
Captura: sin traza no hay caso
El input del flywheel es un run. LangSmith: cada interacción crea un run con inputs, outputs y pasos intermedios. Langfuse: traces, sessions, agents, prompts. Si tu agente no emite un trace_id hasta el webhook, no puedes promover el fallo.
Mínimo por fallo:
- Input crudo (mensaje, adjunto recortado, no el PDF entero).
- Tool calls con nombre, args y status — los tests de tools ya cubren el contrato; aquí solo se copia el que falló.
- Output que vio el usuario (no el razonamiento interno si no lo logueas).
- Ids:
trace_id,tenant_id, versión de prompt/toolset. - Etiqueta humana en 24 h:
falso_positivo,regresión,nuevo_edge,infra.
Sin (5) el dataset se llena de ruido. Un timeout de red no es un caso de calidad.
PII: redacta antes de copiar al dataset. Un recibo o un DPI en el trace no se “anonimiza después”.
Triage semanal, no “cuando haya tiempo”
Anthropic pide criterios específicos y medibles. “El agente falló” no es un criterio. “El clasificador de tickets no eligió Hardware/Software/Other en este input” sí lo es.
Ritmo que aguanta un equipo chico:
- Lunes 30 min. Filtra traces online con score bajo o thumbs-down. Tope: 15 items.
- Por item: reproducir con el mismo input. Si no se reproduce, etiqueta
no_reproy cierra. - Si se reproduce: escribe el expected en una frase (exact match, JSON schema, o rúbrica de 1 criterio). Eso es el gold.
- Tope de altas: 3 casos nuevos por semana al split
regression. Más que eso diluye el gate.
LangSmith versiona el dataset en cada add/update/delete. Taggea la versión que CI corre (prod), no “latest”. Un add del martes no debe mover el umbral del PR del lunes sin que lo veas.

Dataset vivo: el CSV estático muere
OpenAI, en Datasets: we recommend using your dataset as a dynamic space, expanding your set of evaluation data over time. As you identify edge cases or blind spots that need monitoring, add them. LangSmith permite exportar traces filtrados de un experiment de vuelta al dataset. Langfuse: build datasets es un paso del loop, no un proyecto aparte.
Tres splits, no uno:
| Split | Qué vive ahí | Quién lo toca | CI |
|---|---|---|---|
smoke | 8–12 casos baratos, deterministas | el autor del PR | siempre |
regression | fallos reales promovidos | triage semanal | PRs a main |
held_out | nunca visto en prompt-tuning | un humano, no el agente | nightly, no en cada push |
Mezclar held_out con el set que usas para iterar el prompt es hacer trampa. Anthropic lo llama held-out test set; si el modelo ya “vio” el caso en el martes de prompt, el score del jueves no mide generalización.
Cada ejemplo necesita:
idestable (no el índice de fila).input+expected+grader(code/string_check/ juez).source_trace_idpara auditar de dónde salió.added_atyowner.
Borrar un caso también es una decisión. Si el producto cambió y el expected ya no aplica, retira el ejemplo y deja nota. Un gold obsoleto es un falso rojo eterno.
CI que bloquea, no un dashboard que se mira
Langfuse documenta el gate: dataset → experiment SDK → evaluators → RegressionError si un score viola el umbral → GitHub Action langfuse/experiment-action en pull_request. Permisos mínimos: contents: read, pull-requests: write para el comentario. Pin de la action a un release, no a @main.
Contrato del job:
- Corre solo
smoke+regressiontagprod. - Graders de código primero (status, JSON, tool name). El juez LLM, si entra, es un score más —no la verdad.
- Umbral escrito: p. ej.
exact_match >= 0.95en smoke; cero regresiones nuevas vs. baseline del tag. - Rojo = no merge. Amarillo en nightly (
held_out) no bloquea el PR; abre issue.
Si el job tarda 20 minutos porque llama al LLM en 200 casos, nadie lo corre. Por eso el split smoke es determinista y cabe en 2 minutos.
El flywheel cierra aquí: el fallo de producción que entró el lunes tumba el PR del miércoles si el cambio lo revive. Sin ese cierre, el dataset es un museo.

Qué no meter en el loop
- Un screenshot de Slack sin
trace_id. No es reproducible. - PII cruda. Redacta; si no puedes, no copies el trace.
- Cientos de sintéticos el primer mes. Tres fallos reales ganan a 80 paráfrasis.
- Juez sin rúbrica como único grader. Eso es otra demo.
- Online eval en el 100% del tráfico con LLM-as-judge. LangSmith pide sampling; si no muestras, quemas presupuesto y no aprendes más.
- Tag
prod= latest. El CI debe clavar una versión.
Checklist
- Todo fallo que llega a triage trae
trace_id+ input + tools + output. - Etiqueta humana en 24 h;
no_reprose cierra, no se promociona. - Máximo 3 altas/semana al split
regression. - Dataset versionado; CI corre el tag
prod, no HEAD. - Splits
smoke/regression/held_outseparados. - Job de PR con umbral escrito y
RegressionError(o equivalente). - Graders de código antes que el juez.
- PII redactada antes de copiar al dataset.
- Caso retirado deja nota; no se “comenta” el expected.
FAQ
¿Esto reemplaza las evals de 20–50 casos? No. Esa guía arma el set inicial. El flywheel lo mantiene vivo. Sin el inicial, no hay baseline que el CI compare.
¿Puedo usar solo online evals? Miden tendencia. No bloquean un merge. El gate necesita referencia (expected) y un experiment offline.
¿OpenAI Evals platform sigue? No para trabajo nuevo. Read-only 31 oct 2026, shutdown 30 nov 2026. Datasets (o LangSmith/Langfuse) es el camino; el patrón —caso → grader → iterar— no cambia.
¿Cuántos casos son “suficientes” en regression? Los que hayas visto fallar de verdad. 12 bien etiquetados ganan a 200 sintéticos. El tope es el tiempo del job, no la vanidad del número.
¿El agente puede auto-agregar casos? Puede proponer. Un humano etiqueta y escribe el expected. Un dataset que se autoalimenta sin triage es un vertedero.
Relacionado
Lecturas relacionadas
Sigue explorando AgentOps y otras piezas para builders.

SLO y error budget en agentes: 4 SLIs, burn rápido/lento y política 50/100

RAG en producción: permisos en la query, frescura e índices por tenant

Aprobaciones humanas en agentes: lotes, timeout fail-closed y presupuesto de interrupciones
