Open the widget, press Advanced view in its header, then run a scenario. The app on the right is a real page in an iframe, and the assistant acts on it while you watch.
Two packages, two halves.
sgiant-ai-widget runs here and opens your app via
getAdvancedUrl.
sgiant-ai-agent-bridge
runs inside that app — one call, mountAiAgent() —
and publishes the controls marked data-ai-target. The page
being driven is app.html; open it
on its own and the bridge stays dormant, because it is a no-op unless
framed.
highlight and scroll-to draw an overlay on a
control without changing anything. This is the safe half of page control
— the assistant can point without touching.
[[action:{"name":"highlight","label":"Show me the save button",
"data":{"target":"save-settings"}}]]
fill writes a value and fires the events a framework
listens for, so React or Vue state updates rather than the DOM drifting
out of sync with it.
[[action:{"name":"fill","label":"Rename the property",
"data":{"target":"property-name","value":"Seaside Inn & Spa"}}]]
Fill two fields, then click Save — and the click carries a
confirm, so the user approves the only step that changes
anything.
[[action:{"name":"fill","label":"Set the notice period",
"data":{"target":"cancel-days","value":"7"}}]]
[[action:{"name":"fill","label":"Add a checkout note",
"data":{"target":"checkout-notes","value":"Late checkout on request."}}]]
[[action:{"name":"click","label":"Save the changes",
"confirm":"Save these settings?","data":{"target":"save-settings"}}]]
Scenario 2 above carries no confirm, and the widget asks
anyway — "Type 'Seaside Inn & Spa' into property-name?".
Anything that CHANGES the page is confirmed by default; only
highlight, scroll-to and
focus-field run straight through, because they change
nothing.
Setting confirm yourself replaces the wording with your
own, which is what scenario 3 does for the save. You cannot turn the gate
off — a model that has been talked into something should not be able to
silently type into a form.
An id and, for fill, a value. Never a
selector. There is no message that can express "click the third
div", so a compromised parent — or a model talked into something — cannot
reach a control the page never marked. Origins are allow-listed on both
sides and default to same-origin.
// in your app
import { mountAiAgent } from "sgiant-ai-agent-bridge";
mountAiAgent({ allowedOrigins: ["https://your-widget-host.example.com"] });
<button data-ai-target="save-settings">Save changes</button>
// in the widget host
createAiChatWidget({ getAdvancedUrl: () => "/app" });