ReferenceComponents

confirm_card

Server-built approval for a write or destructive action.

The safety mechanism, drawn. Before a write or destructive action runs, the server synthesizes a confirm_card from your action manifest: the summary comes from your confirmTemplate, the parameters come from the invocation the server already validated, and the model never touches either.

That is the whole point. A hallucination cannot misstate what the user is approving, because the model did not write the card.

This cannot be undoneCancel order 1042 and refund $129 to the original card?
Order1042
Refund$129.00
ConfirmGo back

Re-rendered in the browser from the SDK’s own scales. Not a screenshot.

Rendered natively by the Flutter SDK and the Web SDK, both since 0.1.0.

When not to use it

You cannot use it. confirm_card is the one block type the model may not emit. It is absent from the render_ui tool by construction, and no host code creates one either.

If you want the user to choose between options, that is quick_replies or plan_comparison. If you want them to supply values, that is form. Confirmation is not a choice; it is an approval of something already fully specified.

Props

Every block also carries type and a required fallback_text of 1 to 300 characters.

PropTypeRequiredConstraints
invocation_idstringYesServer-assigned.
action_namestringYesThe registered action this card approves.
summarystringYes1 to 300 characters. Rendered from your confirmTemplate.
paramsobjectYesMachine-readable. This is what the handler runs on.
params_displayarrayYesUp to 12 entries. Human-readable only.
params_display[].labelstringYesUp to 60 characters.
params_display[].valuestringYesUp to 200 characters.
riskwrite | destructiveYesread actions never produce a card.
confirmactionYes{ kind: "confirm", invocation_id } or { kind: "cancel", invocation_id }. See Actions. The server sends confirm here.
cancelactionYes{ kind: "confirm", invocation_id } or { kind: "cancel", invocation_id }. See Actions. The server sends cancel here.
expires_atstringNoISO 8601 in UTC (...Z); a numeric offset fails validation. The server stamps every card, write and destructive alike, ten minutes out. Past it the SDK refuses to confirm and the card shows as expired. The server enforces it too, with 150 seconds of grace on top, because the handler runs on the device before the result is posted and the manifest lets a handler take up to 120. It measures from when the card was created, not from when the user pressed, and a decline is accepted however late.
executesserverNoserver for a console action the API runs itself, as the signed-in user, once the confirm is recorded. The device has no handler for it: on confirm it records the decision and sends back a success result with no data, and the server answers with what happened. Absent for an action the device runs.

On the wire

{
  "id": "blk_09",
  "type": "confirm_card",
  "fallback_text": "Confirm cancelling order 1042.",
  "props": {
    "invocation_id": "inv_8f21",
    "action_name": "cancel_order",
    "summary": "Cancel order 1042 and refund $129 to the original card?",
    "params": {
      "order_id": "1042"
    },
    "params_display": [
      {
        "label": "order_id",
        "value": "1042"
      }
    ],
    "risk": "destructive",
    "confirm": {
      "kind": "confirm",
      "invocation_id": "inv_8f21"
    },
    "cancel": {
      "kind": "cancel",
      "invocation_id": "inv_8f21"
    },
    "expires_at": "2026-08-27T10:10:00Z"
  }
}

Interaction

Confirm runs your registered handler with params and posts the result as a new request. Go back posts a declined tool result, so the turn resolves either way and the thread never sits waiting on a card nobody answered.

params_display is a rendering. Every value in it has been through String() and truncated at 200 characters, so nothing may ever be reconstructed from it. The SDK runs params or it runs nothing. A card that somehow arrives without machine-readable params is reported as an error rather than executed on a guess.

Only confirm and cancel are legal here. The general UIAction union does not apply.

States

StateWhat the SDK draws
DestructiveThe plate's edge goes to full ink at 1.5pt and an eyebrow reads "This cannot be undone". The accent stays on the confirm button: weight carries the warning, so a host never has to own a red it did not choose.
ResolvedThe buttons are replaced by "Confirmed" or "Not confirmed", which stays on the card. Scrolling back through the thread still shows exactly what was agreed to.
Not answeredThe user asked something else while the card was open. Both ends treat that as an answer: the SDK marks the card "Not answered" before the new message goes out, and the server closes the invocation so the turn's history is valid. A card left behind is never confirmable again, so tapping it later cannot run a handler whose result nothing will accept.
ExpiredThe buttons are replaced by an "Expired" mark and the line "Nothing was done. Ask again to start it over." A destructive card also releases its raised edge, since there is nothing left to warn about. The card watches its own clock, so it changes the moment the deadline passes rather than at the next unrelated redraw.
Handler not registered on this deviceThe card resolves as declined and an error result is posted, rather than leaving the thread parked on a card that does nothing when tapped.
LoadingA plate with a short eyebrow line, two body lines and two 44pt button shapes, so the card does not double in height when it hydrates.

Accessibility

The card is the most important thing a screen-reader user will hear in the thread. fallback_text is written by the server and states the action and its object. Both buttons are 44pt, and the resolution is announced as a live region so the outcome is spoken without the user hunting for it.