AI Systems Research guide

When nobody approves in time, your AI agent must not act

An expired request records silence. A rejected request records a decision. Both must block the action.

An airport gate at dusk with the jet bridge pulled back from a closed aircraft door and one suitcase left alone by the gate
Nobody said yes. Nobody said no. Decide what happens then.

Direct answer

When nobody approves an AI agent's action before the deadline, the request should expire and the action should stay blocked. A late click must not revive it, and an action that changes while it waits needs a new request. Use four explicit states (pending, approved, rejected, expired), bind each approval to the exact payload, and check at execution that the approval is still valid and the payload still matches. Test silence and a late click with a harmless action, then inspect both the request history and the execution logs.

When nobody approves an AI agent’s action in time, the action must not happen. The request expires, the record says so, and tomorrow’s click on the old approval sends nothing. If the action changes while it waits, it needs a new request.

An approval gate is the checkpoint where an agent must wait for a named person’s permission before it sends, pays, deletes, or publishes. The payload is the exact content of the action: recipients, text, amount, and target. The timeout policy says what happens when the reviewer does not answer.

A platform limit is not an approval policy

A timeout is a decision, not a default. Leaving it to the platform is still a decision; it just never gets written down.

Microsoft Power Automate limits a flow run to 30 days, counted from the run’s start and including pending steps such as approvals. After 30 days, pending steps time out (Microsoft Learn). If you request approval 25 days into a run, that limit leaves at most five days.

The OpenAI Agents SDK (Python) pauses a run when a tool needs approval and lets you store the paused state and resume it later (human-in-the-loop guide). The guide says the server must stop concurrent or replayed submissions from resuming the same snapshot twice. It also suggests storing a version marker if approvals may sit for a while. I found no deadline for pending approvals in the guide.

Neither sets how long this particular action should stay open for approval, or what a late answer may still do. That is your policy, and it belongs in writing.

Four states, and expired is not rejected

Give each request one of four states. This is a proposed engineering contract, not a vendor API or a formal standard.

StateWhat it meansWhat the agent may do
PendingWaiting for a decision, before the deadlineWait. Do not perform the action.
ApprovedA named person said yes to this exact version, in timeExecute only the approved version, while the approval is still valid.
RejectedThe person said noRecord the reason and stop. A revised action is a new request.
ExpiredThe deadline passed without a decisionStop. Start a new request if the work is still needed.

A rejection means someone judged the action and refused it. An expiry means nobody judged it at all. Both block execution, but they call for different fixes: a rejected action needs revising, while an expiry points to the deadline, the routing, or the reviewer’s workload. If the history merges the two, you lose that signal. A late click reopens neither.

Also set how long an approval stays valid before execution. An on-time yes should not authorise the action indefinitely. Keep execution history apart from approval state: “approved” does not mean “sent”. Record each attempt and its result, retries included.

Why approve the exact action, not a summary?

An approval should identify the action, target, payload version, scope, reviewer, and deadline. “Renewal reminder to Acme” is a summary. The final subject line, body, and recipient list are what the person must approve. If any of them changes, the old “Approve” button must not authorise the revised action.

The Bybit theft shows what an altered payload can cost, although it involved neither AI nor a timeout. In February 2025, the cryptocurrency exchange initiated a transaction through the Safe{Wallet} web interface. Sygnia’s investigation describes how the attackers manipulated that transaction and altered its payload (Sygnia). The FBI attributed the theft of approximately $1.5 billion in virtual assets to North Korea (FBI).

For an approval gate, take one lesson from it: approval must bind to the payload that executes, not to whatever the review screen displayed. Store the approved payload, or a fingerprint of it. At execution, check that the approval is still valid and that the payload matches. Make that check part of the execution step itself, so nothing can change in between.

A worked example: the notice that changed after the deadline

This example is fictional. An agent prepares a notice to suppliers about a planned service interruption. The operations owner must approve the recipient list and the final text before anything goes out.

  1. 15:00. Request A holds version 1 of the notice and expires at 16:00, Amsterdam time. The owner leaves without reviewing it.
  2. 16:00. Nobody has answered. Request A moves to expired. Nothing is sent.
  3. 16:10. A colleague adds a recipient and moves the interruption window. That is version 2, so it becomes a new pending request B, with its own deadline and the changes highlighted. B does not inherit A’s approval link.
  4. Next morning. The owner opens yesterday’s notification and clicks “Approve” on request A. The gate reports that A expired, sends nothing, and points to request B, where the new time and the extra recipient are visible.

A test has to prove two things: the state changed, and nothing was attempted. A screen saying “already handled” proves little if the server quietly accepted the old approval behind it. Inspect the request history and the execution logs for the same request ID.

What about retries, restarts, and stand-ins?

Retries. If a send times out, the system may not know whether it went through. That uncertainty is not permission to send again. Use an idempotency key where the receiving system supports one, so it can recognise a retry of the same action. Stripe’s documentation, for example, says idempotency keys let you retry a request safely without performing the same operation twice, and that a repeated key with different parameters returns an error (Stripe). The key deals with duplicates, not permission: a changed action still needs a new request.

Restarts. Store the deadline and the state with the request, not in the memory of a running process. A restart must not forget that a request expired.

Stand-ins. Name the deputy and their authority in advance. Forwarding a notification does not make anyone an approver, and rerouting must not revive an expired request.

Five tests to run on your gate

Use a test environment. Replace the real action with a harmless log entry, but keep the approval and execution checks in place. First confirm that a valid approval produces the entry; otherwise an empty log tells you little.

TestWhat you doA pass looks like
1. SilenceLeave a request unanswered past its deadlineState is expired. No attempt to act.
2. Late clickClick “Approve” on the expired requestIt stays expired. No action is attempted. Any current request requires fresh review.
3. Changed payloadChange the recipients while the request is pending, then use the old approvalThe old approval is refused. A new request shows what changed.
4. Double deliveryApprove once, then deliver the “go” event twiceThe action happens exactly once.
5. RestartRestart the worker with an expired request in storageThe request is still expired after the restart.

A gate that fails any of these is a reminder system: it helps a person notice, but it does not decide whether the action may proceed. Fix each failure before you rely on the gate. A pass shows how the gate behaved in that test, not that it handles every failure.

Where does this fit with human in the loop?

Human in the loop meaning defines the named person who can fail the work. HITL in AI workflows puts that person on the irreversible step and gives each write tool a card with an expiry line. Human on the loop covers the weaker role of a monitor who can stop the next run but cannot fail this one. What an agent may never do covers override doctrine, the written list of decisions an agent may never take. This page answers one narrower question: what happens when the named person does not answer in time.

Try this today (20 minutes)

Use this session for tests 1 and 2: silence and the late click. You need a test environment where you can shorten the deadline and read the execution logs.

  1. Minutes 0–5: isolate the gate. Replace the action with a harmless log entry. Note the platform’s documented waiting limit, if it has one, and set a one-minute approval deadline for the test.
  2. Minutes 5–8: confirm a normal approval works. Approve a fresh request before its deadline. Confirm that it produces exactly one log entry, identifiable by request ID.
  3. Minutes 8–12: leave a request unanswered. Create a second request and save its approval link. After the deadline, inspect the stored state and the execution logs. Expect expired, with no attempt to act.
  4. Minutes 12–16: use the old link. Click “Approve” on the expired request. Check again: it must stay expired, with no execution attempt.
  5. Minutes 16–20: record the result. Save the request ID, deadline, state history, and execution evidence. Check them against one rule: “At the deadline, the request expires and nothing runs. A late click does nothing.”

If setup takes the whole session, record the test as not run. If the logs cannot establish the result, record it as unverified. Fix any failure, rerun the check, then work through tests 3 to 5.

Cite this:When nobody approves in time, your AI agent must not act.Len P. van der Hof. https://lenvanderhof.com/en/blog/human-approval-timeout-test/ ·

Sources

  1. Limits of automated, scheduled, and instant flows · Microsoft Learn
  2. Human-in-the-loop (OpenAI Agents SDK) · OpenAI
  3. Sygnia's investigation into the Bybit hack: what we know so far · Sygnia
  4. North Korea responsible for $1.5 billion Bybit hack · FBI Internet Crime Complaint Center
  5. Idempotent requests · Stripe
  6. Human in the loop meaning: a named person who can fail the work
  7. HITL in AI workflows: put the named person on the irreversible step
  8. Human on the loop: watching is not a fail gate

Further reading

Markdown for LLMs