# How to Upgrade Platform Backends When APIs Change in Agent Reach

> Learn to upgrade Agent Reach platform backends when APIs change by modifying backend priority, implementing probe methods, and verifying with the doctor command.

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

---

**When upstream APIs change in Agent Reach, you modify the channel's `backends` priority list, implement a `_check_<backend>()` probe method to validate the new CLI, and verify the upgrade using the built-in `doctor` command.**

Agent Reach isolates each internet platform behind a **channel** class that routes calls to one of several candidate **backends**. When an upstream API introduces breaking changes—such as new authentication flows, renamed CLI commands, or deprecations—you must follow a specific code-centric workflow to upgrade the platform backend. This process leverages health probes and priority-based routing defined in `agent_reach/channels/<platform>.py` to ensure seamless transitions.

## Understanding Channel-Based Backend Routing

Each platform lives in its own channel file (e.g., [`agent_reach/channels/twitter.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/twitter.py)). The channel declares an ordered list of candidate backends in the class attribute `backends`, which defines the **probe priority**—the first backend returning an "ok" status wins.

The base class in [`agent_reach/channels/base.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/base.py) provides the `ordered_backends()` helper (lines 45-59). This method respects a user-override config key (`<channel>_backend`) while iterating through the default list, allowing users to pin specific backends even after upgrades.

## Step 1: Update the Backend Priority List

Add the new backend identifier to the `backends` class attribute in the target channel. Insert it at the front of the list to give it highest priority, or place it according to your fallback strategy.

```python

# agent_reach/channels/twitter.py

class TwitterChannel(Channel):
    # New backend takes precedence over legacy options

    backends = ["new-twitter-cli", "twitter-cli", "OpenCLI", "bird CLI (legacy)"]
    # ...

```

## Step 2: Implement the Health Probe Method

Add a private method `_check_<backend>()` that uses `agent_reach.probe.probe_command` to execute a lightweight command and interpret its exit status. The method must return one of:
- `None` → backend not installed
- `("ok", msg)` → fully usable
- `("warn", msg)` → installed but misconfigured
- `("error", msg)` → installed but broken

```python
    def _check_new_twitter_cli(self):
        """Probe the new CLI introduced after the API change."""
        probe = probe_command(
            "new-twitter", ["health"], timeout=15, package="new-twitter-cli"
        )
        if probe.status == "missing":
            return None               # not installed

        if not probe.ok:
            return "error", f"new-twitter-cli broken: {probe.hint}"
        # New API prints "status: ready" on success

        if "status: ready" in probe.output:
            return "ok", "new-twitter-cli fully usable."
        return "warn", "new-twitter-cli installed but not ready."

```

## Step 3: Integrate the Probe into the Channel's Check Method

Inside `check()`, iterate over `self.ordered_backends(config)` and call the appropriate `_check_*` method for each backend. Collect results and select the first "ok" (falling back to "warn" then "error"). The generic loop in `TwitterChannel.check()` (lines 29-48) demonstrates this pattern:

```python
    def check(self, config=None):
        self.active_backend = None
        findings = []

        for backend in self.ordered_backends(config):
            if backend == "new-twitter-cli":
                result = self._check_new_twitter_cli()
            elif backend == "twitter-cli":
                result = self._check_twitter_cli()
            # ... existing branches unchanged

            
            if result and result[0] == "ok":
                self.active_backend = backend
                break

```

## Step 4: Adjust OpenCLI Backends (If Applicable)

For platforms relying on the generic **OpenCLI** backend, update the shared probing logic in [`agent_reach/backends/opencli.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/backends/opencli.py). When the OpenCLI API changes—such as adding new flags or output formats—modify the `opencli_status()` function (lines 99-115) to parse the new output:

```python
def opencli_status(timeout: int = 10) -> OpenCLIStatus:
    # ... unchanged version probe ...

    
    daemon_probe = probe_command(
        "opencli", ["daemon", "status"], timeout=timeout, package=OPENCLI_PACKAGE
    )
    output = daemon_probe.output if daemon_probe.ok else ""

    # New API adds "Extension: sleeping" - treat sleeping as usable

    for line in output.splitlines():
        line = line.strip().lower()
        if line.startswith("extension:"):
            if "sleeping" in line:
                st.extension_connected = True
            else:
                st.extension_connected = "connected" in line
    return st

```

## Step 5: Validate with Tests and the Doctor

Add test cases in `tests/` to validate backend detection, mocking `probe_command` as needed. The test suite for Twitter backends in [`tests/test_twitter_channel.py`](https://github.com/Panniantong/Agent-Reach/blob/main/tests/test_twitter_channel.py) (lines 29-46) provides a reference implementation.

Run the full test suite:

```bash
pytest -q

```

Then execute the doctor command to perform a final sanity check on all channels:

```bash
$ python -m agent_reach.cli doctor

# twitter → active backend: new-twitter-cli

```

The doctor aggregates channel checks and reports the `active_backend` set by each channel, confirming that your new backend is correctly detected and prioritized.

## Step 6: Bump the Version

Update the version string in three locations to publish a new release:
- [`pyproject.toml`](https://github.com/Panniantong/Agent-Reach/blob/main/pyproject.toml)
- [`agent_reach/__init__.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/__init__.py)
- CLI test files (as enumerated in the repository's [`CLAUDE.md`](https://github.com/Panniantong/Agent-Reach/blob/main/CLAUDE.md))

## Summary

- **Channel architecture** isolates platforms in `agent_reach/channels/<platform>.py` with an ordered `backends` list defining probe priority
- **Health probes** use `_check_<backend>()` methods with `probe_command` to validate CLI availability and functionality
- **Integration** requires updating the `check()` method to route to new probe methods when iterating through `ordered_backends()`
- **OpenCLI platforms** share probing logic in [`agent_reach/backends/opencli.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/backends/opencli.py) that may need updates for generic API changes
- **Verification** combines `pytest` unit tests with the `python -m agent_reach.cli doctor` command to confirm active backend selection

## Frequently Asked Questions

### How do I force Agent Reach to use a specific backend instead of auto-detecting?

Set the `<channel>_backend` configuration key to pin a specific backend. The `ordered_backends()` helper in [`agent_reach/channels/base.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/base.py) checks for this override before iterating through the default priority list, allowing users to bypass auto-detection even after upgrades.

### What happens if multiple backends are installed but one is broken?

The health-first probing system collects results from all candidate backends and selects the first "ok" status. If no backend returns "ok", it falls back to "warn" then "error". This ensures that a broken but installed backend never masks a fully functional one downstream in the priority list.

### Where should I add tests for a new backend?

Add test cases in `tests/test_<platform>_channel.py` that mock `probe_command` to simulate various installation states (missing, ok, warn, error). Reference [`tests/test_twitter_channel.py`](https://github.com/Panniantong/Agent-Reach/blob/main/tests/test_twitter_channel.py) (lines 29-46) for the standard pattern of validating backend detection without requiring actual CLI installations.

### When do I need to modify OpenCLI instead of the channel-specific files?

Update [`agent_reach/backends/opencli.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/backends/opencli.py) only when the upstream API change affects the generic OpenCLI interface itself—such as changes to the `daemon status` output format or new global flags. Platform-specific changes (like a new Twitter CLI) belong in the channel's `agent_reach/channels/<platform>.py` file.