In this article
September 15, 2026
September 15, 2026

AI agent approval workflows: handling edits and retries

Add human approval to AI agent tool calls. Learn how to review exact requests, resume execution, and handle edits and retries with Airlock.

Explore with AI
Open in ChatGPT
Open in Claude
Open in Perplexity

Approving an agent's $1,200 refund should authorize that refund to that customer. If the agent changes the amount or selects another charge before execution, the original approval should no longer apply. This guide walks through an AI agent approval workflow that binds a human decision to one tool call and resumes execution after approval.

A request enters a gateway and branches into green, red, and amber paths, with a person above the approval path.

WorkOS Airlock can require human approval before a governed agent call proceeds. It is available in early access. The example below shows how your application can preserve the proposed action, resume it after approval, and recover when the provider's response is uncertain.

All code is pseudocode, not an Airlock SDK or API example. It assumes enforcement is enabled and a policy requires approval for the refund. Monitor mode alone does not pause calls. The refund integration and recovery logic are application responsibilities.

Save the action the reviewer will approve

Consider a support agent that handles duplicate-charge tickets. Your policy permits refunds for confirmed duplicates but requires a billing approver above $500. For a $1,200 refund, show the customer, charge, amount and currency, linked billing evidence, and the reason for escalation. “Allow the refund tool?” is too broad. The reviewer needs to approve a particular transaction.

Build and persist that request before sending it through Airlock. For a provider such as Stripe, include an idempotency key: a stable identifier for attempts at the same refund. Create this record once per logical refund, under a unique operation ID. Take the user and organization from authenticated server context. After a restart, reload the record instead of generating a new key.

# Create once; reload on retries.
request = build_refund_request(
    charge="charge-example-17",
    # USD 1,200
    amount_cents=120000
)
request.headers.update({
    "Idempotency-Key": new_key()
})
saved = persist_immutable(
    operation_id=refund_id,
    tenant=tenant_id,
    user=user_id,
    intent=intent_id,
    request=request
)

The review screen should display this saved request. Link to the billing evidence so the reviewer can check the duplicate charge, rather than relying on the agent's assertion. Verify the person's identity and eligibility server-side against the configured approver; an agent-supplied name is not authorization.

Resume the saved tool call after approval

When Airlock requires approval, the call waits instead of reaching the provider. An approval grants a one-time pass for the matching request under the same organization, user, and intent. The client must then retry the call. Clicking “approve” does not itself execute the refund.

saved = load_operation(refund_id)
result = submit_via_airlock(saved)

if result.needs_approval:
    approval = result.approval_id
    save_pending(
        refund_id, approval
    )
    decision = wait_for(approval)

    if decision != "approved":
        return  # Do not send.

    # Same saved call and intent.
    result = submit_via_airlock(
        saved,
        approval_id=approval
    )

record_result(refund_id, result)

These helpers represent your client integration, not actual method names or response fields. On restart, resume from the saved approval ID. If waiting times out, keep the pending state; stopping the wait does not cancel the approval. A denied or expired decision stops this attempt.

On retry, Airlock checks the approval's request fingerprint and identity, that it is approved and unexpired, and that it has not been consumed. Consumption is atomic: two simultaneous retries cannot both spend the same pass. If an explicitly supplied approval is invalid for the request, that retry is denied.

If the agent changes $1,200 to $2,000 or selects another charge, submit that proposal for its own policy evaluation. Do not overwrite the saved request or reuse its approval. Conversely, do not assume editing an ordinary policy revokes an already granted pass; Airlock's pass can survive that policy change.

Recover from a timeout without creating another refund

Suppose the approved call reaches Stripe, which accepts the refund, but the response never reaches your application. The approval may already be consumed while the refund's outcome is unknown. Handle a timeout from the resumed call this way:

try:
    result = submit_via_airlock(
        saved,
        approval_id=approval
    )
except NetworkTimeout:
    mark_outcome(
        refund_id, "unknown"
    )
    enqueue_provider_status_check(
        refund_id
    )
    return  # Do not refund again.

record_result(refund_id, result)

The status check looks for the existing refund in provider records; it does not submit another refund. Record a provider operation ID whenever available. Keep approval status separate from provider outcome: authorization is not proof of success. If you cannot establish the outcome, leave it unresolved for investigation instead of creating a replacement.

For an eligible retry, preserve the original request and idempotency key and send it through Airlock again. A consumed pass cannot be reused; another attempt still needs authorization. Stripe's idempotency rules also apply: the same key returns the stored result, including errors, during its retention window; changed parameters are rejected. Keys can be pruned after at least 24 hours, so they are not permanent duplicate protection.

Test with a provider stub: a pending, denied, or expired approval must not authorize a refund; changing the amount or charge must not spend the original pass; concurrent retries must consume it at most once. Simulate a timeout after the provider accepts the request and verify that your application records an unknown outcome without creating a replacement refund.

The Agent Night demo shows approval and client resume with an email to an unfamiliar distribution list. The recording below shows that workflow; the refund example here is illustrative.

Request Airlock early access to add human approval to your agents' actions.