How the `probe` Command Validates Backend Availability Beyond `shutil.which` in Agent Reach
Agent Reach performs real execution health checks through agent_reach/probe.py, catching stale virtual environments, permission issues, and timeouts that simple path lookups miss.
The probe command in Agent Reach distinguishes itself from basic availability checks by actually running target commands and classifying their runtime behavior. While shutil.which merely confirms that a binary exists on the system PATH, the probe_command function in agent_reach/probe.py executes commands with real arguments to detect nuanced failure modes. This deeper validation powers the doctor diagnostic system, giving users actionable repair guidance when backends break.
The Validation Pipeline in agent_reach/probe.py
The probe_command function implements a seven-stage validation flow that transforms a simple existence check into a comprehensive health assessment.
Stage 1: Existence Check with shutil.which
The probe begins with the standard path lookup. If shutil.which returns None, the function immediately returns ProbeResult("missing") without attempting execution.
# agent_reach/probe.py, lines 67-70
if not cmd_path:
return ProbeResult(
status="missing",
hint=f"{command} is not installed or not on PATH"
)
This is the baseline behavior found in most tooling checks. The distinction comes in what happens when a path is found.
Stage 2: Real Execution via _run_once
When a valid path exists, the helper function _run_once spawns the command through subprocess.run, defaulting to --version arguments:
# agent_reach/probe.py, lines 92-105
def _run_once(cmd: List[str], timeout: int) -> Tuple[bool, str, str, int]:
result = subprocess.run(
cmd,
capture_output=True,
text=True,
timeout=timeout,
env=utf8_subprocess_env() # From agent_reach/utils/process.py
)
return True, result.stdout, result.stderr, result.returncode
The utf8_subprocess_env() utility from agent_reach/utils/process.py ensures a clean environment, preventing locale-related encoding failures during probing.
Stage 3: Shebang and Interpreter Detection
A classic failure case that shutil.which cannot catch: Python packages installed in virtual environments that become orphaned after interpreter upgrades. The probe catches FileNotFoundError and OSError exceptions to flag these as "broken":
# agent_reach/probe.py, lines 106-110
except (FileNotFoundError, OSError) as e:
return ProbeResult(
status="broken",
hint=f"{command} exists but its interpreter is missing. Reinstall recommended."
)
Without this check, users would see mysterious execution failures despite the binary appearing present.
Stage 4: Timeout Detection
Unresponsive commands are classified separately from execution failures. A subprocess.TimeoutExpired exception triggers the "timeout" status:
# agent_reach/probe.py, lines 111-112
except subprocess.TimeoutExpired:
return ProbeResult(status="timeout", hint=f"{command} is not responding")
This distinguishes hung processes from fundamentally broken installations.
Stage 5: Exit-Code Classification
The probe interprets universal exit codes from POSIX shells:
# agent_reach/probe.py, lines 14-15
BROKEN_EXIT_CODES = {126, 127} # Command found but not executable / command not found
# lines 114-115
if returncode in BROKEN_EXIT_CODES:
return ProbeResult(status="broken", hint=f"{command} is not executable")
- 126: Command found but not executable (permission denied)
- 127: Command not found (often indicates broken symlink or PATH issue)
These codes signal "found but fundamentally broken" scenarios that mere path presence cannot reveal.
Stage 6: General Error Reporting
Non-zero exit codes outside the broken set receive "error" status with captured output preserved for debugging:
# agent_reach/probe.py, lines 118-120
if returncode != 0:
return ProbeResult(
status="error",
output=f"stdout: {stdout}\nstderr: {stderr}"
)
Stage 7: Success Confirmation
Only zero exit codes yield "ok" status with command output:
# agent_reach/probe.py, lines 120-121
return ProbeResult(status="ok", output=stdout.strip())
Failure Mode Classification Summary
| Status | Detection Mechanism | Typical Cause |
|---|---|---|
| missing | shutil.which returns None |
Binary not installed or not on PATH |
| broken | FileNotFoundError, OSError, or exit code 126/127 |
Stale virtual environment, bad shebang, permission denied |
| timeout | subprocess.TimeoutExpired |
Process hung or unresponsive |
| error | Non-zero exit code (other than 126/127) | Command-specific runtime failure |
| ok | Exit code 0 | Healthy, responsive backend |
Practical Usage Examples
Standalone Health Check
from agent_reach.probe import probe_command
result = probe_command("yt-dlp", args=["--version"])
if result.ok:
print("yt-dlp is available:", result.output)
elif result.status == "missing":
print("yt-dlp is not installed.")
elif result.status == "broken":
print("yt-dlp exists but cannot be executed:", result.hint)
elif result.status == "timeout":
print("yt-dlp is unresponsive:", result.hint)
else:
print("yt-dlp returned an error:", result.output)
Channel Integration Pattern
Channels implement check() methods that delegate to probe_command, enabling unified diagnostics through agent_reach/doctor.py:
from agent_reach.probe import probe_command
from agent_reach.channels.base import BaseChannel
class YoutubeChannel(BaseChannel):
...
def check(self) -> None:
probe = probe_command("yt-dlp")
if not probe.ok:
self.log.error(f"yt-dlp probe failed: {probe.status} – {probe.hint}")
The doctor module aggregates these checks across all registered channels, producing a comprehensive system health report.
Key Source Files
agent_reach/probe.py— Core probing logic with existence, execution, and classification stagesagent_reach/doctor.py— Orchestrates health checks across all channelsagent_reach/channels/*— Platform backends (YouTube, Reddit, etc.) implementingcheck()withprobe_commandagent_reach/utils/process.py— Subprocess environment utilities for clean command execution
Summary
shutil.whichonly verifies PATH presence;probe_commandexecutes commands to validate actual runtime health- The probe catches broken interpreters, permission issues, and timeouts through exception handling and exit-code analysis
- Channels integrate via
check()methods, enablingdoctordiagnostics to report precise failure modes with actionable repair hints - Five distinct statuses (
missing,broken,timeout,error,ok) provide granular visibility into backend state
Frequently Asked Questions
Why doesn't Agent Reach use just shutil.which like other tools?
shutil.which confirms that a file exists on PATH, but fails to detect common breakage modes: stale Python virtual environments with orphaned shebangs, permission-denied executables, and unresponsive hung processes. The probe_command function in agent_reach/probe.py executes real commands to surface these issues with specific diagnostic messages.
What exit codes does the probe treat as "broken"?
The probe classifies exit codes 126 and 127 as "broken" per POSIX conventions. Code 126 means "command found but not executable" (permissions), while 127 means "command not found" despite path presence (often broken symlinks). These are defined in BROKEN_EXIT_CODES at lines 14-15 of agent_reach/probe.py.
How do channels report probe failures to users?
Channels call probe_command inside their check() methods, then log structured error messages including the probe status and hint. The agent_reach/doctor.py module aggregates all channel checks into a unified diagnostic report, presenting actionable guidance for each failed backend.
Can I customize the arguments passed during probing?
Yes. The probe_command function accepts an optional args parameter defaulting to ["--version"]. Pass custom arguments for backends that don't support --version or require specific flags to validate functionality.
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 →