# `ADK.Policy.HumanApproval`
[🔗](https://github.com/zeroasterisk/adk-elixir/blob/main/lib/adk/policy/human_approval.ex#L1)

A policy that pauses agent execution and requires human approval before
running sensitive tools — Human-in-the-loop (HITL) tool confirmation.

## Modes

* `:cli` — prompts the user interactively via stdin. Blocks the agent process
  until the user types `y`/`yes` or `n`/`no`. Best for terminal-based agents.

* `:server` — registers the request with `ADK.Tool.Approval` GenServer and
  blocks until externally approved or denied. Use this for web UIs (LiveView),
  webhooks, or any async approval flow.

## Usage

    # CLI mode — user is prompted in the terminal
    policy = ADK.Policy.HumanApproval.new(
      sensitive_tools: ["shell_command", "delete_file"],
      mode: :cli
    )

    # CLI mode with custom prompt function
    policy = ADK.Policy.HumanApproval.new(
      sensitive_tools: :all,
      mode: :cli,
      prompt_fn: fn %{tool_name: name, args: args} ->
        IO.puts("About to call #{name} with #{inspect(args)}")
        answer = IO.gets("OK? [y/N]: ") |> String.trim()
        if answer in ["y", "yes"], do: :allow, else: {:deny, "Custom rejection"}
      end
    )

    # Server mode — approve via ADK.Tool.Approval.approve/2
    {:ok, _} = ADK.Tool.Approval.start_link(name: MyApprovals)
    policy = ADK.Policy.HumanApproval.new(
      sensitive_tools: ["delete_file"],
      mode: :server,
      server: MyApprovals,
      timeout: 120_000
    )

    # Pass to Runner.run/5
    ADK.Runner.run(runner, user_id, session_id, message, policies: [policy])

## Struct-based Policies

`HumanApproval` is a struct, not just a module. `ADK.Policy.check_tool_authorization/4`
detects structs and dispatches to `check/4` directly rather than calling `authorize_tool/3`
on the module. This allows per-instance configuration (different tools, modes, servers).

If you use `HumanApproval` as a bare module (unusual), all tools are allowed by default.
Use `new/1` to create a configured struct instance.

# `t`

```elixir
@type t() :: %ADK.Policy.HumanApproval{
  mode: :cli | :server,
  prompt_fn: (map() -&gt; :allow | {:deny, String.t()}) | nil,
  sensitive_tools: [String.t()] | :all,
  server: atom() | pid(),
  timeout: pos_integer()
}
```

# `check`

```elixir
@spec check(t(), map(), map(), ADK.Context.t()) :: :allow | {:deny, String.t()}
```

Check authorization for a specific `HumanApproval` struct instance.

Returns `:allow` or `{:deny, reason}`. May block if awaiting human input.

# `new`

```elixir
@spec new(keyword()) :: t()
```

Create a new `HumanApproval` policy struct.

## Options

  * `:sensitive_tools` — list of tool name strings to intercept, or `:all` (required)
  * `:mode` — `:cli` (default) or `:server`
  * `:server` — `ADK.Tool.Approval` server name or pid (server mode only)
  * `:timeout` — ms to wait for server-mode approval (default: 60_000)
  * `:prompt_fn` — custom `(%{tool_name, args, request_id}) -> :allow | {:deny, reason}`

---

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