# How to Debug Unavailable Channels in Agent-Reach Doctor Output

> Fix unavailable channels in Agent-Reach doctor output. Learn to inspect channel checks, verify backend binaries, and configure credentials in config.yaml.

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

---

**To debug unavailable channels in the Agent-Reach doctor output, inspect the specific channel's `check()` method implementation, verify the backend binary exists and executes correctly using the probe module, and ensure required credentials are configured in [`config.yaml`](https://github.com/Panniantong/Agent-Reach/blob/main/config.yaml) or environment variables.**

The `python -m agent_reach.cli doctor` command generates a comprehensive health report for every channel configured in Agent-Reach, marking unavailable channels with a red **X** when their `check()` method returns a non-ok status or raises an exception. Understanding how the Doctor aggregates these results from [`agent_reach/doctor.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/doctor.py) and the underlying channel implementations allows you to systematically diagnose and resolve backend connectivity issues.

## How the Doctor Command Evaluates Channels

The Doctor orchestrates health checks through four distinct phases defined in [`agent_reach/doctor.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/doctor.py):

1. **Channel Discovery**: Lines 12-20 call `get_all_channels()` to retrieve every concrete subclass of `BaseChannel` from the registry.

2. **Safe Execution**: Lines 21-27 wrap each channel's `check()` call in a `try/except` block. If a channel raises an exception, the Doctor captures it and stores `status="error"` alongside the exception message.

3. **Result Aggregation**: Lines 28-34 construct a result dictionary containing `status`, `message`, `tier`, `backends`, and the runtime-selected `active_backend`.

4. **Report Rendering**: Lines 47-99 in `format_report()` group channels by tier and apply Rich styling. A red **X** appears for any channel where `status` is `"off"` or `"error"`.

## Why Channels Appear as Unavailable

Channels display as unavailable when their `check()` implementation detects environmental or configuration issues:

### Missing External Tools

When a required binary (like `yt-dlp` for YouTube or `twurl` for Twitter) is not installed, the channel's `check()` method returns `status="off"` with a message indicating "未安装" (not installed). This check typically uses `shutil.which()` combined with a lightweight probe via [`agent_reach/probe.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/probe.py).

### Misconfigured Credentials

If required API keys, cookies, or login tokens are absent, `check()` returns `"warn"` (yellow **!**) with messages like "需配置/登录" (needs configuration/login). These credentials are retrieved via `Config.get_secret()` from [`agent_reach/config.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/config.py).

### Probe Failures

Channels that rely on external backends call `agent_reach.probe.probe_command` to verify executability. If the probe fails, the Doctor records `status="error"` with the exception message, such as "体检异常：<error>".

### Stale Active Backend

When a check fails, lines 24-26 of [`doctor.py`](https://github.com/Panniantong/Agent-Reach/blob/main/doctor.py) clear the `active_backend` field to prevent caching invalid backends. This ensures that previously successful checks don't leak stale data into error reports.

### Configuration File Permissions

While not affecting channel status directly, lines 15-24 of [`doctor.py`](https://github.com/Panniantong/Agent-Reach/blob/main/doctor.py) add security warnings (red lines) if `~/.agent-reach/config.yaml` has overly permissive file permissions.

## Step-by-Step Debugging Workflow

Follow this systematic approach to resolve unavailable channels:

### 1. Enable Verbose Output

Run the Doctor with the `--verbose` flag to see raw result dictionaries before formatting:

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

```

This exposes the exact `status` and `message` values for each channel.

### 2. Inspect the Channel's Check Implementation

Open the specific channel file indicated by the error. For example, examine [`agent_reach/channels/youtube.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/youtube.py) for YouTube issues. Look for the `check()` method signature:

```python
def check(self, config):
    # Probes yt-dlp binary, verifies execution, sets active_backend

```

### 3. Verify Backend Binary Availability

Confirm the binary exists and is executable:

```bash
which yt-dlp
yt-dlp --version

```

Channels use both `shutil.which()` and `probe_command` to validate that binaries can actually execute, not just exist in PATH.

### 4. Run the Probe Manually

Test the backend directly using the probe module:

```bash
python -m agent_reach.probe yt-dlp --version

```

If this fails, the error message matches what the Doctor reports.

### 5. Check Backend Overrides

Verify you haven't set an invalid backend override via environment variables. Each channel respects a `<CHANNEL>_BACKEND` override based on `ordered_backends` in [`agent_reach/channels/base.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/base.py) (lines 45-60):

```bash
echo $YOUTUBE_BACKEND  # Should be empty or a valid backend name

```

### 6. Validate Credentials

Ensure required secrets exist in `~/.agent-reach/config.yaml` or as environment variables. The `check()` method calls `Config.get_secret()` to retrieve these values.

### 7. Re-run the Doctor

After fixing the underlying issue, execute the Doctor again to confirm the channel displays a green **✅**.

## Practical Code Examples

### Reproducing a Failing Probe

Test backend availability programmatically:

```python
from agent_reach.probe import probe_command

# The YouTube channel declares yt-dlp as its primary backend

result = probe_command(["yt-dlp", "--version"])
print(result)  # => ('error', 'yt-dlp: command not found')

```

### Overriding Backend Selection

Force a specific backend for debugging:

```python
import os
os.environ["REDDIT_BACKEND"] = "praw"  # Forces 'praw' to the front

from agent_reach.doctor import check_all
from agent_reach.config import Config

report = check_all(Config())
print(report["reddit"])

# => {'status': 'ok', 'active_backend': 'praw', ...}

```

### Quick CLI Health Check

Programmatically run the Doctor from Python:

```bash
python - <<'PY'
from agent_reach.doctor import check_all, format_report
from agent_reach.config import Config
print(format_report(check_all(Config())))
PY

```

## Key Source Files Reference

- **[`agent_reach/doctor.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/doctor.py)** (lines 12-99): Orchestrates channel checks and formats the Rich report.
- **[`agent_reach/channels/base.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/base.py)** (lines 45-60): Defines the `Channel` abstract class, `ordered_backends`, and default `check()`.
- **[`agent_reach/probe.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/probe.py)**: Executes lightweight commands to confirm backend health.
- **[`agent_reach/config.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/config.py)**: Handles YAML/ENV configuration and secret storage via `get_secret()`.
- **`agent_reach/channels/<platform>.py`**: Platform-specific `check()` implementations (e.g., [`youtube.py`](https://github.com/Panniantong/Agent-Reach/blob/main/youtube.py), [`twitter.py`](https://github.com/Panniantong/Agent-Reach/blob/main/twitter.py)).
- **[`agent_reach/cli.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/cli.py)**: Exposes the `doctor` sub-command and implements the `--verbose` flag.

## Summary

- **The Doctor never crashes**; it captures all exceptions in [`agent_reach/doctor.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/doctor.py) and reports them as status strings.
- **Red X marks** indicate `status="off"` (missing dependencies) or `"error"` (exceptions) returned by a channel's `check()` method.
- **Debug systematically** by enabling verbose output, inspecting the specific channel's implementation, and manually running `probe_command`.
- **Verify environment** by checking binary availability, backend overrides in `ordered_backends`, and credentials in [`config.yaml`](https://github.com/Panniantong/Agent-Reach/blob/main/config.yaml).

## Frequently Asked Questions

### What does the red X mean in the Agent-Reach Doctor output?

The red **X** indicates a channel is unavailable because its `check()` method returned a status of `"off"` (missing dependencies) or `"error"` (exception raised during check). This appears in the formatted report generated by `format_report()` in [`agent_reach/doctor.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/doctor.py) when the status tuple contains these values instead of `"ok"`.

### How do I see the exact error message for a failing channel?

Run the Doctor with the `--verbose` flag implemented in [`agent_reach/cli.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/cli.py). This prints the raw result dictionary containing the specific `message` field before Rich table formatting, revealing the exact exception text, missing binary notification, or configuration warning emitted by the channel's `check()` implementation.

### Why does a channel show as unavailable when the binary is in my PATH?

The Doctor uses `probe_command` from [`agent_reach/probe.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/probe.py) to verify the binary can actually execute, not merely exist. Stale virtual environment shims or permission issues may cause `which` to locate a file that cannot run. Delete the invalid shim or reinstall the tool to ensure the binary exits cleanly when invoked.

### Can I force the Doctor to use a specific backend for testing?

Yes. Set the `<CHANNEL>_BACKEND` environment variable (e.g., `YOUTUBE_BACKEND=yt-dlp`) to override the `ordered_backends` list defined in [`agent_reach/channels/base.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/base.py). This forces that backend to the front of the evaluation queue, useful for testing specific implementations without modifying configuration files.