跳到主要内容
非官方简体中文翻译,内容版权归 Mastra 所有,遵循 Apache-2.0 许可。

Trajectory accuracy scorers

Mastra provides two trajectory accuracy scorers for evaluating whether an agent or workflow follows an expected sequence of actions:

  1. Code-based scorer - Deterministic evaluation using exact step matching and ordering
  2. LLM-based scorer - Semantic evaluation using AI to assess trajectory quality and appropriateness

Both scorers work with agents and workflows. The runEvals pipeline automatically extracts trajectories, so scorers receive a Trajectory object directly.

Trajectory extraction
Trajectory extraction的直接链接

The runEvals pipeline uses two extraction strategies, depending on whether observability storage is configured:

Trace-based extraction (preferred)
Trace-based extraction (preferred)的直接链接

When the target's Mastra instance has storage configured, the pipeline fetches the full execution trace from the observability store and calls extractTrajectoryFromTrace(). This produces a hierarchical trajectory with nested children that captures the complete execution tree. The tree includes nested agent runs and tool calls within workflow steps. It also includes model generations.

For example, a workflow that calls an agent, which in turn calls tools, produces:

workflow_run
└─ workflow_step (validate-input)
└─ workflow_step (process-data)
└─ agent_run (my-agent)
└─ model_generation
└─ tool_call (search)
└─ model_generation
└─ tool_call (summarize)
└─ workflow_step (save-result)

Fallback extraction
Fallback extraction的直接链接

When storage isn't available, the pipeline falls back to:

  • Agents: extractTrajectory(), Extracts ToolCallStep entries from toolInvocations in the agent's message output. Produces a flat list of tool calls.
  • Workflows: extractWorkflowTrajectory(), Extracts WorkflowStepStep entries from stepResults. Produces a flat list of workflow steps.

These fallbacks don't capture nested execution or non-tool-call spans.

Trajectory types
Trajectory types的直接链接

Trajectory steps use a discriminated union on stepType. Each step type has specific properties:

ToolCallStep
toolcallstep的直接链接

Represents an agent tool call.

stepType:

'tool_call'
Discriminant.

name:

string
Tool name.

toolArgs?:

Record<string, unknown>
Arguments passed to the tool.

toolResult?:

Record<string, unknown>
Result returned by the tool.

success?:

boolean
Whether the call succeeded.

durationMs?:

number
Execution time in milliseconds.

metadata?:

Record<string, unknown>
Arbitrary metadata.

children?:

TrajectoryStep[]
Nested sub-steps.

WorkflowStepStep
workflowstepstep的直接链接

Represents a workflow step execution.

stepType:

'workflow_step'
Discriminant.

name:

string
Step identifier.

stepId?:

string
Step ID in the workflow.

status?:

string
Step result status (success, failed, suspended, etc.).

output?:

Record<string, unknown>
Step output data.

durationMs?:

number
Execution time in milliseconds.

metadata?:

Record<string, unknown>
Arbitrary metadata.

children?:

TrajectoryStep[]
Nested sub-steps (e.g. tool calls inside the step).

Other step types
Other step types的直接链接

The discriminated union includes these additional step types:

Step typeKey properties
mcp_tool_calltoolArgs, toolResult, mcpServer, success
provider_tool_calltoolArgs, toolResult, success
model_generationmodelId, promptTokens, completionTokens, finishReason
agent_runagentId
workflow_runworkflowId, status
workflow_conditionalconditionCount, selectedSteps
workflow_parallelbranchCount, parallelSteps
workflow_looploopType, totalIterations
workflow_sleepsleepDurationMs, sleepType
workflow_wait_eventeventName, eventReceived
processor_runprocessorId

All step types share the base properties name, durationMs, metadata, and children.

Expected steps
Expected steps的直接链接

When defining expected trajectories, use ExpectedStep instead of the full TrajectoryStep discriminated union. ExpectedStep is a discriminated union that mirrors TrajectoryStep: when you specify a stepType, you get autocomplete for that variant's fields (e.g., toolArgs for tool_call, modelId for model_generation). All variant-specific fields are optional, so you only assert against what you care about.

Omit stepType entirely to match any step by name only.

name:

string
Step name to match (tool name, agent ID, workflow step name, etc.).

stepType?:

TrajectoryStepType
Step type discriminant. When set, enables autocomplete for that variant's fields. If omitted, matches any step type with the given name.

(variant fields)?:

varies
Type-specific fields from the corresponding TrajectoryStep variant. For example, toolArgs and toolResult for tool_call, modelId for model_generation, output for workflow_step. All optional — only specified fields are compared.

children?:

TrajectoryExpectation
Nested expectation config for this step's children. Overrides the parent config for evaluating children of this step.

Simple expected steps
Simple expected steps的直接链接

const steps: ExpectedStep[] = [
// Match by name only (any step type)
{ name: 'search' },

// Match by name and step type (autocomplete for tool_call fields)
{ name: 'search', stepType: 'tool_call' },

// Match with specific toolArgs (auto-compared when present)
{ name: 'search', stepType: 'tool_call', toolArgs: { query: 'weather' } },

// Match a model generation step by model ID
{ name: 'gpt-4o', stepType: 'model_generation', modelId: 'gpt-4o' },
]

Nested expectations
Nested expectations的直接链接

Each expected step can include a children config with its own evaluation rules. This lets you set different ordering or comparison rules at each level of the hierarchy.

const scorer = createTrajectoryScorerCode({
defaults: {
ordering: 'strict',
steps: [
{ name: 'validate-input', stepType: 'workflow_step' },
{
name: 'research-agent',
stepType: 'agent_run',
children: {
// Sub-agent can call tools in any order
ordering: 'unordered',
steps: [
{ name: 'search', stepType: 'tool_call' },
{ name: 'summarize', stepType: 'tool_call' },
],
},
},
{ name: 'save-result', stepType: 'workflow_step' },
],
},
})

In this example, the parent workflow requires strict ordering of its steps, but the nested research-agent allows its tool calls in any order.

Choosing between scorers
Choosing between scorers的直接链接

Use the code-based scorer when:
Use the code-based scorer when:的直接链接

  • You need deterministic, reproducible results
  • You have a known expected trajectory to compare against
  • You want to validate exact step sequences
  • Speed and cost are priorities (no LLM calls)
  • You are running automated tests in CI/CD

Use the LLM-based scorer when:
Use the LLM-based scorer when:的直接链接

  • You need semantic understanding of whether steps were appropriate
  • The optimal trajectory isn't predetermined (evaluate based on task requirements)
  • You want to detect unnecessary, redundant, or missing steps
  • You need explanations for scoring decisions
  • You are evaluating production agent behavior

Code-based trajectory accuracy scorer
Code-based trajectory accuracy scorer的直接链接

The createTrajectoryAccuracyScorerCode() function from @mastra/evals/scorers/prebuilt provides deterministic scoring based on step matching and ordering against an expected trajectory.

Parameters
Parameters的直接链接

expectedTrajectory?:

Trajectory | ExpectedStep[]
Static expected trajectory to compare against. Accepts a full Trajectory or an array of ExpectedStep matchers. When omitted, the scorer reads expectedTrajectory from each dataset item at runtime.

comparisonOptions?:

TrajectoryComparisonOptions
Controls how the comparison is performed.
'strict' | 'relaxed' | 'unordered'
boolean

This function returns an instance of the MastraScorer class. See the MastraScorer reference for details on the .run() method and its input/output.

Expected trajectory sources
Expected trajectory sources的直接链接

The code-based scorer resolves expectedTrajectory from two sources, in order of priority:

  1. Constructor option: A static trajectory passed when creating the scorer. Used for all dataset items.
  2. Dataset item: An expectedTrajectory field on the dataset item, passed through the runEvals pipeline. Allows different expected trajectories per item.
src/static-expected.ts
// Static: same expected trajectory for all items
const scorer = createTrajectoryAccuracyScorerCode({
expectedTrajectory: {
steps: [
{ stepType: 'tool_call', name: 'search' },
{ stepType: 'tool_call', name: 'summarize' },
],
},
})
src/per-item-expected.ts
// Per-item: each dataset item has its own expectedTrajectory
const scorer = createTrajectoryAccuracyScorerCode()

await runEvals({
target: mastra.getAgent('myAgent'),
scorers: { trajectory: [scorer] },
data: [
{
input: 'Search and summarize weather',
expectedTrajectory: {
steps: [
{ stepType: 'tool_call', name: 'search' },
{ stepType: 'tool_call', name: 'summarize' },
],
},
},
{
input: 'Just search for weather',
expectedTrajectory: {
steps: [{ stepType: 'tool_call', name: 'search' }],
},
},
],
})

Evaluation modes
Evaluation modes的直接链接

The code-based scorer operates in one of three modes based on ordering:

Strict mode (ordering: 'strict')
strict-mode-ordering-strict的直接链接

Only an exact match (the same steps in the same order, with nothing extra or missing) scores 1.0. Anything else gets partial credit for the expected steps that matched in position, with a penalty deducted for each extra step. For example, the two expected steps followed by one extra step scores 0.75.

Relaxed mode (ordering: 'relaxed', default)
relaxed-mode-ordering-relaxed-default的直接链接

Allows extra steps. Expected steps must appear in the correct relative order. The score is calculated based on how many expected steps were matched, with optional penalties for extra or repeated steps.

Unordered mode (ordering: 'unordered')
unordered-mode-ordering-unordered的直接链接

Only checks that each expected step is present. Order is ignored, and extra steps are reported in the result but not penalized.

Code-based scoring details
Code-based scoring details的直接链接

  • Continuous scores: Returns values between 0.0 and 1.0 in every ordering mode. In strict mode, the score is the share of expected steps matched in order, minus penalties for extra steps and, when allowRepeatedSteps is false, repeated steps
  • Deterministic: Same input always produces the same output
  • Fast: No external API calls

Code-based scorer results
Code-based scorer results的直接链接

{
runId: string,
preprocessStepResult: {
actualTrajectory: Trajectory,
expectedTrajectory: Trajectory,
comparison: {
score: number,
matchedSteps: number,
totalExpectedSteps: number,
totalActualSteps: number,
missingSteps: string[],
extraSteps: string[],
outOfOrderSteps: string[],
repeatedSteps: string[]
},
actualStepNames: string[],
expectedStepNames: string[]
},
score: number
}

Code-based scorer examples
Code-based scorer examples的直接链接

Agent trajectory with strict ordering
Agent trajectory with strict ordering的直接链接

Validates that an agent follows an exact sequence of tool calls:

src/example-strict-trajectory.ts
import { createTrajectoryAccuracyScorerCode } from '@mastra/evals/scorers/prebuilt'
import { runEvals } from '@mastra/core/evals'

const scorer = createTrajectoryAccuracyScorerCode({
expectedTrajectory: {
steps: [
{ stepType: 'tool_call', name: 'auth-tool' },
{ stepType: 'tool_call', name: 'fetch-tool' },
],
},
comparisonOptions: { ordering: 'strict' },
})

const result = await runEvals({
target: mastra.getAgent('myAgent'),
scorers: { trajectory: [scorer] },
data: [{ input: 'Get my data' }],
})

console.log(result.scores.trajectory['code-trajectory-accuracy-scorer']) // 1.0

Agent trajectory with relaxed ordering
Agent trajectory with relaxed ordering的直接链接

Allows extra steps as long as expected steps appear in the correct relative order:

src/example-relaxed-trajectory.ts
const scorer = createTrajectoryAccuracyScorerCode({
expectedTrajectory: {
steps: [
{ stepType: 'tool_call', name: 'search-tool' },
{ stepType: 'tool_call', name: 'summarize-tool' },
],
},
comparisonOptions: { ordering: 'relaxed' },
})

// Agent called search-tool → log-tool → summarize-tool
// The extra log-tool is allowed in relaxed mode
// score: 0.75 — all expected steps matched, small penalty for extra step

Workflow trajectory
Workflow trajectory的直接链接

Evaluates a workflow's execution path:

src/example-workflow-trajectory.ts
import { createTrajectoryAccuracyScorerCode } from '@mastra/evals/scorers/prebuilt'
import { runEvals } from '@mastra/core/evals'

const scorer = createTrajectoryAccuracyScorerCode({
expectedTrajectory: {
steps: [
{ stepType: 'workflow_step', name: 'validate-input' },
{ stepType: 'workflow_step', name: 'process-data' },
{ stepType: 'workflow_step', name: 'save-result' },
],
},
})

const result = await runEvals({
target: mastra.getWorkflow('myWorkflow'),
scorers: { trajectory: [scorer] },
data: [{ input: { data: 'test' } }],
})

console.log(result.scores.trajectory['code-trajectory-accuracy-scorer'])

Comparing step data
Comparing step data的直接链接

Validates the step names and step-specific data. For tool calls, this compares toolArgs and toolResult. For workflow steps, this compares output.

src/example-trajectory-with-data.ts
const scorer = createTrajectoryAccuracyScorerCode({
expectedTrajectory: {
steps: [
{
stepType: 'tool_call',
name: 'search-tool',
toolArgs: { query: 'weather in NYC' },
},
],
},
})
// Data fields like toolArgs are auto-compared when present on expected steps

LLM-based trajectory accuracy scorer
LLM-based trajectory accuracy scorer的直接链接

The createTrajectoryAccuracyScorerLLM() function from @mastra/evals/scorers/prebuilt uses an LLM to evaluate whether an agent's or workflow's trajectory was appropriate, efficient, and complete.

Parameters
Parameters的直接链接

model:

MastraModelConfig
The LLM model to use for evaluating trajectory quality.

expectedTrajectory?:

Trajectory | ExpectedStep[]
Optional static expected trajectory to compare against. Accepts a full Trajectory or an array of ExpectedStep matchers. When omitted, the LLM evaluates the trajectory based on the task requirements alone. Can also come from dataset items at runtime.

Features
Features的直接链接

The LLM-based scorer provides:

  • Task-aware evaluation: Assesses whether each step was necessary given the user's request
  • Ordering assessment: Evaluates whether steps were taken in a logical order
  • Missing step detection: Identifies steps that should have been taken
  • Redundancy detection: Flags unnecessary or repeated steps
  • Reasoning generation: Provides human-readable explanations for scoring decisions

Evaluation process
Evaluation process的直接链接

  1. Receive trajectory: Gets a pre-extracted Trajectory object from the pipeline
  2. Analyze steps: Evaluates each step for necessity and ordering using the LLM
  3. Generate score: Calculates score weighted as 60% necessity, 30% ordering, minus 10% missing penalty
  4. Generate reasoning: Provides a human-readable explanation

LLM-based scoring details
LLM-based scoring details的直接链接

  • Fractional scores: Returns values between 0.0 and 1.0
  • Context-aware: Considers user intent and task requirements
  • Explanatory: Provides reasoning for scores
  • Flexible: Works with or without an expected trajectory

LLM-based scorer options
LLM-based scorer options的直接链接

// Evaluate based on task requirements (no expected trajectory)
const openScorer = createTrajectoryAccuracyScorerLLM({
model: { provider: 'openai', name: 'gpt-5.4' },
})

// Evaluate against a static expected trajectory
const guidedScorer = createTrajectoryAccuracyScorerLLM({
model: { provider: 'openai', name: 'gpt-5.4' },
expectedTrajectory: {
steps: [
{ stepType: 'tool_call', name: 'search-tool' },
{ stepType: 'tool_call', name: 'summarize-tool' },
],
},
})

LLM-based scorer results
LLM-based scorer results的直接链接

{
runId: string,
preprocessStepResult: {
actualTrajectory: Trajectory,
actualTrajectoryFormatted: string,
expectedTrajectoryFormatted?: string,
hasSteps: boolean
},
analyzeStepResult: {
stepEvaluations: Array<{
stepName: string,
wasNecessary: boolean,
wasInOrder: boolean,
reasoning: string
}>,
missingSteps?: string[],
extraSteps?: string[],
overallAssessment: string
},
score: number,
reason: string
}

Unified trajectory scorer
Unified trajectory scorer的直接链接

The createTrajectoryScorerCode() function from @mastra/evals/scorers/prebuilt provides a multi-dimensional trajectory evaluation that checks accuracy, efficiency, blacklisted tools, and tool failure patterns in a single pass.

Parameters
Parameters的直接链接

defaults?:

TrajectoryExpectation
Default expectations applied to all dataset items. Per-item expectedTrajectory values override these defaults.
ExpectedStep[]
'strict' | 'relaxed' | 'unordered'
boolean
number
number
number
boolean
string[]
string[][]
number

weights?:

TrajectoryScoreWeights
Custom weights for combining dimension scores. Weights are normalized to sum to 1.0.
number
number
number
number

Scoring behavior
Scoring behavior的直接链接

The unified scorer evaluates four dimensions:

  1. Accuracy: Matches actual steps against expected steps (if steps is configured). Uses the ordering mode.
  2. Efficiency: Checks step budgets (maxSteps, maxTotalTokens, maxTotalDurationMs) and redundant calls (noRedundantCalls).
  3. Blacklist: Checks for forbidden tools or sequences. Any violation immediately results in a score of 0.0 regardless of other dimensions.
  4. Tool failures: Detects retry and fallback patterns. It also detects argument correction patterns.

The final score is a weighted combination of active dimensions, normalized by which dimensions are active. Default weights are accuracy 0.4, efficiency 0.3, tool failures 0.2, blacklist 0.1, but you can customize them via the weights option. Blacklist violations override everything to 0. When nested evaluations are present, the score is 70% top-level and 30% nested average.

Unified scorer results
Unified scorer results的直接链接

{
runId: string,
preprocessStepResult: {
accuracy?: TrajectoryComparisonResult,
efficiency?: TrajectoryEfficiencyResult,
blacklist?: TrajectoryBlacklistResult,
toolFailures?: ToolFailureAnalysisResult,
nested?: NestedEvaluationResult[],
},
score: number,
reason: string
}

Per-item expectations
Per-item expectations的直接链接

Each dataset item can override the defaults with its own expectedTrajectory. This lets you vary expectations per prompt:

src/unified-per-item.ts
import { createTrajectoryScorerCode } from '@mastra/evals/scorers/prebuilt'
import { runEvals } from '@mastra/core/evals'

// Default blacklist applies to all items
const scorer = createTrajectoryScorerCode({
defaults: {
blacklistedTools: ['deleteAll'],
maxSteps: 5,
},
})

const result = await runEvals({
target: mastra.getAgent('myAgent'),
scorers: { trajectory: [scorer] },
data: [
{
input: 'Search for weather',
expectedTrajectory: {
steps: [{ stepType: 'tool_call', name: 'search' }],
maxSteps: 2,
},
},
{
input: 'Search and summarize',
expectedTrajectory: {
steps: [
{ stepType: 'tool_call', name: 'search' },
{ stepType: 'tool_call', name: 'summarize' },
],
},
},
],
})

Example: efficiency and blacklist
Example: efficiency and blacklist的直接链接

src/unified-scorer.ts
import { createTrajectoryScorerCode } from '@mastra/evals/scorers/prebuilt'

const scorer = createTrajectoryScorerCode({
defaults: {
blacklistedTools: ['escalate', 'admin-override'],
blacklistedSequences: [['escalate', 'admin-override']],
maxSteps: 10,
noRedundantCalls: true,
maxRetriesPerTool: 2,
},
// Customize how dimensions contribute to the final score
weights: {
accuracy: 0.5, // prioritize step accuracy
efficiency: 0.3,
toolFailures: 0.1,
blacklist: 0.1,
},
})

Using trajectory scorers with runEvals
using-trajectory-scorers-with-runevals的直接链接

Trajectory scorers are configured under the trajectory key in the scorer config. The runEvals pipeline handles trajectory extraction automatically.

Agent trajectory evaluation
Agent trajectory evaluation的直接链接

src/agent-trajectory-eval.ts
import { runEvals } from '@mastra/core/evals'
import { createTrajectoryAccuracyScorerCode } from '@mastra/evals/scorers/prebuilt'

const trajectoryScorer = createTrajectoryAccuracyScorerCode({
expectedTrajectory: {
steps: [
{ stepType: 'tool_call', name: 'search' },
{ stepType: 'tool_call', name: 'format' },
],
},
})

const result = await runEvals({
target: mastra.getAgent('myAgent'),
scorers: {
agent: [qualityScorer], // receives raw MastraDBMessage[] output
trajectory: [trajectoryScorer], // receives pre-extracted Trajectory
},
data: [{ input: 'Find and format the data' }],
})

// result.scores.agent['quality'] — agent-level score
// result.scores.trajectory['code-trajectory-accuracy-scorer'] — trajectory score

Workflow trajectory evaluation
Workflow trajectory evaluation的直接链接

src/workflow-trajectory-eval.ts
import { runEvals } from '@mastra/core/evals'
import { createTrajectoryAccuracyScorerCode } from '@mastra/evals/scorers/prebuilt'

const workflowTrajectoryScorer = createTrajectoryAccuracyScorerCode({
expectedTrajectory: {
steps: [
{ stepType: 'workflow_step', name: 'validate' },
{ stepType: 'workflow_step', name: 'process' },
{ stepType: 'workflow_step', name: 'notify' },
],
},
})

const result = await runEvals({
target: mastra.getWorkflow('myWorkflow'),
scorers: {
workflow: [outputScorer], // receives workflow output
trajectory: [workflowTrajectoryScorer], // receives pre-extracted Trajectory from step results
},
data: [{ input: { userId: '123' } }],
})

// result.scores.workflow['output-quality'] — workflow-level score
// result.scores.trajectory['code-trajectory-accuracy-scorer'] — trajectory score