# How to Route Between Multiple Backends for a Single Platform in Agent Reach

> Learn how to route between multiple backends for a single platform in Agent Reach. Discover priority ordering, health checks, and configurable overrides for robust routing.

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

---

**Agent Reach routes between multiple backends for a single platform using a priority-ordered list that probes each candidate until finding a healthy one, with user-configurable overrides via config files or environment variables.**

The `Panniantong/Agent-Reach` repository provides a flexible channel-based architecture where each social platform (like Twitter) can support multiple CLI tools or APIs as backends. Understanding how to route between multiple backends for a single platform allows you to control which tool handles your requests, whether you need specific features or fallback resilience.

## Understanding the Routing Architecture

Agent Reach implements a two-layer routing system that separates generic ordering logic from platform-specific health checks.

### The Channel Base Class

In [`agent_reach/channels/base.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/base.py), the `Channel` abstract base class defines the `ordered_backends` method (lines 45-58). This method handles the initial ordering of backend candidates:

- It copies the default `backends` list defined by each channel
- Checks for a configuration key `<channel>_backend` (or environment variable `<CHANNEL>_BACKEND`)
- If a match exists, moves that specific backend to the front of the list
- Guarantees that unknown overrides never hide working backends by validating against available options

### Platform-Specific Implementation

Each concrete channel implements the `check` method to probe candidates. For Twitter, [`agent_reach/channels/twitter.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/twitter.py) (lines 29-48) contains the selection loop that calls `_check_twitter_cli`, `_check_opencli`, or `_check_bird` for each backend in the ordered list. These checks utilize `probe_command` from [`agent_reach/probe.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/probe.py) to verify health. Lines 43-47 select the first backend returning `"ok"` or `"warn"` status, storing it in `self.active_backend`.

## How Backend Selection Works

The routing flow for Twitter demonstrates the complete process:

1. **Definition**: `TwitterChannel.backends` lists `["twitter-cli", "OpenCLI", "bird CLI (legacy)"]` (lines 10-12)
2. **Ordering**: `ordered_backends` reorders the list if `twitter_backend` is specified in config or `TWITTER_BACKEND` env var exists
3. **Probing**: `TwitterChannel.check()` iterates through the ordered list, calling the appropriate `_check_*` helper for each
4. **Selection**: The first backend returning `"ok"` (fully usable) or `"warn"` (installed but not fully configured) becomes `self.active_backend`
5. **Fallback**: If none succeed, the channel reports `"error"` or `"warn"` with diagnostics (lines 49-57)

This generic pattern applies to every platform defining a `backends` list, including Reddit, YouTube, and Bilibili.

## Configuring Backend Routing

You can influence backend selection through multiple configuration layers.

### Using Configuration Files

Pass a configuration dictionary when initializing Agent Reach to force a specific backend:

```python
from agent_reach.core import AgentReach

# Load a custom config that forces the "bird" backend for Twitter

custom_cfg = {
    "twitter_backend": "bird CLI (legacy)"   # any string that matches or prefixes a candidate

}

agent = AgentReach(config=custom_cfg)

# The first call will trigger the probe; the chosen backend is now stored:

status, msg = agent.channel("twitter").check(custom_cfg)

print("Chosen backend:", agent.channel("twitter").active_backend)
print("Status:", status)
print("Message:", msg)

```

The `ordered_backends` method moves `"bird CLI (legacy)"` to the front before probing begins.

### Using Environment Variables

Set the backend preference via environment variables before running your CLI commands:

```bash
export TWITTER_BACKEND="OpenCLI"
python -m agent_reach.cli doctor   # runs the health-check for all channels

```

The configuration loader in [`agent_reach/config.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/config.py) reads this variable and passes it to `ordered_backends`, achieving the same effect as the config dict.

### Runtime Inspection

Inspect which backend was selected after automatic discovery:

```python
from agent_reach.core import AgentReach

agent = AgentReach()

# Normal discovery – will pick the first healthy backend automatically

agent.channel("twitter").check()
print("Active Twitter backend:", agent.channel("twitter").active_backend)

```

If `twitter-cli` is installed and authenticated, it will be selected; otherwise the logic falls back to `OpenCLI`, then to `bird CLI (legacy)`.

## Summary

- **Two-layer architecture**: Generic ordering logic in `Channel.ordered_backends` ([`agent_reach/channels/base.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/base.py) lines 45-58) and platform-specific health checks in concrete channels like `TwitterChannel.check` ([`agent_reach/channels/twitter.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/twitter.py) lines 29-48)
- **User overrides**: Configure via `<channel>_backend` config key or `<CHANNEL>_BACKEND` environment variable to prioritize specific backends
- **Automatic fallback**: The system probes each backend in order, selecting the first healthy candidate (`"ok"` or `"warn"` status) and storing it in `self.active_backend`
- **Cross-platform pattern**: The same routing mechanism works for all platforms including Reddit, YouTube, and Bilibili

## Frequently Asked Questions

### How does Agent Reach prioritize backends when multiple are available?

Agent Reach prioritizes backends based on the order in `Channel.ordered_backends`. By default, this matches the definition order in the channel's `backends` list. However, if you specify a backend via the `twitter_backend` config key or `TWITTER_BACKEND` environment variable, that backend moves to the front of the probe order. The system then checks each candidate sequentially until finding one with `"ok"` or `"warn"` status.

### Can I force a specific backend even if it's not responding?

No. The `ordered_backends` method guarantees that an unknown or unhealthy backend override never hides working alternatives. If your specified backend returns an error status during the health check loop in `check()`, the system continues probing the remaining candidates. This safety mechanism prevents configuration errors from breaking functionality.

### Where is the active backend stored after selection?

Once selected, the active backend string is stored in the `self.active_backend` attribute of the channel instance. You can access this after calling `check()` to see which backend was chosen for subsequent operations. This attribute persists for the lifetime of the channel object.

### Does this routing mechanism work for platforms other than Twitter?

Yes. The routing logic is generic and implemented in the `Channel` base class. Any platform that defines a `backends` list—such as Reddit, YouTube, or Bilibili in the Agent Reach codebase—automatically supports the same routing behavior, including user overrides via config files and environment variables.