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:

  • None if the backend is not installed or unavailable
  • A tuple (status, message) where status is "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 Channel in agent_reach/channels/base.py and declare available tools in an ordered backends list.
  • Probe helpers use probe_command from agent_reach/probe.py to normalize health checks, returning None, ("ok", msg), ("warn", msg), or ("error", msg).
  • The check() method iterates through ordered_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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →