# ADR-0021: musicgen interface (blocking Generate over an async job queue) Status: Accepted (2026-07-12) ## Context The llama-swap host gained ACE-Step 1.5 (full songs with vocals, seconds per clip warm on the reference GPU). Its API is an async job queue — `POST /release_task` → poll `POST /query_result` → `GET` the result file — unlike every other majordomo media backend, which is one blocking call. ## Decision - New `musicgen` leaf package, ADR-0016→0020 conventions: `Request{Prompt, Lyrics, DurationSeconds, Format, Steps, Seed}`, `Result{Audio{Data, MIME}, Raw}`, functional options, zero value = backend default, bytes-only. - **`Model.Generate` blocks, polling internally** (2s interval, ctx-bounded). The one-call contract is the package's value: callers budget the whole job with a context deadline exactly like imagegen/videogen, and the async mechanics stay a provider detail. An async job surface (mirroring the deliberately-deferred videogen one, ADR-0019) can come later if a caller ever needs progress. - provider/llamaswap reaches ACE-Step through the `/upstream//` passthrough (ADR-0020). Envelope parsing is tolerant (`data` wrapper or bare array; `result` arrives as a double-encoded JSON string) and the result-file URL is routed back through the same upstream. `audio_duration` is the v1 param name — an unknown field degrades to default clip length upstream, never an error; verify at smoke. ## Consequences - Music jobs occupy the exclusive GPU group like video; callers own the timeout budget (mort keeps the tool timeout under its agent ceiling). - The double-encoded `result` string and envelope shapes are pinned by the netherstorm image build; host smoke tests are the drift defence.