examples/processors-message-length-limiter/README.md
This example shows how to create a custom input processor that validates and limits the total length of messages before they are sent to the language model. This processor helps prevent expensive API calls and ensures consistent input constraints across your application.
A custom input processor in Mastra implements the Processor interface with the processInput method. This processor validates the total character count of all text content in the message thread and blocks requests that exceed the configured limit.
import type { Processor } from '@mastra/core/processors';
import type { MastraMessageV2 } from '@mastra/core/agent/message-list';
import { TripWire } from '@mastra/core/agent';
type MessageLengthLimiterOptions = {
maxLength?: number;
strategy?: 'block' | 'warn' | 'truncate';
};
export class MessageLengthLimiter implements Processor {
readonly id = 'message-length-limiter';
readonly name = 'Message Length Limiter';
private maxLength: number;
private strategy: 'block' | 'warn' | 'truncate';
constructor(options: MessageLengthLimiterOptions | number = {}) {
if (typeof options === 'number') {
this.maxLength = options;
this.strategy = 'block';
} else {
this.maxLength = options.maxLength ?? 1000;
this.strategy = options.strategy ?? 'block';
}
}
processInput({
messages,
abort,
}: {
messages: MastraMessageV2[];
abort: (reason?: string) => never;
}): MastraMessageV2[] {
try {
const totalLength = messages.reduce((sum, msg) => {
return (
sum +
msg.content.parts
.filter(part => part.type === 'text')
.reduce((partSum, part) => partSum + (part.type === 'text' ? part.text.length : 0), 0)
);
}, 0);
if (totalLength > this.maxLength) {
switch (this.strategy) {
case 'block':
abort(`Message too long: ${totalLength} characters (max: ${this.maxLength})`);
break;
case 'warn':
console.warn(
`Warning: Message length ${totalLength} exceeds recommended limit of ${this.maxLength} characters`,
);
break;
case 'truncate':
return this.truncateMessages(messages, this.maxLength);
}
}
} catch (error) {
if (error instanceof TripWire) {
throw error;
}
throw new Error(`Length validation failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
}
return messages;
}
private truncateMessages(messages: MastraMessageV2[], maxLength: number): MastraMessageV2[] {
const truncatedMessages = [...messages];
let currentLength = 0;
for (let i = 0; i < truncatedMessages.length; i++) {
const message = truncatedMessages[i];
const parts = [...message.content.parts];
for (let j = 0; j < parts.length; j++) {
const part = parts[j];
if (part.type === 'text') {
const partLength = part.text.length;
if (currentLength + partLength > maxLength) {
const remainingChars = maxLength - currentLength;
if (remainingChars > 0) {
part.text = part.text.substring(0, remainingChars) + '...';
} else {
parts.splice(j);
break;
}
currentLength = maxLength;
break;
}
currentLength += partLength;
}
}
truncatedMessages[i] = {
...message,
content: { ...message.content, parts },
};
if (currentLength >= maxLength) {
truncatedMessages.splice(i + 1);
break;
}
}
return truncatedMessages;
}
}
'block': Reject the entire input with an error (default)'warn': Log warning but allow content through'truncate': Shorten messages to fit within the limitUsing the options object approach with explicit strategy configuration:
import { Agent } from '@mastra/core/agent';
import { MessageLengthLimiter } from '../processors/message-length-limiter';
export const blockingAgent = new Agent({
id: 'blocking-agent',
name: 'Blocking Agent',
instructions: 'You are a helpful assistant with input length limits',
model: 'openai/gpt-5.1',
inputProcessors: [new MessageLengthLimiter({ maxLength: 2000, strategy: 'block' })],
});
Using the simple number approach (defaults to 'block' strategy):
import { Agent } from '@mastra/core/agent';
import { MessageLengthLimiter } from '../processors/message-length-limiter';
export const simpleAgent = new Agent({
id: 'simple-agent',
name: 'Simple Agent',
instructions: 'You are a helpful assistant',
model: 'openai/gpt-5.1',
inputProcessors: [new MessageLengthLimiter(500)],
});
This example shows a message that stays within the configured character limit and processes successfully.
import { Agent } from '@mastra/core/agent';
import { MessageLengthLimiter } from './mastra/processors/message-length-limiter';
// Create agent with generous character limit
export const agent = new Agent({
id: 'length-limited-agent',
name: 'Length Limited Agent',
instructions: 'You are a helpful assistant',
model: 'openai/gpt-5.1',
inputProcessors: [
new MessageLengthLimiter(500), // 500 character limit
],
});
const shortMessage = 'What is the capital of France?'; // 31 characters
const result = await agent.generate(shortMessage);
console.log(result.text);
The message processes successfully because it's well under the 500-character limit:
"The capital of France is Paris. It's located in the north-central part of the country...";
This example shows a message that's close to but still within the character limit.
import { Agent } from '@mastra/core/agent';
import { MessageLengthLimiter } from './mastra/processors/message-length-limiter';
// Reuse same agent but with tighter character limit
export const agent = new Agent({
id: 'length-limited-agent',
name: 'Length Limited Agent',
instructions: 'You are a helpful assistant',
model: 'openai/gpt-5.1',
inputProcessors: [
new MessageLengthLimiter(300), // 300 character limit
],
});
const mediumMessage =
"Can you explain the difference between machine learning and artificial intelligence? I'm particularly interested in understanding how they relate to each other and what makes them distinct in the field of computer science."; // ~250 characters
const result = await agent.generate(mediumMessage);
console.log(result.text);
The message processes successfully as it's under the 300-character limit:
'Machine learning is a subset of artificial intelligence. AI is the broader concept of machines performing tasks in a smart way...';
This example shows what happens when a message exceeds the configured character limit.
import { Agent } from '@mastra/core/agent';
import { MessageLengthLimiter } from './mastra/processors/message-length-limiter';
// Reuse same agent but with very strict character limit
export const agent = new Agent({
id: 'length-limited-agent',
name: 'Length Limited Agent',
instructions: 'You are a helpful assistant',
model: 'openai/gpt-5.1',
inputProcessors: [
new MessageLengthLimiter(100), // Very strict 100 character limit
],
});
const longMessage =
'I need you to provide a comprehensive analysis of the economic implications of artificial intelligence on global markets, including detailed examination of how AI adoption affects employment rates, productivity metrics, consumer behavior patterns, and long-term economic forecasting models that governments and corporations use for strategic planning purposes.'; // ~400+ characters
const result = await agent.generate(longMessage);
if (result.tripwire) {
console.log('Request blocked:', result.tripwire.reason);
} else {
console.log(result.text);
}
The request is blocked because the message exceeds the 100-character limit:
Request blocked: Message too long: 412 characters (max: 100)
When using MessageLengthLimiter, the processor:
result.tripwire = trueresult.tripwire.reason includes actual length and configured maximumresult.tripwire instead of using try/catch blocksThis processor is particularly useful for: