How to Add a New Backend to an Existing Agent Reach Channel
Adding a new backend to an existing Agent Reach channel requires updating the backends attribute list, implementing a probe helper that returns status tuples, and extending the channel's check() method to evaluate the new backend during the selection loop.
Agent Reach abstracts every platform (Twitter, Reddit, YouTube, etc.) as a channel class that inherits from Channel in agent_reach/channels/base.py. Each channel declares an ordered list of available backends, and the framework probes each one until it finds a working tool. By following the framework's probe-based architecture, you can integrate new CLI tools into existing channels without modifying the core routing logic.
The Three-Step Process for Adding a New Backend
Agent Reach discovers and activates backends through a cascading health check. To add a new backend to an existing Agent Reach channel, you must modify the channel class definition, implement a verification helper, and wire that helper into the existing check loop.
Step 1: Update the Channel's backends Attribute
Locate the channel class in its respective file (e.g., agent_reach/channels/twitter.py). Identify the backends class attribute, which defines an ordered list of backend names. Insert your new backend identifier into this list according to your priority preference.
- Prepend the new backend to the list to give it highest priority
- Append it to serve as a fallback option
class TwitterChannel(Channel):
name = "twitter"
description = "Twitter/X 推文"
# New backend inserted before existing ones for higher priority
backends = ["tweet-cli", "twitter-cli", "OpenCLI", "bird CLI (legacy)"]
tier = 1
Step 2: Implement a Probe Helper Method
Create a private method (conventionally named _check_<backend_name>()) that verifies the tool is installed, executable, and authenticated. Use agent_reach.probe.probe_command to normalize error handling for missing binaries, timeouts, and broken installations.
The probe must return:
Noneif the backend is not installed or unavailable- A tuple
(status, message)wherestatusis"ok","warn", or"error"
def _check_tweet_cli(self):
"""Probe tweet-cli – returns None if missing, otherwise (status, message)."""
probe = probe_command(
"tweet", ["status"], timeout=15, retries=1, package="tweet-cli"
)
if probe.status == "missing":
return None # not installed
if not probe.ok:
return "error", "tweet-cli cannot execute – " + probe.hint
# Assume tweet-cli prints "authenticated: true" on success
if "authenticated: true" in probe.output:
return "ok", "tweet-cli fully usable (search, read, timeline)."
return "warn", "tweet-cli installed but not authenticated."
Step 3: Extend the check() Method Logic
Modify the channel's check() method to call your new probe helper when iterating over ordered_backends(config). Preserve the existing pattern: a for loop that gathers results, then selects the first backend reporting "ok" or "warn" status.
def check(self, config=None):
self.active_backend = None
findings = []
for backend in self.ordered_backends(config):
if backend == "tweet-cli":
result = self._check_tweet_cli()
elif backend == "twitter-cli":
result = self._check_twitter_cli()
elif backend == "OpenCLI":
result = self._check_opencli()
elif backend == "bird CLI (legacy)":
result = self._check_bird()
else:
continue
if result is None:
continue
findings.append((backend, *result))
# Keep the generic selection logic unchanged (first ok, then warn)
for wanted in ("ok", "warn"):
for backend, status, message in findings:
if status == wanted:
self.active_backend = backend
return status, message
return ("error", "\n".join(m for _, _, m in findings)) if findings else \
("warn", "No Twitter backend installed.")
Complete Implementation Example: Integrating tweet-cli into TwitterChannel
Here is the complete implementation showing how to add a fictional tweet-cli backend to the existing TwitterChannel in agent_reach/channels/twitter.py:
from agent_reach.channels.base import Channel
from agent_reach.probe import probe_command
class TwitterChannel(Channel):
name = "twitter"
description = "Twitter/X 推文"
# New backend inserted before existing ones (higher priority)
backends = ["tweet-cli", "twitter-cli", "OpenCLI", "bird CLI (legacy)"]
tier = 1
def _check_tweet_cli(self):
"""Probe tweet-cli – returns None if missing, otherwise (status, message)."""
probe = probe_command(
"tweet", ["status"], timeout=15, retries=1, package="tweet-cli"
)
if probe.status == "missing":
return None # not installed
if not probe.ok:
return "error", "tweet-cli cannot execute – " + probe.hint
# Assume tweet-cli prints "authenticated: true" on success
if "authenticated: true" in probe.output:
return "ok", "tweet-cli fully usable (search, read, timeline)."
return "warn", "tweet-cli installed but not authenticated."
def check(self, config=None):
self.active_backend = None
findings = []
for backend in self.ordered_backends(config):
if backend == "tweet-cli":
result = self._check_tweet_cli()
elif backend == "twitter-cli":
result = self._check_twitter_cli()
elif backend == "OpenCLI":
result = self._check_opencli()
elif backend == "bird CLI (legacy)":
result = self._check_bird()
else:
continue
if result is None:
continue
findings.append((backend, *result))
# Keep the generic selection logic unchanged (first ok, then warn)
for wanted in ("ok", "warn"):
for backend, status, message in findings:
if status == wanted:
self.active_backend = backend
return status, message
return ("error", "\n".join(m for _, _, m in findings)) if findings else \
("warn", "No Twitter backend installed.")
Backend Configuration and User Overrides
The base class method ordered_backends() in agent_reach/channels/base.py automatically respects user preferences through configuration keys. Users can override the automatic selection by setting:
- A configuration key named
<channel>_backend(e.g.,twitter_backend) - An environment variable named
<CHANNEL>_BACKEND(e.g.,TWITTER_BACKEND)
When present, these overrides move the specified backend to the front of the ordered list, ensuring it is probed first. This design allows fallback behavior without code duplication while giving users explicit control over tool selection.
Summary
- Agent Reach channels inherit from
Channelinagent_reach/channels/base.pyand declare available tools in an orderedbackendslist. - Probe helpers use
probe_commandfromagent_reach/probe.pyto normalize health checks, returningNone,("ok", msg),("warn", msg), or("error", msg). - The
check()method iterates throughordered_backends(config), probes each backend, and activates the first one reporting"ok"or"warn"status. - User overrides via configuration keys or environment variables allow runtime backend selection without modifying source code.
Frequently Asked Questions
What happens if the new backend is not installed?
If your probe helper returns None (typically when probe.status == "missing"), the framework skips that backend and continues to the next one in the ordered_backends list. The channel will only report an error if no backends return a valid status.
How do I force a specific backend to be used?
Users can force a specific backend by setting a configuration key named <channel>_backend or an environment variable <CHANNEL>_BACKEND. According to the ordered_backends() implementation in agent_reach/channels/base.py, this moves the specified backend to the front of the priority list.
What is the difference between "warn" and "error" probe statuses?
Return "error" when the backend binary exists but cannot execute properly (e.g., crashes or broken dependencies). Return "warn" when the tool is installed and runnable but lacks required authentication or optional features. The framework prefers "ok" backends, falls back to "warn" if no "ok" exists, and only shows "error" if no working backends are found.
Can I create a channel that supports only the new backend?
Yes. Create a new class inheriting from Channel, set backends = ["mycli"], and implement a single probe helper. The check() method can be simplified since it only needs to evaluate one backend, as shown in the MyPlatformChannel pattern in the Agent Reach codebase.
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 →