Notas prácticas: Desarrollo impulsado por la evaluación: Un enfoque de ingeniería de software para
Guía práctica paso a paso: Desarrollo impulsado por evaluaciones: un enfoque de ingeniería de software para contratos, verificaciones y espacios de código reutilizable destinados a los equipos que implementan este patrón.
Esta guía reconstruye el proceso desde las materias primas hasta un sistema funcional para: Eval-Driven Development: Un enfoque de ingeniería de software para agentes de IA de nivel industrial. El enfoque se centra en pasos operativos, verificaciones explícitas y código que se puede incorporar directamente a un repositorio sin necesidad de adivinar su propósito. En la fase de visión general, se deben definir las entradas, el responsable del paso y los criterios de finalización antes de modificar el código. Los operadores deben poder volver a ejecutar el paso a partir de un punto de control conocido, sin tener que adivinar el estado oculto. Se deben registrar los tiempos de ejecución y el costo en tokens o consultas junto con los resultados funcionales. La visibilidad temprana de los costos evita facturas inesperadas cuando el proceso pasa de una demostración a entornos compartidos.
Resumen
Al trabajar en la etapa de resumen, anote primero el contrato: los datos necesarios, la señal de éxito y qué ocurre en caso de fallo parcial. Esa lista de verificación mantiene honestas las futuras modificaciones del código. Guarde la configuración fuera del código de la aplicación. Los archivos de entorno, los almacenes de secretos y las banderas de funcionalidad deben estar en un lugar donde los operadores puedan auditarlos sin tener que leer todo el sistema. Haga un punto de control después de los pasos costosos. La función de reanudación no debe volver a facturar la misma llamada al LLM cuando un operador intente nuevamente un nodo posterior.
Introducción
Al trabajar en la fase de introducción, anote primero el contrato: los datos necesarios, la señal de éxito y qué ocurre en caso de fallo parcial. Esa lista de verificación mantiene honestas las futuras modificaciones del código. Documente junto con ella el camino óptimo y el camino de recuperación. Las reintentos, los controles humanos y el manejo de mensajes no entregados forman parte del producto, no son mejoras posteriores. Haga un punto de control después de los pasos costosos. El sistema de reanudación no debe volver a facturar la misma llamada al LLM cuando un operador vuelve a intentar un nodo posterior.
El pipeline de producción: el flujo a alto nivel
Al trabajar en la etapa de “El pipeline de producción”, anote primero el contrato: los datos de entrada requeridos, la señal de éxito y qué ocurre en caso de un fallo parcial. Esa lista de verificación mantiene honestas las futuras modificaciones del código. Prefiera unidades pequeñas y verificables en lugar de scripts extensos. Cuando falla un paso, el fallo debe apuntar a una única responsabilidad y no a todo un pipeline complicado. Haga puntos de control después de los pasos costosos. La función de reanudación no debe volver a facturar la misma llamada al LLM cuando un operador intenta nuevamente un nodo posterior.
1. El contrato: Desacoplar y versionar el prompt
Al trabajar en la etapa 1 “Desacoplar mediante el contrato”, anote primero el contrato: las entradas requeridas, la señal de éxito y qué ocurre en caso de fallo parcial. Esa lista de verificación mantiene honestas las futuras modificaciones del código. Trate esta etapa como un contrato entre las entradas y las salidas validadas. Asigne nombres a los artefactos, defina comprobaciones de éxito y rechace las completaciones parciales silenciosas. Almacene en caché las instrucciones del sistema estables y los esquemas de las herramientas. Reenviar un preámbulo idéntico es una causa común de desperdicio de recursos.
[
{
"agent_id": "financial_market_headlines",
"version": 1,
"agent_model": "openai:gpt-4",
"prompt": "What are today's major financial market headlines?",
"eval": {
"contains": ["market"],
"max_model_requests": 3,
"min_tool_calls": 1,
"max_tool_calls": 5,
"judge_rubric": "The answer should be a useful response to the user's financial markets question. It should summarize market-relevant information, avoid obviously unrelated content, avoid investment advice, and avoid claiming certainty beyond what the retrieved information supports."
}
}
]
2. Tiempo de ejecución: El motor de ejecución
Al trabajar en la etapa 2 “El tiempo de ejecución”, anote primero el contrato: las entradas requeridas, la señal de éxito y qué ocurre en caso de fallo parcial. Esa lista de verificación mantiene honestas las futuras modificaciones del código. Registre los tiempos y el costo de tokens o consultas junto con los resultados funcionales. Tener visibilidad del costo desde el principio evita facturas inesperadas cuando el proceso pasa de la fase de demostración a entornos compartidos. Haga un punto de control después de los pasos costosos. La reanudación no debe volver a facturar la misma llamada al LLM cuando un operador intenta nuevamente un nodo posterior.
3. La capa de observabilidad: sin puntos ciegos
Al trabajar en la etapa 3, La capa de observabilidad, primero escribe el contrato: las entradas requeridas, la señal de éxito y qué ocurre en caso de fallo parcial. Esa lista de verificación mantiene honestas las futuras modificaciones del código. Mantén la configuración fuera del código de la aplicación. Los archivos de entorno, los almacenes de secretos y las banderas de funcionalidad deben estar en un lugar donde los operadores puedan auditarlos sin tener que leer todo el sistema. Haz una verificación después de los pasos costosos. La función de reanudación no debe volver a facturar la misma llamada al LLM cuando un operador intenta nuevamente un nodo posterior.
4. La capa de evaluación: El CI/CD de la IA
Al trabajar en la etapa 4, Capa de Evaluación, anote primero el contrato: las entradas requeridas, la señal de éxito y qué ocurre en caso de fallo parcial. Esa lista de verificación mantiene honestas las futuras modificaciones del código. Documente junto con ello el camino óptimo y el camino de recuperación. Las reintentos, los controles humanos y el manejo de mensajes no entregados forman parte del producto, no son mejoras posteriores. Haga un punto de control después de los pasos costosos. La función de reanudación no debe volver a facturar la misma llamada al LLM cuando un operador vuelve a intentar un nodo posterior.
Evaluaciones: Forzando el determinismo en un sistema no determinista
Al trabajar en la implementación de Evals Forcing Determinism, anote primero el contrato: las entradas requeridas, la señal de éxito y qué ocurre en caso de fallo parcial. Esa lista de verificación garantiza que los cambios posteriores en el código sean transparentes. Prefiera unidades pequeñas y verificables a scripts extensos. Cuando un paso falla, el fallo debe referirse a una única responsabilidad y no a un proceso complicado. Haga puntos de control después de los pasos costosos. La función de reanudación no debe volver a facturar la misma llamada al LLM cuando un operador intenta nuevamente un nodo posterior. Al trabajar en la implementación de Evals Forcing Determinism, anote primero el contrato: las entradas requeridas, la señal de éxito y qué ocurre en caso de fallo parcial. Esa lista de verificación garantiza que los cambios posteriores en el código sean transparentes. Registre los tiempos de ejecución y el costo en tokens o consultas junto con los resultados funcionales. Tener visibilidad del costo desde el principio evita facturas inesperadas cuando el proceso pasa de la versión de demostración a entornos compartidos.
Capa 1: Pruebas determinísticas en tiempo real
La etapa de Capa 1 de pruebas determinísticas en tiempo real funciona mejor cuando se trata como una superficie medible. Capture una transcripción de referencia, un caso de fallo y la nota de reversión antes de ampliar el alcance. Mantenga la configuración fuera del código de la aplicación. Los archivos de entorno, los almacenes de secretos y las banderas de funcionalidad deben estar en un lugar donde los operadores puedan auditarlos sin tener que leer todo el grafo. Mantenga el estado del grafo plano y tipado. Los bloques anidados ocultan qué nodo escribió qué campo y provocan interrupciones en la continuación después de las interrupciones.
uv run python tests/unittest_eval_agent.py
evaluators=[
*[Contains(value, case_sensitive=False) for value in case.eval.contains],
MaxModelRequests(case.eval.max_model_requests),
MinToolCalls(case.eval.min_tool_calls),
MaxToolCalls(case.eval.max_tool_calls),
]
(financial-agent2) alex@pop-os:/ssd/ai_works/financial_agent2$ uv run python tests/unittest_eval_agent.py
Running each eval case 3 time(s)
Evaluating task ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 0:00:00
Evaluation Summary: task
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━┓
┃ Case ID ┃ Metrics ┃ Assertions ┃ Duration ┃
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━┩
│ financial_market_headlines_v1 [1/3] │ tool_calls: 1 │ ✔✔✔✔ │ 18.8s │
│ │ requests: 2 │ │ │
│ │ input_tokens: 1,325 │ │ │
│ │ output_tokens: 278 │ │ │
│ │ cost: 0.0564 │ │ │
├─────────────────────────────────────┼───────────────────────┼────────────┼──────────┤
│ financial_market_headlines_v1 [2/3] │ tool_calls: 1 │ ✔✔✔✔ │ 8.8s │
│ │ requests: 2 │ │ │
│ │ input_tokens: 1,195 │ │ │
│ │ output_tokens: 82 │ │ │
│ │ cost: 0.0408 │ │ │
├─────────────────────────────────────┼───────────────────────┼────────────┼──────────┤
│ financial_market_headlines_v1 [3/3] │ tool_calls: 1 │ ✔✔✔✔ │ 13.5s │
│ │ requests: 2 │ │ │
│ │ input_tokens: 1,292 │ │ │
│ │ output_tokens: 388 │ │ │
│ │ cost: 0.0620 │ │ │
├─────────────────────────────────────┼───────────────────────┼────────────┼──────────┤
│ Averages │ requests: 2.00 │ 100.0% ✔ │ 13.7s │
│ │ output_tokens: 249.3 │ │ │
│ │ tool_calls: 1.00 │ │ │
│ │ cost: 0.0531 │ │ │
│ │ input_tokens: 1,270.7 │ │ │
└─────────────────────────────────────┴───────────────────────┴────────────┴──────────┘
Capa 2: Regresión determinística a partir de registros
La etapa de regresión determinística de capa 2 funciona mejor cuando se trata como una superficie medible. Capture un registro ideal, un caso de fallo y la nota de reversión antes de ampliar el alcance. Documente tanto el camino óptimo como el camino de recuperación juntos. Las reintentos, los controles humanos y el manejo de mensajes no entregados forman parte del producto, no son mejoras posteriores. Mantenga el estado del gráfico simple y tipado; los bloques anidados ocultan qué nodo escribió qué campo y provocan interrupciones en la continuación del proceso.
uv run python tests/regression_eval_traces.py
Trace: ff5a53e3392dc26cd0a2890782be70ec
Eval case: financial_market_headlines v1
Status: PASS
Model requests: 2
Tool calls: 1
contains('market'): PASS
MaxModelRequests: PASS
MaxToolCalls: PASS
Capa 3: Pruebas no determinísticas — LLM como juez
La etapa No Determinística de Capa 3 funciona mejor cuando se trata como una superficie medible. Capture un registro ideal, un caso de fallo y la nota de reversión antes de ampliar el alcance. Prefiera unidades pequeñas y verificables en lugar de scripts extensos. Cuando falla un paso, el fallo debe apuntar a una sola responsabilidad y no a un proceso complicado. Asigne un presupuesto de tokens por turno y por sesión. Las herramientas agentes amplían el contexto de forma excesiva; los límites estrictos evitan que las demostraciones se conviertan en facturas inesperadas. La etapa No Determinística de Capa 3 funciona mejor cuando se trata como una superficie medible. Capture un registro ideal, un caso de fallo y la nota de reversión antes de ampliar el alcance. Registre los tiempos y el costo en tokens o consultas junto con los resultados funcionales. Tener visibilidad del costo desde el principio evita facturas inesperadas cuando el proceso pasa de una demostración a entornos compartidos.
[
{
"agent_id": "financial_market_headlines",
"version": 1,
"agent_model": "openai:gpt-4",
"prompt": "What are today's major financial market headlines?",
"eval": {
"contains": ["market"],
"max_model_requests": 3,
"min_tool_calls": 1,
"max_tool_calls": 5,
"judge_rubric": "The answer should be a useful response to the user's financial markets question. It should summarize market-relevant information, avoid obviously unrelated content, avoid investment advice, and avoid claiming certainty beyond what the retrieved information supports."
}
}
]
LLMJudge(
rubric=case.eval_case.eval.judge_rubric,
model=args.judge_model,
include_input=True,
score={"evaluation_name": "judge_score", "include_reason": True},
assertion={"evaluation_name": "judge_pass", "include_reason": True},
)
uv run python tests/regression_llm_judge_traces.py --sample-percent 50
Trace selection: fetched=1 sampled=1 judging=1 lookback_minutes=1440 sample_percent=50 max_traces=5
Trace case: trace_id=3891f0b8432c9bbcb00e5e8adce1600b agent_id=financial_market_headlines prompt_version=1 answer_chars=207
Judging 1 trace(s) with openai:gpt-5.4
Evaluating task ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 0:00:00
Evaluation Summary: task
┏━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━┓
┃ Case ID ┃ Inputs ┃ Outputs ┃ Scores ┃ Assertions ┃ Duration ┃
┡━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━┩
│ financial_market_he… │ {'trace_id': │ Today's major │ judge_score: 0.000 │ judge_pass: ✗ │ 469µs │
│ │ '3891f0b8432c9bbcb00 │ financial market │ Reason: The │ Reason: The │ │
│ │ e5e8adce1600b', │ headlines can be │ response does not │ response does not │ │
│ │ 'agent_id': │ found on major │ summarize any actual │ summarize any │ │
│ │ 'financial_market_he │ business and finance │ market headlines or │ actual market │ │
│ │ adlines', │ news outlets │ provide │ headlines or │ │
│ │ 'prompt_version': 1, │ including CNBC, │ market-relevant │ provide │ │
│ │ 'agent_model': │ Yahoo Finance, │ information; it only │ market-relevant │ │
│ │ 'openai:gpt-4', │ Reuters, and │ redirects the user │ information; it │ │
│ │ 'judge_model': │ Bloomberg. For more │ to news websites. It │ only redirects the │ │
│ │ 'openai:gpt-5.4', │ specific stories, │ avoids investment │ user to news │ │
│ │ 'prompt': "What are │ please visit their │ advice, but it is │ websites. It avoids │ │
│ │ today's major │ websites. │ not a useful answer │ investment advice, │ │
│ │ financial market │ │ to the user's │ but it is not a │ │
│ │ headlines?"} │ │ question. │ useful answer to │ │
│ │ │ │ │ the user's │ │
│ │ │ │ │ question. │ │
│ │ │ │ │ │ │
│ │ │ │ │ │ │
├──────────────────────┼──────────────────────┼──────────────────────┼──────────────────────┼─────────────────────┼──────────┤
│ Averages │ │ │ judge_score: 0.000 │ 0.0% ✔ │ 469µs │
└──────────────────────┴──────────────────────┴──────────────────────┴──────────────────────┴─────────────────────┴──────────┘
uv run python tests/regression_llm_judge_traces.py --sample-percent 10 --lookback-minutes 30
Trace selection: fetched=1 sampled=1 judging=1 lookback_minutes=30 sample_percent=10 max_traces=5
Trace case: trace_id=38fa3a54134d8818c7d7a5afbf50967e agent_id=financial_market_headlines prompt_version=1 answer_chars=654
Judging 1 trace(s) with openai:gpt-5.4
Evaluating task ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 100% 0:00:00
Evaluation Summary: task
┏━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━┓
┃ Case ID ┃ Inputs ┃ Outputs ┃ Scores ┃ Assertions ┃ Duration ┃
┡━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━┩
│ financial_market_… │ {'trace_id': │ Here are today's │ judge_score: 0.450 │ judge_pass: ✗ │ 441µs │
│ │ '38fa3a54134d8818c │ major financial │ Reason: The │ Reason: The │ │
│ │ 7d7a5afbf50967e', │ market headlines: │ response is │ response is │ │
│ │ 'agent_id': │ │ market-related and │ market-related │ │
│ │ 'financial_market_ │ 1. Wall Street's │ avoids investment │ and avoids │ │
│ │ headlines', │ riskiest trades │ advice, but it │ investment │ │
│ │ 'prompt_version': │ are suddenly back │ mostly lists │ advice, but it │ │
│ │ 1, 'agent_model': │ on top: Chart of │ article headlines │ mostly lists │ │
│ │ 'openai:gpt-4', │ the Day - Yahoo │ and links rather │ article headlines │ │
│ │ 'judge_model': │ Finance │ than providing a │ and links rather │ │
│ │ 'openai:gpt-5.4', │ [Link](https://fi │ useful summary of │ than providing a │ │
│ │ 'prompt': "What │ nance.yahoo.com/) │ the key financial │ useful summary of │ │
│ │ are today's major │ 2. S&P 500 │ market │ the key financial │ │
│ │ financial market │ notches │ developments. │ market │ │
│ │ headlines?"} │ record-high close │ │ developments. │ │
│ │ │ as rate-hike │ │ │ │
│ │ │ worries ease - │ │ │ │
│ │ │ Reuters │ │ │ │
│ │ │ [Link](https://ww │ │ │ │
│ │ │ w.reuters.com/mar │ │ │ │
│ │ │ kets/us/) │ │ │ │
│ │ │ 3. Treasury │ │ │ │
│ │ │ yields rise as │ │ │ │
│ │ │ U.S. threatens │ │ │ │
│ │ │ Iran with more │ │ │ │
│ │ │ economic │ │ │ │
│ │ │ sanctions - CNBC │ │ │ │
│ │ │ [Link](https://ww │ │ │ │
│ │ │ w.cnbc.com/) │ │ │ │
│ │ │ 4. Latest stock │ │ │ │
│ │ │ market, financial │ │ │ │
│ │ │ and business news │ │ │ │
│ │ │ - MarketWatch │ │ │ │
│ │ │ [Link](https://ww │ │ │ │
│ │ │ w.marketwatch.com │ │ │ │
│ │ │ /) │ │ │ │
│ │ │ 5. Latest finance │ │ │ │
│ │ │ and stock market │ │ │ │
│ │ │ news covering the │ │ │ │
│ │ │ Dow, S&P 500, │ │ │ │
│ │ │ banking, │ │ │ │
│ │ │ investing and │ │ │ │
│ │ │ regulation - WSJ │ │ │ │
│ │ │ [Link](https://ww │ │ │ │
│ │ │ w.wsj.com/finance │ │ │ │
│ │ │ ) │ │ │ │
├────────────────────┼────────────────────┼───────────────────┼────────────────────┼───────────────────┼──────────┤
│ Averages │ │ │ judge_score: 0.450 │ 0.0% ✔ │ 441µs │
└────────────────────┴────────────────────┴───────────────────┴────────────────────┴───────────────────┴──────────┘mar
{
"id": "financial_market_headlines",
"version": 2,
"agent": "websearch",
"prompt": "Use the web-search tool to find and verify today's major financial-market headlines. Report the 3 to 5 most consequential developments across equities, rates, currencies, commodities, or macroeconomic policy. For each item, state what happened, identify the affected market or region, explain briefly why it matters, and name the source with a link when available. Include the relevant date and units for numerical claims. Cross-check any surprising index level, percentage move, policy decision, or economic release against a second reliable source; if it cannot be verified, omit it or clearly label it as unconfirmed. State when the information was current, distinguish facts from developing reports or interpretation, and say when reliable current information is insufficient. Do not invent facts, present stale information as today's news, or give personalized investment advice.",
"contains": ["market"],
"max_model_requests": 4,
"min_tool_calls": 1,
"max_tool_calls": 7,
"judge_rubric": "The response should provide 3 to 5 current, consequential financial-market developments based on web research. Each item should identify what happened, the affected market or region, why it matters, and its source, preferably with a link. Numerical claims should include meaningful dates and units; surprising figures should be corroborated by a second reliable source or explicitly marked unconfirmed. The answer should state when the information was current, distinguish verified facts from developing reports or interpretation, and acknowledge insufficient evidence rather than inventing details. It must stay relevant, avoid stale news presented as current, avoid unsupported certainty, and avoid personalized investment advice. A polished but uncited answer containing an implausible or unverifiable market figure should fail."
},
Conviirtiendo el patrón en CI/CD
Para convertir el patrón en una etapa, se deben definir las entradas, el responsable de la tarea y los criterios de finalización antes de modificar el código. Los operadores deben poder volver a ejecutar la tarea a partir de un punto de control conocido, sin tener que adivinar el estado oculto. Mantenga la configuración fuera del código de la aplicación. Los archivos de entorno, los almacenes de datos secretos y las banderas de funcionalidad deben encontrarse en un lugar donde los operadores puedan auditarlos sin necesidad de leer todo el sistema. Coloque la aprobación humana en las conexiones que implican gastos o modificaciones en los datos de producción. La configuración en tiempo de compilación no equivale a la completitud del proceso empresarial.
Referencias
En la fase de Referencias, defina las entradas, el responsable del paso y los criterios de finalización antes de modificar el código. Los operadores deben poder volver a ejecutar el paso a partir de un punto de control conocido sin tener que adivinar el estado oculto. Documente tanto la ruta óptima como la ruta de recuperación. Las reintentos, los controles humanos y el manejo de mensajes no entregados forman parte del producto, no son mejoras posteriores. Incluya la aprobación humana en aquellos casos que impliquen gastos o cambios en los datos de producción. La configuración en tiempo de compilación no equivale a la completitud del proceso empresarial.
Lista de verificación operativa
La fase de la lista de verificación operativa funciona mejor cuando se trata como una superficie medible. Capture un registro ideal, un caso de fallo y la nota de reversión antes de ampliar el alcance.
Considere esta fase como un contrato entre las entradas y los resultados validados. Asigne nombres a los artefactos, defina comprobaciones de éxito y rechace cualquier completación parcial silenciosa.
Mantenga el estado del grafo en formato plano y tipado. Los bloques anidados ocultan qué nodo escribió qué campo y provocan interrupciones en la continuación del proceso.
Evalúe por separado las respuestas de una sola ronda y las trayectorias de varias rondas. La agregación de puntuaciones de chat oculta los fallos en los ciclos de herramientas.
Escriba un breve manual de operaciones: cómo rotar claves, cómo vaciar la cola y cómo revertir la última inserción.
Documente tanto el camino óptimo como el de recuperación. Las reintentos, los controles humanos y el manejo de mensajes no entregados forman parte del producto, no son mejoras posteriores.
Antes de promocionar la solución, congele las versiones, capture una transcripción de referencia para el camino crítico y confirme los pasos de reversión. Los entornos compartidos requieren límites de velocidad, verificaciones de asignación y un responsable claro para la rotación de claves secretas. Prefiera una fiabilidad sencilla a demostraciones ingeniosas pero puntuales.
Nota por lotes para 4a86f3fd2d9a: mantener las claves del proveedor fuera del repositorio, establecer un límite para los tokens por sesión y almacenar las transcripciones junto a los archivos de evaluación para que los cambios posteriores en el modelo sigan siendo comparables.