# Agent Reach Channel Contract: Requirements for Platform Implementations

> Understand the Agent Reach channel contract for platform implementations. Learn the essential requirements for defining attributes, implementing methods, and managing backends.

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

---

**The Agent Reach channel contract requires every platform implementation to inherit from the abstract `Channel` class, define four required class attributes (`name`, `description`, `backends`, `tier`), implement the abstract `can_handle()` method, and provide a `check()` method that sets `active_backend` and returns a status tuple.**

Agent Reach treats each supported Internet platform—such as YouTube, Twitter, or Reddit—as a **channel** that must follow a strict interface. This channel contract ensures uniform behavior across diverse platforms while allowing specific implementations to handle unique requirements. In the Panniantong/Agent-Reach repository, the contract is defined in [`agent_reach/channels/base.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/base.py) and enforced by the test suite in [`tests/test_channel_contracts.py`](https://github.com/Panniantong/Agent-Reach/blob/main/tests/test_channel_contracts.py).

## Required Class Attributes

Every concrete channel must define four class-level attributes. These are validated by the contract test suite to ensure consistency across the platform.

- **`name: str`** – A short identifier such as `"youtube"` or `"twitter"` that uniquely identifies the channel.
- **`description: str`** – A human-readable description of the platform's purpose.
- **`backends: List[str]`** – An ordered list of possible backends (e.g., `["yt-dlp"]` for YouTube).
- **`tier: int`** – Configuration difficulty indicator where `0` = zero-config, `1` = needs free API key, and `2` = needs full setup.

Additionally, the instance attribute **`active_backend`** must be initialized to `None` and populated during the `check()` lifecycle.

## Abstract Methods Every Channel Must Implement

### can_handle(url: str) -> bool

This abstract method determines whether the channel can process a given URL. It must return a boolean value indicating support. For example, the YouTube implementation in [`agent_reach/channels/youtube.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/youtube.py) checks if the URL contains `youtube.com` or `youtu.be` domain patterns.

### check(config=None) -> Tuple[str, str]

The `check()` method probes the environment to verify backend availability and initialization status. According to the contract in [`agent_reach/channels/base.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/base.py), this method must:

1. Set `self.active_backend` to the selected backend string or remain `None` if no backend is available.
2. Return a tuple of `(status, message)` where status is one of `"ok"`, `"warn"`, `"off"`, or `"error"`, accompanied by a human-readable message.

## Optional Capabilities: Read and Search

Beyond the required contract, channels may implement optional methods based on platform capabilities.

### read(url: str) -> str

Channels that expose raw page data may implement `read()` to return the full content of a URL, typically formatted as Markdown. The generic Web channel in [`agent_reach/channels/web.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/web.py) provides this capability as a fallback for arbitrary URLs.

### search(query: str, limit: int = 10) -> list

Searchable platforms implement `search()` to perform platform-wide queries. This method accepts a query string and limit parameter, returning a list of result dictionaries containing titles and URLs. Reference implementations appear in [`agent_reach/channels/v2ex.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/v2ex.py) for searchable community platforms.

## Utility Methods Provided by the Base Class

The base class provides **`ordered_backends(config=None) -> List[str]`**, which returns a permutation of the `backends` attribute. If the user specifies a `<channel>_backend` configuration override, that backend moves to the front of the list. Concrete implementations should use this method when selecting which backend to activate during `check()`.

## Contract Validation and Testing

The [`tests/test_channel_contracts.py`](https://github.com/Panniantong/Agent-Reach/blob/main/tests/test_channel_contracts.py) file enforces the channel contract through automated verification:

- Verifies every channel appears in the registry with unique, non-empty `name` and `description` values.
- Confirms `backends` is a list and `tier` is an integer in the set `{0, 1, 2}`.
- Validates that `active_backend` starts as `None` and becomes a string or `None` after `check()` execution.
- Asserts `ordered_backends()` returns a valid permutation and respects configuration overrides.
- Confirms `can_handle()` returns boolean values for representative URLs per channel.

## Implementation Example

Below is a minimal custom channel implementation that satisfies the contract:

```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"

```

To use any channel via the public API:

```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}")

```

For searchable channels, add the optional method:

```python
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.

    pass

```

## Summary

- **Inherit from `Channel`**: All platform implementations must subclass the abstract base class defined in [`agent_reach/channels/base.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/base.py).
- **Define four class attributes**: Every channel needs `name`, `description`, `backends`, and `tier`.
- **Implement `can_handle()`**: This abstract method must return a boolean indicating URL support.
- **Provide `check()`**: Must set `active_backend` and return a status tuple (`"ok"`, `"warn"`, `"off"`, or `"error"`) with a message.
- **Optional extensions**: Implement `read()` for content retrieval or `search()` for platform queries when applicable.
- **Test compliance**: The suite in [`tests/test_channel_contracts.py`](https://github.com/Panniantong/Agent-Reach/blob/main/tests/test_channel_contracts.py) validates all contract requirements.

## Frequently Asked Questions

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

The `Channel` class in [`agent_reach/channels/base.py`](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/base.py) defines `can_handle()` as an abstract method. If a concrete channel fails to implement it, Python will raise a `TypeError` at instantiation time, preventing the channel from being registered or used.

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

Channels call `ordered_backends()` (provided by the base class) to retrieve a prioritized list of backends. This method checks for a user-specified `<channel>_backend` configuration override and moves that backend to the front of the list. The `check()` method then probes these backends in order and sets `active_backend` to the first working option.

### Can I add a new platform without modifying the base Channel class?

Yes. The channel contract supports extension through inheritance. Create a new file in `agent_reach/channels/`, inherit from `Channel`, define the required attributes, and implement `can_handle()` and `check()`. Optional methods like `read()` or `search()` can be added based on platform capabilities. The test suite in [`tests/test_channel_contracts.py`](https://github.com/Panniantong/Agent-Reach/blob/main/tests/test_channel_contracts.py) will automatically discover and validate your new channel.

### What is the tier attribute used for?

The `tier` attribute signals the configuration complexity required to use the channel: `0` for zero-config setups that work immediately, `1` for channels requiring a free API key, and `2` for platforms needing full authentication or complex setup. This helps users understand activation requirements before attempting to use a specific channel.