## Backends


## LlmBackend


Abstract execution contract for an LLM backend.


Usage

``` python
LlmBackend()
```


Concrete backends map abstract model sizes to provider-specific model names and encapsulate how to execute a [RunSpec](running.md#spawnllm.RunSpec) and parse the raw response. The portable decisions -- argv, output resolution, schema strictification -- run in the shared wasm core; a backend supplies only its `provider` and the I/O.


#### Attributes


`models: dict[`<a href="types.html#spawnllm.types.TModel" class="gdls-link gdls-code"><code>TModel</code></a>`, str]`  
Mapping from abstract model size to the provider's model name.

`provider: ProviderName`  
Provider identifier keying a [RunSpec](running.md#spawnllm.RunSpec)'s `provider_configs`.

`schema_dialect: str | None`  
Strict-schema dialect the core applies to a `response_model` (`"anthropic"`, `"openai"`, or `None` to emit the plain JSON schema).

`auto_select_tiers: frozenset[`<a href="types.html#spawnllm.types.TModel" class="gdls-link gdls-code"><code>TModel</code></a>`] | None`  
Model tiers this backend may be auto-selected for; `None` (the default) leaves it eligible for every tier, and an explicit `backend=` reaches it regardless.


#### Methods

| Name | Description |
|----|----|
| [accounting()](#spawnllm.LlmBackend.accounting) | Return the `(cost_usd, usage)` an attempt's output reports, or `(None, None)` when it carries neither. |
| [aexecute()](#spawnllm.LlmBackend.aexecute) | Execute a single run asynchronously and resolve it to a [Response](running.md#spawnllm.Response). |
| [check_status()](#spawnllm.LlmBackend.check_status) | Check whether this backend is installed and authenticated. |
| [core_plan()](#spawnllm.LlmBackend.core_plan) | Ask the core to plan this run's invocation (an exec argv or an HTTP request). |
| [env()](#spawnllm.LlmBackend.env) | Return extra environment variables for the invocation, merged over the inherited environment. |
| [execute()](#spawnllm.LlmBackend.execute) | Execute a single run synchronously and resolve it to a [Response](running.md#spawnllm.Response). |
| [is_authenticated()](#spawnllm.LlmBackend.is_authenticated) | Probe whether the backend holds valid credentials for its provider. |
| [openai_section()](#spawnllm.LlmBackend.openai_section) | Return the `openai_endpoint` wire section; `None` for every backend but the endpoint backend. |
| [resolve_model()](#spawnllm.LlmBackend.resolve_model) | Resolve an abstract tier to this backend's provider model id, passing a concrete id through unchanged. |
| [schema_for()](#spawnllm.LlmBackend.schema_for) | Serialize a Pydantic model into the JSON-schema string this backend expects. |
| [to_response()](#spawnllm.LlmBackend.to_response) | Resolve a raw capture into a structured [Response](running.md#spawnllm.Response) via the core `resolve` op. |
| [wire_schema()](#spawnllm.LlmBackend.wire_schema) | Return the portable schema object for `spec`, from a `response_model` or a raw `schema`. |
| [wire_spec()](#spawnllm.LlmBackend.wire_spec) | Serialize a [RunSpec](running.md#spawnllm.RunSpec) into the portable wire spec the core `plan`/`resolve` ops consume. |


##### accounting()


Return the `(cost_usd, usage)` an attempt's output reports, or `(None, None)` when it carries neither.


Usage

``` python
accounting(raw)
```


The retry loop calls this on each transient failure it discards, so a caller reconciling spend can still see the cost. The default parses nothing; the CLI family reads the core's `resolve` accounting.


##### Parameters


`raw: str`  
The raw output read wherever the provider wrote it.


##### Returns


`tuple[float | None, dict[str, object] | None]`  
A `(cost_usd, usage)` pair, each `None` when the output does not carry it.


##### aexecute()


Execute a single run asynchronously and resolve it to a [Response](running.md#spawnllm.Response).


Usage

``` python
aexecute(spec)
```


The backend runs the process, reads its output wherever the provider writes it, detects failure, and validates against `spec.response_model`.


##### Parameters


`spec: `<a href="running.html#spawnllm.RunSpec" class="gdls-link gdls-code"><code>RunSpec</code></a>  
The configured run to execute.


##### Returns


<a href="running.html#spawnllm.Response" class="gdls-link gdls-code"><code>Response</code></a>  
The resolved [Response](running.md#spawnllm.Response).


##### check_status()


Check whether this backend is installed and authenticated.


Usage

``` python
check_status(*, timeout=10)
```


##### Parameters


`timeout: int = ``10`  
Seconds to wait for the authentication probe.


##### Returns


<a href="backends.html#spawnllm.BackendStatus" class="gdls-link gdls-code"><code>BackendStatus</code></a>  
[BackendReady](backends.md#spawnllm.BackendReady) when authenticated, [BackendNotInstalled](backends.md#spawnllm.BackendNotInstalled) when the

backend is not available, else [BackendNotAuthenticated](backends.md#spawnllm.BackendNotAuthenticated).


##### core_plan()


Ask the core to plan this run's invocation (an exec argv or an HTTP request).


Usage

``` python
core_plan(spec)
```


##### env()


Return extra environment variables for the invocation, merged over the inherited environment.


Usage

``` python
env(spec)
```


##### Parameters


`spec: `<a href="running.html#spawnllm.RunSpec" class="gdls-link gdls-code"><code>RunSpec</code></a>  
The configured run, so a backend can scope env overrides to `spec.isolated` (e.g. a fresh config home only when isolating).


##### execute()


Execute a single run synchronously and resolve it to a [Response](running.md#spawnllm.Response).


Usage

``` python
execute(spec)
```


##### Parameters


`spec: `<a href="running.html#spawnllm.RunSpec" class="gdls-link gdls-code"><code>RunSpec</code></a>  
The configured run to execute.


##### Returns


<a href="running.html#spawnllm.Response" class="gdls-link gdls-code"><code>Response</code></a>  
The resolved [Response](running.md#spawnllm.Response).


##### is_authenticated()


Probe whether the backend holds valid credentials for its provider.


Usage

``` python
is_authenticated(*, timeout)
```


"Authenticated" means the backend reports an active login session for the provider, not merely that an executable is present on PATH.


##### Parameters


`timeout: int`  
Seconds to wait for the credential probe.


##### Returns


`bool`  
`True` when the backend reports an authenticated session.


##### openai_section()


Return the `openai_endpoint` wire section; `None` for every backend but the endpoint backend.


Usage

``` python
openai_section()
```


##### resolve_model()


Resolve an abstract tier to this backend's provider model id, passing a concrete id through unchanged.


Usage

``` python
resolve_model(model)
```


A tier (`small`/`medium`/`large`) maps through `models`; any other string -- a literal provider model id such as `claude-fable-5` -- returns unchanged, so a caller can pin an exact model anywhere a tier is accepted.


##### Parameters


`model: str`  
An abstract tier or a concrete provider model id.


##### Returns


`str`  
The provider model id to run.


##### schema_for()


Serialize a Pydantic model into the JSON-schema string this backend expects.


Usage

``` python
schema_for(model)
```


The core's `strict_schema` op applies the backend's `schema_dialect` transform over the model's plain JSON schema; a `None` dialect emits the schema unchanged.


##### Parameters


`model: type[BaseModel]`  
The Pydantic model describing the structured output.


##### Returns


`str`  
A JSON-schema string suitable for this backend's structured-output argument.


##### to_response()


Resolve a raw capture into a structured [Response](running.md#spawnllm.Response) via the core `resolve` op.


Usage

``` python
to_response(raw, *, returncode, stderr, spec)
```


`output` always carries the full raw stream. The core detects failure (a nonzero exit or an error envelope) and extracts the final text and, when `spec.response_model` is set, the structured value; a `pydantic.ValidationError` from a non-conforming model routes through `error`.


##### Parameters


`raw: str`  
The raw output read wherever the provider wrote it.

`returncode: int`  
The process exit code.

`stderr: str`  
The captured stderr.

`spec: `<a href="running.html#spawnllm.RunSpec" class="gdls-link gdls-code"><code>RunSpec</code></a>  
The configured run, carrying the optional `response_model` or `schema`.


##### Returns


<a href="running.html#spawnllm.Response" class="gdls-link gdls-code"><code>Response</code></a>  
The resolved [Response](running.md#spawnllm.Response).


##### wire_schema()


Return the portable schema object for `spec`, from a `response_model` or a raw `schema`.


Usage

``` python
wire_schema(spec)
```


##### wire_spec()


Serialize a [RunSpec](running.md#spawnllm.RunSpec) into the portable wire spec the core `plan`/`resolve` ops consume.


Usage

``` python
wire_spec(spec)
```


## CliBackend


Execution contract for the subprocess-backed LLM family.


Usage

``` python
CliBackend()
```


The core plans each invocation's argv, files, env, and result source; this class materializes that plan into temp files and a subprocess, runs it, and resolves the result. Concrete CLI backends supply only ClassVars.


#### Attributes


`binary: str`  
Name of the backend's CLI executable on PATH.

`install_hint: str`  
Suggested shell command to install the CLI.


#### Methods

| Name | Description |
|----|----|
| [accounting()](#spawnllm.CliBackend.accounting) | Return the `(cost_usd, usage)` the core's `resolve` op reads from `raw`. |
| [binary_path()](#spawnllm.CliBackend.binary_path) | Return the command every exec of this backend runs as `argv[0]`. |
| [build_command()](#spawnllm.CliBackend.build_command) | Return the core-planned argv (with `${file:id}` placeholders) for a single invocation. |
| [check_status()](#spawnllm.CliBackend.check_status) | Check whether this backend's CLI is installed and authenticated. |
| [claude_isolation()](#spawnllm.CliBackend.claude_isolation) | Return the isolated config home a claude run substitutes into `${isolated_config_dir}`. |
| [env()](#spawnllm.CliBackend.env) | Return the core-planned env, substituting the isolated config home into a claude run's values. |
| [invocation()](#spawnllm.CliBackend.invocation) | Materialize the core's exec plan into a runnable `Invocation`. |
| [is_authenticated()](#spawnllm.CliBackend.is_authenticated) | Report whether any of the core's auth probes for this provider succeeds. |


##### accounting()


Return the `(cost_usd, usage)` the core's `resolve` op reads from `raw`.


Usage

``` python
accounting(raw)
```


##### binary_path()


Return the command every exec of this backend runs as `argv[0]`.


Usage

``` python
binary_path()
```


The default is `binary` itself, left for the operating system to resolve through `PATH`; a backend whose executable ships inside the wheel returns that path instead.


##### build_command()


Return the core-planned argv (with `${file:id}` placeholders) for a single invocation.


Usage

``` python
build_command(spec)
```


##### check_status()


Check whether this backend's CLI is installed and authenticated.


Usage

``` python
check_status(*, timeout=10)
```


##### Parameters


`timeout: int = ``10`  
Seconds to wait for the authentication probe.


##### Returns


<a href="backends.html#spawnllm.BackendStatus" class="gdls-link gdls-code"><code>BackendStatus</code></a>  
[BackendReady](backends.md#spawnllm.BackendReady) when authenticated, [BackendNotInstalled](backends.md#spawnllm.BackendNotInstalled) when

[binary_path](backends.md#spawnllm.CliBackend.binary_path) names no executable file, else [BackendNotAuthenticated](backends.md#spawnllm.BackendNotAuthenticated).


##### Raises


`subprocess.TimeoutExpired`  
If [is_authenticated](backends.md#spawnllm.LlmBackend.is_authenticated) exceeds `timeout`.


##### claude_isolation()


Return the isolated config home a claude run substitutes into `${isolated_config_dir}`.


Usage

``` python
claude_isolation()
```


##### env()


Return the core-planned env, substituting the isolated config home into a claude run's values.


Usage

``` python
env(spec)
```


##### Parameters


`spec: `<a href="running.html#spawnllm.RunSpec" class="gdls-link gdls-code"><code>RunSpec</code></a>  
The configured run; the plan gates isolation on `spec.isolated`.


##### Returns


`dict[str, str]`  
The plan's env map with `${isolated_config_dir}` resolved, or `{}`.


##### invocation()


Materialize the core's exec plan into a runnable `Invocation`.


Usage

``` python
invocation(spec)
```


Mints a temp file per `files[]` entry (writing its content when non-null), points `argv[0]` at [binary_path](backends.md#spawnllm.CliBackend.binary_path), substitutes `${file:id}` placeholders in the argv and -- for a claude run -- `${isolated_config_dir}`, and wires the plan's stdout/result source and the minted paths into the returned `Invocation` for cleanup.


##### Parameters


`spec: `<a href="running.html#spawnllm.RunSpec" class="gdls-link gdls-code"><code>RunSpec</code></a>  
The configured run to translate into an invocation.


##### Returns


`Invocation`  
An `Invocation` carrying the materialized argv, stdin, and result source.


##### is_authenticated()


Report whether any of the core's auth probes for this provider succeeds.


Usage

``` python
is_authenticated(*, timeout)
```


##### Parameters


`timeout: int`  
Seconds to wait for each subprocess-backed probe.


##### Returns


`bool`  
`True` when a probe reports an authenticated session.


## ClaudeCliBackend


[CliBackend](backends.md#spawnllm.CliBackend) for the Anthropic `claude` CLI.


Usage

``` python
ClaudeCliBackend()
```


The core plans the `claude -p` argv (prompt delivered over stdin, result read from a stdout file) and lays out the host-free config home this backend seeds with only the active-account pointer and claude.ai OAuth token.


#### Attributes


`models: dict[`<a href="types.html#spawnllm.types.TModel" class="gdls-link gdls-code"><code>TModel</code></a>`, str]`  
Mapping from abstract model size to a Claude model alias (`haiku`/`sonnet`/`opus`).


#### Example

``` python
>>> from spawnllm.spec import RunSpec
>>> ClaudeCliBackend().invocation(RunSpec(prompt="hi", model="haiku")).argv[:5]
```

\['claude', '-p', '-no-session-persistence', '-model', 'haiku'\]


#### Methods

| Name | Description |
|----|----|
| [claude_isolation()](#spawnllm.ClaudeCliBackend.claude_isolation) | Return the process-lifetime isolated config home, creating and seeding it once. |


##### claude_isolation()


Return the process-lifetime isolated config home, creating and seeding it once.


Usage

``` python
claude_isolation()
```


The core's `claude_isolation_sources` op resolves the account pointer, credentials file, and Keychain service from the caller's effective config home; this host reads those sources (falling back to the Keychain when the credentials file is absent), hands them to `claude_isolation_seed` for the exact files-and-modes to write, and materializes them into a fresh temp dir removed at interpreter exit. The dir is cached on the backend.


## ClaudeSdkBackend


Claude backend hosted through the optional `claude-agent-sdk` package.


Usage

``` python
ClaudeSdkBackend()
```


The SDK bundles Claude Code, so `pip install 'spawnllm[sdk]'` is the only installation step. Authentication comes from the ambient subscription OAuth session: the bundled CLI resolves `/login` credentials from the platform keychain or uses `CLAUDE_CODE_OAUTH_TOKEN`. Here `isolated=True` makes settings and MCP configuration hermetic through `setting_sources=[]` and `strict_mcp_config`, but unlike [ClaudeCliBackend](backends.md#spawnllm.ClaudeCliBackend) it does not seed a fresh `CLAUDE_CONFIG_DIR`, so credentials come from the ambient config home or `CLAUDE_CODE_OAUTH_TOKEN`.

`api_auth=False` blanks Claude's API-key environment variables because the SDK can only overlay its subprocess environment, not truly unset inherited keys. An explicit `RunSpec.env` value still wins. `ClaudeConfig.mcp_config` passes through the SDK's path-capable `mcp_servers` field. Its `output_format` and `verbose` fields are ignored because the SDK transport always uses stream-JSON with verbose output internally.


#### Attributes


`models: dict[`<a href="types.html#spawnllm.types.TModel" class="gdls-link gdls-code"><code>TModel</code></a>`, str]`  
Mapping from abstract model size to a Claude model alias.

`provider: ProviderName`  
Python-only backend identifier used for selection and config.

`schema_dialect: str | None`  
Anthropic strict-schema dialect applied by the core.


#### Methods

| Name | Description |
|----|----|
| [accounting()](#spawnllm.ClaudeSdkBackend.accounting) | Return cost and usage from a reconstructed event via Claude resolution. |
| [aexecute()](#spawnllm.ClaudeSdkBackend.aexecute) | Execute one SDK query asynchronously and resolve its Claude result event. |
| [build_options()](#spawnllm.ClaudeSdkBackend.build_options) | Translate a [RunSpec](running.md#spawnllm.RunSpec) into the SDK options matching the Claude CLI plan. |
| [check_status()](#spawnllm.ClaudeSdkBackend.check_status) | Check whether the optional SDK is installed and its bundled CLI authenticated. |
| [env()](#spawnllm.ClaudeSdkBackend.env) | Return no host-side environment; the SDK owns its subprocess environment. |
| [execute()](#spawnllm.ClaudeSdkBackend.execute) | Execute one SDK query synchronously via `asyncio.run`. |
| [is_authenticated()](#spawnllm.ClaudeSdkBackend.is_authenticated) | Report whether the SDK's Claude Code executable has an active login. |
| [to_response()](#spawnllm.ClaudeSdkBackend.to_response) | Resolve the SDK's reconstructed event through the core's Claude path. |


##### accounting()


Return cost and usage from a reconstructed event via Claude resolution.


Usage

``` python
accounting(raw)
```


##### Parameters


`raw: str`  
The reconstructed Claude result event.


##### Returns


`tuple[float | None, dict[str, object] | None]`  
The event's `(cost_usd, usage)` pair.


##### aexecute()


Execute one SDK query asynchronously and resolve its Claude result event.


Usage

``` python
aexecute(spec)
```


##### Parameters


`spec: `<a href="running.html#spawnllm.RunSpec" class="gdls-link gdls-code"><code>RunSpec</code></a>  
The configured run to execute.


##### Returns


<a href="running.html#spawnllm.Response" class="gdls-link gdls-code"><code>Response</code></a>  
The resolved [Response](running.md#spawnllm.Response), including normalized SDK and timeout errors.


##### build_options()


Translate a [RunSpec](running.md#spawnllm.RunSpec) into the SDK options matching the Claude CLI plan.


Usage

``` python
build_options(spec)
```


##### Parameters


`spec: `<a href="running.html#spawnllm.RunSpec" class="gdls-link gdls-code"><code>RunSpec</code></a>  
The configured run to translate.


##### Returns


`ClaudeAgentOptions`  
Options for the SDK's one-shot `query` generator.


##### check_status()


Check whether the optional SDK is installed and its bundled CLI authenticated.


Usage

``` python
check_status(*, timeout=10)
```


##### Parameters


`timeout: int = ``10`  
Seconds to wait for the authentication probe.


##### Returns


<a href="backends.html#spawnllm.BackendStatus" class="gdls-link gdls-code"><code>BackendStatus</code></a>  
[BackendReady](backends.md#spawnllm.BackendReady) when authenticated, [BackendNotInstalled](backends.md#spawnllm.BackendNotInstalled) without the

SDK extra, else [BackendNotAuthenticated](backends.md#spawnllm.BackendNotAuthenticated).


##### env()


Return no host-side environment; the SDK owns its subprocess environment.


Usage

``` python
env(_spec)
```


##### execute()


Execute one SDK query synchronously via `asyncio.run`.


Usage

``` python
execute(spec)
```


##### Parameters


`spec: `<a href="running.html#spawnllm.RunSpec" class="gdls-link gdls-code"><code>RunSpec</code></a>  
The configured run to execute.


##### Returns


<a href="running.html#spawnllm.Response" class="gdls-link gdls-code"><code>Response</code></a>  
The resolved [Response](running.md#spawnllm.Response).


##### Raises


`RuntimeError`  
If called from a thread already running an event loop.


##### is_authenticated()


Report whether the SDK's Claude Code executable has an active login.


Usage

``` python
is_authenticated(*, timeout)
```


##### Parameters


`timeout: int`  
Seconds to wait for `claude auth status`.


##### Returns


`bool`  
`True` when the authentication probe exits successfully.


##### to_response()


Resolve the SDK's reconstructed event through the core's Claude path.


Usage

``` python
to_response(raw, *, returncode, stderr, spec)
```


##### Parameters


`raw: str`  
The reconstructed Claude result event.

`returncode: int`  
The synthesized transport exit code.

`stderr: str`  
The SDK error text, when present.

`spec: `<a href="running.html#spawnllm.RunSpec" class="gdls-link gdls-code"><code>RunSpec</code></a>  
The configured run carrying any response model.


##### Returns


<a href="running.html#spawnllm.Response" class="gdls-link gdls-code"><code>Response</code></a>  
The resolved [Response](running.md#spawnllm.Response).


## CodexCliBackend


[CliBackend](backends.md#spawnllm.CliBackend) for the OpenAI `codex` CLI.


Usage

``` python
CodexCliBackend()
```


The core plans a `codex exec` argv that runs an ephemeral session in a read-only sandbox, resolving the schema to an `--output-schema` file and the final message to an `-o` file. It pins `service_tier=fast` by default (an isolated run passes `--ignore-user-config`, dropping a user-level tier pin, and the standard tier turns long prompts into multi-minute runs).


#### Attributes


`models: dict[`<a href="types.html#spawnllm.types.TModel" class="gdls-link gdls-code"><code>TModel</code></a>`, str]`  
Mapping from abstract model size to an OpenAI model name.


#### Example

``` python
>>> from spawnllm.spec import RunSpec
>>> CodexCliBackend().invocation(RunSpec(prompt="hi", model="gpt-5.5")).argv[:4]
```

\['codex', 'exec', '-ephemeral', '-sandbox'\]


## GeminiCliBackend


[CliBackend](backends.md#spawnllm.CliBackend) for Google's `gemini` CLI.


Usage

``` python
GeminiCliBackend()
```


The core plans a `gemini --model … -o json` invocation with the prompt delivered inline via `-p`; structured output appends the JSON schema and an instruction to emit only conforming JSON. Authentication prefers cached OAuth credentials and falls back to a `GEMINI_API_KEY`/`GOOGLE_API_KEY` env key.


#### Attributes


`models: dict[`<a href="types.html#spawnllm.types.TModel" class="gdls-link gdls-code"><code>TModel</code></a>`, str]`  
Mapping from abstract model size to a Gemini model name.


#### Example

``` python
>>> from spawnllm.spec import RunSpec
>>> GeminiCliBackend().invocation(RunSpec(prompt="hi", model="gemini-2.5-flash")).argv[:5]
```

\['gemini', '-model', 'gemini-2.5-flash', '-o', 'json'\]


## AntigravityCliBackend


[CliBackend](backends.md#spawnllm.CliBackend) for the Antigravity `agy` CLI, a Gemini-family successor.


Usage

``` python
AntigravityCliBackend()
```


The core plans an `agy --model … -p` invocation and reads its plain-text stdout. Authentication prefers an Antigravity login stored in the macOS keychain and falls back to a `GEMINI_API_KEY`/`ANTIGRAVITY_API_KEY` env key.


#### Attributes


`models: dict[`<a href="types.html#spawnllm.types.TModel" class="gdls-link gdls-code"><code>TModel</code></a>`, str]`  
Mapping from abstract model size to an Antigravity model name.


#### Example

``` python
>>> from spawnllm.spec import RunSpec
>>> AntigravityCliBackend().invocation(RunSpec(prompt="hi", model="gemini-3.5")).argv[:3]
```

\['agy', '-model', 'gemini-3.5'\]


## AppleBackend


[CliBackend](backends.md#spawnllm.CliBackend) for the `spawnllm-apple` on-device Foundation Models sidecar.


Usage

``` python
AppleBackend()
```


The core plans a single `spawnllm-apple` invocation carrying the whole request as one JSON object on stdin and reads one JSON envelope back from stdout. Generation is local to the device, so there is no credential: [RunSpec](running.md#spawnllm.RunSpec)'s `model`, `isolated`, `api_auth`, [env](backends.md#spawnllm.LlmBackend.env), and `cwd` are all inert, and "authenticated" means the sidecar's `--probe` reports Apple Intelligence available. [AppleConfig](running.md#spawnllm.AppleConfig) carries the knobs that do apply -- the use case and guardrails the session is built with, its instructions, and the decoding options.

The macOS wheel bundles the sidecar, so [binary_path](backends.md#spawnllm.CliBackend.binary_path) prefers it and falls back to `PATH`; where neither resolves -- Linux, or a wheel built without it -- the backend reports [BackendNotInstalled](backends.md#spawnllm.BackendNotInstalled) and auto-selection passes it by.


#### Attributes


`models: dict[`<a href="types.html#spawnllm.types.TModel" class="gdls-link gdls-code"><code>TModel</code></a>`, str]`  
Empty identity mapping; the device hosts exactly one model.

`provider: ProviderName`  
Provider identifier keying [AppleConfig](running.md#spawnllm.AppleConfig) on a [RunSpec](running.md#spawnllm.RunSpec).

`binary: str`  
Name of the sidecar executable.

`install_hint: str`  
Suggested shell command to build the sidecar.

`schema_dialect: str | None`  
Apple strict-schema dialect the core applies.

`auto_select_tiers: frozenset[`<a href="types.html#spawnllm.types.TModel" class="gdls-link gdls-code"><code>TModel</code></a>`] | None`  
Only `small`; the on-device model is a small model.


#### Example

``` python
>>> from spawnllm.spec import RunSpec
>>> AppleBackend().invocation(RunSpec(prompt="ping", model="small")).stdin[:16]
```

'{"prompt":"ping"'


#### Methods

| Name | Description |
|----|----|
| [binary_path()](#spawnllm.AppleBackend.binary_path) | Return the wheel-bundled sidecar's path, or the bare binary name for a `PATH` lookup. |


##### binary_path()


Return the wheel-bundled sidecar's path, or the bare binary name for a `PATH` lookup.


Usage

``` python
binary_path()
```


## MlxBackend


In-process backend that runs a prompt through a local [MlxEngine](mlx.md#spawnllm.mlx.MlxEngine).


Usage

``` python
MlxBackend(engine, *, max_tokens=512)
```


Unlike the CLI backends this is never auto-selected; the consumer constructs it explicitly with a loaded [MlxEngine](mlx.md#spawnllm.mlx.MlxEngine). `RunSpec.model` is ignored -- the engine is already bound to a fused model -- and every provider config and CLI flag is irrelevant, so `models` is the empty identity mapping. The core knows no `mlx` provider, so resolution stays in-process here.


#### Example

``` python
>>> backend = MlxBackend(engine=engine, max_tokens=512)
>>> backend.execute(RunSpec(prompt="ping", model="local"))
```


#### Methods

| Name | Description |
|----|----|
| [check_status()](#spawnllm.MlxBackend.check_status) | Report [BackendReady](backends.md#spawnllm.BackendReady); the engine is local and always available once loaded. |
| [env()](#spawnllm.MlxBackend.env) | Return no extra environment variables; MLX runs in-process with nothing to isolate. |
| [is_authenticated()](#spawnllm.MlxBackend.is_authenticated) | Report `True`; the engine is local and needs no credentials. |
| [result_value()](#spawnllm.MlxBackend.result_value) | Return the `structured_output` from a stream-json result event, else `raw` parsed as JSON. |
| [to_response()](#spawnllm.MlxBackend.to_response) | Resolve locally-generated text into a [Response](running.md#spawnllm.Response), validating a `response_model` when set. |


##### check_status()


Report [BackendReady](backends.md#spawnllm.BackendReady); the engine is local and always available once loaded.


Usage

``` python
check_status(*, timeout=10)
```


##### env()


Return no extra environment variables; MLX runs in-process with nothing to isolate.


Usage

``` python
env(_spec)
```


##### is_authenticated()


Report `True`; the engine is local and needs no credentials.


Usage

``` python
is_authenticated(*, timeout)
```


##### result_value()


Return the `structured_output` from a stream-json result event, else `raw` parsed as JSON.


Usage

``` python
result_value(raw)
```


##### to_response()


Resolve locally-generated text into a [Response](running.md#spawnllm.Response), validating a `response_model` when set.


Usage

``` python
to_response(raw, *, returncode, stderr, spec)
```


## OpenAiEndpointBackend


[LlmBackend](backends.md#spawnllm.LlmBackend) that POSTs to an OpenAI-compatible `/chat/completions` endpoint.


Usage

``` python
OpenAiEndpointBackend(base_url, model, *, api_key="local", transport=None)
```


Unlike the CLI backends this drives a raw `httpx` request rather than a subprocess, and it is never auto-selected; the consumer constructs it explicitly with a `base_url` and a literal `model`. The core plans the HTTP request (url, headers, body -- a strict `json_schema` `response_format` when a `response_model` is set) and resolves the response; every abstract tier maps to the one pinned `model`, and `RunSpec.model` is ignored at request time.


#### Parameters


`base_url: str`  
Root URL of the server; `/chat/completions` is appended.

`model: str`  
The literal model id sent in every request body.

`api_key: str = ``"local"`  
Bearer token for the `Authorization` header; defaults to `"local"` for self-hosted servers that ignore it.

`transport: httpx.AsyncBaseTransport | None = None`  
Async transport injected into the `httpx.AsyncClient` used by [aexecute](backends.md#spawnllm.LlmBackend.aexecute) -- e.g. a record/replay caching transport; `None` uses httpx's default transport. The synchronous [execute](backends.md#spawnllm.LlmBackend.execute) path always uses the default transport.


#### Example

``` python
>>> backend = OpenAiEndpointBackend("http://localhost:8000/v1", "qwen3")
>>> backend.execute(RunSpec(prompt="ping", model="qwen3"))
```


#### Methods

| Name | Description |
|----|----|
| [check_status()](#spawnllm.OpenAiEndpointBackend.check_status) | Report [BackendReady](backends.md#spawnllm.BackendReady); the endpoint is reached per-request and carries its own auth. |
| [env()](#spawnllm.OpenAiEndpointBackend.env) | Return no extra environment variables; the endpoint is reached over HTTP with nothing to isolate. |
| [is_authenticated()](#spawnllm.OpenAiEndpointBackend.is_authenticated) | Report `True`; credentials travel inline as the `Authorization` bearer token on every request. |
| [openai_section()](#spawnllm.OpenAiEndpointBackend.openai_section) | Return the `openai_endpoint` wire section the core turns into the HTTP request. |


##### check_status()


Report [BackendReady](backends.md#spawnllm.BackendReady); the endpoint is reached per-request and carries its own auth.


Usage

``` python
check_status(*, timeout=10)
```


##### env()


Return no extra environment variables; the endpoint is reached over HTTP with nothing to isolate.


Usage

``` python
env(_spec)
```


##### is_authenticated()


Report `True`; credentials travel inline as the `Authorization` bearer token on every request.


Usage

``` python
is_authenticated(*, timeout)
```


##### openai_section()


Return the `openai_endpoint` wire section the core turns into the HTTP request.


Usage

``` python
openai_section()
```


## LlmBackends


Registry mapping each specialty to the [LlmBackend](backends.md#spawnllm.LlmBackend) that serves it.


Usage

``` python
LlmBackends()
```


`debugging` and `review` route to [CodexCliBackend](backends.md#spawnllm.CodexCliBackend); `general` routes to the first-priority [ClaudeSdkBackend](backends.md#spawnllm.ClaudeSdkBackend).


#### Attributes


`LLM_BACKENDS: dict[`<a href="types.html#spawnllm.types.TSpecialty" class="gdls-link gdls-code"><code>TSpecialty</code></a>`, `<a href="backends.html#spawnllm.LlmBackend" class="gdls-link gdls-code"><code>LlmBackend</code></a>`]`  
Mapping from specialty to its backend instance.


#### Methods

| Name | Description |
|----|----|
| [for_specialty()](#spawnllm.LlmBackends.for_specialty) | Return the backend registered for a specialty. |


##### for_specialty()


Return the backend registered for a specialty.


Usage

``` python
for_specialty(specialty)
```


##### Parameters


`specialty: `<a href="types.html#spawnllm.types.TSpecialty" class="gdls-link gdls-code"><code>TSpecialty</code></a>  
One of `debugging`, `review`, or `general`.


##### Returns


<a href="backends.html#spawnllm.LlmBackend" class="gdls-link gdls-code"><code>LlmBackend</code></a>  
The [LlmBackend](backends.md#spawnllm.LlmBackend) instance that serves `specialty`.


## select_backend()


Return the first installed, authenticated backend in priority order.


Usage

``` python
select_backend(*, specialty=None, model=None, timeout=10)
```


A `specialty`, when given, promotes its registered backend to the front of the chain; the chain otherwise follows `PRIORITY`, minus [GeminiCliBackend](backends.md#spawnllm.GeminiCliBackend) (its Code Assist OAuth tier is retired, so it reports ready yet fails at call time -- reach it only via an explicit `backend=`) and minus any backend whose `auto_select_tiers` excludes `model`. The first backend whose [check_status](backends.md#spawnllm.LlmBackend.check_status) reports [BackendReady](backends.md#spawnllm.BackendReady) wins, short-circuiting the rest; backends that time out are skipped.


#### Parameters


`specialty: `<a href="types.html#spawnllm.types.TSpecialty" class="gdls-link gdls-code"><code>TSpecialty</code></a>` | None = None`  
Specialty whose backend is tried first, or `None`.

`model: `<a href="types.html#spawnllm.types.TModel" class="gdls-link gdls-code"><code>TModel</code></a>` | str | None = None`  
The abstract tier the run wants, gating tier-restricted backends; a concrete provider model id or `None` excludes every one of them.

`timeout: int = ``10`  
Seconds to wait for each backend's authentication probe.


#### Returns


<a href="backends.html#spawnllm.LlmBackend" class="gdls-link gdls-code"><code>LlmBackend</code></a>  
The first ready [LlmBackend](backends.md#spawnllm.LlmBackend).


#### Raises


<a href="backends.html#spawnllm.BackendUnavailable" class="gdls-link gdls-code"><code>BackendUnavailable</code></a>  
When no backend is installed and authenticated.


## BackendStatus


Result of [LlmBackend.check_status](backends.md#spawnllm.LlmBackend.check_status): [BackendReady](backends.md#spawnllm.BackendReady), [BackendNotInstalled](backends.md#spawnllm.BackendNotInstalled), or [BackendNotAuthenticated](backends.md#spawnllm.BackendNotAuthenticated).


`BackendStatus=BackendReady | BackendNotInstalled | BackendNotAuthenticated`  


## BackendReady


A backend whose CLI is installed and authenticated.


Usage

``` python
BackendReady(binary)
```


#### Attributes


`binary: str`  
Name of the backend's CLI executable on PATH.


## BackendNotInstalled


A backend whose CLI is not on PATH.


Usage

``` python
BackendNotInstalled(binary, install_hint)
```


#### Attributes


`binary: str`  
Name of the backend's CLI executable.

`install_hint: str`  
Suggested shell command to install the CLI.


## BackendNotAuthenticated


A backend whose CLI is installed but not authenticated.


Usage

``` python
BackendNotAuthenticated(binary)
```


#### Attributes


`binary: str`  
Name of the backend's CLI executable on PATH.


## BackendUnavailable


Raised when no backend is ready (installed and authenticated).


Usage

``` python
BackendUnavailable()
```
