# `Planck.Agent.Hooks.Prompt`
[🔗](https://github.com/alexdesousa/planck/blob/v0.2.2/lib/planck/agent/hooks/prompt.ex#L1)

Behaviour for injecting dynamic content into an agent's system prompt.

Implement this behaviour in a sidecar module to inject per-session context
(e.g. memory, project state) into the system prompt before every LLM turn.

## Behaviour

Use `use Planck.Agent.Hooks.Prompt` and override either or both callbacks.
Both default to returning `nil` (no injection).

    defmodule MySidecar.Hooks.Memory do
      use Planck.Agent.Hooks.Prompt

      @impl true
      def after_prompt(session_id) do
        case :ets.lookup(:memory, session_id) do
          [{^session_id, content}] -> content
          [] -> nil
        end
      end
    end

## Dispatch

`Planck.Agent` stores the resolved hook module atom in state and calls
`before_prompt/3` and `after_prompt/3` before every LLM turn:

    Hooks.Prompt.before_prompt(state.prompt_hook, state.session_id, state.sidecar_node)
    Hooks.Prompt.after_prompt(state.prompt_hook, state.session_id, state.sidecar_node)

- `module: nil` — returns `nil` (no injection).
- `sidecar_node: nil` — calls `module.prepend/1` / `module.append/1` in-process.
- `sidecar_node` set — calls via RPC; returns `nil` on `:badrpc`.

The default RPC timeout is 5000 ms; override `hook_timeout/0`
to declare a custom expected latency.

# `after_prompt`

```elixir
@callback after_prompt(session_id :: String.t() | nil) :: String.t() | nil
```

Return text to inject after all other system prompt sections, or `nil` for no injection.

# `before_prompt`

```elixir
@callback before_prompt(session_id :: String.t() | nil) :: String.t() | nil
```

Return text to inject before the base system prompt, or `nil` for no injection.

# `hook_timeout`

```elixir
@callback hook_timeout() :: pos_integer()
```

RPC call timeout in milliseconds when this hook is invoked remotely.

Defaults to 5000 ms.

# `after_prompt`

```elixir
@spec after_prompt(module() | nil, String.t() | nil, atom() | nil) :: String.t() | nil
```

Call `module.after_prompt/1` and return the result, dispatching via RPC when
`sidecar_node` is set. Returns `nil` when `module` is `nil` or on RPC failure.

# `before_prompt`

```elixir
@spec before_prompt(module() | nil, String.t() | nil, atom() | nil) ::
  String.t() | nil
```

Call `module.before_prompt/1` and return the result, dispatching via RPC when
`sidecar_node` is set. Returns `nil` when `module` is `nil` or on RPC failure.

# `default_timeout`

```elixir
@spec default_timeout() :: pos_integer()
```

Default RPC timeout used when a hook module omits `hook_timeout/0`.

---

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