Skip to main content
Most cards are scripted. The AI assistant card is the one that is not: it hands the conversation to a model and lets the visitor talk freely, for as long as it takes, before returning to the flow. It is deliberately not a second product. It runs on the same models, the same timeouts and the same function contract as a WhatsApp chat agent — so anything you already know about writing those applies here unchanged.

Open the flow canvas

Chat agents → your agent → Flow → drag in AI assistant

The Fields

Everything the flow has collected so far is appended to the prompt automatically, so the model already knows the visitor’s name, their order id and anything else an earlier card asked for. You do not have to paste variables into the instructions. Blocks publish: no instructions.

When The Card Ends

There is no turn cap and no “Done” button. The card ends when the assistant calls finish_conversation, then the flow takes the card’s single exit. That is deliberate. A counter ends a conversation mid-sentence, and a “That’s all, thanks” pill asks the visitor to answer a question only the assistant is placed to judge. The assistant is instructed to finish only when the person has clearly signalled they are done — goodbye, thanks that’s all, or confirming their question is fully answered. It is explicitly told not to finish because it could not help, because a function failed, because it did not understand, or because the request is outside its remit. In those cases it says so and lets the visitor decide.
The conversation as a whole is still bounded by the session limit of 200 turns, and there is a backstop at 30 exchanges on a single AI card. Neither should ever be reached in a real conversation.

Functions

Two kinds, and they mirror the WhatsApp chat agent’s function editor field for field.

Custom — your own Python

Write a LangChain tool. Decorate it with @tool, and its signature is the parameter list — nothing is declared separately.
The docstring says what it does; the Description field says when to use it. Both reach the model — the description is appended as “Usage Instructions”.

Send image / send document

No code. You give a name and a description; the assistant supplies the link. The description is where you say where the link comes from — “the URL returned by lookup_invoice”, or a fixed address. Same arrangement as the WhatsApp send functions.
link must be a public http(s) URL. Anything else is refused and the model is told so, so it can ask the right lookup function and try again.

What Your Code Can See

Three objects are injected into every custom function. No imports, no setup.

x_vars

Everything the flow has collected — Ask answers, Set values, API mappings, and anything passed in on the URL as vars.

x_contact

The CRM record for whoever is in this conversation — name, email, tags, custom attributes.

x_secrets

Your account’s secrets by name, so an API key never has to sit in plain text inside a flow graph.
Also in scope without importing: asyncio, httpx, json, re.
Never return a secret. A secret echoed into a chat is a secret in a transcript, readable by anyone who can open that contact. Use it, report whether you had it, and return the result — not the key.
Secrets and the contact record are only loaded when your code actually mentions x_secrets or x_contact. A card whose functions never touch them pays nothing for them.
Manage secrets at Settings → Secrets.

Files, Both Directions

The AI card is one of only two places a visitor can attach something (the other is a human handoff). The composer shows a paperclip and a microphone.

In — what the visitor sends

A PDF is fetched and its text extracted server-side, because no model here takes a PDF directly. If nothing could be extracted the model is told that explicitly, rather than the attachment being quietly dropped.

Out — what the assistant sends

A send_image or send_document call delivers the file to the visitor and writes it into the dashboard transcript as its own message with a real link — so a conversation full of images does not read as a conversation of empty replies.

What Gets Recorded

Every AI turn is stored so somebody reviewing the conversation can see what actually happened:
  • The reply, as the visitor read it
  • Every function call, with its arguments and its result, shown in the timeline’s tool panel
  • Every file sent, as its own message with the link
  • The cost of the turn
A reply that quotes an order number is unreviewable if the lookup behind it is invisible. That is why the calls are stored and not merely logged.

Billing

An AI card is the only card that runs a model, and it is the only one that costs anything.
  • Accounts on per-message pricing are charged their per-AI-message rate for the turn.
  • Everyone else is charged the real model cost, which is recorded on the message itself.
Every other card records zero, because that is what it is.

Billing

Plan, rates and the Widgets subscription

Writing A Good AI Card

An AI card that “handles anything” is a prompt nobody can test. Route the known topics with Buttons cards and let the AI card take what is left — then its instructions can be specific enough to be correct.
Ask for the order id on a scripted card first. The model then starts with it in x_vars instead of spending a turn asking, and your function can look it up immediately.
Errors reach the model as text. Without an instruction it will improvise. “If a lookup fails, tell the person exactly what the error said and offer to pass them to a person” is usually what you want.
The docstring already says what the function does. The Description field is read as usage instructions — “use this whenever the person asks about a delivery date” — and that is what makes the model call it at the right moment.
When the assistant finishes, the flow takes the card’s single exit. Wire it to an End card with a closing line, or back to your main menu — not to nothing.

Limits


Next Steps

Variables and identity

What lands in x_vars, and how uid works

Card types

The other thirteen cards