Agent Reach Transcribe Command: Groq Whisper to OpenAI Whisper Fallback Logic Explained
The transcribe command in Agent Reach attempts audio transcription through Groq's Whisper API first and silently falls back to OpenAI's Whisper API only if Groq fails, exhausting every configured provider in order before raising an aggregated TranscribeError.
The transcribe command in the open-source Agent Reach project provides a robust audio-to-text pipeline that prefers Groq's free-tier Whisper endpoint and degrades gracefully to OpenAI's Whisper when needed. Implemented primarily in agent_reach/transcribe.py, the transcription logic handles provider selection, audio preprocessing, and automatic fallback orchestration without requiring manual user intervention. This article breaks down the exact fallback chain between Groq Whisper and OpenAI Whisper as implemented in the Panniantong/Agent-Reach repository.
Provider Configuration and Fallback Order
The Provider Definition Table
In agent_reach/transcribe.py, the PROVIDERS dictionary (lines 30-41) maps logical names to concrete API details. For Groq, it points to https://api.groq.com/openai/v1/audio/transcriptions and specifies the model whisper-large-v3. For OpenAI, it points to https://api.openai.com/v1/audio/transcriptions with model whisper-1. Each entry also declares the configuration key that holds the respective API token, ensuring secrets are injected at runtime rather than hard-coded.
Provider Selection and _provider_order
The helper _provider_order (lines 98-104) resolves which providers to attempt. When the caller passes provider="auto", the function returns ["groq", "openai"]. If a specific name is supplied, the list contains only that provider. This deterministic order is what creates the Groq-first, OpenAI-second fallback behavior.
The Fallback Orchestration Loop
The heart of the resilience logic is _transcribe_with_fallback in agent_reach/transcribe.py (lines 49-62). For each audio chunk, it iterates over the resolved provider order and performs the following steps:
- Checks whether the provider's API key is present in the
Configobject via_provider_key; if the key is missing, the provider is skipped. - Calls
transcribe_chunkto send the audio to the provider's endpoint. - If
transcribe_chunksucceeds, the loop immediately returns the transcript. - If any exception—including a
TranscribeError—is raised, the loop captures the failure and continues to the next provider.
If the loop exhausts every provider without success, it raises an aggregated error containing all captured failures.
End-to-End Transcription Request Flow
The main transcribe function orchestrates the pipeline from download to final text. The exact sequence implemented in agent_reach/transcribe.py is:
-
Validation. Before touching the audio,
transcribeverifies that at least one provider in the resolved order has a configured API key (lines 20-25). -
Source handling. The input can be a remote URL, which is downloaded with
download_audio(powered by yt-dlp), or a local file path. -
Compression.
compress_audiore-encodes the source to a Whisper-compatible mono, 16 kHz, 32 kbps format (lines 101-108). -
Chunking. If the compressed file exceeds the approximate 24 MiB limit,
chunk_audiosplits it into segments of up to 10 minutes each (lines 126-133). -
Per-chunk fallback. For every segment,
transcribecalls_transcribe_with_fallback, which applies the provider loop described above (lines 49-62). -
HTTP request. Inside the loop,
transcribe_chunkbuilds a multipart POST request: the provider-specific<endpoint>, anAuthorization: Bearer <api_key>header, the audio file, and form data includingmodelandresponse_format=text(lines 81-89). -
Error detection. On HTTP 200, the raw text response is returned. Any non-2xx status causes
transcribe_chunkto raise aTranscribeError(lines 94-96), signaling the outer loop to fall back to the next provider. -
Aggregation. Successful transcripts are stripped and joined with newlines inside
transcribe(lines 42-48) before the final string is returned.
Groq to OpenAI Fallback in Practice
When transcribe is invoked with provider="auto" (the CLI default), the following runtime behavior occurs:
- First attempt: The request is sent to Groq's endpoint (
https://api.groq.com/openai/v1/audio/transcriptions) using modelwhisper-large-v3. If Groq returns HTTP 200, the transcript is accepted and OpenAI is never contacted. - Silent fallback: If Groq fails—whether due to an HTTP 429 rate limit, a network timeout, a missing API key, or any other error—the loop catches the exception and proceeds to OpenAI's endpoint (
https://api.openai.com/v1/audio/transcriptions) with modelwhisper-1. - Final failure: If OpenAI also fails, the aggregated
TranscribeErroris raised to the caller.
This behavior is codified in the unit-test suite in tests/test_transcribe.py. The TestFallback class (lines 99-132) validates three critical scenarios:
test_groq_succeeds_no_openai_callproves that a successful Groq response prevents any OpenAI traffic.test_groq_429_falls_back_to_openaiverifies that an HTTP 429 from Groq triggers the OpenAI path.test_skip_unconfigured_providerconfirms that providers missing API keys are skipped entirely.
Code Examples
Direct Script Usage
The public transcribe function accepts a source path or URL and a Config object that loads keys from the user's configuration file.
from agent_reach import transcribe
from agent_reach.config import Config
# Load keys previously stored with `agent-reach configure`.
cfg = Config()
text = transcribe(
"https://youtu.be/example", # can also be a local .m4a path
provider="auto", # default: Groq to OpenAI fallback
config=cfg,
)
print(text)
This call orchestrates the full pipeline, relying on _provider_order to set the fallback chain and _transcribe_with_fallback to switch providers automatically.
Manual Provider Loop
For advanced use, you can invoke the fallback helper directly on a pre-generated audio chunk.
from agent_reach import transcribe as tr
from pathlib import Path
from agent_reach.config import Config
cfg = Config()
chunk = Path("tmp/chunk_001.m4a")
order = ["groq", "openai"]
try:
result = tr._transcribe_with_fallback(chunk, order, cfg)
print("Transcribed via:", order[0] if result else "none")
except tr.TranscribeError as exc:
print("All providers failed:", exc)
This example demonstrates the inner _transcribe_with_fallback loop that iterates over order, invoking transcribe_chunk for each provider until one succeeds.
CLI Entry Point
The packaged CLI exposes the same logic without writing code:
agent-reach transcribe "https://youtu.be/example" --provider auto
Arguments are forwarded directly to the transcribe function, inheriting the identical Groq-to-OpenAI fallback semantics.
Key Files and Functions
Understanding the transcription fallback logic requires familiarity with these source files:
agent_reach/transcribe.py— Core implementation containingPROVIDERS,_provider_order,_transcribe_with_fallback,transcribe_chunk, and the maintranscribeorchestrator.tests/test_transcribe.py— Test suite (includingTestFallback) that validates provider routing, fallback on HTTP 429, and skipping unconfigured providers.agent_reach/config.py— Storesgroq_api_keyandopenai_api_keyand exposes the configuration object consumed by the transcriber.agent_reach/channels/youtube.py— Example channel implementation that delegates itstranscribemethod to the coretranscribefunction.
Summary
- Agent Reach's
transcribecommand inagent_reach/transcribe.pyimplements a hardcoded provider order that places Groq first and OpenAI second whenprovider="auto"is selected. - The
_transcribe_with_fallbackhelper silently catches any failure from Groq—including rate limits, network errors, or missing keys—and retries the same chunk against OpenAI. - Each provider is defined in the
PROVIDERStable with its own endpoint, model name, and configuration key, keeping secrets isolated from the orchestration logic. - Audio is automatically compressed, chunked if it exceeds the 24 MiB limit, and processed independently, with per-chunk fallback ensuring maximum resilience.
- The behavior is codified in
tests/test_transcribe.py, which explicitly asserts that OpenAI is never called when Groq succeeds and that fallback occurs on Groq HTTP 429 errors.
Frequently Asked Questions
What triggers the fallback from Groq to OpenAI Whisper?
Any failure during the Groq request triggers the fallback. According to _transcribe_with_fallback in agent_reach/transcribe.py, if transcribe_chunk raises an exception—such as an HTTP 429 rate limit, a network timeout, or a TranscribeError from a non-2xx response—the loop immediately proceeds to the next configured provider, which is OpenAI by default.
Can I force the transcribe command to use only one provider?
Yes. Passing provider="groq" or provider="openai" to the transcribe function bypasses the automatic ordering. The _provider_order helper returns a single-element list containing only the requested provider, so no fallback occurs if that provider fails.
How does Agent Reach handle audio files that exceed the Whisper size limit?
Before transcription, compress_audio re-encodes the source to a Whisper-compatible format. If the result still exceeds the approximate 24 MiB limit, chunk_audio splits the file into segments of up to 10 minutes. The main transcribe function then processes each segment independently through _transcribe_with_fallback, so a large file never prevents transcription.
What happens if both Groq and OpenAI providers fail?
If every provider in the resolved order fails, _transcribe_with_fallback exhausts its loop and raises an aggregated TranscribeError. The caller receives a single exception that encapsulates all underlying failures, indicating that no configured provider could complete the transcription.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →