Make an action consequential
A consequential action is one whose effect the user should own. Pick one of two shapes with the consequential prop.
Ring it for the user to press
Section titled “Ring it for the user to press”Pass consequential. When the assistant calls the action, the element is scrolled into view with a ring around it and the label above or below it. The user presses it, or dismisses the ring. From examples/app/app/orders/[id]/page.tsx:
<AssistedAction name="refund_order" label="Refund this order" consequential> <Button variant="destructive" disabled={!refundable} onClick={() => shop.call("refundOrder", [order.id])} > Refund </Button></AssistedAction>The model sees the action marked “(consequential)”. Its call answers Rang "<label>" for the user; pressing it is theirs. A disabled or missing element answers so, and nothing rings.
Ask in the panel, then press
Section titled “Ask in the panel, then press”Pass consequential="confirm". When the assistant calls the action, the panel shows a card with the label and Approve and Deny. On approval the action is pressed. A denial is final for that call. From examples/app/app/orders/page.tsx:
<AssistedAction name="cancel_order" id={order.id} label={`Cancel ${order.customer}'s order #${order.id}`} consequential="confirm"> <Button size="sm" variant="outline" onClick={() => shop.call("cancelOrder", [order.id])} > Cancel </Button></AssistedAction>The model sees the action marked “(asks first)”. In a group, the card asks about the one row the assistant picked. The element is checked again after approval, in case it left or became disabled while the card waited.
The card is unstyled markup on data-assisted-confirm. The registry’s assisted-cards item styles it. See Install the panel.
Ask before a tool runs
Section titled “Ask before a tool runs”A tool has no element to ring. consequential: true on useAssistedTool asks in the panel and runs execute only on approval:
export function Refund({ refund }: { refund: () => Promise<void> }) { useAssistedTool("refund_order", { description: "Refund this order.", parameters: { type: "object", properties: {} }, consequential: true, execute: async () => { await refund(); return "Refunded the order."; }, }); return null;}The card shows the tool’s description.
Ring an element from your own code
Section titled “Ring an element from your own code”useRing returns a function that rings an element. The ring leaves when the component unmounts:
export function WhereToSave() { const ringAt = useRing(); const save = useRef<HTMLButtonElement>(null); return ( <> <Button ref={save}>Save</Button> <Button variant="ghost" onClick={() => save.current && ringAt(save.current, { message: "Save is here" })} > Where do I save? </Button> </> );}ring(element, { message }) does the same outside React and returns a function that dismisses it.