Skip to content

Providers

Stability: files, batches, standalone generation endpoints, stored-cache resources and live sessions are provisional in 1.0. They ship, but may change incompatibly in 1.x with a contract change entry; their presence on a provider class does not make them part of the frozen chat API. See release scope.

AnthropicLM dataclass

Bases: BaseProviderLM

Anthropic Messages dialect, bound to an access policy.

access defaults to the API-key policy (lm15.access.ANTHROPIC_API); lm15.access.CLAUDE_CODE binds the same dialect to a local Claude Code login (ClaudeCodeLM is that binding under a name). The policy is consulted at exactly these points: the auth header, static headers (anthropic-beta is joined with the dialect's own betas), the system prefix, the login hint on errors, and the endpoint surfaces.

AsyncBaseProviderLM

Shared asynchronous provider LM implementation.

Mirrors :class:BaseProviderLM faithfully: build (delegated, pure) -> await async transport -> parse (delegated, pure); status>=400 raises the delegated normalize_error; transport errors are wrapped in lm15.TransportError. Streaming applies MAP-3 via :func:lm15.result.acoalesce_stream.

access: ProviderManifest property

The bound access policy — the inner sync adapter's.

plan(request: Request)

What a call WOULD adapt (MAP-13), no network, no credential; pure, so sync.

list_models() async

Async mirror of BaseProviderLM.list_models (canonical ModelInfo).

batch(requests, *, model: str | None = None, label: str | None = None, extensions=None) async

Third execution mode, async twin: returns an AsyncBatchJob.

AsyncOpenAIChatLM dataclass

Bases: AsyncBaseProviderLM

request_from_openai_chat(body: 'Mapping[str, Any]') -> Request

Pure; the sync sibling's, under this adapter's compat (MAP-12).

response_from_openai_chat(body: 'Mapping[str, Any]', *, model: str | None = None, choice: int | None = None) -> Response

Pure; the sync sibling's reader under this adapter's provider name.

complete(request: Request) -> Response async

Mirror of OpenAIChatLM.complete: the judgment trie driver (MAP-14 §4) over the inner adapter's pure hooks, else the ordinary path.

AsyncTransport

Bases: Protocol

Minimal async transport surface used by async provider LMs.

stream returns an async context manager producing an :class:AsyncTransportResponse (StdlibAsyncTransport's shape).

AsyncTypeSafeLM dataclass

Bases: AsyncBaseProviderLM

Async mirror of :class:TypeSafeLM (composition; the inner adapter cannot reach the network).

AsyncXaiLM dataclass

Bases: AsyncBaseProviderLM

Async mirror of :class:XaiLM (subscription OAuth or bearer key).

BaseProviderLM

Shared synchronous provider LM implementation.

An adapter is a dialect (the class) bound to an access policy (a value, lm15.access): the policy says which credential travels in which header, which static headers ride along, which endpoint surfaces this access path carries, and which backend variant the dialect must switch on. manifest is the class's default policy; access is the bound one. Dialect code reads self.access at a small set of stated points and never carries a subclass per access path.

supports: EndpointSupport property

The endpoint surfaces this bound access path carries.

has_stored_credential() -> bool classmethod

Offline probe for the router's oauth-unless-explicit chain (spec/auth.md AUTH-1): is a usable login stored locally?

credential_origin() -> str

Where this adapter's credential comes from, as a sentence fragment with no secret in it (AUTH-1 provenance). For a cloud chain provider this is the rung that last won, or what will be walked when no request has been sent yet.

plan(request: Request, *, policy: 'AdaptationPolicy | None' = None) -> 'tuple[Adaptation, ...]'

What a call with this request WOULD adapt, with no network and no credential invoked (like resolve(), offline). Raises what the call would raise (a refusal under any policy, or every deviation under adaptations="refuse"). Returns the full record under every policy, "silent" included: a preview that hid what it saw would be no preview.

image_generate(request: ImageGenerationRequest) -> ImageGenerationResponse

Generate (or, with request.images, edit) images.

Input images are ordinary ImageParts; adapters route them to the provider's real edit door (OpenAI: /images/edits; Gemini: the same chat call; xAI: /images/edits) and raise where the wire has none — never silently ignore them.

speech_generate(request: SpeechGenerationRequest) -> SpeechGenerationResponse

Text-to-speech. Omitted voice/format mean the server's defaults, honestly reported in the returned part's media_type — lm15 injects no defaults of its own.

video_submit(request: VideoGenerationRequest) -> VideoJobInfo

Submit a video job; returns the ticket snapshot.

video_result(video_id: str) -> VideoPart

The finished video as a VideoPart, in the provider's own delivery mode (URL or bytes) — no silent re-hosting, no silent gigabyte download; part.bytes fetches URL results on demand. Raises ValueError while the job runs.

video_list(limit: int = 20, model: str | None = None) -> 'tuple[VideoJobInfo, ...]'

One page of this credential's video jobs. model is required on Gemini (operations list per model), ignored on OpenAI; xAI has no list endpoint at all and raises.

video_generate(request: VideoGenerationRequest) -> 'VideoJob'

Submit and wrap the ticket in a VideoJob handle.

video_job(video_id: str) -> 'VideoJob'

Re-attach to an existing job by id alone.

video_jobs(limit: int = 20, model: str | None = None) -> 'tuple[VideoJob, ...]'

Enumerate this credential's video jobs, where the wire lists them (OpenAI: account-wide; Gemini: per model, pass model). xAI has no list endpoint and raises: the ticket you stored is the only copy.

list_models() -> 'tuple[ModelInfo, ...]'

Fetch the models this credential can use, as canonical ModelInfo.

batch_submit(request: BatchRequest) -> BatchJobInfo

Submit to the provider's batch queue; returns the ticket snapshot.

batch_results(batch_id: str) -> 'tuple[BatchEntry, ...]'

Entries in submission order; raises ValueError while the job runs.

batch_cancel(batch_id: str) -> BatchJobInfo

Request cancellation — a request, not a guarantee.

batch_list(limit: int = 20) -> 'tuple[BatchJobInfo, ...]'

Enumerate this credential's batch jobs, newest first.

The provider is the system of record; recovery from a lost id must never depend on the user having been careful.

batch(requests: 'BatchRequest | Sequence[Request]', *, model: str | None = None, label: str | None = None, extensions: 'dict[str, Any] | None' = None) -> 'BatchJob'

Third execution mode: many requests, later, ~half price.

batch_job(batch_id: str) -> 'BatchJob'

Re-attach to a submitted batch from its id (one status round trip).

batches(limit: int = 20) -> 'tuple[BatchJob, ...]'

Lost the ticket? The queue remembers.

cache_create(prefix: Request, *, ttl_seconds: int | None = None, label: str | None = None) -> CacheInfo

Store the prefix (model, system, tools, messages) as a cache object.

cache_delete(cache_id: str) -> None

Returning without an exception IS the confirmation (the files precedent).

cache(prefix: Request, *, ttl_seconds: int | None = None, label: str | None = None) -> CachedPrefix

Make a prompt beginning reusable with the best tier this provider has.

Resource tier: creates the stored object (one network call, billed per hour while it lives) and returns it inside the CachedPrefix. Marks and automatic tiers: pure — the CachedPrefix only records the boundary; cached + messages places the mark or sends nothing.

file_upload(request: FileUploadRequest) -> FileInfo

Store a file with the provider; returns its canonical snapshot.

FileInfo.id is the reference to place in a media Part's file_id. On Gemini the file may come back pending (processing); file_wait_ready covers that.

file_list(limit: int = 20, cursor: str | None = None) -> FilePage

One page of this credential's stored files.

The provider is the system of record: a lost file id is recovered by listing, never by client-side bookkeeping. cursor is the opaque next_cursor of the previous page.

file_delete(file_id: str) -> None

Delete a stored file. Returning without an exception IS the confirmation; provider acknowledgement bodies differ and carry no canonical information.

file_download(file_id: str) -> bytes

Download a file's content, when THIS file supports download.

Every provider restricts which files are downloadable (Anthropic: tool-generated only; OpenAI: by purpose; Gemini: generated only) and refuses the rest with a typed error — forwarded, not masked.

file_wait_ready(file_id: str, poll_every: float = 2.0, timeout: float | None = None) -> FileInfo

Poll until the file leaves pending; returns the terminal snapshot (ready or failed) — check readiness, mirroring BatchJob.wait's return-don't-raise convention. Gemini uploads and Azure OpenAI v1 uploads can be pending; the first poll usually returns.

HttpResponse dataclass

Buffered provider-level HTTP response.

The stdlib transport is streaming-first. LMs that implement ordinary request/response endpoints buffer the body into this small value object so their parsing code can stay pure and easy to test.

json()

The body as JSON. A body that is not JSON — a gateway's HTML error page behind a 200, a truncated reply, a captive portal — is a provider reply that cannot become a Response without inventing one, so it raises :class:ProviderError (ErrorCode provider) carrying the status and the first bytes of what arrived. A raw JSONDecodeError would escape every except LM15Error and say nothing about who sent what.

SyncTransport

Bases: Protocol

Minimal sync transport surface used by provider LMs.

ClaudeCodeLM

Bases: AnthropicLM

Anthropic Messages adapter authenticated with local Claude Code OAuth.

GeminiLM dataclass

OpenAILM dataclass

Bases: BaseProviderLM

OpenAI Responses dialect, bound to an access policy.

access defaults to the API-key policy (lm15.access.OPENAI_API); lm15.access.OPENAI_CODEX binds the same dialect to the ChatGPT Codex backend on a local Codex CLI login (OpenAICodexLM is that binding under a name). Policy consult points: the auth header and static headers, the chatgpt-account-id header when the credential carries an account, the login hint on errors, the endpoint surfaces, and the backend switch at four stated places — payload defaults (instructions prefix, store: false, streaming-only, no max-token knob), streaming-first complete, the {"detail": ...} error envelope, and the /models endpoint shape.

from_profile(*, api_key: Credential, profile: ProviderProfile, transport: SyncTransport | None = None) -> 'OpenAILM' classmethod

DEPRECATED (1.0.0rc2; removed in 1.0.0): OpenAILM(api_key=..., compat=..., base_url=...).

normalize_error(status: int, body: str) -> ProviderError

Extract message from OpenAI error shape.

OpenAIChatLM dataclass

Bases: BaseProviderLM

Adapter for the OpenAI Chat Completions wire dialect.

compat may be an :class:OpenAIChatCompat, a preset name ("ollama", "groq", "openrouter", "vllm", "sglang", "openai", …), or None (plain OpenAI policy). A preset name also supplies that server's default base_url; an explicit non-default base_url argument always wins.

request_from_openai_chat(body: Mapping[str, Any]) -> Request

The inverse of :meth:build_request's body under this adapter's compat (MAP-12): a Chat Completions request body → canonical :class:Request. See :func:request_from_openai_chat.

response_from_openai_chat(body: Mapping[str, Any], *, model: str | None = None, choice: int | None = None, response_format: Mapping[str, Any] | None = None) -> Response

A Chat Completions response body → canonical :class:Response under this adapter's provider name and error mapping; see :func:response_from_openai_chat. response_format (the request's) folds a judgment answer into a DataPart (MAP-14).

OpenAICodexLM

Bases: OpenAILM

OpenAI Responses adapter authenticated with local Codex CLI OAuth.

TypeSafeLM dataclass

Bases: BaseProviderLM

TypeSafe System One dialect (POST /v1/systemone).

XaiLM

Bases: OpenAIChatLM

Chat Completions adapter for xAI, with subscription OAuth fallback.

xAI is a provider, not an access path: its image and video wire, and its refusals (reasoning off, logprobs, the MAP-8 cells), are provider facts and live here. Only the credential path is composed: the lm15.access.XAI policy carries the oauth-unless-explicit chain, the login hint, and the endpoint surfaces.

resolve_credential(credential: Credential) -> str

The bearer/key STRING of a credential — the pre-2026-09-03 shape the dialects' header code reads. AWS credentials have no single string; they travel as a SigV4 signature (_emit), never through here.