Local vs Server Environment Detection in Agent Reach: A Complete Guide
Agent Reach uses a multi-indicator scoring system in _detect_environment() to automatically distinguish between local desktop environments and headless servers, enabling it to install appropriate backends like OpenCLI for desktops or pure CLI tools for remote machines.
Agent Reach requires precise environment detection to determine whether it's running on a graphical workstation or a headless server. This distinction, implemented in the agent_reach/cli.py module, drives critical decisions about which backend tools to install for platforms like Reddit and XiaoHongShu. Understanding how local and server environment detection works in Agent Reach helps developers predict behavior across different deployment scenarios.
How Environment Detection Works in Agent Reach
The _detect_environment() Implementation
The core detection logic resides in agent_reach/cli.py (lines 955-994) within the private helper _detect_environment(). This function aggregates multiple OS-level indicators using a weighted scoring system, returning "server" when the cumulative score reaches 2 or higher, and "local" otherwise.
def _detect_environment():
"""Auto‑detect if running on local computer or server."""
import os
indicators = 0
# 1️⃣ SSH session – typical for remote logins
if os.environ.get("SSH_CONNECTION") or os.environ.get("SSH_CLIENT"):
indicators += 2
# 2️⃣ Docker / container environment
if os.path.exists("/.dockerenv") or os.path.exists("/run/.containerenv"):
indicators += 2
# 3️⃣ Headless display (no X11/Wayland)
if not os.environ.get("DISPLAY") and not os.environ.get("WAYLAND_DISPLAY"):
indicators += 1
# 4️⃣ Cloud‑VM identifiers (Amazon, Google, Azure, DigitalOcean, …)
for cloud_file in ["/sys/hypervisor/uuid",
"/sys/class/dmi/id/product_name"]:
if os.path.exists(cloud_file):
try:
with open(cloud_file) as f:
content = f.read().lower()
if any(x in content
for x in ["amazon", "google", "microsoft",
"digitalocean", "linode", "vultr", "hetzner"]):
indicators += 2
except Exception:
pass
# 5️⃣ systemd‑detect‑virt (detects virtualisation)
try:
import subprocess
result = subprocess.run(
["systemd-detect-virt"], capture_output=True,
encoding="utf-8", errors="replace", timeout=3)
if result.returncode == 0 and result.stdout.strip() != "none":
indicators += 1
except Exception:
pass
return "server" if indicators >= 2 else "local"
The Five Detection Signals
The function checks five specific environment indicators with weighted values:
- SSH connections (2 points): Checks for
SSH_CONNECTIONorSSH_CLIENTenvironment variables, indicating remote login sessions. - Container environments (2 points): Detects
/.dockerenvor/run/.containerenvfiles present in Docker and containerized runtimes. - Missing display servers (1 point): Verifies absence of
DISPLAY(X11) orWAYLAND_DISPLAYvariables, suggesting headless operation. - Cloud VM signatures (2 points): Reads
/sys/hypervisor/uuidand/sys/class/dmi/id/product_namefor strings like "amazon", "google", "microsoft", or "digitalocean". - Virtualization detection (1 point): Executes
systemd-detect-virtto identify virtualized environments, adding a point for any non-"none" result.
Platform-Specific Backend Selection
Agent Reach uses the environment classification to determine which backend implementation to install for each platform.
| Platform | Local Environment | Server Environment |
|---|---|---|
| XiaoHongShu | Installs OpenCLI (reuses desktop Chrome session) | Recommends xiaohongshu-mcp binary with QR-login guide |
Prefers OpenCLI; falls back to existing rdt-cli |
Installs rdt-cli (pure CLI without UI requirements) | |
| General | Browser-based tools assuming graphical environment | Self-contained binaries or pure CLI tools |
Reddit Installation Logic
The branching logic for Reddit dependencies (lines 778-892 in cli.py) demonstrates this pattern:
def _install_reddit_deps():
"""Set up Reddit — desktop prefers OpenCLI, rdt-cli for servers/legacy."""
if _detect_environment() != "server":
_install_opencli_deps()
print(" Reddit 走 OpenCLI(浏览器里登录过 reddit.com 即可用)")
# ... optionally use rdt‑cli if already present ...
return
_install_rdt_cli()
This ensures that desktop users get the browser-integrated OpenCLI experience while server deployments receive the headless-compatible rdt-cli tool.
Understanding the Threshold Logic
The function returns "server" only when indicators >= 2. This threshold-based design intentionally weights strong signals (SSH, containers, cloud VMs) at 2 points each, while weak signals (missing display, virtualization) contribute only 1 point.
This prevents false positives where a desktop workstation might lack a DISPLAY variable but isn't actually a server. Conversely, a Docker container automatically scores 2 points, immediately triggering server mode regardless of other factors.
Testing Environment Detection
The test suite in tests/test_cli.py (lines 88-100) verifies this branching behavior by mocking the environment detection function:
# Simulating a server environment in a test (see tests/test_cli.py)
def test_install_reddit_deps_routes_by_environment(monkeypatch):
monkeypatch.setattr(cli, "_detect_environment", lambda: "local")
# ...assert OpenCLI path...
monkeypatch.setattr(cli, "_detect_environment", lambda: "server")
# ...assert rdt‑cli path...
You can manually verify your current environment using:
from agent_reach.cli import _detect_environment
print(_detect_environment()) # Outputs: 'local' or 'server'
Summary
- Multi-factor detection: Agent Reach evaluates SSH sessions, container files, display variables, cloud VM signatures, and virtualization status to determine the environment type.
- Weighted scoring: Strong indicators (SSH, containers, cloud VMs) contribute 2 points; weak indicators (missing display, virtualization) contribute 1 point.
- Threshold decision: The environment is classified as
"server"only when the cumulative score reaches 2 or higher. - Backend routing: Local environments receive browser-based tools like OpenCLI, while server environments get pure CLI binaries like
rdt-cliorxiaohongshu-mcp. - Implementation location: All detection logic resides in
agent_reach/cli.py(lines 955-994), with platform-specific installation branching throughout the same file.
Frequently Asked Questions
How does Agent Reach detect if it's running on a server?
Agent Reach checks five OS-level indicators in agent_reach/cli.py: SSH environment variables, Docker/container files, display server availability, cloud VM hardware signatures, and virtualization status via systemd-detect-virt. Each indicator carries a weighted score, and the function returns "server" when the total reaches 2 or more points.
What happens if Agent Reach incorrectly detects my environment?
If detection fails, the tool defaults to "local" mode (since the threshold requires >= 2 points to trigger server mode). However, this may cause installation failures when attempting to launch browser-based tools like OpenCLI on headless systems. You can verify the detection by importing _detect_environment() from agent_reach.cli and checking the return value.
Can I override the automatic environment detection in Agent Reach?
While the source code in agent_reach/cli.py shows that installation functions directly call _detect_environment(), the test suite demonstrates that you can monkeypatch this function for custom behavior. For production deployments, ensure your environment presents sufficient server indicators (such as running inside Docker) to trigger automatic server mode.
Why does Agent Reach use different backends for Reddit on local vs server?
OpenCLI requires a graphical browser environment to reuse existing Chrome sessions, making it ideal for local desktops but incompatible with headless servers. rdt-cli operates as a pure CLI tool without UI dependencies, ensuring Reddit functionality remains available in SSH sessions or containerized deployments where no display server exists.
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 →