feat: deterministic trajectory assertions for agent tool-call evaluation - #56
Open
brainsparker wants to merge 1 commit into
Open
feat: deterministic trajectory assertions for agent tool-call evaluation#56brainsparker wants to merge 1 commit into
brainsparker wants to merge 1 commit into
Conversation
…luation New trajectory block on test cases asserts on the sequence of tool calls a model makes (require, forbid, order, min/max call budgets, no_repeat_calls) with zero LLM cost. Results surface in the run summary, JSON export, and JUnit XML (TrajectoryAssertionFailed), plus a --fail-on-trajectory CI gate. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this adds
Deterministic trajectory assertions for agent tool-call evaluation. A new
trajectoryblock on any test case checks the sequence of tool calls a model makes, with zero LLM cost:Five check types:
require(tool must be called, optionally with an argument subset),forbid(tool must never be called),order(tools must appear in relative order, subsequence match so other calls may interleave),min_calls/max_calls(step budgets,max_calls: 0asserts no tools were used), andno_repeat_calls(same tool with identical arguments twice fails, catching agent loops).Results are pure functions of the recorded calls: stable across runs, free to compute, and they run alongside or entirely without LLM-as-judge scoring.
How to use:
trajectoryblock to a test case (seeexamples/golden_sets/agent_trajectory.yaml)TrajectoryAssertionFailedfailures)--fail-on-trajectoryflag: exits 2 on any trajectory failure, costs nothing, never flakesWhy this, why now
Three signals from this week's market scan:
Judge cost and flakiness are the loudest 2026 eval complaints. LangSmith led with an 82 percent judge-cost reduction headline (Tuned Evaluators, Aug 18: https://www.langchain.com/blog/introducing-langsmith-tuned-evaluators-starting-with-perceived-error), and practitioners document DeepEval scores swinging 0.85 to 0.72 on identical data at temperature 0 (Jul 16: https://communities.stackinsight.net/community/llm-eval-frameworks/why-is-deepeval-producing-inconsistent-scores-on-same-data/). Deterministic checks sidestep both problems for the class of assertions that never needed a judge.
Agent trajectory evaluation is the consensus unsolved gap. The dominant practitioner pattern is hand-stitched deterministic unit tests for tool calls plus rubrics for overall quality, with no lightweight declarative format for the first half ("agents fail by multiplication", Aug 5: https://www.kunalganglani.com/blog/agent-evaluation-harness-replay). This PR gives PromptLens that declarative format.
CI judge spend is a practical blocker: roughly 3 to 8 dollars per PR for a 20-test suite run 5 times (Apr 9: https://blog.appxlab.io/2026/04/09/ai-agent-testing-cicd-pipeline/). A zero-cost gate lets teams run trajectory checks on every PR and reserve the judge for merges.
Runner-up candidates considered today: OTel
gen_ai.evaluation.resultspan emission for PromptLens (strong timing, promptfoo aligned Aug 26, but the convention is still marked Development and it adds a dependency), and a memory-import bridge for you.md (the repo already ships an MCP server, native exports, and a ChatGPT connector, so the researched gap was thinner than expected).Implementation notes
promptlens/models/trajectory.py(TrajectorySpec, TrajectoryEvaluation, validation that rejects empty specs and malformed order constraints),promptlens/evaluators/trajectory.py(pure evaluator, no network, no LLM)TestCase(new optionaltrajectoryfield),EvaluationResult(new optionaltrajectory_evaluation), the runner (checks run before judging so results exist even when the judge fails), the CLI (--fail-on-trajectory, summary line), and the JUnit exportertrajectoryblock, no new dependenciesexamples/golden_sets/agent_trajectory.yamlTest status
test_trajectory_evaluator.py,test_trajectory_spec_validation.py, andtest_junit_trajectory.pypromptlens validate examples/golden_sets/agent_trajectory.yamlpasses🤖 Generated with Claude Code