How Agent Reach Multi-Backend Routing Works: Complete Guide to Override the Default Backend
Agent Reach uses an ordered backends list per channel with ordered_backends() to prioritize user overrides before probing each candidate, making the first working backend active.
Agent Reach treats every platform—YouTube, Twitter, Reddit—as a channel that binds to one or more backends (e.g., yt-dlp, OpenCLI, rdt-cli). The routing intelligence lives in the abstract base class Channel at [agent_reach/channels/base.py](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/base.py), and every concrete channel inherits this multi-backend selection logic.
How Channels Declare Available Backends
Each channel defines an ordered list backends where the first element is the preferred backend and subsequent items serve as fallbacks.
Single-backend channel:
class YouTubeChannel(Channel):
backends = ["yt-dlp"]
Multi-backend channels:
class RedditChannel(Channel):
backends = ["OpenCLI", "rdt-cli"]
class TwitterChannel(Channel):
backends = ["twitter-cli", "OpenCLI", "bird CLI (legacy)"]
These declarations appear in their respective channel files: [youtube.py](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/youtube.py), [reddit.py](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/reddit.py), and [twitter.py](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/twitter.py).
The ordered_backends() Method: How Prioritization Works
The core routing method Channel.ordered_backends(config=None) builds the probe sequence by respecting user overrides while preserving fallback safety.
Algorithm steps:
- Copy the channel's
self.backendslist. - Check for override in
config(key:<channel>_backend) or environment variable (<CHANNEL>_BACKEND). - If the override matches or prefixes an existing backend, move it to index 0.
- Ignore unknown overrides to prevent breaking fallback chains.
def ordered_backends(self, config=None) -> List[str]:
"""Candidate backends in probe order, honoring the user override."""
candidates = list(self.backends)
override = config.get(f"{self.name}_backend") if config else None
if override:
for i, b in enumerate(candidates):
if b == override or b.startswith(override):
candidates.insert(0, candidates.pop(i))
break
return candidates
Source: [agent_reach/channels/base.py](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/base.py)
Backend Probing and Selection in check()
Concrete channels implement check(self, config=None) following a common probe pattern:
- Reset
self.active_backend = None. - Iterate through
self.ordered_backends(config). - Call channel-specific validation helpers (e.g.,
_check_opencli,_check_twitter_cli). - Collect
(backend, status, message)tuples infindings. - Return first
"ok"result; if none, return first"warn"result. - Aggregate
"error"/"broken"results only if no viable backend exists.
for backend in self.ordered_backends(config):
if backend == "OpenCLI":
result = self._check_opencli()
elif backend == "twitter-cli":
result = self._check_twitter_cli(config)
...
if result is None:
continue # backend not installed -> skip
findings.append((backend, *result))
Channel-specific behaviors:
- YouTube: Directly sets
self.active_backend = "yt-dlp"after successful probe. - Reddit: Sets
self.active_backendonly when status equals"ok"(see probe loop in [reddit.py](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/reddit.py)). - Twitter: Same two-stage pattern with
twitter-cli,OpenCLI, and legacybird CLIpriority (see [twitter.py](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/twitter.py)).
How to Override the Default Backend
Agent Reach provides two override mechanisms that feed into ordered_backends():
| Override source | Syntax | Example |
|---|---|---|
Configuration file (~/.agent-reach/config.yaml) |
<channel>_backend |
twitter_backend: OpenCLI |
| Environment variable | Uppercase <CHANNEL>_BACKEND |
export REDDIT_BACKEND=rdt-cli |
Configuration file example:
# ~/.agent-reach/config.yaml
youtube_backend: yt-dlp
twitter_backend: OpenCLI
reddit_backend: rdt-cli
Environment variable example:
export TWITTER_BACKEND=twitter-cli
export REDDIT_BACKEND=OpenCLI
Critical behavior: Overrides are prefix-safe. The name twitter would match twitter-cli and move it to the front. However, a non-matching override like twitter_backend: nonexistent is silently ignored—preserving the original backends order rather than breaking the channel with a dead backend search.
Tracking the Active Backend
After check() completes successfully, the winning backend name is stored in Channel.active_backend. This attribute:
- Is reset to
Noneat the start of everycheck()call to prevent stale state. - Appears in
agent_reach.doctor.check_allreports for operational visibility. - Can be inspected programmatically to verify which backend actually served the request.
channel = TwitterChannel()
channel.check(config) # probes in order, selects first viable backend
print(channel.active_backend) # e.g., "OpenCLI"
Summary
- Backend declaration: Channels define ordered
backendslists; position 0 is the default preference. - Override injection:
ordered_backends()checks<channel>_backendconfig key or<CHANNEL>_BACKENDenv var to reprioritize. - Safe fallback: Unknown overrides are ignored; partial matches work via prefix check.
- Probe execution:
check()iterates candidates, validates each, and selects"ok">"warn"> fail. - State tracking:
active_backendreflects the selected backend and resets per health check.
Frequently Asked Questions
How do I force Agent Reach to use a specific backend for Twitter?
Set either twitter_backend: OpenCLI in ~/.agent-reach/config.yaml or run export TWITTER_BACKEND=OpenCLI before execution. The ordered_backends() method will move OpenCLI to the front of Twitter's probe list.
What happens if my backend override is misspelled?
Agent Reach ignores unrecognized overrides entirely. The original backends list order is preserved, allowing normal fallback behavior rather than failing with a missing backend error.
Can I use partial backend names in overrides?
Yes. The ordered_backends() method matches prefixes, so twitter_backend: twitter successfully prioritizes twitter-cli while still allowing full name specificity when multiple backends share a prefix.
Why does active_backend reset during each health check?
The check() method explicitly sets self.active_backend = None at entry to prevent stale backend state from previous invocations. This ensures accurate reporting of which backend actually passed the current probe cycle.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →