How to Evaluate AI Agents: Trajectory, Tool Calls, Task Completion (2026)

Khimananda Oli 13 min read Database, Virtualization
How to Evaluate AI Agents: Trajectory, Tool Calls, Task Completion (2026)

By Khimananda Oli | Last reviewed: October 2026

Evaluating an AI agent means scoring the path it took, not just the answer it gave — because a correct final answer can hide a wasteful loop, a wrong tool that happened not to matter, or a lucky recovery from an error a stricter judge would never excuse. Score tool-call correctness deterministically against an expected list, score task completion with an LLM judge comparing the goal to the outcome, and track step count and cost as a third, separate signal. Combining all three into one pass/fail number hides exactly the failure you built the eval to catch.

Why is evaluating an agent a different problem from evaluating an LLM's output?

To evaluate AI agents properly you need more than a single-turn eval. If you have already built evals for single-turn LLM responses — see how to evaluate LLM outputs — the instinct is to point the same machinery at an agent: capture the final answer, score it against a reference, done. That approach misses the part of an agent that actually breaks in production.

An agent is not one call; it is a sequence — the model picks a tool, the tool returns a result, the model decides what to do next, and the loop repeats until it produces a final answer. Two agents can reach the identical correct answer through completely different paths, and only one of those paths is the one you want running at scale:

  • The efficient path: three tool calls, each one informed by the last, reaching the answer in the minimum necessary steps.
  • The lucky path: nine tool calls, two of them wrong, one argument malformed and silently retried, the agent effectively guessing its way to a correct answer that an output-only eval scores as a perfect pass.

Score only the final answer and both paths look identical. The lucky path is the one that burns ten times the tokens, takes ten times as long, and — critically — is the one that fails differently and unpredictably the next time the same question is asked with slightly different phrasing. This is why agent evaluation decomposes into at least three separate measurements, each catching a failure mode the others cannot see.

Same answer, two very different pathsOutput-only evaluation scores both of these as a perfect passThe efficient path — 3 stepssearch_docsget_recordcompute_totalcorrect answer, 3 calls, 1.2sEvery tool call used the prior result. No retries, no dead ends.The lucky path — 9 steps, same final answersearch_docswrong_toolretry (bad args)get_recordredundant call... 4 more calls, one malformed argument silently retried ...same correct answer, 9 calls, 11.4s9x the latency, 9x the cost, same pass/fail score
Two agent trajectories reaching the same correct answer — only trajectory and tool-call evaluation can tell these apart, because output-only scoring cannot.

What does trajectory matching actually check?

Trajectory evaluation compares the sequence of tool calls an agent actually made against a reference sequence you define for the test case — no LLM judge required, which makes it fast, cheap and perfectly repeatable. Google's Agent Development Kit (ADK) defines this with three match strategies that are a clean mental model regardless of which framework you use:

Match typeRequirementUse when
ExactThe actual and expected tool calls match perfectly — no extra calls, none missing, same orderThe task has exactly one correct procedure, e.g. a fixed approval workflow
In-orderEvery expected call appears in the actual sequence in the same relative order, but other calls may appear between themSteps must happen in sequence, but the agent may legitimately check extra things along the way
Any-orderEvery expected call appears somewhere in the actual sequence, order unconstrainedA set of lookups must all happen, but which one happens first genuinely does not matter

Each tool call is compared by name and, optionally, by arguments — ADK's evaluator exposes an ignore_args option for exactly this, because sometimes you only care that get_customer_record was called at all, not whether it was called with customer_id=481 versus customer_id="481". Pick exact matching when the procedure itself is the thing under test; pick any-order when you only care that the right information was gathered.

How do you score tool-call correctness without writing your own matcher?

DeepEval's ToolCorrectnessMetric implements the same idea as a drop-in metric, comparing the tools an agent actually called against the ones you expected:

from deepeval.test_case import LLMTestCase, ToolCall
from deepeval.metrics import ToolCorrectnessMetric
from deepeval import evaluate

test_case = LLMTestCase(
    input="A customer wants a refund for order #4821.",
    actual_output="Refund of $42.00 has been issued for order #4821.",
    tools_called=[
        ToolCall(name="lookup_order",
                 input={"order_id": "4821"}),
        ToolCall(name="check_refund_eligibility"),
        ToolCall(name="issue_refund",
                 input={"order_id": "4821", "amount": 42.00}),
    ],
    expected_tools=[
        ToolCall(name="lookup_order"),
        ToolCall(name="check_refund_eligibility"),
        ToolCall(name="issue_refund"),
    ],
)

metric = ToolCorrectnessMetric(
    should_consider_ordering=True,  # like ADK's in-order match
    should_exact_match=False,       # names only, args ignored
)

evaluate(test_cases=[test_case], metrics=[metric])

should_consider_ordering and should_exact_match are the two levers worth understanding before you write a single test case. Leave both off for a loose, "did it touch the right tools" check during early development; turn both on once you are hardening a workflow where the sequence and the arguments genuinely matter — a payment flow is a reasonable candidate, a free-form research assistant usually is not.

How do you measure whether the agent actually finished the job?

Tool-call correctness tells you the agent used the right tools. It does not tell you the agent's final state is actually what the user asked for — an agent can call every expected tool in the right order and still fail to synthesize them into a complete answer, or stop one step early. That is what task completion metrics are for, and because "did this accomplish the goal" is a judgment call rather than a string comparison, this layer needs an LLM judge.

DeepEval's TaskCompletionMetric works directly from a trace rather than a single input/output pair — it extracts the task and the outcome from the full agent trajectory, then scores how well the outcome aligns with the task:

from deepeval.tracing import observe
from deepeval.metrics import TaskCompletionMetric
from deepeval.dataset import Golden
from deepeval import evaluate

@observe()
def refund_agent(user_input: str) -> str:
    # ... your agent's full tool-calling loop runs here ...
    return "Refund of $42.00 has been issued for order #4821."

metric = TaskCompletionMetric(
    threshold=0.7, model="gpt-4o", include_reason=True
)

goldens = [Golden(input="A customer wants a refund for order #4821.")]
evaluate(goldens=goldens, observed_callback=refund_agent, metrics=[metric])

Because this runs an LLM judge over the trace, give it a tighter rubric than "was this good" — the judge model should be told explicitly what counts as task completion for your domain (did the refund actually get issued, not just discussed), the same discipline covered generally in how to evaluate LLM outputs. A vague judge prompt produces a score that moves with the judge model's mood more than with the agent's actual behaviour, and it inherits every weakness of LLM-as-judge scoring — including the tendency to reward confident, well-formatted answers that are quietly wrong, which is exactly the failure mode covered in reducing LLM hallucinations.

Three layers, three different failures caughtRun them in this order — cheapest and most deterministic first1 · Trajectory match — no LLM, deterministicExact / in-order / any-order comparison against an expected tool sequenceCatches: wrong procedure, skipped steps, steps in the wrong orderCost: near zero. Run this on every single test case, every build.2 · Tool-call correctness — deterministic, name/argument levelWere the right tools called, with the right arguments, in the right order?Catches: wrong tool chosen, malformed arguments, redundant callsCost: near zero. Tighten ordering/exact-match as the workflow hardens.3 · Task completion — LLM judge over the full traceDid the outcome actually satisfy the user's goal, end to end?Catches: right tools used, but synthesis failed or goal unmetCost: a judge call per trace. Give it a tight, domain-specific rubric.
Agent evaluation as three layers of increasing cost and judgment: trajectory and tool-call checks are deterministic and cheap, task completion needs an LLM judge and a tight rubric.

What should you track alongside correctness?

A fourth dimension sits outside pass/fail entirely: efficiency. Two trajectories can both score a perfect 1.0 on trajectory match, tool correctness and task completion, and still differ by an order of magnitude in cost and latency — exactly the efficient-versus-lucky-path problem from the opening example, except now both paths are "correct" by every quality metric you have. Track these as their own time series, not folded into a pass/fail score:

  • Step count — the number of tool calls per successful trajectory. A sudden increase in the median, even with completion rate unchanged, usually means a tool's output format changed and the agent is now working around it.
  • Loop/retry count — how often the agent calls the same tool with near-identical arguments in succession. This is the signature of an agent that is confused rather than exploring, and it is invisible to a metric that only looks at the final trajectory.
  • Cost and latency per completed task — the metric that actually appears on your bill. If you are already instrumenting LLM calls per OpenTelemetry's GenAI semantic conventions, gen_ai.invoke_agent.duration and the per-tool gen_ai.execute_tool.duration give you exactly this, broken down by which step in the trajectory is slow.

How do you build a golden set to evaluate AI agents?

The same golden-set discipline that applies to RAG evaluation — see RAG evaluation metrics for the general approach — applies here with one addition: each test case needs an expected trajectory, not just an expected answer. For the refund example above that means recording not only "a $42 refund should be issued" but "the agent should call lookup_order, then check_refund_eligibility, then issue_refund, in that order." Writing that down is the part teams skip, and it is the part that makes trajectory and tool-call evaluation possible at all — without it you are back to scoring the final answer alone and losing the one thing agent evaluation exists to catch.

Stratify the set the same way you would for any eval: include cases with a single clear correct path, cases where more than one tool sequence legitimately reaches the right answer (use any-order matching for these), and — importantly — cases where the right behaviour is to call no tools at all, such as a question the agent should answer directly or decline. An agent that reaches for a tool on every input, including the ones that do not need one, is a real and common failure that only shows up if your golden set contains examples where the expected tool list is empty.

One golden test case, three layers of scoringWrite the expected trajectory once; every metric reads from itGolden test caseinput: "reset my password, I'm locked out"expected_tools: [verify_identity, reset_password]completion_rubric: "password is reset and theuser is told how to sign in again"Trajectory matchreads: expected_tools,their orderignores: arguments,the rubricTool correctnessreads: expected_tools,actual argumentsignores: the rubric,final wordingTask completionreads: completion_rubric,the full traceignores: whether the exactexpected tools were used
A single golden test case feeds all three evaluation layers, each reading a different part of the same record — write the trajectory and rubric once, score three ways.

What does a worked example of all three layers together look like?

Concreteness helps more than any abstract description. Take an internal IT-helpdesk agent that resolves "reset my password" and similar tickets, evaluated against three golden test cases after a prompt change intended to make it more cautious about irreversible actions.

Test caseTrajectory matchTool correctnessTask completionVerdict
Standard password resetExact: pass1.00.95Ship — behaves as before
Reset for a locked, high-privilege admin accountIn-order: pass1.00.40Tools correct, but the agent reset the account without the extra approval step the new prompt was meant to add — task completion catches what tool correctness could not
Ambiguous request needing clarificationAny-order: fail — called reset_password directly0.00.60Block — the agent should have called ask_clarifying_question first; it guessed instead and got a plausible-sounding but wrong answer

Each layer earns its place in this example. Trajectory matching alone would have shipped the regression in row two, since the expected tools were still called in a valid order — the extra approval step was simply never defined as part of the expected trajectory, so trajectory matching had no way to flag its absence. Tool correctness alone would have missed it for the same reason: every expected tool was present. Only task completion, scored against the explicit intent "irreversible admin actions require approval," caught that the agent had technically used the right tools while skipping the actual point of the prompt change. Row three shows the opposite pattern — trajectory and tool correctness both fail loudly and immediately, with no LLM judge required at all, because the agent simply called the wrong tool.

Where does this fit with safety evaluation?

Trajectory, tool-call and task-completion metrics answer "did the agent do its job well." They say nothing about whether it should have been allowed to take a given action at all — that is a permissions and approval question, covered in guardrails for autonomous AI agents and, for the specific case of an agent operating infrastructure, building an AI agent for Linux server administration. Run both kinds of evaluation. A trajectory that scores perfectly on correctness and efficiency but included a tool call your guardrails should have blocked is not a quality bug — it is the guardrail failing, and no amount of task-completion scoring will surface that; a deliberate adversarial pass, as in the hallucination-reduction and red-teaming work for LLM apps generally, is what finds it. If you are coordinating several agents rather than one, the trajectory question becomes which agent called which tool and in what order across the whole system, which is where multi-agent systems: patterns and pitfalls picks up.

If you have not built your first agent yet, what are AI agents: a practical introduction and building your first AI agent with tool use are the right starting point before any of this evaluation machinery is worth setting up — there is no trajectory to score until there is a working tool-calling loop to score it from.

If you want a harness built to evaluate AI agents properly — not just their final output — — golden trajectories, tool-correctness gates in CI, and task-completion judging with a rubric tuned to your domain — my DevOps and cloud consulting services cover exactly this.

Frequently Asked Questions

An LLM output eval scores one input-output pair. An agent takes multiple steps — tool calls, results, further decisions — before reaching an answer, and two agents can reach the identical correct answer through very different paths, one efficient and one wasteful or lucky. Output-only scoring cannot tell those apart.

Comparing the sequence of tool calls an agent actually made against a reference sequence defined for the test case. It requires no LLM judge, is fast and perfectly repeatable, and catches wrong procedures, skipped steps and out-of-order execution.

Exact match requires the actual and expected tool calls to match perfectly with nothing extra or missing. In-order allows other calls in between but keeps the expected calls in the same relative order. Any-order only requires every expected call to appear somewhere, regardless of sequence.

Compare the tools actually called against an expected list, by name and optionally by arguments. DeepEval's ToolCorrectnessMetric implements this directly, with should_consider_ordering and should_exact_match flags controlling how strict the comparison is.

Whether the agent's final state actually satisfies the user's goal, judged from its full execution trace rather than a single output. Unlike trajectory and tool-call checks, this needs an LLM judge, because "did this accomplish the goal" is a judgment call, not a string comparison.

Because success is defined by intent, not by an exact string match — an agent can call every right tool and still fail to synthesize a complete answer, or stop one step early. A deterministic comparison cannot capture that; it requires comparing the task to the outcome, which is a judgment task.

Yes. It can call every expected tool in the right order and still fail to combine the results into what the user actually asked for, or run far less efficiently than necessary. That is exactly why trajectory, tool-call correctness and task completion are scored as three separate metrics rather than one.

Each test case needs an expected tool trajectory, not just an expected final answer — without it, trajectory and tool-call evaluation are impossible. Include cases with one correct path, cases where multiple valid tool sequences exist, and cases where the correct behaviour is to call no tools at all.

Because an agent that reaches for a tool on every input, including ones that need no tool at all, is a common real failure. It only shows up in evaluation if the golden set contains examples where the expected tool list is genuinely empty.

Step count per successful trajectory, loop or retry count for the same tool called repeatedly with near-identical arguments, and cost and latency per completed task. Two trajectories can both pass every correctness metric and still differ by an order of magnitude in efficiency.

The GenAI semantic conventions define gen_ai.invoke_agent.duration for a full agent turn and gen_ai.execute_tool.duration per tool call, which together show which specific step in a trajectory is slow, broken out automatically if you already instrument LLM calls this way.

No. Trajectory, tool-call and task-completion metrics measure whether an agent did its job well; guardrails decide whether it should have been allowed to take an action at all. A trajectory can score perfectly on quality while including a call that safety controls should have blocked.

Google's Agent Development Kit (ADK) implements exact, in-order and any-order trajectory matching natively. DeepEval provides ToolCorrectnessMetric for deterministic tool-call scoring and TaskCompletionMetric for LLM-judged task completion over a full trace.

Depends on what you are testing. Comparing names only is looser and useful early in development; comparing arguments exactly is stricter and worth enabling once you are hardening a specific workflow where the precise parameters genuinely matter, such as a payment amount or an order ID.

Cheapest and most deterministic first: trajectory matching, then tool-call correctness, both near-instant and requiring no LLM. Run task completion's LLM-judge pass last, since it is the most expensive check and the one most worth saving for cases that already passed the deterministic layers.