# Why a Channel Shows Installed but Fails in Use in Agent-Reach

> Agent-Reach channels show installed but fail in use when probe_command checks fail. Discover why your channel is broken or misconfigured and how to fix it.

- Repository: [Pnant/Agent-Reach](https://github.com/Panniantong/Agent-Reach)
- Tags: troubleshooting
- Published: 2026-06-29

---

**In Agent-Reach, a channel reports "installed" when its CLI binary is found on the system PATH, but the framework's `probe_command` health check may still mark it as broken, unauthenticated, or misconfigured, preventing actual usage.**

Agent-Reach is a Python framework that abstracts platform-specific command-line tools into reusable **channels**. While the base `Channel` class quickly verifies binary presence using `shutil.which`, this surface-level check does not guarantee that the underlying tool can actually execute commands, authenticate, or return valid output. The disconnect between binary detection and runtime health explains why a channel can appear ready yet fail when invoked.

## How Agent-Reach Determines If a Channel Is Installed

The generic `Channel.check()` implementation in [`agent_reach/channels/base.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/base.py) (lines 61-70) performs an initial discovery check using Python's `shutil.which` function. This method scans the system PATH for the upstream command-line tool associated with the channel (e.g., `twitter-cli` for Twitter). If `shutil.which` returns a path, the channel is considered **installed** from the perspective of the doctor output.

However, this check only confirms that the executable file exists. It does not validate that the binary is runnable, that required environment variables are set, or that authentication tokens are configured.

## The Five Failure Modes Detected by probe_command

The real operational verification happens in [`agent_reach/probe.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/probe.py) (lines 80-94), where the `probe_command` function executes the discovered binary and classifies the result into five distinct states:

- **missing** — `shutil.which` returns `None`; the tool is not on PATH.
- **broken** — The binary exists but raises `FileNotFoundError` or `OSError` when executed, typically caused by stale virtual-environment shims or corrupted installations.
- **timeout** — The command runs but does not return within the allotted time, often indicating a locked or hanging process.
- **error** — The command returns a non-zero exit code (excluding 126/127, which indicate broken binaries). This usually signals missing authentication, invalid configuration, or runtime failures.
- **ok** — The command executes successfully and yields the expected output.

### Broken Executables

A **broken** status occurs when a file exists at the expected PATH location but cannot be launched. This commonly happens after Python upgrades leave stale shims in `bin/` directories, or when the binary's shebang points to a non-existent interpreter. The `probe_command` catches these cases with `FileNotFoundError` or `OSError` handling.

### Authentication and Configuration Errors

Even when a binary runs without crashing, it may return an **error** or **warn** status due to missing credentials. For example, `twitter-cli` may exit with code 0 but output `"not_authenticated"` if the `TWITTER_AUTH_TOKEN` environment variable is unset.

## Real-World Example: TwitterChannel Authentication Failures

The `TwitterChannel` implementation in [`agent_reach/channels/twitter.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/twitter.py) (lines 66-84) demonstrates how a channel can be installed yet unusable. When `probe_command` locates `twitter-cli` successfully, the channel probes it with `["status"]` arguments. If the tool reports it is not authenticated, the channel interprets this as a **warn** status rather than **ok**, returning a message like `"twitter-cli 已安装但未认证..."` (installed but not authenticated).

This means the binary is present and executable, but the channel cannot function because runtime requirements are unmet.

## Backend Selection Logic

The `Channel.check()` method uses a two-pass selection algorithm, visible in [`agent_reach/channels/twitter.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/twitter.py) (lines 43-51):

1. **First pass**: Selects the first backend returning `"ok"` status.
2. **Second pass**: If no `"ok"` backend exists, selects the first `"warn"` backend as the active backend.
3. **Fallback**: If only `"error"` or `"timeout"` results remain, the channel reports `"error"` with aggregated diagnostic messages.

Consequently, a channel may show as **installed** (binary found) but select a `"warn"` backend, meaning it will report a warning status to the user rather than being fully operational. When the doctor command lists the channel as present, it reflects the binary detection, not the operational readiness.

## Practical Code Examples

The following examples demonstrate how to inspect channel health and interpret the various failure modes:

```python
from agent_reach.channels.twitter import TwitterChannel
from agent_reach.config import Config

# Load default config (could be empty)

cfg = Config().load()

tw = TwitterChannel()
status, msg = tw.check(cfg)   # Probes each backend

print(status, msg)

# → "warn" "twitter-cli 已安装但未认证…"

```

Simulating a broken installation with a stale virtual-environment shim:

```python

# Simulate a broken installation (e.g. stale venv)

import shutil, subprocess

# Suppose `twitter` binary points to a non‑existent interpreter

# probe_command will return ProbeResult("broken", hint=...)

```

Checking a channel with missing backend tools:

```python

# A channel that only has a missing backend

from agent_reach.channels.youtube import YouTubeChannel
yt = YouTubeChannel()
print(yt.check())   # → ("warn", "YouTube CLI 未安装。安装方式：...")

```

## Summary

- **Binary presence ≠ functionality**: The `shutil.which` check in [`agent_reach/channels/base.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/base.py) only confirms the executable exists on PATH.
- **Five distinct states**: `probe_command` classifies health as missing, broken, timeout, error, or ok.
- **Authentication gaps**: Tools like `twitter-cli` may be installed but unauthenticated, triggering a `"warn"` status in [`agent_reach/channels/twitter.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/twitter.py).
- **Two-pass selection**: Channels prioritize `"ok"` backends, fall back to `"warn"`, and only report `"error"` when no viable option exists.
- **Doctor output limitation**: The [`agent_reach/doctor.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/doctor.py) summary may list channels as "installed" based on binary discovery alone, masking underlying runtime failures.

## Frequently Asked Questions

### Why does Agent-Reach say my channel is installed but I can't use it?

Agent-Reach considers a channel installed when `shutil.which` finds the binary on your PATH, but this does not verify that the tool can run successfully. If the binary is broken (stale shim), unauthenticated (missing API tokens), or misconfigured (wrong environment variables), `probe_command` will detect these issues and prevent the channel from functioning while still reporting the binary as present.

### What's the difference between "broken" and "error" in probe_command?

A **broken** status means the binary exists but cannot be executed—typically due to missing interpreters or corrupted files detected via `FileNotFoundError` or `OSError`. An **error** status means the binary runs but returns a non-zero exit code (other than 126/127), indicating runtime failures like authentication errors or invalid configuration. Both prevent channel usage but require different fixes: reinstalling the tool versus configuring credentials.

### How do I fix a "warn" status on a channel?

A `"warn"` status indicates the backend binary is present and executable, but operational requirements are unmet. Check the specific message returned by `Channel.check()`—for example, the Twitter channel warns when `twitter-cli` reports `"not_authenticated"`. Set the required environment variables (e.g., `TWITTER_AUTH_TOKEN`) or configuration files, then rerun the check.

### Where does the "installed" check happen in the codebase?

The initial installation check occurs in [`agent_reach/channels/base.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/base.py) (lines 61-70), where the generic `Channel.check()` method uses `shutil.which` to locate the command-line tool. The deeper health verification that determines actual usability is implemented in [`agent_reach/probe.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/probe.py) (lines 80-94) within the `probe_command` function.