ProviderHistoryCompat
The ProviderHistoryCompat processor handles provider-specific history incompatibilities. It can rewrite the outbound language model prompt before a provider call, or react to API errors and retry with repaired message history.
Use it when an agent may switch between model providers, reuse message history across providers, or call a provider that rejects fields emitted by another provider.
Usage exampleDirect link to Usage example
Add ProviderHistoryCompat to inputProcessors when you want all built-in compatibility rules available for an agent:
import { Agent } from '@mastra/core/agent'
import { ProviderHistoryCompat } from '@mastra/core/processors'
export const agent = new Agent({
name: 'my-agent',
instructions: 'You are a helpful assistant.',
model: 'anthropic/claude-sonnet-4-5',
inputProcessors: [new ProviderHistoryCompat()],
})
Mastra agents don't add this processor automatically. Add it explicitly when you need provider history compatibility rules, reactive API error recovery, custom rules, or predictable processor ordering.
Constructor parametersDirect link to Constructor parameters
opts?:
additionalRules?:
PropertiesDirect link to Properties
id:
name:
processLLMRequest:
processAPIError:
Built-in rulesDirect link to Built-in rules
ProviderHistoryCompat includes these built-in compatibility rules:
| Rule | Provider | Timing | Behavior |
|---|---|---|---|
anthropic-tool-id-format | Anthropic | Reactive API error recovery | Rewrites tool call IDs that contain characters outside [a-zA-Z0-9_-] and retries the request. |
cerebras-strip-reasoning-content | Cerebras | Preemptive prompt rewrite | Removes assistant reasoning parts from the outbound prompt so they're not serialized as unsupported reasoning_content fields. |
anthropic-strip-foreign-reasoning-content | Anthropic | Preemptive prompt rewrite | Removes non-Anthropic assistant reasoning parts from the outbound prompt. Anthropic-native thinking history is preserved. |
Preemptive rules run through processLLMRequest after Mastra converts messages to the model prompt format and before the prompt is sent to the provider. These rewrites affect only the current provider call.
Reactive rules run through processAPIError after a provider rejection. They can update the persisted messageList and request a retry.
CompatRuleDirect link to compatrule
A CompatRule defines one provider history compatibility fix:
import type { CompatRule } from '@mastra/core/processors'
const removeUnsupportedPromptParts: CompatRule = {
name: 'remove-unsupported-prompt-parts',
applyToPrompt({ prompt, model }) {
// Return a modified LanguageModelV2Prompt, or undefined to leave it unchanged.
return undefined
},
}
name:
errorPatterns?:
fix?:
applyToPrompt?:
Custom rulesDirect link to Custom rules
Pass custom rules through additionalRules. Custom rules run after the built-in rules:
import { Agent } from '@mastra/core/agent'
import { ProviderHistoryCompat, type CompatRule } from '@mastra/core/processors'
const stripUnsupportedAssistantMetadata: CompatRule = {
name: 'strip-unsupported-assistant-metadata',
applyToPrompt({ prompt, model }) {
if (typeof model !== 'string' || !model.startsWith('example-provider/')) {
return undefined
}
let changed = false
const nextPrompt = prompt.map(message => {
if (message.role !== 'assistant' || typeof message.content === 'string') {
return message
}
const nextContent = message.content.map(part => {
if (!('providerOptions' in part)) return part
changed = true
const { providerOptions: _providerOptions, ...rest } = part
return rest
})
return { ...message, content: nextContent }
})
return changed ? nextPrompt : undefined
},
}
export const agent = new Agent({
name: 'custom-provider-agent',
instructions: 'You are a helpful assistant.',
model: 'example-provider/model',
inputProcessors: [
new ProviderHistoryCompat({
additionalRules: [stripUnsupportedAssistantMetadata],
}),
],
})
Use applyToPrompt for provider-specific rewrites that shouldn't be saved to memory. Use fix with errorPatterns when the provider rejects persisted message history and the repaired history should be reused on future turns.