# How Agent Reach Handles Platform API Changes Like the BiliBili yt-dlp Block

> Discover how Agent Reach tackles platform API changes, like the BiliBili yt-dlp block, using its multi-backend architecture for automatic tool probing and fallback.

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

---

**Agent Reach uses a multi-backend channel architecture that automatically probes and falls back to alternative implementations when platforms like BiliBili block specific tools such as yt-dlp.**

The open-source Agent Reach repository (Panniantong/Agent-Reach) provides AI agents with stable internet access through a **plugin-style channel system** where each platform is encapsulated in a Python class that can switch between multiple backend implementations without code changes. This design ensures that when upstream APIs change or anti-bot measures block specific tools, the system silently redirects to working alternatives.

## Multi-Backend Channel Architecture

Agent Reach represents every internet platform as a standalone **channel** that inherits from `BaseChannel`. Rather than hard-coding a single method to fetch data, each channel declares an ordered list of candidate backends that can satisfy the same capability—such as reading video metadata or performing searches.

### Ordered Backend Lists

In [`agent_reach/channels/bilibili.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/bilibili.py), the `BilibiliChannel` class defines its resilience strategy through the `backends` attribute:

```python

# agent_reach/channels/bilibili.py

class BilibiliChannel(Channel):
    ...
    backends = ["bili-cli", "OpenCLI", "B站搜索 API"]

```

The system prioritizes these backends in sequence:
- **`bili-cli`**: A public CLI tool handling search, hot lists, and video details without requiring login credentials.
- **`OpenCLI`**: Reuses browser sessions to fetch subtitles when the CLI-only approach fails.
- **`B站搜索 API`**: A zero-dependency HTTP endpoint serving as a last-ditch fallback.

These backends are **hard-coded in order of preference**, meaning a platform change that disables one tool (such as the yt-dlp block) requires no modifications to the core logic—only a potential reordering of this list.

### The BaseChannel Contract

The abstract base class in [`agent_reach/channels/base.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/base.py) defines the interface that enables this flexibility. Each channel implements `can_handle()`, `read()`, `search()`, and critically, the **`check()`** method, which validates backend availability at runtime.

## Automatic Probe-Based Fallback

The resilience mechanism operates through proactive probing. When a channel initializes, it iterates through its candidate backends and selects the first functional option.

### How the check() Method Works

The `check()` method in [`agent_reach/channels/bilibili.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/bilibili.py) implements the selection logic:

```python

# agent_reach/channels/bilibili.py

def check(self, config=None):
    self.active_backend = None
    findings = []
    for backend in self.ordered_backends(config):
        if backend == "bili-cli":
            result = self._check_bili_cli()
        elif backend == "OpenCLI":
            result = self._check_opencli()
        else:
            result = self._check_search_api()
        ...

```

The `ordered_backends()` method respects user configuration while maintaining the default priority order. Each private `_check_*` helper runs a **probe command** that evaluates the specific backend's health.

### Probe States and Error Handling

The probing system in [`agent_reach/probe.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/probe.py) normalizes command execution into four distinct states:

- **`missing`**: The backend binary is not installed—candidate is ignored.
- **`broken`**: The binary exists but cannot execute—candidate marked as "error."
- **`ok`**: The backend runs successfully and is fully operational.
- **`warn`**: The backend functions but may have limitations or deprecation notices.

If `bili-cli` returns `missing` or `broken`, the channel automatically advances to `OpenCLI`; if that also fails, the HTTP search API attempts to satisfy the request. This cascade happens silently without user intervention.

## Case Study: The BiliBili yt-dlp Block

The BiliBili channel's module header explicitly documents the architectural decision to remove yt-dlp following platform changes:

```python

# agent_reach/channels/bilibili.py

"""Bilibili — multi-backend: bili-cli / OpenCLI / search API.

yt-dlp was REMOVED from this channel (live-verified 2026-06):
bilibili's risk control 412-blocks yt-dlp's requests...
"""

```

### Why yt-dlp Was Removed

BiliBili's risk control systems began returning 412 error codes specifically blocking yt-dlp requests. Because Agent Reach maintains a **data-driven backend list**, maintainers removed yt-dlp from the `backends` array entirely. The probe logic never attempts to initialize it, preventing the channel from entering a broken state.

### Current Backend Stack

The channel now relies exclusively on `bili-cli` for video retrieval and `OpenCLI` for subtitle extraction when the CLI approach falls short. When upstream risk controls changed, the diagnostics automatically switched the active backend and surfaced informative messages:

```

bili-cli 可用（搜索/热门/排行/视频详情/音频，无需登录；
字幕需 OpenCLI。上游 2026-03 起停更）

```

The adaptation required only updating the backend list in the source file—no changes to the probing logic or fallback mechanisms.

## Diagnostic and Maintenance Tools

Agent Reach provides visibility into backend status through the `doctor` command, ensuring users can verify which implementation is currently active.

### The doctor Command

The [`agent_reach/doctor.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/doctor.py) module implements a CLI command that runs `check()` on every registered channel:

```bash
$ agent-reach doctor

# … output …

Bilibili: ok (active backend: bili-cli)

```

If the primary backend is unavailable, the output reflects the automatic fallback:

```bash
$ agent-reach doctor

# … output …

Bilibili: warn (bili-cli not installed, falling back to OpenCLI)

```

### Real-Time Status Reporting

Programmatic verification is available through the Python API:

```python
from agent_reach.channels.bilibili import BilibiliChannel

channel = BilibiliChannel()
status, message = channel.check()
print(f"Status: {status}\nMessage: {message}")

# → Status: ok

# → Message: bili-cli 可用（搜索/热门/排行/视频详情/音频，无需登录；字幕需 OpenCLI。上游 2026-03 起停更）

```

When upstream changes occur, maintainers simply **reorder or append candidates** to the channel file, and the `doctor` command immediately surfaces the new configuration to users.

## Summary

- **Agent Reach** uses a plugin-style channel architecture where each platform inherits from `BaseChannel` and declares multiple backends.
- The **`check()`** method automatically probes candidates in [`agent_reach/channels/bilibili.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/bilibili.py) and selects the first functional option.
- **Probe states** (`missing`, `broken`, `ok`, `warn`) determined by [`agent_reach/probe.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/probe.py) enable seamless fallback without user intervention.
- The **BiliBili yt-dlp block** was handled by removing yt-dlp from the backend list, allowing the channel to fall back to `bili-cli` and `OpenCLI`.
- The **`agent-reach doctor`** command provides real-time visibility into active backends and diagnostic information.

## Frequently Asked Questions

### How does Agent Reach detect when a backend stops working?

The `check()` method in each channel runs probe commands via [`agent_reach/probe.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/probe.py) that execute lightweight validation tests. If a backend returns a `broken` status or fails to execute, the channel marks it as unavailable and moves to the next candidate in the `ordered_backends()` list.

### Can I manually configure which backend Agent Reach uses?

Yes. While `ordered_backends()` respects hard-coded defaults in files like [`agent_reach/channels/bilibili.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/bilibili.py), the method accepts an optional `config` parameter that can override the priority order or disable specific candidates without modifying source code.

### What happens if all backends for a platform fail?

If every candidate returns `missing` or `broken`, the channel reports an `error` status through `agent-reach doctor`. The system will not crash, but the specific capability (such as video search) will be unavailable until maintainers add a new backend or the upstream API restores service.

### How do I add a new backend to handle future API changes?

To add a new backend, modify the `backends` list in the specific channel file (e.g., [`agent_reach/channels/bilibili.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/bilibili.py)) and implement a corresponding `_check_<backend>()` method. The existing probe logic in [`agent_reach/probe.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/probe.py) will automatically include the new candidate in the health check cycle.