New request
#195: Reliability: os.environ race condition between concurrent agent sessions
We'll provision a sandbox, run an agent against the issue, and open a draft PR. You can pull the branch and iterate from there.
Problem
In api/streaming.py, concurrent agent sessions share process-level os.environ for critical variables (TERMINAL_CWD, HERMES_SESSION_KEY, HERMES_EXEC_ASK, HERMES_HOME). While _ENV_LOCK serializes the mutation of these env vars, it does not isolate them per-session during the agents execution.
How It Works Today
with _ENV_LOCK:
os.environ["TERMINAL_CWD"] = str(s.workspace)
os.environ["HERMES_SESSION_KEY"] = session_id
# Lock released -- agent runs WITHOUT holding it
The lock is released before the agent runs (comment explicitly says "Lock released -- agent runs without holding it"). This means Session A agent thread and Session B agent thread can run simultaneously while os.environ points to whichever one wrote last.
Risk
Any tool in the Hermes agent that reads os.environ["TERMINAL_CWD"] or os.environ["HERMES_SESSION_KEY"] could see the wrong sessions context. The agent also receives workspace context via the system message (which is session-safe), but tools that bypass that and read env vars directly could:
- Write files to the wrong workspace
- Log session data to the wrong session file
- Trigger approvals for the wrong session
Suggested Fix
Option A (minimal): Set per-process env only for the subprocess spawn. When the agent spawns a terminal command, pass an explicit env= dict to subprocess.run() that merges the current env with the session-specific overrides, rather than mutating os.environ globally.
Option B (preferred if agent architecture allows): Remove the process-level os.environ mutation entirely. The thread-local mechanism (_set_thread_env, _clear_thread_env) already exists -- make the Hermes agent tools consult thread-local context instead of os.environ for these values. The process-level env write could be removed or reduced to a fallback.
Option C (belt-and-suspenders): Keep both, but add a session-specific prefix/check: tools that read TERMINAL_CWD should also verify against the active HERMES_SESSION_KEY to detect mismatches and refuse to operate.
Concurrency bug in shared process environment isolation requiring careful changes to agent execution spawning and per-session env handling.
- api/streaming.py
- api/execution.py
- api/subprocess_utils.py
- tests/test_concurrent_sessions.py