The Provider (ADR 0002/0003/0019): the OpenAI Responses API dialect, reached with
either Credential kind. Pixir always sends store: false; the local Log remains the
source of truth. The HTTP/SSE path sends folded History as full input. The
WebSocket path may use connection-local previous_response_id and a late delta as an
optimization, but it never replaces Log replay.
stream/2 performs one streamed model call:
- ephemeral
text/reasoningdeltas are delivered to the:on_deltacallback as{:text_delta, chunk}/{:reasoning_delta, chunk}(the Turn loop turns these into ephemeral Events — keeping this module free of bus/Session deps); - the assembled result
%{text, reasoning, function_calls, finish_reason}is returned for the Turn loop to persist (the finalassistant_message) and to decide whether to run tools.
Errors are structured (ADR 0005). Tests may still inject :transport directly; the
production path uses Pixir.Provider.TransportPolicy (:auto | :websocket | :http_sse) so WebSocket can be preferred while HTTP/SSE remains fallback. Routing is
frozen once per stream invocation; authentication is resolved once per logical
attempt and reused by any transport fallback inside that attempt. An explicit
open_responses backend uses the portable HTTP/SSE body/header policy, strict WHATWG
framing, generated pinned-schema validation before capability policy, and a
conservative no-reasoning/nonportable-output boundary; the default ChatGPT/Codex
wire and compatibility reducer remain separate.
Known strict-open events alone reach that reducer; unknown matched event names are
counted as bounded other evidence and their payloads remain opaque.
Summary
Functions
Resolve the model id (open knob) through Pixir.Config.load/1's effective snapshot.
That snapshot applies this precedence
Whether model_id is in the advertised catalog (models/0). Used to reject an
unknown per-turn _meta.model before it reaches the backend (epic A.5,
decision #8 — fail early with -32602 rather than passing through to a backend
model_not_supported).
The model catalog Pixir advertises to a client (epic A.5). A list of
%{"id" => slug, "name" => label, "default" => bool} (string-keyed so it
rides ACP _meta verbatim). Source: the built-in list (gpt-5.5 &
family), extended/overridden by a ~/.pixir/config.json "models" array of
slugs if present. The active default_model/0 is always included and flagged
default: true (so the client's picker has a default even if config narrows
the list).
Cheaply validate connectivity and the model id: a minimal streamed call (tiny
prompt, no tools). Returns {:ok, %{model: id}} if the backend accepts it, or the
structured error otherwise (e.g. a provider_http_error for a bad model id). Useful
before committing to a full Turn.
Build a Responses request body preview without auth or network.
Whether this Provider accepts an explicit Responses backend selection.
Stream one Responses call, retrying transient failures (network, :rate_limited,
5xx) with capped exponential backoff. Terminal errors (:usage_limit_reached,
:model_not_supported, auth) are not retried. See the module doc for the result
shape. Options: :max_retries (default 2), :sleep (injectable for tests).
Map a tool definition from a __tool__/0 callback to a Responses function tool.
Normalize OpenAI usage payloads into the fields Pixir records as Provider evidence.
Types
@type request() :: %{ optional(:model) => String.t(), optional(:system_prompt) => String.t(), optional(:developer_context) => String.t(), optional(:workspace) => String.t(), optional(:history) => [map()], optional(:tools) => [map()], optional(:hosted_tools) => [map()], optional(:web_search) => map() | keyword() | boolean(), optional(:prompt_cache_key) => String.t(), optional(:prompt_cache_retention) => String.t(), optional(:output_schema) => map() }
@type result() :: %{ text: String.t(), reasoning: String.t(), reasoning_items: [map()], function_calls: [%{call_id: String.t(), name: String.t(), args: map()}], output_items: [ reasoning: map(), function_call: map(), provider_hosted_tool: map() ], provider_hosted_tools: map(), web_search: map(), finish_reason: :stop | :tool_calls, usage: map() | nil, usage_summary: map(), provider_metadata: map(), output_truncation: Pixir.Provider.OutputTruncation.t() }
Functions
Resolve the model id (open knob) through Pixir.Config.load/1's effective snapshot.
That snapshot applies this precedence:
config :pixir, :model(programmatic override)PIXIR_MODELenv var~/.pixir/config.json→"model"- the built-in default (
gpt-5.5) when earlier values are absent or blank
Whether model_id is in the advertised catalog (models/0). Used to reject an
unknown per-turn _meta.model before it reaches the backend (epic A.5,
decision #8 — fail early with -32602 rather than passing through to a backend
model_not_supported).
The model catalog Pixir advertises to a client (epic A.5). A list of
%{"id" => slug, "name" => label, "default" => bool} (string-keyed so it
rides ACP _meta verbatim). Source: the built-in list (gpt-5.5 &
family), extended/overridden by a ~/.pixir/config.json "models" array of
slugs if present. The active default_model/0 is always included and flagged
default: true (so the client's picker has a default even if config narrows
the list).
Cheaply validate connectivity and the model id: a minimal streamed call (tiny
prompt, no tools). Returns {:ok, %{model: id}} if the backend accepts it, or the
structured error otherwise (e.g. a provider_http_error for a bad model id). Useful
before committing to a full Turn.
Build a Responses request body preview without auth or network.
This uses the same request-shaping path as stream/2, including Provider-hosted
tools, prompt-cache fields, and the px2 developer-context item. Smoke tasks should
still bound/redact the returned body before printing it.
Whether this Provider accepts an explicit Responses backend selection.
Stream one Responses call, retrying transient failures (network, :rate_limited,
5xx) with capped exponential backoff. Terminal errors (:usage_limit_reached,
:model_not_supported, auth) are not retried. See the module doc for the result
shape. Options: :max_retries (default 2), :sleep (injectable for tests).
Map a tool definition from a __tool__/0 callback to a Responses function tool.
Normalize OpenAI usage payloads into the fields Pixir records as Provider evidence.
Supports the Responses shape (input_tokens_details.cached_tokens) and the legacy
prompt/completion naming used by older examples.