Skip to main content

Quick Checks

Quick Checks are zero-LLM, composable micro-scorers for common assertions. They plug into the existing scorers: [...] array anywhere scorers are used — in runEvals, live scoring, experiments, and Studio.

Internally they are standard createScorer() instances, so they have the same observability, storage, and pipeline integration as any other scorer.

Usage example
Direct link to Usage example

src/evals/weather-checks.ts
import { checks } from '@mastra/evals/checks'
import { runEvals } from '@mastra/core/evals'
import { myAgent } from '../agents'

const result = await runEvals({
data: [{ input: 'What is the weather in Brooklyn?' }],
target: myAgent,
scorers: [
checks.includes('sunny'),
checks.calledTool('get_weather'),
checks.toolOrder(['get_weather', 'summarize']),
checks.noToolErrors(),
],
})

console.log(result.scores)

Text checks
Direct link to Text checks

checks.includes(expected, options?)
Direct link to checksincludesexpected-options

Scores 1 if the agent's output text contains the expected substring, 0 otherwise.

checks.includes('sunny')
checks.includes('Sunny', { ignoreCase: false })

expected:

string
Substring to search for in the output.

options.ignoreCase?:

boolean
= true
Case-insensitive matching.

Returns: 1 if found, 0 otherwise.

checks.excludes(unwanted, options?)
Direct link to checksexcludesunwanted-options

Scores 1 if the agent's output text does NOT contain the substring, 0 otherwise.

checks.excludes('error')
checks.excludes('Error', { ignoreCase: false })

unwanted:

string
Substring that must not appear in the output.

options.ignoreCase?:

boolean
= true
Case-insensitive matching.

Returns: 1 if absent, 0 otherwise.

checks.equals(expected, options?)
Direct link to checksequalsexpected-options

Scores 1 if the output text exactly equals the expected string after optional normalization.

checks.equals('Hello, world!')
checks.equals('Hello', { ignoreCase: false })

expected:

string
Exact string the output must match.

options.ignoreCase?:

boolean
= true
Case-insensitive matching.

Returns: 1 if equal, 0 otherwise.

checks.matches(pattern, options?)
Direct link to checksmatchespattern-options

Scores 1 if the output matches the given regular expression.

checks.matches(/\d+°[FC]/)
checks.matches(/^hello$/, { exact: true })

pattern:

RegExp
Regular expression to test against the output.

options.exact?:

boolean
= false
Anchor the pattern to match the entire output (adds ^ and $).

Returns: 1 if matched, 0 otherwise.

checks.similarity(expected, options?)
Direct link to checkssimilarityexpected-options

Returns the string similarity score (0-1) between the output and an expected string using the Dice coefficient. When a threshold is set, returns binary 1/0 instead.

checks.similarity('Sunny, 72°F')
checks.similarity('Sunny, 72°F', { threshold: 0.7 })

expected:

string
Reference string to compare against.

options.threshold?:

number
Minimum similarity score (0-1) to return 1. When omitted, returns the raw similarity score.

options.ignoreCase?:

boolean
= true
Case-insensitive comparison.

Returns: Raw similarity score (0-1), or binary 1/0 when threshold is set.

Tool call checks
Direct link to Tool call checks

checks.calledTool(toolName, options?)
Direct link to checkscalledtooltoolname-options

Scores 1 if the agent called the specified tool at least the required number of times.

checks.calledTool('get_weather')
checks.calledTool('search', { times: 2 })

toolName:

string
Name of the tool to look for.

options.times?:

number
= 1
Minimum number of times the tool must be called.

Returns: 1 if called at least times times, 0 otherwise.

checks.didNotCall(toolName)
Direct link to checksdidnotcalltoolname

Scores 1 if the agent did NOT call the specified tool.

checks.didNotCall('delete_user')

toolName:

string
Name of the tool that must not appear.

Returns: 1 if the tool was not called, 0 otherwise.

checks.toolOrder(expectedOrder)
Direct link to checkstoolorderexpectedorder

Scores 1 if the tools were called in the specified order. Uses relaxed matching — other tool calls between the expected tools are allowed.

checks.toolOrder(['search', 'summarize', 'respond'])

expectedOrder:

string[]
Tool names in the expected calling sequence. Must appear as a subsequence of the actual tool calls.

Returns: 1 if the expected order is satisfied, 0 otherwise.

checks.maxToolCalls(max)
Direct link to checksmaxtoolcallsmax

Scores 1 if the agent used no more than max tool calls.

checks.maxToolCalls(5)

max:

number
Maximum number of tool calls allowed.

Returns: 1 if within the limit, 0 otherwise.

checks.usedNoTools()
Direct link to checksusednotools

Scores 1 if the agent made no tool calls at all.

checks.usedNoTools()

Returns: 1 if no tools were called, 0 otherwise.

checks.noToolErrors()
Direct link to checksnotoolerrors

Scores 1 if none of the tool invocations resulted in an error state. Detects both error results (result.error present) and incomplete tool calls (state === 'call').

checks.noToolErrors()

Returns: 1 if all tool calls succeeded, 0 otherwise.

Combining checks with other scorers
Direct link to Combining checks with other scorers

Checks compose with LLM-based and code-based scorers in the same scorers array:

src/evals/combined-eval.ts
import { checks } from '@mastra/evals/checks'
import { createAnswerRelevancyScorer } from '@mastra/evals/scorers/prebuilt'
import { runEvals } from '@mastra/core/evals'
import { myAgent } from '../agents'

const result = await runEvals({
data: [{ input: 'What is the weather in Brooklyn?' }],
target: myAgent,
scorers: [
// Zero-LLM checks
checks.includes('Brooklyn'),
checks.calledTool('get_weather'),
checks.noToolErrors(),
// LLM-based scorer
createAnswerRelevancyScorer({ model: 'openai/gpt-5-mini' }),
],
})