Approval
Asks before the agent acts. It names the action as a question, shows the risk with a word and an icon, previews what will be sent, and lets the person edit it first. The outcome stays in the thread.
Medium riskslack.post_message
Send this summary to #design-system?
Weekly update: 3 accessibility issues fixed on checkout, radius tokens shipped in Figma, Agent kit in review.
Add the source to a shadcn project
npx shadcn@latest add https://docs.atomus.io/r/ai-approval.jsonOpen in v0Installs the component source, its CSS and the Atomus tokens into components/atomus/. How the registry works
Risk levels
Section titled “Risk levels”Low riskfs.read
Read 3 files in /design-tokens?
High riskfigma.delete_variables
Delete 214 unused variables from the Figma file?
Collections: Color (128), Spacing (52), Radius (34). This can’t be undone from the assistant.
In Figma
Section titled “In Figma”From guidelines/components/ai-approval.md
Properties, variants and anatomy of the Figma components. React props use the same names.
Approval
Section titled “Approval”Human-in-the-loop confirmation before an agent acts: the action as a question, a short summary, the risk level, a preview of what will be sent or changed, and Approve / Deny. People can edit the content before approving and can allow the action for the rest of the chat. After they decide, the card stays in the thread with the outcome. Part of the Agent kit.
Figma: component set Approval on the 🤖 Agent kit page of Atomus 4.0 (node 25550:1196), connected to React with Code Connect. React props use the same names as the Figma properties below.
| Property | Type / options |
|---|---|
| Title | text |
| Summary | text |
| Risk | Low · Medium · High |
| Tool name | text |
| Details | slot (preview) |
| Editable | boolean (off) |
| Always allow | boolean (off) + label |
| State | Pending · Approved · Denied |
| Approve label · Deny label | text |
Risk
- Low — read-only or easy to undo; shield icon, success accent.
- Medium (default) — sends, posts or changes something people can fix; warning accent.
- High — deletes, pays, publishes or can’t be undone; error accent and border. Name the action on the button (“Delete variables”).
Anatomy
- Accent bar on the left in the risk colour, and a risk icon tile.
- Eyebrow: risk word (“High risk”) and tool name.
- Title (the question) and summary.
- Details or editable preview.
- Footer: “Always allow” checkbox; Deny, Edit, Approve.
- Outcome after the decision: “Approved”, “Approved with your edits” or “Denied”.
Use for
- Any agent action that writes, sends, spends, deletes or shares.
- Steps the person may want to adjust before they happen (an email, a message, a list of issues).
Not for
- Read-only actions the person already asked for: just run them and show a Tool call.
- Confirming a person’s own action in a form: use Modal.
Accessibility
- The card is a labelled region (
aria-labelledbythe title, described by the summary). - Risk is a word and an icon, never colour alone.
- Focus is not moved to the card when it appears (Primer: keep focus stable); it is reachable in reading order and the buttons are standard buttons.
- The outcome is announced in a status region.
import { Approval } from '@stanvision/atomus-react';
<Approval title="Send this summary to #design-system?" risk="medium" toolName="slack.post_message" editableText={draft} alwaysAllowLabel="Always allow posting to #design-system" status={decision} // 'pending' | 'approved' | 'denied' onApprove={({ alwaysAllow, editedText }) => run(editedText ?? draft, alwaysAllow)} onDeny={cancel}> The assistant will post one message as you.</Approval>Props at a glance
Section titled “Props at a glance”Full types and defaults are in React API at the end of the page.
title(the question),children(summary),risk(low·medium·high),toolName.detailsfor a read-only preview, oreditableTextfor edit-then-approve;onApprovereceives{ alwaysAllow, editedText }.alwaysAllowLabelshows the checkbox — never for high risk.statuskeeps the outcome visible after the decision;approveLabelnames the action (“Delete variables”).
Design guidance
Section titled “Design guidance”From the Figma guidelines.
Do
- Phrase the title as a yes/no question with the scope: “File 3 issues in Linear?”.
- Show exactly what will be sent or changed, and let people edit it when it is text.
- Keep the card in the thread after the decision so the record stays visible.
- Offer “Always allow” only for low- and medium-risk actions, scoped to this chat.
Forbidden
- Never run the action before the person approves.
- Never pre-tick “Always allow”.
- Never offer “Always allow” for high-risk actions.
- Never use a vague label such as “OK” or “Continue” — say what Approve does.
React API
Section titled “React API”Generated from react/src/components by scripts/gen-react-api.mjs — the same tables agents read in guidelines/components/ai-approval.md.
Use only these props; anything else is not part of the API.
Approval
Section titled “Approval”Figma: Approval — human-in-the-loop confirmation before an agent acts. Approve, deny, or edit then approve. The person stays the decision-maker; the outcome stays visible after they decide.
import { Approval } from '@stanvision/atomus-react'; — source: react/src/components/ai/Approval.tsx
| Prop | Type | Default | Description |
|---|---|---|---|
title |
ReactNode |
required | Figma: Title — the action as a question: “Send this email to 12 people?” |
children |
ReactNode |
— | Figma: Summary — what will happen and what it affects, in one or two sentences. |
risk |
'low' | 'medium' | 'high' |
'medium' |
Figma: Risk — low · medium · high; shown with an icon and a word, never colour alone. |
toolName |
string |
— | Figma: Tool name — the function that will run (send_email). |
details |
ReactNode |
— | Figma: Details — a preview of what will be sent or changed (read-only). |
editableText |
string |
— | Figma: Editable — plain text the person may edit before approving (“edit then approve”). |
editLabel |
string |
'Edit before approving' |
Label of the editable field |
alwaysAllowLabel |
string |
— | Figma: Always allow — shows the checkbox with this label (“Always allow send_email in this chat”). |
status |
'pending' | 'approved' | 'denied' |
'pending' |
Figma: State — pending asks; approved and denied show the outcome in place of the buttons. |
approveLabel |
string |
'Approve' |
Figma: Approve label — name the action for high risk (“Delete variables”) |
denyLabel |
string |
'Deny' |
Figma: Deny label |
onApprove |
(decision: ApprovalDecision) => void |
— | Called with the decision when the person approves (after any edits) |
onDeny |
() => void |
— | Called when the person denies; keep the card and set status="denied" |
className |
string |
— | Extra class on the root element (layout only — never restyle colours or sizes). |
Accepts only the props above.
ApprovalDecision:
| Field | Type | Description |
|---|---|---|
alwaysAllow |
boolean |
The “always allow” checkbox was ticked |
editedText? |
string |
The edited text, when the person used Edit before approving |