# `ADK.Tool.Approval`
[🔗](https://github.com/zeroasterisk/adk-elixir/blob/main/lib/adk/tool/approval.ex#L1)

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: true

## Usage

    # 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: ...}]

# `request`

```elixir
@type request() :: %{
  id: String.t(),
  tool_name: String.t(),
  args: map(),
  requested_at: DateTime.t()
}
```

# `approve`

```elixir
@spec approve(atom() | pid(), String.t()) :: :ok | {:error, :not_found}
```

Approve a pending request by ID.

# `await`

```elixir
@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`

```elixir
@spec deny(atom() | pid(), String.t(), String.t()) :: :ok | {:error, :not_found}
```

Deny a pending request by ID with an optional reason.

# `list_pending`

```elixir
@spec list_pending(atom() | pid()) :: [request()]
```

List all pending (unresolved) approval requests.

# `register`

```elixir
@spec register(atom() | pid(), String.t(), map()) :: {String.t(), request()}
```

Register a new approval request. Returns `{request_id, request_map}`.

Called by `ADK.Policy.HumanApproval` before blocking on `await/3`.

# `start_link`

```elixir
@spec start_link(keyword()) :: GenServer.on_start()
```

Start the Approval server.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
