Documentation

Human handoff

Sooner or later a visitor needs a person. This page covers how your assistant makes that happen — by sending the request to a support inbox, or by pushing it into a system you run — and how to configure it.

Everything here lives in the Human Handoff card on the Channels tab of the assistant editor. Expand the card to configure it. Its header counts the escalation channels you have configured — only the ones the assistant is actually served, so the count never claims a hand-off route the AI was never given.

How a conversation reaches a person

Your assistant does not guess. Turn on at least one escalation channel and it is given an escalate_to_human tool, which it calls when a visitor asks for a human, when it cannot resolve the issue, or when the subject is billing, account access, a complaint, or something similarly sensitive. The channel Description you write is how the model decides which of your channels fits the situation.

Handoff works the same way in text chat and in voice conversations.

Your team answers an escalation later, so before one is sent the assistant has to have a way to reach the visitor back. If it has neither an email address nor a phone number for them, the escalation is rejected and the assistant is told to collect the details and try again. That check runs on the server, so it holds regardless of what the browser sends. The one exception is when the visitor was asked and explicitly declined; the assistant can then send the request anyway rather than lose it.

Escalation channels

Add a channel with Add channel, or + Add Channel once you have at least one. You can save up to five per assistant.

Every channel has the same four controls, whatever its type:

Control Notes
Channel Type Email or Webhook. Changing the type clears the type-specific fields
Enabled Off keeps the channel configured but hides it from the assistant. The badge reads Active or Disabled
Display Name What the visitor sees on the button. Up to 100 characters
Description Up to 500 characters. This is written for the assistant, not the visitor — it is how the model decides which channel fits the situation, so be specific ("For urgent billing issues")

Remove Channel at the bottom of a channel deletes it. Changes take effect when you Save the assistant.

Note

If an assistant carries a channel whose type this deployment does not serve, the card badges it Unavailable instead of Active, and the assistant is never offered it. Change its type or remove it.

Display mode

Both types have a Display Mode setting:

  • Inline in Chat — the action happens in the conversation itself.
  • Open in Popup Window — Hiroi opens a small standalone window with a single call-to-action button. If the browser blocks the popup, the widget falls back to the inline behaviour.

Leave Webhook on Inline in Chat. A webhook has nothing for a visitor to click, so popup mode gives them an empty window — and the request is not delivered.

Email

Field Notes
Support Email Where the escalation is sent
CC (optional) A second address, copied on every escalation
Include conversation transcript On by default. Attaches the last 20 messages of the conversation to the email

In Inline in Chat mode Hiroi sends this email itself, so there is no button for the visitor to click. The message carries the urgency the assistant assigned, its summary of what the visitor wants, the issue, and the visitor's name and contact details. The visitor sees a confirmation in the chat. If sending fails, no confirmation is shown — a retry button appears instead.

In Open in Popup Window mode the visitor gets a Send Email button that opens their own mail client instead — Hiroi does not send the email.

Webhook

Use this to push escalations into your own system — a ticket queue, an on-call pager, a Slack relay you host.

Field Notes
Webhook URL Your endpoint. http:// and https:// only
HTTP Method POST, PUT, or PATCH

Hiroi sends a JSON body:

{
  "event": "escalation",
  "site_id": "...",
  "site_name": "Acme Support",
  "visitor": { "name": "Dana Reed", "email": "dana@example.com" },
  "issue": {
    "reason": "Card declined on renewal",
    "summary": "Wants the renewal retried on a new card before Friday",
    "urgency": "high"
  },
  "transcript": [ { "role": "user", "content": "..." } ]
}

transcript is included whenever the widget sends one — webhook channels have no transcript toggle in the editor, so it is always included. It is capped at the last 20 messages, each truncated to 500 characters. urgency is low, medium, or high.

Requests time out after 10 seconds, redirects are not followed, and URLs that resolve to a private address are refused. Any response status below 400 counts as delivered; anything else shows the visitor a retry button. This delivery is not signed — if you need a signature and a delivery log, use an Action instead.

Events for Actions

If you are wiring the hand-off into your own tooling, escalation.triggered is available to Actions. It fires when the assistant uses an escalation channel, carrying the channel type, the reason, the urgency and the visitor's name and email — and it fires before delivery is attempted, so subscribe to it if you want your own alerting independent of whether the channel itself succeeded.