Skip to content

Automation  ·  AI operations

How to build human approval for agent actions

An agent is about to email four hundred customers and the only thing between it and them is somebody noticing. Here is the model behind an approval step, the prompts that build it, and what it takes to run in production.

Built with Tray Headless

  1. System Agent
  2. Step Classify blast radius
  3. Step Below threshold: act
  4. Step Above: request approval
  5. System Slack
Also Audit record

The threshold is blast radius instead of confidence, and an approval request that expires defaults to not acting.

The short answer

What is agent action approval?

Agent action approval is four parts: a threshold based on blast radius rather than on model confidence, a request that shows the approver exactly what will happen, an expiry that defaults to not acting, and a record of who approved what. The part that goes wrong most often is using confidence as the trigger. A model is often most confident when it has misunderstood, so confidence decides nothing useful and reversibility decides everything.

What matters here

  • Trigger on blast radius, not model confidence. A model is frequently most confident when it has misunderstood.
  • Show what will actually happen: the records, the recipients, the amounts. Not a summary the model wrote of its own plan.
  • Expire to no action. An approval nobody answers must never default to proceeding.
  • Route to whoever owns the consequence, not whoever is nearest. The approver has to be able to judge it.
  • If approval rates sit near 100%, the threshold is wrong and everybody is rubber-stamping.

Who this is for

You run AI operations or platform engineering. Agents are doing useful work and the question of what they may do without asking has not been answered.

How it works in practice

What happens between an agent deciding to act and the action happening.

  1. 1

    The action is classified by blast radius

    How many records, is it reversible, does it reach a customer, does it move money.

  2. 2

    Below the threshold it proceeds and is logged

    Approval for everything trains people to approve without reading.

  3. 3

    Above it, a request goes to whoever owns the consequence

    With the actual effect shown, not a summary the model wrote.

  4. 4

    The approver sees the real payload

    Records, recipients, amounts and a diff where something is being changed.

  5. 5

    No answer means no action

    The request expires and the agent is told it was not approved, never that it timed out into proceeding.

  6. 6

    The decision is recorded either way

    Who, when, what was shown, and what happened afterwards.

What an approval step is made of

Four pieces, and the first is a judgement about reversibility.

A blast radius threshold

Record count, reversibility, whether it is customer-facing and whether money moves. Confidence is not on that list for good reason.

A request showing the real effect

The payload, the recipients, the diff. An approver reading a model summary of its own plan is not reviewing anything.

A safe expiry

Unanswered means not approved. Anything that defaults to proceeding turns approval into a delay, not a control.

A decision record

Who approved, what they were shown, and what happened. That record is what makes the whole arrangement defensible.

The Tray Headless prompts

Paste these into Claude Code or Codex with the Tray Headless plugin installed. Each stage runs on its own. The systems named in them are the worked example rather than a requirement, and every prompt says so.

Once per project, run /tray-workflows:set-workspace to pick the workspace these build in. Point it at a sandbox first.

  1. 1

    First, define blast radius, not confidence

    The trigger is the design, and confidence is the wrong one.

    Headless skills build-workflow

    Use build-workflow.
    
    Classify every agent action before it executes:
    
      Record count: how many things change
      Reversibility: can this be undone, and how easily
      Customer-facing: does anything reach somebody outside the company
      Financial: does money or an entitlement move
      Destructive: does anything get deleted or overwritten irrecoverably
    
    Then set the threshold on those, never on model confidence. A model is
    frequently at its most confident when it has misunderstood the request,
    so confidence tells you about the model instead of about the risk.
    
    Start conservative: anything customer-facing, anything financial,
    anything touching more than a handful of records, and anything
    irreversible.

    Reversibility is the most useful of the five. An action you can undo in a minute rarely needs a gate; one you cannot always does.

  2. 2

    Show the approver what will actually happen

    A model summarising its own plan is not a review.

    Build the approval request to show the real effect, not a description:
    
      The exact records that will change, with a before and after diff
      For anything outgoing, the full recipient list and the actual message
      For anything financial, the amounts and the accounts
      What triggered the agent, and the instruction it was given
    
    Never show only the model's own summary of its plan. If it misunderstood
    the task, its summary will be a confident description of the wrong thing,
    and an approver reading it will approve.
    
    Cap the display and say so: showing the first twenty of four hundred
    records with the count is honest. Showing four hundred is unreadable, and
    unreadable is the same as unreviewed.
  3. 3

    Route to whoever owns the consequence

    An approver who cannot judge it will approve it.

    Route by what the action touches, not by who is available:
    
      Customer-facing goes to the account owner
      Financial goes to the budget owner or finance
      Data changes go to the system owner
      Anything above a higher threshold goes to two approvers
    
    Send it where they already work, not to a queue they would have
    to remember to open.
    
    Include enough context to decide without going elsewhere: the account,
    the amount, the history, the instruction. An approver who has to open
    three tabs will approve on the summary, which is the failure this whole
    step exists to prevent.
  4. 4

    Expire to no action, always

    Anything that defaults to proceeding is a delay, not a control.

    Headless skills tray-gotchas

    Use tray-gotchas, then set an expiry on every request, and expire to not
    approved.
    
    An unanswered approval must never proceed on a timeout. If that is
    unacceptable for a given action, the action does not need approval, and
    pretending otherwise gives everybody the reassurance of a gate without
    the gate.
    
    Tell the agent it was refused, in a form it can act on: not approved,
    expired without an answer, and what it should do instead.
    
    Handle these: an approver who is away, which routes to a deputy rather
    than waiting; a request superseded because the agent has moved on; and
    approval arriving after the underlying data changed, which should
    re-validate rather than execute a stale plan.
  5. 5

    Record it, and watch the approval rate

    A 99% approval rate means nobody is reading.

    Record every decision: who, when, exactly what was shown, the outcome,
    and what happened after it executed.
    
    Then report: approval rate by action type, median time to decision,
    expiries, and how often an approved action later needed correcting.
    
    If approval rates sit near 100%, the threshold is wrong. Either the
    agent is being gated on things that do not need it, in which case people
    are rubber-stamping and the real ones will be rubber-stamped too, or the
    requests are unreadable and everybody is approving on trust.
    
    Both of those look like a working process and neither one is.
  6. 6

    Test it, then hand the thresholds over

    Because what needs approving is a risk decision that will change.

    Run the per-step schema checks and the whole-workflow audit before this
    touches production. Run it in observe mode first: classify every action
    and request approval for nothing, then read a week of what would have
    been gated.
    
    Then open the same workflow in Tray Build so the team owning the agents
    can adjust thresholds and routing in the visual canvas as trust in a
    given agent grows.

What it connects to

The agent proposes, a person decides, and the record outlives both.

Slack

Send the request where the approver already works, with the real payload rather than a link to it.

Writes

Okta

Resolve the owning group from the ownership register to the people currently in it, so approval never depends on one named individual.

Reads

Salesforce

Read the records an action would change so a before and after diff can be shown.

Reads

Snowflake

Land every decision with what was shown, which is what makes the arrangement defensible afterwards.

Writes

Jira

Raise a record for anything refused, so a refusal is a conversation instead of a dead end.

Writes

Same build, other stacks

The design does not change if you run something else in one of these seats. The same prompts build it against Microsoft Dynamics 365, Google BigQuery, Microsoft Teams, Azure Active Directory, ServiceNow or HubSpot.

Named systems are the ones most teams run, not the only ones that work. Each is an authentication in your Tray workspace, referenced by name, so the workflow never holds a credential. Where we have a connector page, the name links to it.

Running it in production

This is the control between an agent and an irreversible action. It has to fail safe.

The platform runs it, not a laptop under a desk

Requests, expiries and re-validation run on the same engine, so an approval at 2am behaves exactly like one at midday.

Every decision is evidence

Who approved, precisely what they were shown, and what happened next. Showing a summary and recording a payload is not the same thing.

Credentials are managed, never in code

The approval step reads records to build the diff. Read-only, scoped, and held in your workspace instead of alongside the agent.

The agent team owns the thresholds

Blast radius rules and routing open in Tray Build, so a gate can be relaxed as trust in an agent is earned instead of assumed.

Expiry never proceeds

Unanswered is refused. Any action that cannot tolerate that does not need approval, and pretending otherwise is worse than having no gate.

Questions people ask

Why not trigger on model confidence?

Because a model is frequently most confident when it has misunderstood the request. Confidence tells you about the model, and reversibility tells you about the risk.

What should the approver see?

The actual effect: the records changing with a diff, the full recipient list, the amounts. Never only the model summary of its own plan, which will confidently describe the wrong thing if it misread the task.

What happens if nobody answers?

It expires as not approved. Anything that proceeds on a timeout is a delay rather than a control, and it gives everybody the reassurance of a gate without one.

Who should approve?

Whoever owns the consequence: the account owner for customer-facing actions, finance for money, the system owner for data. An approver who cannot judge it will approve it.

What does a 99% approval rate mean?

That the threshold is wrong. Either trivial actions are being gated, so people rubber-stamp and will rubber-stamp the real ones too, or the requests are unreadable and everybody is approving on trust.

Last reviewed September 2026.