# Channel Contract for Platform Module Implementation in Agent Reach: Complete Technical Guide

> Understand the Agent Reach channel contract, a base class protocol for platform modules. Learn essential attributes and methods for URL routing and content retrieval in this technical guide.

- Repository: [Pnant/Agent-Reach](https://github.com/Panniantong/Agent-Reach)
- Tags: architecture
- Published: 2026-07-15

---

**The channel contract in Agent Reach is an abstract base class protocol defined in [`agent_reach/channels/base.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/base.py) that requires every platform module to implement specific class attributes (`name`, `description`, `backends`, `tier`, `active_backend`) and methods (`can_handle`, `read`, `search`, `check`) to enable automatic URL routing and content retrieval.**

Agent Reach is an open-source framework that abstracts external platforms—such as YouTube, Twitter, and GitHub—into pluggable **channels**. The **channel contract for platform module implementation** defines the strict interface that every channel must follow to integrate with the core routing system, ensuring consistent behavior across diverse upstream tools.

## Core Requirements of the Channel Contract

### Required Class Attributes

Every concrete channel must define five class-level attributes (lines 32‑38 in [`agent_reach/channels/base.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/base.py)):

- **`name`**: String identifier for the channel
- **`description`**: Human-readable summary of the platform
- **`backends`**: Ordered list of possible upstream tools or CLIs
- **`tier`**: Configuration complexity level indicating setup difficulty
- **`active_backend`**: Set dynamically by the `check` method to store the verified working tool

### Abstract Methods Every Channel Must Implement

The `Channel` base class declares three abstract methods that subclasses must override:

**`can_handle(url: str) -> bool`** (lines 40‑44): Determines if the channel can process a given URL. The core router iterates through all channels and selects the first one returning `True` for the provided URL.

**`read(url: str) -> Any`**: Retrieves full content from the URL (e.g., fetching a YouTube video page or tweet thread). This method is documented in the project conventions ([`CLAUDE.md`](https://github.com/Panniantong/Agent-Reach/blob/main/CLAUDE.md)) and must be implemented by every concrete channel.

**`search(query: str) -> List[Any]`**: Executes platform-specific searches and returns a list of results. Like `read`, this is required by the project conventions and forwards queries to the active backend.

### Backend Verification and Selection

The base class provides two critical methods for managing upstream tool availability:

**`check(config: Optional[Mapping] = None) -> Tuple[str, str]`** (lines 61‑70): Probes the environment to verify that the required CLI binary or API is installed and functional. Returns a status tuple containing `'ok'`, `'warn'`, `'off'`, or `'error'`, plus a human-readable message. Channels may override this for deeper probing logic.

**`ordered_backends(config: Optional[Mapping] = None) -> List[str]`** (lines 45‑59): Returns the list of candidate backends, applying any user overrides (e.g., `<channel>_backend` configuration values) to customize tool priority.

## How the Contract Works in Practice

The Agent Reach CLI relies on this contract to route requests through three distinct phases:

1. **Discovery**: When a URL is provided, the system iterates over all registered channel classes and calls `can_handle`. The first channel returning `True` handles the request.

2. **Backend Selection**: The selected channel invokes `ordered_backends` to respect user preferences, then runs `check` on each candidate until one succeeds, setting `self.active_backend`.

3. **Execution**: With a verified backend, the CLI calls either `read(url)` or `search(query)`, which forwards the request to the upstream tool (such as `yt-dlp` for YouTube or `twurl` for Twitter).

This architecture decouples the high-level routing logic in [`agent_reach/core.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/core.py) from platform-specific implementations.

## Implementing a Custom Platform Channel

### Minimal Channel Implementation

To create a new platform module, inherit from `Channel` and implement the required attributes and methods:

```python
from agent_reach.channels.base import Channel
from typing import Any, List, Optional, Mapping, Tuple

class MyCoolPlatform(Channel):
    name = "mycool"
    description = "MyCoolPlatform – fetches cool data"
    backends = ["mycool-cli"]          # Preferred CLI for this platform

    tier = 1                           # Needs a free API key

    def can_handle(self, url: str) -> bool:
        return url.startswith("https://mycool.example.com/")

    def read(self, url: str) -> Any:
        from subprocess import run, PIPE
        result = run([self.active_backend, "fetch", url], capture_output=True, text=True)
        return result.stdout

    def search(self, query: str) -> List[Any]:
        from subprocess import run, PIPE
        result = run([self.active_backend, "search", query], capture_output=True, text=True)
        return result.stdout.splitlines()

```

### Real-World Example: Twitter Channel

The `Twitter` channel in [`agent_reach/channels/twitter.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/twitter.py) demonstrates the contract in production:

```python
class Twitter(Channel):
    name = "twitter"
    description = "Twitter / X"
    backends = ["twurl", "twine"]
    tier = 2

    def can_handle(self, url: str) -> bool:
        return "twitter.com" in url or "x.com" in url

    def read(self, url: str):
        # Calls the chosen backend to fetch a tweet or thread

        ...

    def search(self, query: str):
        # Uses the backend to run a Twitter search

        ...

    # Inherits the default check() which probes the backend binary

```

The Twitter channel adheres to the same contract: it defines the required class attributes, implements `can_handle`, `read`, and `search`, and relies on the base `check` logic.

## Summary

- The **channel contract** is defined by the abstract `Channel` class in [`agent_reach/channels/base.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/base.py).
- All channels must define `name`, `description`, `backends`, `tier`, and `active_backend` attributes.
- Concrete implementations must override `can_handle()`, `read()`, and `search()` methods.
- The `check()` method verifies upstream tool availability, while `ordered_backends()` applies user configuration overrides.
- The contract enables automatic URL routing and decouples platform logic from core system architecture.

## Frequently Asked Questions

### What happens if a channel doesn't implement can_handle?

If a concrete channel class fails to implement the `can_handle` method, Python will raise a `TypeError` when the class is instantiated, as `can_handle` is an abstract method defined in the `Channel` base class (lines 40‑44 in [`agent_reach/channels/base.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/base.py)). This prevents incomplete channels from being registered in the system.

### How does Agent Reach choose which backend to use for a channel?

The system calls `ordered_backends()` to retrieve the priority list of available tools, then iterates through them calling `check()` on each. The first backend returning an `'ok'` status becomes the `active_backend` for that channel instance. Users can override the priority by setting a `<channel>_backend` configuration option.

### Can a channel support multiple backends simultaneously?

While a channel instance only has one `active_backend` at a time, the `backends` class attribute is an ordered list allowing fallback options. If the primary CLI tool is not installed, the `check` method automatically attempts the next backend in the list until finding a functional option.

### Where is the channel contract documented outside the source code?

Project conventions are explicitly documented in [`CLAUDE.md`](https://github.com/Panniantong/Agent-Reach/blob/main/CLAUDE.md) at the repository root, which states that every channel must implement `can_handle`, `read`, `search`, and `check`. The canonical implementation reference remains [`agent_reach/channels/base.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/base.py) according to the Panniantong/Agent-Reach source code.