Music Router routed_model: log which engine made each track
With sume/music-auto, job.request.routed_model names the engine that ran, such as lyria-3.5. Why to store it per track and how to read it from a job.

When you send model: sume/music-auto or omit model, the Music Router picks the engine, and job.request.routed_model tells you which one ran, for example lyria-3.5 today (read 2026-10-03). Store that field next to every track you keep, because job.model only echoes what you requested, and sume/music-auto stays sume/music-auto whatever engine answered.
The docs say this holds on both the router and the older Music 1.0 routes, which now resolve through the router as well. If you ever have to explain why two tracks sound different, or reproduce one, routed_model is the field that answers it.
What each field means
The Music Router docs list the routable ids: sume/music-auto (the default), lyria-3.5 and lyria-3-pro. Unknown ids fail with 400 model_not_found and a catalog_url, and the catalog is at GET /v1/music-router/models. Every router model charges the same fixed Music price per audio generation, with the catalog showing the provider list price for reference.
So the choice between auto and a pinned id is not about cost. It is about control: auto lets Sume change the engine as the catalog evolves, pinning keeps the engine fixed.
| Request | Behavior | What you read back |
|---|---|---|
| sume/music-auto | Sume picks; Lyria 3.5 today | job.model = sume/music-auto; routed_model names engine |
| lyria-3.5 | Pinned engine | routed_model = lyria-3.5 |
| lyria-3-pro | Pinned engine | routed_model = lyria-3-pro |
| sume/music-1.0 | Retiring route | Still resolves through the router |
Read it from the job
After the job completes, fetch it and take the field from the request block. The exact envelope is in the live OpenAPI; the sketch below reads the field defensively, because a missing field should be logged rather than crash your pipeline.
import asyncio
def routed_engine(job: dict) -> str:
request = job.get("request") or {}
return request.get("routed_model") or "unknown"
async def main() -> None:
sample = {"model": "sume/music-auto", "request": {"routed_model": "lyria-3.5"}}
print(routed_engine(sample), routed_engine({}))
asyncio.run(main())
When to pin
Keep the track, prompt, job id and routed model together in one record. Three months later, that record is the difference between 'make another one like that' and guessing.
- A client deliverable that must stay consistent across a series: pin one id.
- An A/B test of engines: pin each arm and record
routed_modelto confirm. - General use: leave it on auto and log what ran.
- Migration from Music 1.0: switch the route to the router and keep your prompts; the price is unchanged.
A small record format
One line per track is enough. Keep the job id, the prompt text, the requested model, the routed_model, the date and a verdict such as kept or rejected. When Sume adds an engine to the catalog, you can filter your records by routed_model and see whether new-engine tracks are kept more often. That is far better evidence than a single listening session.
The catalog itself can change, so fetch GET /v1/music-router/models when you start a project and save the list with your records. The docs say each entry shows the provider list price for reference, and the price you pay is the fixed Music price, which is $0.125 per accepted generation (read 2026-10-03).
What `routed_model` does not tell you
It names the engine, not the quality of a specific track and not the seed, since Sume Music offers no seed or temperature parameter. Two requests with the same prompt can sound different even on the same engine. If you need the same track again, keep the audio file and its job id rather than expecting to regenerate it, and read the result's artifact URL from the completed job.
Migration note
Music 1.0 is retiring gradually. Its routes keep working and keep job.model = sume/music-1.0, but every request now resolves through the router. If your logs only show sume/music-1.0, add routed_model to them now; it is the only field that tells you which engine produced the audio.
Sources
Related posts
More in Models
- Nano Banana Pro interleaved text and images vs Sume image output
Google documents Nano Banana Pro returning text blocks with illustrations in one answer. Sume's Image API documents image results only; here is the workaround.
- OmniVoice: 600+ languages, CC-BY-NC weights, hosted TTS instead
OmniVoice covers 600+ languages in a 0.6B model, but its weights are CC-BY-NC. What the card says, what it omits, and where a hosted TTS job fits.
- Pick an ElevenLabs model by language count: 90+, 70+, 32, 29
ElevenLabs lists 90+ languages for v4, 70+ for v3, 32 for Flash v2.5, 29 for Multilingual v2 and English only for Flash v2. Where Sume Sonic fits.
- Pocket TTS languages: six or seven, and Sume's language field
Kyutai lists six Pocket TTS languages on its model card and blog, seven in the GitHub README. Here is how to read that, and how Sume TTS sets a language.
Written by Sume