CyberRefusalHandler
The CyberRefusalHandler retries a step once when a provider's cybersecurity safeguard refuses it. These safeguards can refuse ordinary coding work partway through a long agent run. Many of those refusals are false positives, and asking the model to continue usually gets past them. If the retried step is refused again, the refusal stands and surfaces as a normal error or stop.
The handler covers two providers, which report refusals differently:
- OpenAI fails the model call with a
cyber_policyerror ("This content was flagged for possible cybersecurity risk"). The handler matches the error code or the message, whether the refusal arrives as an HTTP error or as a failed stream. It's handled inprocessAPIError, which only runs for processors inerrorProcessors. - Anthropic finishes the step with a
content-filterfinish reason andstopDetails.category: 'cyber'in the provider metadata. It's handled inprocessOutputStep, which runs for processors inoutputProcessors. The refused step is rolled back, including any partial text, before the retry.
How it worksDirect link to How it works
For an OpenAI refusal:
- The model call fails with a
cyber_policyerror CyberRefusalHandlerchecks that this is the first retry attempt for the step- It sends a
system-remindersignal withcontinueas its contents - It returns
{ retry: true }, and the same model is called again
For an Anthropic refusal:
- The step finishes with a
cyberclassifier refusal CyberRefusalHandlerchecks that this is the first retry attempt for the step- It calls
abort('continue', { retry: true }) - The refused step is rolled back and the model is called again with
continueappended as a system reminder
Only one retry runs per step. A successful step resets the count, so a refusal later in the same run is retried again.
Usage exampleDirect link to Usage example
Add CyberRefusalHandler to both errorProcessors and outputProcessors to cover both providers:
import { Agent } from '@mastra/core/agent'
import { CyberRefusalHandler, StreamErrorRetryProcessor } from '@mastra/core/processors'
export const agent = new Agent({
id: 'coding-agent',
name: 'Coding Agent',
instructions: 'You are a coding agent.',
model: 'openai/gpt-5.6-sol',
errorProcessors: [new CyberRefusalHandler(), new StreamErrorRetryProcessor()],
outputProcessors: [new CyberRefusalHandler()],
maxProcessorRetries: 3,
})
In errorProcessors, place it before StreamErrorRetryProcessor. Error processors stop at the first one that returns { retry: true }, and a retry processor placed first would resend the refused request unchanged.
Output-step retries count against maxProcessorRetries, and unlike the error lane they have no implicit default. Set it explicitly whether or not the agent has errorProcessors, or the Anthropic retry is treated as an abort.
createCodingAgent() includes the handler in both lanes by default.
Constructor parametersDirect link to Constructor parameters
The CyberRefusalHandler takes no constructor parameters.
PropertiesDirect link to Properties
id:
name:
processAPIError:
continue system reminder and signaling retry. Only triggers on the first retry attempt.processOutputStep:
retry: true. Only triggers on the first retry attempt.