# How to Add a New Platform Channel to Agent Reach: Complete Developer Guide

> Learn how to add a new platform channel to Agent Reach. This developer guide explains subclassing the Channel class, implementing methods, and registering your channel.

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

---

**To add a new platform channel to Agent Reach, subclass the `Channel` abstract base class from [`agent_reach/channels/base.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/base.py), implement the required `can_handle()` and `check()` methods, and register the 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 treats every supported internet platform as a **Channel**—a modular wrapper that enables the core routing logic to interact with specific sites. When you add a new platform channel to Agent Reach, you create a Python class that defines how the system identifies URLs, validates dependencies, and optionally extracts content. This architecture allows the doctor diagnostic tool and the CLI router to discover and interact with platforms dynamically.

## Understanding the Channel Base Class and Tier System

Every channel inherits from the `Channel` class defined in [`agent_reach/channels/base.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/base.py). The base class establishes a contract that concrete implementations must fulfill to integrate with the routing system.

The architecture uses a **tier system** to categorize setup complexity:

- **Tier 0** – Zero configuration required (e.g., `WebChannel` works out-of-the-box)
- **Tier 1** – Requires a free API key or a simple binary installation
- **Tier 2** – Needs extra setup such as authentication via cookies or complex configuration

The `check` method must return a tuple `(status, message)` where `status` is one of `ok`, `warn`, `off`, or `error`. The doctor module in [`agent_reach/doctor.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/doctor.py) aggregates these results to inform users about the health of their environment.

### Required Methods: can_handle and check

Every channel must implement two core methods:

- **`can_handle(self, url: str) -> bool`**: Returns `True` if the channel recognizes and can process the given URL
- **`check(self, config=None) -> Tuple[str, str]`**: Validates that required upstream tools are installed and configured, returning a status code and human-readable message

### Optional Content Methods: read and search

If your platform supports content extraction, implement:
- **`read(self, url: str) -> str`**: Returns article text as plain Markdown
- **`search(self, query: str) -> List[str]`**: Returns a list of relevant URLs

Reference implementations exist 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).

## Creating a New Platform Channel

### Step 1: Implement the Channel Class

Create a new file in `agent_reach/channels/` named after your platform (e.g., [`myplatform.py`](https://github.com/Panniantong/Agent-Reach/blob/main/myplatform.py)). Subclass `Channel` and define the required attributes and methods:

```python

# agent_reach/channels/myplatform.py

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

import shutil
import subprocess
from typing import List, Tuple
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) -> Tuple[str, str]:
        binary = shutil.which("mycli")
        if not binary:
            return "off", "mycli not installed. Install with: pip install mycli"
        
        try:
            result = subprocess.run(
                [binary, "--version"], 
                capture_output=True, 
                encoding="utf-8", 
                timeout=5
            )
            if result.returncode == 0:
                return "ok", "mycli ready"
        except Exception:
            pass
        return "warn", "mycli installed but not responding"

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

    def search(self, query: str) -> List[str]:
        """Search for content and return list of URLs."""
        binary = shutil.which("mycli")
        result = subprocess.run(
            [binary, "search", query], 
            capture_output=True, 
            encoding="utf-8", 
            timeout=15
        )
        return [line.strip() for line in result.stdout.splitlines() if line.strip()]

```

### Step 2: Register in ALL_CHANNELS

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 the `ALL_CHANNELS` list. This registration makes the channel visible to the doctor check and the core router:

```python

# agent_reach/channels/__init__.py

from typing import List
from .base import Channel
from .web import WebChannel
from .twitter import TwitterChannel
from .youtube import YouTubeChannel
from .myplatform import MyPlatformChannel  # Add this import

ALL_CHANNELS: List[Channel] = [
    WebChannel(),
    TwitterChannel(),
    YouTubeChannel(),
    MyPlatformChannel(),  # Add this instance

]

```

## Testing Your Channel

Add tests to verify your implementation handles URLs correctly and responds appropriately when dependencies are missing. Create a dedicated test file following the pattern in [`tests/test_twitter_channel.py`](https://github.com/Panniantong/Agent-Reach/blob/main/tests/test_twitter_channel.py):

```python

# tests/test_myplatform_channel.py

import pytest
from agent_reach.channels import get_channel


def test_myplatform_can_handle():
    ch = get_channel("myplatform")
    assert ch is not None
    assert ch.can_handle("https://myplatform.com/article/123") is True
    assert ch.can_handle("https://other-site.com/post/456") is False


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

    monkeypatch.setattr("shutil.which", lambda x: None)
    ch = get_channel("myplatform")
    status, message = ch.check()
    assert status == "off"
    assert "not installed" in message


def test_myplatform_check_ok(monkeypatch):
    # Mock successful binary detection

    def mock_which(cmd):
        if cmd == "mycli":
            return "/usr/bin/mycli"
        return None
    
    def mock_run(*args, **kwargs):
        class Result:
            returncode = 0
            stdout = "mycli v1.0.0"
            stderr = ""
        return Result()
    
    monkeypatch.setattr("shutil.which", mock_which)
    monkeypatch.setattr("subprocess.run", mock_run)
    
    ch = get_channel("myplatform")
    status, message = ch.check()
    assert status == "ok"

```

Run the full test suite to ensure no regressions:

```bash
pytest tests/ -v

```

## Updating CLI Documentation (Optional)

To display your channel in `agent-reach --help` output or the `--list-platforms` option, update [`agent_reach/cli.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/cli.py) where the platform listing logic reads from `Channel.name` and `Channel.description` attributes. Most CLI commands automatically discover channels through the `ALL_CHANNELS` registry, but explicit help text may need manual updates.

## 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` attributes
- **Implement `can_handle()`** to route URLs to your channel based on domain or pattern matching
- **Implement `check()`** to return `(status, message)` tuples that the doctor uses to report dependency health
- **Optionally implement `read()` and `search()`** to enable content extraction capabilities
- **Register the instance** in [`agent_reach/channels/__init__.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/__init__.py) by importing the class and adding it to `ALL_CHANNELS`
- **Write tests** in `tests/` that verify URL handling and dependency checking behavior

## Frequently Asked Questions

### What is the minimum implementation required to add a new platform channel?

You must subclass `Channel` in a new file under `agent_reach/channels/`, implement `can_handle(self, url)` to identify your platform's URLs, and implement `check(self, config)` to return a status tuple. Then import and instantiate your class in [`agent_reach/channels/__init__.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/__init__.py), adding it to the `ALL_CHANNELS` list. The `read` and `search` methods are optional and only needed if your platform supports content extraction.

### How does the tier system affect channel behavior?

The `tier` attribute (0, 1, or 2) categorizes setup complexity for documentation purposes but does not change runtime logic. Tier 0 channels require no configuration, Tier 1 channels need binaries or API keys, and Tier 2 channels require complex authentication. The doctor command in [`agent_reach/doctor.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/doctor.py) reports these tiers to users when diagnosing their environment.

### Why is my channel not appearing in the doctor check output?

The doctor only reports channels registered in `ALL_CHANNELS` inside [`agent_reach/channels/__init__.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/__init__.py). Verify that you imported your channel class and appended an instance to the list. Also ensure your `check()` method returns a valid status string (`ok`, `warn`, `off`, or `error`) rather than raising an exception, as uncaught errors prevent the doctor from aggregating results.

### Can a single channel support multiple backends?

Yes. Set the `backends` attribute to a list of strings, such as `["yt-dlp", "youtube-api"]`, and implement `check()` to verify that at least one backend is available. The `check` method should return `ok` if any backend works, or cycle through alternatives to report specific missing dependencies. This pattern appears in the YouTube channel implementation where multiple extraction tools are supported.