# `ALLM.Usage`
[🔗](https://github.com/cykod/ALLM/blob/v0.5.0/lib/allm/usage.ex#L1)

Token and cost usage for a single response — Layer A serializable data.

Every numeric field is optional and `nil`-able because not every
provider returns every counter. Costs are populated either by an
adapter that knows its own pricing or by an optional model-catalog
integration.

## Fields

| Field | Type | Notes |
|-------|------|-------|
| `:input_tokens` | `non_neg_integer \| nil` | |
| `:output_tokens` | `non_neg_integer \| nil` | |
| `:cached_input_tokens` | `non_neg_integer \| nil` | Provider-cached prompt tokens. |
| `:reasoning_tokens` | `non_neg_integer \| nil` | Reasoning-model thinking tokens. |
| `:total_tokens` | `non_neg_integer \| nil` | |
| `:input_cost` | `float \| nil` | USD; populated when the adapter knows pricing. |
| `:output_cost` | `float \| nil` | |
| `:total_cost` | `float \| nil` | |
| `:tool_usage` | `map` | Per-tool tally (caller-derived). |
| `:extra` | `map` | Provider-specific spillover. |

# `cost`

```elixir
@type cost() :: float()
```

# `t`

```elixir
@type t() :: %ALLM.Usage{
  cached_input_tokens: non_neg_integer() | nil,
  extra: map(),
  input_cost: cost() | nil,
  input_tokens: non_neg_integer() | nil,
  output_cost: cost() | nil,
  output_tokens: non_neg_integer() | nil,
  reasoning_tokens: non_neg_integer() | nil,
  tool_usage: map(),
  total_cost: cost() | nil,
  total_tokens: non_neg_integer() | nil
}
```

# `new`

```elixir
@spec new(keyword()) :: t()
```

Build a `%Usage{}` from keyword opts.

Every field is optional. Unknown keys raise `ArgumentError` via `struct!/2`.

## Examples

    iex> u = ALLM.Usage.new(input_tokens: 10, output_tokens: 20)
    iex> u.input_tokens
    10
    iex> u.tool_usage
    %{}

# `total_tokens`

```elixir
@spec total_tokens(t()) :: non_neg_integer() | nil
```

Return the `:total_tokens` field when set, otherwise the sum of
`:input_tokens + :output_tokens` when both are integers, otherwise `nil`.

## Examples

    iex> ALLM.Usage.total_tokens(ALLM.Usage.new(total_tokens: 42))
    42

    iex> ALLM.Usage.total_tokens(ALLM.Usage.new(input_tokens: 10, output_tokens: 20))
    30

    iex> ALLM.Usage.total_tokens(ALLM.Usage.new([]))
    nil

---

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