Mar 26, 2026 · cloud
Why Your AI Agent Shouldn't Block When It Needs Human Approval
AI agents get stuck waiting for humans. There's a better pattern than blocking - async approval with reminders, escalation, and timeout.
Your AI agent asks a question. The human is at lunch.
What happens next depends on your architecture. And most architectures get this wrong.
The Pattern Everyone Uses (and Why It Breaks)
agent: "Should I delete the staging database?"
human: (at lunch)
agent: (blocks)
agent: (still blocking)
agent: (30 minutes later, still blocking)
agent: (timeout, session lost, start over)
This is the default in every framework. LangGraph's interrupt(). CrewAI's human_input=True. OpenAI's run pause. They all do the same thing: block and wait.
It works in demos. It breaks in production because:
- Humans aren't instant. They're in meetings. On a plane. Asleep. The agent needs an answer in 5 seconds, the human responds in 5 hours.
- Connections drop. WebSocket disconnects. SSH session times out. Terminal closes. Approval state is gone.
- Nobody knows the agent is waiting. No push notification. No email. No reminder. The agent sits there silently burning compute.
- No escalation. If the assigned reviewer is on vacation, the agent waits forever. Nobody else gets notified.
What Should Happen Instead
agent -> send_intent("needs_approval", remind=5min, timeout=8h)
5 min later: platform sends reminder (Slack push / email)
30 min later: platform escalates to backup reviewer
2 hours later: human approves from phone
agent <- resumes with approval result
The agent doesn't poll. Doesn't block. Doesn't hold a connection open. It suspends durably and resumes when the human responds - whether that's 5 seconds or 5 hours later.
The Difference: Sync vs Async Approval
| Sync (block and wait) | Async (durable) | |
|---|---|---|
| Human at lunch | Agent blocks forever | Reminder in 5 min |
| Human doesn't respond | Timeout, session lost | Escalation to backup |
| Connection drops | Approval state lost | State durable in DB |
| Response time | Must respond NOW | Hours or days later |
| Reminder | None | Configurable |
| Escalation | None | Chain: A -> B -> team |
| Task types | Yes/No only | Approval, review, form, override, ... |
What This Looks Like in Code
Before: DIY async approval (200+ lines)
def request_approval(reviewer, context):
token = secrets.token_urlsafe(32)
db.insert("approvals", token=token, status="pending")
send_slack_message(reviewer, f"Approval needed: {context}")
schedule_reminder(token, delay=300) # custom scheduler
schedule_escalation(token, delay=1800) # custom escalation
schedule_timeout(token, delay=28800) # custom timeout
return token
# Plus: reminder cron job, escalation handler, webhook callback,
# polling loop, token expiry, audit logging, DB cleanup...
After: AXME intent lifecycle (4 lines)
from axme import AxmeClient, AxmeClientConfig
client = AxmeClient(AxmeClientConfig(api_key=os.environ["AXME_API_KEY"]))
intent_id = client.send_intent({
"intent_type": "intent.data.export_approval.v1",
"to_agent": "agent://myorg/production/data-analyst",
"payload": {"dataset": "customers_q1", "pii_detected": True},
})
result = client.wait_for(intent_id)
No reminder scheduler. No escalation handler. No webhook endpoint. No polling loop. The platform handles all of it.
Not Just Yes/No
Most approval implementations only support binary yes/no. Real workflows need more:
| Type | Example |
|---|---|
| approval | "Deploy to production?" |
| review | "Review this PR summary" (with comments) |
| form | "Fill in budget justification" (structured fields) |
| manual_action | "Flip the DNS switch" (out-of-band action) |
| override | "Override rate limit for VIP customer" |
| clarification | "Which region should I deploy to?" |
Works With Any Framework
This isn't framework-specific. The same pattern works whether your agent is built with LangGraph, CrewAI, AutoGen, OpenAI Agents SDK, Google ADK, Pydantic AI, or raw Python.
The agent framework handles reasoning. The coordination layer handles waiting.
Try It
Full working example with scenario, agent, and approval flow:
github.com/AxmeAI/async-human-approval-for-ai-agents
Built with AXME - a coordination layer for operations that take minutes, hours, or days to complete. Alpha - feedback welcome.
Related posts
How to Add Human Approval to AI Agent Workflows Without Building It Yourself
Adding a human approval step to an AI agent workflow means building a notification service, reminder scheduler, escalation chain, and webhook handler. Or you can use 4 lines of code.
Your AI Agent Crashed at Step 47. Why Isn't Crash Recovery the Default?
Your agent ran 47 steps of a 50-step pipeline. Then it crashed. The state is gone. Every framework says you should have configured checkpointing. Why isn't durability built in?
A2A Tells Agents How to Talk. It Doesn't Tell Them What Happens When Things Break.
Google's A2A protocol handles agent communication. But crash recovery, retries, timeouts, and human approval gates? That's still on you. Unless you add a lifecycle layer.
Your Agent Has Been Stuck for 3 Hours and Nobody Knows
API call hangs. Agent blocks. No timeout fires. No one gets paged. The default behavior in most agent frameworks is silence. Here's how to fix that.