# `ADK.Callback`
[🔗](https://github.com/zeroasterisk/adk-elixir/blob/main/lib/adk/callback.ex#L1)

Callback hooks for agent, model, and tool invocations.

Callbacks allow intercepting and transforming execution at key points in the
agent pipeline. Each callback receives a callback context and can either
continue execution or halt it early.

## Callback Types

- `before_agent/1` — called before an agent runs; can short-circuit with `{:halt, events}`
- `after_agent/2` — called after an agent runs; can transform the resulting events
- `before_model/1` — called before an LLM call; can short-circuit with `{:halt, response}`
- `after_model/2` — called after an LLM call; can transform the response
- `before_tool/1` — called before a tool runs; can short-circuit with `{:halt, result}`
- `after_tool/2` — called after a tool runs; can transform the result

## Usage

    defmodule MyCallbacks do
      @behaviour ADK.Callback

      @impl true
      def before_agent(callback_ctx), do: {:cont, callback_ctx}

      @impl true
      def after_agent(events, _callback_ctx), do: events
    end

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

# `callback_ctx`

```elixir
@type callback_ctx() :: %{
  :agent =&gt; any(),
  :context =&gt; ADK.Context.t(),
  optional(:request) =&gt; map(),
  optional(:tool) =&gt; map(),
  optional(:tool_args) =&gt; map()
}
```

# `after_agent`
*optional* 

```elixir
@callback after_agent([ADK.Event.t()], callback_ctx()) :: [ADK.Event.t()]
```

Called after an agent executes. Receives the events and callback context; returns (possibly transformed) events.

# `after_model`
*optional* 

```elixir
@callback after_model({:ok, map()} | {:error, term()}, callback_ctx()) ::
  {:ok, map()} | {:error, term()}
```

Called after a model call. Receives the response and callback context; returns (possibly transformed) response.

# `after_tool`
*optional* 

```elixir
@callback after_tool(ADK.Tool.result(), callback_ctx()) :: ADK.Tool.result()
```

Called after a tool executes. Receives the result and callback context; returns (possibly transformed) result.

# `before_agent`
*optional* 

```elixir
@callback before_agent(callback_ctx()) ::
  {:cont, callback_ctx()} | {:halt, [ADK.Event.t()]}
```

Called before an agent executes. Return `{:cont, callback_ctx}` to continue or `{:halt, events}` to short-circuit.

# `before_model`
*optional* 

```elixir
@callback before_model(callback_ctx()) ::
  {:cont, callback_ctx()} | {:halt, {:ok, map()} | {:error, term()}}
```

Called before a model call. Return `{:cont, callback_ctx}` to continue or `{:halt, {:ok, response}}` to short-circuit.

# `before_tool`
*optional* 

```elixir
@callback before_tool(callback_ctx()) ::
  {:cont, callback_ctx()} | {:halt, ADK.Tool.result()}
```

Called before a tool executes. Return `{:cont, callback_ctx}` to continue or `{:halt, result}` to short-circuit.

# `on_model_error`
*optional* 

```elixir
@callback on_model_error(
  {:error, term()},
  callback_ctx()
) :: {:retry, callback_ctx()} | {:fallback, {:ok, map()}} | {:error, term()}
```

Called when the LLM backend returns an error.

Return one of:
- `{:retry, callback_ctx}` — retry the LLM call
- `{:fallback, {:ok, response}}` — use a fallback response
- `{:error, reason}` — propagate the error (re-raise)

# `on_tool_error`
*optional* 

```elixir
@callback on_tool_error(
  {:error, term()},
  callback_ctx()
) :: {:retry, callback_ctx()} | {:fallback, {:ok, term()}} | {:error, term()}
```

Called when a tool returns an error.

Return one of:
- `{:retry, callback_ctx}` — retry the tool call
- `{:fallback, {:ok, result}}` — use a fallback result
- `{:error, reason}` — propagate the error

# `run_after`

```elixir
@spec run_after([module()], atom(), term(), callback_ctx()) :: term()
```

Run a list of "after" callbacks in order, threading the result through each.

# `run_before`

```elixir
@spec run_before([module()], atom(), callback_ctx()) ::
  {:cont, callback_ctx()} | {:halt, term()}
```

Run a list of "before" callbacks in order. Returns `{:cont, callback_ctx}` if all
callbacks continue, or `{:halt, result}` on the first halt.

# `run_on_error`

```elixir
@spec run_on_error([module()], {:error, term()}, callback_ctx()) ::
  {:retry, callback_ctx()} | {:fallback, {:ok, map()}} | {:error, term()}
```

Run on_model_error callbacks. Returns `{:retry, callback_ctx}`, `{:fallback, {:ok, response}}`,
or `{:error, reason}`. First callback to return non-error wins.

# `run_on_tool_error`

```elixir
@spec run_on_tool_error([module()], {:error, term()}, callback_ctx()) ::
  {:retry, callback_ctx()} | {:fallback, {:ok, term()}} | {:error, term()}
```

Run on_tool_error callbacks. Returns `{:retry, callback_ctx}`, `{:fallback, {:ok, result}}`,
or `{:error, reason}`. First callback to return non-error wins.

---

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