ByteNoteByteNote

字节笔记本

2026年6月21日

hermes教程-配置

API中转
¥120

目录结构

所有设置都存储在 ~/.hermes/ 目录中,方便访问。

提示 — 获得可用 config.yaml 的最简单路径

运行 hermes setup --portal — 一次 OAuth 即可获得一个模型提供商和所有四个 Tool Gateway 工具,无需手动编辑 YAML。Portal 订阅者还可享受按令牌计费提供商 10% 的折扣。参见 Nous Portal

目录结构

text
~/.hermes/
├── config.yaml     # 设置(模型、终端、TTS、压缩等)
├── .env            # API 密钥和机密信息
├── auth.json       # OAuth 提供商凭据(Nous Portal 等)
├── SOUL.md         # 主要代理身份(系统提示中的 #1 插槽)
├── memories/       # 持久记忆(MEMORY.md, USER.md)
├── skills/         # 代理创建的技能(通过 skill_manage 工具管理)
├── cron/           # 定时任务
├── sessions/       # 网关会话
└── logs/           # 日志(errors.log, gateway.log — 机密信息自动编辑)

管理配置

bash
hermes config              # 查看当前配置
hermes config edit         # 在编辑器中打开 config.yaml
hermes config set KEY VAL  # 设置特定值
hermes config check        # 检查缺失选项(更新后)
hermes config migrate      # 交互式添加缺失选项
## 示例:
hermes config set model anthropic/claude-opus-4
hermes config set terminal.backend docker
hermes config set OPENROUTER_API_KEY sk-or-...  # 保存到 .env

提示

hermes config set 命令会自动将值路由到正确的文件 — API 密钥保存到 .env,其他所有内容保存到 config.yaml

配置优先级

设置按以下顺序解析(最高优先级优先):

  1. CLI 参数 — 例如 hermes chat --model anthropic/claude-sonnet-4(每次调用的覆盖)
  2. ~/.hermes/config.yaml — 所有非机密设置的主要配置文件
  3. ~/.hermes/.env — 环境变量的后备;必需用于机密信息(API 密钥、令牌、密码)
  4. 内置默认值 — 当没有其他设置时的硬编码安全默认值

信息 — 经验法则

机密信息(API 密钥、机器人令牌、密码)放在 .env 中。其他所有内容(模型、终端后端、压缩设置、内存限制、工具集)放在 config.yaml 中。当两者都设置时,config.yaml 对非机密设置具有更高优先级。

环境变量替换

你可以在 config.yaml 中使用 ${VAR_NAME} 语法引用环境变量:

yaml
auxiliary:
  vision:
    api_key: ${GOOGLE_API_KEY}
    base_url: ${CUSTOM_VISION_URL}

delegation:
  api_key: ${DELEGATION_KEY}

单个值中的多个引用也有效:url: "${HOST}:${PORT}"。如果引用的变量未设置,则占位符保持原样(${UNDEFINED_VAR} 保持不变)。仅支持 ${VAR} 语法 — 裸 $VAR 不会被展开。

有关 AI 提供商设置(OpenRouter、Anthropic、Copilot、自定义端点、自托管 LLM、后备模型等),请参见 AI 提供商

提供商超时

你可以设置 providers.<id>.request_timeout_seconds 作为提供商范围的请求超时,以及 providers.<id>.models.<model>.timeout_seconds 作为模型特定的覆盖。适用于每个传输(OpenAI-wire、原生 Anthropic、Anthropic 兼容)上的主要轮次客户端、后备链、凭据轮换后的重建,以及(对于 OpenAI-wire)每个请求的超时 kwargs — 因此配置的值优先于旧的 HERMES_API_TIMEOUT 环境变量。

你还可以设置 providers.<id>.stale_timeout_seconds 用于非流式陈旧调用检测器,以及 providers.<id>.models.<model>.stale_timeout_seconds 用于模型特定的覆盖。这优先于旧的 HERMES_API_CALL_STALE_TIMEOUT 环境变量。

保持这些未设置则保留旧的默认值(HERMES_API_TIMEOUT=1800 秒,HERMES_API_CALL_STALE_TIMEOUT=300 秒,原生 Anthropic 900 秒)。目前不适用于 AWS Bedrock(bedrock_converse 和 AnthropicBedrock SDK 路径都使用 boto3 及其自己的超时配置)。参见 cli-config.yaml.example 中的注释示例。

更新行为

hermes update 设置位于 config.yamlupdates 下:

yaml
updates:
  pre_update_backup: false       # 每次更新前创建完整的 HERMES_HOME zip 备份
  backup_keep: 5                 # 保留这么多更新前的备份 zip
  non_interactive_local_changes: stash  # stash | discard

对于 git 安装,Hermes 在检出更新分支或拉取之前,会自动暂存脏的跟踪文件和未跟踪文件。交互式终端更新会在恢复该暂存之前提示。非交互式更新(桌面/聊天应用、网关或 --yes)使用 updates.non_interactive_local_changesstash 在成功拉取后恢复本地源代码编辑,而 discard 在成功拉取后丢弃更新创建的暂存。仅在托管安装中使用 discard,其中本地源代码编辑永远不应持久化。

在该暂存步骤之前,Hermes 还会恢复由 npm install/build 变动留下的跟踪的 package-lock.json 差异。在更新之前,提交或手动暂存有意的 lockfile 编辑。

终端后端配置

Hermes 支持六个终端后端。每个后端决定了代理的 shell 命令实际执行的位置 — 你的本地机器、Docker 容器、通过 SSH 的远程服务器、Modal 云沙箱(直接或通过 Nous 管理的网关)、Daytona 工作区或 Singularity/Apptainer 容器。

yaml
terminal:
  backend: local    # local | docker | ssh | modal | daytona | singularity
  cwd: "."          # 网关/cron 工作目录(CLI 始终使用启动目录)
  timeout: 180      # 每个命令的超时时间(秒)
  home_mode: auto   # auto | real | profile — 子进程 HOME 策略
  env_passthrough: []  # 要转发到沙箱执行的环境变量名称(terminal + execute_code)
  singularity_image: "docker://nikolaik/python-nodejs:python3.11-nodejs20"  # Singularity 后端的容器镜像
  modal_image: "nikolaik/python-nodejs:python3.11-nodejs20"                 # Modal 后端的容器镜像
  daytona_image: "nikolaik/python-nodejs:python3.11-nodejs20"               # Daytona 后端的容器镜像

对于云沙箱(如 Modal 和 Daytona),container_persistent: true 意味着 Hermes 将尝试在沙箱重建时保留文件系统状态。它不保证相同的实时沙箱、PID 空间或后台进程稍后仍然运行。

后端概览

后端命令运行位置隔离性最适合
local直接在你的机器上开发、个人使用
docker单个持久 Docker 容器(跨会话、/new、子代理共享)完全(命名空间、cap-drop)安全沙箱、CI/CD
ssh通过 SSH 的远程服务器网络边界远程开发、强大硬件
modalModal 云沙箱完全(云 VM)临时云计算、评估
daytonaDaytona 工作区完全(云容器)托管云开发环境
singularitySingularity/Apptainer 容器命名空间(--containall)HPC 集群、共享机器

本地后端

默认值。命令直接在你的机器上运行,没有隔离。无需特殊设置。

yaml
terminal:
  backend: local

默认情况下,本地工具子进程保留你真实的 OS 用户 HOME。这允许外部 CLI(如 gitsshghaznpm、Claude Code 和 Codex)找到它们已经在你的正常 shell 中使用的凭据和配置。Hermes 状态仍然通过 HERMES_HOME 进行配置文件范围限定;HOME 不是配置文件选择配置、内存、会话或技能的方式。

Hermes 不会更改你的系统范围 HOME、你的 shell 启动文件或操作系统帐户主目录。此设置仅控制传递给 Hermes 通过工具(如 terminal、后台终端进程、execute_code 和 ACP 辅助进程)启动的子进程的环境。

terminal.home_mode

模式主机安装容器权衡
auto保留真实的 OS 用户 HOME使用 {HERMES_HOME}/home推荐默认值。主机 CLI 继续工作;容器状态持久化。
real强制使用真实的 OS 用户 HOME如果可见,强制使用真实的 OS 用户 HOME如果父进程意外启动时 HOME 指向配置文件主目录,则很有用。
profile当存在时使用 {HERMES_HOME}/home当存在时使用 {HERMES_HOME}/home严格的每个配置文件 CLI 配置隔离,但正常的 ~/.ssh~/.gitconfig~/.azure~/.config/gh、Claude/Codex 认证、npm 状态等将不可见,除非你在配置文件主目录内初始化或链接它们。

默认的缺点是主机配置文件共享相同的正常用户级 CLI 凭据/配置(位于 ~ 下)。如果你需要一个具有独立 git 身份、SSH 密钥、GitHub CLI 登录、npm 配置或云 CLI 登录的配置文件,请使用 home_mode: profile 并在该配置文件主目录中故意初始化这些工具。

如果你有意想要严格的每个配置文件工具配置隔离,请设置:

yaml
terminal:
  home_mode: profile

在该模式下,工具子进程使用 {HERMES_HOME}/home 作为 HOME。Hermes 还会设置 HERMES_REAL_HOME,以便脚本在需要时仍能定位实际用户主目录。容器后端在 auto 模式下继续使用 {HERMES_HOME}/home,因为该目录位于持久化的 Hermes 数据卷上。

需要区分配置文件状态和实际用户主目录的脚本应优先使用 HERMES_HOME 获取 Hermes 数据,使用 HERMES_REAL_HOME 获取帐户主目录:

python
from pathlib import Path
import os

hermes_home = Path(os.environ["HERMES_HOME"])
real_home = Path(os.environ.get("HERMES_REAL_HOME", os.environ["HOME"]))

警告

代理具有与你的用户帐户相同的文件系统访问权限。使用 hermes tools 禁用你不希望使用的工具,或切换到 Docker 进行沙箱化。

Docker 后端

在 Docker 容器内运行命令,并具有安全强化(所有能力被丢弃,无权限提升,PID 限制)。

单个持久容器,跨 Hermes 进程共享。 Hermes 在首次使用时启动一个长期存在的容器,并通过 docker exec 将每个终端、文件和 execute_code 调用路由到该同一容器中 — 跨会话、/new/resetdelegate_task 子代理。工作目录更改、已安装的包、/workspace 中的文件以及后台进程都会从一个工具调用延续到下一个,以及从一个 Hermes 进程延续到下一个。当你关闭 TUI 会话、运行 /quit 或启动新的 hermes 调用时,容器继续运行,下一个 Hermes 进程通过标签查找重用它。有关确切的拆除规则,请参见下面的容器生命周期

yaml
terminal:
  backend: docker
  docker_image: "nikolaik/python-nodejs:python3.11-nodejs20"
  docker_mount_cwd_to_workspace: false  # 将启动目录挂载到 /workspace
  docker_run_as_host_user: false   # 参见下面的“以主机用户身份运行容器”
  docker_forward_env:              # 要转发到容器的主机环境变量
    - "GITHUB_TOKEN"
  docker_env:                      # 要注入的字面环境变量(KEY=value)
    DEBUG: "1"
    PYTHONUNBUFFERED: "1"
  docker_volumes:                  # 主机目录挂载
    - "/home/user/projects:/workspace/projects"
    - "/home/user/data:/data:ro"   # :ro 表示只读
  docker_extra_args:               # 逐字附加到 `docker run` 的额外标志
    - "--gpus=all"
    - "--network=host"
## 资源限制
  container_cpu: 1                 # CPU 核心数(0 = 无限制)
  container_memory: 5120           # MB(0 = 无限制)
  container_disk: 51200            # MB(需要 overlay2 和 XFS+pquota)
  container_persistent: true       # 持久化 /workspace 和 /root 绑定挂载目录
## 跨进程容器重用(默认匹配“跨会话共享的单个长期容器”约定 — 参见容器生命周期)。
  docker_persist_across_processes: true   # 跨 Hermes 重启重用容器
  docker_orphan_reaper: true              # 启动时清理已退出的孤立容器
## 跨后端生命周期设置(也适用于 docker)
  timeout: 180                     # 每个命令的超时时间(秒)
  lifetime_seconds: 300            # 空闲回收窗口;也作为 2× 孤立回收阈值

docker_envdocker_forward_env:前者注入你在配置中指定的字面 KEY=value 对(这些值位于你的 config.yaml 中,或通过 TERMINAL_DOCKER_ENV='{"DEBUG":"1"}' 作为 JSON 字典传递)。后者从你的 shell 或 ~/.hermes/.env 转发值,因此实际的机密信息永远不会出现在配置文件中。对令牌使用 docker_forward_env,对容器需要的静态旋钮使用 docker_env

terminal.docker_extra_args(也可通过 TERMINAL_DOCKER_EXTRA_ARGS='["--gpus=all"]' 覆盖)允许你传递 Hermes 未作为一级键公开的任意 docker run 标志 — --gpus--network--add-host、替代的 --security-opt 覆盖等。每个条目必须是字符串;该列表最后附加到组合的 docker run 调用中,因此如果需要,它可以覆盖 Hermes 的默认值。谨慎使用 — 与沙箱强化(能力丢弃、--user、工作区绑定挂载)冲突的标志将静默削弱隔离。

要求: 已安装并运行 Docker Desktop 或 Docker Engine。Hermes 探测 $PATH 以及常见的 macOS 安装位置(/usr/local/bin/docker/opt/homebrew/bin/docker、Docker Desktop 应用包)。Podman 开箱即用:当两者都安装时,设置 HERMES_DOCKER_BINARY=podman(或完整路径)以强制使用。

容器生命周期

每个由 Hermes 管理的容器都带有三个标签,以便后续进程(和孤立回收器)可以识别它:

  • hermes-agent=1 — 标记为 Hermes 管理
  • hermes-task-id=<sanitized task_id> — 键控每个任务的重用探测
  • hermes-profile=<sanitized profile name> — 将重用和回收范围限定到活动的 Hermes 配置文件

启动时,Hermes 运行 docker ps --filter label=hermes-task-id=<id> --filter label=hermes-profile=<profile> 并在找到现有容器时附加到该容器。如果容器已退出(例如在 Docker 守护进程重启后),则执行 docker start 并重用 — 文件系统状态和任何已安装的包都会保留,但容器内的后台进程不会。

当 Hermes 进程退出时 — /quit、关闭 TUI 会话、网关关闭,甚至 SIGKILL — 清理路径在默认模式下对容器是无操作。容器继续运行。下一个 Hermes 进程通过标签探测在毫秒内附加到它。这是“跨会话共享的单个长期容器”约定所需的行为:这是后台进程(npm 监视器、开发服务器、长时间运行的 pytest)跨会话存活的唯一方式。

容器仅在以下情况下被拆除(停止并 docker rm -f):

触发条件何时触发
docker_persist_across_processes: false显式的每个进程隔离。每次 cleanup() 执行 stop + rm -f。匹配问题 #20561 之前的行为。
空闲回收器(lifetime_seconds,默认 300 秒)仅当环境为 persist_across_processes=false 时。持久模式环境为无操作;容器在空闲扫描中存活。
下次启动时的孤立回收器清理已退出的 Hermes 标签容器,这些容器早于 2 × lifetime_seconds(默认 600 秒 = 10 分钟),范围限定到当前配置文件。正在运行的容器永远不会被触及 — 兄弟进程安全。设置 docker_orphan_reaper: false 以禁用。
用户直接操作docker rm -fdocker system prune、Docker Desktop 重启。我们不设置 --restart=always,因此主机重启会使容器处于 Exited 状态(其 CoW 层保留并在下次启动时重用,但后台进程消失)。

值得了解的边缘情况:

  • 容器内 PID 1 的 OOM 杀死 将容器转换为 Exited。下次重用将执行 docker start;文件系统状态保留,后台进程不保留。
  • 切换配置文件 将容器彼此隔离 — 标记为 hermes-profile=work 的容器对运行在 hermes-profile=research 下的 Hermes 进程不可见。孤立回收器也按配置文件范围限定,因此跨配置文件的容器不会意外被回收,但也不会自动清理,直到你在其原始配置文件下再次启动 Hermes。

通过 delegate_task(tasks=[...]) 生成的并行子代理共享这一个容器 — 并发的 cd、环境变量突变和对同一路径的写入将发生冲突。如果子代理需要隔离的沙箱,它必须通过 register_task_env_overrides() 注册每个任务的镜像覆盖,RL 和基准测试环境(TerminalBench2、HermesSweEnv 等)会自动为其每个任务的 Docker 镜像执行此操作。

安全强化:

  • --cap-drop ALL 仅添加回 DAC_OVERRIDECHOWNFOWNER
  • --security-opt no-new-privileges
  • --pids-limit 256
  • 大小限制的 tmpfs 用于 /tmp(512MB)、/var/tmp(256MB)、/run(64MB)

凭据转发: docker_forward_env 中列出的环境变量首先从你的 shell 环境解析,然后从 ~/.hermes/.env 解析。技能还可以声明 required_environment_variables,这些变量会自动合并。

环境变量覆盖

terminal: 下的每个键都有一个形式为 TERMINAL_<KEY_UPPERCASE> 的环境变量覆盖。Docker 后端最有用的几个:

环境变量映射到备注
TERMINAL_DOCKER_IMAGEdocker_image基础镜像
TERMINAL_DOCKER_FORWARD_ENVdocker_forward_envJSON 数组:'["GITHUB_TOKEN","OPENAI_API_KEY"]'
TERMINAL_DOCKER_ENVdocker_envJSON 字典:'{"DEBUG":"1"}'
TERMINAL_DOCKER_VOLUMESdocker_volumesJSON 数组,元素为 "host:container[:ro]" 字符串
TERMINAL_DOCKER_EXTRA_ARGSdocker_extra_argsJSON 数组
TERMINAL_DOCKER_MOUNT_CWD_TO_WORKSPACEdocker_mount_cwd_to_workspacetrue / false
TERMINAL_DOCKER_RUN_AS_HOST_USERdocker_run_as_host_usertrue / false
TERMINAL_DOCKER_PERSIST_ACROSS_PROCESSESdocker_persist_across_processestrue / false — 默认 true
TERMINAL_DOCKER_ORPHAN_REAPERdocker_orphan_reapertrue / false — 默认 true
TERMINAL_CONTAINER_CPUcontainer_cpuCPU 核心数
TERMINAL_CONTAINER_MEMORYcontainer_memoryMB
TERMINAL_CONTAINER_DISKcontainer_diskMB
TERMINAL_CONTAINER_PERSISTENTcontainer_persistenttrue / false — 控制绑定挂载的工作区目录,与 docker_persist_across_processes 不同
TERMINAL_LIFETIME_SECONDSlifetime_seconds空闲回收窗口
TERMINAL_TIMEOUTtimeout每个命令的超时时间
HERMES_DOCKER_BINARY强制使用特定的 docker/podman 二进制路径

SSH 后端

通过 SSH 在远程服务器上运行命令。使用 ControlMaster 进行连接重用(5 分钟空闲保活)。默认启用持久 shell — 状态(cwd、环境变量)跨命令保留。

yaml
terminal:
  backend: ssh
  persistent_shell: true           # 保持一个长期存在的 bash 会话(默认:true)

必需的环境变量:

bash
TERMINAL_SSH_HOST=my-server.example.com
TERMINAL_SSH_USER=ubuntu

可选的:

变量默认值描述
TERMINAL_SSH_PORT22SSH 端口
TERMINAL_SSH_KEY(系统默认)SSH 私钥路径
TERMINAL_SSH_PERSISTENTtrue启用持久 shell

工作原理: 在初始化时使用 BatchMode=yesStrictHostKeyChecking=accept-new 连接。持久 shell 在远程主机上保持一个单一的 bash -l 进程存活,通过临时文件进行通信。需要 stdin_datasudo 的命令会自动回退到一次性模式。

Modal 后端

Modal 云沙箱中运行命令。每个任务获得一个隔离的 VM,具有可配置的 CPU、内存和磁盘。文件系统可以跨会话快照/恢复。

yaml
terminal:
  backend: modal
  container_cpu: 1                 # CPU 核心数
  container_memory: 5120           # MB(5GB)
  container_disk: 51200            # MB(50GB)
  container_persistent: true       # 快照/恢复文件系统

必需: 要么 MODAL_TOKEN_ID + MODAL_TOKEN_SECRET 环境变量,要么 ~/.modal.toml 配置文件。

持久性: 启用后,沙箱文件系统在清理时被快照,并在下次会话时恢复。快照在 ~/.hermes/modal_snapshots.json 中跟踪。这保留文件系统状态,而不是实时进程、PID 空间或后台作业。

凭据文件: 自动从 ~/.hermes/ 挂载(OAuth 令牌等),并在每个命令之前同步。

Daytona 后端

Daytona 托管工作区中运行命令。支持停止/恢复以实现持久性。

yaml
terminal:
  backend: daytona
  container_cpu: 1                 # CPU 核心数
  container_memory: 5120           # MB → 转换为 GiB
  container_disk: 10240            # MB → 转换为 GiB(最大 10 GiB)
  container_persistent: true       # 停止/恢复而不是删除

必需: DAYTONA_API_KEY 环境变量。

持久性: 启用后,沙箱在清理时停止(而不是删除),并在下次会话时恢复。沙箱名称遵循模式 hermes-{task_id}

磁盘限制: Daytona 强制最大 10 GiB。超过此限制的请求会被限制并发出警告。

Singularity/Apptainer 后端

Singularity/Apptainer 容器中运行命令。专为 HPC 集群和共享机器设计,其中 Docker 不可用。

yaml
terminal:
  backend: singularity
  singularity_image: "docker://nikolaik/python-nodejs:python3.11-nodejs20"
  container_cpu: 1                 # CPU 核心数
  container_memory: 5120           # MB
  container_persistent: true       # 可写覆盖层跨会话持久化

要求: apptainersingularity 二进制文件在 $PATH 中。

镜像处理: Docker URL(docker://...)会自动转换为 SIF 文件并缓存。现有的 .sif 文件直接使用。

临时目录: 按以下顺序解析:TERMINAL_SCRATCH_DIRTERMINAL_SANDBOX_DIR/singularity/scratch/$USER/hermes-agent(HPC 约定) → ~/.hermes/sandboxes/singularity

隔离: 使用 --containall --no-home 实现完全命名空间隔离,而不挂载主机主目录。

常见终端后端问题

如果终端命令立即失败或终端工具报告为禁用:

  • Local — 无特殊要求。入门时最安全的默认值。
  • Docker — 运行 docker version 验证 Docker 是否正常工作。如果失败,修复 Docker 或 hermes config set terminal.backend local
  • SSH — 必须设置 TERMINAL_SSH_HOSTTERMINAL_SSH_USER。如果缺少任何一个,Hermes 会记录清晰的错误。
  • Modal — 需要 MODAL_TOKEN_ID 环境变量或 ~/.modal.toml。运行 hermes doctor 检查。
  • Daytona — 需要 DAYTONA_API_KEY。Daytona SDK 处理服务器 URL 配置。
  • Singularity — 需要 apptainersingularity$PATH 中。常见于 HPC 集群。

如有疑问,将 terminal.backend 设置回 local,并首先验证命令在那里运行。

拆除时远程到主机的文件同步

对于 SSHModalDaytona 后端(代理的工作树位于与运行 Hermes 的主机不同的机器上),Hermes 会跟踪代理在远程沙箱中接触的文件,并在会话拆除/沙箱清理时,将修改后的文件同步回主机,放在 ~/.hermes/cache/remote-syncs/<session-id>/ 下。

  • 触发条件:会话关闭、/new/reset、网关消息超时、delegate_task 子代理完成(当子代理使用远程后端时)。
  • 覆盖代理修改的整个树,而不仅仅是它显式打开的文件。添加、编辑和删除都会被捕获。
  • 远程沙箱可能在你查看时已被拆除;本地的 ~/.hermes/cache/remote-syncs/… 副本是代理更改的权威记录。
  • 大型二进制输出(模型检查点、原始数据集)受大小限制 — 同步会跳过超过 file_sync_max_mb(默认 100)的文件。如果你期望更大的工件返回,请增加该值。
yaml
terminal:
  file_sync_max_mb: 100     # 默认 — 同步每个最大 100 MB 的文件
  file_sync_enabled: true   # 默认 — 设置为 false 以完全跳过同步

这就是你从会话结束后被销毁的临时云沙箱中恢复结果的方式,而无需告诉代理显式地 scpmodal volume put 每个工件。

Docker 卷挂载

使用 Docker 后端时,docker_volumes 允许你与容器共享主机目录。每个条目使用标准的 Docker -v 语法:host_path:container_path[:options]

yaml
terminal:
  backend: docker
  docker_volumes:
    - "/home/user/projects:/workspace/projects"   # 读写(默认)
    - "/home/user/datasets:/data:ro"              # 只读
    - "/home/user/.hermes/cache/documents:/output" # 网关可见的导出

这对于以下情况很有用:

  • 提供文件给代理(数据集、配置、参考代码)
  • 接收文件从代理(生成的代码、报告、导出)
  • 共享工作区,你和代理都可以访问相同的文件

如果你使用消息网关并希望代理通过 MEDIA:/... 发送生成的文件,请优先使用专用的主机可见导出挂载,例如 /home/user/.hermes/cache/documents:/output

  • 在 Docker 内将文件写入 /output/...
  • MEDIA: 中发出主机路径,例如: MEDIA:/home/user/.hermes/cache/documents/report.txt
  • 不要发出 /workspace/.../output/...,除非该确切路径在主机上也存在于网关进程中

警告

YAML 重复键会静默覆盖较早的键。如果你已经有一个 docker_volumes: 块,请将新的挂载合并到同一个列表中,而不是在文件后面添加另一个 docker_volumes: 键。

也可以通过环境变量设置:TERMINAL_DOCKER_VOLUMES='["/host:/container"]'(JSON 数组)。

Docker 凭据转发

默认情况下,Docker 终端会话不会继承任意主机凭据。如果你需要在容器内使用特定的令牌,请将其添加到 terminal.docker_forward_env

yaml
terminal:
  backend: docker
  docker_forward_env:
    - "GITHUB_TOKEN"
    - "NPM_TOKEN"

Hermes 首先从当前 shell 解析每个列出的变量,然后回退到 ~/.hermes/.env(如果已使用 hermes config set 保存)。

警告

docker_forward_env 中列出的任何内容对容器内运行的命令都是可见的。仅转发你愿意暴露给终端会话的凭据。

以主机用户身份运行容器

默认情况下,Docker 容器以 root(UID 0)身份运行。在 /workspace 或其他绑定挂载中创建的文件最终在主机上由 root 拥有,因此会话结束后,你必须使用 sudo chown 才能从主机编辑器编辑它们。terminal.docker_run_as_host_user 标志解决了这个问题:

yaml
terminal:
  backend: docker
  docker_run_as_host_user: true   # 默认:false

启用后,Hermes 将 --user $(id -u):$(id -g) 附加到 docker run 命令,因此写入绑定挂载目录(/workspace/rootdocker_volumes 中的任何内容)的文件由你的主机用户拥有,而不是 root。权衡:容器无法再执行 apt install 或写入 root 拥有的路径(如 /root/.npm) — 如果你两者都需要,请使用 HOME 由非 root 用户拥有的基础镜像(或在镜像构建时添加所需的工具)。

保持此值为 false(默认)以实现向后兼容的行为。当你的工作流程主要是“编辑挂载的主机文件”并且你厌倦了 sudo chown -R 时,请将其打开。

可选:将启动目录挂载到 /workspace

Docker 沙箱默认保持隔离。Hermes 不会将当前主机工作目录传递到容器中,除非你明确选择加入。

config.yaml 中启用:

yaml
terminal:
  backend: docker
  docker_mount_cwd_to_workspace: true

启用后:

  • 如果你从 ~/projects/my-app 启动 Hermes,该主机目录将绑定挂载到 /workspace
  • Docker 后端在 /workspace 中启动
  • 文件工具和终端命令都看到相同的挂载项目

禁用后,/workspace 保持沙箱所有,除非你通过 docker_volumes 显式挂载某些内容。

安全权衡:

  • false 保留沙箱边界
  • true 使沙箱直接访问你启动 Hermes 的目录

仅当你有意希望容器处理实时主机文件时,才使用选择加入。

持久 Shell

默认情况下,每个终端命令在其自己的子进程中运行 — 工作目录、环境变量和 shell 变量在命令之间重置。当启用持久 shell 时,一个单一的长期存在的 bash 进程在 execute() 调用之间保持存活,因此状态在命令之间保留。

这对于 SSH 后端最有用,因为它还消除了每个命令的连接开销。持久 shell 默认为 SSH 启用,并为本地后端禁用。

yaml
terminal:
  persistent_shell: true   # 默认 — 为 SSH 启用持久 shell

要禁用:

bash
hermes config set terminal.persistent_shell false

跨命令持久化的内容:

  • 工作目录(cd /tmp 对下一个命令有效)
  • 导出的环境变量(export FOO=bar
  • Shell 变量(MY_VAR=hello

优先级:

级别变量默认值
配置terminal.persistent_shelltrue
SSH 覆盖TERMINAL_SSH_PERSISTENT跟随配置
本地覆盖TERMINAL_LOCAL_PERSISTENTfalse

每个后端的环境变量具有最高优先级。如果你也想要本地后端上的持久 shell:

bash
export TERMINAL_LOCAL_PERSISTENT=true

注意

需要 stdin_data 或 sudo 的命令会自动回退到一次性模式,因为持久 shell 的 stdin 已被 IPC 协议占用。

有关每个后端的详细信息,请参见 代码执行README 的终端部分

技能设置

技能可以通过其 SKILL.md 前置元数据声明自己的配置设置。这些是非机密值(路径、偏好、域设置),存储在 config.yamlskills.config 命名空间下。

yaml
skills:
  config:
    myplugin:
      path: ~/myplugin-data   # 示例 — 每个技能定义自己的键

技能设置的工作原理:

  • hermes config migrate 扫描所有启用的技能,找到未配置的设置,并提供提示
  • hermes config show 在“技能设置”下显示所有技能设置及其所属技能
  • 当技能加载时,其解析的配置值会自动注入到技能上下文中

手动设置值:

bash
hermes config set skills.config.myplugin.path ~/myplugin-data

有关在你自己技能中声明配置设置的详细信息,请参见 创建技能 — 配置设置

对代理创建的技能写入进行防护

当代理使用 skill_manage 创建、编辑、修补或删除技能时,Hermes 可以选择扫描新/更新的内容,查找危险的关键字模式(凭据收集、明显的提示注入、外泄指令)。扫描器默认关闭 — 真实的代理工作流合法地接触 ~/.ssh/ 或提及 $OPENAI_API_KEY 时,过于频繁地触发启发式规则。如果你希望扫描器在代理的技能写入落地之前提示你,请将其重新打开:

yaml
skills:
  guard_agent_created: true   # 默认:false

启用后,任何被标记的 skill_manage 写入都会显示为批准提示,并附有扫描器的理由。接受的写入落地;拒绝的写入向代理返回解释性错误。

技能写入的写入批准

独立于上述内容扫描器,skills.write_approval每个代理技能写入(创建/编辑/修补/删除/支持文件)置于你的明确批准之后 — 与危险命令相同的批准/拒绝机制:

yaml
skills:
  write_approval: false   # false = 自由写入(默认) | true = 将每个写入暂存以供审查

启用后,技能写入暂存在 ~/.hermes/pending/skills/ 下,并通过 /skills pending/skills diff <id>/skills approve <id>/skills reject <id> 进行审查 — 从 CLI 或任何消息平台。运行时使用 /skills approval on|off 切换。内存具有相同的门控(memory.write_approval,见下文)。完整演练:门控代理技能写入

内存配置

yaml
memory:
  memory_enabled: true
  user_profile_enabled: true
  memory_char_limit: 2200   # ~800 个令牌
  user_char_limit: 1375     # ~500 个令牌
  write_approval: false     # true = 任何内存写入前需要批准

使用 memory.write_approval: true 时,内存写入需要你的批准才能落地:交互式 CLI 会内联提示;消息会话和后台自我改进审查阶段会将写入暂存,供 /memory pending/memory approve <id> / /memory reject <id> 审查。运行时使用 /memory approval on|off 切换。参见 控制内存写入

上下文文件截断

控制 Hermes 在应用头/尾截断之前从每个自动上下文文件加载多少内容。这适用于注入到系统提示中的文件,如 SOUL.md.hermes.mdAGENTS.mdCLAUDE.md.cursorrules。它不影响 read_file 工具。

yaml
context_file_max_chars: 20000  # 默认

当你故意保留较大的身份或项目上下文文件,并且运行的模型具有足够的上下文窗口来承载它们时,请提高此值:

yaml
context_file_max_chars: 25000

文件读取安全

控制单个 read_file 调用可以返回多少内容。超过限制的读取会被拒绝,并返回错误,告诉代理使用 offsetlimit 获取较小的范围。这可以防止单个读取小型化的 JS 包或大型数据文件淹没上下文窗口。

yaml
file_read_max_chars: 100000  # 默认 — ~25-35K 个令牌

如果你使用具有大上下文窗口的模型并且经常读取大文件,请提高此值。对于小上下文模型,降低此值以保持读取效率:

yaml
## 大上下文模型(200K+)
file_read_max_chars: 200000
## 小型本地模型(16K 上下文)
file_read_max_chars: 30000

代理还会自动去重文件读取 — 如果同一文件区域被读取两次且文件未更改,则返回一个轻量级存根,而不是重新发送内容。这在上下文压缩时重置,以便代理可以在其内容被摘要化后重新读取文件。

工具输出截断限制

三个相关的上限控制工具在 Hermes 截断之前可以返回多少原始输出:

yaml
tool_output:
  max_bytes: 50000        # 终端输出上限(字符数)
  max_lines: 2000         # read_file 分页上限
  max_line_length: 2000   # read_file 行号视图中的每行上限
  • max_bytes — 当 terminal 命令产生的组合 stdout/stderr 超过此字符数时,Hermes 保留前 40% 和后 60%,并在它们之间插入 [OUTPUT TRUNCATED] 通知。默认 50000(在典型分词器上约为 12-15K 个令牌)。
  • max_lines — 单个 read_file 调用的 limit 参数的上限。超过此上限的请求会被限制,因此单个读取不会淹没上下文窗口。默认 2000
  • max_line_length — 当 read_file 发出行号视图时应用的每行上限。超过此长度的行被截断为此字符数,后跟 ... [truncated]。默认 2000

在具有大上下文窗口的模型上提高限制,这些模型可以承受每次调用更多的原始输出。对于小上下文模型降低限制,以保持工具结果紧凑:

yaml
## 大上下文模型(200K+)
tool_output:
  max_bytes: 150000
  max_lines: 5000
## 小型本地模型(16K 上下文)
tool_output:
  max_bytes: 20000
  max_lines: 500

全局工具集禁用

要在一个地方抑制跨 CLI 和每个网关平台的特定工具集,请在 agent.disabled_toolsets 下列出它们的名称:

yaml
agent:
  disabled_toolsets:
    - memory       # 隐藏内存工具 + MEMORY_GUIDANCE 注入
    - web          # 任何地方都没有 web_search / web_extract

每个平台工具配置(由 hermes tools 写入的 platform_toolsets)之后应用,因此此处列出的工具集始终被移除 — 即使平台的已保存配置仍然列出它。当你想要一个单一的开关来“在所有地方关闭 X”而不是在 hermes tools UI 中编辑 15 多个平台行时,请使用此选项。

将列表留空或省略键,则无操作。

Git 工作树隔离

启用隔离的 git 工作树,以便在同一仓库上并行运行多个代理:

yaml
worktree: true    # 始终创建工作树(与 hermes -w 相同)
## worktree: false # 默认 — 仅当传递 -w 标志时

启用后,每个 CLI 会话在 .worktrees/ 下创建一个新的工作树,并带有自己的分支。代理可以编辑文件、提交、推送和创建 PR,而不会相互干扰。干净的工作树在退出时被删除;脏的工作树保留用于手动恢复。

你还可以通过仓库根目录中的 .worktreeinclude 列出要复制到工作树中的 gitignore 文件:

text
## .worktreeinclude
.env
.venv/
node_modules/

上下文压缩

Hermes 自动压缩长对话,以保持在模型的上下文窗口内。压缩摘要器是一个单独的 LLM 调用 — 你可以将其指向任何提供商或端点。

所有压缩设置都位于 config.yaml 中(无环境变量)。

完整参考

yaml
compression:
  enabled: true                                     # 切换压缩开/关
  threshold: 0.50                                   # 在上下文限制的此百分比处压缩
  target_ratio: 0.20                                # 要保留为最近尾部的阈值分数
  protect_last_n: 20                                # 保持未压缩的最近消息的最小数量
  protect_first_n: 3                                # 跨压缩固定的非系统头部消息(0 = 不固定任何内容)
  hygiene_hard_message_limit: 400                   # 网关安全阀 — 见下文
## 摘要模型/提供商在 auxiliary 下配置:
auxiliary:
  compression:
    model: ""                                       # 空 = 使用主聊天模型。覆盖为例如 "google/gemini-3-flash-preview" 以获得更便宜/更快的压缩。
    provider: "auto"                                # 提供商:"auto"、"openrouter"、"nous"、"codex"、"main" 等。
    base_url: null                                  # 自定义 OpenAI 兼容端点(覆盖提供商)

信息 — 旧配置迁移

具有 compression.summary_modelcompression.summary_providercompression.summary_base_url 的旧配置会在首次加载时自动迁移到 auxiliary.compression.*(配置版本 17)。无需手动操作。

hygiene_hard_message_limit 是仅限网关的预压缩安全阀。具有数千条消息的失控会话可能会在正常的上下文百分比阈值触发之前达到模型上下文限制;当消息计数超过此上限时,Hermes 会强制压缩,无论令牌使用情况如何。默认 400 — 对于非常长会话是正常的平台,请提高此值;降低以强制更积极的压缩。在运行中的网关上编辑此值会在下一条消息时生效(见下文)。

protect_first_n 控制每次压缩时固定的非系统头部消息数量。默认 3 — 开头的用户/助手交换会在每次摘要器传递中存活,因此原始目标保持可见。在长时间运行的滚动压缩会话中,如果开头的轮次不再相关,请设置 protect_first_n: 0 以仅固定系统提示 + 摘要 + 尾部。系统提示本身始终保留,无论此设置如何。

提示 — 网关热重载压缩和上下文长度

从最近的版本开始,在运行中的网关上编辑 model.context_length 或任何 compression.* 键会在下一条消息时生效 — 无需网关重启、/reset 或会话轮换。缓存的代理签名包含这些键,因此网关在检测到更改时会透明地重建代理。API 密钥和工具/技能配置仍然需要通常的重载路径。

常见设置

默认(自动检测)— 无需配置:

yaml
compression:
  enabled: true
  threshold: 0.50

使用你的主提供商和主模型。如果你希望压缩使用比主聊天模型更便宜的模型,请按任务覆盖(例如 auxiliary.compression.provider: openrouter + model: google/gemini-2.5-flash)。

强制使用特定提供商(基于 OAuth 或 API 密钥):

yaml
auxiliary:
  compression:
    provider: nous
    model: gemini-3-flash

适用于任何提供商:nousopenroutercodexanthropicmain 等。

自定义端点(自托管、Ollama、zai、DeepSeek 等):

yaml
auxiliary:
  compression:
    model: glm-4.7
    base_url: https://api.z.ai/api/coding/paas/v4

指向自定义 OpenAI 兼容端点。使用 OPENAI_API_KEY 进行身份验证。

三个旋钮如何交互

auxiliary.compression.providerauxiliary.compression.base_url结果
auto(默认)未设置自动检测最佳可用提供商
nous / openrouter未设置强制使用该提供商,使用其身份验证
任意设置直接使用自定义端点(提供商被忽略)

警告 — 摘要模型上下文长度要求

摘要模型必须具有至少与主代理模型一样大的上下文窗口。压缩器将对话的完整中间部分发送给摘要模型 — 如果该模型的上下文窗口小于主模型的上下文窗口,则摘要调用将失败并出现上下文长度错误。发生这种情况时,中间轮次在没有摘要的情况下被丢弃,从而静默丢失对话上下文。如果你覆盖模型,请验证其上下文长度是否达到或超过主模型的上下文长度。

上下文引擎

上下文引擎控制当接近模型的令牌限制时如何管理对话。内置的 compressor 引擎使用有损摘要(参见 上下文压缩)。插件引擎可以用替代策略替换它。

yaml
context:
  engine: "compressor"    # 默认 — 内置有损摘要

要使用插件引擎(例如 LCM 用于无损上下文管理):

yaml
context:
  engine: "lcm"          # 必须与插件的名称匹配

插件引擎永远不会自动激活 — 你必须显式地将 context.engine 设置为插件名称。可用的引擎可以通过 hermes plugins → 提供商插件 → 上下文引擎进行浏览和选择。

参见 内存提供商 了解内存插件的类似单选系统。

迭代预算压力

当代理处理具有许多工具调用的复杂任务时,它可能会在未意识到即将耗尽的情况下消耗其迭代预算(默认:90 轮)。预算压力会在接近限制时自动警告模型:

阈值级别模型看到的内容
70%谨慎[BUDGET: 63/90. 27 iterations left. Start consolidating.]
90%警告[BUDGET WARNING: 81/90. Only 9 left. Respond NOW.]

警告被注入到最后一个工具结果的 JSON 中(作为 _budget_warning 字段),而不是作为单独的消息 — 这保留了提示缓存,并且不会破坏对话结构。

yaml
agent:
  max_turns: 90                # 每轮对话的最大迭代次数(默认:90)
  api_max_retries: 3           # 在回退启用之前每个提供商的重试次数(默认:3)

预算压力默认启用。代理作为工具结果的一部分自然看到警告,鼓励它整合工作并在迭代耗尽之前提供响应。

当迭代预算完全耗尽时,CLI 会向用户显示通知:⚠ 迭代预算已用尽(90/90)— 响应可能不完整。如果在活动工作期间预算耗尽,代理会在停止之前生成已完成内容的摘要。

agent.api_max_retries 控制 Hermes 在瞬态错误(速率限制、连接断开、5xx)上重试提供商 API 调用的次数,然后才进行回退提供商切换。默认值为 3 — 总共四次尝试。如果你配置了回退提供商并希望更快地故障转移,请将其降低到 0,这样主提供商上的第一个瞬态错误会立即交给回退,而不是对故障端点进行重试。

API 超时

Hermes 为流式传输设置了单独的超时层,以及用于非流式调用的陈旧检测器。仅当你将它们保留为隐式默认值时,陈旧检测器才会自动调整本地提供商。

超时默认值本地提供商配置 / 环境变量
Socket 读取超时120 秒自动提高到 1800 秒HERMES_STREAM_READ_TIMEOUT
陈旧流检测180 秒自动禁用HERMES_STREAM_STALE_TIMEOUT
陈旧非流检测300 秒隐式时自动禁用providers.<id>.stale_timeout_secondsHERMES_API_CALL_STALE_TIMEOUT
API 调用(非流式)1800 秒不变providers.<id>.request_timeout_seconds / timeout_secondsHERMES_API_TIMEOUT

Socket 读取超时控制 httpx 等待来自提供商的下一块数据的时间。本地 LLM 可能需要几分钟进行大上下文预填充,然后才产生第一个令牌,因此 Hermes 在检测到本地端点时将其提高到 30 分钟。如果你显式设置 HERMES_STREAM_READ_TIMEOUT,则无论端点检测如何,始终使用该值。

陈旧流检测会杀死接收 SSE 保活 ping 但没有实际内容的连接。对于本地提供商,这完全禁用,因为它们在预填充期间不发送保活 ping。

陈旧非流检测会杀死长时间没有产生响应的非流式调用。默认情况下,Hermes 在本地端点上禁用此功能,以避免在长预填充期间出现误报。如果你显式设置 providers.<id>.stale_timeout_secondsproviders.<id>.models.<model>.stale_timeout_secondsHERMES_API_CALL_STALE_TIMEOUT,则该显式值即使在本地端点上也会被遵守。

上下文压力警告

与迭代预算压力分开,上下文压力跟踪对话距离压缩阈值有多近 — 即上下文压缩触发以摘要化旧消息的点。这有助于你和代理了解对话何时变长。

进度级别发生什么
≥ 60% 到阈值信息CLI 显示青色进度条;网关发送信息通知
≥ 85% 到阈值警告CLI 显示粗体黄色条;网关警告压缩即将发生

在 CLI 中,上下文压力显示为工具输出流中的进度条:

◐ context ████████████░░░░░░░░ 62% to compaction 48k threshold (50%) · approaching compaction

在消息平台上,发送纯文本通知:

◐ Context: ████████████░░░░░░░░ 62% to compaction (threshold: 50% of window).

如果自动压缩被禁用,警告会告诉你上下文可能被截断。

上下文压力是自动的 — 无需配置。它纯粹作为面向用户的通知触发,不会修改消息流或将任何内容注入模型的上下文。

凭据池策略

当你为同一提供商拥有多个 API 密钥或 OAuth 令牌时,配置轮换策略:

yaml
credential_pool_strategies:
  openrouter: round_robin    # 均匀循环使用密钥
  anthropic: least_used      # 始终选择使用最少的密钥

选项:fill_first(默认)、round_robinleast_usedrandom。参见 凭据池 获取完整文档。

提示缓存

当活动提供商支持时,Hermes 会自动启用跨会话提示缓存 — 无需用户配置。

对于 原生 AnthropicOpenRouterNous Portal 上的 Claude,Hermes 在系统提示和技能块上附加 cache_control 断点,TTL 为 1 小时(ttl: "1h")。在新的一小时内第一次发送支付完整的输入费率;同一小时内跨任何会话的后续发送从缓存中提取,享受折扣的缓存读取费率。这意味着系统提示、加载的技能内容以及任何长上下文包含的早期部分会在 hermes 会话和分叉的子代理之间重用,持续第一个小时。

Qwen Cloud(阿里云 DashScope)上游将缓存 TTL 限制为 5 分钟,因此 Hermes 在那里使用 5 分钟断点 TTL。其他通过第三方路径的 Claude(AWS Bedrock、Azure Foundry)回退到提供商自己的缓存默认值。xAI Grok 使用单独的会话固定 conversation-id 机制 — 参见 xAI 提示缓存

没有旋钮可以禁用它 — 缓存始终开启,即使在单轮对话中也能节省资金,因为仅系统提示就占了输入令牌数量的重要部分。

辅助模型

Hermes 使用“辅助”模型处理侧边任务,如图像分析、网页摘要、浏览器截图分析、会话标题生成和上下文压缩。默认情况下(auxiliary.*.provider: "auto"),Hermes 将每个辅助任务路由到你的主聊天模型 — 你在 hermes model 中选择的相同提供商/模型。你无需配置任何内容即可开始,但请注意,在昂贵的推理模型(Opus、MiniMax M2.7 等)上,辅助任务会增加可观的成本。如果你希望无论主模型如何,侧边任务都快速且便宜,请显式设置 auxiliary.<task>.providerauxiliary.<task>.model(例如,在 OpenRouter 上使用 Gemini Flash 进行视觉和网页提取)。

注意 — 为什么“auto”使用你的主模型

早期版本将聚合器用户(OpenRouter、Nous Portal)拆分到便宜的提供商侧默认值。这令人惊讶 — 为聚合器订阅付费的用户会看到不同的模型处理他们的辅助流量。auto 现在为所有人使用主模型,并且 config.yaml 中的每个任务覆盖仍然有效(参见下面的完整辅助配置参考)。

交互式配置辅助模型

无需手动编辑 YAML,运行 hermes model 并从菜单中选择 “配置辅助模型”。你将获得一个交互式每个任务选择器:

text
$ hermes model
→ 配置辅助模型

[ ] vision               currently: auto / main model
[ ] web_extract          currently: auto / main model
[ ] title_generation     currently: openrouter / google/gemini-3-flash-preview
[ ] tts_audio_tags       currently: auto / main model
[ ] compression          currently: auto / main model
[ ] approval             currently: auto / main model
[ ] triage_specifier     currently: auto / main model
[ ] kanban_decomposer    currently: auto / main model
[ ] profile_describer    currently: auto / main model

选择一个任务,选择一个提供商(OAuth 流程会打开浏览器;API 密钥提供商提示),选择一个模型。更改会持久化到 config.yaml 中的 auxiliary.<task>.*。与主模型选择器相同的机制 — 无需学习额外语法。

视频教程

视频: 在 YouTube 上观看

通用配置模式

Hermes 中的每个模型插槽 — 辅助任务、压缩、回退 — 都使用相同的三个旋钮:

作用默认值
provider用于身份验证和路由的提供商"auto"
model要请求的模型提供商的默认值
base_url自定义 OpenAI 兼容端点(覆盖提供商)未设置

当设置 base_url 时,Hermes 忽略提供商并直接调用该端点(使用 api_keyOPENAI_API_KEY 进行身份验证)。当仅设置 provider 时,Hermes 使用该提供商的内置身份验证和基础 URL。

辅助任务可用的提供商:automain,以及提供商注册表中的任何提供商 — openrouternousopenai-codexcopilotcopilot-acpanthropicgeminigoogle-gemini-cliqwen-oauthzaikimi-codingkimi-coding-cnminimaxminimax-cnminimax-oauthdeepseeknvidiaxaixai-oauthollama-cloudalibababedrockhuggingfacearceexiaomikilocodeopencode-zenopencode-goazure-foundry — 或来自你的 custom_providers 列表的任何命名自定义提供商(例如 provider: "beans")。

提示 — MiniMax OAuth

minimax-oauth 通过浏览器 OAuth 登录(无需 API 密钥)。运行 hermes model 并选择 MiniMax (OAuth) 进行身份验证。辅助任务自动使用 MiniMax-M2.7-highspeed。参见 MiniMax OAuth 指南

提示 — xAI Grok OAuth

xai-oauth 通过浏览器 OAuth 为 SuperGrok 和 X Premium+ 订阅者登录(无需 API 密钥)。运行 hermes model 并选择 xAI Grok OAuth (SuperGrok / Premium+) 进行身份验证。相同的 OAuth 令牌会重用于每个直接到 xAI 的表面(聊天、辅助任务、TTS、图像生成、视频生成、转录)。参见 xAI Grok OAuth 指南,如果 Hermes 在远程主机上,请参见 通过 SSH / 远程主机的 OAuth

警告 — "main" 仅用于辅助任务

"main" 提供商选项意味着“使用我的主代理使用的任何提供商” — 它仅在 auxiliary:compression: 和主回退条目(fallback_providers: 或旧版 fallback_model:)内有效。它不是你的顶级 model.provider 设置的有效值。如果你使用自定义 OpenAI 兼容端点,请在 model: 部分设置 provider: custom。参见 AI 提供商 了解所有主模型提供商选项。

完整辅助配置参考

yaml
auxiliary:
## 图像分析(vision_analyze 工具 + 浏览器截图)
  vision:
    provider: "auto"           # "auto", "openrouter", "nous", "codex", "main" 等。
    model: ""                  # 例如 "openai/gpt-4o", "google/gemini-2.5-flash"
    base_url: ""               # 自定义 OpenAI 兼容端点(覆盖提供商)
    api_key: ""                # base_url 的 API 密钥(回退到 OPENAI_API_KEY)
    timeout: 120               # 秒 — LLM API 调用超时;视觉负载需要慷慨的超时
    download_timeout: 30       # 秒 — 图像 HTTP 下载;对于慢速连接增加此值
## 网页摘要 + 浏览器页面文本提取
  web_extract:
    provider: "auto"
    model: ""                  # 例如 "google/gemini-2.5-flash"
    base_url: ""
    api_key: ""
    timeout: 360               # 秒(6 分钟)— 每次尝试的 LLM 摘要
## 危险命令批准分类器
  approval:
    provider: "auto"
    model: ""
    base_url: ""
    api_key: ""
    timeout: 30                # 秒
## Gemini 3.1 TTS 隐藏音频标签插入
  tts_audio_tags:
    provider: "auto"
    model: ""                  # 空 = 主聊天模型
    base_url: ""
    api_key: ""
    timeout: 30
## 上下文压缩超时(与 compression.* 配置分开)
  compression:
    timeout: 120               # 秒 — 压缩摘要化长对话,需要更多时间
## 技能中心 — 技能匹配和搜索
  skills_hub:
    provider: "auto"
    model: ""
    base_url: ""
    api_key: ""
    timeout: 30
## MCP 工具调度
  mcp:
    provider: "auto"
    model: ""
    base_url: ""
    api_key: ""
    timeout: 30
## Kanban 分类说明器 — `hermes kanban specify <id>`(或仪表板上 Triage 列卡片的 ✨ Specify 按钮)使用此插槽将一行说明扩展为具体规范并将任务提升到 `todo`。便宜快速的模型在这里效果很好;规范扩展很短,不需要推理深度。
  triage_specifier:
    provider: "auto"
    model: ""
    base_url: ""
    api_key: ""
    timeout: 120

提示

每个辅助任务都有一个可配置的 timeout(以秒为单位)。默认值:vision 120 秒,web_extract 360 秒,approval 30 秒,compression 120 秒。如果你为辅助任务使用慢速本地模型,请增加这些值。Vision 还有一个单独的 download_timeout(默认 30 秒)用于 HTTP 图像下载 — 对于慢速连接或自托管图像服务器,请增加此值。

信息

上下文压缩有自己的 compression: 块用于阈值,以及 auxiliary.compression: 块用于模型/提供商设置 — 参见上面的上下文压缩。主回退链使用顶级的 fallback_providers: 列表 — 参见回退提供商。所有三个都遵循相同的 provider/model/base_url 模式。

OpenRouter 路由和辅助任务的 Pareto Code

当辅助任务解析为 OpenRouter(无论是显式还是通过 provider: "main" 而你的主代理在 OpenRouter 上)时,主代理的 provider_routingopenrouter.min_coding_score 设置不会传播 — 按设计,每个辅助任务都是独立的。要为特定辅助任务设置 OpenRouter 提供商首选项或使用 Pareto Code 路由器,请通过 extra_body 按任务设置:

yaml
auxiliary:
  compression:
    provider: openrouter
    model: openrouter/pareto-code         # 为此任务使用 Pareto Code 路由器
    extra_body:
      provider:                            # OpenRouter 提供商路由首选项
        order: [anthropic, google]         # 按顺序尝试这些提供商
        sort: throughput                   # 或 "price" | "latency"
## only: [anthropic]                # 限制到特定提供商
## ignore: [deepinfra]              # 排除特定提供商
      plugins:                             # OpenRouter Pareto Code 路由器旋钮
        - id: pareto-router
          min_coding_score: 0.5            # 0.0–1.0;越高 = 更强的编码器

其形状与 OpenRouter 在聊天补全请求体中接受的相同。Hermes 逐字转发整个 extra_body,因此 openrouter.ai/docs 中记录的任何其他 OpenRouter 请求体字段都以相同方式工作。

更改视觉模型

要使用 GPT-4o 而不是 Gemini Flash 进行图像分析:

yaml
auxiliary:
  vision:
    model: "openai/gpt-4o"

或通过环境变量(在 ~/.hermes/.env 中):

bash
AUXILIARY_VISION_MODEL=openai/gpt-4o

提供商选项

这些选项适用于辅助任务配置auxiliary:compression:)和主回退条目(fallback_providers: 或旧版 fallback_model:),不适用于你的主 model.provider 设置。

提供商描述要求
"auto"最佳可用(默认)。Vision 尝试 OpenRouter → Nous → Codex。
"openrouter"强制 OpenRouter — 路由到任何模型(Gemini、GPT-4o、Claude 等)OPENROUTER_API_KEY
"nous"强制 Nous Portalhermes auth
"codex"强制 Codex OAuth(ChatGPT 帐户)。支持视觉(gpt-5.3-codex)。hermes model → Codex
"minimax-oauth"强制 MiniMax OAuth(浏览器登录,无需 API 密钥)。辅助任务使用 MiniMax-M2.7-highspeed。hermes model → MiniMax (OAuth)
"xai-oauth"强制 xAI Grok OAuth(浏览器登录,适用于 SuperGrok 或 X Premium+ 订阅者,无需 API 密钥)。相同的 OAuth 令牌覆盖聊天、TTS、图像、视频和转录。hermes model → xAI Grok OAuth (SuperGrok / Premium+)
"main"使用你的活动自定义/主端点。这可以来自 OPENAI_BASE_URL + OPENAI_API_KEY 或通过 hermes model / config.yaml 保存的自定义端点。适用于 OpenAI、本地模型或任何 OpenAI 兼容 API。仅限辅助任务 — 对 model.provider 无效。自定义端点凭据 + 基础 URL

主提供商目录中的直接 API 密钥提供商也可以在这里工作,当你希望侧边任务绕过默认路由器时。一旦配置了 GMI_API_KEYgmi 就有效:

yaml
auxiliary:
  compression:
    provider: "gmi"
    model: "anthropic/claude-opus-4.6"

对于 GMI 辅助路由,请使用 GMI 的 /v1/models 端点返回的确切模型 ID。

常见设置

使用直接自定义端点(比 provider: "main" 更清晰,用于本地/自托管 API):

yaml
auxiliary:
  vision:
    base_url: "http://localhost:1234/v1"
    api_key: "local-key"
    model: "qwen2.5-vl"

base_url 优先于 provider,因此这是将辅助任务路由到特定端点最明确的方式。对于直接端点覆盖,Hermes 使用配置的 api_key 或回退到 OPENAI_API_KEY;它不会为该自定义端点重用 OPENROUTER_API_KEY

使用 OpenAI API 密钥进行视觉:

yaml
## 在 ~/.hermes/.env 中:
## OPENAI_BASE_URL=https://api.openai.com/v1
## OPENAI_API_KEY=sk-...

auxiliary:
  vision:
    provider: "main"
    model: "gpt-4o"       # 或 "gpt-4o-mini" 以获得更便宜

使用 OpenRouter 进行视觉(路由到任何模型):

yaml
auxiliary:
  vision:
    provider: "openrouter"
    model: "openai/gpt-4o"      # 或 "google/gemini-2.5-flash" 等。

使用 Codex OAuth(ChatGPT Pro/Plus 帐户 — 无需 API 密钥):

yaml
auxiliary:
  vision:
    provider: "codex"     # 使用你的 ChatGPT OAuth 令牌
## 模型默认为 gpt-5.3-codex(支持视觉)

使用 MiniMax OAuth(浏览器登录,无需 API 密钥):

yaml
model:
  default: MiniMax-M2.7
  provider: minimax-oauth
  base_url: https://api.minimax.io/anthropic

运行 hermes model 并选择 MiniMax (OAuth) 登录并自动设置此配置。对于中国区域,基础 URL 将是 https://api.minimaxi.com/anthropic。参见 MiniMax OAuth 指南 获取完整演练。

使用本地/自托管模型:

yaml
auxiliary:
  vision:
    provider: "main"      # 使用你的活动自定义端点
    model: "my-local-model"

provider: "main" 使用 Hermes 用于正常聊天的任何提供商 — 无论是命名的自定义提供商(例如 beans)、内置提供商(如 openrouter),还是旧版 OPENAI_BASE_URL 端点。

提示

如果你使用 Codex OAuth 作为主模型提供商,视觉会自动工作 — 无需额外配置。Codex 包含在视觉的自动检测链中。

警告

视觉需要多模态模型。 如果你设置 provider: "main",请确保你的端点支持多模态/视觉 — 否则图像分析将失败。

环境变量(旧版)

辅助模型也可以通过环境变量配置。然而,config.yaml 是首选方法 — 它更易于管理,并支持所有选项,包括 base_urlapi_key

设置环境变量
Vision 提供商AUXILIARY_VISION_PROVIDER
Vision 模型AUXILIARY_VISION_MODEL
Vision 端点AUXILIARY_VISION_BASE_URL
Vision API 密钥AUXILIARY_VISION_API_KEY
Web extract 提供商AUXILIARY_WEB_EXTRACT_PROVIDER
Web extract 模型AUXILIARY_WEB_EXTRACT_MODEL
Web extract 端点AUXILIARY_WEB_EXTRACT_BASE_URL
Web extract API 密钥AUXILIARY_WEB_EXTRACT_API_KEY

压缩和回退模型设置仅限 config.yaml。

提示

运行 hermes config 查看你当前的辅助模型设置。覆盖仅在它们与默认值不同时显示。

推理努力

控制模型在响应之前进行多少“思考”:

yaml
agent:
  reasoning_effort: ""   # 空 = medium(默认)。选项:none, minimal, low, medium, high, xhigh (max)

当未设置(默认)时,推理努力默认为“medium” — 一个平衡的级别,适用于大多数任务。设置一个值会覆盖它 — 更高的推理努力在复杂任务上提供更好的结果,但代价是更多的令牌和延迟。

注意 — 自适应思考模型(Claude 4.6+、Fable/Mythos 类)通过 OpenRouter

这些模型使用自适应思考,不接受通常的 reasoning.effort 字段 — OpenRouter 会忽略它。Hermes 透明地将你的 reasoning_effort 路由到 OpenRouter 的 verbosity 参数(它映射到 Anthropic 的 output_config.effort),因此相同的 low/medium/high/xhigh 旋钮继续工作 — 无需额外配置。none(或未设置)让模型使用其自己的自适应默认值。(max 在线上被接受,但不是一个可选择的 reasoning_effort 值;xhigh 是可配置的上限。)原生 Anthropic 提供商已经直接控制努力,不受影响。

你也可以在运行时使用 /reasoning 命令更改推理努力:

text
/reasoning           # 显示当前努力级别和显示状态
/reasoning high      # 将推理努力设置为 high
/reasoning none      # 禁用推理
/reasoning show      # 在每个响应上方显示模型思考
/reasoning hide      # 隐藏模型思考

工具使用强制

某些模型偶尔会将预期的操作描述为文本,而不是进行工具调用(“我会运行测试...”而不是实际调用终端)。工具使用强制会注入系统提示指导,将模型引导回实际调用工具。

yaml
agent:
  tool_use_enforcement: "auto"   # "auto" | true | false | ["model-substring", ...]
行为
"auto"(默认)对匹配的模型启用:gptcodexgeminigemmagrok。对所有其他模型禁用(Claude、DeepSeek、Qwen 等)。
true始终启用,无论模型如何。如果你注意到当前模型描述操作而不是执行操作,则很有用。
false始终禁用,无论模型如何。
["gpt", "codex", "qwen", "llama"]仅当模型名称包含列出的子字符串之一时启用(不区分大小写)。

它注入什么

启用后,可能会向系统提示添加三层指导:

  1. 通用工具使用强制(所有匹配的模型) — 指示模型立即进行工具调用而不是描述意图,继续工作直到任务完成,并且永远不要以未来行动的承诺结束一轮。

  2. OpenAI 执行纪律(仅限 GPT 和 Codex 模型) — 额外的指导,解决 GPT 特定的失败模式:在部分结果上放弃工作、跳过先决条件查找、幻觉而不是使用工具、以及在没有验证的情况下声明“完成”。

  3. Google 操作指导(仅限 Gemini 和 Gemma 模型) — 简洁性、绝对路径、并行工具调用和先验证后编辑的模式。

这些对用户透明,仅影响系统提示。已经可靠使用工具的模型(如 Claude)不需要此指导,这就是为什么 "auto" 排除它们。

何时打开

如果你使用的模型不在默认的自动列表中,并且注意到它经常描述它做什么而不是实际去做,请设置 tool_use_enforcement: true 或将模型子字符串添加到列表中:

yaml
agent:
  tool_use_enforcement: ["gpt", "codex", "gemini", "grok", "my-custom-model"]

TTS 配置

yaml
tts:
  provider: "edge"              # "edge" | "elevenlabs" | "openai" | "minimax" | "mistral" | "gemini" | "xai" | "neutts"
  speed: 1.0                    # 全局速度乘数(所有提供商的后备)
  edge:
    voice: "en-US-AriaNeural"   # 322 种声音,74 种语言
    speed: 1.0                  # 速度乘数(转换为速率百分比,例如 1.5 → +50%)
  elevenlabs:
    voice_id: "pNInz6obpgDQGcFmaJgB"
    model_id: "eleven_multilingual_v2"
  openai:
    model: "gpt-4o-mini-tts"
    voice: "alloy"              # alloy, echo, fable, onyx, nova, shimmer
    speed: 1.0                  # 速度乘数(由 API 限制在 0.25–4.0)
    base_url: "https://api.openai.com/v1"  # 覆盖用于 OpenAI 兼容 TTS 端点
  minimax:
    speed: 1.0                  # 语音速度乘数
## base_url: ""              # 可选:覆盖用于 OpenAI 兼容 TTS 端点
  mistral:
    model: "voxtral-mini-tts-2603"
    voice_id: "c69964a6-ab8b-4f8a-9465-ec0925096ec8"  # Paul - Neutral(默认)
  gemini:
    model: "gemini-2.5-flash-preview-tts"   # 或 gemini-3.1-flash-tts-preview
    voice: "Kore"               # 30 种预制声音:Zephyr, Puck, Kore, Enceladus 等。
    audio_tags: false           # 隐藏的 Gemini 3.1 TTS 音频标签插入
    persona_prompt_file: ""      # 可选的 Markdown/文本文件,包含 Gemini 语音方向
  xai:
    voice_id: "eve"             # xAI TTS 声音
    language: "en"              # ISO 639-1
    sample_rate: 24000
    bit_rate: 128000            # MP3 比特率
## base_url: "https://api.x.ai/v1"
  neutts:
    ref_audio: ''
    ref_text: ''
    model: neuphonic/neutts-air-q4-gguf
    device: cpu

这控制 text_to_speech 工具和语音模式下的语音回复(CLI 或消息网关中的 /voice tts)。

速度回退层次结构: 提供商特定速度(例如 tts.edge.speed) → 全局 tts.speed1.0 默认值。设置全局 tts.speed 以在所有提供商上应用统一速度,或按提供商覆盖以进行精细控制。

显示设置

yaml
display:
  tool_progress: all      # off | new | all | verbose
  tool_progress_command: false  # 在消息网关中启用 /verbose 斜杠命令
  platforms: {}           # 每个平台的显示覆盖(见下文)
  tool_progress_overrides: {}  # 已弃用 — 改用 display.platforms
  interim_assistant_messages: true  # 网关:将完成的中间轮次助手更新作为单独的消息发送
  skin: default           # 内置或自定义 CLI 皮肤(参见 user-guide/features/skins)
  personality: "kawaii"  # 旧版装饰字段,仍在某些摘要中显示
  compact: false          # 紧凑输出模式(更少的空白)
  resume_display: full    # full(恢复时显示先前的消息)| minimal(仅一行)
  bell_on_complete: false # 代理完成时播放终端铃声(适合长任务)
  show_reasoning: false   # 在每个响应上方显示模型推理/思考(使用 /reasoning show|hide 切换)
  streaming: false        # 将令牌流式传输到终端(实时输出)
  show_cost: false        # 在 CLI 状态栏中显示估计的 $ 成本
  timestamps: false       # 当为 true 时,在 CLI / TUI 转录中为用户和助手标签添加 [HH:MM] 时间戳前缀
  tool_preview_length: 0  # 工具调用预览的最大字符数(0 = 无限制,显示完整路径/命令)
  runtime_footer:         # 网关:将运行时上下文页脚附加到最终回复
    enabled: false
    fields: ["model", "context_pct", "cwd"]
  file_mutation_verifier: true    # 当 write_file/patch 调用在此轮中失败时,附加建议页脚
  credits_notices: true   # Nous 积分状态栏通知(使用情况波段、赠款支出、耗尽)。false = 静音;/usage 仍然有效
  language: en            # 静态消息的 UI 语言(批准提示、某些网关回复)。en | zh | zh-hant | ja | de | es | fr | tr | uk | af | ko | it | ga | pt | ru | hu

文件变异验证器

display.file_mutation_verifiertrue(默认)时,每当 write_filepatch 调用在该轮中失败且从未被对同一路径的成功写入取代时,Hermes 会在助手的最终响应后附加一行建议。这捕获了“一批并行补丁,一半静默失败,模型总结成功”这类过度声明,而无需你在每次编辑后手动运行 git status

示例页脚:

text
⚠️ 文件变异验证器:尽管上面的措辞可能另有暗示,但此轮中 3 个文件未被修改。运行 `git status` 或 `read_file` 确认。
  • concepts/automatic-organization.md — [patch] 找不到 old_string 的匹配
  • concepts/lora.md — [patch] 找不到 old_string 的匹配
  • concepts/rag-pipeline.md — [patch] 找不到 old_string 的匹配

设置 file_mutation_verifier: false(或 HERMES_FILE_MUTATION_VERIFIER=0)以抑制页脚。验证器仅在轮次结束时存在实际失败时触发 — 重试失败补丁并在同一轮内成功的模型不会触发该文件的验证器。

静态消息的 UI 语言

display.language 设置翻译一小部分静态面向用户的消息 — CLI 批准提示、一些网关斜杠命令回复(例如重启耗尽通知、“批准已过期”、“目标已清除”)。它翻译代理响应、日志行、工具输出、错误回溯或斜杠命令描述 — 这些保持英文。如果你希望代理本身用另一种语言回复,只需在你的提示或系统消息中告诉它。

支持的值:en(默认)、zh(简体中文)、zh-hant(繁体中文)、ja(日语)、de(德语)、es(西班牙语)、fr(法语)、tr(土耳其语)、uk(乌克兰语)、af(南非荷兰语)、ko(韩语)、it(意大利语)、ga(爱尔兰语)、pt(葡萄牙语)、ru(俄语)、hu(匈牙利语)。未知值回退到英语。

你也可以使用 HERMES_LANGUAGE 环境变量按会话设置此值,该变量会覆盖配置值。

yaml
display:
  language: zh   # CLI 批准提示以中文显示
模式你看到的内容
off静默 — 仅最终响应
new仅当工具更改时显示工具指示器
all每个工具调用带有简短预览(默认)
verbose完整参数、结果和调试日志

在 CLI 中,使用 /verbose 循环这些模式。要在消息平台(Telegram、Discord、Slack 等)中使用 /verbose,请在上面的 display 部分设置 tool_progress_command: true。然后该命令将循环模式并保存到配置。

工具进度需要一个能够安全显示进度更新的网关适配器。不支持消息编辑的平台(包括 Signal)会抑制工具进度气泡,即使 /verbose 保存了非 off 模式。

运行时元数据页脚(仅限网关)

display.runtime_footer.enabled: true 时,Hermes 会将一个小的运行时上下文页脚附加到每个网关轮次的最终消息。当前页脚可以显示模型、上下文窗口百分比和当前工作目录。默认关闭;如果你的团队希望每个回复都包含此来源信息,请按网关选择加入。

yaml
display:
  runtime_footer:
    enabled: true
    fields: ["model", "context_pct", "cwd"]   # 支持的字段:model, context_pct, cwd

/footer 斜杠命令在运行时在任何会话中切换此功能。

附加到 Telegram/Discord/Slack 回复的示例页脚:

— claude-opus-4.7 · 12 个工具调用 · 2 分 14 秒 · $0.042

只有轮次的最终消息会获得页脚;中间更新保持干净。

每个平台的进度覆盖

不同平台有不同的详细程度需求。使用 display.platforms 设置每个平台的模式:

yaml
display:
  tool_progress: all          # 全局默认值
  platforms:
    signal:
      tool_progress: 'off'    # Signal 目前无法显示工具进度气泡
    telegram:
      tool_progress: verbose  # Telegram 上显示详细进度
    slack:
      tool_progress: 'off'    # 在共享 Slack 工作区中保持安静

没有覆盖的平台回退到全局 tool_progress 值。有效的平台键:telegramdiscordslacksignalwhatsappmatrixmattermostemailsmshomeassistantdingtalkfeishuwecomweixinbluebubblesqqbot。旧版 display.tool_progress_overrides 键仍然加载以保持向后兼容性,但已弃用并在首次加载时迁移到 display.platforms

Signal 被列为有效的平台键,因为设置可以按平台保存,但当前的 Signal 适配器无法编辑已发送的消息,并且不会渲染工具进度气泡。将 Signal 的 tool_progress 保持为 off;如果你需要实时观看每个工具调用,请使用 CLI 或支持编辑的消息平台。

interim_assistant_messages 仅限网关。启用后,Hermes 将完成的中间轮次助手更新作为单独的聊天消息发送。这与 tool_progress 无关,并且不需要网关流式传输。

隐私

yaml
privacy:
  redact_pii: false  # 从 LLM 上下文中剥离 PII(仅限网关)

redact_piitrue 时,网关在将系统提示发送到 LLM 之前,会在支持的平台上编辑个人身份信息:

字段处理方式
电话号码(WhatsApp/Signal 上的用户 ID)哈希为 user_<12-char-sha256>
用户 ID哈希为 user_<12-char-sha256>
聊天 ID数字部分哈希,平台前缀保留(telegram:<hash>
主频道 ID数字部分哈希
用户名 / 用户名不受影响(用户选择,公开可见)

平台支持: 编辑适用于 WhatsApp、Signal 和 Telegram。Discord 和 Slack 被排除,因为它们的提及系统(<@user_id>)需要在 LLM 上下文中使用真实 ID。

哈希是确定性的 — 同一用户始终映射到相同的哈希,因此模型仍然可以在群聊中区分用户。路由和传递在内部使用原始值。

语音转文本 (STT)

yaml
stt:
  provider: "local"            # "local" | "groq" | "openai" | "mistral"
  local:
    model: "base"              # tiny, base, small, medium, large-v3
  openai:
    model: "whisper-1"         # whisper-1 | gpt-4o-mini-transcribe | gpt-4o-transcribe
## model: "whisper-1"         # 旧版回退键仍然受尊重

提供商行为:

  • local 使用你机器上运行的 faster-whisper。使用 pip install faster-whisper 单独安装。
  • groq 使用 Groq 的 Whisper 兼容端点,并读取 GROQ_API_KEY
  • openai 使用 OpenAI 语音 API,并读取 VOICE_TOOLS_OPENAI_KEY

如果请求的提供商不可用,Hermes 按以下顺序自动回退:localgroqopenai

Groq 和 OpenAI 模型覆盖由环境驱动:

bash
STT_GROQ_MODEL=whisper-large-v3-turbo
STT_OPENAI_MODEL=whisper-1
GROQ_BASE_URL=https://api.groq.com/openai/v1
STT_OPENAI_BASE_URL=https://api.openai.com/v1

语音模式 (CLI)

yaml
voice:
  record_key: "ctrl+b"         # CLI 内的按键通话键
  max_recording_seconds: 120    # 长录音的硬停止
  auto_tts: false               # 当 /voice on 时自动启用语音回复
  beep_enabled: true            # 在 CLI 语音模式下播放录音开始/停止蜂鸣声
  silence_threshold: 200        # 语音检测的 RMS 阈值
  silence_duration: 3.0         # 自动停止前的静音秒数

在 CLI 中使用 /voice on 启用麦克风模式,使用 record_key 开始/停止录音,使用 /voice tts 切换语音回复。参见 语音模式 了解端到端设置和平台特定行为。

流式传输

将令牌流式传输到终端或消息平台,而不是等待完整响应。

CLI 流式传输

yaml
display:
  streaming: true         # 实时将令牌流式传输到终端
  show_reasoning: true    # 也流式传输推理/思考令牌(可选)

启用后,响应会逐令牌出现在流式框内。工具调用仍然静默捕获。如果提供商不支持流式传输,它会自动回退到正常显示。

网关流式传输 (Telegram, Discord, Slack)

yaml
streaming:
  enabled: true           # 启用渐进式消息编辑
  transport: edit         # "edit"(渐进式消息编辑)或 "off"
  edit_interval: 0.3      # 消息编辑之间的秒数
  buffer_threshold: 40    # 强制编辑刷新的字符数
  cursor: " ▉"            # 流式传输期间显示的光标
  fresh_final_after_seconds: 0    # 当预览足够旧时,选择加入新鲜最终消息(Telegram)

启用后,机器人在第一个令牌上发送一条消息,然后随着更多令牌到达逐步编辑它。不支持消息编辑的平台(Signal、Email、Home Assistant)会在第一次尝试时自动检测 — 流式传输会优雅地禁用,而不会产生消息洪流。

对于没有渐进式令牌编辑的单独自然中间轮次助手更新,设置 display.interim_assistant_messages: true

溢出处理: 如果流式文本超过平台的消息长度限制(~4096 个字符),当前消息会完成,并自动开始新消息。

新鲜最终消息(Telegram): Telegram 的 editMessageText 保留原始消息时间戳,因此长时间运行的流式回复即使在完成后也会保留第一个令牌的时间戳。设置 fresh_final_after_seconds > 0 以选择加入将旧预览作为全新的最终消息传递,并尽力删除预览。默认值为 0,始终在原地完成流式回复,并避免在同时显示两个操作的客户端上出现短暂的重复消息/删除序列。

注意 — 每个平台的流式传输默认值

streaming.enabled 开关默认为 false — 在你翻转它之前,没有任何内容流式传输。一旦启用,流式传输按平台决定:Telegram 附带 display.platforms.telegram.streaming: true(流式传输),Discord 附带 display.platforms.discord.streaming: false(不流式传输)。因此,启用流式传输后,Telegram 开箱即用,Discord 保持整条消息回复,直到你更改其切换。你可以从仪表板的频道切换或直接在 ~/.hermes/config.yaml 中调整这些每个平台的开关。

群聊会话隔离

限制跨 CLI、TUI/仪表板和消息网关可以同时打开的聊天会话数量:

yaml
max_concurrent_sessions: null  # null/0 = 无限制;正整数 = 活动会话上限

当达到上限时,Hermes 会为新会话返回直接限制消息。现有活动会话保持正常行为。

规范键是顶级的 max_concurrent_sessions。Hermes 也接受 gateway.max_concurrent_sessions 作为回退,但当两者都设置时,顶级键获胜。

该上限通过本地运行时租约文件强制执行,并且是尽力而为:如果注册表无法读取或锁定,Hermes 会开放失败,以便用户不会被困住。它适用于单个主机/配置文件运行时,而不是跨多台机器挂载的共享 $HERMES_HOME

控制共享聊天是保持每个房间一个对话还是每个参与者一个对话:

yaml
group_sessions_per_user: true  # true = 群组/频道中每个用户隔离,false = 每个聊天一个共享会话
  • true 是默认且推荐的设置。在 Discord 频道、Telegram 群组、Slack 频道和类似的共享上下文中,当平台提供用户 ID 时,每个发送者获得自己的会话。
  • false 恢复为旧的共享房间行为。如果你明确希望 Hermes 将频道视为一个协作对话,这可能很有用,但它也意味着用户共享上下文、令牌成本和中断状态。
  • 直接消息不受影响。Hermes 仍然像往常一样通过聊天/DM ID 键控 DM。
  • 线程无论哪种方式都与父频道隔离;使用 true 时,每个参与者在线程内也获得自己的会话。

有关行为细节和示例,请参见 会话Discord 指南

未授权 DM 行为

控制当未知用户发送直接消息时 Hermes 做什么:

yaml
unauthorized_dm_behavior: pair

whatsapp:
  unauthorized_dm_behavior: ignore
  • pair 是默认值。Hermes 拒绝访问,但在 DM 中回复一次性配对码。
  • ignore 静默丢弃未授权的 DM。
  • 平台部分覆盖全局默认值,因此你可以保持配对广泛启用,同时让一个平台更安静。

快速命令

定义自定义命令,这些命令要么运行 shell 命令而不调用 LLM,要么将一个斜杠命令别名到另一个。Exec 快速命令是零令牌的,并且从消息平台(Telegram、Discord 等)进行快速服务器检查或实用脚本时很有用。

yaml
quick_commands:
  status:
    type: exec
    command: systemctl status hermes-agent
  disk:
    type: exec
    command: df -h /
  update:
    type: exec
    command: cd ~/.hermes/hermes-agent && git pull && pip install -e .
  gpu:
    type: exec
    command: nvidia-smi --query-gpu=name,utilization.gpu,memory.used,memory.total --format=csv,noheader
  restart:
    type: alias
    target: /gateway restart

用法:在 CLI 或任何消息平台中输入 /status/disk/update/gpu/restartexec 命令在主机上本地运行并直接返回输出 — 没有 LLM 调用,不消耗令牌。alias 命令重写为配置的斜杠命令目标。

  • 30 秒超时 — 长时间运行的命令会被杀死并显示错误消息
  • 优先级 — 快速命令在技能命令之前检查,因此你可以覆盖技能名称
  • 自动补全 — 快速命令在调度时解析,不会显示在内置斜杠命令自动补全表中
  • 类型 — 支持的类型是 execalias;其他类型显示错误
  • 随处可用 — CLI、Telegram、Discord、Slack、WhatsApp、Signal、Email、Home Assistant

仅字符串的提示快捷方式不是有效的快速命令。对于可重用的提示工作流,创建一个技能或别名到现有的斜杠命令。

人类延迟

在消息平台中模拟类似人类的响应节奏:

yaml
human_delay:
  mode: "off"                  # off | natural | custom
  min_ms: 800                  # 最小延迟(自定义模式)
  max_ms: 2500                 # 最大延迟(自定义模式)

代码执行

配置 execute_code 工具:

yaml
code_execution:
  mode: project                # project(默认)| strict
  timeout: 300                 # 最大执行时间(秒)
  max_tool_calls: 50           # 代码执行内的最大工具调用次数

mode 控制脚本的工作目录和 Python 解释器:

  • project(默认) — 脚本在会话的工作目录中运行,使用活动的 virtualenv/conda 环境的 python。项目依赖(pandastorch、项目包)和相对路径(.env./data.csv)自然解析,与 terminal() 看到的一致。
  • strict — 脚本在临时暂存目录中运行,使用 sys.executable(Hermes 自己的 python)。最大可重现性,但项目依赖和相对路径不会解析。

环境清理(剥离 *_API_KEY*_TOKEN*_SECRET*_PASSWORD*_CREDENTIAL*_PASSWD*_AUTH)和工具白名单在两种模式下相同 — 切换模式不会改变安全态势。

网页搜索后端

web_searchweb_extract 工具支持五个后端提供商。在 config.yaml 中或通过 hermes tools 配置后端:

yaml
web:
  backend: firecrawl    # firecrawl | searxng | parallel | tavily | exa
## 或使用每个能力的键来混合提供商(例如免费搜索 + 付费提取):
  search_backend: "searxng"
  extract_backend: "firecrawl"
后端环境变量搜索提取
Firecrawl(默认)FIRECRAWL_API_KEY
SearXNGSEARXNG_URL
ParallelPARALLEL_API_KEY
TavilyTAVILY_API_KEY
ExaEXA_API_KEY

后端选择: 如果未设置 web.backend,则从可用的 API 密钥自动检测后端。如果仅设置了 SEARXNG_URL,则使用 SearXNG。如果仅设置了 EXA_API_KEY,则使用 Exa。如果仅设置了 TAVILY_API_KEY,则使用 Tavily。如果仅设置了 PARALLEL_API_KEY,则使用 Parallel。否则默认使用 Firecrawl。

SearXNG 是一个免费的、自托管的、尊重隐私的元搜索引擎,查询 70 多个搜索引擎。无需 API 密钥 — 只需将 SEARXNG_URL 设置为你的实例(例如 http://localhost:8080)。SearXNG 仅搜索;web_extract 需要单独的提取提供商(设置 web.extract_backend)。参见 网页搜索设置指南 了解 Docker 设置说明。

自托管 Firecrawl:FIRECRAWL_API_URL 设置为指向你自己的实例。当设置了自定义 URL 时,API 密钥变为可选(在服务器上设置 USE_DB_AUTHENTICATION=*** 以禁用身份验证)。

Parallel 搜索模式: 设置 PARALLEL_SEARCH_MODE 以控制搜索行为 — fastone-shotagentic(默认:agentic)。

Exa:~/.hermes/.env 中设置 EXA_API_KEY。支持 category 过滤(companyresearch papernewspeoplepersonal sitepdf)和域/日期过滤器。

浏览器

配置浏览器自动化行为:

yaml
browser:
  inactivity_timeout: 120        # 自动关闭空闲会话前的秒数
  command_timeout: 30             # 浏览器命令的超时时间(秒)(截图、导航等)
  record_sessions: false         # 自动将浏览器会话录制为 WebM 视频到 ~/.hermes/browser_recordings/
## 可选的 CDP 覆盖 — 设置后,Hermes 直接附加到你自己的 Chromium 系列浏览器(通过 /browser connect),而不是启动无头浏览器。
  cdp_url: ""
## 对话框监督器 — 控制当附加了 CDP 后端(Browserbase、本地 Chromium 系列浏览器通过 /browser connect)时如何处理原生 JS 对话框(alert / confirm / prompt)。在 Camofox 和默认本地代理浏览器模式下忽略。
  dialog_policy: must_respond    # must_respond | auto_dismiss | auto_accept
  dialog_timeout_s: 300          # must_respond 下的安全自动关闭(秒)
  camofox:
    managed_persistence: false   # 当为 true 时,Camofox 会话在重启后持久化 cookie/登录
    user_id: ""                  # 可选的外部管理的 Camofox userId
    session_key: ""              # 当 Hermes 创建标签页时发送的可选会话密钥
    adopt_existing_tab: false    # 在创建新标签页之前重用此身份的现有标签页

对话框策略:

  • must_respond(默认) — 捕获对话框,在 browser_snapshot.pending_dialogs 中显示,并等待代理调用 browser_dialog(action=...)。在 dialog_timeout_s 秒内无响应后,对话框会自动关闭,以防止页面的 JS 线程永远停滞。
  • auto_dismiss — 捕获,立即关闭。代理仍然在 browser_snapshot.recent_dialogs 中看到对话框记录,其中 closed_by="auto_policy"
  • auto_accept — 捕获,立即接受。适用于具有激进 beforeunload 提示的页面。

参见 浏览器功能页面 了解完整的对话框工作流。

浏览器工具集支持多个提供商。参见 浏览器功能页面 了解 Browserbase、Browser Use 和本地 Chromium 系列 CDP 设置的详细信息。

时区

使用 IANA 时区字符串覆盖服务器本地时区。影响日志中的时间戳、cron 调度和系统提示时间注入。

yaml
timezone: "America/New_York"   # IANA 时区(默认:"" = 服务器本地时间)

支持的值:任何 IANA 时区标识符(例如 America/New_YorkEurope/LondonAsia/KolkataUTC)。留空或省略以使用服务器本地时间。

Discord

配置消息网关的 Discord 特定行为:

yaml
discord:
  require_mention: true          # 在服务器频道中需要 @提及才能响应
  free_response_channels: ""     # 逗号分隔的频道 ID,机器人无需 @提及即可响应
  auto_thread: true              # 在频道中 @提及时自动创建线程
  • require_mention — 当为 true(默认)时,机器人仅在服务器频道中被提及 @BotName 时才响应。DM 始终无需提及即可工作。
  • free_response_channels — 逗号分隔的频道 ID 列表,机器人无需提及即可响应每条消息。
  • auto_thread — 当为 true(默认)时,频道中的提及会自动为对话创建线程,保持频道整洁(类似于 Slack 线程)。

安全

预执行安全扫描和机密编辑:

yaml
security:
  redact_secrets: true           # 在工具输出和日志中编辑 API 密钥模式(默认开启)
  tirith_enabled: true           # 启用 Tirith 安全扫描终端命令
  tirith_path: "tirith"          # tirith 二进制路径(默认:$PATH 中的 "tirith")
  tirith_timeout: 5              # 等待 tirith 扫描的超时秒数
  tirith_fail_open: true         # 如果 tirith 不可用,允许命令执行
  website_blocklist:             # 参见下面的网站黑名单部分
    enabled: false
    domains: []
    shared_files: []
  • redact_secrets — 当为 true 时,自动检测并编辑看起来像 API 密钥、令牌和密码的模式,在工具输出进入对话上下文和日志之前。默认开启。仅当你需要原始凭据样式的字符串进行调试或编辑开发时,才显式设置为 false
  • tirith_enabled — 当为 true 时,终端命令在执行前由 Tirith 扫描,以检测潜在危险操作。
  • tirith_path — tirith 二进制文件的路径。如果 tirith 安装在非标准位置,请设置此值。
  • tirith_timeout — 等待 tirith 扫描的最大秒数。如果扫描超时,命令继续执行。
  • tirith_fail_open — 当为 true(默认)时,如果 tirith 不可用或失败,允许执行命令。设置为 false 以在 tirith 无法验证时阻止命令。

网站黑名单

阻止代理的网页和浏览器工具访问特定域:

yaml
security:
  website_blocklist:
    enabled: false               # 启用 URL 阻止(默认:false)
    domains:                     # 被阻止的域模式列表
      - "*.internal.company.com"
      - "admin.example.com"
      - "*.local"
    shared_files:                # 从外部文件加载额外规则
      - "/etc/hermes/blocked-sites.txt"

启用后,任何匹配被阻止域模式的 URL 都会在网页或浏览器工具执行之前被拒绝。这适用于 web_searchweb_extractbrowser_navigate 以及任何访问 URL 的工具。

域规则支持:

  • 精确域:admin.example.com
  • 通配符子域:*.internal.company.com(阻止所有子域)
  • TLD 通配符:*.local

共享文件每行包含一个域规则(空行和 # 注释被忽略)。缺失或无法读取的文件会记录警告,但不会禁用其他网页工具。

策略缓存 30 秒,因此配置更改会快速生效,无需重启。

智能批准

控制 Hermes 如何处理潜在危险命令:

yaml
approvals:
  mode: manual   # manual | smart | off
模式行为
manual(默认)在执行任何被标记的命令之前提示用户。在 CLI 中,显示交互式批准对话框。在消息中,排队待处理的批准请求。
smart使用辅助 LLM 评估被标记的命令是否真正危险。低风险命令自动批准,并具有会话级持久性。真正有风险的命令升级给用户。
off跳过所有批准检查。等同于 HERMES_YOLO_MODE=true谨慎使用。

智能模式对于减少批准疲劳特别有用 — 它允许代理在安全操作上更自主地工作,同时仍然捕获真正具有破坏性的命令。

警告

设置 approvals.mode: off 会禁用终端命令的所有安全检查。仅在受信任的沙箱环境中使用此设置。

检查点

在破坏性文件操作之前自动进行文件系统快照。参见 检查点与回滚 了解详细信息。

yaml
checkpoints:
  enabled: false                 # 启用自动检查点(也可用:hermes chat --checkpoints)。默认:false(选择加入)。
  max_snapshots: 20              # 每个目录保留的最大检查点数(默认:20)

委托

配置委托工具的子代理行为:

yaml
delegation:
## model: "google/gemini-3-flash-preview"  # 覆盖模型(空 = 继承父级)
## provider: "openrouter"                  # 覆盖提供商(空 = 继承父级)
## base_url: "http://localhost:1234/v1"    # 直接 OpenAI 兼容端点(优先于提供商)
## api_key: "local-key"                    # base_url 的 API 密钥(回退到 OPENAI_API_KEY)
## api_mode: ""                            # base_url 的线路协议:"chat_completions", "codex_responses", 或 "anthropic_messages"。空 = 从 URL 自动检测(例如 /anthropic 后缀 → anthropic_messages)。对于启发式无法检测的非标准端点,显式设置。
  max_concurrent_children: 3                # 每批次的并行子代理数(下限 1,无上限)。也可通过 DELEGATION_MAX_CONCURRENT_CHILDREN 环境变量设置。
  max_spawn_depth: 1                        # 委托树深度上限(1-3,限制)。1 = 扁平(默认):父级生成叶子,叶子不能委托。2 = 编排器子级可以生成叶子孙级。3 = 三级。
  orchestrator_enabled: true                # 全局终止开关。当为 false 时,role="orchestrator" 被忽略,每个子级都被强制为叶子,无论 max_spawn_depth 如何。

子代理提供商:模型覆盖: 默认情况下,子代理继承父代理的提供商和模型。设置 delegation.providerdelegation.model 以将子代理路由到不同的提供商:模型对 — 例如,为范围狭窄的子任务使用便宜/快速的模型,而你的主代理运行昂贵的推理模型。

直接端点覆盖: 如果你想要明显的自定义端点路径,请设置 delegation.base_urldelegation.api_keydelegation.model。这将子代理直接发送到该 OpenAI 兼容端点,并优先于 delegation.provider。如果省略 delegation.api_key,Hermes 仅回退到 OPENAI_API_KEY

线路协议(api_mode): Hermes 从 delegation.base_url 自动检测线路协议(例如以 /anthropic 结尾的路径 → anthropic_messages;Codex / 原生 Anthropic / Kimi-coding 主机名保持其现有检测)。对于启发式无法分类的端点 — 例如 Azure AI Foundry、MiniMax、Zhipu GLM 或前端 Anthropic 形状后端的 LiteLLM 代理 — 显式设置 delegation.api_modechat_completionscodex_responsesanthropic_messages 之一。留空(默认)以保持自动检测。

委托提供商使用与 CLI/网关启动相同的凭据解析。所有配置的提供商都受支持:openrouternouscopilotzaikimi-codingminimaxminimax-cn。当设置提供商时,系统会自动解析正确的基础 URL、API 密钥和 API 模式 — 无需手动凭据接线。

优先级: 配置中的 delegation.base_url → 配置中的 delegation.provider → 父提供商(继承)。配置中的 delegation.model → 父模型(继承)。仅设置 model 而不设置 provider 会更改模型名称,同时保留父级的凭据(对于在同一提供商(如 OpenRouter)内切换模型很有用)。

宽度和深度: max_concurrent_children 限制每批次并行运行的子代理数量(默认 3,下限为 1,无上限)。也可以通过 DELEGATION_MAX_CONCURRENT_CHILDREN 环境变量设置。当模型提交的 tasks 数组超过上限时,delegate_task 返回工具错误,解释限制,而不是静默截断。max_spawn_depth 控制委托树深度(限制为 1-3)。在默认的 1 下,委托是扁平的:子级不能生成孙级,传递 role="orchestrator" 会静默降级为 leaf。提高到 2 以便编排器子级可以生成叶子孙级;3 用于三级树。代理通过 role="orchestrator" 每次调用选择加入编排;orchestrator_enabled: false 强制每个子级回到叶子,无论 max_spawn_depth 如何。成本成倍增长 — 在 max_spawn_depth: 3max_concurrent_children: 3 下,树可以达到 3×3×3 = 27 个并发叶子代理。参见 子代理委托 → 深度限制和嵌套编排 了解使用模式。

澄清

配置澄清提示行为:

yaml
clarify:
  timeout: 120                 # 等待用户澄清响应的秒数

上下文文件 (SOUL.md, AGENTS.md)

Hermes 使用两种不同的上下文范围:

文件用途范围
SOUL.md主要代理身份 — 定义代理是谁(系统提示中的 #1 插槽)~/.hermes/SOUL.md$HERMES_HOME/SOUL.md
.hermes.md / HERMES.md项目特定指令(最高优先级)遍历到 git 根目录
AGENTS.md项目特定指令、编码约定递归目录遍历
CLAUDE.mdClaude Code 上下文文件(也检测)仅工作目录
.cursorrulesCursor IDE 规则(也检测)仅工作目录
.cursor/rules/*.mdcCursor 规则文件(也检测)仅工作目录
  • SOUL.md 是代理的主要身份。它占据系统提示中的 #1 插槽,完全替换内置的默认身份。编辑它以完全自定义代理是谁。
  • 如果 SOUL.md 缺失、为空或无法加载,Hermes 回退到内置的默认身份。
  • 项目上下文文件使用优先级系统 — 仅加载一种类型(第一个匹配获胜):.hermes.mdAGENTS.mdCLAUDE.md.cursorrules。SOUL.md 始终独立加载。
  • AGENTS.md 是分层的:如果子目录也有 AGENTS.md,则所有内容合并。
  • Hermes 会自动播种一个默认的 SOUL.md,如果尚不存在。
  • 所有加载的上下文文件都限制在 context_file_max_chars 字符(默认 20,000),并带有智能截断。

另请参见:

工作目录

上下文默认值
CLI (hermes)你运行命令的当前目录
消息网关~/.hermes/config.yaml 中的 terminal.cwd;如果未设置,则为主目录 ~
Docker / Singularity / Modal / SSH容器或远程机器内的用户主目录

覆盖工作目录:

yaml
## 在 ~/.hermes/config.yaml 中:
terminal:
  cwd: /home/myuser/projects

MESSAGING_CWD~/.hermes/.env 中的直接 TERMINAL_CWD 条目是旧版兼容性回退。新配置应使用 terminal.cwd


分享: