# `Raxol.AgentClientProtocol.Agent`
[🔗](https://github.com/DROOdotFOO/raxol-agent/blob/raxol_agent_client_protocol-v0.1.0/packages/raxol_agent_client_protocol/lib/raxol/agent_client_protocol/agent.ex#L130)

`use Raxol.AgentClientProtocol.Agent` to implement the **agent** side of
ACP: the process that answers `initialize`, creates/loads sessions, and
serves `session/prompt` turns.

This is a **thin ergonomic layer** over `Raxol.AgentClientProtocol.Connection`
and `Raxol.AgentClientProtocol.Session`:
it only generates the callback surface and wires the supervision tree.
Protocol correlation, cancellation, permission fan-out, and turn/streaming
semantics live entirely in those two modules -- nothing here re-implements
or shortcuts them.

## Callback surface

One `@callback` per `Raxol.AgentClientProtocol.MethodTable.rows_for_side(:agent)`
row that carries an app-level callback (`layer: :app` -- everything except
`session/cancel`, which is Connection-routed session control with no
handler callback at all). Naming and arity are
generated straight from the table, not hand-maintained:

  * `params: nil` rows (currently only `logout`) get callback arity 1:
    `callback(ctx)`.
  * every other row gets arity 2: `callback(params, ctx)` for requests,
    `callback(notification, ctx)` for notifications.

`ctx` is `Raxol.AgentClientProtocol.Connection.Ctx.t()`: read-only
per dispatch, carries `conn` (the `Connection` pid, for
`Connection.request/async_request/notify/reply/delegate_reply`),
`handler_state` (produced once by `c:init/1`), `reply_ref`, `rx_seq`,
`session_sup`, `task_sup`.

A request callback returns `{:ok, result_struct}`, `{:error, %Error{}}`,
or `:deferred` (legal only after `Connection.delegate_reply/3`; a
`:deferred` return without a prior delegation is a contract breach the
Connection turns into `-32603`). A notification callback's return value is
always ignored (`Router.dispatch/4`).

Call `callbacks/0` to introspect the generated `{callback, arity, wire}`
list.

## Defaults

Every generated callback (and `c:handle_ext_request/3`,
`c:handle_ext_notification/3`) has an overridable default: requests answer
`{:error, Error.method_not_found()}`, notifications are a silent `:ok`.
Override only what your agent supports -- an unimplemented,
capability-gated method (e.g. `session/load` without `loadSession`
advertised) never needs an explicit override, the wire-correct
`-32601` falls out for free. `c:init/1` defaults to `{:ok, handler_arg}`.

## Extension methods

`"_"`-prefixed wire methods with no `MethodTable` row are routed by
`Connection` directly to `c:handle_ext_request/3` /
`c:handle_ext_notification/3` (never through the table-driven callbacks
above -- see `Router`'s moduledoc). Both default the same way as any other
unsupported method.

## Example

    defmodule MyAgent do
      use Raxol.AgentClientProtocol.Agent
      alias Raxol.AgentClientProtocol.Schema.AgentTypes.InitializeResponse

      @impl true
      def init(_arg), do: {:ok, %{sessions: %{}}}

      @impl true
      def initialize(_req, _ctx), do: {:ok, InitializeResponse.new(1)}

      # ... new_session/2, prompt/2, etc. -- only what you support.
    end

    {:ok, sup} = Raxol.AgentClientProtocol.Agent.start_link(MyAgent, transport: {mod, handle})

## Library-mode wiring

`start_link/2` and `child_spec/1` build exactly this subtree:

    ConnectionSupervisor          Supervisor, :one_for_all,
    │                             auto_shutdown: :any_significant
    ├── Task.Supervisor           restart: :permanent
    ├── DynamicSupervisor         restart: :permanent  (Session.Supervisor; :temporary children)
    └── Connection                restart: :temporary, significant: true

`Connection` resolves its `task_sup`/`session_sup` siblings via
`Supervisor.which_children/1` in `handle_continue/2` (never in `init/1`),
so this layer does not need to name or pre-register them; it only
needs to hand `Connection` the `ConnectionSupervisor`'s own pid as
`parent_sup`, which the nested `ConnectionSupervisor.init/1` callback
captures via `self()` (that callback body runs *in* the supervisor
process, before any child starts -- the standard OTP way to hand a
supervisor's own pid to a child it is about to start).

# `ctx`

```elixir
@type ctx() :: Raxol.AgentClientProtocol.Connection.Ctx.t()
```

Per-dispatch context. See `Raxol.AgentClientProtocol.Connection.Ctx`.

# `authenticate`

```elixir
@callback authenticate(
  Raxol.AgentClientProtocol.Schema.AgentTypes.AuthenticateRequest.t(),
  Raxol.AgentClientProtocol.Connection.Ctx.t()
) ::
  {:ok, Raxol.AgentClientProtocol.Schema.AgentTypes.AuthenticateResponse.t()}
  | {:error, Raxol.AgentClientProtocol.Error.t()}
  | :deferred
```

# `close_session`

```elixir
@callback close_session(
  Raxol.AgentClientProtocol.Schema.LifecycleExtras.CloseSessionRequest.t(),
  Raxol.AgentClientProtocol.Connection.Ctx.t()
) ::
  {:ok,
   Raxol.AgentClientProtocol.Schema.LifecycleExtras.CloseSessionResponse.t()}
  | {:error, Raxol.AgentClientProtocol.Error.t()}
  | :deferred
```

# `delete_session`

```elixir
@callback delete_session(
  Raxol.AgentClientProtocol.Schema.LifecycleExtras.DeleteSessionRequest.t(),
  Raxol.AgentClientProtocol.Connection.Ctx.t()
) ::
  {:ok,
   Raxol.AgentClientProtocol.Schema.LifecycleExtras.DeleteSessionResponse.t()}
  | {:error, Raxol.AgentClientProtocol.Error.t()}
  | :deferred
```

# `handle_ext_notification`

```elixir
@callback handle_ext_notification(wire :: String.t(), params :: map(), ctx()) :: term()
```

Handle an inbound `"_"`-prefixed extension notification. Return value is
ignored. Default: `:ok`.

# `handle_ext_request`

```elixir
@callback handle_ext_request(wire :: String.t(), params :: map(), ctx()) ::
  {:ok, map()} | {:error, Raxol.AgentClientProtocol.Error.t()} | :deferred
```

Handle an inbound `"_"`-prefixed extension request with no `MethodTable`
row. Return shape matches the table-driven request callbacks. Default:
`{:error, Error.method_not_found()}`.

# `init`

```elixir
@callback init(handler_arg :: term()) :: {:ok, handler_state :: term()} | {:stop, term()}
```

Produce this handler's per-connection state from `handler_arg` (the value
passed as `handler_arg:` to `start_link/2` / `child_spec/1`). Called once,
at `Connection` boot; the result is threaded read-only through every
dispatch as `ctx.handler_state` -- handlers run as concurrent `Task`s, so
it is never mutated after init. Default: `{:ok,
handler_arg}`.

# `initialize`

```elixir
@callback initialize(
  Raxol.AgentClientProtocol.Schema.AgentTypes.InitializeRequest.t(),
  Raxol.AgentClientProtocol.Connection.Ctx.t()
) ::
  {:ok, Raxol.AgentClientProtocol.Schema.AgentTypes.InitializeResponse.t()}
  | {:error, Raxol.AgentClientProtocol.Error.t()}
  | :deferred
```

# `list_sessions`

```elixir
@callback list_sessions(
  Raxol.AgentClientProtocol.Schema.Unstable.ListSessionsRequest.t(),
  Raxol.AgentClientProtocol.Connection.Ctx.t()
) ::
  {:ok, Raxol.AgentClientProtocol.Schema.Unstable.ListSessionsResponse.t()}
  | {:error, Raxol.AgentClientProtocol.Error.t()}
  | :deferred
```

# `load_session`

```elixir
@callback load_session(
  Raxol.AgentClientProtocol.Schema.AgentTypes.LoadSessionRequest.t(),
  Raxol.AgentClientProtocol.Connection.Ctx.t()
) ::
  {:ok, Raxol.AgentClientProtocol.Schema.AgentTypes.LoadSessionResponse.t()}
  | {:error, Raxol.AgentClientProtocol.Error.t()}
  | :deferred
```

# `logout`

```elixir
@callback logout(Raxol.AgentClientProtocol.Connection.Ctx.t()) ::
  {:ok, Raxol.AgentClientProtocol.Schema.LifecycleExtras.LogoutResponse.t()}
  | {:error, Raxol.AgentClientProtocol.Error.t()}
  | :deferred
```

# `new_session`

```elixir
@callback new_session(
  Raxol.AgentClientProtocol.Schema.AgentTypes.NewSessionRequest.t(),
  Raxol.AgentClientProtocol.Connection.Ctx.t()
) ::
  {:ok, Raxol.AgentClientProtocol.Schema.AgentTypes.NewSessionResponse.t()}
  | {:error, Raxol.AgentClientProtocol.Error.t()}
  | :deferred
```

# `prompt`

```elixir
@callback prompt(
  Raxol.AgentClientProtocol.Schema.AgentTypes.PromptRequest.t(),
  Raxol.AgentClientProtocol.Connection.Ctx.t()
) ::
  {:ok, Raxol.AgentClientProtocol.Schema.AgentTypes.PromptResponse.t()}
  | {:error, Raxol.AgentClientProtocol.Error.t()}
  | :deferred
```

# `raxol_load_session`

```elixir
@callback raxol_load_session(
  Raxol.AgentClientProtocol.Schema.AgentTypes.LoadSessionRequest.t(),
  Raxol.AgentClientProtocol.Connection.Ctx.t()
) ::
  {:ok, Raxol.AgentClientProtocol.Schema.AgentTypes.LoadSessionResponse.t()}
  | {:error, Raxol.AgentClientProtocol.Error.t()}
  | :deferred
```

# `raxol_steer_session`

```elixir
@callback raxol_steer_session(
  Raxol.AgentClientProtocol.Ext.Schema.SteerRequest.t(),
  Raxol.AgentClientProtocol.Connection.Ctx.t()
) ::
  {:ok, Raxol.AgentClientProtocol.Ext.Schema.SteerResponse.t()}
  | {:error, Raxol.AgentClientProtocol.Error.t()}
  | :deferred
```

# `resume_session`

```elixir
@callback resume_session(
  Raxol.AgentClientProtocol.Schema.Unstable.ResumeSessionRequest.t(),
  Raxol.AgentClientProtocol.Connection.Ctx.t()
) ::
  {:ok, Raxol.AgentClientProtocol.Schema.Unstable.ResumeSessionResponse.t()}
  | {:error, Raxol.AgentClientProtocol.Error.t()}
  | :deferred
```

# `set_session_config_option`

```elixir
@callback set_session_config_option(
  Raxol.AgentClientProtocol.Schema.Unstable.SetSessionConfigOptionRequest.t(),
  Raxol.AgentClientProtocol.Connection.Ctx.t()
) ::
  {:ok,
   Raxol.AgentClientProtocol.Schema.Unstable.SetSessionConfigOptionResponse.t()}
  | {:error, Raxol.AgentClientProtocol.Error.t()}
  | :deferred
```

# `set_session_mode`

```elixir
@callback set_session_mode(
  Raxol.AgentClientProtocol.Schema.AgentTypes.SetSessionModeRequest.t(),
  Raxol.AgentClientProtocol.Connection.Ctx.t()
) ::
  {:ok, Raxol.AgentClientProtocol.Schema.AgentTypes.SetSessionModeResponse.t()}
  | {:error, Raxol.AgentClientProtocol.Error.t()}
  | :deferred
```

# `callbacks`

```elixir
@spec callbacks() :: [{atom(), arity(), String.t()}]
```

Introspect the generated callback surface: `{callback_atom, arity, wire_method}`, in table order.

# `child_spec`

```elixir
@spec child_spec(keyword()) :: Supervisor.child_spec()
```

Library-mode child spec: embed one ACP agent connection subtree into the
caller's own supervision tree, e.g.

    children = [
      {Raxol.AgentClientProtocol.Agent, handler: MyAgent, transport: {Transport.Stdio, handle}}
    ]

Required: `:handler` (a module using this behaviour), `:transport`
(a `{module, handle}` pair per `Raxol.AgentClientProtocol.Transport`).
Optional: `:handler_arg` (passed to `c:init/1`, default `nil`), `:name`
(registers the `ConnectionSupervisor`), `:id` (child id in the parent's
supervisor, defaults to `Raxol.AgentClientProtocol.Agent` -- override when
embedding more than one agent connection in the same tree).

# `connection`

```elixir
@spec connection(pid()) :: {:ok, pid()} | {:error, :not_found}
```

Resolve the `Connection` pid out of a started connection subtree. `sup`
must be the **`ConnectionSupervisor`'s own pid** -- this is the ONLY
supported way to reach the pid `Connection.request/4`, `async_request/6`,
and `notify/3` need, since `start_link/2`/`child_spec/1` deliberately
return/register the `ConnectionSupervisor`, not the `Connection` child
itself (the supervisor is the stable handle across the
child's `:temporary` restart policy).

Getting `sup`:

  * `start_link/2` returns it directly -- pass that return value straight in.
  * Any starter that hands you back the STARTED CHILD's pid also works
    unchanged -- `start_supervised!/1` (ExUnit) and
    `DynamicSupervisor.start_child/2` both do this for a `child_spec/1`
    entry.
  * A plain `Supervisor.start_link(children, ...)` where a `child_spec/1`
    entry is one of several `children` does NOT hand you the
    `ConnectionSupervisor` pid directly -- that call returns YOUR OWN
    supervisor's pid, one level further out. Resolve the
    `ConnectionSupervisor` child from
    `Supervisor.which_children(your_sup)` yourself first, then pass THAT
    pid here.

Returns `{:error, :not_found}` if `sup` has no live `Connection` child
(already torn down, or `sup` isn't a `ConnectionSupervisor` at all --
e.g. you passed your own outer supervisor's pid from the last bullet
above by mistake).

# `start_link`

```elixir
@spec start_link(module(), keyword()) :: Supervisor.on_start()
```

Standalone start: `Agent.start_link(MyAgent, transport: {mod, handle})`.

Returns the `ConnectionSupervisor`'s `Supervisor.on_start()` result --
link to (or monitor) the returned pid to observe the whole subtree's
lifecycle. A `Connection`/`Session` crash
is never silently swallowed: it tears the subtree down
(`auto_shutdown: :any_significant`), it does not restart in place.

Options: same as `child_spec/1` minus `:handler` (positional) and `:id`
(not meaningful outside a parent supervisor's children list).

---

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