docs
GitHub

Tool Approvals

Agent Port is safe by default: every tool call requires explicit approval before execution.

How it works

  1. Default deny — All discovered tools start in require_approval mode. Nothing runs unless explicitly allowed.

  2. Per-tool modes — Each tool on an installed integration has an execution mode:

    • require_approval (default) — calls are blocked until approved
    • allow — calls execute immediately without approval
  3. Approval flow — When a blocked call happens:

    • Agent Port creates a pending approval request
    • Returns a 403 (REST) or an approval-required text response (MCP) with an approval_url and the approval_request_id
    • The agent presents the link to the user
    • The user reviews and decides in the UI
    • The agent either retries the call (REST) or long-polls agentport__await_approval(request_id) (MCP — see below)
  4. MCP long-poll flow — Over the MCP surface, the agent should call agentport__await_approval(request_id) immediately after sharing the approval URL with the human, instead of waiting for a chat reply. The meta-tool blocks until the human approves, denies, or the server's long-poll budget (approval_long_poll_timeout_seconds, default 240 s) elapses. On approve it returns the real upstream tool result — no retry needed. On timeout it returns a "still pending" message so the agent can loop back in without human intervention.

  5. Decision options:

    • Approve once — allows this exact call one time; the agent must retry to consume it
    • Allow exact forever — creates a permanent policy for this exact tool + arguments combination
    • Deny — rejects the request
  6. Optional second factor (TOTP) — Users who turn on two-factor in Settings must enter a 6-digit authenticator code (or a recovery code) alongside every decision. Recovery codes are single-use.

Exact-match policies

When a user chooses "allow exact forever", Agent Port creates an exact-match approval policy. Future calls with the same integration, tool, and normalized arguments are allowed automatically, even if the tool is in require_approval mode.

Arguments are normalized (stable key ordering, compact JSON) and hashed with SHA-256 for matching.

Request lifecycle

pending → approved (approve_once) → consumed (on retry)
pending → approved (allow_exact_forever) → policy created
pending → denied
pending → expired (after 24 hours)

Duplicate blocked calls with the same arguments reuse the same pending request.

Policy evaluation order

For each tool call:

  1. Check for an exact-match approval policy → allow
  2. Check the tool's execution setting → if allow, execute
  3. Otherwise → block and create/reuse approval request

API endpoints

See API Reference for full details:

  • PUT /api/tool-settings/{integration}/{tool} — set execution mode
  • GET /api/tool-approvals/requests — list approval requests
  • POST /api/tool-approvals/requests/{id}/approve-once — one-time approval
  • POST /api/tool-approvals/requests/{id}/approve-forever — permanent exact-match rule
  • POST /api/tool-approvals/requests/{id}/deny — deny request

Logging

All blocked calls generate log entries with outcome: "approval_required" and a reference to the approval request ID. Successful calls log outcome: "executed".