Python SDK for the to11.ai platform
Project description
to11ai-sdk
Python SDK for to11.ai — the AI engineering platform for prompt management, tracing, and evals.
Use it to fetch managed prompts at runtime, wire your provider client (OpenAI, Anthropic, …) to the to11 gateway with the right auth/trace headers, and group model calls into sessions, conversations, and turns for tracing. Synchronous, snake_case, Python 3.10+. Only runtime dependency: Pydantic.
Installation
pip install to11ai-sdk
# or: uv add to11ai-sdk · poetry add to11ai-sdk
The SDK's only runtime dependency is Pydantic. The provider client libraries used in the examples below (openai, anthropic) are not dependencies — install whichever you use yourself, e.g. pip install openai.
Quick start
Create a client, fetch a prompt for the current environment, and send it through the gateway with your normal provider client:
import os
from to11ai_sdk import create_client
from openai import OpenAI
to11 = create_client(
# Each also resolves from an env var, so on a server you can pass nothing:
base_url=os.environ.get("TO11_API_URL"), # -> https://api.to11.ai
api_key=os.environ.get("TO11_API_KEY"), # -> TO11_API_KEY
project_id=os.environ.get("TO11_PROJECT_ID"), # -> TO11_PROJECT_ID
env=os.environ.get("TO11_ENV"), # "prod", "staging", … -> TO11_ENV
)
# Fetch a released prompt for the client's project + environment, shaped for OpenAI.
prompt = to11.prompts.render("welcome-message", variables={"name": "Ada"}, format="openai")
# Point your provider client at the gateway and send it.
openai = OpenAI(**to11.openai_options())
completion = openai.chat.completions.create(
**prompt["config"],
messages=prompt["messages"],
extra_headers=to11.turn().headers(prompt), # auth + trace id + prompt provenance
)
prompt["config"] carries the model parameters, prompt["messages"] the rendered messages, and turn().headers(prompt) the headers that authenticate the gateway call and record which prompt produced the trace.
Configuring the client
create_client(...) takes keyword-only args. Each URL/credential resolves option → environment variable → built-in default, so a server app can construct it from the environment alone:
| Argument | Resolves from | Default |
|---|---|---|
base_url |
option → TO11_API_URL |
https://api.to11.ai |
gateway_url |
option → TO11_GATEWAY_URL |
https://gw.to11.ai |
api_key |
option → TO11_API_KEY |
— (required) |
project_id |
option → TO11_PROJECT_ID |
— |
env |
option → TO11_ENV |
— (lowercase-kebab, 1–63 chars) |
provider_api_key |
option | — (BYOK; carried by openai_options()/anthropic_options()) |
format |
option | — ("openai" | "anthropic"; omit for the neutral result) |
on_unknown_role |
option | "drop" |
timeout_s / max_retries |
option | 30.0 / 3 |
behavior_overrides |
option | None |
The client exposes the resolved values as read-only attributes — to11.base_url, to11.gateway_url, to11.api_key, to11.project_id, and to11.env. Use the non-secret ones (base_url/gateway_url/project_id/env) for diagnostics; api_key is exposed to build manual auth headers — treat it as a secret and never log it. provider_api_key (BYOK) is deliberately not exposed back off the client.
Fetching prompts
prompts.render(slug, ...) resolves the released prompt for the client's project_id + env in one request. Set format (on the client or per call) to get a result shaped for that provider; omit it for the provider-neutral result.
prompt = to11.prompts.render(
"weather-concierge",
variables={"city": "New York", "units": "fahrenheit"},
# label=... # override the client's environment for this call
# subject=... # a stable id so a weighted release pins the same caller to a variant
# fallback=... # a previously-rendered RenderedPrompt served on a network error
# format="openai" | "anthropic"
# on_unknown_role="drop" | "warn" | "error"
)
- With
formatthe result is spread-ready:{"messages": ..., "config": ..., "metadata": ...}(config= the version's model params;metadata= prompt/version/release provenance). For Anthropic it also carries a top-level"system". - Without
formatyou get the neutralRenderedPrompt:.messages,.tools,.tool_choice,.prompt_id,.version,.version_id,.release_id,.variant_name,.content_hash,.label,.slug,.block_render_record,.model_config_(trailing underscore avoids Pydantic's reserved name).
Authored developer blocks come back as-is; the SDK maps them per provider (OpenAI keeps developer; Anthropic folds system/developer into the top-level system). on_unknown_role controls how an unrecognized role is handled during provider conversion.
Sending through the gateway
openai_options() / anthropic_options() return spread-ready kwargs (base_url, api_key, default_headers) for a provider client pointed at the gateway; default_headers carries the static tenant auth. Add turn().headers(prompt) per call for the trace id and prompt provenance:
from anthropic import Anthropic
anthropic = Anthropic(**to11.anthropic_options())
By default the gateway runs the call on the project's configured provider credential (managed). For BYOK, set provider_api_key on create_client.
Sessions, conversations & turns
Group model calls for tracing. to11.turn() uses the client's default session; create explicit ones with to11.session(id=None) / to11.conversation(id=None). turn().headers(prompt=None) emits the session/conversation ids + a fresh traceparent (plus prompt provenance when a rendered/shaped prompt is passed) — for the gateway call you make. (This is separate from the SDK's OTel-based traceparent on its own control-plane requests.)
Managing prompts, versions & labels
Beyond render(), the prompts namespace covers the control-plane lifecycle. All of these default project_id from the client — pass it per call only to override:
to11 = create_client(api_key="...", project_id="proj_abc123")
to11.prompts.list() # uses the bound project_id
to11.prompts.get(prompt_id="prompt_1")
to11.prompts.get_version(prompt_id="prompt_1", version_number=3)
to11.prompts.move_label(prompt_id="prompt_1", label="production", version_id="ver_9", reason="promote")
Full set: create, list, get, update, archive, create_version, list_versions, get_version, move_label, list_labels, and the project-label registry (list_project_labels, create_project_label, get_project_label, update_project_label, delete_project_label, list_project_label_usages, list_label_events). to11.project_environments and to11.routing_rules expose the environment and routing-rule surfaces.
update_project_label(description=None) means "leave unchanged"; pass description="" to clear it.
Error handling
To11aiError is the base; catch it broadly or match a subclass:
from to11ai_sdk import To11aiRateLimitError, PromptNotFoundError
try:
prompt = to11.prompts.render("welcome-message")
except To11aiRateLimitError as exc:
... # exc.retry_after_seconds
except PromptNotFoundError:
...
| Class | When |
|---|---|
To11aiApiError |
non-2xx API response (status_code, error_code, details) |
To11aiAuthError |
401/403 |
To11aiRateLimitError |
429 (retry_after_seconds) |
To11aiValidationError |
400 |
To11aiNetworkError |
network failure / timeout |
PromptNotFoundError · LabelNotFoundError · MissingLabelError · NoActiveReleaseError · PromptPolicyViolationError · PromptLabelNotRegisteredError |
typed prompt-resolution errors |
UnknownRoleError |
an unrecognized message role with on_unknown_role="error" |
To11aiResponseValidationError |
a 2xx body that fails schema validation |
Documentation
Full reference: https://docs.to11.ai/reference/python-sdk. Licensed under MPL-2.0.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file to11ai_sdk-2.0.0rc1.tar.gz.
File metadata
- Download URL: to11ai_sdk-2.0.0rc1.tar.gz
- Upload date:
- Size: 119.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.31 {"installer":{"name":"uv","version":"0.11.31","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1931e107a8fbb3e3df5b95d7a395e9785d46bf88787d604747dcc6ae8744b68c
|
|
| MD5 |
498c4ee2bee98c5ed000aab32c6b28f8
|
|
| BLAKE2b-256 |
7521f9a2dfa21cabe769b63213ee524abd1ecbeab2a274f58bf5dea377c0e556
|
File details
Details for the file to11ai_sdk-2.0.0rc1-py3-none-any.whl.
File metadata
- Download URL: to11ai_sdk-2.0.0rc1-py3-none-any.whl
- Upload date:
- Size: 54.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.31 {"installer":{"name":"uv","version":"0.11.31","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6697124b8035ee1a1879ad4575be4a741b585ddeb5486e782ab274971920ddfd
|
|
| MD5 |
a576ff10da286356410246dd8480dcd3
|
|
| BLAKE2b-256 |
ffc37ee1b308e599511dd3d6c705f297131c06b0f929de80470fb05e7cb495e2
|