Event-driven architecture
Subscribe only to what you need using Node’s EventEmitter
interface. Events you can listen for:
-
Message events
attachment
: a new incoming remote attachment messagemessage
: all incoming messages (fires for every message regardless of type)reaction
: a new incoming reaction messagereply
: a new incoming reply messagetext
: a new incoming text messageunknownMessage
: a message that doesn't match any specific type
-
Lifecycle events
start
/stop
: agent lifecycle eventsunhandledError
: unhandled errors
Example
// Listen to specific message types
agent.on('text', async (ctx) => {
console.log(`Text message: ${ctx.message.content}`);
});
agent.on('reaction', async (ctx) => {
console.log(`Reaction: ${ctx.message.content}`);
});
agent.on('reply', async (ctx) => {
console.log(`Reply to: ${ctx.message.content.reference}`);
});
// Listen to unhandled events
agent.on('unhandledError', (error) => {
console.error('Agent error', error);
});
agent.on('unknownMessage', (ctx) => {
console.error('Message type is unknown', ctx);
});
Best practice example
import { filter } from '@xmtp/agent-sdk';
const agent = await Agent.createFromEnv();
agent.on('message', async (ctx) => {
// Filter for specific message types
if (filter.isText(ctx.message)) {
await ctx.sendText(`Echo: ${ctx.message.content}`);
}
});
Next steps
- Learn about middleware and routing to add cross-cutting behavior
- Explore message filters to process messages selectively
- Understand context and helpers for rich message handling