# How to Add a Custom Channel for a New Platform in Agent Reach

> Learn to add a custom channel for a new platform in Agent Reach. Subclass Channel, implement required methods, and register your custom channel for enhanced platform integration.

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

---

**To add a custom channel for a new platform in Agent Reach, subclass the `Channel` class from [`agent_reach/channels/base.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/base.py), implement the `can_handle` and `check` methods, and register your instance in the `ALL_CHANNELS` list inside [`agent_reach/channels/__init__.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/__init__.py).**

Agent Reach is an open-source routing engine that abstracts internet platforms into pluggable channels. Adding support for a new platform requires creating a Python class that defines how the system recognizes URLs, validates dependencies, and optionally reads content. This guide walks through the exact implementation patterns used in the Panniantong/Agent-Reach repository.

## Understanding the Channel Architecture

### The Base Channel Contract

In [`agent_reach/channels/base.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/base.py), the abstract `Channel` class defines the interface every platform must implement. At minimum, your custom channel must provide:

- **`name`**: Short identifier string
- **`description`**: Human-readable summary
- **`backends`**: List of required binaries or APIs
- **`tier`**: Integer (0, 1, or 2) indicating setup complexity
- **`can_handle(url)`**: Returns boolean if the URL belongs to this platform
- **`check(config)`**: Returns tuple `(status, message)` where status is `ok`, `warn`, `off`, or `error`

### Configuration Tiers

The tier system helps users understand setup requirements:

- **Tier 0**: Zero-config channels like `WebChannel` that work immediately.
- **Tier 1**: Requires free API keys or simple binaries (e.g., `TwitterChannel`).
- **Tier 2**: Needs complex authentication such as cookies or OAuth flows.

## Step-by-Step Implementation Guide

### Step 1: Create the Channel Class

Create a new file in `agent_reach/channels/` (e.g., [`myplatform.py`](https://github.com/Panniantong/Agent-Reach/blob/main/myplatform.py)). Inherit from `Channel` and implement the core identification logic:

```python

# file: agent_reach/channels/myplatform.py

# -*- coding: utf-8 -*-

"""MyPlatform — read and search via `mycli`."""

import shutil
import subprocess
from .base import Channel


class MyPlatformChannel(Channel):
    name = "myplatform"
    description = "MyPlatform – articles and comments"
    backends = ["mycli"]
    tier = 1                           # requires a binary, no extra auth

    def can_handle(self, url: str) -> bool:
        from urllib.parse import urlparse
        domain = urlparse(url).netloc.lower()
        return "myplatform.com" in domain

    def check(self, config=None):
        binary = shutil.which("mycli")
        if not binary:
            return "off", "mycli 未安装。安装：pip install mycli"
        # Simple sanity check – ask the binary for its version

        try:
            r = subprocess.run([binary, "--version"], capture_output=True,
                               encoding="utf-8", timeout=5)
            if r.returncode == 0:
                return "ok", "mycli 已就绪"
        except Exception:
            pass
        return "warn", "mycli 已安装但无法运行"

    def read(self, url: str) -> str:
        """Return the article text as plain Markdown."""
        binary = shutil.which("mycli")
        r = subprocess.run([binary, "read", url], capture_output=True,
                           encoding="utf-8", timeout=15)
        return r.stdout

```

### Step 2: Implement Optional Content Methods

If your platform supports reading posts or searching content, implement `read(self, url: str) -> str` and `search(self, query: str) -> List[str]` following the signatures used by existing channels. Reference the implementations in [`agent_reach/channels/youtube.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/youtube.py) and [`agent_reach/channels/reddit.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/reddit.py) for exact patterns.

### Step 3: Register the Channel

Open [`agent_reach/channels/__init__.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/__init__.py) and import your class. Add an instantiated object to the `ALL_CHANNELS` list:

```python

# file: agent_reach/channels/__init__.py

from .myplatform import MyPlatformChannel      # <-- add this import

ALL_CHANNELS: List[Channel] = [
    # ... existing channels ...

    MyPlatformChannel(),                       # <-- add the instance

]

```

### Step 4: Update CLI Documentation (Optional)

To appear in `agent-reach --help` output, modify [`agent_reach/cli.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/cli.py) where the `--list-platforms` option iterates through registered channels and prints `Channel.name` and `Channel.description`.

### Step 5: Add Tests

Create a test file following the pattern in [`tests/test_twitter_channel.py`](https://github.com/Panniantong/Agent-Reach/blob/main/tests/test_twitter_channel.py). Verify both `can_handle` logic and the `check` method's behavior when dependencies are present or missing:

```python

# file: tests/test_myplatform_channel.py

def test_myplatform_can_handle():
    from agent_reach.channels import get_channel
    ch = get_channel("myplatform")
    assert ch is not None
    assert ch.can_handle("https://myplatform.com/article/123")

def test_myplatform_check_off(monkeypatch):
    # Force shutil.which to return None → simulate missing binary

    monkeypatch.setattr("shutil.which", lambda _: None)
    ch = get_channel("myplatform")
    status, _ = ch.check()
    assert status == "off"

```

### Step 6: Validate with the Doctor

Run `python -m agent_reach.doctor` or `agent-reach doctor` to execute the `check` method across all channels. The doctor aggregates results from [`agent_reach/doctor.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/doctor.py) to inform users of missing dependencies.

## Summary

- **Subclass `Channel`** from [`agent_reach/channels/base.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/base.py) to define your platform wrapper.
- **Implement `can_handle`** to route URLs correctly and **`check`** to validate dependencies.
- **Register in `ALL_CHANNELS`** inside [`agent_reach/channels/__init__.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/__init__.py) to make the channel visible to the router.
- **Use tiers** (0, 1, or 2) to communicate setup complexity to users.
- **Write tests** verifying URL handling and dependency checks before submitting.

## Frequently Asked Questions

### What is the minimum implementation required for a new channel in Agent Reach?

You must subclass `Channel` and implement four attributes (`name`, `description`, `backends`, `tier`) plus two methods: `can_handle` to identify URLs belonging to your platform, and `check` to return a `(status, message)` tuple indicating whether required tools are installed. The `read` and `search` methods are optional.

### How does the `check` method communicate dependency status?

The `check` method returns a tuple where the first element is a string status: `ok` (ready), `warn` (installed but issues detected), `off` (not installed), or `error` (exception occurred). The second element is a human-readable message displayed by the doctor in [`agent_reach/doctor.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/doctor.py).

### Where do I register a new channel so Agent Reach recognizes it?

Import your channel class in [`agent_reach/channels/__init__.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/__init__.py) and append an instantiated object to the `ALL_CHANNELS` list. This registry is consumed by the core router and the doctor command to discover available platforms.

### What is the difference between Tier 1 and Tier 2 channels?

**Tier 1** channels require only a free API key or simple binary installation (e.g., `TwitterChannel`). **Tier 2** channels need additional setup such as authentication via cookies, OAuth flows, or complex configuration files. Tier 0 channels require zero configuration and work immediately.