The agent already sent the client email. I am staring at a recovery screen. A free model drafted the undo label. It sounds calm and finished. It wrote, You can undo this send. Can I actually reverse it?
The send API has no reverse path. I own this approval. The client owns the consequence. The last reversible moment is this card. Missing evidence should stop me here. Extra flavor text should not.
This is a research tutorial, not a launch story. I label every example as a protocol. I will not treat model copy as a finding. I will not invent an undo that product never shipped.
Freeze the decision, not the vibe
Name the decision before any model talks. Who may paste recovery copy into the system? What harm follows a false undo promise? Where does reversibility die?
I write those three answers on paper first. Decision owner is the designer on the review. Consequence is a billed or public action. Reversibility dies after the paste.
Does confidence in the draft change any of that? No. Tone is not evidence. A fluent sentence is still a hypothesis.
Here is the user flow I keep on the wall.
failed action
-> agent offers recovery
-> review card (human)
-> STOP if undo is unproven
-> HAND BACK if user must choose
-> paste copy only after proof
-> focus returns to the failed control
If that middle card is missing, I do not proceed. A pretty label is not a product.
Stage 1: Build the evidence card
I refuse a blank prompt at this stage. The card has fields, not vibes. Each field is either evidence or noise.
{
"decision_id": "recovery-undo-label",
"failed_action": "",
"action_already_committed": null,
"undo_api_exists": null,
"undo_window_ms": null,
"focus_return_target": "",
"model_origin": "",
"model_assumptions": [],
"copy_claims_undo": null,
"evidence_vs_hypothesis": {
"evidence": [],
"hypotheses": []
},
"stop_approval": true
}
Verification for this stage is boring on purpose. Every required field is present. Empty strings stay empty. Null stays null. I do not let a model fill undo_api_exists.
Which missing evidence should stop approval? A blank undo_api_exists stops me. A missing focus_return_target stops me. A missing failed_action stops me.
Which extra information is only noise? Synonym lists. Confidence percentages. Brand adjectives. A paragraph about empathy. None of that reverses the email.
Stage 2: Record the failed action in human language
I write the failed action as the user saw it. Not as the trace saw it. "Send proposal to Northwind" is the record. POST /messages is support, not the record.
Then I ask one mean question. Has this action already left our boundary? If yes, undo copy is probably a lie. If no, I still need a window.
failed_action: Send proposal to Northwind
action_already_committed: true
undo_api_exists: false
Verification: I can read those three lines aloud. A teammate who never saw the ticket still understands the harm. If they cannot, the record is too technical. Rewrite it.
Stage 3: Draft on a free model, then lock the origin
I need a disposable draft, not a source of truth. Disclosure: This article was prepared as part of MonkeyCode's product outreach. I used MonkeyCode's free model access and free server option only to generate candidate recovery sentences. The server does not prove the undo exists.
I keep the prompt small. I feed the evidence card. I forbid the model from inventing APIs.
You draft recovery copy only.
You may not claim undo unless undo_api_exists is true.
If undo_api_exists is false, offer hand-back, not undo.
Quote failed_action in the first sentence.
Do not fill evidence fields.
Return three candidates. Label each as hypothesis.
Verification: the response still contains hypothesis. The origin field is filled. model_assumptions lists what it guessed. If it guessed an undo API, I mark stop_approval true. I do not negotiate with that guess.
A free draft is useful like scratch paper. Scratch paper does not ship. Would you frame scratch paper in the design system? I would not.
Stage 4: Separate evidence from design hypotheses
This is the part teams skip. They paste the nicest sentence. Then they call it research.
I split the notebook in half. Left column is evidence. Right column is hypothesis. Nothing crosses without a source.
EVIDENCE
- Send already left the boundary
- No reverse endpoint in the contract
- User still has focus on Send
HYPOTHESIS
- "Undo send" reduces panic
- A 10-second window would feel fair
- Users want a joke in the error
The left column can stop the paste. The right column cannot approve it. A joke in the error is noise here. Panic reduction is also untested. It does not create an API.
Verification: every sentence on the right starts with "might". Every sentence on the left names a source. If I cannot name the source, it moves right.
Stage 5: Run three research scenarios with stop conditions
I do not recruit a panel for this gate. I run a tabletop first. If the tabletop fails, live sessions would only decorate the failure.
Scenario A. The send already went out. The user is still on the screen. The draft says Undo. Stop condition: they believe the email can return. Success measure: they hear that it cannot, and they get a next step.
Scenario B. The send is queued for eight seconds. An undo API exists. Stop condition: focus jumps to a toast they never requested. Success measure: focus stays on Send, and the window is spoken.
Scenario C. The model offers both Undo and Edit recipient. Stop condition: two primary actions, no owner. Success measure: one action, one hand-back, one record of the discarded option.
I read those scenes out loud with a teammate. We do not act kind to the copy. Kindness is not a stop condition.
STOP if copy_claims_undo && !undo_api_exists
STOP if undo_window_ms is null && copy mentions a timer
STOP if focus_return_target is empty
HAND BACK if the user must pick a new recipient
NOISE: extra synonyms, mascot lines, model confidence
Verification: I can fail the draft with one of those STOP lines. If every draft still passes, my stops are too soft. Tighten them before any user session.
Stage 6: Accessibility review of the recovery path
Recovery is not a visual badge. It is a path back to control. I check the path like a person who cannot see the toast.
Does the announcement name the failed action? Does it avoid saying Undo when undo is false? Does focus return to the control that caused the send? Does a timer exist only when a real window exists?
# proposed live-region pattern, unexecuted
[role=status]
Send to Northwind already left this screen.
This send cannot be undone.
You are back on Send. You can edit the recipient.
I want that status before any button. A red inline error that never receives focus is a trap. A modal that steals focus and offers a fake Undo is worse.
Verification: keyboard only, then a screen reader pass. I tab from the failed control through the card and back. If I cannot return, the pattern fails. If the reader says Undo and the API cannot, the pattern fails. No extra copy will fix that.
Stage 7: Paste only after the card flips
The card stays red until proof exists. Proof is not a prettier synonym. Proof is undo_api_exists measured against the contract, plus a focus target, plus a honest first sentence.
// proposed check, unexecuted
function mayPasteRecovery(card) {
if (card.copy_claims_undo && card.undo_api_exists !== true) {
return { ok: false, stop: "undo claimed without api" };
}
if (!card.failed_action) {
return { ok: false, stop: "failed action missing" };
}
if (!card.focus_return_target) {
return { ok: false, stop: "no focus return" };
}
if (card.evidence_vs_hypothesis.evidence.length === 0) {
return { ok: false, stop: "no evidence listed" };
}
return { ok: true, stop: null };
}
Verification: I run the function against a lying draft and a honest draft. The lying draft must fail. The honest draft may still fail on focus. That is correct. Shipping without a return path is another kind of lie.
After a pass, I paste one sentence. I keep the discarded candidates in the decision record. Future me will thank present me. Future me is messy.
What this protocol is not
It is not a benchmark of free models. I have no latency table for you. I have no token quota to advertise. I have no claim that a free server makes recovery safe.
It is not permission to skip users. Tabletop stops are cheaper than harm. They are not a substitute for a session when undo is real and timed.
Who should not use this approach? Anyone hoping the model will invent a reverse API. Anyone pasting recovery copy into a design system without a contract check. Anyone who needs production uptime from a free scratch server. Anyone who treats outreach drafts as research evidence.
The useful question stays small. What missing proof should stop this paste? What extra sentence would only add noise? If you cannot answer both, do not ask a model for the label yet.
Top comments (0)