XMTP Agent SDK
Build event‑driven, middleware‑powered messaging agents on the XMTP network. 🚀
[!CAUTION]
This SDK is in beta status and ready for you to build with in production. Software in this status may change based on feedback.
Documentation
Full agent building guide: Build an XMTP Agent
This SDK is based on familiar Node.js patterns: you register event listeners, compose middleware, and extend behavior just like you would in frameworks such as Express. This makes it easy to bring existing JavaScript and TypeScript skills into building conversational agents.
Installation
Choose your package manager:
npm install @xmtp/agent-sdk
pnpm add @xmtp/agent-sdk
yarn add @xmtp/agent-sdk
Quick Start
import { createUser, createSigner, Agent, getTestUrl } from "@xmtp/agent-sdk";
const user = createUser();
const signer = createSigner(user);
const agent = await Agent.create(signer, {
env: "dev",
dbPath: null,
});
agent.on("message", async (ctx) => {
await ctx.conversation.send("Hello from my XMTP Agent! 👋");
});
agent.on("start", () => {
console.log(`We are online: ${getTestUrl(agent)}`);
});
await agent.start();
Environment Variables
The XMTP Agent SDK supports environment variables (process.env
) to simplify configuration without code changes.
Available Variables:
Using the environment variables, you can setup your agent in just a few lines of code:
process.loadEnvFile(".env");
const agent = await Agent.create();
Core Concepts
1. Event‑Driven Architecture
Subscribe only to what you need using Node’s EventEmitter
interface.
Events you can listen for:
message
– a new incoming (non‑self) message
start
/ stop
– lifecycle events
error
– surfaced errors
Example:
agent.on("error", (error) => {
console.error("Agent error", error);
});
2. Middleware Support
Extend your agent with custom business logic using middlewares. Compose cross-cutting behavior like routing, telemetry, rate limiting, analytics, and feature flags, or plug in your own.
Example:
import { CommandRouter } from "@xmtp/agent-sdk";
const router = new CommandRouter();
router.command("/version", async (ctx) => {
await ctx.conversation.send(`v${process.env.npm_package_version}`);
});
agent.use(router.middleware());
3. Built‑in Filters
Instead of manually checking every incoming message, you can compose simple, reusable filters that make intent clear.
Example:
import { withFilter, filter } from "@xmtp/agent-sdk";
agent.on(
"message",
withFilter(filter.startsWith("@agent"), async (ctx) => {
await ctx.conversation.send("How can I help you?");
}),
);
const combined = filter.and(filter.notFromSelf, filter.textOnly);
agent.on(
"message",
withFilter(combined, async (ctx) => {
await ctx.conversation.send("You sent a text message ✅");
}),
);
For convenience, the filter
object can also be imported as f
:
import { filter, f } from "@xmtp/agent-sdk";
const longVersion = filter.and(filter.notFromSelf, filter.textOnly);
const shortVersion = f.and(f.notFromSelf, f.textOnly);
You can find all available prebuilt filters here.
4. Rich Context
Every message
handler receives an AgentContext
with:
message
– decoded message
conversation
– the active conversation object
client
– underlying XMTP client
- Helpers like
sendText()
/ sendTextReply()
Example:
agent.on("message", async (ctx) => {
await ctx.sendTextReply("Reply using helper ✨");
});
Adding Custom Content Types
Pass codecs when creating your agent to extend supported content:
import { ReplyCodec } from "@xmtp/content-type-reply";
const agent = await Agent.create(signer, {
env: "dev",
dbPath: null,
codecs: [new ReplyCodec()],
});
Debugging
FAQ (Quick Hits)
Does middleware run for every message? | Yes, in the order added. |
How do I reject a message early? | Don’t call next() in middleware. |
How do I filter messages? | Use withFilter(...) around an event listener. |
Can I send custom content types? | Yes, register codecs during agent creation. |
Contributing / Feedback
We’d love your feedback: open an issue or discussion. PRs welcome for docs, examples, and core improvements.
Build something delightful. Then tell us what you wish was easier.
Happy hacking 💫