Designing an approval workflow for AI-placed orders
Figures on this page are as of 2026-09. Fees, limits and margin tiers change — check the venue's own docs before acting on a number.
Adding a confirmation dialog is easy. Designing one that still carries information on its two-hundredth appearance is the actual problem, and most implementations do not survive it.
This is about the second thing.
What the specification asks for
MCP’s tools specification is more specific than “ask the user”:
Clients SHOULD:
- Prompt for user confirmation on sensitive operations
- Show tool inputs to the user before calling the server, to avoid malicious or accidental data exfiltration
The second item is the substantive one. Not a notification that a tool ran, not a name — the inputs, before the call.
For an order, the inputs are the trade. Symbol, side, quantity, price, order
type. A dialog reading “Claude wants to use place_order. Allow?” technically
satisfies “prompt for confirmation” and conveys nothing. You are approving a
verb.
The design problem is fatigue, not consent
Every approval step degrades. The first few are read carefully. By the fiftieth the hand moves before the eyes do. This is not a discipline failure; it is how attention works, and a design that requires it not to happen is a design that will fail.
So the question is not “should we confirm?” but “how do we keep the confirmation carrying information?” Three things help.
Confirm state changes, not everything. If reading balances also prompts, the
prompt stops meaning “something consequential is about to happen” and starts
meaning “the software is doing things”. The signal is gone before the first
order. The line that works is mutation versus read — and MCP’s annotation
vocabulary names exactly this distinction with readOnlyHint, even though the
annotation itself cannot be trusted as a permission.
Make the content differ. A dialog that looks identical every time is processed as a shape, not as text. If the size is unusual for your account, the dialog should not look the way it looks for a normal size. Variation is what attention hooks onto.
Let hard limits handle the obvious cases. An order that exceeds your per-trade cap should not be presented for approval at all — it should be rejected. Asking a human to be the check on things a function can check is how you spend attention on the cases that do not need it and run out for the ones that do.
What to put on the card
A useful approval screen answers “what happens if I say yes” without arithmetic.
The trade itself — symbol, side, quantity, order type, entry, stop. The parameters as they will be submitted, not as they were discussed.
The consequence, computed. What this costs if the stop is hit, in currency
and as a percentage of the account. This is the single highest-value element,
because it converts a quantity you have to reason about into the number you
actually care about. A decimal-place error is invisible in 0.5 BTC and obvious
in “risks 41% of account”.
The resulting state. Position after this fills, and total exposure. Orders are rarely evaluated in isolation and usually presented that way.
Which limits were checked. Briefly. “Within per-trade cap; daily loss 0.4% of 2%” tells you the guards ran, which is different from trusting that they exist.
The reasoning, secondary. Useful context, but it should not be the most prominent thing — it is the most persuasive element on the screen and the least verifiable.
Where approval flows go wrong
Approving a summary rather than the parameters. The model describes what it intends; you approve the description; the call is constructed separately. These are two artifacts and they can disagree. Approve the payload.
The batch. Five orders, one confirm. The click is priced at one decision and buys five.
Timeout defaults. Any behaviour on no-response other than “do nothing” turns inattention into authorisation.
Remember this choice. Reasonable for file permissions. For orders it converts a per-trade decision into a standing one, which is exactly the property you were trying to avoid.
Approval as the only control. If the human is the sole check, every failure is an attention failure, and attention is the least reliable component in the system. Approval should be the second line. Hard limits are the first.
The part that must not be in the prompt
Worth separating clearly, because they get conflated:
- The approval step is a human decision on a specific trade. It catches things that are wrong in ways only you can see — the model misread the situation, this is not what you meant, the size feels off for reasons you could not articulate in advance.
- The limits are rules you set in advance that do not require you to be present, alert, or in a good mood. They catch the things that are wrong in ways a function can see.
Limits written into a prompt are neither. They are suggestions to a probabilistic process, and they hold right up until the unusual situation that motivated them.
A reasonable shape
model drafts plan
→ deterministic limits evaluated (reject, do not display)
→ plan card shown with parameters and computed risk
→ human approves or rejects
→ order submitted
→ outcome logged against the plan
Two properties worth preserving. Limits run before display, so rejected orders never consume attention. And the outcome is logged against the plan, so you can later ask what you approved and what happened — which is what makes a review meaningful rather than nostalgic.
The specification also recommends clients “log tool usage for audit purposes”. For trading that log is not only forensic; it is the raw material for finding out whether your approvals were any good.
FAQ
Isn’t an approval step just friction?
For read-only tools, yes, and they should not have one. For order placement the friction is the product — it is the cost of the human staying in the loop the specification recommends. What is worth eliminating is unnecessary friction: approvals on reads, on orders that violate a limit and should be rejected outright, and on identical-looking dialogs that no longer carry information.
What should happen if the user does not respond?
Nothing. Any other default converts inattention into authorisation. A pending order that expires unsubmitted is a recoverable situation; one that submits on a timeout is not.
Should the approval screen show the model’s reasoning?
Show it, but not prominently. Reasoning is useful context and it is also the most persuasive and least verifiable element on the screen — a confident rationale makes an approval feel justified independently of whether the parameters are right. The parameters and the computed risk should dominate.
How is this different from just being careful?
Being careful is an attention budget that depletes; a structural control does not. The distinction matters most on the tenth trade of a bad day, when attention is at its worst and the decision is at its most consequential. The design goal is a system whose safety does not degrade in exactly the conditions where you need it.