Async Approvals¶
Non-blocking approval mode for agentic flows and long-running AI sessions.
Availability
Async approvals are available in all editions.
Overview¶
By default, when a tool call requires approval, the MCP connection blocks — the agent waits until a human approves or declines. This works well for interactive sessions but has two drawbacks:
- Client timeouts. Most MCP clients default to 30–60 s; approval can take minutes.
- Blocked agents. The agent cannot do other work while waiting.
Async approval mode solves both problems. Instead of blocking, the tool call returns immediately with a pending_approval status and a request_id. The agent then polls get_approval_status(request_id) until the human decides, at which point the tool executes and the result is returned in the poll response.
Agent ──▶ call tool ──▶ Preloop returns {status: "pending_approval", request_id: "..."}
Agent ──▶ get_approval_status(request_id) ──▶ {status: "pending", remaining_seconds: 280}
Agent ──▶ get_approval_status(request_id) ──▶ {status: "approved", tool_result: {...}}
Configuration¶
Via Policy YAML¶
Enable async approval on an approval workflow:
version: "1.0"
metadata:
name: async-deploy-review
approval_workflows:
- name: "deploy-review"
timeout_seconds: 600
required_approvals: 1
async_approval: true # ← enables async mode
tools:
- name: "bash"
source: mcp
approval_workflow: "deploy-review"
conditions:
- expression: "args.command.contains('deploy')"
action: require_approval
Via Web UI¶
- Navigate to Tools → Approval Workflows
- Edit or create a policy
- Toggle Async Approval on
- Save
Polling Flow¶
1. Tool Call Returns Immediately¶
When async approval is enabled, the tool call does not block. The agent receives:
{
"status": "pending_approval",
"request_id": "ar_abc123",
"message": "Approval required. Poll get_approval_status('ar_abc123') to check."
}
2. Agent Polls for Decision¶
The agent calls get_approval_status(request_id) periodically:
{
"status": "pending",
"remaining_seconds": 280,
"tool_name": "bash",
"tool_args": {"command": "deploy --production"},
"requested_at": "2026-02-17T20:00:00Z"
}
3. Human Decides¶
The human approves or declines via mobile app, email, Slack, or web UI.
4. Agent Receives Result¶
On the next poll after approval, the response includes the tool's execution result:
{
"status": "approved",
"tool_result": {
"text": "Deployment completed successfully."
},
"approver_comment": "Looks good, ship it.",
"resolved_at": "2026-02-17T20:02:15Z"
}
If declined:
{
"status": "declined",
"approver_comment": "Not ready for production yet.",
"resolved_at": "2026-02-17T20:01:30Z"
}
State Transitions¶
┌─────────┐
│ pending │──── human approves ───▶ approved ──▶ tool executes ──▶ result cached
│ │──── human declines ───▶ declined
│ │──── timeout reached ──▶ expired
└─────────┘
| State | Description |
|---|---|
pending |
Waiting for human decision |
approved |
Human approved; tool result available (or executing) |
declined |
Human declined; tool not executed |
expired |
Timeout reached without a decision |
Idempotency: Once a tool result is cached on an approved request, subsequent polls return the same cached result without re-executing the tool.
Client Configuration¶
Because the tool call returns immediately in async mode, no client timeout increase is needed. The agent polls at its own pace.
If you are using synchronous (blocking) approval mode instead, you may need to increase your MCP client timeout. See the timeout guidance in your MCP client reference page, such as Claude Code.
API Reference¶
get_approval_status (MCP tool)¶
Called by the agent to poll approval status.
| Parameter | Type | Required | Description |
|---|---|---|---|
request_id |
string | Yes | The approval request ID returned by the original tool call |
REST Endpoints¶
| Endpoint | Description |
|---|---|
GET /api/v1/approval-requests/{id} |
Get approval request details (authenticated) |
POST /api/v1/approval-requests/{id}/approve |
Approve a request |
POST /api/v1/approval-requests/{id}/decline |
Decline a request |
POST /api/v1/approval-requests/{id}/decide |
Approve or decline |
GET /approval/{id}/data?token={token} |
Public token-based access |
POST /approval/{id}/decide?token={token} |
Public token-based decision |
Best Practices¶
- Set reasonable timeouts. 10 minutes (
timeout_seconds: 600) works for most workflows. - Use with agentic flows. Async approval is ideal for automated flow executions where the agent runs unattended.
- Combine with justification. Require agents to explain why they need the tool — reviewers see the justification in the approval notification. See Per-Tool Justification.
- Monitor via WebSocket. Subscribe to the
approvalstopic for real-time approval status updates in the UI.