How to Add a Custom Channel or Backend to Agent Reach: A Complete Developer Guide
To add a custom channel or backend to Agent Reach, subclass the abstract Channel base class in agent_reach/channels/, implement the can_handle() and check() methods, register the instance in ALL_CHANNELS, and optionally extend the backends list to support additional data retrieval tools.
Agent Reach discovers internet platforms through pluggable channel classes that live in the Panniantong/Agent-Reach repository. Whether you need to integrate a new social media site or extend an existing channel with alternative CLI tools, the framework provides a consistent architecture based on abstract base classes and a central registry. This guide walks through the exact file locations, method signatures, and code patterns required to integrate custom platforms.
Understanding the Channel Architecture
Agent Reach identifies platforms using three core components: the abstract base class, the channel registry, and contract tests.
The Channel Base Class
The file agent_reach/channels/base.py defines the abstract Channel class that enforces a consistent interface across all platforms. Every subclass must declare the class attributes name, description, backends, and tier, plus implement can_handle(url: str) -> bool to identify platform-specific URLs and check(config=None) -> Tuple[str, str] to probe available backends and set self.active_backend.
The Channel Registry
The agent_reach/channels/__init__.py file maintains ALL_CHANNELS, a list containing every channel instance. This registry powers the agent_reach.doctor diagnostic tool and public API functions like get_channel() and get_all_channels(). The registry automatically imports every channel file in the directory, making manual registration mandatory for new additions.
Contract Tests
The file tests/test_channel_contracts.py enforces mandatory attributes and methods. Any new channel must pass these assertions; otherwise, the agent-reach doctor command will raise an assertion error indicating which required property is missing.
Adding a New Custom Channel
Creating a custom channel follows four concrete steps: file creation, class implementation, registry registration, and contract validation.
Step 1: Create the Channel File
Create a new Python file at agent_reach/channels/<your_platform>.py. Import the base class and define your channel subclass with the required attributes.
Step 2: Implement Required Methods
Implement can_handle() to recognize your platform's URLs by inspecting the netloc or path. Implement check() to validate backend availability, set self.active_backend to the working backend name (or None for builtin channels), and return a tuple of (status, message).
For builtin channels that require no external tools, set backends = [] and return "ok" from check():
# agent_reach/channels/examplesite.py
from urllib.parse import urlparse
from .base import Channel
class ExampleSiteChannel(Channel):
name = "examplesite"
description = "ExampleSite – demo read-only platform"
backends = [] # Builtin channel requires no external tools
tier = 0 # Zero-config platform
def can_handle(self, url: str) -> bool:
return urlparse(url).netloc.lower().endswith("example.com")
def check(self, config=None):
self.active_backend = None
return "ok", "built-in – no external tools required"
Step 3: Register in the Channel Registry
Import the new class in agent_reach/channels/__init__.py and append an instance to ALL_CHANNELS:
# agent_reach/channels/__init__.py
from .examplesite import ExampleSiteChannel
ALL_CHANNELS: List[Channel] = [
# ... existing channels ...
ExampleSiteChannel(),
]
Step 4: Validate with Contract Tests
Run the test suite to ensure your channel satisfies the contract:
pytest tests/test_channel_contracts.py -q
All assertions should pass, confirming that name, description, backends, tier, and active_backend are properly defined.
Adding a New Backend to an Existing Channel
Many platforms support multiple data retrieval methods. Extend existing channels by modifying the backends list and updating the probing logic in check().
Extending the Backends List
Append the new backend name to the channel's backends attribute, preserving order of preference (preferred first). The ordered_backends() method in the base class automatically respects user overrides from config files using the pattern <channel_name>_backend: <backend_name>.
Implementing Backend Probing
Update the check() method to probe the new backend before falling back to existing ones. Use probe_command() from agent_reach.probe to test CLI availability, and set self.active_backend to the first successful candidate.
Here is an example extending the YouTube channel with a hypothetical myyt CLI:
# agent_reach/channels/youtube.py
from agent_reach.probe import probe_command
from .base import Channel
class YouTubeChannel(Channel):
name = "youtube"
description = "YouTube videos and subtitles"
backends = ["myyt", "yt-dlp"] # New preferred backend first
tier = 0
def can_handle(self, url: str) -> bool:
# Existing URL matching logic...
return "youtube.com" in url or "youtu.be" in url
def check(self, config=None):
# Probe new backend first
probe = probe_command("myyt", ["--version"], timeout=10, package="myyt")
if probe.status == "ok":
self.active_backend = "myyt"
return "ok", "myyt CLI available"
# Fallback to yt-dlp
probe = probe_command("yt-dlp", ["--version"], timeout=10, package="yt-dlp")
if probe.status != "ok":
self.active_backend = None
return "off", "yt-dlp not installed"
self.active_backend = "yt-dlp"
return "ok", "yt-dlp available"
Full Implementation Example: Multi-Backend Platform
For a complete real-world scenario, consider adding "FooTalk", a platform supporting both a native CLI and a generic browser-based backend:
# agent_reach/channels/footalk.py
from agent_reach.probe import probe_command
from agent_reach.backends import opencli_status, opencli_summary
from .base import Channel
class FooTalkChannel(Channel):
name = "footalk"
description = "FooTalk – micro-blogging platform"
backends = ["footalk-cli", "opencli"] # Native CLI preferred, fallback to OpenCLI
tier = 1 # Requires login/key handled by CLI
def can_handle(self, url: str) -> bool:
from urllib.parse import urlparse
return urlparse(url).netloc.lower().endswith("footalk.com")
def check(self, config=None):
# Try native CLI first
probe = probe_command("footalk-cli", ["--version"], timeout=10, package="footalk-cli")
if probe.status == "ok":
self.active_backend = "footalk-cli"
return "ok", "footalk-cli available"
# Fallback to OpenCLI
st = opencli_status()
if st.ready:
self.active_backend = "opencli"
return "ok", opencli_summary(st)
# Nothing available
self.active_backend = None
return "off", "Neither footalk-cli nor OpenCLI detected"
Register this channel in agent_reach/channels/__init__.py as shown previously. The agent-reach doctor command will now display the active backend, and agents can invoke the appropriate CLI directly.
Testing and Validation
After implementation, verify your integration:
- Run contract tests:
pytest tests/test_channel_contracts.py -qensures all required attributes exist. - Check doctor output:
agent-reach doctorshould list your channel with the correct active backend. - Test URL handling: Verify
can_handle()returnsTruefor your platform URLs andFalsefor others.
Summary
- Subclass
Channelfromagent_reach/channels/base.pyand implementcan_handle()for URL recognition andcheck()for backend probing. - Define required attributes:
name,description,backends(ordered list), andtier(configuration complexity level). - Register the channel by importing the class in
agent_reach/channels/__init__.pyand appending an instance toALL_CHANNELS. - Add new backends by extending the
backendslist and probing each candidate incheck(), settingself.active_backendto the first successful option. - Validate using
pytest tests/test_channel_contracts.pybefore runningagent-reach doctor.
Frequently Asked Questions
What is the minimum required code to add a custom channel to Agent Reach?
At minimum, create a file in agent_reach/channels/, subclass Channel, define name, description, backends, and tier, implement can_handle() to return True for your platform URLs, and implement check() to set self.active_backend and return a status tuple. Finally, import and instantiate the class in agent_reach/channels/__init__.py and append it to ALL_CHANNELS.
How does Agent Reach choose which backend to use for a channel?
The check() method probes backends in order of preference and sets self.active_backend to the first successful candidate. Users can override this via ~/.agent-reach/config.yaml using the <channel_name>_backend key, which the ordered_backends() method respects when reordering the backends list.
Can I add a backend to an existing channel without modifying the original source files?
While you must edit the channel's Python file to add backend logic, you should extend the existing channel class in your fork or modify the existing one directly. There is currently no plugin system for backends independent of channel files; all backend logic must be registered within the channel's check() method and backends list.
What happens if my custom channel fails the contract tests?
The agent-reach doctor command will raise an assertion error indicating which required attribute or method is missing. Common failures include missing name, description, backends, or tier attributes, or failing to set active_backend in the check() method before returning.
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 →