Server Config
The NeMo Labs Voice Agent server is driven entirely by one YAML file. This page walks through the
top-level blocks of examples/generic_voice_agent/server/server_configs/default.yaml and names the
builder that consumes each one.
How the File Is Loaded
ConfigManager (nemo_voice_agent/utils/config_manager.py) loads the top-level YAML, then for the
stt, llm, and tts blocks merges in a model-specific sub-config. examples/generic_voice_agent/server/server.py
passes server_base_path=os.path.dirname(__file__) and reads the config path from the
SERVER_CONFIG_PATH environment variable, defaulting to <server dir>/server_configs/default.yaml.
Three rules govern the merge:
- The sub-config wins. For every key present in the sub-YAML,
ConfigManagerassigns it over the top-level value and logs an... is overridden from ... to ...line. Editing a key indefault.yamlthat the sub-YAML also sets has no effect. - Only the basename of
model_configmatters. The directory is fixed per component:server_configs/stt_configs/,server_configs/llm_configs/,server_configs/tts_configs/. - Interpolation in the top-level file is resolved eagerly at load (
OmegaConf.to_container(..., resolve=True)), while sub-config values are copied over unresolved and resolved lazily against the merged config. That is hownemotron_nano_v3.yamlcan writetemperature: ${llm.temperature}— it resolves to thetemperature: 0.6the same sub-config contributed, sincedefault.yamldefines nollm.temperatureat all.
If a component omits model_config and server.use_model_registry is true, the model name is looked
up in model_registry.yaml instead. Refer to Model Registry.
server
The server block controls model-registry resolution and the connection lifecycle.
transport
Consumed by build_ws_transport and build_audio_logger. The transport is
SingleClientWebsocketServerTransport from Pipecat: while a client is connected, a second connection is
closed with code 1013 and the incumbent is kept.
vad
Consumed by build_vad_analyzer, which always constructs a SileroVADAnalyzer — VAD cannot be turned
off on this pipeline, and type: silero is descriptive only. build_vad_processor wraps the analyzer in
the processor placed right after transport.input().
All four are read as direct attributes and passed to Pipecat’s VADParams, so all four must be present.
stt
Consumed by build_stt using get_stt_service_from_config. type accepts nemo or nvidia. Any other
value raises. For details, refer to ASR.
For type: nvidia, the relevant keys are language, model, and function_id — the model name and
function id address one specific NVCF deployment and must be changed together. NVIDIA_API_KEY from the
environment takes precedence over any api_key in YAML.
diar
Consumed by build_diar, which returns None when enabled is false, so the diarization stage drops
out of the pipeline entirely. Refer to
Diarization.
Two keys in the shipped file are inert: diar.device is not read — build_diar runs the diarizer on
stt.device — and diar.type has no consumer.
turn_taking
Consumed by build_turn_taking, which returns None when enabled is false (the key is absent from
default.yaml and defaults to true). Whether this service exists also decides who emits user-turn
frames. With turn-taking on, build_context_and_aggregators selects ExternalUserTurnStrategies.
With it off, the aggregator drives turns from VAD. Refer to
Turn Taking.
llm
Consumed by build_llm using get_llm_service_from_config, and by build_context_and_aggregators for the
system message. Refer to Large Language Model Backends.
Backend-specific keys arrive from the sub-config. nemotron_nano_v3.yaml adds system_role,
system_prompt_suffix, enable_tool_calling, inject_dummy_user_message, sampling knobs
(temperature, top_k, top_p, min_p, max_new_tokens), the vLLM endpoint (api_key, base_url),
start_vllm_on_init, vllm_server_params, and the vllm_generation_params block sent to the OpenAI
API. Because start_vllm_on_init is false, python server.py does not work by itself. Start vLLM first
with the flags from vllm_server_params:
Setting llm.is_omni_model inserts a UserAudioBuffer before the user aggregator, which reads the
pre_cache_duration_secs, use_stt_transcript, keep_only_last_audio_turn, text_prompt_for_audio,
and text_prompt_for_transcript keys. Refer to
Multimodal.
tts
Consumed by build_tts (the synthesis service) and build_llm_text_processor (the upstream text
segmenter). type accepts nemo, nvidia, or nemotron. For type: nemo, the supported model values
are kokoro, fastpitch-hifigan, and magpie. Refer to
TTS.
The NIM Variant
server_configs/default_nvidia.yaml runs the same pipeline against hosted NVIDIA endpoints. The stt.type,
llm.type, and tts.type keys are all nvidia, and NVIDIA_API_KEY must be set. Both diar.enabled and
turn_taking.enabled are false, so the pipeline has no diarization stage and VAD alone drives turns. The
llm block carries base_url, system_role, system_prompt_suffix, and a
nvidia_generation_params block instead of the vLLM ones. Because none of its models appear in
model_registry.yaml and none set model_config, ConfigManager logs a not-in-registry warning per
component and every key is taken from this one file. Refer to
NVIDIA NIM.
Next Steps
Continue with the guide for the component or behavior you need to refine:
- Model Registry — how a model name resolves to a sub-config.
- Prompts — system prompt files and suffixes.
- Config Schema — full key reference.
- Builders — the functions that turn each block into a pipeline stage.