Port from earendil-works/pi#7493: advertise AI_AGENT env var for child-process attribution

CLI and gateway entry points now set AI_AGENT=hermes (the emerging
cross-agent standard read by e.g. huggingface_hub agent detection) and
HERMES_AGENT=true, via setdefault so an outer harness is never
clobbered.
This commit is contained in:
Teknium 2026-08-06 17:52:54 -07:00
parent 0957277f2f
commit fde6a843e5
No known key found for this signature in database
4 changed files with 62 additions and 0 deletions

View File

@ -27020,6 +27020,14 @@ async def start_gateway(config: Optional[GatewayConfig] = None, replace: bool =
def main():
"""CLI entry point for the gateway."""
# Advertise the agent harness to child processes (AI_AGENT is the
# cross-agent standard; HERMES_AGENT the Hermes-specific marker — see
# _advertise_agent_env in hermes_cli/main.py, kept inline here to avoid
# importing that module's startup side effects). setdefault so an outer
# harness is never clobbered.
os.environ.setdefault("AI_AGENT", "hermes")
os.environ.setdefault("HERMES_AGENT", "true")
# Force UTF-8 stdio on Windows — gateway logs and startup banner would
# otherwise UnicodeEncodeError on cp1252 consoles. No-op on POSIX.
try:

View File

@ -11180,12 +11180,30 @@ def cmd_claw(args):
claw_command(args)
def _advertise_agent_env() -> None:
"""Advertise the agent harness to child processes.
``AI_AGENT`` is the emerging cross-agent standard (huggingface_hub's agent
detection reads it; pi and other agents set it earendil-works/pi#7493)
so generic tooling can attribute subprocesses to the harness that spawned
them. ``HERMES_AGENT`` is the Hermes-specific marker. setdefault: never
clobber an outer harness (e.g. Hermes running inside another agent's
terminal).
"""
os.environ.setdefault("AI_AGENT", "hermes")
os.environ.setdefault("HERMES_AGENT", "true")
def main():
"""Main entry point for hermes CLI."""
# Cosmetic: make the process show up as 'hermes' instead of 'python3.11'
# in ps/top/htop. Non-fatal — just a nicer UX.
_set_process_title()
# Let child processes (and tools like huggingface_hub) detect they run
# under an AI agent harness.
_advertise_agent_env()
# Force UTF-8 stdio on Windows before anything prints. No-op elsewhere.
try:
from hermes_cli.stdio import configure_windows_stdio

View File

@ -0,0 +1,34 @@
"""Tests for the AI_AGENT / HERMES_AGENT harness-attribution env vars.
Port of earendil-works/pi#7493: entry points advertise the agent harness to
child processes via the cross-agent ``AI_AGENT`` standard plus a
Hermes-specific marker, without clobbering an outer harness.
"""
import os
from hermes_cli.main import _advertise_agent_env
class TestAdvertiseAgentEnv:
def test_sets_both_vars_when_unset(self, monkeypatch):
monkeypatch.delenv("AI_AGENT", raising=False)
monkeypatch.delenv("HERMES_AGENT", raising=False)
_advertise_agent_env()
assert os.environ["AI_AGENT"] == "hermes"
assert os.environ["HERMES_AGENT"] == "true"
def test_does_not_clobber_outer_harness(self, monkeypatch):
monkeypatch.setenv("AI_AGENT", "pi")
monkeypatch.delenv("HERMES_AGENT", raising=False)
_advertise_agent_env()
assert os.environ["AI_AGENT"] == "pi"
assert os.environ["HERMES_AGENT"] == "true"
def test_idempotent(self, monkeypatch):
monkeypatch.delenv("AI_AGENT", raising=False)
monkeypatch.delenv("HERMES_AGENT", raising=False)
_advertise_agent_env()
_advertise_agent_env()
assert os.environ["AI_AGENT"] == "hermes"
assert os.environ["HERMES_AGENT"] == "true"

View File

@ -864,6 +864,8 @@ Unset the variable or remove it from `.env` to restore normal writes (still subj
| `SESSION_IDLE_MINUTES` | Reset sessions after N minutes of inactivity (default: 1440) |
| `SESSION_RESET_HOUR` | Daily reset hour in 24h format (default: 4 = 4am) |
| `HERMES_SESSION_ID` | **Exported automatically into every tool subprocess** Hermes spawns (`terminal`, `execute_code`, persistent shell, Docker/Singularity backends, delegated subagent runs). Set by the agent to the current session ID; user scripts called from tools can read it to correlate their output, telemetry, or side effects with the originating Hermes session. **You should not set this manually** — overriding it from a parent shell only takes effect outside an agent run, and is overwritten the moment the agent starts a session. |
| `AI_AGENT` | **Set to `hermes` by the CLI and gateway entry points** (only when not already set by an outer harness). The emerging cross-agent standard for child-process attribution — generic tooling (e.g. huggingface_hub's agent detection) reads it to know it runs under an AI agent. Don't set manually. |
| `HERMES_AGENT` | **Set to `true` by the CLI and gateway entry points** so child processes can detect they run inside Hermes specifically. Don't set manually. |
## Context Compression (config.yaml only)