This repository contains examples of agents that use the XMTP network.
- End-to-end & compliant: Data is encrypted in transit and at rest, meeting strict security and regulatory standards.
- Open-source & trustless: Built on top of the MLS protocol, it replaces trust in centralized certificate authorities with cryptographic proofs.
- Privacy & metadata protection: Offers anonymous or pseudonymous usage with no tracking of sender routes, IPs, or device and message timestamps.
- Decentralized: Operates on a peer-to-peer network, eliminating single points of failure.
- Multi-agent: Allows multi-agent multi-human confidential communication over MLS group chats.
See FAQ for more detailed information.
To run your XMTP agent, you must create a .env
file with the following variables:
WALLET_KEY= # the private key of the wallet
ENCRYPTION_KEY= # encryption key for the local database
You can generate random keys with the following command:
yarn gen:keys <name>
Warning
Running the gen:keys
or gen:keys <name>
command will append keys to your existing .env
file.
Dev
and production
networks are hosted by XMTP, while local
network is hosted by yourself. Use local network for development purposes only.
-
- Install docker
-
- Start the XMTP service and database
./dev/up
-
- Change the .env file to use the local network
XMTP_ENV = local;
There are to ways to fetch messages from a conversation, one is by starting a stream
const stream = client.conversations.streamAllMessages();
for await (const message of await stream) {
/*You message*/
}
And by polling you can call all the messages at once, which we stored in your local database
/* Sync the conversations from the network to update the local db */
await client.conversations.sync();
// get message array
await client.conversations.messages();
The new Group
and Dm
classes extend the Conversation
class and provide specific functionality based on the conversation type.
const conversations: (Group | Dm)[] = await client.conversations.list();
for (const conversation of conversations) {
// narrow the type to Group to access the group name
if (conversation instanceof Group) {
console.log(group.name);
}
// narrow the type to Dm to access the peer inboxId
if (conversation instanceof Dm) {
console.log(conversation.peerInboxId);
}
}
Because XMTP is interoperable, you may interact with inboxes that are not on your app. In these scenarios, you will need to find the appropriate inbox ID or address.
// get an inbox ID from an address
const inboxId = await getInboxIdForIdentifier({
identifier: "0x1234567890abcdef1234567890abcdef12345678",
identifierKind: IdentifierKind.Ethereum,
});
// find the addresses associated with an inbox ID
const inboxState = await client.inboxStateFromInboxIds([inboxId]);
interface InboxState {
inboxId: string;
recoveryIdentifier: Identifier;
installations: Installation[];
identifiers: Identifier[];
}
const addresses = inboxState.identifiers
.filter((i) => i.identifierKind === IdentifierKind.Ethereum)
.map((i) => i.identifier);
Interact with the XMTP network using xmtp.chat, the official web inbox for developers.
- gm: A simple agent that replies to all text messages with "gm".
- gpt: An example using GPT API's to answer messages.
- gated-group: Add members to a group that hold a certain NFT.
See all the available examples.
Examples integrating XMTP with external libraries from the ecosystem
See all the available integrations.