# How to Add a New Platform Channel in Agent Reach: A Step-by-Step Guide

> Learn how to add a new platform channel in Agent Reach by subclassing Channel and registering your implementation. Follow our step by step guide for Agent Reach.

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

---

**To add a new platform channel in Agent Reach, subclass the `Channel` base 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 an instance in the `ALL_CHANNELS` list located in [`agent_reach/channels/__init__.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/__init__.py).**

Agent Reach (Panniantong/Agent-Reach) treats every supported internet platform as a **Channel**—a thin wrapper that informs the core routing logic how to validate URLs and verify dependencies. When you add a new platform channel in Agent Reach, you extend this abstraction layer without modifying the underlying router. This guide references the actual source code to demonstrate the exact implementation pattern used by built-in channels like YouTube and Reddit.

## Understanding the Channel Architecture

### The Channel Base Class

Every platform integration inherits from the abstract `Channel` class defined in [`agent_reach/channels/base.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/base.py). A concrete channel must define four class attributes:

- **`name`**: Unique identifier for the platform (e.g., `"youtube"`, `"twitter"`).
- **`description`**: Human-readable summary displayed in CLI help.
- **`backends`**: List of required binaries or API clients (e.g., `["yt-dlp"]`).
- **`tier`**: Integer indicating setup complexity (`0` for zero-config, `1` for API keys/simple binaries, `2` for cookie-based auth).

### Tier Levels and the Check Contract

The `check` method validates whether required upstream tools are installed. According to the source code in [`agent_reach/doctor.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/doctor.py), this method returns a tuple `(status, message)` where `status` is one of:

- **`ok`**: Dependency installed and functional.
- **`warn`**: Installed but potentially misconfigured.
- **`off`**: Not installed (user sees installation instructions).
- **`error`**: Unexpected failure during verification.

**Tier 0** channels like `WebChannel` work out-of-the-box. **Tier 1** channels require a free API key or simple binary (e.g., `TwitterChannel`). **Tier 2** channels need extra setup such as authentication via cookies.

## Step-by-Step Implementation

### 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)) and subclass `Channel`:

```python

# agent_reach/channels/myplatform.py

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

```

### Step 2: Implement the Core Interface Methods

You must implement `can_handle` and `check` to satisfy the base contract.

**`can_handle(self, url: str) -> bool`** determines if this channel should process a given URL:

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

```

**`check(self, config=None)`** verifies the backend binary exists:

```python
    def check(self, config=None):
        binary = shutil.which("mycli")
        if not binary:
            return "off", "mycli 未安装。安装：pip install mycli"
        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 已安装但无法运行"

```

### Step 3: Add Content Retrieval Methods (Optional)

If your platform supports reading content or searching, implement the optional methods following the signatures 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):

```python
    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

    def search(self, query: str) -> List[str]:
        """Return list of URLs matching the query."""
        # Implementation specific to platform API

        pass

```

### Step 4: Register the Channel

Import your class in [`agent_reach/channels/__init__.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/__init__.py) and append an instance to `ALL_CHANNELS`:

```python

# agent_reach/channels/__init__.py

from .myplatform import MyPlatformChannel  # Add import

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

    MyPlatformChannel(),  # Add instance

]

```

This registration makes the channel visible to the doctor check ([`agent_reach/doctor.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/doctor.py)) and the core router.

### Step 5: Testing and CLI Integration

Add tests in [`tests/test_myplatform_channel.py`](https://github.com/Panniantong/Agent-Reach/blob/main/tests/test_myplatform_channel.py) following the pattern in [`tests/test_twitter_channel.py`](https://github.com/Panniantong/Agent-Reach/blob/main/tests/test_twitter_channel.py):

```python
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):
    monkeypatch.setattr("shutil.which", lambda _: None)
    ch = get_channel("myplatform")
    status, _ = ch.check()
    assert status == "off"

```

Optionally update [`agent_reach/cli.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/cli.py) where the `--list-platforms` option prints `Channel.name` and `Channel.description` to ensure your platform appears in help output.

## Complete Working Example

Here is the full implementation of a Tier 1 channel wrapping a fictional `mycli` tool:

```python

# agent_reach/channels/myplatform.py

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

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

import shutil
import subprocess
from typing import List
from .base import Channel


class MyPlatformChannel(Channel):
    name = "myplatform"
    description = "MyPlatform – articles and comments"
    backends = ["mycli"]
    tier = 1

    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"
        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:
        binary = shutil.which("mycli")
        r = subprocess.run([binary, "read", url], capture_output=True,
                           encoding="utf-8", timeout=15)
        return r.stdout

    def search(self, query: str) -> List[str]:
        binary = shutil.which("mycli")
        r = subprocess.run([binary, "search", query], capture_output=True,
                           encoding="utf-8", timeout=15)
        return r.stdout.strip().split("\n")

```

Run the full test suite to verify your implementation:

```bash
pytest tests/ -v

```

## Summary

- **Subclass `Channel`** from [`agent_reach/channels/base.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/base.py) and set `name`, `description`, `backends`, and `tier`.
- **Implement `can_handle`** to route URLs to your channel based on domain or pattern matching.
- **Implement `check`** to return a status tuple verifying whether required binaries are installed.
- **Register the instance** in [`agent_reach/channels/__init__.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/__init__.py) by adding it to `ALL_CHANNELS`.
- **Add tests** in [`tests/test_channels.py`](https://github.com/Panniantong/Agent-Reach/blob/main/tests/test_channels.py) or a dedicated file to verify `can_handle` and `check` behavior.
- **Reference existing channels** like [`youtube.py`](https://github.com/Panniantong/Agent-Reach/blob/main/youtube.py) and [`reddit.py`](https://github.com/Panniantong/Agent-Reach/blob/main/reddit.py) for `read` and `search` implementation patterns.

## Frequently Asked Questions

### What methods are mandatory when adding a new platform channel in Agent Reach?

You must implement **`can_handle(self, url: str) -> bool`** and **`check(self, config=None)`**. The `can_handle` method tells the router which URLs your platform handles, while `check` verifies dependencies. Optional methods like `read` and `search` are only required if your platform supports content retrieval.

### How does Agent Reach validate that a channel's dependencies are installed?

The [`doctor.py`](https://github.com/Panniantong/Agent-Reach/blob/main/doctor.py) module iterates through `ALL_CHANNELS` and calls each channel's `check` method. This method returns a tuple `(status, message)` where status is `ok`, `warn`, `off`, or `error`. The doctor aggregates these results to report which platforms are ready for use.

### Where does Agent Reach store the list of available platform channels?

The canonical list lives in **[`agent_reach/channels/__init__.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/__init__.py)** as the `ALL_CHANNELS` list. This list contains instantiated channel objects and is imported by the CLI ([`agent_reach/cli.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/cli.py)) and the doctor ([`agent_reach/doctor.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/doctor.py)) to discover available platforms.

### Can I add a platform channel without modifying the core repository?

Currently, Agent Reach requires you to create a new file in `agent_reach/channels/` and import it into [`agent_reach/channels/__init__.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/__init__.py). There is no dynamic plugin loading mechanism; channels must be registered directly in the source tree to appear in `ALL_CHANNELS` and be recognized by the router.