Skip to main content
The audio primitive gives your agent ears and a voice. One endpoint covers all three speech modalities, routed automatically across a managed catalog of speech models: You never manage a speech-provider account or key. Naive holds the credentials, picks the model, and bills each call in Naive credits. Speech-to-speech is not transcription followed by synthesis — the model listens to the audio itself, so it hears tone, hesitation, and emphasis.

CLI First

Endpoints

Routing

Every modality takes either a managed alias or an exact model slug. Managed routes enable automatic fallbacks; a pinned model does not retry elsewhere unless you opt in with provider.allow_fallbacks. Responses carry a route object explaining what was considered, filtered, and attempted:

Route by language

Set language and leave model unset. The request goes to the best model for that language, and you never name a model yourself. Always send language when you know it — it skips detection (lower latency, better accuracy). Use a BCP-47-style code (de, es, pt-BR); a region tag with no dedicated model falls back to its base language.

Steering speech synthesis

With model: "tts/auto" and voice: "auto" you can name the capability that matters and let Naive rank models for it. Omit feature and it is inferred from your text, instructions, language, and length. Speech-to-speech has its own set: Emotion Understanding, Emotion Alignment, Expressive Robustness, Voice naturalness, and Problem redirecting. feature values are case-sensitive, and valid only on tts/auto / s2s/auto with voice: "auto"; sending one with a pinned model is rejected.

Constraining the route

The optional provider object narrows and orders candidates for a single request:
Residency: requests default to provider.region: ["us", "global"]; setting provider.region yourself replaces that default entirely. Speech-to-speech rejects the whole provider object, so the residency floor does not apply to POST /v1/audio/speech-to-speechs2s/auto may pick models served from ap-southeast-1 or cn-beijing. Pin an exact model slug when you need a residency guarantee on an audio turn.

Transcription

Response:

Key parameters

Multipart requests take the same fields as form values (provider, metadata, options, and keyterms as JSON-encoded strings). Upload limits differ by transport: multipart accepts up to 100 MB; the base64 JSON body caps at ~18 MB of source audio (25 MB request limit). The SDK and CLI use the JSON transport, so upload larger recordings via multipart or downsample first.

Long recordings

Add ?async=true to queue the job. You get a 202 with a request id instead of holding the connection open:
Status moves through queuedrunningsucceeded (or failed / canceled). Result fields stay null until it succeeds, and the credit charge lands on the first poll that sees succeeded — polling again never double-charges.
Do not set retention: "none" on an async transcription — the job completes as succeeded with text: null: you are billed and the transcript is gone. Async requests default to retention: "transcript", sync to "none"; an explicit value always wins.

Speech synthesis

The response is binary audio in the requested response_format, streamed straight through.
The upstream request id is returned on the X-Audio-Request-Id header — use it with GET /v1/audio/requests/{id} (route trace) or GET /v1/audio/usage/{id} (cost), since a binary body carries no usage object. Supported formats vary by model; check GET /v1/audio/endpoints for a model’s limits.formats before pinning one.

Audio conversations

Send one spoken turn and get a spoken reply, plus both transcripts.
Response:

Catalog & observability

GET /v1/audio/endpoints is the detailed view: per-endpoint capability flags (diarization, word_timestamps, stream, redaction, translation, …), price unit and rate, accepted formats, and byte/duration limits. Use it when you need to pin a model and want to check it can actually do the job first.

Multi-tenant

Like every primitive, the routes are AccountKit-gated and available per-user:
audio is enabled by default and sends tenant voice to a per-request selection of 30+ speech providers. There is no consent gate in front of it: audio is not one of the opt-in primitives (those are payments, brain and people), so a kit that has never mentioned audio — including every older kit with no audio entry — can call these routes.To stop that, set primitives_config.audio.enabled = false on the Account Kit; the routes then return 403 forbidden with reason primitive_disabled_by_kit. An explicit false is the only thing that closes them, and subprocessor_consent_required is never the reason for audio. See Account Kits.

Billing

Naive bills the exact cost each request reports, times a small markup, converted to credits ($0.05 = 1 credit) — the same model as LLM, with no per-model rate table to keep in sync. Catalog, usage, and route-trace reads are free. Async transcriptions are charged once, when the job completes. Very short calls can round below credit precision and cost nothing at all. See Credits.

Agent tools

The audio primitive is part of agentTools(). The model can call naive_run_primitive(primitive: "audio", method: "transcribe" | "transcription" | "converse" | "models", arguments: { ... }). Synthesis is intentionally not exposed as an agent tool: it returns raw audio bytes, which have no useful representation in a model’s context. Call POST /v1/audio/speech (or naive.audio.speech()) directly and write the bytes to a file or a signed URL.

Error Handling