# `Alloy.Middleware`
[🔗](https://github.com/alloy-ex/alloy/blob/v0.10.1/lib/alloy/middleware.ex#L1)

Behaviour for middleware that wraps the agent loop.

Middleware runs at defined hook points:
- `:before_completion` - Before calling the provider
- `:after_completion` - After provider response with :end_turn (final state)
- `:after_compaction` - After context compaction occurs (only fires when messages changed)
- `:after_tool_request` - After provider response with :tool_use (gates tool execution)
- `:after_tool_execution` - After tools have been executed
- `:on_error` - When an error occurs

Middleware can modify state (e.g., add logging, enforce policies,
track metrics) but should not change the fundamental loop behavior.

# `call_result`

```elixir
@type call_result() ::
  Alloy.Agent.State.t()
  | {:block, String.t()}
  | {:halt, String.t()}
  | {:edit, map()}
```

# `hook`

```elixir
@type hook() ::
  :before_completion
  | :after_completion
  | :after_compaction
  | :after_tool_request
  | :after_tool_execution
  | :on_error
  | :before_tool_call
  | :session_start
  | :session_end
```

# `call`

```elixir
@callback call(hook(), Alloy.Agent.State.t()) :: call_result()
```

Called at the specified hook point. Returns modified state,
`{:block, reason}` for `:before_tool_call` to prevent execution,
or `{:halt, reason}` to stop the entire agent loop immediately.

# `run`

```elixir
@spec run(hook(), Alloy.Agent.State.t()) ::
  Alloy.Agent.State.t() | {:halted, String.t()}
```

Runs all middleware for a given hook point.

Middleware can return `{:halt, reason}` to stop processing immediately
and mark the agent as halted. Returns either the final state or
`{:halted, reason}` tuple.

# `run_before_tool_call`

```elixir
@spec run_before_tool_call(Alloy.Agent.State.t(), map()) ::
  :ok | {:block, String.t()} | {:edit, map()} | {:halted, String.t()}
```

Runs `:before_tool_call` middleware for a single tool call.

Injects the tool call into `state.config.context[:current_tool_call]`
before running middleware. Returns `:ok`, `{:block, reason}`,
`{:edit, modified_call}`, or `{:halted, reason}`.

The `{:edit, modified_call}` return lets middleware rewrite tool arguments
before execution. The modified call must keep the same `:id` and `:name`.

Note: `{:edit, ...}`, `{:block, ...}`, and `{:halt, ...}` all stop the
middleware chain immediately. The first middleware that returns one of
these wins — subsequent middleware modules will not see the tool call.

---

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