A normalised inference response.
:text is the concatenated assistant text. :tool_calls holds any tool
calls the model wants the runtime to execute (empty when the model just
replied with text). :usage carries token accounting when the provider
reports it; :raw keeps the provider's original payload for debugging.
:session_id is the provider-side conversation identifier when the
provider maintains its own session state (e.g. the Claude Code CLI) —
hosts pass it back as resume: to continue that conversation; nil for
stateless providers.
:starvation is a typed capacity signal set by adapters when the turn
was output-starved: the model burned the whole per-turn completion budget
(typically on hidden reasoning) and produced no visible text and no tool
calls. Carries the token counts so the loop can escalate the budget and
callers can diagnose the failure. nil for every healthy turn.
Summary
Types
@type starvation() :: %{ completion_cap: pos_integer() | nil, output_tokens: non_neg_integer() | nil, reasoning_tokens: non_neg_integer() | nil }
@type t() :: %ExAthena.Response{ finish_reason: :stop | :length | :tool_calls | :content_filter | :error | nil, model: String.t() | nil, provider: atom() | module() | nil, raw: term() | nil, session_id: String.t() | nil, starvation: starvation() | nil, text: String.t() | nil, thinking: String.t() | nil, tool_calls: [ExAthena.Messages.ToolCall.t()], usage: usage() | nil }
@type usage() :: %{ optional(:input_tokens) => non_neg_integer(), optional(:output_tokens) => non_neg_integer(), optional(:total_tokens) => non_neg_integer(), optional(:reasoning_tokens) => non_neg_integer() }