Tazo Python SDK
Typed, synchronous and asynchronous clients for Tazo audio decisions. Supports exactly four public operations: uploaded decisions, streaming decisions, model discovery, and health. API-key management and internal APIs are outside this package.
Install
Python 3.11 or newer is required. Install tazo-sdk from PyPI:
python -m pip install tazo-sdk
export TAZO_API_KEY='your-key'
Sign in to the Tazo console, open API keys, and
create a key. Set TAZO_API_KEY to the complete key, including its tazo_sk_
prefix. The SDK reads this environment variable or accepts Tazo(api_key="...").
See the Python SDK documentation
for installation, examples, and API reference.
Uploaded decision
from pathlib import Path
from tazo import Tazo
questions = {
"action": {
"type": "choice",
"instructions": "Which action should be taken?",
"criteria": {
"get_weather": "Get weather for a city.",
"NO_TOOL": "No tool is needed.",
},
}
}
with Tazo() as client:
result = client.decisions.create(
audio=Path("request.wav"),
state="Choose the action matching the spoken request.",
questions=questions,
)
print(result.answers["action"])
print(result.request_id, result.idempotency_key)
model defaults to tazo-large. Choice and noul dictionaries or the optional
ChoiceQuestion / NoulQuestion models are accepted. Check models.list() for
model-specific capabilities. Score questions aren't supported by this SDK release.
Audio can be a path, bytes, or a binary stream. For bytes, pass filename and
content_type when known. Uploads are snapshotted once, up to 16 MiB, so retries
use the same bytes and MIME type. Caller-provided streams aren't closed;
seekable streams are restored to their initial position. Nonseekable streams are
consumed once. No prompt word limit is imposed by the SDK.
Models and health
from tazo import Tazo
with Tazo() as client:
print(client.health.check().status) # ok or unavailable; no auth sent
for model in client.models.list().models:
print(model.id, model.ready, model.capabilities.question_types)
Credentials are required only for protected calls. HTTP 503 with the documented
unavailable health body returns HealthStatus(status="unavailable").
Async
import asyncio
from tazo import AsyncTazo
async def main():
async with AsyncTazo() as client:
print((await client.models.list()).models)
asyncio.run(main())
Await decisions.create, models.list, and health.check. Async streaming is an
async context manager, not an awaitable factory.
Streaming
Both clients expose decisions.stream(state=..., questions=...). Entering the
context authenticates in session.start and waits for session.ready. Inspect
session.ready for limits. Send raw mono 16 kHz PCM16 little-endian bytes, at most
max_audio_message_bytes per message. The wav_chunks helper strips WAV headers
and validates the format; it does not resample or pace audio.
Send audio in one task while another consumes events:
import asyncio
from tazo import AsyncTazo, wav_chunks
async def stream_recording(questions):
async with AsyncTazo() as client:
async with client.decisions.stream(
state="Choose an action.", questions=questions, audio_scope="turn"
) as session:
async def send():
for chunk in wav_chunks("request.wav"):
await asyncio.sleep(len(chunk) / 32000) # microphone pacing
await session.send_audio(chunk)
await session.commit()
async def receive():
async for event in session:
if event.type in {"decision.updated", "decision.finalized"}:
print(event.model_dump())
if event.type == "decision.finalized":
await session.finish()
async with asyncio.TaskGroup() as group:
group.create_task(send())
group.create_task(receive())
The executable examples/stream.py also propagates producer failures immediately.
For synchronous streaming, use a sender thread and iterate the session in the
receiving thread. Never receive concurrently from multiple tasks or threads.
commit() sends a control message; consume decision.finalized before another
turn. update(state=..., questions=...) is allowed between turns; consume
session.updated before audio. finish() requests finalization and closure;
continue iterating through session.closed. Context exit closes immediately.
Fatal server errors raise StreamingError; recoverable errors are ErrorEvents.
Future event types become UnknownEvent, preserving their fields.
Default audio_scope="turn" evaluates cumulative audio. chunk evaluates only
new audio; its final result covers the last window, not the whole turn. Each
evaluation counts against the account's per-model limits. Long recordings must
be divided into turns within the server's advertised duration. There is no
automatic reconnect, audio replay, silence detection, or microphone dependency.
Retries and errors
Each decisions.create() call generates a UUID operation key, unless you supply
idempotency_key. All automatic attempts reuse the key, JSON, and audio. A new
method call creates a new operation unless you explicitly reuse a retained key.
Use a caller-generated key if you need recovery across process crashes or async
cancellation. Accepted durable work can continue after a disconnect.
from pathlib import Path
from uuid import uuid4
from tazo import DecisionPendingError, Tazo
key = str(uuid4()) # persist alongside your original request before submission
with Tazo() as client:
try:
result = client.decisions.create(
audio=Path("request.wav"),
state="Choose an action.",
questions=questions,
idempotency_key=key,
)
except DecisionPendingError as error:
print(error.request_id, error.idempotency_key)
# Later: call create with this key and the exact same input and MIME type.
Default max_retries=2 means at most three attempts. Retryable service/network
errors use bounded exponential backoff with jitter and respect Retry-After.
Authentication, invalid input, conflicts, and oversized uploads are not retried.
decision_pending may be retried with the retained key. There is no job-status
endpoint. Recovery requires calling create again with the original input.
Exceptions expose status_code, code, request_id, idempotency_key,
retryable, and retry_after where available. Invalid server responses raise
ProtocolError. HTTP errors without JSON receive a safe generic message.
The SDK does not log request content, credentials, or audio. Don't enable wire
debug logging in applications that must keep these private.
Configuration and lifecycle
Defaults: base_url="https://api.tazolabs.com", connect timeout 5 seconds,
read timeout 65 seconds, write timeout 30 seconds, pool timeout 5 seconds, and
operation_timeout=180 seconds. Set a float or an httpx.Timeout for timeout.
The operation timeout bounds the HTTP retry budget and caps each network phase
by the remaining time. Sync calls cannot forcibly interrupt a response that keeps
delivering chunks or spans multiple phases; async HTTP additionally enforces a
hard per-attempt deadline within the remaining budget. Upload snapshotting is
before this budget. Streaming has its own event_timeout (default 65 seconds),
5-second connection timeout, and 2-second close timeout. All are seconds.
Custom base_url supports local HTTP and path-prefixed proxies; omit /v1.
Use max_retries=0 with direct-inference development servers that don't persist
idempotency keys. Safe replay requires a target honoring durable idempotency.
WebSocket URLs are derived as ws/wss from that URL. Redirects aren't followed.
Clients are reusable connection pools; close them after their streaming contexts.
An injected http_client remains caller-owned. Injected clients should not have
default authorization headers if health requests must remain unauthenticated.
Development and release
From the repository root, uv sync --all-packages --all-groups prepares development.
CI uses an isolated environment and installs this package directly, preventing
backend dependencies from masking missing SDK dependencies.
uv run --package tazo-sdk --group dev pytest packages/tazo-sdk/tests
uv run --package tazo-sdk --group dev ruff check packages/tazo-sdk
uv run --package tazo-sdk --group dev mypy --config-file packages/tazo-sdk/pyproject.toml packages/tazo-sdk/src/tazo
See RELEASING.md before publishing. API v1 and SDK versions are independent. This beta may change its Python interface before 1.0; changes are recorded in CHANGELOG.md. Response fields are additive-compatible.
Metadata
Release files for tazo-sdk 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| tazo_sdk-0.1.1.tar.gz | 35.5 kB | With provenance | Details for tazo_sdk-0.1.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| tazo_sdk-0.1.1-py3-none-any.whl | Python 3 | none | any | Details for tazo_sdk-0.1.1-py3-none-any.whl |
Total release size: 61.3 kB
Release files / tazo_sdk-0.1.1.tar.gz
| Download URL | tazo_sdk-0.1.1.tar.gz |
|---|---|
| Size | 35.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
536e4aec9f77ab464a58a6c2b80f5e2cc8ef31ab7d0958b91a0e1eaf7f2f6596
|
|
BLAKE2b-256 checksum How to use checksums |
f9dcb259beba8ba03b649606e7ec099ba5e863f88ba98a11758e10dad557291f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 26, 2026.
Transparency logRelease files / tazo_sdk-0.1.1-py3-none-any.whl
| Download URL | tazo_sdk-0.1.1-py3-none-any.whl |
|---|---|
| Size | 25.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ae239618429aa2744d802e1514730b41bdc17a3c43f15fdf72660fbb7a556960
|
|
BLAKE2b-256 checksum How to use checksums |
89b6b0238c50c205cde9a440c0c489998ebc5eae98f02f0987b76ee43db5afa6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 26, 2026.
Transparency logSecurity for tazo-sdk 0.1.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for tazo_sdk-0.1.1.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 26, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.