AgileTTS
The sovereign voice of the Agile suite: text → audio in Italian, voice cloning with tracked consent. Data never leaves the European Union; no external provider speaks on our behalf without saying so.
OpenAI-compatible APIkeys per product and tenantstreamingusage metering
Who it is for
AgileTTS speaks on a product's behalf whenever a natural Italian voice is needed and the data cannot leave the European Union:
- Switchboards and phone answering — telephony format and
stream: true: the first chunk of audio leaves while the sentence is still being synthesized. - Avatars and talking video — an audio track to sync with the lips, same engine and same voices as the phone.
- Courses, e-learning, voice notifications — long texts read whole, split on the pauses and stitched back by the service.
- Accessibility and document reading — correct Italian for amounts, dates, acronyms, POD and IBAN codes.
If you need to integrate, start from the API documentation; if you need to evaluate the service, start from the plans below.
Plans and licences
One licence per company: the licence holds the keys (one per product), the scopes they may use, and the agreed quota and rate. Prices are set by Agile Software case by case — this page publishes no figures.
| Plan | Scopes | Monthly quota of characters | Limit per minute | Duration | Price |
|---|---|---|---|---|---|
prova (trial) | speech, stream, voices with low ceilings | reduced, enough to evaluate | reduced | mandatory expiry: after it, the key answers 403 KEY_EXPIRED | on request |
standard | speech, stream, voices; one key per product, rotation and revocation | agreed in the company plan | agreed in the company plan | agreed, renewable | on request |
enterprise | as standard, plus the company console, its users and the audit of operations | agreed, with this month's consumption in the console | agreed per company, not per single key | agreed, renewable | on request |
Quota and rate are the two ceilings of the company plan: the regia writes them, the company administrator reads them together with this month's consumption, and they are the very same number the service refuses on (429 QUOTA_EXCEEDED, 429 RATE_LIMIT). A refusal stays a refusal: no silent fallback to third parties.
Request a licence
The form reaches the regia — the control room of Agile Software — which answers with the plan, the ceilings and the key. No credit card and no self-activation: a licence is issued by a person.
How long we keep this data: a request notified to the regia is deleted 180 days after the notice, the fact of a request refused by the honeypot field 30 days after it, and a request not yet notified is never deleted — the round on the box counts and logs every deletion, without the email.
Service status
reading…
This page reads GET /health of the front end from your own browser, with no libraries and no intermediary: if the service does not answer it says so, and shows nothing made up. A 503 is an answer, not a hole: during a redeploy the front end declares the shutdown and says when to retry.
Why us
The market reference for AgileTTS is ElevenLabs, which is also what the products use today. Our numbers below are measurements taken in the repository, each with the file that produced it and its date; the leader's column is a measurement pending the vault key: our own scoped copy (agiletts__elevenlabs__api_key) has been blocked since 21/9 and the box has no tool to read it, so the elevenlabs arm of the bench has never run. A number that has not been measured does not get written.
| What is compared | AgileTTS — measurement and source | ElevenLabs |
|---|---|---|
| Italian pronunciation (amounts, dates, acronyms, POD, IBAN) | 241 cases out of 241, 0 errors — banco/lessico/verifica_lessico.py --autoprova, measured 30/9/2026 | measurement pending the vault key |
| The service does not alter the engine's audio | the same bytes as the engine, in block and in streaming; the service's overhead is 10.7 ms p50 in block and 3.2 ms in streaming — banco/tts/prova_parita_fronte_motore.py (36/36), measured 29/9/2026 | measurement pending the vault key |
| An honest refusal when the queue is full | the 503 arrives before the first byte, with Retry-After: 0 truncated streams and 0 errors over 40 runs — banco/tts/prova_carico_fronte.py §F, measured 29/9/2026 | measurement pending the vault key |
| A restart does not throw away whoever is speaking | 3 phone calls out of 3 get their audio (they were 0 out of 3), address silent for 0.25 s — banco/tts/capienza_chiusura.py, measured 30/9/2026 in docs/NOVITA.md | measurement pending the vault key |
| Spoken texts are left nowhere | 0 traces across 9 files of the front end's disk, 26 paths probed with 12 needles (the journal included) — fronte/prova_ritenzione.py, measured 29/9/2026 | measurement pending the vault key |
| Three conversations at once above real time | not yet: on the real engine the real-time factor is 1.41 with one conversation and 2.83 with three — docs/OBIETTIVI.md obj. 3, measured 21/9/2026. The goal is open and the number is written where it can be seen | measurement pending the vault key |
The differences that need no bench — they are verified by reading the repository, not by talking:
- Sovereignty: Qwen3-TTS engine (Apache-2.0) on Agile Software's own hardware in the EU; texts and audio never leave the European Union.
- No silent fallback: when the engine is not there you get an honest error, not a non-EU provider speaking in our place; the
X-AgileTTS-Viaheader always says who spoke. - Tracked consent: every voice carries its provenance, its scope of use and the expiry of the consent, with the catalog audit (
banco/catalogo/audit_catalogo.py); in the public catalog, synthetic voices only. - Usage metered, texts never: requests, characters, milliseconds and audio produced are counted — the text never enters the logs.
How to use it
Endpoint https://api.agiletts.agile.software. Key in the Authorization: Bearer ats_… header (or X-Api-Key). The body is that of OpenAI's /v1/audio/speech.
curl https://api.agiletts.agile.software/v1/audio/speech \
-H "Authorization: Bearer $AGILETTS_KEY" -H "Content-Type: application/json" \
-d '{"model":"agiletts","input":"Buongiorno, come posso aiutarla?","voice":"serena","response_format":"wav"}' \
-o saluto.wav
With the official OpenAI client you just change base_url and the key:
from openai import OpenAI
client = OpenAI(base_url="https://api.agiletts.agile.software/v1", api_key=AGILETTS_KEY)
with client.audio.speech.with_streaming_response.create(model="agiletts", voice="serena",
input="Il corso dura sei mesi.", response_format="pcm") as r:
r.stream_to_file("frase.pcm") # pcm = 24 kHz, 16 bit, mono
Endpoints
| Method and path | What it does |
|---|---|
POST /v1/audio/speech | model = agiletts, input (≤ 2000 characters), voice, response_format = wav | pcm (24 kHz) | pcm16k (telephony) | mp3, speed 0.5–2.0, stream: true to receive the audio in chunks while it is synthesized (pcm/pcm16k only) |
GET /v1/models | the available models |
GET /v1/voices | the voices the key can use (id, language, rate) |
GET /v1/usage | your key's usage: requests, characters, milliseconds, audio produced — never the texts |
GET /health | state of the front end and the engine |
Errors
| HTTP | code | meaning |
|---|---|---|
| 401 | KEY_MISSING, KEY_INVALID | key missing or unknown |
| 403 | KEY_REVOKED, SCOPE_NOT_ALLOWED | key revoked or without the permission (speech, stream, voices) |
| 404 | UNKNOWN_VOICE, UNKNOWN_MODEL | voice or model that does not exist |
| 413 | TEXT_TOO_LONG | over 2000 characters |
| 429 | RATE_LIMIT, QUOTA_EXCEEDED | too many requests per minute or monthly character quota exhausted |
| 503 | BUSY, ENGINE_DOWN | engine busy or unavailable: Retry-After says when to retry. No silent fallback to third parties. |
Rules
- Sovereignty: Qwen3-TTS engine (Apache-2.0) on our own hardware in the EU. The
X-AgileTTS-Viaheader always says who spoke. - Consent: every voice has a provenance (person with consent, synthetic or blend), a scope of use and the reference encrypted at rest. In the public catalog, synthetic voices only.
- Privacy: texts are never logged; only requests, characters and times are counted.
For integrators
To move a product onto the front end — one at a time, on the owner's "go" and with the rollback ready — the step-by-step guide is in docs/ADOZIONE.md. For those who prefer the command line there is client/agiletts-cli.py, the pure standard-library client: synthesis to a file, reading models, voices and your key's usage.