# What Is the `agent-reach transcribe` Command and Its Whisper Fallback Logic?

> Discover the agent-reach transcribe command for audio to text conversion. Learn how it automatically falls back from Groq to OpenAI with Whisper for seamless transcription.

- Repository: [Pnant/Agent-Reach](https://github.com/Panniantong/Agent-Reach)
- Tags: how-to-guide
- Published: 2026-07-13

---

**The `agent-reach transcribe` command converts audio files or URLs into text using Whisper-compatible APIs, automatically falling back from Groq to OpenAI if the primary provider fails.**

The **Panniantong/Agent-Reach** repository provides a robust transcription pipeline that orchestrates audio downloading, chunking, and provider selection. The implementation guarantees reliability by iterating through an ordered list of Whisper providers until one succeeds or all are exhausted.

## The Core Transcribe Function

The transcription workflow centers on the **`transcribe()`** function defined in [`agent_reach/transcribe.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/transcribe.py).

```python
def transcribe(
    source: str,
    *,
    provider: str = "auto",
    out_dir: Optional[Path] = None,
    config: Optional[Config] = None,
) -> str:
    """Download, chunk, and send the audio to a Whisper provider."""

```

This function performs three critical operations:

1. **Downloads** the audio source using *yt‑dlp* when a URL is provided.
2. **Segments** the audio into chunks of ≤ 600 seconds (`CHUNK_SECONDS = 600`).
3. **Dispatches** each chunk to a Whisper provider using the fallback logic.

## Provider Configuration and Selection

### The PROVIDERS Mapping

Inside [`agent_reach/transcribe.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/transcribe.py), the **`PROVIDERS`** dictionary (lines 32‑42) defines the available endpoints:

| Provider | Endpoint | Model | API Key Field |
|----------|----------|-------|---------------|
| **groq** | `https://api.groq.com/openai/v1/audio/transcriptions` | `whisper-large-v3` | `groq_api_key` |
| **openai** | `https://api.openai.com/v1/audio/transcriptions` | `whisper-1` | `openai_api_key` |

### The _choose_providers() Logic

The helper **`_choose_providers()`** (lines 251‑258) determines which providers to attempt:

```python
def _choose_providers(provider: str, cfg: Config) -> List[str]:
    if provider != "auto":
        return [provider]          # user-specified provider only

    # auto-mode: use any provider that has a configured API key

    return [p for p, v in PROVIDERS.items() if cfg.get(v["key_field"])]

```

When **`provider="auto"`** (the default), the function returns a list of providers with valid API keys. If no keys are detected, the system falls back to the hard-coded default order **`["groq", "openai"]`**.

## Whisper Fallback Logic Implementation

### The _transcribe_with_fallback() Function

The actual resilience mechanism lives in **`_transcribe_with_fallback()`** (lines 306‑315):

```python
def _transcribe_with_fallback(
    chunk: Path,
    order: List[str],
    config: Config,
) -> str:
    """Try each provider in order; return first success or raise the last error."""
    last_error = None
    for p in order:
        try:
            return transcribe_chunk(chunk, p, config=config)
        except TranscribeError as err:
            last_error = err          # remember the failure, try next provider

    raise last_error                # all providers failed → propagate the last error

```

This function iterates through the ordered provider list. For each provider, it calls **`transcribe_chunk()`**; if a **`TranscribeError`** (e.g., HTTP 4xx/5xx) is raised, the error is captured and the loop continues. Upon success, the transcription text returns immediately. If the loop completes without success, the final error is re‑raised.

### Error Handling and Provider Ordering

The default ordering prioritizes **Groq** over **OpenAI**. This behavior is validated in [`tests/test_transcribe.py`](https://github.com/Panniantong/Agent-Reach/blob/main/tests/test_transcribe.py) (lines 111‑144), which confirms that the system attempts Groq first and only invokes OpenAI when Groq raises an error. The CLI entry point in [`agent_reach/cli.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/cli.py) (lines 1135‑1150) wires this logic directly to the command-line interface:

```python
elif args.command == "transcribe":
    _cmd_transcribe(args)

def _cmd_transcribe(args):
    from agent_reach.transcribe import TranscribeError, transcribe
    try:
        text = transcribe(args.source, provider=args.provider)
        if args.out:
            Path(args.out).write_text(text, encoding="utf-8")
        else:
            print(text)
    except TranscribeError as e:
        sys.exit(f"❌  {e}")

```

## Practical Usage Examples

### Example 1: Basic CLI Transcription

Transcribe a YouTube video using the default provider order (Groq first, OpenAI fallback):

```bash
agent-reach transcribe "https://www.youtube.com/watch?v=dQw4w9WgXcQ"

```

### Example 2: Force a Specific Provider

Skip the fallback chain and use only OpenAI:

```bash
agent-reach transcribe "audio.mp3" -p openai

```

### Example 3: Programmatic Usage with Auto-Mode

```python
from agent_reach.transcribe import transcribe, Config

cfg = Config()                     # reads API keys from environment variables

text = transcribe(
    "https://example.com/podcast.mp3",
    provider="auto",              # tries groq → openai automatically

    config=cfg,
)
print(text)

```

### Example 4: Manual Error Handling

```python
from agent_reach.transcribe import transcribe, TranscribeError

try:
    result = transcribe("audio.wav")
except TranscribeError as exc:
    print(f"Transcription failed: {exc}")
else:
    print(result)

```

## Summary

- The **`agent-reach transcribe`** command is implemented in [`agent_reach/transcribe.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/transcribe.py) and exposed via [`agent_reach/cli.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/cli.py).
- It supports two providers: **Groq** (`whisper-large-v3`) and **OpenAI** (`whisper-1`).
- The **`_choose_providers()`** function builds an ordered list, defaulting to `["groq", "openai"]` when `provider="auto"`.
- The **`_transcribe_with_fallback()`** function implements the resilience logic, catching **`TranscribeError`** and trying the next provider until success or exhaustion.
- Audio files are automatically chunked into 600-second segments before processing.

## Frequently Asked Questions

### What happens if both Groq and OpenAI fail during transcription?

If both providers fail, the **`_transcribe_with_fallback()`** function propagates the last encountered **`TranscribeError`**, causing the CLI to exit with a non-zero status code and the error message to be printed to stderr.

### Can I use a custom provider order instead of the default Groq-then-OpenAI sequence?

Yes. While the CLI defaults to `"auto"`, you can programmatically pass a custom **`Config`** object or modify the provider selection logic. However, the command-line interface currently supports specifying a single provider with `-p` rather than a custom sequence.

### Does the transcribe command handle large audio files automatically?

Yes. The **`transcribe()`** function splits audio into chunks of **`CHUNK_SECONDS = 600`** (10 minutes) before sending them to the Whisper API, ensuring compatibility with provider file-size and duration limits.

### Where is the fallback behavior tested in the repository?

The fallback logic is validated in **[`tests/test_transcribe.py`](https://github.com/Panniantong/Agent-Reach/blob/main/tests/test_transcribe.py)**, specifically in lines 111‑144, which verify that `_transcribe_with_fallback` attempts Groq first and only falls back to OpenAI when the former raises an error, and lines 185‑226, which confirm the auto-mode provider selection logic.