The widget can show a Create ticket button under an answer. It passes the conversation to a person, so the reader does not have to explain it again. The button stays hidden until you say where the conversation goes: an email address, a URL, or your own JavaScript. Use it for support escalation, sales or demo requests, bug reports, or to open a ticketing widget already on your page (Zendesk, Intercom and similar).

Handoff modes

data-handoff-mode sets what the button does. Setting data-handoff-email or data-handoff-url is enough on its own; the mode follows from it.
data-handoff-modeWhat a click doesNeeds
emailOpens the reader’s email app with a message to your address, the conversation in the bodydata-handoff-email
urlOpens your URL in a new tab: a ticket form, a chat, a Discord invitedata-handoff-url
customOpens nothing. Fires onAskAIHandoffOpen and then onAskAIHandoffSubmit for your codeA handler
custom-with-formThe same as custom. There is no built-in ticket formA handler
When both an address and a URL are set, the URL wins unless data-handoff-mode="email".

Email handoff

<script async src="https://widget.kelu.dev/kelu-widget.js"
  data-knowledge-base-id="YOUR_KNOWLEDGE_BASE_ID"
  data-client-key="kl_pk_..."
  data-handoff-email="support@example.com"></script>
Kelu sends nothing itself. The button is a mailto: link, so the message goes from the reader’s own email app and your reply goes straight back to them. Any helpdesk with an email address for new tickets turns it into a ticket.
  • Subject: the reader’s first question, up to 120 characters.
  • Body: the conversation and the page it was asked on, up to 1,800 characters so the link still opens in every email app.

Handoff to a URL

<script async src="https://widget.kelu.dev/kelu-widget.js"
  data-knowledge-base-id="YOUR_KNOWLEDGE_BASE_ID"
  data-client-key="kl_pk_..."
  data-handoff-url="https://example.com/support/new-ticket"
  data-handoff-button-text="Contact support"></script>
The URL gets no conversation attached. Use custom mode when the destination needs the conversation.

Handing off through code

With data-handoff-mode="custom", a click fires onAskAIHandoffOpen and then onAskAIHandoffSubmit, with the same payload:
FieldTypeWhat it holds
transcriptstringThe conversation as text. Each turn starts Question: or Answer:; answers keep their markdown
conversation{ role, text, citations }[]The same conversation as data
threadIdstringThe conversation’s id, once there is one
triggersMatchedstring[]The triggers that showed the button on this answer
The widget does not close itself. A typical handler closes it and opens the ticketing tool already on the page:
<script async src="https://widget.kelu.dev/kelu-widget.js"
  data-knowledge-base-id="YOUR_KNOWLEDGE_BASE_ID"
  data-client-key="kl_pk_..."
  data-handoff-mode="custom"></script>
<script>
  window.Kelu("onAskAIHandoffOpen", function ({ transcript }) {
    window.Kelu("close");
    // Replace with your ticketing tool's own API.
    myTicketingWidget.prefillForm({ message: transcript });
    myTicketingWidget.open();
  });
</script>
window.Kelu(...) exists only once the widget script has loaded. To register the handler from a script that may run first, preinitialize it. The two events also fire when the button is an email or URL link.

Configuring triggers

data-handoff-triggers is a comma-separated list of when the button appears. It shows under an answer when any listed trigger matches.
TriggerAlso acceptedThe button appears
alwaysUnder every answer. The default
uncertainuncertaintyUnder an answer that cited no sources, or that says it is not sure or could not find the answer
negative-feedbackdownvoteUnder an answer once the reader presses 👎 on it
conversation-lengthOnce the conversation has data-handoff-conversation-length-threshold answers (default 3)
data-handoff-triggers="uncertain,negative-feedback"
Unknown values are ignored. If none is recognised, the button falls back to always. data-uncertain-answer-callout adds a line of markdown under the same uncertain answers. It is a good place to say what the button is for:
data-uncertain-answer-callout="Not what you needed? Create a ticket below and our team will follow up."

Renaming the button

AttributeDefaultWhat it does
data-handoff-button-text"Create ticket"The button label, such as “Talk to sales” or “Report a bug”
Style it with the handoff-button component, such as data-handoff-button-background-color. See Component styles.

Reference

AttributeDefaultWhat it does
data-handoff-modeFrom the email or URLemail, url, custom, or custom-with-form (same as custom)
data-handoff-emailThe address the email goes to. Turns the button on
data-handoff-urlThe page the button opens. Turns the button on
data-handoff-triggersalwaysWhen the button appears
data-handoff-conversation-length-threshold3Answers before conversation-length matches
data-handoff-button-text"Create ticket"The button label
You can also set the email, URL, label and triggers on a widget integration, in the dashboard’s Hand-off tab under Integrations → Website widget. The mode and the threshold have no dashboard field, so set them on the tag. An attribute on the tag wins on that page.