Skip to main content

Custom Components in Chat

You can inject custom interactive components (like video previews, loaders or buttons) directly inside your AI Agent chat. There are two ways to achieve this:

  1. Using frontend Callbacks — Add components dynamically via JavaScript callbacks when AI Agent sends data or triggers events.
  2. Using Tools/Actions - Return custom HTML components directly from a Function Node within your tools using the _agent_custom_components parameter.

Method 1: Custom Components Using frontend Callbacks

This method allows you to inject custom HTML components dynamically in the chat when AI Agent sends structured data or triggers specific events.

Load AI Agent Script and Initialize

Add the AI Agent script to your webpage before the closing </body> tag and initialize it with tools and callbacks.

<script type="application/javascript">
(function(w,d,s,o,f,js,fjs){
w[o]=w[o]||function(){(w[o].q=w[o].q||[]).push(arguments);};
js=d.createElement(s);
fjs=d.getElementsByTagName(s)[0];
js.id=o;
js.src=f;
js.async=1;
js.referrerPolicy="origin";
fjs.parentNode.insertBefore(js,fjs);
})(window,document,"script","copilot",
"https://script.copilot.live/v1/copilot.min.js?tkn=YOUR_TOKEN_HERE");

copilot("init", {}, function() {
// Register tools (optional)
copilot.tools.add([
{
name: "open_cart",
description: "Opens user's cart",
handler: () => ({ success: true, message: "Cart opened" }),
},
]);

// Handle Navigate button clicks
copilot.callbacks.add({
name: "call_api",
handler: (val) => {
// call internal api with the value provided
},
});

// Handle Quick Replies
copilot.callbacks.add({
name: "send_message",
handler: (val) => {
copilot("event", "sendUserMessage", { value: val.value });
},
});

// Custom component handler
copilot.callbacks.add({
name: "tool:components",
handler: (data) => {
const customDiv = document.createElement("div");
customDiv.innerHTML = `
<div style="max-width:560px;margin:12px 0;border:1px solid #ddd;
border-radius:10px;padding:14px;background:#f8f9fa;">
<h3 style="margin-bottom:8px;">🎥 YouTube Video</h3>
<iframe width="100%" height="300"
src="https://www.youtube.com/embed/44eFf-tRiSg"
frameborder="0" allowfullscreen></iframe>
<div style="display:flex;gap:10px;margin-top:10px;">
<button
data-callback-name="call_api"
data-callback-args='{"value":"product_id"}'
style="flex:1;padding:8px 12px;background:#0d6efd;
color:#fff;border:none;border-radius:8px;cursor:pointer;">
Like Video
</button>
<button
data-callback-name="send_message"
data-callback-args='{"val":"Add this product to my cart"}'
style="flex:1;padding:8px 12px;background:#dc3545;
color:#fff;border:none;border-radius:8px;cursor:pointer;">
▶️ Watch on YouTube
</button>
</div>
</div>
`;
return { id: "video-card", content: customDiv };
},
});
});
</script>
Custom YouTube video component with embedded iframe and action button rendered in the chat using script callbacks.

Adding Buttons to Custom Components

There are two ways to define or add buttons in your custom components:

Method 1: Using data-callback-type="instruction"

This is the simplest approach. Add buttons with data-callback-type="instruction" and they will automatically send responses back to the chat when clicked.

Example:

<!-- Button that triggers a chat instruction when clicked -->
<button
data-callback-type="instruction"
data-callback-name="quick_reply"
data-callback-args='{"value":"Sample action triggered"}'
>
Perform Action
</button>

<!-- Button to navigate the user to a specific URL -->
<button
data-callback-type="instruction"
data-callback-name="navigate"
data-callback-args='{"url":"https://example.com"}'
>
Navigate
</button>
Example of a custom component with multiple buttons configured with different callback types (instruction, navigate) for interactive user actions.

Method 2: Register the callback handler

Register a callback function with the same name as the button’s data-callback-name attribute. This function will automatically execute when the button is clicked. For additional details, refer to the section above.

copilot("init", {}, function() {
// Register callback to handle button clicks
copilot.callbacks.add({
name: "custom_action",
handler: (args) => {
// args will contain: {"action":"process_order","orderId":"12345"}
console.log("Processing order:", args.orderId);
// Perform your custom logic here
// For example: call an API, update UI, etc.
fetch('/api/process-order', {
method: 'POST',
body: JSON.stringify({ orderId: args.orderId }),
headers: { 'Content-Type': 'application/json' }
})
.then(response => response.json())
.then(data => {
// Optionally send a message back to chat
copilot("event", "sendUserMessage", {
value: `Order ${args.orderId} processed successfully!`
});
});
},
});
});
tip

Use data-callback-type="instruction" for simple actions like sending messages or navigating. Register custom callback handlers when you need to perform complex logic, API calls, or update your application state before responding to the user.


Method 2: Custom Components via Workflow

This method allows you to return custom HTML components directly from a Function Node in your workflow using the _agent_custom_components property.

Step 1: Add a Tool Node

Start with a Tool Node — for example, one that fetches data or performs a calculation. This Tool Node provides the data or context needed for your custom component.

Adding a Tool Node in the workflow to fetch data or perform calculations before creating custom components.

Step 2: Add a Function Node After the Tool

Add a Function Node immediately after your Tool Node. Inside this Function Node, you'll create and return your custom HTML using _agent_custom_components. The Function Node processes the data from the Tool Node and formats it into an interactive HTML component that will be displayed in the chat.

Function Node implementation showing how to return custom HTML components using the _agent_custom_components parameter.

Example Code

const _agent_custom_components = `
<div id="product-card" style="
max-width:480px;
margin:24px auto;
padding:20px;
background:#ffffff;
border:1px solid #e5e7eb;
border-radius:14px;
box-shadow:0 2px 6px rgba(0,0,0,0.05);
font-family:system-ui, sans-serif;
">
<h3 style="text-align:center;color:#0f172a;margin-bottom:12px;">🛒 Product Details</h3>

<div style="display:flex;align-items:center;gap:12px;margin-bottom:16px;">
<img
src="https://headsetsindia.com/wp-content/uploads/2020/06/evolve2_65b-1-750x750.jpg"
alt="Product image"
style="width:80px;height:80px;border-radius:8px;object-fit:cover;border:1px solid #d1d5db;"
/>
<div style="flex:1;">
<p style="margin:0;font-weight:600;color:#111827;">Wireless Headphones</p>
<p style="margin:2px 0 6px;color:#6b7280;font-size:14px;">Bluetooth 5.0, Noise Cancelling</p>
<p style="margin:0;color:#0d6efd;font-weight:600;">$59.99</p>
</div>
</div>

<div style="display:flex;flex-wrap:wrap;gap:10px;">
<!-- Add to Cart Button -->
<button
data-callback-type="instruction"
data-callback-name="quick_reply"
data-callback-args='{"value":"Added to cart"}'
style="flex:1;padding:8px;border:none;border-radius:8px;background:#198754;color:#fff;cursor:pointer;"
>
Add to Cart
</button>

<!-- Go to Checkout Button -->
<button
data-callback-type="instruction"
data-callback-name="navigate"
data-callback-args='{"url":"https://example.com/checkout"}'
style="flex:1;padding:8px;border:none;border-radius:8px;background:#0d6efd;color:#fff;cursor:pointer;"
>
Go to Checkout
</button>

<!-- View Details Button -->
<button
data-callback-type="instruction"
data-callback-name="navigate"
data-callback-args='{"url":"https://example.com/product"}'
style="flex:1;padding:8px;border:none;border-radius:8px;background:#6b7280;color:#fff;cursor:pointer;"
>
View Details
</button>
</div>

<div style="margin-top:14px;border:1px dashed #d1d5db;border-radius:8px;padding:10px;text-align:center;color:#374151;">
Status: <span id="status-value">Available in stock ✅</span>
</div>
</div>`;

return { _agent_custom_components };

Product card component displaying product information, image, price, and multiple action buttons (Add to Cart, Go to Checkout, View Details) rendered from workflow.
tip

Combine multiple buttons with different callback types to create richer, more dynamic user interactions directly inside your chat UI. For example, you could create a component with action buttons, navigation buttons, and status displays all working together to provide a complete interactive experience.

Kaily logo

More than just a virtual AI assistant, Kaily brings interactive, human-like conversations to your website. Easy to create, easier to customize, and the easiest to deploy—no code required. Let Kaily enhance your user experience using the information you provide.

Is this page useful?