create_client(**options) is a factory function that returns a client. All arguments are keyword-only; call it directly (it is not a class).
Credential resolution
Each URL and credential resolves with a per-option precedence, so an app can construct the client from the environment alone:- URLs (
base_url,gateway_url) — option → environment variable → built-in default. api_key,project_id,env— option → environment variable (no default).format— option only.
api_key (a to11 API key). For control-plane calls the SDK sets Authorization: Bearer <api_key> for you and carries the project in the URL path. project_id and env are validated at construction — a blank project_id, or an env that isn’t a lowercase-kebab slug, raises ValueError.
Keep credentials server-side. A to11 API key carries gateway access, so it must never ship to an end user’s device. The same goes for a
provider_api_key (BYOK). Use the SDK from a server, CLI, or backend job.Options
What the client exposes
- Resource namespaces
promptsandproject_environments. - Read-only accessors for the resolved config:
client.base_url,client.gateway_url(the gateway root, host only — no/v1),client.api_key,client.project_id(orNonewhen unset), andclient.env(orNonewhen unset).provider_api_key(BYOK) is deliberately not exposed — it’s a secret, not a config value to read. - Provider-client options
openai_options()andanthropic_options(), each returningbase_url,api_key, anddefault_headerskwargs for a gateway-pointed client. - The context factory
session(),conversation(), andturn()— see Sessions, conversations & turns.
project_id set here is the default for every prompts.* method — render() and the lifecycle / version / label calls (get, list, get_version, move_label, …). Bind it once on the client and omit it per call; pass project_id on an individual call only to override.
Provider-client options
openai_options() and anthropic_options() return spread-ready kwargs — base_url, api_key, and default_headers — for a provider client that targets the gateway. Both point at the same gateway; the base_url differs only by each SDK’s own convention: openai_options() returns f"{gateway_url}/v1" (the OpenAI client puts /v1 in base_url), while anthropic_options() returns the gateway root (the Anthropic client appends /v1/messages itself). default_headers carries the static tenant auth (x-to11-authorization, x-to11-project-id, and x-to11-env when set), so the client authenticates on its own; add turn().headers(prompt) per call for the request’s trace id and prompt provenance.
project_id is required (it becomes x-to11-project-id); the helpers raise without one, or without an api_key.
api_key: managed vs BYOK
The returnedapi_key is the provider client’s key:
- Managed (default): with no
provider_api_key,api_keyis the to11 key as a placeholder. The gateway ignores it and runs the call on the project’s configured provider credential. - BYOK: set
provider_api_keyoncreate_client(or passapi_keyper call — see below) and it becomes the provider client’s key, forwarded upstream. Whether the gateway uses it depends on the provider’s passthrough mode; otherwise the stored credential still wins.
Overrides and passthrough
Both helpers accept extra keyword arguments. The three managed fields are merged —api_key and base_url override; default_headers shallow-merges over the tenant-auth headers (caller wins) — and any other keyword passes through untouched to the provider client:
client.gateway_url (the gateway root) — an OpenAI-compatible client wants f"{client.gateway_url}/v1" — and attach turn().headers() (or gateway_auth_headers) yourself.