Cette page est publiée en anglais et en ukrainien ; la version anglaise figure ci-dessous.
Actions a turn sends: navigate, handoff, events
For developers, in code: the action vocabulary a turn can emit — navigate, handoff, a custom event, close_widget, listen — their fields, the confirm flag, and what a host does with each.
A turn’s actions[] is what the assistant asks the host to do. The widget turns each into a
pair of DOM events (Events) and acts on some of them itself; a custom front
end reads them straight off the done frame or the /message response.
The Action model: type, url, label, source_id, targets[], collect, source,
payload{}, confirm. Only the fields a type uses are meaningful.
navigate
{
"type": "navigate",
"url": "https://shop.example/pricing",
"label": "Open: Pricing",
"source_id": "…",
"referral_kind": "auto_redirect"
}
Emitted only on a real decision: the visitor commanded it («take me to pricing», in any
navigation mode), the agent’s mode is auto and the page is a strong match, or the visitor agreed
to an offer. referral_kind — auto_redirect, suggestion, confirmed, citation — names the
offer and is what the /followed beacon must echo. With confirm: true it is a question: the
assistant asked «take you there, or explain here?», the host must not navigate, and the next
reply is judged as agreement or refusal. The widget: same origin, same tab, one per turn, held
during a spoken answer, cancelable.
A page merely worth opening is not an action: it arrives in nav_suggestions[] as a plate
(≤ 1), and a click on the plate is the visitor opting in.
handoff
{
"type": "handoff",
"collect": true,
"source": "agent",
"targets": [
{ "mode": "url", "value": "https://wa.me/380…?text=…", "channel": "whatsapp" },
{ "mode": "email", "value": "mailto:help@example.com?subject=…&body=…", "channel": "email" }
]
}
The assistant offered a person: targets are the owner’s link-outs in the owner’s order, each
with its derived channel (whatsapp · telegram · viber · email · link) and the
question already in the link; collect says to show the in-chat contact form; source is
agent (it gave up) or asked (the visitor asked). The host draws the buttons and the form, and
reports a pressed link with POST /handoff/opened.
A custom event
{ "type": "show_products", "payload": { "products": [ … ] }, "suppress_navigate": true }
An owner’s event, type its name, payload its fields. The host renders it; nothing is fed back.
With confirm: true it is held until the visitor agrees. Custom events.
close_widget and listen
{ "type": "close_widget" } — the visitor asked the assistant to close («close yourself», in any
language). { "type": "listen" } — the visitor told it to be quiet and listen («stop»); the widget
drops to listening. Both are performed by the widget itself; a host only observes.
plan — internal
A held page-action press travels as { "type": "plan", "confirm": true, "page": "/…", "steps": [ … ] }. It exists so the consent chips and the agreement judge need no new machinery;
a host must never dispatch or replay it — the server applies it through the page-actions bridge
on the visitor’s yes.
Scrolling is not an action
scroll_to_element and scroll_page are bridge round trips during the turn, not actions on
done: for scroll_page the widget dispatches a cancelable shukai:action:scroll event before it
scrolls so a host can take over, but nothing scroll-shaped appears in actions[].
The confirm flag, in one paragraph
Any action may carry confirm: true. It means: do not act; show the question; the server kept
the offer and will judge the next reply in any wording. The widget’s accept chip performs a
held navigate (reported with kind: "confirmed") or dispatches a held event itself; agreeing in
words makes the server replay it; a held press (plan) is always applied by the server. One turn holds one offer: a held press beats an event teaser, which
beats a page redirect.