From 4553280fe7c1b6ce8f2fd223b5ac60d1f1e393d6 Mon Sep 17 00:00:00 2001 From: Christopher Tso Date: Mon, 6 Jul 2026 03:53:50 +0200 Subject: [PATCH 1/2] docs(migration): align skill and trajectory assertions --- .../docs/docs/next/evaluation/batch-cli.mdx | 6 +- .../docs/docs/next/evaluation/examples.mdx | 37 +-- .../docs/docs/next/evaluation/rubrics.mdx | 2 +- .../docs/next/graders/tool-trajectory.mdx | 263 ------------------ .../next/graders/trajectory-assertions.mdx | 185 ++++++++++++ .../docs/next/guides/agent-eval-layers.mdx | 38 +-- .../docs/next/guides/evaluation-types.mdx | 2 +- .../guides/skill-improvement-workflow.mdx | 6 +- apps/web/src/content/docs/docs/next/index.mdx | 2 +- .../docs/next/reference/promptfoo-parity.mdx | 13 +- .../docs/next/reference/result-artifacts.mdx | 2 +- .../content/docs/docs/next/tools/prepare.mdx | 2 +- .../evals/multi-agent.eval.results.jsonl | 4 +- .../references/environment-adaptation.md | 6 +- 14 files changed, 249 insertions(+), 319 deletions(-) delete mode 100644 apps/web/src/content/docs/docs/next/graders/tool-trajectory.mdx create mode 100644 apps/web/src/content/docs/docs/next/graders/trajectory-assertions.mdx diff --git a/apps/web/src/content/docs/docs/next/evaluation/batch-cli.mdx b/apps/web/src/content/docs/docs/next/evaluation/batch-cli.mdx index 0a1854920..6c60e8d8b 100644 --- a/apps/web/src/content/docs/docs/next/evaluation/batch-cli.mdx +++ b/apps/web/src/content/docs/docs/next/evaluation/batch-cli.mdx @@ -111,9 +111,9 @@ JSONL where each line is a JSON object with an `id` matching a test: The `id` field must match the test `id` for AgentV to route output to the correct grader. -### Output with Tool Trajectory +### Output with Trajectory Assertions -To enable `tool-trajectory` evaluation, include `output` with `tool_calls`: +To enable `trajectory:*` assertions, include `output` with `tool_calls`: ```json { @@ -138,7 +138,7 @@ To enable `tool-trajectory` evaluation, include `output` with `tool_calls`: } ``` -AgentV extracts tool calls directly from `output[].tool_calls[]` for `tool-trajectory` graders. +AgentV extracts tool calls directly from `output[].tool_calls[]` for trajectory assertions. ## Grader Implementation diff --git a/apps/web/src/content/docs/docs/next/evaluation/examples.mdx b/apps/web/src/content/docs/docs/next/evaluation/examples.mdx index 1dc330aec..109d2d100 100644 --- a/apps/web/src/content/docs/docs/next/evaluation/examples.mdx +++ b/apps/web/src/content/docs/docs/next/evaluation/examples.mdx @@ -124,7 +124,7 @@ tests: See [`examples/features/file-transforms/`](../../../../../examples/features/file-transforms/) for a runnable end-to-end example with a file-producing target and custom grader target. -## Tool Trajectory +## Trajectory Assertions Validate that an agent uses specific tools during execution: @@ -139,11 +139,14 @@ tests: input: Research REST vs GraphQL assert: - name: research-check - type: tool-trajectory - mode: any_order - minimums: - knowledgeSearch: 2 - documentRetrieve: 1 + type: trajectory:tool-used + value: + name: knowledgeSearch + min: 2 + - type: trajectory:tool-used + value: + name: documentRetrieve + min: 1 # Validate exact tool sequence - id: auth-flow @@ -151,11 +154,12 @@ tests: input: Authenticate user assert: - name: auth-sequence - type: tool-trajectory - mode: exact - expected: - - tool: checkCredentials - - tool: generateToken + type: trajectory:tool-sequence + value: + mode: exact + steps: + - checkCredentials + - generateToken ``` ## Offline Grader Benchmark @@ -204,11 +208,12 @@ tests: input: Analyze trace assert: - name: trace-check - type: tool-trajectory - mode: in_order - expected: - - tool: webSearch - - tool: readFile + type: trajectory:tool-sequence + value: + mode: in_order + steps: + - webSearch + - readFile ``` ## Multi-Turn Conversation diff --git a/apps/web/src/content/docs/docs/next/evaluation/rubrics.mdx b/apps/web/src/content/docs/docs/next/evaluation/rubrics.mdx index a76cbb2d7..d0cd7b67f 100644 --- a/apps/web/src/content/docs/docs/next/evaluation/rubrics.mdx +++ b/apps/web/src/content/docs/docs/next/evaluation/rubrics.mdx @@ -199,7 +199,7 @@ assert: - The agent used Read to inspect the config file before editing ``` -This is a lightweight alternative to the `skill-trigger` evaluator when you want to check tool usage with natural-language criteria. +Use this for qualitative tool-use checks. Use `skill-used`, `not-skill-used`, or `trajectory:*` assertions when the requirement can be deterministic. ## Combining with Other Graders diff --git a/apps/web/src/content/docs/docs/next/graders/tool-trajectory.mdx b/apps/web/src/content/docs/docs/next/graders/tool-trajectory.mdx deleted file mode 100644 index ddc84d2be..000000000 --- a/apps/web/src/content/docs/docs/next/graders/tool-trajectory.mdx +++ /dev/null @@ -1,263 +0,0 @@ ---- -title: Tool Trajectory Graders -description: Validate that agents use the right tools in the right order with argument matching and latency assertions. -sidebar: - order: 5 -slug: docs/graders/tool-trajectory ---- - -Tool trajectory graders validate that an agent used the expected tools during execution. They work with trace data returned by agent providers (codex, vscode, cli with trace support). - -`tool-trajectory` is an AgentV extension over AgentV-normalized transcripts and trace summaries. Promptfoo's `trajectory:*`, `tool-call-f1`, `skill-used`, and `trace-*` assertion names are not aliases for this grader; AgentV rejects them until their trace semantics are implemented directly. - -## Modes - -### `any_order` — Minimum Tool Counts - -Validates that each tool was called at least N times, regardless of order: - -```yaml -assert: - - name: tool-usage - type: tool-trajectory - mode: any_order - minimums: - knowledgeSearch: 2 # Must be called at least twice - documentRetrieve: 1 # Must be called at least once -``` - -Use `any_order` when you want to ensure required tools are used but don't care about execution order. - -### `in_order` — Sequential Matching - -Validates tools appear in the expected sequence, but allows gaps (other tools can appear between expected ones): - -```yaml -assert: - - name: workflow-sequence - type: tool-trajectory - mode: in_order - expected: - - tool: fetchData - - tool: validateSchema - - tool: transformData - - tool: saveResults -``` - -Use `in_order` when you need to verify logical workflow order while allowing the agent to use additional helper tools between steps. - -### `exact` — Strict Sequence Match - -Validates the exact tool sequence with no gaps or extra tools: - -```yaml -assert: - - name: auth-sequence - type: tool-trajectory - mode: exact - expected: - - tool: checkCredentials - - tool: generateToken - - tool: auditLog -``` - -Use `exact` for security-critical workflows, strict protocol validation, or regression testing specific behavior. - -## Argument Matching - -For `in_order` and `exact` modes, you can optionally validate tool arguments: - -```yaml -assert: - - name: search-validation - type: tool-trajectory - mode: in_order - expected: - # Partial match — only specified keys are checked - - tool: search - args: { query: "machine learning" } - - # Skip argument validation for this tool - - tool: process - args: any - - # No args field = no argument validation (same as args: any) - - tool: saveResults -``` - -| Syntax | Behavior | -|--------|----------| -| `args: { key: value }` | Partial deep equality — only specified keys are checked | -| `args: any` | Skip argument validation | -| No `args` field | Same as `args: any` | - -## Latency Assertions - -For `in_order` and `exact` modes, you can validate per-tool timing with `max_duration_ms`: - -```yaml -assert: - - name: perf-check - type: tool-trajectory - mode: in_order - expected: - - tool: Read - max_duration_ms: 100 # Must complete within 100ms - - tool: Edit - max_duration_ms: 500 # Allow 500ms for edits - - tool: Write # No timing requirement -``` - -Each `max_duration_ms` assertion counts as a separate scoring aspect. The rules: - -| Condition | Result | -|-----------|--------| -| `actual_duration <= max_duration_ms` | Pass (assertion entry with `passed: true`) | -| `actual_duration > max_duration_ms` | Fail (assertion entry with `passed: false`) | -| No `duration_ms` in trace output | Warning logged, neutral (no assertion entry) | - -Set generous thresholds to avoid flaky tests from timing variance. Only add latency assertions where timing matters on critical paths. - -## Scoring - -| Mode | Score Calculation | -|------|------------------| -| `any_order` | (tools meeting minimum) / (total tools with minimums) | -| `in_order` | (passed assertions) / (total assertions) | -| `exact` | (passed assertions) / (total assertions) | - -Example: 3 expected tools with 2 latency assertions = 5 total assertion entries scored. - -## Trace Data Format - -Tool trajectory graders require trace data from the agent provider. Providers return `output` containing `tool_calls`: - -```json -{ - "id": "eval-001", - "output": [ - { - "role": "assistant", - "content": "I'll search for information about this topic.", - "tool_calls": [ - { - "tool": "knowledgeSearch", - "input": { "query": "REST vs GraphQL" }, - "output": { "results": [] }, - "id": "call_123", - "timestamp": "2024-01-15T10:30:00Z", - "duration_ms": 45 - } - ] - } - ] -} -``` - -The grader extracts tool calls from `output[].tool_calls[]`. The `tool` and `input` fields are required. Optional fields: - -- `id` and `timestamp` — for debugging -- `duration_ms` — required if using `max_duration_ms` latency assertions - -### Supported Providers - -- **codex** — returns `output` via JSONL log events -- **vscode / vscode-insiders** — returns `output` from Copilot execution -- **cli** — returns `output` with `tool_calls` - -## CLI Options - -```bash -# Write trace files to disk -agentv eval evals/test.yaml --dump-traces - -# Include full trace in result output -agentv eval evals/test.yaml --include-trace -``` - -Use `--dump-traces` to inspect actual traces and understand agent behavior before writing graders. - -## Complete Examples - -### Research Agent Validation - -```yaml -description: Validate research agent tool usage -target: codex_agent - -tests: - - id: comprehensive-research - criteria: Agent thoroughly researches the topic - - input: Research machine learning frameworks - - assert: - # Check minimum tool usage - - name: coverage - type: tool-trajectory - mode: any_order - minimums: - webSearch: 1 - documentRead: 2 - noteTaking: 1 - - # Check workflow order - - name: workflow - type: tool-trajectory - mode: in_order - expected: - - tool: webSearch - - tool: documentRead - - tool: summarize -``` - -### Multi-Step Pipeline - -```yaml -tests: - - id: data-pipeline - criteria: Process data through complete pipeline - - input: Process the customer dataset - - assert: - - name: pipeline-check - type: tool-trajectory - mode: exact - expected: - - tool: loadData - - tool: validate - - tool: transform - - tool: export -``` - -### Pipeline with Latency Assertions - -```yaml -tests: - - id: data-pipeline-perf - criteria: Process data within timing budgets - - input: Process the customer dataset quickly - - assert: - - name: pipeline-perf - type: tool-trajectory - mode: in_order - expected: - - tool: loadData - max_duration_ms: 1000 # Network fetch within 1s - - tool: validate # No timing requirement - - tool: transform - max_duration_ms: 500 # Transform must be fast - - tool: export - max_duration_ms: 200 # Export should be quick -``` - -## Best Practices - -1. **Start with `any_order`**, then tighten to `in_order` or `exact` as needed. -2. **Combine with other graders** — use tool trajectory for execution validation and LLM graders for output quality. -3. **Inspect traces first** with `--dump-traces` to understand agent behavior before writing graders. -4. **Use generous latency thresholds** to avoid flaky tests from timing variance. -5. **Use script graders for custom validation** — write custom tool validation scripts when built-in modes are insufficient. diff --git a/apps/web/src/content/docs/docs/next/graders/trajectory-assertions.mdx b/apps/web/src/content/docs/docs/next/graders/trajectory-assertions.mdx new file mode 100644 index 000000000..dea6451b6 --- /dev/null +++ b/apps/web/src/content/docs/docs/next/graders/trajectory-assertions.mdx @@ -0,0 +1,185 @@ +--- +title: Trajectory Assertions +description: Validate tool usage, tool order, arguments, step counts, and goal completion from agent traces. +sidebar: + order: 5 +slug: docs/graders/trajectory-assertions +--- + +Trajectory assertions validate that an agent used expected tools during execution. They read AgentV-normalized traces from agent providers such as Codex, Copilot, and CLI targets with trace support. + +Use Promptfoo-compatible assertion names for authored eval YAML: + +- `trajectory:tool-used` +- `trajectory:tool-sequence` +- `trajectory:tool-args-match` +- `trajectory:step-count` +- `trajectory:goal-success` + +## Tool Usage + +Use `trajectory:tool-used` to require one or more tool calls. The `value` can be a string, an array of tool names, or an object with `name` or `pattern` plus optional `min` and `max` counts. + +```yaml +assert: + - name: tool-usage + type: trajectory:tool-used + value: + name: knowledgeSearch + min: 2 + - type: trajectory:tool-used + value: + name: documentRetrieve + min: 1 +``` + +Use one assertion per required tool when each tool needs its own count. + +To forbid tool usage, invert `trajectory:tool-used`: + +```yaml +assert: + - name: no-delete + type: not-trajectory:tool-used + value: deleteFile +``` + +## Tool Sequence + +Use `trajectory:tool-sequence` when tool order matters. `mode: in_order` allows unrelated calls between expected steps. `mode: exact` requires the observed tool sequence to match exactly. + +```yaml +assert: + - name: workflow-sequence + type: trajectory:tool-sequence + value: + mode: in_order + steps: + - fetchData + - validateSchema + - transformData + - saveResults +``` + +```yaml +assert: + - name: auth-sequence + type: trajectory:tool-sequence + value: + mode: exact + steps: + - checkCredentials + - generateToken + - auditLog +``` + +## Argument Matching + +Use `trajectory:tool-args-match` to check arguments for a matching tool call. `mode: partial` checks only the specified keys. `mode: exact` compares the complete argument object, with optional `defaults` and `ignore` fields for known runtime-added values. + +```yaml +assert: + - name: search-validation + type: trajectory:tool-args-match + value: + name: search + args: + query: machine learning + mode: partial +``` + +## Step Counts + +Use `trajectory:step-count` to budget observed trajectory steps. The `type` field can target `tool`, `command`, `message`, `reasoning`, `search`, or `span` steps. + +```yaml +assert: + - name: bounded-tools + type: trajectory:step-count + value: + type: tool + min: 1 + max: 8 +``` + +## Goal Success + +Use `trajectory:goal-success` when the final answer and trace together need LLM judgment. Configure an LLM grader target in the eval so AgentV can judge whether the observed trajectory achieved the goal. + +```yaml +assert: + - name: goal + type: trajectory:goal-success + value: + goal: Find the order and compose a customer reply +``` + +## Complete Examples + +### Research Agent Validation + +```yaml +description: Validate research agent tool usage +target: codex_agent + +tests: + - id: comprehensive-research + criteria: Agent thoroughly researches the topic + + input: Research machine learning frameworks + + assert: + # Check minimum tool usage + - name: coverage + type: trajectory:tool-used + value: + name: webSearch + min: 1 + - type: trajectory:tool-used + value: + name: documentRead + min: 2 + - type: trajectory:tool-used + value: + name: noteTaking + min: 1 + + # Check workflow order + - name: workflow + type: trajectory:tool-sequence + value: + mode: in_order + steps: + - webSearch + - documentRead + - summarize +``` + +### Multi-Step Pipeline + +```yaml +tests: + - id: data-pipeline + criteria: Process data through complete pipeline + + input: Process the customer dataset + + assert: + - name: pipeline-check + type: trajectory:tool-sequence + value: + mode: exact + steps: + - loadData + - validate + - transform + - export +``` + +## Best Practices + +1. **Start with `trajectory:tool-used`**, then tighten to `trajectory:tool-sequence` when order matters. +2. **Use one assertion per independent requirement** so failure output points to the exact missing tool or argument. +3. **Combine with other graders**: use trajectory assertions for execution validation and `llm-rubric` for output quality. +4. **Inspect traces first** with run artifacts or prepared trace files to understand agent behavior before writing assertions. +5. **Use script assertions for custom validation** when built-in trajectory assertions are not expressive enough. diff --git a/apps/web/src/content/docs/docs/next/guides/agent-eval-layers.mdx b/apps/web/src/content/docs/docs/next/guides/agent-eval-layers.mdx index bcb043c8a..7efffeb07 100644 --- a/apps/web/src/content/docs/docs/next/guides/agent-eval-layers.mdx +++ b/apps/web/src/content/docs/docs/next/guides/agent-eval-layers.mdx @@ -41,28 +41,30 @@ Covers tool call correctness, argument validity, execution path, and redundancy. | Concern | AgentV grader | |---------|-----------------| -| Tool sequence | `tool-trajectory` (`in_order`, `exact`) | -| Minimum tool usage | `tool-trajectory` (`any_order`) | -| Argument correctness | `tool-trajectory` with `args` matching | +| Tool sequence | `trajectory:tool-sequence` (`in_order`, `exact`) | +| Minimum tool usage | `trajectory:tool-used` | +| Argument correctness | `trajectory:tool-args-match` | | Custom validation logic | `script` | ```yaml # Layer 2: Action — verify the agent called the right tools assert: - name: tool-sequence - type: tool-trajectory - mode: in_order - expected: - - tool: searchDocs - - tool: readFile - - tool: applyEdit + type: trajectory:tool-sequence + value: + mode: in_order + steps: + - searchDocs + - readFile + - applyEdit - name: arg-check - type: tool-trajectory - mode: any_order - minimums: - searchDocs: 1 - readFile: 1 + type: trajectory:tool-args-match + value: + name: searchDocs + args: + query: payment retry policy + mode: partial ``` ## Layer 3: End-to-End @@ -154,10 +156,10 @@ tests: # Layer 2: Action - name: tool-usage - type: tool-trajectory - mode: any_order - minimums: - search: 1 + type: trajectory:tool-used + value: + name: search + min: 1 # Layer 3: End-to-End - name: correct-answer diff --git a/apps/web/src/content/docs/docs/next/guides/evaluation-types.mdx b/apps/web/src/content/docs/docs/next/guides/evaluation-types.mdx index 7851f03e8..16bad0def 100644 --- a/apps/web/src/content/docs/docs/next/guides/evaluation-types.mdx +++ b/apps/web/src/content/docs/docs/next/guides/evaluation-types.mdx @@ -65,7 +65,7 @@ AgentV's eval tooling is designed for **execution quality**: - **`EVAL.yaml`** — define test cases with inputs, expected outputs, and assertions - **Agent Skills `evals.json` adapter** — run lightweight skill evaluation datasets directly or convert them into AgentV YAML - **`agentv eval`** — execute evaluations and collect results -- **Graders** — `llm-rubric`, `script`, `tool-trajectory`, `contains`, `regex`, and others all measure execution behavior +- **Graders** — `llm-rubric`, `script`, `trajectory:*`, `contains`, `regex`, and others all measure execution behavior These tools assume the skill is already loaded and invoked. They measure what happens *after* routing, not the routing decision itself. diff --git a/apps/web/src/content/docs/docs/next/guides/skill-improvement-workflow.mdx b/apps/web/src/content/docs/docs/next/guides/skill-improvement-workflow.mdx index cd760d76e..8994ab1ef 100644 --- a/apps/web/src/content/docs/docs/next/guides/skill-improvement-workflow.mdx +++ b/apps/web/src/content/docs/docs/next/guides/skill-improvement-workflow.mdx @@ -217,7 +217,7 @@ Keep your baseline stable across iterations. Only re-run the baseline when the t ## Graduating to EVAL.yaml -When `evals.json` is your starting point, you can run it directly for quick checks. Convert it to EVAL.yaml before using AgentV's workspace isolation, script graders, tool trajectory checks, or multi-turn conversations: +When `evals.json` is your starting point, you can run it directly for quick checks. Convert it to EVAL.yaml before using AgentV's workspace isolation, script graders, trajectory assertions, or multi-turn conversations: ```bash agentv eval evals.json --target claude @@ -258,7 +258,7 @@ After converting, you can: - Replace `llm-rubric` assertions with faster deterministic graders (`contains`, `regex`, `equals`) - Add `workspace` configuration for file-system isolation - Use `script` for custom scoring logic -- Define `tool-trajectory` assertions to check tool usage patterns +- Define `skill-used`, `not-skill-used`, or `trajectory:*` assertions to check tool usage patterns See [Agent Skills evals.json Adapter](/docs/integrations/agent-skills-evals/) for the full field mapping and side-by-side comparison. @@ -328,7 +328,7 @@ Start simple and add complexity only when the evaluation results demand it: 1. **Start with EVAL.yaml** — 5-10 test cases, natural-language checks 2. **Add deterministic checks** — when you find assertions that can be exact (`contains`, `regex`) 3. **Run or convert existing `evals.json`** — when Agent Skills tooling owns the source file -4. **Add tool trajectory checks** — when tool usage patterns matter +4. **Add trajectory assertions** — when tool usage patterns matter 5. **Use rubrics** — when you need weighted, structured scoring criteria ## Automated Iteration diff --git a/apps/web/src/content/docs/docs/next/index.mdx b/apps/web/src/content/docs/docs/next/index.mdx index e7e69c59a..c36b25e8e 100644 --- a/apps/web/src/content/docs/docs/next/index.mdx +++ b/apps/web/src/content/docs/docs/next/index.mdx @@ -52,7 +52,7 @@ Use this topic map when you are an AI agent trying to decide which primitive or | Create a first eval | [Quickstart](/docs/getting-started/quickstart/) → [Eval files](/docs/evaluation/eval-files/) | Defines the smallest runnable YAML shape before adding advanced fields. | | Translate Promptfoo-style evals | [Promptfoo parity matrix](/docs/reference/promptfoo-parity/) → [Eval files](/docs/evaluation/eval-files/) | Shows which prompt, test, vars, target, assertion, and runtime-option fields align directly and which AgentV fields are intentional extensions. | | Choose graders | [Rubrics](/docs/evaluation/rubrics/) → [Script graders](/docs/graders/script-graders/) → [LLM graders](/docs/graders/llm-rubrics/) | Keeps deterministic checks, rubric scoring, and LLM judgment separate. | -| Evaluate tool use or agents | [Tool trajectory](/docs/graders/tool-trajectory/) → [Coding agents](/docs/targets/coding-agents/) → [CLI provider](/docs/targets/cli-provider/) | Shows how targets, transcripts, and tool-call assertions compose. | +| Evaluate tool use or agents | [Trajectory assertions](/docs/graders/trajectory-assertions/) → [Coding agents](/docs/targets/coding-agents/) → [CLI provider](/docs/targets/cli-provider/) | Shows how targets, transcripts, and tool-call assertions compose. | | Share and inspect results | [Result artifact contract](/docs/reference/result-artifacts/) → [Results](/docs/tools/results/) → [Dashboard](/docs/tools/dashboard/) | Explains canonical run bundles, local artifacts, reports, remote result repositories, and Dashboard review flows. | | Compare runs | [Compare](/docs/tools/compare/) → [Dashboard Analytics](/docs/tools/dashboard/#analytics) | Use CLI metrics for automation and Dashboard analytics for interactive inspection. | | Govern or improve an agent workflow | [Agent eval layers](/docs/guides/agent-eval-layers/) → [Skill improvement workflow](/docs/guides/skill-improvement-workflow/) → [Enterprise governance](/docs/guides/enterprise-governance/) | Moves from primitive eval design to iterative agent improvement and governance checks. | diff --git a/apps/web/src/content/docs/docs/next/reference/promptfoo-parity.mdx b/apps/web/src/content/docs/docs/next/reference/promptfoo-parity.mdx index 14163ce00..d004f34da 100644 --- a/apps/web/src/content/docs/docs/next/reference/promptfoo-parity.mdx +++ b/apps/web/src/content/docs/docs/next/reference/promptfoo-parity.mdx @@ -49,8 +49,9 @@ implements equivalent semantics directly. | Deterministic assertion vocabulary | Common Promptfoo types include `contains`, `icontains`, `contains-any`, `contains-all`, `starts-with`, `regex`, `is-json`, `equals`, `latency`, `cost`, `javascript`, `python`, `webhook`, `similar`, and `llm-rubric`. | AgentV accepts the implemented overlap, including `contains`, `icontains`, `contains-any`, `contains-all`, `starts-with`, `regex`, `is-json`, `equals`, `latency`, `cost`, `javascript`, `python`, `webhook`, `similar`, and `llm-rubric`. | Align with Promptfoo | Unsupported Promptfoo assertion names error instead of silently becoming custom assertion names. | | Custom assertion terminology | Promptfoo calls normal eval custom logic assertions, with fixed code assertion types such as `javascript`, `python`, `ruby`, and `webhook`. | `defineAssertion()` files in `.agentv/assertions/` become reusable assertion type names. | Keep AgentV extension | AgentV keeps assertion terminology and extends discovery to arbitrary assertion type names such as `has-citation`. | | Script/custom grader terminology | Promptfoo custom code assertions are still assertion types. | `defineScriptGrader()` powers command-backed graders referenced with `type: script` and `command:`. | Keep AgentV divergence | Use script grader wording only for command-backed or LLM-backed scoring components that need explicit score and assertion-result control. | -| Tool and trace assertions | Promptfoo includes `trajectory:tool-used`, `trajectory:tool-sequence`, `trajectory:tool-args-match`, `trajectory:step-count`, `trajectory:goal-success`, `tool-call-f1`, `skill-used`, `trace-span-count`, `trace-span-duration`, and `trace-error-spans`. | AgentV rejects those names until their semantics are implemented directly. | Defer/future-scope | These names are not aliases for AgentV's `tool-trajectory` grader. | -| Tool trajectory grader | No direct Promptfoo alias for AgentV-normalized transcript semantics. | `type: tool-trajectory`. | Keep AgentV extension | This is AgentV-specific and operates over AgentV-normalized transcripts and trace summaries. | +| Skill assertions | Promptfoo includes `skill-used` for checking whether an agent invoked a named skill. | `type: skill-used` and `type: not-skill-used` with `value: ` or a matcher object. | Align with Promptfoo | AgentV evaluates these against normalized tool-call and skill-use trace data. | +| Trajectory assertions | Promptfoo includes `trajectory:tool-used`, `trajectory:tool-sequence`, `trajectory:tool-args-match`, `trajectory:step-count`, and `trajectory:goal-success`. | AgentV accepts the same assertion names over AgentV-normalized traces. | Align with Promptfoo | Use these for tool presence, order, argument checks, step budgets, and LLM-judged goal success. | +| Other Promptfoo trace assertions | Promptfoo also includes `tool-call-f1`, `trace-span-count`, `trace-span-duration`, and `trace-error-spans`. | Not accepted yet. | Defer/future-scope | Use `script` assertions or `execution-metrics` when current AgentV primitives cover the requirement. | | Coding-agent testbeds | Promptfoo normal evals do not define a typed coding-agent testbed primitive. | `environment`, usually inline or `environment: file://...`, plus distinct top-level `env` and lifecycle `extensions`. | Keep AgentV extension | `environment` is an AgentV extension informed by Margin local-agent ergonomics and Harbor/Terminal-Bench Docker substrate evidence. Use it for host/Docker workdir, setup argv, fixtures, services, and repo materialization. Use top-level `env` for provider/eval variables and `extensions` for lifecycle hooks. | | Run artifacts and inspection | Promptfoo owns its own result viewer and output formats. | AgentV writes `.agentv/results//` bundles with `summary.json`, `.internal/index.jsonl`, sidecars, and local Dashboard support. | Keep AgentV extension | AgentV-owned bundles are the source of truth for compare, Dashboard, CI, and adapters. Phoenix is link-out correlation only through safe external trace metadata. | | Compare command | Promptfoo has its own result comparison surfaces. | `agentv results compare `. | Keep AgentV extension | Compare consumes completed AgentV run indexes such as `.agentv/results//.internal/index.jsonl`. | @@ -121,10 +122,10 @@ tests: task: Update the refund policy handler. expected_output: The handler supports the damaged-item exception. assert: - - type: tool-trajectory - mode: any_order - minimums: - shell: 1 + - type: trajectory:tool-used + value: + name: shell + min: 1 - type: script command: [bun, run, graders/check-refund-policy.ts] ``` diff --git a/apps/web/src/content/docs/docs/next/reference/result-artifacts.mdx b/apps/web/src/content/docs/docs/next/reference/result-artifacts.mdx index a04748195..41e8f4b06 100644 --- a/apps/web/src/content/docs/docs/next/reference/result-artifacts.mdx +++ b/apps/web/src/content/docs/docs/next/reference/result-artifacts.mdx @@ -104,7 +104,7 @@ reserved for rebuildable local state and are skipped by run discovery. | `target-execution.json` | Provider-neutral target runtime envelope, including command, cwd, timeout, exit code or signal, error kind, timestamps, log truncation metadata, and artifact paths. | Distinguishing target task failures, target crashes, timeouts, cancellation, malformed provider output, and sandbox/runner failures from AgentV orchestrator failures. | | `stdout.txt` / `stderr.txt` | Captured target process logs when the runtime exposes them, with truncation metadata recorded in `target-execution.json`. | Debugging crashed, timed-out, cancelled, or malformed target runs without treating raw logs as the canonical row index. | | `outputs/file_changes.diff` | Full unified diff of workspace file changes when file changes are captured. | Human review and external artifact inspection; LLM and script graders still receive the same full diff through `file_changes`. | -| `transcript.json` | AgentV-normalized transcript/timeline document with canonical `tool_name` values and `transcript_summary`. | Portable human review, transcript-aware graders, and tool-trajectory analysis. | +| `transcript.json` | AgentV-normalized transcript/timeline document with canonical `tool_name` values and `transcript_summary`. | Portable human review, transcript-aware graders, and trajectory assertion analysis. | | `transcript-raw.jsonl` | Native provider or harness evidence when available. | Parser debugging, forensic review, and preserving source bytes without making provider schemas public AgentV fields. | | `test/` | Generated test bundle for the exact eval slice and target settings that produced a row. | Audit, external review, and rerun workflows that should not depend on a mutable source checkout. | | `artifact_pointers` | Offload indirection for large detached payload bytes. | Finding payloads published outside the primary metadata/control-plane branch, such as transcript bytes on `agentv/artifacts/v1`. | diff --git a/apps/web/src/content/docs/docs/next/tools/prepare.mdx b/apps/web/src/content/docs/docs/next/tools/prepare.mdx index b994c7b95..5e6c1edbc 100644 --- a/apps/web/src/content/docs/docs/next/tools/prepare.mdx +++ b/apps/web/src/content/docs/docs/next/tools/prepare.mdx @@ -65,7 +65,7 @@ Supported `--trace` inputs: | `agentv.trace.v1` JSON or JSONL | Explicit trace replay/export files | | AgentV transcript JSONL | `agentv import claude`, `agentv import codex`, or `agentv import copilot` output | -Single-record trace files are accepted directly. Multi-record files are matched by `test_id` and target. The selected trace is projected into AgentV's normal `trace` and `messages` grader context, so `tool-trajectory`, execution-metrics, and script graders receive the same shape they see during eval runs. +Single-record trace files are accepted directly. Multi-record files are matched by `test_id` and target. The selected trace is projected into AgentV's normal `trace` and `messages` grader context, so `trajectory:*`, execution-metrics, and script graders receive the same shape they see during eval runs. Use `--response` when the final answer text should be graded independently of the trace. If `--response` is omitted and the trace contains an assistant message with content, AgentV uses the last assistant message as the candidate answer. diff --git a/examples/features/trace-analysis/evals/multi-agent.eval.results.jsonl b/examples/features/trace-analysis/evals/multi-agent.eval.results.jsonl index cc2f21e75..6c0f9b744 100644 --- a/examples/features/trace-analysis/evals/multi-agent.eval.results.jsonl +++ b/examples/features/trace-analysis/evals/multi-agent.eval.results.jsonl @@ -1,5 +1,5 @@ -{"timestamp": "2026-02-22T10:00:01.000Z", "test_id": "research-question", "suite": "multi-agent", "score": 0.75, "target": "gpt-4o", "scores": [{"name": "response_quality", "type": "llm_grader", "score": 0.75}, {"name": "routing_accuracy", "type": "tool_trajectory", "score": 1.0}, {"name": "step_efficiency", "type": "execution_metrics", "score": 1.0}], "trace": {"event_count": 8, "tool_names": ["Read", "WebSearch", "tavily_search", "write_report"], "tool_calls_by_name": {"Read": 2, "WebSearch": 3, "tavily_search": 2, "write_report": 1}, "error_count": 0, "token_usage": {"input": 8500, "output": 1667}, "cost_usd": 0.105, "duration_ms": 15080, "llm_call_count": 4, "tool_durations": {"Read": [120, 85], "WebSearch": [2100, 1800, 2200], "tavily_search": [3460, 2100], "write_report": [450]}}, "output": [{"role": "assistant", "content": "I'll research this question by searching multiple sources.", "tool_calls": [{"tool": "WebSearch", "input": {"query": "latest findings on topic"}, "duration_ms": 2100}, {"tool": "WebSearch", "input": {"query": "recent papers 2025 topic"}, "duration_ms": 1800}], "duration_ms": 2360, "token_usage": {"input": 2498, "output": 312}}, {"role": "assistant", "content": "Let me dig deeper with specialized search.", "tool_calls": [{"tool": "tavily_search", "input": {"query": "deep dive topic analysis"}, "duration_ms": 3460}], "duration_ms": 2570, "token_usage": {"input": 1357, "output": 245}}, {"role": "assistant", "content": "Now reading the key documents.", "tool_calls": [{"tool": "Read", "input": {"file": "doc1.pdf"}, "duration_ms": 120}, {"tool": "Read", "input": {"file": "doc2.pdf"}, "duration_ms": 85}, {"tool": "tavily_search", "input": {"query": "supplementary data"}, "duration_ms": 2100}], "duration_ms": 3890, "token_usage": {"input": 3701, "output": 567}}, {"role": "assistant", "content": "Here is my comprehensive research report covering the key findings from multiple sources...", "tool_calls": [{"tool": "write_report", "input": {"title": "Research Summary"}, "duration_ms": 450}], "duration_ms": 2800, "token_usage": {"input": 2611, "output": 543}}], "assertions": [{"text": "Provides relevant research findings", "passed": true}, {"text": "Cites multiple sources", "passed": true}, {"text": "Missing critical source from 2025", "passed": false}]} +{"timestamp": "2026-02-22T10:00:01.000Z", "test_id": "research-question", "suite": "multi-agent", "score": 0.75, "target": "gpt-4o", "scores": [{"name": "response_quality", "type": "llm_grader", "score": 0.75}, {"name": "routing_accuracy", "type": "trajectory:tool-sequence", "score": 1.0}, {"name": "step_efficiency", "type": "execution_metrics", "score": 1.0}], "trace": {"event_count": 8, "tool_names": ["Read", "WebSearch", "tavily_search", "write_report"], "tool_calls_by_name": {"Read": 2, "WebSearch": 3, "tavily_search": 2, "write_report": 1}, "error_count": 0, "token_usage": {"input": 8500, "output": 1667}, "cost_usd": 0.105, "duration_ms": 15080, "llm_call_count": 4, "tool_durations": {"Read": [120, 85], "WebSearch": [2100, 1800, 2200], "tavily_search": [3460, 2100], "write_report": [450]}}, "output": [{"role": "assistant", "content": "I'll research this question by searching multiple sources.", "tool_calls": [{"tool": "WebSearch", "input": {"query": "latest findings on topic"}, "duration_ms": 2100}, {"tool": "WebSearch", "input": {"query": "recent papers 2025 topic"}, "duration_ms": 1800}], "duration_ms": 2360, "token_usage": {"input": 2498, "output": 312}}, {"role": "assistant", "content": "Let me dig deeper with specialized search.", "tool_calls": [{"tool": "tavily_search", "input": {"query": "deep dive topic analysis"}, "duration_ms": 3460}], "duration_ms": 2570, "token_usage": {"input": 1357, "output": 245}}, {"role": "assistant", "content": "Now reading the key documents.", "tool_calls": [{"tool": "Read", "input": {"file": "doc1.pdf"}, "duration_ms": 120}, {"tool": "Read", "input": {"file": "doc2.pdf"}, "duration_ms": 85}, {"tool": "tavily_search", "input": {"query": "supplementary data"}, "duration_ms": 2100}], "duration_ms": 3890, "token_usage": {"input": 3701, "output": 567}}, {"role": "assistant", "content": "Here is my comprehensive research report covering the key findings from multiple sources...", "tool_calls": [{"tool": "write_report", "input": {"title": "Research Summary"}, "duration_ms": 450}], "duration_ms": 2800, "token_usage": {"input": 2611, "output": 543}}], "assertions": [{"text": "Provides relevant research findings", "passed": true}, {"text": "Cites multiple sources", "passed": true}, {"text": "Missing critical source from 2025", "passed": false}]} {"timestamp": "2026-02-22T10:00:16.000Z", "test_id": "code-review-task", "suite": "multi-agent", "score": 1.0, "target": "gpt-4o", "scores": [{"name": "response_quality", "type": "llm_grader", "score": 1.0}, {"name": "step_efficiency", "type": "execution_metrics", "score": 1.0}], "trace": {"event_count": 3, "tool_names": ["Read", "Grep"], "tool_calls_by_name": {"Read": 2, "Grep": 1}, "error_count": 0, "token_usage": {"input": 3200, "output": 800}, "cost_usd": 0.032, "duration_ms": 4500, "llm_call_count": 2, "tool_durations": {"Read": [95, 110], "Grep": [340]}}, "output": [{"role": "assistant", "content": "Let me review the code.", "tool_calls": [{"tool": "Read", "input": {"file": "main.ts"}, "duration_ms": 95}, {"tool": "Grep", "input": {"pattern": "function handleError"}, "duration_ms": 340}], "duration_ms": 1200, "token_usage": {"input": 1600, "output": 200}}, {"role": "assistant", "content": "I found a critical bug in the error handling logic. The function catches the error but doesn't propagate it correctly...", "tool_calls": [{"tool": "Read", "input": {"file": "error-handler.ts"}, "duration_ms": 110}], "duration_ms": 1800, "token_usage": {"input": 1600, "output": 600}}], "assertions": [{"text": "Identifies the bug", "passed": true}, {"text": "Suggests fix", "passed": true}, {"text": "Explains root cause", "passed": true}, {"text": "Follows coding standards", "passed": true}]} {"timestamp": "2026-02-22T10:00:21.000Z", "test_id": "data-analysis", "suite": "multi-agent", "score": 0.5, "target": "claude-sonnet", "scores": [{"name": "response_quality", "type": "llm_grader", "score": 0.5}, {"name": "step_efficiency", "type": "execution_metrics", "score": 0.8}], "trace": {"event_count": 12, "tool_names": ["Read", "python_exec", "write_file"], "tool_calls_by_name": {"Read": 4, "python_exec": 6, "write_file": 2}, "error_count": 1, "token_usage": {"input": 12000, "output": 3500}, "cost_usd": 0.18, "duration_ms": 28000, "llm_call_count": 5, "tool_durations": {"Read": [80, 90, 110, 75], "python_exec": [1500, 2200, 1800, 3500, 900, 1100], "write_file": [200, 350]}}, "assertions": [{"text": "Processes data correctly", "passed": true}, {"text": "Missing visualization", "passed": false}, {"text": "Incomplete statistical analysis", "passed": false}]} {"timestamp": "2026-02-22T10:00:50.000Z", "test_id": "simple-qa", "suite": "multi-agent", "score": 1.0, "target": "gpt-4o", "trace": {"event_count": 0, "tool_names": [], "tool_calls_by_name": {}, "error_count": 0, "token_usage": {"input": 500, "output": 150}, "cost_usd": 0.005, "duration_ms": 1200, "llm_call_count": 1}, "assertions": [{"text": "Correct answer", "passed": true}, {"text": "Clear explanation", "passed": true}]} -{"timestamp": "2026-02-22T10:00:52.000Z", "test_id": "multi-step-planning", "suite": "multi-agent", "score": 0.9, "target": "claude-sonnet", "scores": [{"name": "response_quality", "type": "llm_grader", "score": 0.9}, {"name": "routing_accuracy", "type": "tool_trajectory", "score": 1.0}, {"name": "step_efficiency", "type": "execution_metrics", "score": 0.85}], "trace": {"event_count": 6, "tool_names": ["Read", "Write", "execute_plan"], "tool_calls_by_name": {"Read": 2, "Write": 2, "execute_plan": 2}, "error_count": 0, "token_usage": {"input": 5800, "output": 1200}, "cost_usd": 0.065, "duration_ms": 9500, "llm_call_count": 3, "tool_durations": {"Read": [100, 90], "Write": [250, 300], "execute_plan": [2500, 3200]}}, "assertions": [{"text": "Creates valid plan", "passed": true}, {"text": "Executes steps in order", "passed": true}, {"text": "Handles dependencies", "passed": true}, {"text": "Plan could be more efficient", "passed": false}]} +{"timestamp": "2026-02-22T10:00:52.000Z", "test_id": "multi-step-planning", "suite": "multi-agent", "score": 0.9, "target": "claude-sonnet", "scores": [{"name": "response_quality", "type": "llm_grader", "score": 0.9}, {"name": "routing_accuracy", "type": "trajectory:tool-sequence", "score": 1.0}, {"name": "step_efficiency", "type": "execution_metrics", "score": 0.85}], "trace": {"event_count": 6, "tool_names": ["Read", "Write", "execute_plan"], "tool_calls_by_name": {"Read": 2, "Write": 2, "execute_plan": 2}, "error_count": 0, "token_usage": {"input": 5800, "output": 1200}, "cost_usd": 0.065, "duration_ms": 9500, "llm_call_count": 3, "tool_durations": {"Read": [100, 90], "Write": [250, 300], "execute_plan": [2500, 3200]}}, "assertions": [{"text": "Creates valid plan", "passed": true}, {"text": "Executes steps in order", "passed": true}, {"text": "Handles dependencies", "passed": true}, {"text": "Plan could be more efficient", "passed": false}]} diff --git a/skills-data/agentv-bench/references/environment-adaptation.md b/skills-data/agentv-bench/references/environment-adaptation.md index 67f4d626d..0b495e777 100644 --- a/skills-data/agentv-bench/references/environment-adaptation.md +++ b/skills-data/agentv-bench/references/environment-adaptation.md @@ -39,15 +39,15 @@ tool calls; reserve `output` for final-answer text checks. ```yaml # Example: script-grader for Codex skill-use detection tests: - - id: should-trigger-codex + - id: codex-skill-use input: "Analyze this CSV file" assert: - type: script - command: [bun, run, ./judges/codex-skill-trigger.ts] + command: [bun, run, ./judges/codex-skill-use.ts] ``` ```typescript -// judges/codex-skill-trigger.ts +// judges/codex-skill-use.ts import { defineScriptGrader } from '@agentv/sdk'; export default defineScriptGrader(({ messages }) => { From 17e247ed4dc80b92b58c73a81cea33de1a5a1b7f Mon Sep 17 00:00:00 2001 From: Christopher Tso Date: Mon, 6 Jul 2026 04:01:16 +0200 Subject: [PATCH 2/2] docs: canonicalize trajectory assertion examples --- .../next/graders/trajectory-assertions.mdx | 29 ++++++++++++++----- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/apps/web/src/content/docs/docs/next/graders/trajectory-assertions.mdx b/apps/web/src/content/docs/docs/next/graders/trajectory-assertions.mdx index dea6451b6..62a9e4d14 100644 --- a/apps/web/src/content/docs/docs/next/graders/trajectory-assertions.mdx +++ b/apps/web/src/content/docs/docs/next/graders/trajectory-assertions.mdx @@ -122,12 +122,13 @@ assert: description: Validate research agent tool usage target: codex_agent +prompts: + - "{{ task }}" + tests: - id: comprehensive-research - criteria: Agent thoroughly researches the topic - - input: Research machine learning frameworks - + vars: + task: Research machine learning frameworks assert: # Check minimum tool usage - name: coverage @@ -153,17 +154,26 @@ tests: - webSearch - documentRead - summarize + + # Check final answer quality + - name: answer-quality + type: llm-rubric + value: The answer synthesizes the research into a useful framework comparison. ``` ### Multi-Step Pipeline ```yaml -tests: - - id: data-pipeline - criteria: Process data through complete pipeline +description: Validate a strict data pipeline +target: pipeline_agent - input: Process the customer dataset +prompts: + - "{{ task }}" +tests: + - id: data-pipeline + vars: + task: Process the customer dataset assert: - name: pipeline-check type: trajectory:tool-sequence @@ -174,6 +184,9 @@ tests: - validate - transform - export + - name: result-quality + type: llm-rubric + value: The final response explains that the dataset was loaded, validated, transformed, and exported. ``` ## Best Practices