ClassifierProcessor
The ClassifierProcessor is a hybrid processor that runs a Classifier over message text and passes the typed answers to onResult. In onResult, call abort(reason) to stop the request with a tripwire, call filter() to drop the content and continue, or do nothing to let it through. The classifier provides evidence such as probabilities, choices, and scores. onResult owns application policy.
Abort reasons are always the string supplied by the caller. Provider-generated text is never included in the abort message.
Usage exampleDirect link to Usage example
import { Classifier } from '@mastra/core/classifier'
import { ClassifierProcessor } from '@mastra/core/processors'
const safety = new Classifier({
id: 'safety',
model,
questions: {
unsafe: {
type: 'boolean',
criteria: { true: 'The message is unsafe', false: 'The message is safe' },
},
},
})
const processor = new ClassifierProcessor({
classifier: safety,
onResult: (answers, { abort }) => {
if (answers.unsafe.probability > 0.8) abort('Message rejected by safety policy')
},
lastMessageOnly: true,
})
Several conditions can share one onResult, or use separate processors when they need different classifiers. Give each processor a unique id. Processor instances with the same id share per-run state, including accumulated stream chunks.
inputProcessors: [
new ClassifierProcessor({
id: 'safety-check',
classifier: safety,
onResult: (a, { abort }) => {
if (a.unsafe.probability > 0.8) abort('Rejected by safety policy')
},
}),
new ClassifierProcessor({
id: 'topic-check',
classifier: topic,
onResult: (a, { abort }) => {
if (a.topic.choice === 'other') abort('Support questions only')
},
}),
]
Constructor parametersDirect link to Constructor parameters
options:
classifier:
onResult:
id?:
errorStrategy?:
lastMessageOnly?:
chunkWindow?:
maxInputLength?:
providerOptions?:
Behavior by phaseDirect link to Behavior by phase
| Phase | no call | abort(reason) | filter() |
|---|---|---|---|
Input (inputProcessors) | message passes | abort before the LLM | message removed from context |
Output result (outputProcessors) | message passes | abort the response | message removed from the response |
Stream (outputProcessors) | chunk emitted | abort the stream | chunk not emitted |
Messages with no text content are passed through without calling the classifier.
Extended usage examplesDirect link to Extended usage examples
Topic scopingDirect link to Topic scoping
import { Agent } from '@mastra/core/agent'
import { Classifier } from '@mastra/core/classifier'
import { ClassifierProcessor } from '@mastra/core/processors'
const topic = new Classifier({
id: 'topic',
model,
questions: {
topic: {
type: 'choice',
criteria: {
billing: 'Questions about invoices or payments',
account: 'Questions about account settings',
other: 'Anything else',
},
},
},
})
export const agent = new Agent({
id: 'support-agent',
name: 'support-agent',
instructions: 'You help customers with billing and account questions.',
model: 'openai/gpt-5.6-sol',
inputProcessors: [
new ClassifierProcessor({
classifier: topic,
lastMessageOnly: true,
onResult: (answers, { abort }) => {
if (answers.topic.choice === 'other') {
abort('This assistant only handles billing and account questions')
}
},
}),
],
})
Output quality gateDirect link to Output quality gate
import { Agent } from '@mastra/core/agent'
import { Classifier } from '@mastra/core/classifier'
import { ClassifierProcessor } from '@mastra/core/processors'
const quality = new Classifier({
id: 'quality',
model,
questions: {
quality: {
type: 'score',
instructions: 'Rate how well the response answers the user',
criteria: ['Off-topic', 'Partial', 'Complete'],
},
},
})
export const agent = new Agent({
id: 'quality-gated-agent',
name: 'quality-gated-agent',
instructions: 'You are a helpful assistant',
model: 'openai/gpt-5.6-sol',
outputProcessors: [
new ClassifierProcessor({
classifier: quality,
onResult: (answers, { filter }) => {
if (answers.quality.score < 1) filter()
},
}),
],
})
Registered classifierDirect link to Registered classifier
Register the classifier on the Mastra instance and reference it by key or ID. The processor resolves it on first use.
import { Mastra } from '@mastra/core'
import { Classifier } from '@mastra/core/classifier'
export const mastra = new Mastra({
classifiers: {
safety: new Classifier({ id: 'safety', model, questions: {/* ... */} }),
},
})
import { ClassifierProcessor } from '@mastra/core/processors'
type SafetyQuestions = {
unsafe: { type: 'boolean' }
}
const processor = new ClassifierProcessor<SafetyQuestions>({
classifier: 'safety',
onResult: (answers, { abort }) => {
if (answers.unsafe.probability > 0.8) abort('Message rejected by safety policy')
},
})
When using a registered classifier by string, answer types aren't inferred from the registered instance. Pass its question map as the ClassifierProcessor type argument to type the answers parameter.