Evaluar al agente: trayectoria y tool-calls
evaluarás la trayectoria del agente Aurora —tool-call correctness y argument correctness— y aplicarás el principio outcome > transcript: juzgar el estado final logrado, no el guion exacto de pasos. Sin esto, el tercer modo de fallo de Aurora —el de orquestación— se te escapa entre los dedos.
3.1El reembolso que el agente prometió sin mirar la política
Vuelve a las zapatillas usadas. En L1 vimos tres trazas que producen la misma respuesta mala: "sí, hasta 90 días". La política real de Aurora dice 30 días y solo sin usar.
La trace C era la más escurridiza. El agente respondió de memoria. Nunca llamó a consultar_politica. No hubo retrieval, no hubo contexto.
Y ahí está el problema. Tu RAG triad (L2) no la detecta: si no hubo retrieval, no hay contexto que puntuar. Tus métricas IR (L3) tampoco: no hay top-K de chunks que medir. Ambas familias asumen que el paso de recuperación ocurrió.
En la trace C no ocurrió. El fallo vive en otra capa: la trayectoria. Qué herramientas eligió el agente, con qué argumentos, en qué orden. La respuesta es el qué; la trayectoria es el cómo.
Necesitas evaluar el cómo. Esta lección te da las herramientas.
3.2Qué vas a poder hacer
Al terminar esta lección sabrás:
- Distinguir los tres niveles de evaluación de un agente: outcome, trayectoria y componente.
- Medir la trayectoria de Aurora con tool-call correctness (¿llamó a las tools correctas?) y argument correctness (¿con los argumentos correctos?).
- Aplicar el principio outcome > transcript y justificar cuándo el guion de pasos importa y cuándo solo importa el resultado.
- Explicar pass@k y pass^k para razonar sobre la fiabilidad de un agente no-determinista.
Necesitas saber antes:
- De N0·L1, qué capturaba el tool span: nombre de la herramienta, argumentos y resultado.
- De N3·L1, el mapa de fallos por componente, en particular el "fallo de orquestación".
- De N3·L2 y L3, por qué retrieval y generación se miden con la triad y con métricas IR.
3.3Recupera
Antes de seguir, responde mentalmente. No mires lo de abajo hasta tener una respuesta.
- De N3·L1, ¿cuál era el "fallo de orquestación" del mapa de tres capas? Da el ejemplo de Aurora.
- De N0·L1, ¿qué tres datos capturaba un tool span explotable?
- De N1, tu dataset tenía casos de "no llamó a la tool" y de "escaló de más". ¿Por qué la triad y las métricas IR no bastan para esos dos casos?
La respuesta a la 3 es directa. La triad y las métricas IR miran el bloque RAG: contexto recuperado y respuesta generada sobre él. Un caso de "no llamó a la tool" no tiene retrieval que medir. Un "escaló de más" puede tener la respuesta correcta y aun así seguir una ruta mala. Ambos fallos están en la secuencia de decisiones del agente, no en el contenido de un chunk.
3.4El concepto: tres niveles de evaluación, y el del medio es nuevo
Empecemos por lo concreto. Tienes una ejecución de Aurora grabada como traza. ¿Por dónde la juzgas?
Los tres niveles
Hay tres formas de mirar la misma ejecución, de más gruesa a más fina (Confident AI, LLM Agent Evaluation Complete Guide):
- Outcome / end-to-end — la caja negra. ¿Completó la tarea? ¿El estado final es el correcto? No mira cómo llegó.
- Trayectoria — el plan y los pasos. Qué tools llamó, con qué argumentos, en qué orden, con qué reintentos o handoffs.
- Componente — las piezas sueltas: retrievers, modelos, sub-agentes, tools individuales. Esto fue L2 y L3.
L2 y L3 cubrieron el componente RAG. L1 te dio el marco del outcome. La pieza que falta es la del medio: la trayectoria.
Defino el término. La trayectoria es la secuencia de decisiones de orquestación del agente: qué herramientas invoca, con qué argumentos y en qué orden. La analogía: es la receta que siguió, no el plato que sirvió. El límite de la analogía: una receta tiene un único orden correcto; una trayectoria de agente, no —puede haber varias rutas válidas—.
Por qué los agentes son difíciles de evaluar
Anthropic lo formula con precisión: "las capacidades que hacen útiles a los agentes son las mismas que los hacen difíciles de evaluar" (Anthropic, Demystifying evals for AI agents, 9 ene 2026). Esas capacidades son autonomía, inteligencia y flexibilidad. Multi-turno, más tools, más estado: los errores se propagan.
Por eso la trayectoria importa. Un error en el primer tool-call contamina todo lo que viene después. Es la misma idea del primer fallo de la cadena que viste en el error analysis de N1.
Tool-call correctness y argument correctness
Dos preguntas distintas, dos métricas distintas:
- Tool-call correctness — ¿llamó a las herramientas correctas? En DeepEval,
ToolCorrectnessMetriccompara las tools llamadas contra las esperadas; por defecto, solo por nombre. Si le pasasavailable_tools, añade una evaluación LLM y toma elminde ambas (corpus D.3). - Argument correctness — ¿con los argumentos correctos? Por ejemplo: ¿
buscar_pedidorecibió elorder_idreal del cliente, o uno inventado? En DeepEval esto se activa conevaluation_params(corpus D.3). En Ragas,ToolCallAccuracycompara nombre y argumentos de cada tool call (corpus D.2).
Aquí hay un matiz que rompe la intuición. Un agente puede acertar la respuesta y fallar la trayectoria, y al revés (corpus D.4). Tools innecesarias, argumentos incorrectos, pasos repetidos, una ruta innecesariamente compleja: todo eso es trayectoria mala con outcome —a veces— correcto.
Outcome > transcript
Llegamos al principio que gobierna toda la evaluación de agentes. Léelo con cuidado, porque parece contradecir lo que acabamos de decir.
Anthropic recomienda preferir evaluar el outcome —el estado del entorno— sobre el transcript —la secuencia exacta de tool calls— (corpus D.4, A.6). El motivo: los agentes hallan rutas válidas no anticipadas. Si castigas al agente por no seguir tu guion, penalizas soluciones legítimas que no se te ocurrieron.
El ejemplo es real. Claude Opus 4.5 (24 nov 2025) resolvió un problema de tau2-bench explotando un loophole en la política. "Falló" el eval mientras producía un resultado mejor (corpus A.6). El guion esperado no contemplaba esa ruta.
Es común leer esto como "ignora la trayectoria". No es eso. Outcome > transcript dice: no exijas un orden de pasos rígido cuando varias rutas logran el objetivo. No dice: deja de mirar si el agente llamó a buscar_pedido con un order_id inventado. La trayectoria sigue importando para diagnosticar el porqué de un fallo y para detectar rutas peligrosas. Lo que cambia es que el outcome manda en el veredicto de pass/fail.
Fiabilidad de lo no-determinista: pass@k y pass^k
Un agente no es determinista. La misma entrada puede dar trayectorias distintas en ejecuciones distintas. Una sola ejecución correcta no prueba fiabilidad. Anthropic introduce dos métricas para esto (corpus D.4):
- pass@k — al menos 1 de k intentos es correcta. Mide si el agente puede resolverlo.
- pass^k — los k intentos son correctos. Mide si lo resuelve de forma consistente.
pass^k es el listón duro. Premia consistencia, no suerte. Un agente con pass@3 alto y pass^3 bajo "lo logra a veces": útil para saber el techo, peligroso para confiar en producción.
3.5Míralo funcionar: dos trayectorias para el mismo caso
Vamos a evaluar dos ejecuciones de Aurora sobre el mismo caso: un cliente pregunta por el estado de su pedido A-4471.
Lee primero ambas trayectorias enteras. Después medimos.
- Trayectoria 1 (mínima y correcta): el agente llama a
buscar_pedido("A-4471")→ responde con el estado. Una tool, el argumento correcto. - Trayectoria 2 (outcome correcto, trayectoria mala): el agente llama a
escalar_a_humano("cliente pregunta por pedido")sin necesidad → luegobuscar_pedido("A-4471")→ responde. La respuesta final acierta, pero escaló de más.
El outcome no distingue una de otra: las dos acaban con el estado correcto del pedido. La trayectoria sí. Vamos a medirla con ToolCorrectnessMetric de DeepEval.
1from deepeval import evaluate
2from deepeval.test_case import LLMTestCase, ToolCall
3from deepeval.metrics import ToolCorrectnessMetric
4
5# Las herramientas que Aurora DEBÍA llamar para este caso
6expected = [ToolCall(name="buscar_pedido")]
7
8# Trayectoria 1: una sola tool, la correcta
9caso_1 = LLMTestCase(
10 input="¿Dónde está mi pedido A-4471?",
11 actual_output="Tu pedido A-4471 está en reparto, llega mañana.",
12 tools_called=[ToolCall(name="buscar_pedido")],
13 expected_tools=expected,
14)
15
16# Trayectoria 2: escaló de más antes de buscar el pedido
17caso_2 = LLMTestCase(
18 input="¿Dónde está mi pedido A-4471?",
19 actual_output="Tu pedido A-4471 está en reparto, llega mañana.",
20 tools_called=[ToolCall(name="escalar_a_humano"), ToolCall(name="buscar_pedido")],
21 expected_tools=expected,
22)
23
24metric = ToolCorrectnessMetric()
25evaluate(test_cases=[caso_1, caso_2], metrics=[metric])¿Por qué expected_tools lista solo buscar_pedido y no escalar_a_humano? Porque define la trayectoria esperada para este caso. El cliente pregunta por un pedido; basta buscarlo. La métrica compara lo que el agente llamó contra esa expectativa. El caso 2 incluye una tool de más, así que su score baja: la trayectoria sobra pasos.
Ahora la argument correctness. La pregunta cambia: no "¿llamó a la tool correcta?" sino "¿con qué argumento?". Mide la trayectoria a nivel de turno con Ragas, que compara nombre y argumentos contra una referencia.
1import asyncio
2from ragas.metrics.collections import ToolCallAccuracy
3from ragas.messages import HumanMessage, AIMessage, ToolCall
4
5async def evaluar_argumentos():
6 # El order_id correcto del cliente es "A-4471"
7 user_input = [
8 HumanMessage(content="¿Dónde está mi pedido A-4471?"),
9 AIMessage(
10 content="Déjame consultar tu pedido.",
11 tool_calls=[ToolCall(name="buscar_pedido", args={"order_id": "A-4471"})],
12 ),
13 ]
14 reference_tool_calls = [
15 ToolCall(name="buscar_pedido", args={"order_id": "A-4471"}),
16 ]
17
18 metric = ToolCallAccuracy()
19 result = await metric.ascore(
20 user_input=user_input,
21 reference_tool_calls=reference_tool_calls,
22 )
23 print(f"Tool Call Accuracy: {result.value}")
24
25asyncio.run(evaluar_argumentos())Si el agente hubiera llamado a buscar_pedido con order_id="A-9999" —un id inventado— el nombre coincidiría pero el argumento no. La métrica lo penaliza. Esto captura el modo de fallo "inventa el estado de un pedido": a veces ni llama a la tool, a veces la llama con basura.
Por último, la fiabilidad. Imagina que ejecutas el mismo input tres veces y registras si cada trayectoria fue correcta:
1# Resultado de 3 ejecuciones del mismo input (True = trayectoria correcta)
2resultados = [True, False, True]
3
4k = len(resultados)
5pass_at_k = any(resultados) # ≥1 correcta → True
6pass_pow_k = all(resultados) # todas correctas → False
7
8print(f"pass@{k} = {pass_at_k}") # True: el agente PUEDE resolverlo
9print(f"pass^{k} = {pass_pow_k}") # False: NO de forma consistenteAuto-explicación. Antes de seguir, responde: ¿por qué outcome > transcript NO significa "ignora la trayectoria"?
Porque el outcome decide el veredicto pass/fail, pero la trayectoria decide el diagnóstico. Sin mirar la trayectoria del caso 2, nunca sabrías que Aurora escala de más en preguntas triviales. El outcome dice "salió bien"; la trayectoria dice "salió bien por suerte, gastando un ticket humano que no hacía falta". Una es para juzgar; la otra, para arreglar.
3.6Hazlo tú
Ejercicio 1 — andamiaje parcial
Un cliente pregunta "¿puedo devolver unas zapatillas usadas?". La trayectoria esperada es: consultar_politica con el tema correcto. El agente respondió de memoria, sin llamar a ninguna tool (la trace C de L1).
Completa el test case con los dos huecos:
1from deepeval.test_case import LLMTestCase, ToolCall
2
3caso = LLMTestCase(
4 input="¿Puedo devolver unas zapatillas usadas?",
5 actual_output="Sí, tienes hasta 90 días para devolverlas.",
6 tools_called=__________, # pista: ¿qué tools llamó la trace C?
7 expected_tools=[ToolCall(name="__________")], # pista: la que DEBÍA llamar
8)¿Qué score de ToolCorrectnessMetric esperas, y por qué? Piensa cuántas de las tools esperadas aparecen en las llamadas reales.
Ejercicio 2 — autónomo
Tienes una trayectoria de Aurora con outcome correcto pero sospechosa. El agente, para responder "¿está disponible la talla 42?", hizo: buscar_pedido("") → consultar_politica("tallas") → buscar_pedido("") → respondió bien.
Sin mirar la solución, escribe:
- Qué métrica delata el problema de argumentos y por qué.
- Qué métrica delata los pasos repetidos.
- Por qué pass^3 sería más exigente que pass@3 para confiar en este agente.
Antes de seguir, una pregunta de interrogación elaborativa. Respóndela tú primero: ¿por qué ToolCorrectnessMetric por defecto solo compara nombres, y cuándo necesitas activar la comprobación de argumentos?
Porque comparar nombres es determinista, barato y suficiente para detectar el fallo más común: llamar (o no) a la tool correcta. Activas la comprobación de argumentos cuando el nombre correcto no basta —por ejemplo, cuando un order_id inventado produce una respuesta plausible pero falsa—. El argumento es donde se esconde el fallo silencioso.
3.7Comprueba
Sin pistas. Aquí tienes una ejecución de Aurora. El cliente pregunta por una devolución; el agente responde la política correcta de 30 días. Outcome: correcto.
Su trayectoria fue:
1TRACE conv_91c2
2├─ tool consultar_politica(tema="devoluciones") -> "30 días, sin usar"
3├─ tool escalar_a_humano(motivo="duda de devolución") -> "ticket #6610"
4└─ respuesta "Tienes 30 días para devolverlo, sin usar."Responde dos cosas. ¿Qué métrica delata el problema de esta trayectoria? ¿Y por qué pass^k sería más exigente que pass@k para decidir si confías en este agente?
Ver la respuesta razonada
La métrica que lo delata es tool-call correctness (ToolCorrectnessMetric). La trayectoria esperada para una duda de política es consultar_politica. El agente la llamó —bien— pero añadió escalar_a_humano sin necesidad: la respuesta ya estaba en la KB. El outcome es correcto, así que un eval que solo mire el resultado aprobaría esta ejecución. La métrica de trayectoria no: hay una tool de más, y abrió un ticket humano que no hacía falta. Es el modo de fallo "escaló de más" de N1.
pass^k es más exigente porque exige consistencia. pass@k aprobaría si una de k ejecuciones evita el escalado innecesario. pass^k solo aprueba si las k lo evitan. Para confiar en producción, "a veces escala de más" no basta: quieres que nunca lo haga en este tipo de caso. pass^k mide eso.
Feedback formativo:
- Si nombraste tool-call correctness y explicaste el escalado de más: dominas la distinción central de la lección —outcome correcto no implica trayectoria correcta—. Reutilizarás esto en L5, donde la trayectoria es el primer paso del árbol de diagnóstico.
- Si dijiste "argument correctness": revisa la traza. Los argumentos aquí son correctos (
tema="devoluciones"es el adecuado). El problema no es con qué llamó, sino qué de más llamó: una tool sobrante. Vuelve a §3.5 y compara el caso 1 con el caso 2. - Si dijiste que la ejecución está bien porque el outcome es correcto: confundiste el veredicto con el diagnóstico. Outcome > transcript decide el pass/fail, pero no apaga la lectura de la trayectoria. Aquí el outcome aprueba y la trayectoria suspende: gastó un ticket humano de balde. Relee §3.4, "Outcome > transcript".
3.8Conecta
Vuelve a la trace C de las zapatillas: el agente que respondió "90 días" sin llamar a consultar_politica.
Con lo de esta lección, ese fallo ya no es invisible. ToolCorrectnessMetric lo marca al instante: la trayectoria esperada incluía consultar_politica, el agente no la llamó, score al suelo. El fallo de orquestación tiene, por fin, su medidor.
Ahora tienes los tres bloques de métricas del nivel:
- Retrieval — métricas IR (precision@k, recall@k, MRR, NDCG), de L3.
- Generación — la RAG triad (groundedness, answer relevance, context relevance), de L2.
- Trayectoria — tool-call y argument correctness, outcome > transcript, pass@k/pass^k, de esta lección.
¿Dónde lo aplicarías en tu trabajo? Piensa en cualquier agente con tools que hayas tocado. Cuando da una respuesta correcta, ¿sabes si llegó por la ruta que esperabas, o por una ruta cara y frágil que un día se romperá? Si no lo sabes, no estás evaluando la trayectoria.
En L5 unimos los tres bloques en un protocolo de diagnóstico. Ante un fallo end-to-end, ¿quién es el culpable: retrieval, generación u orquestación? El orden de lectura empieza por la trayectoria —lo que mediste hoy—, porque un fallo de orquestación hace irrelevante todo lo de aguas abajo.
3.9Reflexiona
Tómate dos minutos. Estas preguntas consolidan más que releer.
- Con tus palabras: ¿qué diferencia hay entre evaluar el outcome y evaluar la trayectoria de un agente?
- ¿Por qué outcome > transcript no equivale a "ignora la trayectoria"? Da un caso de Aurora donde el outcome aprueba y la trayectoria suspende.
- ¿Qué sigue sin estar claro? Si es "cómo combino estas métricas con la triad para señalar al culpable", es la pregunta correcta —la responde L5—.
Referencia rápida
- Tres niveles de eval de agentes: outcome (caja negra, ¿completó la tarea?) · trayectoria (plan, tool calls, args, orden) · componente (retrievers, tools, sub-agentes). (Confident AI; corpus D.4).
- Tool-call correctness: ¿llamó a las tools correctas? DeepEval
ToolCorrectnessMetric(por defecto, por nombre; conavailable_toolsañade eval LLM y toma elmin). RagasToolCallAccuracy/ToolCallF1(corpus D.3, D.2). - Argument correctness: ¿con los argumentos correctos? El
order_idreal vs. uno inventado. DeepEval víaevaluation_params; RagasToolCallAccuracycompara args (corpus D.3, D.2). - outcome > transcript: preferir el estado final sobre el guion de pasos; los agentes hallan rutas válidas no anticipadas (Claude Opus 4.5 / tau2-bench). No castigues el guion si el objetivo se logró; sigue leyendo la trayectoria para diagnosticar (corpus D.4, A.6).
- pass@k vs pass^k: pass@k = ≥1 de k correcta (¿puede?); pass^k = los k correctos (¿lo hace consistentemente?). pass^k es el listón duro (Anthropic; corpus D.4).
- Herramienta:
agentevalsde LangChain —create_trajectory_match_evaluatorcon modos strict / unordered / subset / superset (corpus D.4).