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

> Easily add a new platform channel to Agent Reach with this step-by-step guide. Learn to implement the channel contract and integrate seamlessly.

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

---

**To add a new platform channel to Agent Reach, create a Python module in `agent_reach/channels/` that subclasses the abstract `Channel` base class, implements the required contract methods (`can_handle`, `read`, `search`, `check`), defines the metadata attributes (`name`, `description`, `backends`, `tier`), and exports the class in [`agent_reach/channels/__init__.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/__init__.py) so the core router can discover it.**

Agent Reach is an extensible open-source framework that unifies internet platforms through a modular channel architecture. Each platform is encapsulated as a channel that adheres to a strict contract defined in the base class. This guide walks you through the exact steps to add a new platform channel to Agent Reach while satisfying the Channel contract requirements as implemented in the source code.

## Understanding the Channel Contract

The **Channel contract** is defined in [`agent_reach/channels/base.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/base.py). Any concrete channel must inherit from the `Channel` abstract base class and provide the following attributes and methods:

- **`name`** (`str`): Short identifier used in configuration files and CLI commands (e.g., `"twitter"` or `"github"`).
- **`description`** (`str`): Human-readable description displayed by the CLI.
- **`backends`** (`List[str]`): Ordered list of candidate backend implementations (CLI tools, APIs, etc.).
- **`tier`** (`int`): Difficulty level where `0` = zero-config, `1` = needs a free key, and `2` = requires full setup.
- **`can_handle(url)`** → `bool`: Returns `True` when the provided URL belongs to this platform.
- **`read(url)`** → `str`: Fetches content from a specific URL (post, video, repository).
- **`search(query)`** → `str`: Executes a search operation on the platform.
- **`check(config=None)`** → `(status, msg)`: Probes available backends, sets `self.active_backend`, and returns health status.

The base class provides helper methods like `ordered_backends(config)` which respects user configuration overrides while maintaining the default priority order.

## Step-by-Step Implementation Guide

Follow these steps to create a fully functional platform channel that adheres to the Agent Reach architecture.

### 1. Create the Channel Module

Create a new file named after your platform in snake_case:

```python

# agent_reach/channels/new_platform.py

```

### 2. Import the Base Class and Utilities

Import the abstract base class and any probing utilities needed for backend detection:

```python
from .base import Channel
from agent_reach.probe import probe_command
import subprocess

```

### 3. Define the Subclass and Metadata

Subclass `Channel` and define the required class attributes:

```python
class NewPlatformChannel(Channel):
    name = "newplatform"
    description = "New Platform – read posts and search content"
    backends = ["new-cli", "new-api"]  # Priority order

    tier = 1  # Requires free API key

```

### 4. Implement `can_handle`

Define URL detection logic to determine if a given URL belongs to your platform:

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

```

### 5. Implement `read`

Execute the read operation using the active backend:

```python
def read(self, url: str) -> str:
    cmd = [self.active_backend, "read", url, "--output", "yaml"]
    result = subprocess.run(cmd, capture_output=True, text=True)
    return result.stdout

```

### 6. Implement `search`

Implement search functionality similar to `read` but accepting a query string:

```python
def search(self, query: str) -> str:
    cmd = [self.active_backend, "search", query, "--output", "yaml"]
    result = subprocess.run(cmd, capture_output=True, text=True)
    return result.stdout

```

### 7. Implement `check` with Backend Probing

Probe each backend in order, set `self.active_backend` to the first working option, and return status. Follow the pattern from `TwitterChannel` in [`agent_reach/channels/twitter.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/twitter.py):

```python
def check(self, config=None):
    self.active_backend = None
    findings = []

    for backend in self.ordered_backends(config):
        if backend == "new-cli":
            probe = probe_command(
                "new-cli", 
                ["status"], 
                timeout=15, 
                package="new-cli"
            )
            if probe.status == "missing":
                continue
            if probe.ok:
                self.active_backend = backend
                return "ok", "new-cli fully available"
            if probe.status == "broken":
                findings.append((backend, "error", "new-cli installed but broken"))
            else:
                findings.append((backend, "warn", "new-cli config issue"))

    # Fallback logic

    for status in ("ok", "warn", "error"):
        for b, s, m in findings:
            if s == status:
                self.active_backend = b
                return s, m
    return "warn", "new-cli not installed"

```

### 8. Export in [`__init__.py`](https://github.com/Panniantong/Agent-Reach/blob/main/__init__.py)

Edit [`agent_reach/channels/__init__.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/__init__.py) to import the new channel so the core routing engine discovers it:

```python
from .new_platform import NewPlatformChannel

```

### 9. Verify Registration

Run the diagnostic command to confirm your channel registers correctly:

```bash
python -m agent_reach.cli doctor

```

Your new platform should appear in the output table with the status reported by your `check()` method.

## Working Channel Implementation Example

Here is a complete skeleton implementation combining all steps:

```python

# agent_reach/channels/new_platform.py

"""New Platform channel implementation for Agent Reach."""

from .base import Channel
from agent_reach.probe import probe_command
import subprocess


class NewPlatformChannel(Channel):
    name = "newplatform"
    description = "New Platform – read, search, and check content"
    backends = ["new-cli", "new-api"]
    tier = 1

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

    def read(self, url: str) -> str:
        cmd = [self.active_backend, "read", url, "--output", "yaml"]
        result = subprocess.run(cmd, capture_output=True, text=True)
        return result.stdout

    def search(self, query: str) -> str:
        cmd = [self.active_backend, "search", query, "--output", "yaml"]
        result = subprocess.run(cmd, capture_output=True, text=True)
        return result.stdout

    def check(self, config=None):
        self.active_backend = None
        findings = []

        for backend in self.ordered_backends(config):
            if backend == "new-cli":
                probe = probe_command(
                    "new-cli", 
                    ["status"], 
                    timeout=15, 
                    package="new-cli"
                )
                if probe.status == "missing":
                    continue
                if probe.ok:
                    self.active_backend = backend
                    return "ok", "new-cli fully available"
                if probe.status == "broken":
                    findings.append((backend, "error", "new-cli broken"))
                else:
                    findings.append((backend, "warn", "new-cli config issue"))

        for status in ("ok", "warn", "error"):
            for b, s, m in findings:
                if s == status:
                    self.active_backend = b
                    return s, m
        return "warn", "new-cli not installed"

```

Update the channels initialization file:

```python

# agent_reach/channels/__init__.py

from .base import Channel
from .twitter import TwitterChannel
from .github import GitHubChannel
from .new_platform import NewPlatformChannel  # Add this line

```

## 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 the four contract methods**: `can_handle(url)`, `read(url)`, `search(query)`, and `check(config)`.
- **Use `ordered_backends(config)`** to respect user configuration while maintaining backend priority.
- **Set `self.active_backend`** in the `check()` method to indicate which backend is operational.
- **Export the class** in [`agent_reach/channels/__init__.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/__init__.py) to register it with the core routing system.

## Frequently Asked Questions

### What is the Channel contract in Agent Reach?

The Channel contract is an abstract interface defined in [`agent_reach/channels/base.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/base.py) that requires implementing `can_handle`, `read`, `search`, and `check` methods, plus metadata attributes (`name`, `description`, `backends`, `tier`). This contract ensures all platforms integrate consistently with the CLI and routing system.

### How do I handle multiple backends in a new channel?

Define an ordered list of backend strings in the `backends` class attribute. In the `check()` method, iterate through `self.ordered_backends(config)` and test each backend using `probe_command()` or similar logic. Set `self.active_backend` to the first working backend and return appropriate status messages.

### Where does Agent Reach discover available channels?

The core routing system discovers channels through imports in [`agent_reach/channels/__init__.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/__init__.py). Each channel class must be imported there to be registered. Some versions also maintain a `CHANNELS` dictionary in [`agent_reach/core.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/core.py) that maps channel names to instances.

### What tier value should I use for my platform channel?

Use `tier=0` for zero-configuration channels that work immediately, `tier=1` for platforms requiring a free API key or simple authentication, and `tier=2` for platforms requiring complex setup or paid credentials. This value helps users understand the onboarding difficulty when running `agent_reach doctor`.