sound Plugin
Use the FED model catalog to provide unified ASR, TTS, and automatic inbound voice transcription
sound Plugin
sound is the unified speech capability plugin. It discovers models whose FED modalities include asr or tts, then performs the actual call through City AI Service.
sound does not download or run local speech models. It has no Python, Whisper, Piper, or other local inference dependency. A local audio file is only read and converted to a data URL before it is sent to FED.
Create the plugin
import { SoundPlugin } from "@downcity/plugins";
const sound = new SoundPlugin({
list_models: async () => {
const catalog = await city.ai.listModels();
return catalog.all().filter((model) =>
model.modalities.includes("asr") || model.modalities.includes("tts")
);
},
asr: (input) => city.ai.asr(input),
tts: (input) => city.ai.tts(input),
});Actions
models
List speech-capable FED models:
plugin_call({
plugin: "sound",
action: "models",
payload: { capability: "asr" },
});capability can be asr or tts. Omit it to return models supporting either capability. Each model's modalities field states its exact capabilities.
asr
Transcribe audio with a FED ASR model:
plugin_call({
plugin: "sound",
action: "asr",
payload: {
model: "asr-model-id",
audio_path: "./input.wav",
},
});Provide one audio source:
audio_path: an absolute path or a path relative to the Agent project rooturl: a remote audio URLdata_url: audio encoded as a data URL
The result uses the serializable core fields from AI SDK TranscriptionResult:
{
text: string;
segments?: Array<{
text: string;
startSecond: number;
endSecond: number;
}>;
language?: string;
durationInSeconds?: number;
}tts
Generate speech with a FED TTS model:
plugin_call({
plugin: "sound",
action: "tts",
payload: {
model: "tts-model-id",
text: "Welcome back",
voice: "alloy",
format: "mp3",
},
});TTS returns an AI SDK UIMessage. Audio is represented by a file part, which the Agent saves to project resources and attaches to the assistant message.
Default models
Configure separate ASR and TTS defaults when needed:
new SoundPlugin({
default_asr_model: "asr-model-id",
default_tts_model: "tts-model-id",
list_models,
asr,
tts,
});If neither the action nor the plugin provides a model, the call fails with guidance to read sound.models. The plugin never picks a model implicitly.
Automatic inbound transcription
auto_asr: true transcribes inbound voice and audio chat attachments. This path cannot ask the user to choose a model, so default_asr_model is required:
new SoundPlugin({
auto_asr: true,
default_asr_model: "asr-model-id",
list_models,
asr,
tts,
});The transcript is appended to user text as <voice src="...">...</voice>. A failed attachment transcription does not block the main chat flow.
web Plugin
A detailed guide to the web built-in plugin as web methodology plus an install action for web-related skills and CLIs
workboard Plugin
A detailed guide to the workboard built-in plugin, how it exposes structured work snapshots through runtime HTTP, and why it belongs more to observability and control-plane capability