ADK.Policy behaviour (ADK v0.0.1-alpha.1)

Copy Markdown View Source

Policy behaviour for agent governance — tool access control, content filtering, etc.

Policies are checked at key points in the agent pipeline:

  • authorize_tool/3 — before a tool executes, decides allow/deny
  • filter_input/2 — filters user input before it reaches the LLM
  • filter_output/2 — filters agent output events before they're returned

Usage

defmodule MyPolicy do
  @behaviour ADK.Policy

  @impl true
  def authorize_tool(%{name: "dangerous_tool"}, _args, _ctx), do: {:deny, "forbidden"}
  def authorize_tool(_tool, _args, _ctx), do: :allow

  @impl true
  def filter_input(content, _ctx), do: {:cont, content}

  @impl true
  def filter_output(events, _ctx), do: events
end

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

Composition

Multiple policies are composed as a chain of responsibility:

  • authorize_tool — first :deny wins; all must allow
  • filter_input — chained sequentially; first {:halt, events} short-circuits
  • filter_output — chained sequentially, each transforms the events

Summary

Callbacks

Authorize a tool call. Return :allow or {:deny, reason}.

Filter user input before the LLM sees it. Return {:cont, content} or {:halt, [ADK.Event.t()]}.

Filter output events before they're returned. Returns transformed events.

Functions

Run authorize_tool across a list of policies. First deny wins.

Run filter_input across a list of policies. First halt wins; otherwise content is threaded.

Run filter_output across a list of policies, threading events through each.

Types

tool_decision()

@type tool_decision() :: :allow | {:deny, String.t()}

Callbacks

authorize_tool(tool, args, ctx)

(optional)
@callback authorize_tool(tool :: map(), args :: map(), ctx :: ADK.Context.t()) ::
  tool_decision()

Authorize a tool call. Return :allow or {:deny, reason}.

filter_input(content, ctx)

(optional)
@callback filter_input(content :: map(), ctx :: ADK.Context.t()) ::
  {:cont, map()} | {:halt, [ADK.Event.t()]}

Filter user input before the LLM sees it. Return {:cont, content} or {:halt, [ADK.Event.t()]}.

filter_output(list, t)

(optional)
@callback filter_output([ADK.Event.t()], ADK.Context.t()) :: [ADK.Event.t()]

Filter output events before they're returned. Returns transformed events.

Functions

check_tool_authorization(policies, tool, args, ctx)

@spec check_tool_authorization([module() | struct()], map(), map(), ADK.Context.t()) ::
  tool_decision()

Run authorize_tool across a list of policies. First deny wins.

Supports both module-based policies (atoms implementing the ADK.Policy behaviour) and struct-based policies (e.g., %ADK.Policy.HumanApproval{}). Struct policies must implement a check/4 function for per-instance configuration.

run_input_filters(policies, content, ctx)

@spec run_input_filters([module()], map(), ADK.Context.t()) ::
  {:cont, map()} | {:halt, [ADK.Event.t()]}

Run filter_input across a list of policies. First halt wins; otherwise content is threaded.

run_output_filters(policies, events, ctx)

@spec run_output_filters([module()], [ADK.Event.t()], ADK.Context.t()) :: [
  ADK.Event.t()
]

Run filter_output across a list of policies, threading events through each.