Audio Services
Audio Services let a deployed agent generate spoken audio, create sound effects, and discover available voices. Agent steps call the typed ctx.sapiom.speech capability; Sapiom supplies the authenticated cloud connection when the deployed agent runs.
Choose the audio operation
Section titled “Choose the audio operation”| What the agent needs | Recommended operation |
|---|---|
| Spoken narration, an alert, or a voiceover | speech.textToSpeech.create(...) |
| A non-verbal sound described in words | speech.soundEffects.create(...) |
| The voices available at runtime | speech.voices.list() |
| Audio that must survive its hosted URL | Pass storage and retain the returned fileId |
Do not copy a fixed voice inventory into the agent. List voices when selecting or validating a voice, then store the chosen voice name or ID as configuration.
Generate speech
Section titled “Generate speech”const audio = await ctx.sapiom.speech.textToSpeech.create({ text: input.announcement, voice: input.voice, storage: { visibility: "private" },});
if (audio.storageError) { throw new Error(`Audio persistence failed: ${audio.storageError}`);}
if (!audio.fileId && !audio.url) { throw new Error("Speech generation returned no audio reference");}
return { fileId: audio.fileId ?? null, temporaryUrl: audio.url ?? null,};text must be a non-empty string. voice accepts a voice name or ID; omit it to use the SDK’s default. The hosted url can expire, so prefer fileId whenever the output must be used by a later run or external recipient.
Generate a sound effect
Section titled “Generate a sound effect”const effect = await ctx.sapiom.speech.soundEffects.create({ text: "A short wooden door knock in a quiet room", durationSeconds: 2, storage: { visibility: "private" },});
return { fileId: effect.fileId ?? null, temporaryUrl: effect.url ?? null, storageError: effect.storageError ?? null,};Use durationSeconds only when the effect needs a particular length. Text-to-speech and sound effects have separate inputs even though both return the same SpeechResult shape.
Discover voices
Section titled “Discover voices”const { voices } = await ctx.sapiom.speech.voices.list();
return voices.map(({ voiceId, name }) => ({ voiceId, name: name ?? null,}));Treat voiceId as the stable selection value when one is presented. A voice name is optional, and the available set can change.
Test the behavior locally
Section titled “Test the behavior locally”Local Run replaces ctx.sapiom.speech calls with deterministic URLs and does not generate or store audio. Override the exact path when a step requires persistence or branches on an error:
{ "version": 1, "steps": { "make-announcement": { "speech.textToSpeech.create": { "url": "https://fixtures.example/announcement.mp3", "expiresAt": "2099-01-01T00:00:00.000Z", "fileId": "file-audio-local" } } }}Sound-effect and voice-list overrides use speech.soundEffects.create and speech.voices.list. Supply every field the step consumes, assert the terminal output, and require both unusedStubs and stubWarnings to be empty. A passing Local Run does not prove live voice availability, pronunciation, audio quality, storage, or runtime usage.
Manage usage and retention
Section titled “Manage usage and retention”Generate only the duration the task needs. Retain fileId for durable use, mint fresh private download URLs when needed, and use public visibility only for assets intentionally available without tenant authentication.
Use the signed-in capability catalog for current availability, limits, and pricing. Voice listing is runtime discovery; generation usage depends on the operation and output.
© 2026 Sapiom, Inc.