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

> Discover how Agent Reach uses Groq or OpenAI for audio transcription. Learn about the fallback mechanism and technical details of the transcribe command.

- Repository: [Pnant/Agent-Reach](https://github.com/Panniantong/Agent-Reach)
- Tags: deep-dive
- Published: 2026-08-05

---

**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`](https://github.com/Panniantong/Agent-Reach/blob/main/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`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/transcribe.py), the `PROVIDERS` dictionary defines the endpoint URLs, model names, and configuration key for each service:

```python

# 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`](https://github.com/Panniantong/Agent-Reach/blob/main/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`](https://github.com/Panniantong/Agent-Reach/blob/main/transcribe.py)) determines which providers to try and in what sequence:

```python
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:

```python
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

```python

# 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`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/cli.py) (lines 1329-1334) exposes the transcribe functionality:

```bash

# 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`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/youtube.py) (lines 120-129):

```python
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`](https://github.com/Panniantong/Agent-Reach/blob/main/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`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/cli.py)), library (`transcribe()`), and channels ([`youtube.py`](https://github.com/Panniantong/Agent-Reach/blob/main/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`](https://github.com/Panniantong/Agent-Reach/blob/main/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`](https://github.com/Panniantong/Agent-Reach/blob/main/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.