How to Add a New Platform Channel to Agent Reach: A Step-by-Step Guide
To add a new platform channel to Agent Reach, subclass the Channel base class from agent_reach/channels/base.py, implement the can_handle and check methods, optionally define read and search functionality, and register your instance in the ALL_CHANNELS list within agent_reach/channels/__init__.py.
Agent Reach (Panniantong/Agent-Reach) treats every supported internet platform as a Channel—a modular wrapper that tells the core routing logic which URLs it can handle and how to validate required dependencies. Adding support for a new platform requires implementing a minimal contract and registering your component in the channel registry. This guide provides the exact file paths, method signatures, and implementation patterns used in the source code.
Understanding the Channel Architecture
Every channel in Agent Reach inherits from the abstract Channel class defined in agent_reach/channels/base.py. The architecture requires two core methods:
can_handle(self, url: str) -> bool: Determines if this channel should process a given URL based on domain matching or pattern recognition.check(self, config=None): Validates that required upstream tools (binaries, APIs, or credentials) are installed and configured. Returns a tuple(status, message)wherestatusis one ofok,warn,off, orerror.
Optional methods include read(self, url: str) -> str for content extraction and search(self, query: str) -> List[str] for platform-specific search functionality, as implemented in agent_reach/channels/youtube.py and agent_reach/channels/reddit.py.
Step 1: Create the Channel Class
Create a new file in agent_reach/channels/ (e.g., myplatform.py) and subclass Channel. Define the class attributes and implement can_handle:
# agent_reach/channels/myplatform.py
import shutil
from urllib.parse import urlparse
from .base import Channel
class MyPlatformChannel(Channel):
name = "myplatform"
description = "MyPlatform – articles and comments"
backends = ["mycli"] # Required binaries or tools
tier = 1 # 0=no config, 1=API key/binary, 2=complex auth
def can_handle(self, url: str) -> bool:
domain = urlparse(url).netloc.lower()
return "myplatform.com" in domain
Step 2: Implement the Check Method
The check method validates dependencies and returns a status tuple. The tier attribute indicates setup complexity: tier 0 works out-of-the-box (like WebChannel), tier 1 requires a free API key or simple binary, and tier 2 needs extra setup like cookie authentication.
def check(self, config=None):
binary = shutil.which("mycli")
if not binary:
return "off", "mycli 未安装。安装:pip install mycli"
try:
import subprocess
r = subprocess.run([binary, "--version"], capture_output=True,
encoding="utf-8", timeout=5)
if r.returncode == 0:
return "ok", "mycli 已就绪"
except Exception:
pass
return "warn", "mycli 已安装但无法运行"
The doctor check located in agent_reach/doctor.py aggregates these results across all channels to report system health.
Step 3: Add Content Access Methods (Optional)
If your platform supports reading content or searching, implement the standard signatures:
def read(self, url: str) -> str:
"""Return article text as plain Markdown."""
import subprocess
binary = shutil.which("mycli")
r = subprocess.run([binary, "read", url], capture_output=True,
encoding="utf-8", timeout=15)
return r.stdout
def search(self, query: str) -> List[str]:
"""Return list of URLs matching the query."""
# Implementation specific to platform API
pass
Step 4: Register in the Channel Registry
Import your class in agent_reach/channels/__init__.py and add an instance to ALL_CHANNELS:
# agent_reach/channels/__init__.py
from .myplatform import MyPlatformChannel # Add import
ALL_CHANNELS: List[Channel] = [
# ... existing channels ...
MyPlatformChannel(), # Add instance
]
This registration makes the channel visible to the doctor check and the core router.
Step 5: Update CLI and Testing
To include your platform in agent-reach --help output, update agent_reach/cli.py where the --list-platforms option iterates through Channel.name and Channel.description.
Create tests following the pattern in tests/test_twitter_channel.py:
# tests/test_myplatform_channel.py
def test_myplatform_can_handle():
from agent_reach.channels import get_channel
ch = get_channel("myplatform")
assert ch is not None
assert ch.can_handle("https://myplatform.com/article/123")
def test_myplatform_check_off(monkeypatch):
monkeypatch.setattr("shutil.which", lambda _: None)
ch = get_channel("myplatform")
status, _ = ch.check()
assert status == "off"
Run the full test suite with pytest tests/ -v to ensure no regressions.
Complete Working Example
Here is a complete implementation for a hypothetical platform requiring the mycli binary:
# agent_reach/channels/myplatform.py
# -*- coding: utf-8 -*-
"""MyPlatform — read and search via `mycli`."""
import shutil
import subprocess
from typing import List
from .base import Channel
class MyPlatformChannel(Channel):
name = "myplatform"
description = "MyPlatform – articles and comments"
backends = ["mycli"]
tier = 1
def can_handle(self, url: str) -> bool:
from urllib.parse import urlparse
domain = urlparse(url).netloc.lower()
return "myplatform.com" in domain
def check(self, config=None):
binary = shutil.which("mycli")
if not binary:
return "off", "mycli 未安装。安装:pip install mycli"
try:
r = subprocess.run([binary, "--version"], capture_output=True,
encoding="utf-8", timeout=5)
if r.returncode == 0:
return "ok", "mycli 已就绪"
except Exception:
pass
return "warn", "mycli 已安装但无法运行"
def read(self, url: str) -> str:
binary = shutil.which("mycli")
r = subprocess.run([binary, "read", url], capture_output=True,
encoding="utf-8", timeout=15)
return r.stdout
Summary
- Subclass
Channelfromagent_reach/channels/base.pyand setname,description,backends, andtierattributes. - Implement
can_handleto route URLs to your channel based on domain or pattern matching. - Implement
checkreturning(status, message)to validate dependencies, using statusesok,warn,off, orerror. - Register the instance in
agent_reach/channels/__init__.pyby adding it toALL_CHANNELS. - Add optional
read/searchmethods following signatures from existing channels likeyoutube.pyandreddit.py. - Test thoroughly using
pytestand verify integration withagent_reach/doctor.pyandagent_reach/cli.py.
Frequently Asked Questions
What is the minimum required implementation for a new Agent Reach channel?
You must subclass Channel and implement can_handle(self, url: str) -> bool for URL routing and check(self, config=None) for dependency validation. The check method must return a tuple of (status, message) where status is one of ok, warn, off, or error. All other methods like read and search are optional.
How does the tier system work in Agent Reach channels?
The tier attribute categorizes setup complexity: tier 0 channels work out-of-the-box without configuration (e.g., WebChannel), tier 1 channels require a free API key or simple binary installation, and tier 2 channels need complex authentication like cookie-based logins. This tier system helps users understand setup requirements when running the doctor check.
Why is my new channel not appearing in the doctor check results?
The doctor check in agent_reach/doctor.py iterates over ALL_CHANNELS defined in agent_reach/channels/__init__.py. If your channel is missing, ensure you have imported the class in __init__.py and appended an instance to the ALL_CHANNELS list. Also verify there are no import errors preventing the module from loading.
Can I implement a channel without the read or search methods?
Yes. The read and search methods are optional. If your platform only needs to validate that it can handle certain URLs (for routing purposes) but does not support content extraction or search, you only need to implement can_handle and check. The base class provides default implementations that raise NotImplementedError for these optional operations.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →