Dynamic action buttons that provide context-aware interactions with each response
Action buttons allow you to provide context-aware actions with each assistant response. Users can trigger handovers, open URLs, send queries, or emit custom events.
💡 Tip: Click the "Chat with Acme" button in the bottom-right corner to open the widget and try the demo scenarios.
Try typing these messages in the widget to see different action button patterns:
// Via message interceptor
messageInterceptor: async (message, context) => {
return {
handled: true,
response: {
text: "Hello! How can I help you?",
role: "assistant",
actions: {
position: "bottom",
alignment: "center",
spacing: "0.75rem",
actions: [
{
id: "chat-agent",
label: "Chat with Agent",
icon: { type: "emoji", content: "💬" },
action: { type: "trigger_handover" },
style: {
backgroundColor: "#2563eb",
iconColor: "#ffffff",
},
behavior: {
oneTimeUse: true,
},
},
],
},
},
};
};Triggers agent handover following the established handover pattern. Emits "handover" event. Supports custom message override.
{
type: "trigger_handover",
payload: {
reason: "user_requested",
priority: "normal",
message: "Connecting you to our priority support team...", // Optional custom message
metadata: {
/* optional */
},
},
}Opens URL with security validation (http/https/tel/mailto only).
{
type: "open_url",
url: "https://example.com/page",
target: "_blank", // or "_self", "_parent", "_top"
}Emits custom event through event emitter. Emits "customAction" event.
{
type: "send_event",
eventName: "download_statement",
eventData: {
/* optional */
},
}Sends a query on behalf of the user. Useful for quick shortcuts to common questions. Supports optional displayText to show different text in chat vs what's sent to API.
{
type: "send_query",
queryText: "What are your pricing plans?",
displayText: "Show Pricing" // Optional: shown in chat instead of queryText
}Disables the action after the first click. Useful for actions like "Request Callback" that shouldn't be repeated.
When combined with oneTimeUse, disables ALL buttons in the group when any button is clicked. Perfect for mutually exclusive choices like plan selection.
Auto-disables the action after N more conversation turns. Useful for time-sensitive offers or context-dependent actions.
widget.on("actionClick", (data) => {
console.log("Action clicked:", data.actionId, data.actionType);
});
widget.on("handover", (data) => {
console.log("Handover triggered:", data.reason);
});
widget.on("customAction", (data) => {
console.log("Custom event:", data.eventName, data.eventData);
});
widget.on("sendQuery", (data) => {
console.log("Query sent:", data.queryText, data.displayText);
});