hermes-soniox
Native BYOK Soniox text-to-speech and speech-to-text for
Hermes Agent. Provider id: soniox (both TTS and STT).
It calls Soniox directly with your own SONIOX_API_KEY — no proxy, no gateway, no third-party middleman.
STT auto-detects language by default; TTS defaults to English with Adrian and can be configured for every
language and voice exposed by the selected Soniox model. The plugin uses only Hermes-bundled httpx plus the
standard library.
Install
hermes plugins install XimilalaXiang/hermes-soniox
hermes plugins enable hermes-soniox
Add your key to ~/.hermes/.env (never to config.yaml):
SONIOX_API_KEY=your-soniox-key
Data path (what leaves your machine)
| Feature | Destination | Data sent |
|---|---|---|
| TTS | POST https://tts-rt.soniox.com/tts |
reply text, model, voice, language, format, speed |
| STT | https://api.soniox.com/v1 (/files, /transcriptions) |
the audio file, optional language hints and prompt text |
The key is sent only as an Authorization: Bearer header to those two Soniox hosts. It is resolved through
Hermes' active-profile secret scope on each call, never written to config.yaml, returned, logged, or included
in error messages. This keeps credentials isolated when one gateway serves multiple Hermes profiles.
After each transcription the plugin deletes the remote transcription and the uploaded file (best effort).
Soniox's own retention and billing terms apply to anything you send.
Configuration
tts:
provider: soniox
model: tts-rt-v2 # optional; non-"tts-*" values are ignored
voice: Adrian # optional; any voice id from GET /v1/tts-models
soniox:
language: en # optional, default en
stt:
enabled: true
provider: soniox
soniox:
model: stt-async-v5 # optional
# language: en # optional hint; omit for automatic language detection
Defaults: TTS model tts-rt-v2, language en, voice Adrian; STT model stt-async-v5 with automatic
language detection. Nothing restricts the plugin to English: set any model-supported language and voice.
Chinese preset
tts:
provider: soniox
model: tts-rt-v2
voice: Meilin
soniox:
language: zh
stt:
enabled: true
provider: soniox
soniox:
model: stt-async-v5
language: zh
How Hermes passes settings (verified against Hermes v0.22.4): TTS receives tts.voice, tts.model,
tts.speed and tts.output_format from the dispatcher; tts.soniox.language is read by the plugin itself.
STT receives stt.soniox.model; its optional language hint resolves in this order:
stt.soniox.language → stt.language → legacy HERMES_LOCAL_STT_LANGUAGE → no hint. With no resolved hint,
Soniox detects the language. stt.prompt is sent as context.text.
- Languages: BCP-47 values are reduced to the ISO code (
zh-CN→zh). STT accepts a comma-separated list (zh,en) which is sent aslanguage_hints; hints bias recognition, they do not restrict it. - Voices: Soniox built-in voice names or a cloned voice id. The plugin's catalog is a short static list;
the authenticated
GET https://api.soniox.com/v1/tts-modelscatalog confirms thattts-rt-v2supportsMeilinand Chinese (zh). Any voice can speak any language supported by the model.tts.voice/tts.modelare shared Hermes keys; a stale value from another provider (a non-tts-*model is ignored, a voice is not) will be sent as-is. - Speed: Hermes allows 0.25–4.0; Soniox accepts 0.7–1.3, so values are clamped into that range.
- Formats:
mp3,wav,flacnatively;ogg/opusrequest Sonioxopus(saved as.oggif the response is an Ogg container, otherwise.opus). Unknown formats fall back tomp3. The provider opts into voice bubbles; Hermes converts to Opus with ffmpeg when needed. - Limits: TTS text ≤ 5000 characters (the Soniox limit; Hermes may apply its own cap first). STT polls with backoff
(1s → 5s) for up to 300 s until
completed/error, then fails with a timeout error. - Realtime WebSocket TTS/STT is not implemented in 0.2.0.
Testing
uv venv --python 3.14 .venv-test && uv pip install --python .venv-test/bin/python pytest ruff httpx
.venv-test/bin/python -m pytest -q
.venv-test/bin/python -m ruff check .
Tests use mocked HTTP only and need no credentials. They import Hermes' provider ABCs from
~/.hermes/hermes-agent (override with HERMES_AGENT_PATH).
For catalog admission, validate a clean tracked-files export rather than the development directory: the
recursive security scanner intentionally sees dependencies inside .venv-test as plugin content.
Troubleshooting
- "SONIOX_API_KEY is not set" — add it to
~/.hermes/.envand restart Hermes. - HTTP 401 — wrong key. HTTP 402 — Soniox balance/budget exhausted. HTTP 429 — rate/concurrency limit.
- HTTP 400 invalid_request on TTS — voice or language not valid for the model; check
/v1/tts-models. - "transcription timed out" — very long audio; retry or split the file.
- Provider not picked up —
hermes plugins list, ensure it is enabled, and thattts.provider/stt.provideris exactlysoniox.
Uninstall / rollback
hermes plugins disable hermes-soniox
hermes plugins uninstall hermes-soniox
Then set tts.provider / stt.provider back to your previous provider and remove SONIOX_API_KEY
from ~/.hermes/.env if you no longer need it.
License
MIT