# Agent Reach Channel Contract: Required Interface for Platform Implementations

> Understand the Agent Reach channel contract. Implement the abstract Channel class, required attributes, and specific methods for successful platform integration. Learn the essentials for seamless execution.

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

---

**Every platform implementation in Agent Reach must inherit 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) and implement four required class attributes, the abstract `can_handle()` method, and a `check()` method that initializes the `active_backend` attribute.**

The Panniantong/Agent-Reach repository treats each supported Internet platform—such as YouTube, Twitter, and Reddit—as a **channel**. To ensure consistent behavior across diverse platforms, the codebase enforces a strict **channel contract** through an abstract base class and automated validation via [`tests/test_channel_contracts.py`](https://github.com/Panniantong/Agent-Reach/blob/main/tests/test_channel_contracts.py).

## Core Requirements of the Channel Contract

All concrete channel implementations must satisfy three categories of requirements: mandatory class attributes, abstract methods, and runtime state management.

### Mandatory Class Attributes

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

- **`name: str`** – A short identifier string (e.g., `"youtube"` or `"twitter"`) used for registry lookups.
- **`description: str`** – A human-readable description of the platform.
- **`backends: List[str]`** – An ordered list of possible back-end implementations (e.g., `["yt-dlp"]` for YouTube).
- **`tier: int`** – An integer defining setup complexity: `0` for zero-config, `1` for requiring a free API key, and `2` for full manual setup.

### The `active_backend` Attribute

Channels must initialize an instance attribute **`active_backend`** to `None`. The `check()` method is responsible for setting this to a string value from the `backends` list after probing the environment, indicating which back-end is actually serving the channel.

### Abstract Methods

The `Channel` base class defines two critical methods that subclasses must implement:

**`can_handle(url: str) -> bool`**  
This method determines whether the channel can process a given URL. It must return a boolean value and is used by the router to delegate URLs to the appropriate platform handler.

**`check(config=None) -> Tuple[str, str]`**  
This method probes the runtime environment, validates back-end availability, sets `active_backend`, and returns a tuple containing:
- A status string: `"ok"`, `"warn"`, `"off"`, or `"error"`
- A human-readable message describing the state

## Optional Capabilities

Beyond the core contract, channels may implement additional methods to expose platform-specific features:

**`read(url: str) -> str`**  
Returns the full content of a URL, typically formatted as Markdown. This is only required for channels that expose raw page data, such as the generic Web channel in [`agent_reach/channels/web.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/web.py).

**`search(query: str, limit: int = 10) -> list`**  
Performs a platform-wide search and returns a list of result dictionaries. Searchable channels like V2EX and Xueqiu implement this method in their respective files (e.g., [`agent_reach/channels/v2ex.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/v2ex.py)).

## Base Class Utilities

The base class provides **`ordered_backends(config=None) -> List[str]`**, which returns a permutation of the `backends` attribute. If the configuration contains a `<channel>_backend` override, that back-end is moved to the front of the returned list, allowing user preferences to take precedence without modifying the channel code.

## Contract Enforcement via Automated Testing

The [`tests/test_channel_contracts.py`](https://github.com/Panniantong/Agent-Reach/blob/main/tests/test_channel_contracts.py) suite validates that every channel adheres to the contract:

- Verifies that `name` and `description` are unique, non-empty strings.
- Confirms that `backends` is a list and `tier` is an integer in `{0, 1, 2}`.
- Checks that `active_backend` exists, starts as `None`, and after `check()` is either `None` or a valid string from `backends`.
- Asserts that `ordered_backends()` returns a permutation of `backends` and respects configuration overrides.
- Validates that `can_handle()` returns a boolean for representative URLs.

## Practical Implementation Examples

### Minimal Channel Implementation

The following example demonstrates a minimal valid channel for a fictional *Foo* platform:

```python

# agent_reach/channels/foo.py

from .base import Channel

class FooChannel(Channel):
    name = "foo"
    description = "Foo platform – example channel"
    backends = ["foo-cli"]
    tier = 1                     # needs a free API key

    def can_handle(self, url: str) -> bool:
        return "foo.com" in url.lower()

    def check(self, config=None):
        # Simple probe – pretend the CLI is always present

        self.active_backend = self.backends[0]
        return "ok", "foo-cli is ready"

```

This class fulfills the contract by inheriting from `Channel`, supplying all required attributes, implementing `can_handle()`, and providing a `check()` method that sets `active_backend`.

### Consuming Channels via the Public API

All channels expose a uniform interface that calling code can rely on regardless of the underlying platform:

```python
from agent_reach.channels import get_all_channels

# Find the YouTube channel and ask it to handle a URL

yt = next(ch for ch in get_all_channels() if ch.name == "youtube")
assert yt.can_handle("https://youtu.be/dQw4w9WgXcQ")

status, message = yt.check()
print(f"status={status}, message={message}, backend={yt.active_backend}")

```

### Implementing Search Functionality

For platforms that support search, implement the optional method as shown in channels like V2EX:

```python

# In a searchable channel (e.g., V2EX) you would add:

def search(self, query: str, limit: int = 10) -> list:
    # Perform HTTP request to the platform's search endpoint

    # Return a list of dicts with title, url, etc.

    ...

```

## Summary

- The **Agent Reach 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 implementations must provide **`name`**, **`description`**, **`backends`**, and **`tier`** class attributes.
- The **`can_handle()`** method is abstract and must return a boolean to indicate URL support.
- The **`check()`** method must probe the environment, set **`active_backend`**, and return a status tuple.
- **`read()`** and **`search()`** are optional methods for content retrieval and platform search.
- The **[`tests/test_channel_contracts.py`](https://github.com/Panniantong/Agent-Reach/blob/main/tests/test_channel_contracts.py)** suite automatically validates compliance for all registered channels.

## Frequently Asked Questions

### What happens if a channel does not implement `can_handle()`?

Since `can_handle()` is declared as an abstract method in the `Channel` base class, any concrete subclass that fails to implement it will raise a `TypeError` at instantiation time, preventing incomplete implementations from being registered in the channel registry.

### Is the `read()` method required for all platforms?

No, `read()` is optional. Only channels that expose raw page content—such as the generic Web channel in [`agent_reach/channels/web.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/web.py)—need to implement this method. Platforms like YouTube typically use transcription or API-specific methods instead of raw HTML reading.

### How does the test suite validate the `tier` attribute?

The [`tests/test_channel_contracts.py`](https://github.com/Panniantong/Agent-Reach/blob/main/tests/test_channel_contracts.py) file asserts that every channel has a `tier` attribute with an integer value in the set `{0, 1, 2}`, ensuring consistent categorization of platforms by their setup complexity (zero-config, free key required, or full setup required).

### Can developers override the default backend selection?

Yes, the base class provides `ordered_backends()` which checks the configuration for a `<channel>_backend` key. If present, that back-end is moved to the front of the returned list, allowing users to override defaults without modifying the channel implementation.