# `ALLM.Request`
[🔗](https://github.com/cykod/ALLM/blob/v0.3.0/lib/allm/request.ex#L1)

A single LLM request. See spec §5.4.

Layer A — pure serializable data. Carries the `:messages` list, optional
`:model`, `:tools`, `:tool_choice`, `:temperature`, `:max_tokens`,
`:response_format`, and adapter-opaque `:options` and `:metadata`.

Validation lives in `ALLM.Validate.request/1` (sub-phase 1.4). Per spec
§9 and the Phase 1 design (non-obvious decision #7), `new/2` itself does
not validate — it stays composable so callers can opt into validation
explicitly.

# `response_format`

```elixir
@type response_format() ::
  nil
  | :text
  | %{type: :json_object}
  | %{type: :json_schema, name: String.t(), schema: map(), strict: boolean()}
```

# `t`

```elixir
@type t() :: %ALLM.Request{
  max_tokens: non_neg_integer() | nil,
  messages: [ALLM.Message.t()],
  metadata: map(),
  model: String.t() | nil,
  options: map(),
  response_format: response_format(),
  stream: boolean(),
  structured_finalize: boolean(),
  temperature: number() | nil,
  tool_choice: tool_choice(),
  tools: [ALLM.Tool.t()]
}
```

# `tool_choice`

```elixir
@type tool_choice() :: :auto | :none | :required | String.t() | map() | nil
```

# `new`

```elixir
@spec new(
  [ALLM.Message.t()],
  keyword()
) :: t()
```

Build a `%Request{}` from a list of messages and keyword opts.

`messages` is required and becomes the `:messages` field. `opts` may set any
other struct field; unknown keys raise `ArgumentError` via `struct!/2`.

## Examples

    iex> req = ALLM.Request.new([%ALLM.Message{role: :user, content: "hi"}])
    iex> req.stream
    false
    iex> length(req.messages)
    1

    iex> req = ALLM.Request.new([%ALLM.Message{role: :user, content: "hi"}], model: "fake:x", temperature: 0.2)
    iex> {req.model, req.temperature}
    {"fake:x", 0.2}

---

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