The first time I saw an approval card do real work, it was not because the button said the right thing. It was because the card showed enough context that I could tell whether I was approving a harmless edit or a bad idea with a nice label on it.
That is the trap with approval UI. A team sees a risky action, adds a button, and assumes the system is safer. All they have really done is move the decision from the model to the user without giving the user much to decide about.
If the prompt only says “approve tool call,” the human is guessing. Guessing is not review.
The better version names the thing that will change, shows the scope, and tells me what happens next. For a blog edit, I want the filename, the number of paragraphs, the kind of change, and the verification step. For an email, I want the recipient, subject, and body. For a calendar change, I want the time, attendees, and timezone. For a database write, I want the table, filter, row count, and fields.
Tool names are developer language. People do not approve updateRecord or runCommand; they approve a specific side effect. The product should treat arguments as the real interface.
action
edit local file
target
src/content/blog/approval-buttons-need-context.mdx
change
replace current body with a rewritten article draft
why
current post still reads like generated template residue
after approval
write file, run markdown check
undo
restore previous file contents from git diff
That card is plain, which is the point. I can see the target, the scope, the reason, and the escape hatch. If I was expecting a typo fix and the agent was about to rewrite the whole post, I have a chance to stop it before the damage is committed.
The right amount of context also depends on risk. A read-only action can stay compact. A local file write needs more room. A destructive action needs even more. Anything that crosses an identity boundary or reaches outside the workspace should start expanded, not hidden behind a “more” link.
That is where a lot of approval flows go wrong. They collapse the details that matter because the design is trying to stay tidy. Tidiness is not the goal here. Decision quality is.
Timing matters too. A prompt can be technically accurate and still be useless if it arrives after the user lost the thread. When an approval appears minutes after the model has wandered through several intermediate steps, the UI needs to reconnect the person to the original request. What started this? What step is this? What is already done? What is still pending if I say yes?
I like prompts that carry a little history, not just the current action:
- original request
- current plan step
- files already inspected
- assumptions the agent is making
- what remains undone after this approval
That last line matters more than it looks. Approval is not completion. It is permission for one move. The user should know whether the agent will stop after this, continue automatically, or come back for another decision.
The agent also should not argue for the click. Models are very good at sounding reasonable. “I need to do this to complete your request” is not evidence. It is pressure with a clean interface.
What helps is evidence. The prompt should show why the system believes this action is the right one: the file still contains generated residue, the requested scope is a rewrite, the current checklist item points at this path, and the follow-up command is the configured checker. Then the human can verify the chain instead of trusting the model’s confidence.
Denials should be useful, not terminal. If the user says “wrong file,” “too broad,” “show me the diff,” or “stop,” that is information. It helps the system recover. It also tells you where the UI is failing. Repeated denials on expanded prompts usually mean the summary is vague. Repeated denials on shell commands usually mean the risk language is too thin.
After approval, I want a receipt that reads like a record, not a victory lap.
approved by
jeremy
approved action
edit local markdown file
approved target
src/content/blog/approval-buttons-need-context.mdx
executed
yes
verification
pnpm markdown:check passed for this file
That gives the next review pass a place to start. If something went wrong, the question is no longer “what did the agent do?” It becomes “where did the approved plan diverge from the result?”
I do not want approval steps everywhere. Too many of them turn the user into a click-through operator. But when the action matters, the button has to earn the click.
Related posts

About Jeremy London
Engineering leader and builder in Denver. I write about AI platforms, agents, security, reliability, homelab infrastructure, and the parts of engineering work that have to survive production.