Built‑in filters
Instead of manually checking every incoming message, you can use the provided filters.
Example
import { Agent, filter } from '@xmtp/agent-sdk';
const agent = await Agent.createFromEnv();
// Using filter in message handler
agent.on('text', async (ctx) => {
if (filter.isText(ctx.message)) {
await ctx.sendText('You sent a text message!');
}
});
// Combine multiple conditions
agent.on('text', async (ctx) => {
if (
filter.hasContent(ctx.message) &&
!filter.fromSelf(ctx.message, ctx.client) &&
filter.isText(ctx.message)
) {
await ctx.sendText('Valid text message received ✅');
}
});For convenience, the filter object can also be imported as f:
// You can import either name:
import { filter, f } from '@xmtp/agent-sdk';
// Both work the same way:
if (f.isText(ctx.message)) {
// Handle message...
}Custom content type filtering
Use the usesCodec filter to check for custom content types with full TypeScript type inference:
import { Agent, filter } from '@xmtp/agent-sdk';
import { ReactionCodec } from '@xmtp/content-type-reaction';
import { MyCustomCodec } from './my-custom-codec';
const agent = await Agent.createFromEnv();
agent.on('message', async (ctx) => {
// Check for specific codec with type safety
if (filter.usesCodec(ctx.message, ReactionCodec)) {
// ctx.message.content is now typed as Reaction
console.log(`Reaction: ${ctx.message.content.content}`);
console.log(`Action: ${ctx.message.content.action}`);
}
// Works with custom content types too
if (filter.usesCodec(ctx.message, MyCustomCodec)) {
// ctx.message.content is now typed to MyCustomCodec's decoded type
console.log('Received custom content:', ctx.message.content);
}
});This is particularly useful when you need to handle multiple custom content types or want precise type inference for your message content.
Available filters
fromSelfhasContentisDMisGroupisGroupAdminisGroupSuperAdminisReactionisReplyisRemoteAttachmentisTextisTextReplyusesCodec
To learn more about all available prebuilt filters, see filter.ts.

