TokenLimiterProcessor
The TokenLimiterProcessor limits the number of tokens in messages. Depending on trimMode, it acts as a prompt processor, an input processor, and an output processor:
- Prompt processor (
processLLMRequest): In the defaultbest-fitandcontiguoustrim modes, enforces the input budget on the provider prompt right before each model call, at every step of the agentic loop. The prompt is measured after earlier prompt processors (such asToolCallFilter) have transformed it, so only tokens that actually reach the model are counted. Tool call and tool result messages are grouped so they're kept or removed together, and trimming is transient: stored messages are never modified. - Input processor (
processInput): Inmemory-onlytrim mode, filters historical messages to fit within the context window before the agentic loop starts, prioritizing recent messages - Output processor: Limits generated response tokens via streaming or non-streaming with configurable strategies for handling exceeded limits
Usage exampleDirect link to Usage example
import { TokenLimiterProcessor } from '@mastra/core/processors'
const processor = new TokenLimiterProcessor({
limit: 1000,
strategy: 'truncate',
countMode: 'cumulative',
})
Constructor parametersDirect link to Constructor parameters
options:
limit:
encoding?:
strategy?:
countMode?:
trimMode?:
ReturnsDirect link to Returns
id:
name?:
processInput?:
processInputStep?:
processLLMRequest?:
processOutputStream:
processOutputResult:
getMaxTokens:
Output stream behaviorDirect link to Output stream behavior
As an output processor, only parts that carry generated output count against the limit: text-delta and object. Lifecycle parts (such as step-start), reasoning deltas, response metadata, and tool parts (tool-call, tool-result) are neither counted nor withheld, so tool calls always reach the agentic loop and get executed.
With the default truncate strategy, the first time output is withheld the processor emits a transient data-token-limit-reached part on the stream:
for await (const part of stream.fullStream) {
if (part.type === 'data-token-limit-reached') {
console.log('output truncated at', part.data.limit, 'tokens')
}
}
Media token countingDirect link to Media token counting
Images and file attachments are estimated instead of tokenized, including file message parts and tool results shaped like { data, mediaType }. Images use a flat per-image estimate; other media uses decoded byte size, while remote URLs and provider file ids use a flat fallback because their size isn't known locally. Encoded payloads such as base64 data are never counted as text, avoiding an inflated count that could truncate history unnecessarily.
Error behaviorDirect link to Error behavior
When trimming input, TokenLimiterProcessor throws a TripWire error in the following cases:
- Empty messages: If there are no non-system messages to process, a TripWire is thrown because you can't send an LLM request with no messages.
- System messages exceed limit: If system messages alone exceed the token limit, a TripWire is thrown because you can't send an LLM request with only system messages and no user/assistant messages.
- No messages fit: If no message fits within the remaining token budget, a TripWire is thrown because you can't send an LLM request with no messages.
import { TripWire } from '@mastra/core/agent'
try {
await agent.generate('Hello')
} catch (error) {
if (error instanceof TripWire) {
console.log('Token limit error:', error.message)
}
}
Extended usage exampleDirect link to Extended usage example
As an input processor (limit context window)Direct link to As an input processor (limit context window)
Use inputProcessors to limit historical messages sent to the model, which helps stay within context window limits:
import { Agent } from '@mastra/core/agent'
import { Memory } from '@mastra/memory'
import { TokenLimiterProcessor } from '@mastra/core/processors'
export const agent = new Agent({
id: 'context-limited-agent',
name: 'context-limited-agent',
instructions: 'You are a helpful assistant',
model: 'openai/gpt-5.6-sol',
memory: new Memory({/* ... */}),
inputProcessors: [
new TokenLimiterProcessor({ limit: 4000 }), // Limits historical messages to ~4000 tokens
],
})
As a per-step processor (limit multi-step token growth)Direct link to As a per-step processor (limit multi-step token growth)
When an agent uses tools across multiple steps (e.g. maxSteps > 1), each step accumulates conversation history from all previous steps. TokenLimiterProcessor applies its limit at every step, measuring the prompt that's about to be sent after any earlier prompt processors have run. Register prompt-shrinking processors such as ToolCallFilter before it, so the limiter counts the prompt the model actually receives:
import { Agent } from '@mastra/core/agent'
import { TokenLimiterProcessor } from '@mastra/core/processors'
export const agent = new Agent({
id: 'multi-step-agent',
name: 'multi-step-agent',
instructions: 'You are a helpful research assistant with access to tools',
model: 'openai/gpt-5.6-sol',
inputProcessors: [
new TokenLimiterProcessor({ limit: 8000 }), // Applied at every step
],
})
// Each tool call step will be limited to ~8000 input tokens
const result = await agent.generate('Research this topic using your tools', {
maxSteps: 10,
})
Processor workflows don't run processLLMRequest, so a TokenLimiterProcessor inside a processor workflow trims stored messages in processInputStep, before prompt processors such as ToolCallFilter remove anything from the request. To count the prompt the model receives, add the limiter directly to inputProcessors.
As an output processor (limit response length)Direct link to As an output processor (limit response length)
Use outputProcessors to limit the length of generated responses:
import { Agent } from '@mastra/core/agent'
import { TokenLimiterProcessor } from '@mastra/core/processors'
export const agent = new Agent({
id: 'response-limited-agent',
name: 'response-limited-agent',
instructions: 'You are a helpful assistant',
model: 'openai/gpt-5.6-sol',
outputProcessors: [
new TokenLimiterProcessor({
limit: 1000,
strategy: 'truncate',
countMode: 'cumulative',
}),
],
})