Skip to main content

Human-in-the-Loop Approvals

AgentFlow’s approval system lets you gate sensitive tool executions with human review. When an agent tries to use a tool that requires approval, execution pauses until a user approves or denies the action.

How it works

  1. A tool is registered with require_approval=True
  2. During a conversation, the agent decides to call that tool
  3. Execution pauses and an approval request is created with the tool name and arguments
  4. The user reviews the request via the API or UI
  5. If approved, the tool executes and the agent continues
  6. If denied, the agent is informed and can adjust its approach

Configuring approval on tools

Via SDK

# When registering a new tool
await agent.register_tool(
    send_contract,
    require_approval=True,
)

# Toggle approval on an existing tool
tool = await agent.get_tool("send_contract")
await tool.set_approval(enabled=True, timeout=300)  # 5 minute timeout

Via REST API

PUT /agent/{agent_id}/tools/{tool_name}/approval
{
  "enabled": true,
  "timeout": 300
}

Approval API

List pending approvals

GET /api/approvals/pending?page=1&page_size=20&tool_name=send_contract
{
  "approvals": [
    {
      "id": "appr_abc123",
      "tool_name": "send_contract",
      "tool_id": "tool_xyz",
      "arguments": {
        "recipient": "[email protected]",
        "contract_id": "contract_456"
      },
      "status": "pending",
      "created_at": "2026-01-15T10:30:00Z",
      "expires_at": "2026-01-15T10:35:00Z"
    }
  ],
  "total": 1,
  "pending": 1,
  "expired": 0
}

Respond to an approval

POST /api/approvals/{approval_id}/respond
{
  "status": "approved",
  "reason": "Verified contract details are correct"
}
Status values: approved, denied

Bulk operations

Respond to multiple approvals at once:
POST /api/approvals/bulk-respond
{
  "approval_ids": ["appr_abc123", "appr_def456"],
  "status": "approved",
  "reason": "Batch approved after review"
}

Cancel a pending approval

DELETE /api/approvals/{approval_id}?reason=No+longer+needed

Monitoring & analytics

Per-tool statistics

GET /api/approvals/tools/{tool_id}/stats
{
  "tool_id": "tool_xyz",
  "tool_name": "send_contract",
  "total_requests": 47,
  "approved_count": 42,
  "denied_count": 3,
  "timeout_count": 1,
  "auto_approved_count": 0,
  "cancelled_count": 1,
  "success_rate": 0.89,
  "avg_response_time": 12.5
}

Dashboard summary

GET /api/approvals/dashboard/summary
{
  "total_pending": 3,
  "expiring_soon": 1,
  "total_today": 12,
  "approval_rate": 0.91,
  "avg_response_time": 8.3
}

Expiration & cleanup

Approval requests have a configurable timeout (default: 300 seconds). Expired requests are tracked separately and can be cleaned up:
POST /api/approvals/cleanup-expired