How to Add a New Platform Channel to Agent Reach: A Complete Implementation Guide
To add a new platform channel to Agent Reach, create a Python module in agent_reach/channels/ that inherits from the abstract Channel base class, implement the can_handle() and check() methods, and register the class in agent_reach/channels/__init__.py to enable automatic discovery.
Agent Reach treats every supported internet platform as a channel that lives in the agent_reach/channels/ package. Each channel inherits from the abstract base class defined in [agent_reach/channels/base.py](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/base.py), which standardizes how the framework detects, probes, and routes platform-specific operations. This guide explains the architectural requirements and provides a production-ready template to add a new platform channel to Agent Reach.
Understand the Channel Architecture
The Channel base class defines the lifecycle contract that every platform must implement. Subclasses must declare four metadata properties and override two critical methods.
Metadata Properties:
name: A short identifier used in CLI arguments and configuration keys (e.g.,"twitter").description: Human-readable diagnostic text describing the platform.backends: An ordered list of command-line tools that can fulfill requests for this channel (e.g.,["twitter-cli", "OpenCLI"]). The first healthy backend becomes the active instance.tier: An integer indicating setup complexity:0for zero-config,1for requiring a free API key, or2for full user setup.
Core Methods:
can_handle(self, url: str) -> bool: Determines if a given URL belongs to this platform by parsing the domain or path.check(self, config): Probes each candidate backend inordered_backendsand setsactive_backendto the first usable tool. Returns a tuple of(status, message)where status is"ok","warn", or"error".
The base class also provides ordered_backends(self, config), which returns the backend list respecting any user override via configuration variables or environment settings.
Step-by-Step Implementation
Step 1: Create the Channel Module
Create a new file at agent_reach/channels/<platform>.py. This module will contain your channel class and any helper functions for probing backends.
# agent_reach/channels/myplatform.py
from .base import Channel
from agent_reach.probe import probe_command
Step 2: Define Metadata and Class Properties
Declare the metadata fields as class attributes. The backends list should prioritize native CLIs over generic fallbacks.
class MyPlatformChannel(Channel):
name = "myplatform"
description = "MyPlatform – short description"
backends = ["myplatform-cli", "OpenCLI", "legacy-cli"]
tier = 1 # Requires API key but minimal setup
active_backend = None
Step 3: Implement URL Detection with can_handle
The can_handle method must return True if the supplied URL belongs to your platform. Parse the hostname using urllib.parse to ensure robust matching.
def can_handle(self, url: str) -> bool:
from urllib.parse import urlparse
domain = urlparse(url).netloc.lower()
return "myplatform.com" in domain or "mp.com" in domain
Step 4: Implement Backend Probing with check
The check method iterates through ordered_backends, probes each candidate using probe_command, and selects the first healthy backend. Follow the pattern used in [agent_reach/channels/twitter.py](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/twitter.py) for multi-backend support.
def check(self, config=None):
"""Probe each backend in order; the first usable backend becomes active."""
self.active_backend = None
findings = []
for backend in self.ordered_backends(config):
if backend == "myplatform-cli":
result = self._check_myplatform_cli()
elif backend == "OpenCLI":
result = self._check_opencli()
else:
continue
if result is None:
continue
findings.append((backend, *result))
# Prefer "ok", then "warn"
for wanted in ("ok", "warn"):
for backend, status, message in findings:
if status == wanted:
self.active_backend = backend
return status, message
if findings:
return "error", "\n".join(msg for _, _, msg in findings)
return "warn", (
"MyPlatform CLI not installed. Install it with:\n"
" pipx install myplatform-cli\n"
"or use OpenCLI if you have a browser session."
)
def _check_myplatform_cli(self):
"""Return None if missing, or (status, message) tuple."""
probe = probe_command(
"myplatform",
["status"],
timeout=15,
retries=1,
package="myplatform-cli"
)
if probe.status == "missing":
return None
if probe.status == "broken":
return "error", f"myplatform-cli exists but failed to run.\n{probe.hint}"
if probe.ok and "ready" in probe.output.lower():
return "ok", "myplatform-cli ready (search, read, …)"
return "warn", "myplatform-cli installed but not authenticated"
def _check_opencli(self):
from agent_reach.backends import opencli_status
st = opencli_status()
if not st.installed:
return None
if st.broken:
return "error", st.hint
if st.ready:
return "ok", "OpenCLI usable (browser-based login)"
return "warn", st.hint
Step 5: Register in Package Index
Edit [agent_reach/channels/__init__.py](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/__init__.py) to import your new class so the auto-discovery machinery can locate it.
from .myplatform import MyPlatformChannel # Add this line
Step 6: Verify with Diagnostics
Run the built-in diagnostics to confirm your channel is discovered and its check() method passes.
python -m agent_reach.cli doctor
You should see output similar to:
✔ MyPlatform (myplatform) – ok – myplatform-cli
Production-Ready Code Template
Copy the complete skeleton below into agent_reach/channels/myplatform.py to accelerate your implementation.
# agent_reach/channels/myplatform.py
"""MyPlatform channel implementation."""
from .base import Channel
from agent_reach.probe import probe_command
class MyPlatformChannel(Channel):
name = "myplatform"
description = "MyPlatform – short description"
backends = ["myplatform-cli", "OpenCLI"]
tier = 1
active_backend = None
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):
self.active_backend = None
findings = []
for backend in self.ordered_backends(config):
if backend == "myplatform-cli":
result = self._check_native()
elif backend == "OpenCLI":
result = self._check_opencli()
else:
continue
if result is None:
continue
findings.append((backend, *result))
for wanted in ("ok", "warn"):
for backend, status, message in findings:
if status == wanted:
self.active_backend = backend
return status, message
if findings:
return "error", "\n".join(m for _, _, m in findings)
return "warn", (
"MyPlatform CLI not installed.\n"
" pipx install myplatform-cli\n"
"or use OpenCLI if you have a logged-in browser."
)
def _check_native(self):
probe = probe_command(
"myplatform", ["status"], timeout=15, retries=1, package="myplatform-cli"
)
if probe.status == "missing":
return None
if probe.status == "broken":
return "error", f"myplatform-cli broken.\n{probe.hint}"
if probe.ok and "ready" in probe.output.lower():
return "ok", "myplatform-cli ready"
return "warn", "myplatform-cli installed but not authenticated"
def _check_opencli(self):
from agent_reach.backends import opencli_status
st = opencli_status()
if not st.installed:
return None
if st.broken:
return "error", st.hint
if st.ready:
return "ok", "OpenCLI ready"
return "warn", st.hint
def read(self, url: str):
"""Delegate reading to the selected backend."""
if self.active_backend == "myplatform-cli":
return probe_command("myplatform", ["read", url]).output
if self.active_backend == "OpenCLI":
return probe_command("opencli", ["myplatform", "get", url]).output
raise RuntimeError("No active backend for read")
Key Source Files
- [
agent_reach/channels/base.py](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/base.py): AbstractChanneldefinition, helper methods, and defaultcheck()implementation. - [
agent_reach/channels/twitter.py](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/twitter.py): Reference implementation showing multi-backend probing and health check patterns. - [
agent_reach/channels/__init__.py](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/__init__.py): Package index where new channels must be imported for auto-discovery. - [
agent_reach/probe.py](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/probe.py): Utility that executes command probes, capturing status (missing,broken,ok,timeout) and generating installation hints. - [
agent_reach/core.py](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/core.py): Central routing logic that selects a channel based oncan_handleresponses.
Summary
- Inherit from
Channel: All platform support modules must subclass the abstract base class inagent_reach/channels/base.py. - Implement
can_handle: This method routes URLs to the correct channel by inspecting domains or path patterns. - Implement
check: Probe candidate backends usingprobe_commandand setactive_backendto the first healthy tool. - Register the class: Import the new channel in
agent_reach/channels/__init__.pyto enable discovery. - Verify diagnostics: Run
python -m agent_reach.cli doctorto validate the channel health and backend connectivity.
Frequently Asked Questions
What is the minimum required to implement a functional channel?
You must implement can_handle(self, url) to return True for your platform's URLs and check(self, config) to return a status tuple. While you can return hardcoded values from check for development, production channels should probe actual backend binaries using probe_command to ensure the tool is installed and authenticated.
How does Agent Reach decide which channel handles a specific URL?
The AgentReach router iterates through all registered channels and calls can_handle(url) on each instance. The first channel returning True receives the operation. Order matters, so ensure your URL patterns are specific enough to avoid collisions with generic channels.
Can a single channel support multiple backend tools?
Yes. Define multiple entries in the backends class property. The ordered_backends method respects user overrides, and your check implementation should probe each candidate in order. The first backend reporting "ok" or "warn" status becomes active_backend, allowing graceful fallbacks from native CLIs to generic tools like OpenCLI.
Why doesn't my new channel appear in the doctor diagnostics?
If python -m agent_reach.cli doctor skips your channel, verify that you imported the class in [agent_reach/channels/__init__.py](https://github.com/Panniantong/Agent-Reach/blob/main/agent_reach/channels/__init__.py) and that the file exists at agent_reach/channels/<name>.py. Also ensure the class name follows the *Channel naming convention and that Python can parse the module without syntax errors.
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 →