# How to Add a New Platform Channel to Agent Reach: The BaseChannel Contract Guide

> Learn how to add a new platform channel to Agent Reach by subclassing the BaseChannel contract. Implement key methods and register your channel for seamless integration.

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

---

**To add a new platform channel to Agent Reach, create a subclass of the abstract `Channel` class defined in [`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, define the required metadata attributes, and register the instance in the channel registry.**

Agent Reach is an extensible agent framework that treats every supported platform (YouTube, Twitter, Reddit, etc.) as a **channel** implementing a strict interface. When you add a new platform channel to Agent Reach, you must adhere to the **BaseChannel contract**—a minimal set of requirements enforced by the abstract base class and validated by contract tests.

## Understanding the BaseChannel Contract

The contract is defined by the `Channel` abstract base class (ABC) in **[`agent_reach/channels/base.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/base.py)**. Every new channel must satisfy four core requirements to integrate with Agent Reach's doctor command, health probes, and automatic discovery system.

### Required Class Attributes

Set these attributes on your subclass to define static metadata:

- **`name`** – Unique identifier for the platform (e.g., `"youtube"`, `"twitter"`)
- **`description`** – Human-readable summary of capabilities
- **`backends`** – List of supported backend strings (e.g., `["yt-dlp"]`, `["gallery-dl"]`)
- **`tier`** – Configuration complexity level (`0` for zero-config, `1` for API key required, `2` for full setup)

### The can_handle Method

Implement `can_handle(self, url: str) -> bool` to detect if a given URL belongs to your platform. The implementation typically uses `urllib.parse.urlparse` to check the domain, as seen in the Twitter channel implementation.

### The check Method

Implement `check(self, config=None) -> (str, str)` to probe available backends and return a status tuple. The method must:

1. Probe each backend in order using `self.ordered_backends(config)`
2. Return a status from the set `{"ok", "warn", "off", "error"}`
3. Return a human-readable message
4. Set `self.active_backend` to the first working backend string (or `None` if none work)

### The active_backend Attribute

After `check()` runs successfully, `active_backend` must contain a string naming the functional backend. This attribute is verified by [`tests/test_channel_contracts.py`](https://github.com/Panniantong/Agent-Reach/blob/main/tests/test_channel_contracts.py) to ensure consistent behavior across all channels.

## Step-by-Step Implementation Guide

Follow these steps to add a new platform channel to Agent Reach while respecting the contract.

### 1. Create the Channel Module

Create a new Python file under `agent_reach/channels/`, for example [`myplatform.py`](https://github.com/Panniantong/Agent-Reach/blob/main/myplatform.py).

```python

# agent_reach/channels/myplatform.py

from urllib.parse import urlparse
from agent_reach.probe import probe_command
from .base import Channel

```

### 2. Implement Required Class Attributes

Define the metadata that Agent Reach uses for discovery and documentation:

```python
class MyPlatformChannel(Channel):
    name = "myplatform"
    description = "MyPlatform – read/search support"
    backends = ["myplatform-cli"]
    tier = 1  # 0 = zero-config, 1 = needs key, 2 = needs full setup

```

### 3. Implement URL Detection with can_handle()

Add the `can_handle` method to identify URLs belonging to your platform:

```python
    def can_handle(self, url: str) -> bool:
        """Return True iff the URL belongs to MyPlatform."""
        return urlparse(url).netloc.lower().endswith("myplatform.com")

```

### 4. Implement Health Checking with check()

The `check` method probes each backend and sets `active_backend`. Follow the pattern from [`youtube.py`](https://github.com/Panniantong/Agent-Reach/blob/main/youtube.py) and [`twitter.py`](https://github.com/Panniantong/Agent-Reach/blob/main/twitter.py) for handling missing, broken, timeout, and ok states:

```python
    def check(self, config=None):
        """Probe the CLI and set active_backend."""
        self.active_backend = None
        findings = []

        for backend in self.ordered_backends(config):
            if backend == "myplatform-cli":
                result = self._check_cli()
            else:
                continue
            if result is None:
                continue  # not installed

            findings.append((backend, *result))

        # Prefer "ok" over "warn"

        for wanted in ("ok", "warn"):
            for backend, status, message in findings:
                if status == wanted:
                    self.active_backend = backend
                    return status, message

        return ("error", "\n".join(m for _, _, m in findings)) if findings else ("off", "myplatform-cli 未安装。")

    def _check_cli(self):
        """Run a harmless command to verify health."""
        probe = probe_command(
            "myplatform-cli", 
            ["--version"], 
            timeout=10, 
            package="myplatform-cli"
        )
        if probe.status == "missing":
            return None
        if probe.status in {"broken", "timeout"}:
            return "error", f"myplatform-cli 不能执行。\n{probe.hint}"
        return "ok", "myplatform-cli 可用"

```

### 5. Register Your Channel

Edit **[`agent_reach/channels/__init__.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/__init__.py)** to import and register your channel:

```python

# agent_reach/channels/__init__.py

from .myplatform import MyPlatformChannel

# Append to ALL_CHANNELS

ALL_CHANNELS.append(MyPlatformChannel())

```

This makes your channel visible to `get_all_channels()` and the doctor command.

### 6. Validate with Contract Tests

Run the contract tests to verify your implementation satisfies the interface:

```bash
pytest tests/test_channel_contracts.py

```

These tests validate that `can_handle` returns booleans, `check` returns valid status strings, and `active_backend` is properly set.

## Complete Working Example

Here is the complete skeleton for a new channel implementation:

```python

# agent_reach/channels/myplatform.py

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

"""MyPlatform – example channel implementation."""

from urllib.parse import urlparse
from agent_reach.probe import probe_command
from .base import Channel


class MyPlatformChannel(Channel):
    name = "myplatform"
    description = "MyPlatform – read/search support"
    backends = ["myplatform-cli"]
    tier = 1

    def can_handle(self, url: str) -> bool:
        """Return True iff the URL belongs to MyPlatform."""
        return urlparse(url).netloc.lower().endswith("myplatform.com")

    def check(self, config=None):
        """Probe the CLI and set active_backend."""
        self.active_backend = None
        findings = []

        for backend in self.ordered_backends(config):
            if backend == "myplatform-cli":
                result = self._check_cli()
            else:
                continue
            if result is None:
                continue
            findings.append((backend, *result))

        for wanted in ("ok", "warn"):
            for backend, status, message in findings:
                if status == wanted:
                    self.active_backend = backend
                    return status, message

        return ("error", "\n".join(m for _, _, m in findings)) if findings else ("off", "myplatform-cli 未安装。")

    def _check_cli(self):
        """Run a harmless command (e.g. `--version`) to verify health."""
        probe = probe_command(
            "myplatform-cli", 
            ["--version"], 
            timeout=10, 
            package="myplatform-cli"
        )
        if probe.status == "missing":
            return None
        if probe.status in {"broken", "timeout"}:
            return "error", f"myplatform-cli 不能执行。\n{probe.hint}"
        return "ok", "myplatform-cli 可用"

```

You can test your implementation manually:

```python
>>> from agent_reach.channels import get_all_channels
>>> ch = next(c for c in get_all_channels() if c.name == "myplatform")
>>> ch.can_handle("https://example.myplatform.com/path")
True
>>> ch.check()
('off', 'myplatform-cli 未安装。')

```

## Summary

- **Subclass `Channel`** from [`agent_reach/channels/base.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/base.py) to create a new platform channel
- **Define metadata** (`name`, `description`, `backends`, `tier`) as class attributes
- **Implement `can_handle()`** to detect platform URLs using `urllib.parse`
- **Implement `check()`** to probe backends, return status in `{"ok","warn","off","error"}`, and set `active_backend`
- **Register** your channel in [`agent_reach/channels/__init__.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/__init__.py) by appending to `ALL_CHANNELS`
- **Validate** using `pytest tests/test_channel_contracts.py` to ensure contract compliance

## Frequently Asked Questions

### What is the tier attribute used for in Agent Reach channels?

The `tier` attribute indicates the configuration complexity required to use the channel. Tier `0` means zero-config (works immediately), tier `1` requires an API key or simple credentials, and tier `2` requires full setup with multiple dependencies. This helps the doctor command prioritize channels and inform users about setup requirements.

### How does the ordered_backends method work when adding a new platform channel?

The `ordered_backends(config)` method, inherited from the base `Channel` class, returns backends in priority order while respecting user overrides. If a user specifies a preferred backend in the config (e.g., `myplatform_backend: "alternative-cli"`), that backend appears first in the list. This ensures your `check()` method probes user-preferred backends before falling back to defaults, providing consistent behavior across all Agent Reach channels.

### Why must check() return specific status strings like 'ok' and 'warn'?

The `check()` method must return specific status strings—`"ok"`, `"warn"`, `"off"`, or `"error"`—because the doctor command in `agent_reach.doctor` relies on these values to generate health reports. The doctor aggregates results from all channels and formats them based on these status codes. Deviating from this contract would break the health reporting interface and cause the contract tests in [`tests/test_channel_contracts.py`](https://github.com/Panniantong/Agent-Reach/blob/main/tests/test_channel_contracts.py) to fail.

### Where are channel contract tests defined in Agent Reach?

Contract tests are defined in **[`tests/test_channel_contracts.py`](https://github.com/Panniantong/Agent-Reach/blob/main/tests/test_channel_contracts.py)**. These tests validate that every channel in `ALL_CHANNELS` properly implements the `can_handle` method, returns valid status strings from `check()`, and manages the `active_backend` attribute correctly. Running these tests ensures that new channels integrate properly with the discovery and health-check systems without manual verification.