Launch priceOne payment

Approval Request

A human-in-the-loop gate that shows the thing itself — the email, or a record's fields before and after — with the permissions it will use and why it is risky. Reject asks why in one click, Request changes sends it back with a note, high-risk actions can ask twice, and an approval that fails on your server stays open with the error. Once decided it folds to a one-line record.

Ready for AI tools one file typed props installs by name prompt included

The decision inside it

Rejecting is as useful as approving

A bare "No" leaves the agent stuck. Reject offers reasons in one click and hands them to the agent, so it can try another way instead of asking again.

Installation

How you get it

Paste this into Claude Code, Cursor, Codex or any coding agent. It installs the file and uses it as it is, instead of writing a new one.

Use Layro's Approval Request for this.
Install it: npx shadcn@latest add @layro/approval-request
Import it from @/components/ui/approval-request.
Do not rewrite or restyle it. Pass my data through its props
and keep its built-in states.

For the full brief with every prop and the mistakes assistants usually make, use Copy prompt above. Pro components install through the @layro registry with your CLI token: see the Namespaced tab.

API

“Copy prompt” above puts a full brief on your clipboard — install command, dependencies, props, and the mistakes an assistant usually makes with this component.

Props

Read from the component’s own TypeScript interface when the site is built, so this table cannot drift from the file you install.

PropTypeNotes
titlerequiredReact.ReactNodeWhat the agent wants to do, as an action: "Send an email to Olivia".
descriptionReact.ReactNodeWhy it wants to, in a sentence.
toolstringThe tool it will call: `email.send`.
riskApprovalRiskDefault `medium`.
detailsApprovalDetail[]The facts of the action: To, Subject, Amount.
previewReact.ReactNodeThe thing itself: the message, the change, the file.
changesApprovalChange[]Before and after, for an action that edits a record.
scopesstring[]The permissions the action uses: "gmail.send", "crm.write".
targetReact.ReactNodeWhere it lands: "Vela Labs · Gmail". Shown beside the tool.
requestedByReact.ReactNodeWho or what asked: "Renewal agent".
riskExplanationReact.ReactNodeWhy it carries this risk, in a sentence from your backend.
requireConfirmationbooleanApprove asks once more before it counts.
onRequestChanges(note: string) => void | Promise<void>Adds "Request changes": send it back with a note instead of a yes or no. May return a promise.
submittingbooleanSet while your server is acting on the answer, if you track it yourself.
errorReact.ReactNodeAn error from your side, shown above the buttons.
statusApprovalStatusControlled state. Leave it out and the card keeps its own.
defaultStatusApprovalStatus—
onApprove(options: { remember: boolean }) => void | Promise<void>May return a promise: the card waits for it, and stays open if it rejects.
onReject(reason?: string) => void | Promise<void>May return a promise, like `onApprove`.
onEdit() => voidAdds an Edit button, for changing the action before it runs.
rememberLabelReact.ReactNodeAdds a checkbox with this label: "Always allow email.send in this run".
reasonsstring[]One-click reasons offered on Reject.
expiresAtDate | number | stringWhen the request stops being answerable. Shows a countdown.
onExpire() => void—
decidedByReact.ReactNodeShown on the folded record: "by you", "by Michael Carter". Default "by you".
decidedAtReact.ReactNodeShown on the folded record: "10:42".

Dependencies

npm packages

clsxframer-motionlucide-reacttailwind-merge

Layro foundations, installed alongside it

layro-themebadgebuttoncheckboxtextarea

Lifetime access

Every component, and everything we ship next.

  • All 112 components, source included
  • The template, and everything released after you buy
  • shadcn CLI or download — React 18/19, Tailwind v4
  • One payment. No subscription.

More in AI Agent

All AI Agent components