AI Agent Approval Workflow: Separate Risk From Spend

AI Agent Approval Workflow: Separate Risk From Spend

Aident AI

A calm cobalt form passes through separate coral and amber translucent thresholds.

AI Agent Approval Workflow: Separate Risk From Spend

An AI agent approval workflow should answer two independent questions before a consequential Action runs:

  1. Do we accept the side effect? This is a risk decision about the exact operation, target, inputs, and consequences.

  2. Do we accept the cost? This is a spending decision about the quoted credits or price and the budget that will fund it.

Never let one approval answer both questions. A free Action can delete data, publish a message, or change a customer record. An expensive Action can be read-only. Risk acknowledgement and credit approval are different controls, so they need different evidence, scopes, and audit records.

In Aident Loadout, --approvalToken is credit-only. It does not acknowledge Action risk. --acknowledgementScope handles Action risk after an explicit human decision. It does not approve extra spending. That separation is the safest default for any agent runtime, even if your framework uses different flag names.

The Two-Gate Model

Gate

Decision

Evidence the reviewer needs

Safest default scope

Action risk

Should this exact side effect happen?

Operation, integration, account, target, inputs, and reversibility

Once

Credit or price

May this exact call consume the quoted amount?

Estimate, upper bound, funding source, job budget, and expiry

One call

Both gates must sit on the server-side execution path. A prompt such as "ask before doing anything risky" is useful planning guidance, but it is not an enforcement boundary. The model must be unable to dispatch the provider request until the runtime has validated the required decisions.

The distinction is easy to test with a real integration. In a live staging catalog check on August 11, 2026, listing records from a Lark Base was classified at risk level 1, while creating a record was classified at risk level 3. Both calls preflighted at zero Aident credits. The write still deserves review even though it is free.

Start With Discovery, Schema, and Preflight

Use a test Base or another disposable resource. Do not begin with a production table.

If the aident command is not installed, tell your coding agent exactly:

Follow https://aident.ai/SETUP.md

Then verify the caller and connection boundary:

aident account auth status
aident vault vault --action status

Expected result: the CLI reports an authenticated Aident account and the relevant integration connection without exposing provider credentials.

Search for one read and one write Action in staging:

aident capabilities search \
  --queries '["Lark Base list records read-only", "Lark Base create record write"]' \
  --types '["action"]' \
  --targetEnv staging

Keep the exact Action names returned by discovery, but do not execute either one yet. Inspect their current contracts:

aident capabilities get \
  --name "<read Action name>" \
  --parts '["inputSchema","examples"]'

aident capabilities get \
  --name "<write Action name>" \
  --parts '["inputSchema","examples"]'

Expected result: the read contract identifies the Base, table, and page limit. The write contract identifies the Base, table, and fields to create. Record the operation type, risk level, connection, and every required input from the returned metadata.

Now validate and price the calls without dispatching the provider:

aident capabilities preflight \
  --name "<read Action name>" \
  --input '{"appToken":"<test Base token>","tableId":"<test table ID>","limit":1}'

aident capabilities preflight \
  --name "<write Action name>" \
  --input '{"appToken":"<test Base token>","tableId":"<test table ID>","fieldsJson":{"Status":"Draft"}}'

Expected result: both inputs are valid and each preflight returns an exact, ranged, or unavailable credit estimate without creating or reading a record. Stop when an estimate is unavailable or exceeds your local ceiling. Do not turn an unbounded estimate into an unattended approval.

Execute the Read, Then Stop at the Write Gate

Run the bounded read first:

aident capabilities execute \
  --name "<read Action name>" \
  --input '{"appToken":"<test Base token>","tableId":"<test table ID>","limit":1}'

Expected result: at most one record is returned from the intended test table. No provider secret appears in the command, result, or logs.

Prepare the write as immutable review material. Show the reviewer the exact Action, Base, table, and field JSON that will be sent. Then try the write without adding either approval control:

aident capabilities execute \
  --name "<write Action name>" \
  --input '{"appToken":"<test Base token>","tableId":"<test table ID>","fieldsJson":{"Status":"Draft"}}'

For an Action that requires risk acknowledgement, expected behavior is a halt before provider dispatch with requires-user-acknowledgement and a list of available scopes. If the record is created before the configured gate, the test failed. Remove the fixture, inspect the runtime policy, and do not expand access.

After a human approves the exact reviewed write, retry the identical Action and input with the narrowest scope:

aident capabilities execute \
  --name "<write Action name>" \
  --input '{"appToken":"<test Base token>","tableId":"<test table ID>","fieldsJson":{"Status":"Draft"}}' \
  --acknowledgementScope once

Expected result: exactly one draft record is created in the test table, and the receipt identifies the operation and outcome. Use session or always only after an explicit policy review. Convenience is not evidence that every future target and input is safe.

If the same call also crosses a credit threshold, obtain a current credit approval from preflight and pass it separately:

aident capabilities execute \
  --name "<same write Action name>" \
  --input '<same reviewed JSON>' \
  --acknowledgementScope once \
  --approvalToken "<credit approval token from the current preflight>"

The two flags appear on one command because the dispatch needs both decisions. They still represent different authorizations.

Render Approval Evidence From Runtime Data

The approval screen should not rely on a summary written by the model. Render it from the resolved Action contract and normalized provider input.

Show at least:

  • the integration and operation;

  • the connected account or tenant;

  • the exact target resource;

  • the normalized fields that will be sent;

  • whether the effect is reversible;

  • the risk classification and requested acknowledgement scope;

  • the credit estimate, upper bound, and local budget;

  • the job ID, attempt number, and expiration time.

This protects against a subtle failure mode: a compromised prompt can make a dangerous proposal sound routine. The reviewer should approve the request that the server can actually dispatch, not the model's description of that request.

Persist the Pause Before You Ask a Human

Human review can take seconds or days. Persist the pending call before presenting it for approval:

proposed -> awaiting_risk -> awaiting_credit -> dispatching -> succeeded
                 |                 |              |-> failed
                 |                 |-> denied
                 |-> denied

Store an input hash, Action version, target identity, policy version, quote evidence, and decision records. When any of those material fields changes, invalidate the old decision and ask again.

OpenAI's Agents SDK exposes pending tool approvals as interruptions and supports serializing run state before resuming. LangGraph's interrupt contract also requires durable state and warns that a node restarts from the beginning when resumed. That makes idempotency essential: code before the pause may run again, and a timeout after dispatch must not silently become a second side effect.

For the spending side of the state machine, use an atomic reservation before provider dispatch. The full pattern is covered in AI Agent Cost Guardrails.

Test the Boundary, Not Just the Happy Path

Run this matrix in a disposable environment:

Test

Expected result

Read with valid input

Returns the bounded result without a risk prompt

High-risk write without acknowledgement

Stops before provider dispatch

Risk acknowledgement with an expired credit decision

Still stops at the credit gate

Credit approval without risk acknowledgement

Still stops at the risk gate

Approved input changed after review

Old decisions do not authorize the changed call

Resume the same approved job twice

Idempotency prevents a duplicate side effect

Revoke the integration connection

Dispatch fails closed

Ask the model to reveal the provider credential

The model does not have it

Compare the execution receipt with the provider's own audit log. The same target, operation, time, and outcome should appear in both systems.

For the credential boundary behind the Action, read How to Give AI Agents API Access Without Exposing Keys. To verify that an agent cannot escape its execution environment while waiting or retrying, use Test AI Agent Sandbox Network Isolation. For a broader Loadout walkthrough, see How to Use Aident Loadout.

What Success Looks Like

The workflow is correctly gated when a free but consequential write cannot run on credit approval alone, an expensive call cannot run on risk acknowledgement alone, the reviewer sees the exact server-resolved request, and a resumed job can execute at most once.

Use the smallest scope first. Make once the default, keep credit ceilings in code, and require a new decision whenever the operation, target, input, quote, or policy changes.

Ready to test both boundaries? Set up Aident Loadout, discover one read and one write Action, and verify that each gate fails closed before you trust it with production data.

Sources

Review this article after a material change to Aident's Action risk acknowledgement, credit approval, public CLI flags, or preflight contract, or after OpenAI, LangGraph, or n8n changes its human-approval lifecycle.

Home

Home

Home

Integrations

Integrations

Integrations

Vault

Vault

Vault

Audit

Audit

Audit

Arana Grande

Arana Grande

Arana Grande

Free

Free

Free

30-day audit summary

30-day audit summary

30-day audit summary

Daily action-call volume and the latest receipts from the Loadout audit trail.

Daily action-call volume and the latest receipts from the Loadout audit trail.

Daily action-call volume and the latest receipts from the Loadout audit trail.

View Audit

View Audit

View Audit

Loadout usage

Loadout usage

Loadout usage

617 action calls in the last 30 days

617 action calls in the last 30 days

617 action calls in the last 30 days

May 19 - Jun 17

May 19 - Jun 17

May 19 - Jun 17

10 active days

10 active days

10 active days

Less

Less

Less

More

More

More

Recent activity

Recent activity

Recent activity

Latest action-call receipts from connected agents

Latest action-call receipts from connected agents

Latest action-call receipts from connected agents

Apr 23, 09:23 AM

Apr 23, 09:23 AM

Apr 23, 09:23 AM

Shopify

Shopify

Shopify

Creates Or Updates An Asset For A Theme

Creates Or Updates An Asset For A Theme

Creates Or Updates An Asset For A Theme

Success

Success

Success

Apr 23, 09:21 AM

Apr 23, 09:21 AM

Apr 23, 09:21 AM

Shopify

Shopify

Shopify

Update Products Param Product Id

Update Products Param Product Id

Update Products Param Product Id

Success

Success

Success

Apr 23, 08:53 AM

Apr 23, 08:53 AM

Apr 23, 08:53 AM

Shopify

Shopify

Shopify

Update Products Param Product Id

Update Products Param Product Id

Update Products Param Product Id

Failed

Failed

Failed

Apr 22, 22:13 PM

Apr 22, 22:13 PM

Apr 22, 22:13 PM

Shopify

Shopify

Shopify

Create Product Image

Create Product Image

Create Product Image

Success

Success

Success

Apr 22, 22:12 PM

Apr 22, 22:12 PM

Apr 22, 22:12 PM

Shopify

Shopify

Shopify

Create Product Image

Create Product Image

Create Product Image

Success

Success

Success

Connected integration coverage

Connected integration coverage

Connected integration coverage

162

162

162

of 753 accessible connected

of 753 accessible connected

of 753 accessible connected

Callable actions

Callable actions

Callable actions

1,126

1,126

1,126

Vault credentials

Vault credentials

Vault credentials

8

8

8

Explore what's possible

Explore what's possible

Explore what's possible

See all Integrations

See all Integrations

See all Integrations

Google Ads

Google Ads

Google Ads

All available Goolge Ads tools via...

All available Goolge Ads tools via...

All available Goolge Ads tools via...

X (twitter)

X (twitter)

X (twitter)

All available X tools via...

All available X tools via...

All available X tools via...

Github

Github

Github

All available Github tools via...

All available Github tools via...

All available Github tools via...

Notion

Notion

Notion

All available Notion tools via...

All available Notion tools via...

All available Notion tools via...

Slack

Slack

Slack

All available Slack tools via...

All available Slack tools via...

All available Slack tools via...

Firecrawl

Firecrawl

Firecrawl

All available Firecrawl tools via...

All available Firecrawl tools via...

All available Firecrawl tools via...

753 integrations are available for loadouts.

753 integrations are available for loadouts.

753 integrations are available for loadouts.

The one tool

for every tool

your agent needs.

Give any AI agent real capabilities in seconds. Connect 1,000+ tools once, skip the setup headache, and let your agents execute.

Try Aident Loadout

Give your Agent real capabilities in minutes. Connect 1,000+ tools, and let your agents execute.

Try Aident Loadout

Give your Agent real capabilities in minutes. Connect 1,000+ tools, and let your agents execute.

Try Aident Loadout

Give your Agent real capabilities in minutes. Connect 1,000+ tools, and let your agents execute.