How Agent Reach Uses Groq or OpenAI for Audio Transcription: A Technical Deep Dive

Agent Reach's transcribe command automatically routes audio files to Groq's Whisper-large-v3 API first, then falls back to OpenAI's Whisper-1 endpoint if Groq fails or is unconfigured.

The transcribe command in the Panniantong/Agent-Reach repository converts audio from local files or public URLs into text using cloud-based Whisper APIs. This article examines the complete implementation in agent_reach/transcribe.py, showing how the system selects providers, handles authentication, chunks large files, and manages failover between Groq and OpenAI.


Provider Configuration and API Mapping

The transcription system starts with a hardcoded provider registry. At lines 38-49 of agent_reach/transcribe.py, the PROVIDERS dictionary defines the endpoint URLs, model names, and configuration key for each service:


# From agent_reach/transcribe.py (simplified)

PROVIDERS = {
    "groq": {
        "endpoint": "https://api.groq.com/openai/v1/audio/transcriptions",
        "model": "whisper-large-v3",
        "api_key_config": "groq_api_key"
    },
    "openai": {
        "endpoint": "https://api.openai.com/v1/audio/transcriptions",
        "model": "whisper-1",
        "api_key_config": "openai_api_key"
    }
}

This registry enables provider-agnostic request building. The Groq endpoint uses their OpenAI-compatible API with the whisper-large-v3 model, while OpenAI uses the standard whisper-1 model.


Configuration and API Key Retrieval

API keys are resolved through agent_reach/config.py. The Config.get() method (lines 58-67) retrieves values from user configuration files or environment variables. The required keys are declared in FEATURE_REQUIREMENTS at lines 8-11:

  • groq_api_key — for Groq access
  • openai_api_key — for OpenAI access

When a user runs agent-reach transcribe, the system validates that at least one provider is configured before attempting transcription.


Automatic Provider Selection and Fallback Logic

The _provider_order() function (lines 50-55 in transcribe.py) determines which providers to try and in what sequence:

def _provider_order(preferred: str = "auto") -> list[str]:
    if preferred == "auto":
        return ["groq", "openai"]  # Groq prioritized for speed/cost

    return [preferred]

This ordered list feeds into _transcribe_with_fallback() (lines 26-38), which iterates through providers until one succeeds. The default behavior prioritizes Groq due to its typically faster inference and lower pricing, falling back to OpenAI only on failure.


Chunk-Level Transcription Implementation

Building the HTTP Request

The transcribe_chunk() function (lines 13-47) handles the actual API communication:

def transcribe_chunk(audio_path: Path, provider: str, config: Config) -> str:
    """Send a single audio chunk to the specified provider's Whisper API."""
    # Retrieve API key via _provider_key()

    api_key = _provider_key(provider, config)
    
    provider_info = PROVIDERS[provider]
    
    # Construct multipart/form-data payload

    files = {"file": audio_path.open("rb")}
    data = {"model": provider_info["model"], "response_format": "text"}
    
    # Execute POST with Bearer token authentication

    response = requests.post(
        provider_info["endpoint"],
        headers={"Authorization": f"Bearer {api_key}"},
        files=files,
        data=data,
        timeout=300
    )
    
    if response.status_code != 200:
        raise TranscribeError(
            f"{provider} API error {response.status_code}: {response.text}"
        )
    
    return response.text

Key implementation details:

  • Authentication: Uses standard Bearer token header
  • Payload: Multipart form with file, model, and response_format fields
  • Error handling: Non-2xx responses raise TranscribeError (lines 44-46)
  • Timeout: 5-minute default for large chunks

Full Orchestration Pipeline

The main transcribe() entry point (lines 57-78) coordinates the complete workflow:

  1. Validation: Ensures at least one provider has a configured API key
  2. Workspace preparation: Creates temporary directory (or uses user-supplied out_dir)
  3. Preprocessing: Delegates to _transcribe_in_dir() which:
    • Downloads remote audio via yt-dlp
    • Compresses to fit Whisper's 25 MiB limit
    • Chunks long audio into processable segments
  4. Transcription: Each chunk processed through _transcribe_with_fallback()
  5. Aggregation: Concatenates chunk transcripts into final output

# Direct library usage example

from agent_reach.transcribe import transcribe

# Auto-provider selection: tries Groq first, then OpenAI

text = transcribe("https://example.com/podcast.mp3")
print(text)

# Force specific provider

text = transcribe("local_audio.m4a", provider="openai")

CLI and Channel Integration

Command-Line Interface

The CLI parsing in agent_reach/cli.py (lines 1329-1334) exposes the transcribe functionality:


# Automatic provider selection

$ agent-reach transcribe https://youtu.be/dQw4w9WgXcQ

# Explicit Groq selection

$ agent-reach transcribe ./meeting.mp3 -p groq

# Explicit OpenAI selection

$ agent-reach transcribe ./meeting.mp3 -p openai

Channel Shortcuts

YouTube channels and other integrations reuse the same core function. In agent_reach/channels/youtube.py (lines 120-129):

from agent_reach.transcribe import transcribe

class YouTubeChannel:
    def transcribe(self, video_url: str, **kwargs) -> str:
        """Transcribe this channel's YouTube video audio."""
        # Delegates to the same orchestration pipeline

        return transcribe(video_url, **kwargs)

This design ensures consistent provider handling across all entry points.


Error Handling and Resilience

The system implements multiple layers of error handling:

Layer Mechanism Location
Network failures requests exceptions caught, wrapped in TranscribeError transcribe_chunk()
API errors HTTP status check → TranscribeError with response body Lines 44-46
Provider unavailability Automatic retry with next provider in _transcribe_with_fallback() Lines 26-38
Complete failure TranscribeError raised after all providers exhausted Caller receives clear error

Summary

  • Provider registry: Hardcoded in PROVIDERS dict (transcribe.py lines 38-49) with endpoints, models, and config keys
  • Default priority: Groq first (whisper-large-v3), OpenAI fallback (whisper-1)
  • Authentication: Bearer token from Config.get() resolving groq_api_key or openai_api_key
  • Chunk processing: Audio downloaded, compressed, split if needed, then transcribe_chunk() POSTs to API
  • Entry points: CLI (agent_reach/cli.py), library (transcribe()), and channels (youtube.py) all converge on the same pipeline
  • Failure mode: Graceful degradation across providers with informative errors

Frequently Asked Questions

How do I configure API keys for transcription?

Set groq_api_key and/or openai_api_key in your Agent Reach configuration file, or export them as environment variables. The system reads these via Config.get() in agent_reach/config.py (lines 58-67). At least one provider must be configured for transcription to function.

Why does Agent Reach prefer Groq over OpenAI by default?

The _provider_order() function returns ["groq", "openai"] when provider="auto" (the default). Groq's Whisper-large-v3 typically offers faster inference at lower cost while maintaining equivalent accuracy to OpenAI's Whisper-1. Users can override this with -p openai in the CLI or provider="openai" in library calls.

What happens if both Groq and OpenAI fail?

The _transcribe_with_fallback() loop exhausts all providers in the ordered list. If none succeed, the final TranscribeError propagates to the caller with details of the last failure. For chunked audio, this aborts the entire transcription rather than continuing with partial results.

Does Agent Reach support transcription models other than Whisper?

No. The PROVIDERS dictionary in agent_reach/transcribe.py only defines Groq and OpenAI endpoints, both using Whisper variants. The multipart payload structure (file, model, response_format) assumes OpenAI-compatible Whisper APIs.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →