GenServer that manages pending human approval requests for tool calls.
When ADK.Policy.HumanApproval intercepts a sensitive tool call, it registers
a request here and blocks until a decision is made. External actors (CLI, LiveView,
webhook handlers) call approve/2 or deny/3 to resolve pending requests.
Supervision
Start it in your supervision tree or via Application config:
# In your Supervisor:
{ADK.Tool.Approval, name: ADK.Tool.Approval}
# Or via ADK application config (starts with default name):
config :adk, start_approval_server: trueUsage
# From a policy (internal — use ADK.Policy.HumanApproval instead):
{request_id, request} = ADK.Tool.Approval.register("shell_command", %{"command" => "rm -rf /"})
decision = ADK.Tool.Approval.await(request_id, 60_000)
# => :allow | {:deny, reason}
# From a LiveView or CLI handler:
ADK.Tool.Approval.approve(request_id)
ADK.Tool.Approval.deny(request_id, "User clicked No")
# List pending (for a LiveView dashboard):
requests = ADK.Tool.Approval.list_pending()
# => [%{id: ..., tool_name: ..., args: ..., requested_at: ...}]
Summary
Functions
Approve a pending request by ID.
Block the calling process until request_id is approved, denied, or times out.
Deny a pending request by ID with an optional reason.
List all pending (unresolved) approval requests.
Register a new approval request. Returns {request_id, request_map}.
Start the Approval server.
Types
@type request() :: %{ id: String.t(), tool_name: String.t(), args: map(), requested_at: DateTime.t() }
Functions
Approve a pending request by ID.
@spec await(atom() | pid(), String.t(), pos_integer()) :: :allow | {:deny, String.t()}
Block the calling process until request_id is approved, denied, or times out.
Returns:
:allow— request was approved{:deny, reason}— request was denied or timed out
Deny a pending request by ID with an optional reason.
List all pending (unresolved) approval requests.
Register a new approval request. Returns {request_id, request_map}.
Called by ADK.Policy.HumanApproval before blocking on await/3.
@spec start_link(keyword()) :: GenServer.on_start()
Start the Approval server.