Skip to content

Repository files navigation

Hermes Azure Voice

CI License: MIT

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.

The one-command install: tell your Hermes to do it

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

The gotcha the docs don't spell out

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.

What's inside

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.

Install

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-voice

Then the entire config is two lines:

stt:
  provider: azure-gpt-transcribe
tts:
  provider: azure-gpt-audio

Option 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}.py

Optionally, the agent-facing skill (operational notes for the bot itself):

hermes skills install forcewake/hermes-azure-voice/skills/azure-voice

Then 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: true

Environment (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.

Verify without touching Telegram

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

Behavior notes (measured, not marketed)

  • 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.5 is 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 DeploymentNotFound for ~30–60 minutes while front-ends propagate. The STT script retries through that window instead of failing the voice message.

Demo

A terminal round trip — text in, spoken audio out, transcription back (real Azure calls, idle time compressed):

azure voice round trip

Video (Reddit/X-friendly): MP4 · raw cast: roundtrip.cast

Requirements

  • Hermes Agent v0.19+ (command STT/TTS providers)
  • Azure AI Services resource (the services.ai.azure.com kind) with the two model deployments
  • Python with openai and requests

License

MIT

About

Azure AI Services speech for Hermes Agent: gpt-4o-transcribe STT + gpt-audio-1.5 TTS as command providers. Ships the URL-path fix for the DeploymentNotFound error that breaks every OpenAI-SDK tool on services.ai.azure.com resources.

Topics

Resources

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages