Send messages while a function runs
Check or change a function's version in the editor's status bar. See Runtime versions.
A function can tell the user what's happening while it works, instead of keeping them waiting until it finishes: text, quick-reply buttons, cards, an image, a video or a file. Each message reaches the user the moment the function sends it, and the function keeps running.
import { apis } from "@yellow/bot";
import { sendMessage } from "@yellow/bot/responses";
export default async function* ({ orderId }) {
yield sendMessage("Let me check that order for you…");
const response = await apis.execute("getOrderStatus", { orderId });
return { status: response.body.status };
}
- Each builder from
@yellow/bot/responsesdescribes one message.yieldis what sends it. - What the function returns is still its result, as before. The agent reads it and decides what to say next.
- On chat channels each message is its own bubble, and looks the same as when a workflow's Output node sends it. On a voice call only text is spoken.
Types of messages
| Builder | Sends |
|---|---|
sendMessage(text) | Text |
sendQuickReplies(prompt, options) | A prompt with tappable options. On WhatsApp they show as buttons. |
sendCards(cards) | One or more cards, each with a title and an optional description, image and buttons |
sendImage(url) | An image |
sendVideo(url) | A video |
sendFile(url, { name, size, type }) | A file to download, with an optional file name, size in bytes and MIME type |
import { sendMessage, sendQuickReplies, sendCards, sendImage, sendVideo, sendFile } from "@yellow/bot/responses";
import { haltTurn } from "@yellow/bot/agent";
export default async function* ({ name, amount }) {
const reference = "LN-" + Date.now().toString(36).toUpperCase();
yield sendMessage(`Thanks ${name}, your application is saved. Your reference is ${reference}.`);
yield sendQuickReplies("What would you like to do next?", [
"Check eligibility",
{ title: "Talk to a loan officer", value: "officer" },
{ title: "Loan FAQ", url: "https://example.com/faq" },
]);
yield sendCards([
{
title: `Application ${reference}`,
description: `₹${amount} for ${name}`,
image: "https://example.com/loan.png",
buttons: ["Track application", { title: "Help", url: "https://example.com/help" }],
},
]);
yield sendImage("https://example.com/offer.png");
yield sendVideo("https://example.com/how-it-works.mp4");
yield sendFile("https://example.com/terms.pdf", { name: "Loan terms.pdf", type: "application/pdf" });
return haltTurn({ reference });
}
Options and buttons
A quick-reply option or a card button is either a string or an object:
| Field | Meaning |
|---|---|
title | The label the user sees |
value | What is sent back when the user taps it. Leave it out to send the label. |
url | A link opened when tapped, instead of sending anything back |
image | An image shown with the option. Quick-reply options only. |
A string is both the label and the value: "Check eligibility" is the same as { title: "Check eligibility" }.
Where messages are sent
| Where the function runs | Messages |
|---|---|
| An AI agent calls it as a tool | Sent to the user. On a voice call only text is spoken; the other kinds are skipped and the function carries on. |
| The Run button | Listed under Sent to the user in the run panel, each with its kind. See Test and debug. |
| A Function node in a flow | Not sent yet. The node gets the return value only. |
Chat or call
On a voice call only sendMessage is spoken. To offer choices on both, check context.callSid, which is "" outside a call:
import { sendMessage, sendQuickReplies } from "@yellow/bot/responses";
export default async function* ({ slots }, context) {
const options = slots.slice(0, 3);
if (context.callSid) {
yield sendMessage(`I have ${options.join(", ")}. Which one suits you?`);
} else {
yield sendQuickReplies("Pick a time:", options);
}
return { offered: options };
}
Don't repeat yourself
After the function returns, the agent replies as usual, so it may say again what your messages already said. When the messages already cover everything, return haltTurn so the agent waits for the user instead, as in the example above.
The agent's history records everything the user saw as text, so on the next turn it knows what is on the screen. For example, quick replies are recorded as Buttons: 1. Check eligibility 2. Talk to a loan officer …. Image and file links appear as their URLs; a card's image doesn't. Put anything the agent should remember, such as a reference number, in what you return as well as in the messages.
Limits
| What | Limit |
|---|---|
| Messages in one run | up to 10; sending more stops the function with an error |
| One message | up to 256 KB |
| Text, and the quick-reply prompt | 1 to 4,096 characters |
| Quick-reply options | 1 to 10 |
| Cards | 1 to 10 |
| Buttons on a card | 1 to 5 |
| Option, button and card titles | up to 256 characters |
| Card descriptions, option values, file names and types | up to 1,024 characters |
Links (url, image, and the URL of an image, video or file) | http:// or https://, up to 2,048 characters |
size of a file | a whole number of bytes |
Lengths count characters: a plain emoji such as 😀 is one, while a combined one such as 👨👩👧 counts as several.
When something is wrong
The function stops with an error that names the field, so the user never gets a broken message. Messages yielded before the mistake are already sent, so test with Run first.
| Mistake | Error |
|---|---|
| An empty or missing title | sendCards(cards): cards[0].title must be a non-empty string |
| A misspelled field | sendQuickReplies(prompt, options): options[0] has an unknown key "vaule"; allowed: title, value, url, image |
| A link that isn't http(s) | sendImage(url): url must be an http(s) URL |
| Too many items | sendQuickReplies(prompt, options): options may have at most 10 items |
- Only messages built with
@yellow/bot/responsesare sent. Yielding anything else, such as plain text or an object, sends nothing; the run panel marks it Not a message. - Call actions and agent actions are returned, not yielded. Yielding
endCall(),transferCall()orhaltTurn()stops the function with "return them, don't yield them".