Azure AI Services speech for Hermes Agent — gpt-4o-transcribe in, gpt-audio-1.5 out, one command each.
If you've ever pointed Hermes (or any OpenAI-SDK tool) at an Azure AI Services resource for transcription and gotten DeploymentNotFound for a model you definitely deployed — read the next section. This repo exists because of that error.
Paste this to your Hermes agent and it sets itself up:
Set up Azure voice for yourself using https://github.com/forcewake/hermes-azure-voice :
1. Copy plugins/azure-voice/ from that repo into your plugins directory and enable it
2. Check that HERMES_AZURE_OPENAI_ENDPOINT and HERMES_AZURE_OPENAI_API_KEY are set in
your env file; ask me for values if they're missing
3. Switch stt.provider to azure-gpt-transcribe and tts.provider to azure-gpt-audio
(no command blocks needed — the plugin registers both providers natively)
4. Run the round-trip verification from the repo README and show me the transcript
5. Restart the gateway only after I confirm the verification passed
Microsoft documents the deployment-path URL format for Azure OpenAI REST — that part exists in the Whisper quickstart. What no doc covers is the asymmetry on the new unified AI Services resources (*.services.ai.azure.com): chat.completions works fine through the OpenAI-compatible /openai/v1 endpoint with the plain OpenAI SDK, so you reasonably use it everywhere — and then audio.transcriptions on that same endpoint fails DeploymentNotFound for every model, deployed or not. The transcription API alone needs the deployment name in the URL path:
POST {endpoint}/openai/deployments/{deployment}/audio/transcriptions?api-version=2024-10-21
The plain OpenAI SDK puts the model in the request body and hits /audio/transcriptions directly — same client that just worked for chat. Result: every model name returns the same error:
{"error": {"code": "DeploymentNotFound",
"message": "The API deployment for this resource does not exist..."}}Facts we verified against a live resource, so you don't have to:
| Attempt | Result |
|---|---|
SDK call with model=gpt-4o-transcribe |
DeploymentNotFound |
SDK call with gpt-audio-1.5 (a deployed, working chat model) |
DeploymentNotFound — even working models fail on this path |
Path-format URL, api-version=2024-10-21 |
200 OK |
Path-format URL, 2022-12-01 / 2024-06-01 / 2023-05-15 |
API version not supported |
gpt-transcribe-2026-07-28 style dated names as deployment ids |
same rules — the deployment id is whatever you named it |
TTS is the opposite: gpt-audio-1.5 speaks happily through plain chat.completions with modalities: ["text","audio"], no path tricks needed. Chat works, speech works, transcription doesn't — same base URL, same client, same key. That asymmetry is the whole reason this repo exists as more than a config snippet.
scripts/
├── azure_gpt_audio_stt.py # gpt-4o-transcribe; correct URL built by hand,
│ # retries the propagation 409s fresh
│ # deployments throw
└── azure_gpt_audio_tts.py # gpt-audio-1.5 via chat.completions
skills/azure-voice/SKILL.md # optional: agent-facing operational notes
Both scripts are stdlib + openai + requests only, read credentials from
the environment, and fail closed with a clear message when the endpoint
variable is missing.
Option A — native plugin (recommended). No command blocks, no subprocess
per call: the plugin registers azure-gpt-transcribe (STT) and
azure-gpt-audio (TTS) as first-class providers through the plugin API.
git clone https://github.com/forcewake/hermes-azure-voice /tmp/hav
cp -r /tmp/hav/plugins/azure-voice ~/.hermes/plugins/
hermes plugins enable azure-voiceThen the entire config is two lines:
stt:
provider: azure-gpt-transcribe
tts:
provider: azure-gpt-audioOption B — command-provider scripts (no plugin). Same behavior, one subprocess per call. Useful if you avoid plugins on principle.
Fetch the two scripts into your Hermes scripts directory:
curl -fsSL https://raw.githubusercontent.com/forcewake/hermes-azure-voice/main/scripts/azure_gpt_audio_stt.py \
-o ~/.hermes/scripts/azure_gpt_audio_stt.py
curl -fsSL https://raw.githubusercontent.com/forcewake/hermes-azure-voice/main/scripts/azure_gpt_audio_tts.py \
-o ~/.hermes/scripts/azure_gpt_audio_tts.py
chmod +x ~/.hermes/scripts/azure_gpt_audio_{stt,tts}.pyOptionally, the agent-facing skill (operational notes for the bot itself):
hermes skills install forcewake/hermes-azure-voice/skills/azure-voiceThen merge the provider blocks into your Hermes gateway configuration (the two places Hermes reads STT/TTS providers from):
stt:
provider: azure-gpt-transcribe
azure-gpt-transcribe:
type: command
command: python3 ${HOME}/.hermes/scripts/azure_gpt_audio_stt.py --input {input_path} --output {output_path} --model gpt-4o-transcribe
model: gpt-4o-transcribe
timeout: 120
format: txt
tts:
provider: azure-gpt-audio
providers:
azure-gpt-audio:
type: command
command: python3 ${HOME}/.hermes/scripts/azure_gpt_audio_tts.py --input {input_path} --output {output_path}
output_format: ogg
timeout: 120
voice_compatible: trueEnvironment (in your Hermes env file):
HERMES_AZURE_OPENAI_ENDPOINT=https://YOUR-RESOURCE.services.ai.azure.com
HERMES_AZURE_OPENAI_API_KEY=<your key>
Deploy the two models on your resource with deployment ids
gpt-4o-transcribe and gpt-audio-1.5, restart the gateway, done.
echo "hello from azure" > /tmp/t.txt
python3 ~/.hermes/scripts/azure_gpt_audio_tts.py \
--input /tmp/t.txt --output /tmp/t.ogg
python3 ~/.hermes/scripts/azure_gpt_audio_stt.py \
--input /tmp/t.ogg --output /tmp/back.txt --model gpt-4o-transcribe
cat /tmp/back.txt- STT: ~0.8–0.9s for a short clip, 24kHz Ogg/Opus in, plain text out. Handles Russian, English and Arabic in daily use.
- TTS: ~3s for a sentence.
gpt-audio-1.5is a conversational audio model — it paraphrases rather than reading verbatim ("Got it, here's your phrase…"). Ideal for voice-chat replies; if you need literal TTS, point the TTS block at a literal provider instead. - Fresh deployments throw intermittent
DeploymentNotFoundfor ~30–60 minutes while front-ends propagate. The STT script retries through that window instead of failing the voice message.
A terminal round trip — text in, spoken audio out, transcription back (real Azure calls, idle time compressed):
Video (Reddit/X-friendly): MP4 · raw cast: roundtrip.cast
- Hermes Agent v0.19+ (command STT/TTS providers)
- Azure AI Services resource (the
services.ai.azure.comkind) with the two model deployments - Python with
openaiandrequests
MIT