action_done
One line saying what a reversible change did, with Undo.
Your user asked, and it is done: "Added INNER GOODNESS Oat Milk 1L to your cart · Undo". No card to tap first. An action that names the action that takes it back (undo) is a write that can run at once, and the server draws this line in the answer instead of a confirm_card. Adding to a cart, following, saving: changes the user would not want to approve every time, and can take back with one tap.
Drawn live in your browser with the SDK’s own sizes and colours, not a screenshot.
Rendered natively by the Flutter SDK since 0.69.0 and the web SDK since 0.46.0. A build that does not declare it is never sent one: its writes keep their confirmation card.
When it is drawn
Only by the server, never by the model. A write with an undo whose inverse is offered in the same turn, to a build that draws this block, runs with no card. A destructive action always asks. A write without an undo always asks. You can keep the card for one that has an undo with confirm: "always", in your code or under Actions › the action › Safety in the console.
The line is the model's sentence about what happened, in the user's language, held to the same rule as every card: any number in it must be one your actions returned. Without one, it is your confirmTemplate.
Props
Every block also carries type and a required fallback_text of 1 to 300 characters.
| Prop | Type | Required | Constraints |
|---|---|---|---|
invocation_id | string | Yes | Server-assigned: the invocation Undo takes back. |
action_name | string | Yes | The registered action that ran. |
text | string | Yes | 1 to 200 characters. The model's line about what happened, held to the numbers your actions returned; your confirmTemplate without one. |
undo_until | string | No | ISO 8601 in UTC (...Z); a numeric offset fails validation. Ten minutes after the action ran. Past it the SDK hides Undo, and the server refuses it. |
undone | boolean | No | Set on the stored block once it was undone, so a restored thread says so. |
On the wire
{
"id": "blk_14",
"type": "action_done",
"fallback_text": "Added INNER GOODNESS Oat Milk 1L to your cart",
"props": {
"invocation_id": "inv_3c90",
"action_name": "add_to_cart",
"text": "Added INNER GOODNESS Oat Milk 1L to your cart",
"undo_until": "2026-10-29T10:10:00.000Z"
}
}Interaction
Undo runs the inverse once through POST /v1/invocations/:id/undo, however often it is tapped. The server claims it, then either runs a console action's inverse itself or hands the SDK the inverse to run with its handler, and the line says "Undone". A failed undo says so, and can be tried again. Undo is offered for ten minutes after the action ran; the server refuses it after that, whatever the screen shows.
Accessibility
A status line: announced when it appears, and again when it says "Undone".