Intent
MessageKit Intent allows bots to interpret and execute commands internally, giving them the ability to process user requests in a conversational manner.
Explicit commands
Explicit commands are directly handled by the bot through a well-defined structure. The bot uses the parameters provided to trigger specific actions.
Example:
A user wants to swap tokens:
/swap 1 eth usdc
MessageKit directly processes the parameters from the command and handles the parameters to return a Frame URL.
Declaring commands
import { HandlerContext } from "@xmtp/message-kit";
import { handleSwap } from "./handler/swap.js";
export const commands: CommandGroup[] = [
{
name: "Swap Bot",
description: "Swap bot for base.",
triggers: ["/swap", "@swap", "@swapbot"],
commands: [
{
command: "/swap [amount] [token_from] [token_to]",
handler: handleSwap,
description: "Exchange one cryptocurrency for another.",
params: {
amount: { type: "number", default: 1 },
token_from: { type: "string", values: ["eth", "usdc", "dai"] },
token_to: { type: "string", values: ["eth", "usdc", "dai"] },
},
},
],
},
];
Handling command responses
MessageKit will automatically handle the command parameters allowing you to focus on handling the command logic.
import { HandlerContext } from "@xmtp/message-kit";
export async function handleSwap(context: HandlerContext) {
const {
message: {
content: { command, params },
},
} = context;
const baseUrl = "https://{url}";
if (command === "swap") {
const { amount, token_from, token_to } = params;
if (!amount || !token_from || !token_to) {
context.reply(
"Missing required parameters. Please provide amount, token_from, and token_to.",
);
return;
}
// Generate URL for the swap transaction
let url_swap = generateFrameURL(baseUrl, "swap", {
amount,
token_from,
token_to,
});
context.reply(`${url_swap}`);
}
}
The bot will reply with the URL to the swap transaction.
{baseUrl}/swap?amount=1&token_from=eth&token_to=usdc
Natural language
Bots can also understand natural language prompts, allowing users to interact with the bot more conversationally. The bot translates the user's natural language input into a command and executes it.
Example:
A user types:
@swap 1 usdc to eth please
The message will trigger an AI text generation model to convert the natural language to a command.
You are a helpful and playful betting bot that lives inside a web3 messaging group.
Users can start a swap by tagging you in a prompt like "@swap 1 eth to usdc"
You then have an internal command to create a swap: "/swap [amount] [token_from] [token_to]"
Format examples:
/swap 1 eth usdc
/swap 100 dai usdc
/swap 0.1 eth usdt
The AI model will return this command:
/swap 1 usdc eth
And then the bot using intent
will execute the command. Internally MessageKit will execute the handler handleSwap
for the command as defined in the commands file seen before.
const { reply } = await textGeneration(userPrompt, systemPrompt);
if (reply.startsWith("/")) {
// Execute the command if it's a slash command
await context.intent(reply);
}
Reasoning (Multiple Commands)
Bots can manage multiple commands or steps in a sequence and wait for the user response at each step, enabling them to process more complex user requests.
Example:
A user interacts with the ENS bot:
lets register fabriethsf.eth
We already have the commands defined:
{
name: "ENS Bot",
commands: [
{
command: "/check [domain]",
handler: handleEns,
description: "Check if a domain is available.",
},
{
command: "/register [domain]",
handler: handleEns,
description: "Register a domain.",
},
{
command: "/info [domain]",
handler: handleEns,
description: "Get information about a domain.",
}
],
}
Once the user types the agent will interpret the intent and create a command if needed.
You are a helpful and playful ens domain register bot that lives inside a web3 messaging app.
- Only provide answers based on verified information.
- Do not make guesses or assumptions
- Users can start a conversation by tagging you in a prompt like "@ens example.eth" or chatting 1:1
- You can respond with multiple messages if needed. Each message should be separated by a newline character.
- You can execute commands by sending the command as a message.
## Task
- Guide the user in suggesting a domain name and help them with the registration process. You can trigger commands by only sending the command as a message.
- To trigger registration mini-app: "/register [domain]".
- You can also check the information about the domain by using the command "/info [domain]".
- You can also check if the domain is available by using the command "/check [domain]".
## Commands
- /help: Show the list of commands
- /check [domain]: Check if a domain is available
- /register [domain]: Register a domain
Format examples:
/register vitalik.eth
/check vitalik.eth
/info vitalik.eth
/help
In this case the agent creates 2 messages:
[
"Let's first check if the domain is available. ",
'/check fabriethsf.eth'
]
The check handler can return an api response:
return {
code: 200,
message: `Looks like ${domain} is available! Do you want to register it? https://ens.steer.fun/frames/manage?name=${domain}`,
};
The agent now has 2 messages to reply to the user and a response to the command /check fabriethsf.eth
.
for (const message of messages) {
if (message.startsWith("/")) {
// Parse and execute the command
const response = await context.intent(message);
await context.send((response as ApiResponse)?.message);
} else {
// Send the message as a text response
await context.send(message);
}
}
Short-Term Memory
Bots can maintain short-term memory, which allows them to remember recent interactions. This feature helps bots continue conversations and complete actions based on previous inputs without needing the user to repeat information.
const chatHistories: Record<string, any[]> = {};
let userPrompt = params?.prompt ?? content;
const { reply, history } = await textGeneration(
userPrompt,
systemPrompt,
chatHistories[sender.address],
);
chatHistories[sender.address] = history;
In summary MessageKit provides a way to handle commands and natural language in a conversational manner allowing for infinite use cases. Can't wait to see what you build!