Send actions and handle intents
Actions let your agent send a message with tappable buttons. When the user picks one, the agent gets an intent event with the selected button's ID. This works well for confirmations, payment flows, menu navigation, and polls.
Send actions
Node
await ctx.conversation.sendActions({
id: `actions-${Date.now()}`,
description: 'Would you like to proceed?',
actions: [
{ id: 'action-yes', label: 'Yes', style: 'primary' },
{ id: 'action-no', label: 'No', style: 'secondary' },
],
});Each action button has the following fields:
id: Returned asactionIdin the intent when tappedlabel: The button textstyle(optional):"primary","secondary", or"danger"imageUrl(optional): An image to show alongside the buttonexpiresAt(optional): ISO 8601 timestamp after which the button expires
Set a top-level expiresAt to expire the entire prompt.
Payment example
Node
await ctx.conversation.sendActions({
id: 'payment_alice_123',
description: 'Choose amount to send',
actions: [
{ id: 'send_10', label: 'Send $10', style: 'primary' },
{ id: 'send_20', label: 'Send $20', style: 'primary' },
],
});Receive an intent
When a user taps a button, the SDK fires an "intent" event. Match on actionId to know which button was pressed.
Node
agent.on('intent', async (ctx) => {
const { actionId } = ctx.message.content;
if (actionId === 'send_10') {
await ctx.conversation.sendText('Sending $10...');
} else if (actionId === 'send_20') {
await ctx.conversation.sendText('Sending $20...');
}
});The intent payload has three fields:
id: The ID of the original action promptactionId: The ID of the button that was tappedmetadata(optional): Key-value context sent by the client

