# Hermes 并发缺陷待办 > 调研日期:2026-08-18 > 背景:对话页多会话并发场景调研结论。当前主流程(对话页多会话并发)链路安全, > 以下缺陷暂不触发或影响面有限,记录备查。 ## 并发安全现状(无缺陷部分) | 层 | 隔离机制 | 位置 | |---|---|---| | Java 执行层 | `ChatRunService` 固定线程池 `max(8, cpu×2)`,每 run 独立线程;SseEventBus 按 runId 隔离 | `backend/src/main/java/com/agent/management/service/ChatRunService.java:110` | | Bridge 线程层 | 每个 `/run` 请求创建独立 daemon 线程,事件经 run 级 `queue`(局部变量)隔离 | `backend/hermes-bridge/hermes_bridge.py:541` | | Agent 实例层 | LRU 池按 `session_id::hermes_home::model_id` 键控;每会话有独立 `hermesSession` | `hermes_bridge.py:202`、`ChatSessionService.java:51` | | 工作目录(主要路径) | `_SESSION_CWD` 为 contextvars,线程内 set/reset 配对,hermes-agent 工具优先读取 | `hermes_bridge.py:489-525` | | Clarify | 按 `clarify_id` 注册/唤醒,run 级孤儿清理配对 | `hermes_bridge.py:411-447` | ## 缺陷清单 ### 缺陷 1:`os.chdir` 进程级竞态(优先级:中) **位置**:`backend/hermes-bridge/hermes_bridge.py:474-479` **现象**:`working_dir` 除设置 contextvar 外,还会切换进程 cwd(`os.chdir(wd)`) 并覆盖进程级环境变量 `TERMINAL_CWD`。多个 run 并发时: - 进程 cwd 由最后执行 `chdir` 的 run 主导,先启动的 run 拿到错误目录; - 一个 run 结束时在 finally 中恢复 `original_cwd`,会破坏仍在运行的 run 的进程 cwd。 **影响面**:仅限直接调用 `os.getcwd()` 的工具;走 `_SESSION_CWD`(contextvar, 线程隔离)的工具不受影响。 **触发场景**:工作流 DAG 同层多个 Hermes 节点并发执行(多个 `/run` 请求同时 携带不同 `working_dir`)。对话页多会话场景因 Agent 隔离 + 工具走 contextvar 基本无感。 **修复建议**:将 `os.chdir` / `TERMINAL_CWD` 下沉为按 `task_id` 的隔离机制 (与 `register_task_env_overrides` 同思路),运行线程内不再触碰进程全局状态。 ### 缺陷 2:同 cache_key 并发复用同一 Agent 实例(优先级:高) **位置**:`backend/hermes-bridge/hermes_bridge.py:494-500`、`:202-207` **现象**:同一 `session_id::hermes_home::model_id` 的两个并发 run 会从 LRU 池 拿到**同一个 Agent 实例**: - `_run` 内直接给实例属性赋回调(`agent.tool_start_callback = ...` 等), 后启动的 run 覆盖先启动 run 的全部回调 → 事件流向错乱; - Agent 的对话上下文(`run_conversation` 历史)交叉污染。 **当前防线**:仅前端"同会话运行中禁发"(`useChat.js` 的 `sending` computed)。 双浏览器窗口打开同一会话、或直接调 API 可绕过。 **修复建议**(低成本方案):Java 层 `ChatRunService.startRun` 增加校验—— 同会话存在 `RUNNING` 状态消息时拒绝新 run(返回业务错误)。Bridge 层可选 加固:`/run` 检测 cache_key 已有活跃 run 时强制 `force_new` 并发运行。 ### 缺陷 3:`HERMES_HOME` 环境变量进程全局覆盖(优先级:低) **位置**:`backend/hermes-bridge/hermes_bridge.py:210-212` **现象**:带 `hermes_home` 的请求直接 `os.environ["HERMES_HOME"] = ...`, 并发请求互相覆盖,技能目录加载可能错乱。 **当前防线**:对话页与工作流节点均传 `hermes_home=null`(Java 侧 `HermesAgentExecutor.java:98`),回落固定 `HERMES_HOME`,暂不触发。 **修复建议**:仅在 Agent 构造期间临时设置并立即恢复(临界区内),或改为 显式传参注入而非环境变量。 ## 修复优先级建议 缺陷 2(Java 层会话级 run 互斥校验,成本低、封堵面大)> 缺陷 1(工作目录 隔离机制重构)> 缺陷 3(当前不触发,可延后)。