--- sidebar_position: 2 title: "配置" description: "配置 Hermes Agent — config.yaml、providers、模型、API 密钥等" --- # 配置 所有设置均存储在 `~/.hermes/` 目录中,便于访问。 ## 目录结构 ```text ~/.hermes/ ├── config.yaml # 设置(模型、终端、TTS、压缩等) ├── .env # API 密钥和机密 ├── auth.json # OAuth provider 凭据(Nous Portal 等) ├── SOUL.md # 主要 agent 身份(系统提示词第 #1 槽位) ├── memories/ # 持久记忆(MEMORY.md、USER.md) ├── skills/ # Agent 创建的技能(通过 skill_manage 工具管理) ├── cron/ # 定时任务 ├── sessions/ # Gateway 会话 └── 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 ``` :::tip `hermes config set` 命令会自动将值路由到正确的文件 —— API 密钥保存到 `.env`,其他所有内容保存到 `config.yaml`。 ::: ## 配置优先级 设置按以下顺序解析(优先级从高到低): 1. **CLI 参数** —— 例如 `hermes chat --model anthropic/claude-sonnet-4`(单次调用覆盖) 2. **`~/.hermes/config.yaml`** —— 所有非机密设置的主配置文件 3. **`~/.hermes/.env`** —— 环境变量的回退;机密(API 密钥、token、密码)**必须**放这里 4. **内置默认值** —— 未设置任何内容时的硬编码安全默认值 :::info 经验法则 机密(API 密钥、bot token、密码)放入 `.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 provider 设置(OpenRouter、Anthropic、Copilot、自定义端点、自托管 LLM、回退模型等),请参阅 [AI Providers](/integrations/providers)。 ### Provider 超时 可以为 provider 设置 `providers..request_timeout_seconds` 作为全局请求超时,以及 `providers..models..timeout_seconds` 作为特定模型的覆盖值。适用于每种传输方式(OpenAI-wire、原生 Anthropic、Anthropic 兼容)上的主轮次客户端、回退链、凭据轮换后的重建,以及(对于 OpenAI-wire)每请求超时 kwarg —— 因此配置值优先于旧版 `HERMES_API_TIMEOUT` 环境变量。 还可以设置 `providers..stale_timeout_seconds` 用于非流式陈旧调用检测器,以及 `providers..models..stale_timeout_seconds` 作为特定模型的覆盖值。此值优先于旧版 `HERMES_API_CALL_STALE_TIMEOUT` 环境变量。 不设置这些值将保持旧版默认值(`HERMES_API_TIMEOUT=1800`s、`HERMES_API_CALL_STALE_TIMEOUT=300`s、原生 Anthropic 900s)。目前不适用于 AWS Bedrock(`bedrock_converse` 和 AnthropicBedrock SDK 路径均使用 boto3 及其自身的超时配置)。请参阅 [`cli-config.yaml.example`](https://github.com/NousResearch/hermes-agent/blob/main/cli-config.yaml.example) 中的注释示例。 ## 终端后端配置 Hermes 支持七种终端后端。每种后端决定 agent 的 shell 命令实际在哪里执行 —— 本地机器、Docker 容器、通过 SSH 的远程服务器、Modal 云沙箱(直接或通过 Nous 托管的 gateway)、Daytona 工作区、Vercel Sandbox,或 Singularity/Apptainer 容器。 ```yaml terminal: backend: local # local | docker | ssh | modal | daytona | vercel_sandbox | singularity cwd: "." # Gateway/cron 工作目录(CLI 始终使用启动目录) timeout: 180 # 每条命令的超时时间(秒) 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 和 Vercel Sandbox 等云沙箱,`container_persistent: true` 表示 Hermes 将尝试在沙箱重建后保留文件系统状态。这并不保证相同的活跃沙箱、PID 空间或后台进程之后仍在运行。 ### 后端概览 | 后端 | 命令运行位置 | 隔离性 | 最适合 | |---------|-------------------|-----------|----------| | **local** | 直接在您的机器上 | 无 | 开发、个人使用 | | **docker** | 单个持久 Docker 容器(跨会话、`/new`、子 agent 共享) | 完全(命名空间、cap-drop) | 安全沙箱、CI/CD | | **ssh** | 通过 SSH 的远程服务器 | 网络边界 | 远程开发、强大硬件 | | **modal** | Modal 云沙箱 | 完全(云 VM) | 临时云计算、评估 | | **daytona** | Daytona 工作区 | 完全(云容器) | 托管云开发环境 | | **vercel_sandbox** | Vercel Sandbox | 完全(云 microVM) | 带快照文件系统持久化的云执行 | | **singularity** | Singularity/Apptainer 容器 | 命名空间(--containall) | HPC 集群、共享机器 | ### Local 后端 默认后端。命令直接在您的机器上运行,无隔离。无需特殊设置。 ```yaml terminal: backend: local ``` :::warning Agent 拥有与您的用户账户相同的文件系统访问权限。使用 `hermes tools` 禁用不需要的工具,或切换到 Docker 进行沙箱隔离。 ::: ### Docker 后端 在具有安全加固的 Docker 容器内运行命令(所有权限已删除、无权限提升、PID 限制)。 **单个持久容器,而非每条命令一个容器。** Hermes 在首次使用时启动一个长期运行的容器,并通过 `docker exec` 将每个终端、文件和 `execute_code` 调用路由到同一容器中 —— 跨会话、`/new`、`/reset` 和 `delegate_task` 子 agent,贯穿 Hermes 进程的整个生命周期。工作目录更改、已安装的包以及 `/workspace` 中的文件会从一次工具调用延续到下一次,就像本地 shell 一样。容器在关闭时停止并删除。详情请参阅下方的**容器生命周期**。 ```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_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(需要 XFS+pquota 上的 overlay2) container_persistent: true # 跨会话持久化 /workspace 和 /root ``` **`terminal.docker_extra_args`**(也可通过 `TERMINAL_DOCKER_EXTRA_ARGS='["--gpus=all"]'` 覆盖)允许传递 Hermes 未作为一级键公开的任意 `docker run` 标志 —— `--gpus`、`--network`、`--add-host`、替代 `--security-opt` 覆盖等。每个条目必须是字符串;该列表最后附加到组装好的 `docker run` 调用中,因此可以在需要时覆盖 Hermes 的默认值。请谨慎使用 —— 与沙箱加固(权限删除、`--user`、workspace 绑定挂载)冲突的标志将悄然削弱隔离性。 **要求:** 已安装并运行 Docker Desktop 或 Docker Engine。Hermes 会探测 `$PATH` 以及常见的 macOS 安装位置(`/usr/local/bin/docker`、`/opt/homebrew/bin/docker`、Docker Desktop 应用包)。开箱即用支持 Podman:设置 `HERMES_DOCKER_BINARY=podman`(或完整路径)以在两者都安装时强制使用它。 **容器生命周期:** Hermes 为每个终端和文件工具调用重用单个长期运行的容器(`docker run -d ... sleep 2h`),跨会话、`/new`、`/reset` 和 `delegate_task` 子 agent,贯穿 Hermes 进程的整个生命周期。命令通过带登录 shell 的 `docker exec` 运行,因此工作目录更改、已安装的包以及 `/workspace` 中的文件都会从一次工具调用延续到下一次。容器在 Hermes 关闭时(或空闲清理回收时)停止并删除。 通过 `delegate_task(tasks=[...])` 生成的并行子 agent 共享这一个容器 —— 并发的 `cd`、环境变量修改以及对同一路径的写入会发生冲突。如果子 agent 需要隔离的沙箱,必须通过 `register_task_env_overrides()` 注册每任务镜像覆盖,RL 和基准测试环境(TerminalBench2、HermesSweEnv 等)会自动为其每任务 Docker 镜像执行此操作。 **安全加固:** - `--cap-drop ALL`,仅添加回 `DAC_OVERRIDE`、`CHOWN`、`FOWNER` - `--security-opt no-new-privileges` - `--pids-limit 256` - `/tmp`(512MB)、`/var/tmp`(256MB)、`/run`(64MB)的大小限制 tmpfs **凭据转发:** `docker_forward_env` 中列出的环境变量首先从您的 shell 环境解析,然后回退到 `~/.hermes/.env`。技能也可以声明 `required_environment_variables`,这些变量会自动合并。 ### 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_PORT` | `22` | SSH 端口 | | `TERMINAL_SSH_KEY` | (系统默认) | SSH 私钥路径 | | `TERMINAL_SSH_PERSISTENT` | `true` | 启用持久 shell | **工作原理:** 使用 `BatchMode=yes` 和 `StrictHostKeyChecking=accept-new` 在初始化时连接。持久 shell 在远程主机上保持单个 `bash -l` 进程存活,通过临时文件进行通信。需要 `stdin_data` 或 `sudo` 的命令会自动回退到单次模式。 ### Modal 后端 在 [Modal](https://modal.com) 云沙箱中运行命令。每个任务获得一个具有可配置 CPU、内存和磁盘的隔离 VM。文件系统可以跨会话快照/恢复。 ```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 token 等),并在每条命令前同步。 ### Daytona 后端 在 [Daytona](https://daytona.io) 托管工作区中运行命令。支持停止/恢复以实现持久化。 ```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 最大值。超过此值的请求将被截断并发出警告。 ### Vercel Sandbox 后端 在 [Vercel Sandbox](https://vercel.com/docs/vercel-sandbox) 云 microVM 中运行命令。Hermes 使用普通的终端和文件工具接口;没有 Vercel 特定的面向模型的工具。 ```yaml terminal: backend: vercel_sandbox vercel_runtime: node24 # node24 | node22 | python3.13 cwd: /vercel/sandbox # 默认工作区根目录 container_persistent: true # 快照/恢复文件系统 container_disk: 51200 # 仅共享默认值;不支持自定义磁盘 ``` **必需安装:** 安装可选 SDK 扩展: ```bash pip install 'hermes-agent[vercel]' ``` **必需认证:** 使用 `VERCEL_TOKEN`、`VERCEL_PROJECT_ID` 和 `VERCEL_TEAM_ID` 三者全部配置访问令牌认证。这是在 Render、Railway、Docker 及类似宿主上部署和正常长期运行 Hermes 进程的受支持设置。 对于一次性本地开发,Hermes 也接受短期 Vercel OIDC token: ```bash VERCEL_OIDC_TOKEN="$(vc project token )" hermes chat ``` 在已链接的 Vercel 项目目录中,可以省略项目名称: ```bash VERCEL_OIDC_TOKEN="$(vc project token)" hermes chat ``` OIDC token 是短期的,不应作为文档化的部署路径使用。 **运行时:** `terminal.vercel_runtime` 支持 `node24`、`node22` 和 `python3.13`。未设置时,Hermes 默认使用 `node24`。 **持久化:** 当 `container_persistent: true` 时,Hermes 在清理期间对沙箱文件系统进行快照,并从该快照为同一任务恢复后续沙箱。快照内容可以包括复制到沙箱中的 Hermes 同步凭据、技能和缓存文件。这仅保留文件系统状态;不保留活跃沙箱身份、PID 空间、shell 状态或正在运行的后台进程。 **后台命令:** `terminal(background=true)` 使用 Hermes 的通用非本地后台进程流程。您可以在沙箱存活期间通过普通进程工具生成、轮询、等待、查看日志和终止进程。Hermes 不提供清理或重启后的原生 Vercel 分离进程恢复。 **磁盘大小:** Vercel Sandbox 目前不支持 Hermes 的 `container_disk` 资源旋钮。将 `container_disk` 保持未设置或使用共享默认值 `51200`;非默认值会导致诊断和后端创建失败,而不是被静默忽略。 ### Singularity/Apptainer 后端 在 [Singularity/Apptainer](https://apptainer.org) 容器中运行命令。专为 Docker 不可用的 HPC 集群和共享机器设计。 ```yaml terminal: backend: singularity singularity_image: "docker://nikolaik/python-nodejs:python3.11-nodejs20" container_cpu: 1 # CPU 核心数 container_memory: 5120 # MB container_persistent: true # 可写覆盖层跨会话持久化 ``` **要求:** `$PATH` 中有 `apptainer` 或 `singularity` 二进制文件。 **镜像处理:** Docker URL(`docker://...`)自动转换为 SIF 文件并缓存。现有 `.sif` 文件直接使用。 **临时目录:** 按顺序解析:`TERMINAL_SCRATCH_DIR` → `TERMINAL_SANDBOX_DIR/singularity` → `/scratch/$USER/hermes-agent`(HPC 惯例)→ `~/.hermes/sandboxes/singularity`。 **隔离:** 使用 `--containall --no-home` 实现完全命名空间隔离,不挂载宿主 home 目录。 ### 常见终端后端问题 如果终端命令立即失败或终端工具报告为已禁用: - **Local** —— 无特殊要求。入门时最安全的默认选项。 - **Docker** —— 运行 `docker version` 验证 Docker 是否正常工作。如果失败,修复 Docker 或执行 `hermes config set terminal.backend local`。 - **SSH** —— `TERMINAL_SSH_HOST` 和 `TERMINAL_SSH_USER` 都必须设置。如果缺少任一项,Hermes 会记录清晰的错误。 - **Modal** —— 需要 `MODAL_TOKEN_ID` 环境变量或 `~/.modal.toml`。运行 `hermes doctor` 检查。 - **Daytona** —— 需要 `DAYTONA_API_KEY`。Daytona SDK 处理服务器 URL 配置。 - **Singularity** —— 需要 `$PATH` 中有 `apptainer` 或 `singularity`。HPC 集群上常见。 如有疑问,将 `terminal.backend` 设回 `local` 并首先验证命令在那里运行。 ### 拆卸时远程到宿主文件同步 对于 **SSH**、**Modal** 和 **Daytona** 后端(agent 的工作树位于与运行 Hermes 的宿主不同的机器上),Hermes 跟踪 agent 在远程沙箱中触及的文件,并在会话拆卸/沙箱清理时,将修改的文件**同步回宿主**,存放在 `~/.hermes/cache/remote-syncs//` 下。 - 触发时机:会话关闭、`/new`、`/reset`、gateway 消息超时、子 agent 使用远程后端时 `delegate_task` 子 agent 完成。 - 覆盖 agent 修改的整个树,而不仅仅是它明确打开的文件。添加、编辑和删除都会被捕获。 - 远程沙箱可能在您查找时已被拆除;本地 `~/.hermes/cache/remote-syncs/…` 副本是 agent 更改内容的权威记录。 - 大型二进制输出(模型检查点、原始数据集)按大小限制 —— 同步跳过超过 `file_sync_max_mb`(默认 `100`)的文件。如果您期望更大的工件返回,请调高该值。 ```yaml terminal: file_sync_max_mb: 100 # 默认 —— 同步最大 100 MB 的文件 file_sync_enabled: true # 默认 —— 设为 false 可完全跳过同步 ``` 这是从会话结束后被销毁的临时云沙箱中恢复结果的方式,无需告诉 agent 显式地 `scp` 或 `modal 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" # Gateway 可见的导出 ``` 适用于: - **向 agent 提供文件**(数据集、配置、参考代码) - **从 agent 接收文件**(生成的代码、报告、导出) - **共享工作区**,您和 agent 都访问相同的文件 如果您使用消息 gateway 并希望 agent 通过 `MEDIA:/...` 发送生成的文件,建议使用专用的宿主可见导出挂载,例如 `/home/user/.hermes/cache/documents:/output`。 - 在 Docker 中将文件写入 `/output/...` - 在 `MEDIA:` 中发出**宿主路径**,例如:`MEDIA:/home/user/.hermes/cache/documents/report.txt` - **不要**发出 `/workspace/...` 或 `/output/...`,除非该确切路径在宿主上对 gateway 进程也存在 :::warning YAML 重复键会静默覆盖之前的键。如果您已有 `docker_volumes:` 块,请将新挂载合并到同一列表中,而不是在文件后面再添加一个 `docker_volumes:` 键。 ::: 也可以通过环境变量设置:`TERMINAL_DOCKER_VOLUMES='["/host:/container"]'`(JSON 数组)。 ### Docker 凭据转发 默认情况下,Docker 终端会话不继承任意宿主凭据。如果您需要在容器内使用特定 token,请将其添加到 `terminal.docker_forward_env`。 ```yaml terminal: backend: docker docker_forward_env: - "GITHUB_TOKEN" - "NPM_TOKEN" ``` Hermes 首先从您当前的 shell 解析每个列出的变量,然后回退到通过 `hermes config set` 保存的 `~/.hermes/.env`。 :::warning `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`、`/root`、`docker_volumes` 中的任何内容)的文件归您的宿主用户所有,而非 root。权衡:容器将无法再 `apt install` 或写入 `/root/.npm` 等 root 拥有的路径 —— 如果您同时需要这两者,请使用 `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_shell` | `true` | | SSH 覆盖 | `TERMINAL_SSH_PERSISTENT` | 遵循配置 | | Local 覆盖 | `TERMINAL_LOCAL_PERSISTENT` | `false` | 每个后端的环境变量具有最高优先级。如果您也想在本地后端使用持久 shell: ```bash export TERMINAL_LOCAL_PERSISTENT=true ``` :::note 需要 `stdin_data` 或 sudo 的命令会自动回退到单次模式,因为持久 shell 的 stdin 已被 IPC 协议占用。 ::: 有关每个后端的详细信息,请参阅[代码执行](features/code-execution.md)和 [README 的终端部分](features/tools.md)。 ## 技能设置 技能可以通过其 SKILL.md frontmatter 声明自己的配置设置。这些是非机密值(路径、偏好、域设置),存储在 `config.yaml` 的 `skills.config` 命名空间下。 ```yaml skills: config: myplugin: path: ~/myplugin-data # 示例 —— 每个技能定义自己的键 ``` **技能设置的工作原理:** - `hermes config migrate` 扫描所有已启用的技能,找到未配置的设置,并提供提示 - `hermes config show` 在"技能设置"下显示所有技能设置及其所属技能 - 技能加载时,其解析的配置值会自动注入到技能上下文中 **手动设置值:** ```bash hermes config set skills.config.myplugin.path ~/myplugin-data ``` 有关在您自己的技能中声明配置设置的详细信息,请参阅[创建技能 — 配置设置](/developer-guide/creating-skills#config-settings-configyaml)。 ### Agent 创建技能写入的守卫 当 agent 使用 `skill_manage` 创建、编辑、修补或删除技能时,Hermes 可以选择扫描新/更新的内容以查找危险关键字模式(凭据收集、明显的 prompt 注入、数据外泄指令)。扫描器**默认关闭** —— 合法触及 `~/.ssh/` 或提及 `$OPENAI_API_KEY` 的真实 agent 工作流触发启发式规则过于频繁。如果您希望扫描器在 agent 的技能写入落地前提示您,请重新开启: ```yaml skills: guard_agent_created: true # 默认:false ``` 开启后,任何被标记的 `skill_manage` 写入都会以审批提示的形式出现,并附带扫描器的理由。接受的写入落地;拒绝的写入向 agent 返回解释性错误。 ## 内存配置 ```yaml memory: memory_enabled: true user_profile_enabled: true memory_char_limit: 2200 # ~800 tokens user_char_limit: 1375 # ~500 tokens ``` ## 文件读取安全 控制单次 `read_file` 调用可以返回多少内容。超过限制的读取将被拒绝,并向 agent 返回错误,提示使用 `offset` 和 `limit` 读取较小范围。这可以防止单次读取压缩的 JS 包或大型数据文件时淹没上下文窗口。 ```yaml file_read_max_chars: 100000 # 默认 —— ~25-35K tokens ``` 如果您使用具有大上下文窗口的模型并经常读取大文件,请调高此值。对于小上下文模型,请降低以保持读取高效: ```yaml # 大上下文模型(200K+) file_read_max_chars: 200000 # 小型本地模型(16K 上下文) file_read_max_chars: 30000 ``` Agent 还会自动去重文件读取 —— 如果同一文件区域被读取两次且文件未更改,则返回轻量级存根而不是重新发送内容。这在上下文压缩后重置,以便 agent 在内容被摘要后可以重新读取文件。 ## 工具输出截断限制 三个相关的上限控制工具在 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 tokens)。 - **`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 和每个 gateway 平台上统一禁用特定工具集,请在 `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 Worktree 隔离 启用隔离的 git worktree,以便在同一仓库上并行运行多个 agent: ```yaml worktree: true # 始终创建 worktree(与 hermes -w 相同) # worktree: false # 默认 —— 仅在传递 -w 标志时 ``` 启用后,每个 CLI 会话在 `.worktrees/` 下创建一个带有自己分支的新 worktree。Agent 可以编辑文件、提交、推送和创建 PR,而不会相互干扰。干净的 worktree 在退出时删除;脏的 worktree 保留以供手动恢复。 您还可以通过仓库根目录中的 `.worktreeinclude` 列出要复制到 worktree 的 gitignore 文件: ``` # .worktreeinclude .env .venv/ node_modules/ ``` ## 上下文压缩 Hermes 自动压缩长对话以保持在模型的上下文窗口内。压缩摘要器是一个单独的 LLM 调用 —— 您可以将其指向任何 provider 或端点。 所有压缩设置都在 `config.yaml` 中(无环境变量)。 ### 完整参考 ```yaml compression: enabled: true # 开启/关闭压缩 threshold: 0.50 # 在上下文限制的此百分比时压缩 target_ratio: 0.20 # 保留为最近尾部的阈值分数 protect_last_n: 20 # 保持未压缩的最少最近消息数 hygiene_hard_message_limit: 400 # Gateway 安全阀 —— 见下文 # 摘要模型/provider 在 auxiliary: 下配置: auxiliary: compression: model: "" # 空 = 使用主聊天模型。覆盖为例如 "google/gemini-3-flash-preview" 以获得更便宜/更快的压缩。 provider: "auto" # Provider:"auto"、"openrouter"、"nous"、"codex"、"main" 等 base_url: null # 自定义 OpenAI 兼容端点(覆盖 provider) ``` :::info 旧版配置迁移 带有 `compression.summary_model`、`compression.summary_provider` 和 `compression.summary_base_url` 的旧版配置在首次加载时自动迁移到 `auxiliary.compression.*`(配置版本 17)。无需手动操作。 ::: `hygiene_hard_message_limit` 是仅限 gateway 的**预压缩安全阀**。拥有数千条消息的失控会话可能在正常的上下文百分比阈值触发之前就达到模型上下文限制;当消息数超过此上限时,Hermes 强制压缩,无论 token 使用情况如何。默认 `400` —— 对于非常长的会话正常的平台,请调高;要强制更积极的压缩,请降低。在运行中的 gateway 上编辑此值将在下一条消息时生效(见下文)。 :::tip Gateway 热重载压缩和上下文长度 从最近的版本开始,在运行中的 gateway 上编辑 `config.yaml` 中的 `model.context_length` 或任何 `compression.*` 键将在下一条消息时生效 —— 无需 gateway 重启、`/reset` 或会话轮换。缓存的 agent 签名包含这些键,因此 gateway 在检测到更改时会透明地重建 agent。API 密钥和工具/技能配置仍需要通常的重载路径。 ::: ### 常见设置 **默认(自动检测)—— 无需配置:** ```yaml compression: enabled: true threshold: 0.50 ``` 使用您的主 provider 和主模型。如果您希望在比主聊天模型更便宜的模型上进行压缩,请覆盖每任务(例如 `auxiliary.compression.provider: openrouter` + `model: google/gemini-2.5-flash`)。 **强制特定 provider**(基于 OAuth 或 API 密钥): ```yaml auxiliary: compression: provider: nous model: gemini-3-flash ``` 适用于任何 provider:`nous`、`openrouter`、`codex`、`anthropic`、`main` 等。 **自定义端点**(自托管、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.provider` | `auxiliary.compression.base_url` | 结果 | |---------------------|---------------------|--------| | `auto`(默认) | 未设置 | 自动检测最佳可用 provider | | `nous` / `openrouter` / 等 | 未设置 | 强制使用该 provider,使用其认证 | | 任意 | 已设置 | 直接使用自定义端点(忽略 provider) | :::warning 摘要模型上下文长度要求 摘要模型**必须**具有至少与您的主 agent 模型一样大的上下文窗口。压缩器将对话的完整中间部分发送给摘要模型 —— 如果该模型的上下文窗口小于主模型的,摘要调用将因上下文长度错误而失败。发生这种情况时,中间轮次将**在没有摘要的情况下被丢弃**,静默丢失对话上下文。如果您覆盖模型,请验证其上下文长度满足或超过您的主模型。 ::: ## 上下文引擎 上下文引擎控制在接近模型 token 限制时如何管理对话。内置的 `compressor` 引擎使用有损摘要(参见[上下文压缩](/developer-guide/context-compression-and-caching))。插件引擎可以用替代策略替换它。 ```yaml context: engine: "compressor" # 默认 —— 内置有损摘要 ``` 使用插件引擎(例如,用于无损上下文管理的 LCM): ```yaml context: engine: "lcm" # 必须与插件名称匹配 ``` 插件引擎**永远不会自动激活** —— 您必须将 `context.engine` 显式设置为插件名称。可用引擎可以通过 `hermes plugins` → Provider Plugins → Context Engine 浏览和选择。 有关内存插件的类似单选系统,请参阅[内存 Providers](/user-guide/features/memory-providers)。 ## 迭代预算压力 当 agent 在处理具有许多工具调用的复杂任务时,它可能会在没有意识到预算不足的情况下耗尽其迭代预算(默认:90 轮)。预算压力会在模型接近限制时自动发出警告: | 阈值 | 级别 | 模型看到的内容 | |-----------|-------|---------------------| | **70%** | 注意 | `[BUDGET: 63/90. 27 iterations left. Start consolidating.]` | | **90%** | 警告 | `[BUDGET WARNING: 81/90. Only 9 left. Respond NOW.]` | 警告注入到最后一个工具结果的 JSON 中(作为 `_budget_warning` 字段),而不是作为单独的消息 —— 这保留了 prompt 缓存,不会破坏对话结构。 ```yaml agent: max_turns: 90 # 每次对话轮次的最大迭代次数(默认:90) api_max_retries: 3 # 回退启动前每个 provider 的重试次数(默认:3) ``` 预算压力默认启用。Agent 自然地将警告视为工具结果的一部分,鼓励它在耗尽迭代之前整合工作并提供响应。 当迭代预算完全耗尽时,CLI 向用户显示通知:`⚠ Iteration budget reached (90/90) — response may be incomplete`。如果预算在活跃工作期间耗尽,agent 会在停止前生成已完成内容的摘要。 `agent.api_max_retries` 控制 Hermes 在回退 provider 切换启动**之前**对瞬时错误(速率限制、连接断开、5xx)重试 provider API 调用的次数。默认为 `3` —— 总共四次尝试。如果您配置了[回退 providers](/user-guide/features/fallback-providers) 并希望更快地故障转移,请将其降至 `0`,这样主 provider 上的第一个瞬时错误会立即切换到回退,而不是对不稳定的端点进行重试。 ### API 超时 Hermes 对流式传输有单独的超时层,以及用于非流式调用的陈旧检测器。陈旧检测器仅在您将其保留为隐式默认值时才会自动调整本地 provider。 | 超时 | 默认值 | 本地 providers | 配置/环境变量 | |---------|---------|----------------|--------------| | Socket 读取超时 | 120s | 自动提升至 1800s | `HERMES_STREAM_READ_TIMEOUT` | | 陈旧流检测 | 180s | 自动禁用 | `HERMES_STREAM_STALE_TIMEOUT` | | 陈旧非流检测 | 300s | 保持隐式时自动禁用 | `providers..stale_timeout_seconds` 或 `HERMES_API_CALL_STALE_TIMEOUT` | | API 调用(非流式) | 1800s | 不变 | `providers..request_timeout_seconds` / `timeout_seconds` 或 `HERMES_API_TIMEOUT` | **Socket 读取超时**控制 httpx 等待 provider 下一个数据块的时间。本地 LLM 在大上下文上预填充可能需要几分钟才能产生第一个 token,因此当 Hermes 检测到本地端点时,会将此值提升至 30 分钟。如果您显式设置 `HERMES_STREAM_READ_TIMEOUT`,无论端点检测如何,始终使用该值。 **陈旧流检测**终止接收 SSE 保活 ping 但没有实际内容的连接。对于本地 providers,这完全禁用,因为它们在预填充期间不发送保活 ping。 **陈旧非流检测**终止长时间没有响应的非流式调用。默认情况下,Hermes 在本地端点上禁用此功能,以避免长时间预填充期间的误报。如果您显式设置 `providers..stale_timeout_seconds`、`providers..models..stale_timeout_seconds` 或 `HERMES_API_CALL_STALE_TIMEOUT`,即使在本地端点上也会遵守该显式值。 ## 上下文压力警告 与迭代预算压力分开,上下文压力跟踪对话距**压缩阈值**有多近 —— 即上下文压缩触发以摘要旧消息的点。这有助于您和 agent 了解对话何时变长。 | 进度 | 级别 | 发生的事情 | |----------|-------|-------------| | **≥ 60%** 到阈值 | 信息 | CLI 显示青色进度条;gateway 发送信息通知 | | **≥ 85%** 到阈值 | 警告 | CLI 显示粗体黄色进度条;gateway 警告压缩即将发生 | 在 CLI 中,上下文压力在工具输出流中显示为进度条: ``` ◐ context ████████████░░░░░░░░ 62% to compaction 48k threshold (50%) · approaching compaction ``` 在消息平台上,发送纯文本通知: ``` ◐ Context: ████████████░░░░░░░░ 62% to compaction (threshold: 50% of window). ``` 如果自动压缩被禁用,警告会告诉您上下文可能被截断。 上下文压力是自动的 —— 无需配置。它纯粹作为面向用户的通知触发,不修改消息流或向模型上下文注入任何内容。 ## 凭据池策略 当您为同一 provider 拥有多个 API 密钥或 OAuth token 时,配置轮换策略: ```yaml credential_pool_strategies: openrouter: round_robin # 均匀循环使用密钥 anthropic: least_used # 始终选择使用最少的密钥 ``` 选项:`fill_first`(默认)、`round_robin`、`least_used`、`random`。完整文档请参阅[凭据池](/user-guide/features/credential-pools)。 ## Prompt 缓存 当活跃 provider 支持时,Hermes 自动开启跨会话 prompt 缓存 —— 无需用户配置。 对于**原生 Anthropic**、**OpenRouter** 和 **Nous Portal** 上的 Claude,Hermes 在系统提示词和技能块上附加带有 1 小时 TTL(`ttl: "1h"`)的 `cache_control` 断点。在新鲜的一小时内首次发送时按完整输入费率计费;同一小时内任何会话的后续发送以折扣缓存读取费率从缓存中提取。这意味着系统提示词、加载的技能内容以及任何长上下文包含的早期部分在第一个小时内跨 `hermes` 会话和分叉子 agent 被重用。 Qwen Cloud(阿里巴巴 DashScope)上游将缓存 TTL 限制为 5 分钟,因此 Hermes 在那里使用 5 分钟断点 TTL。其他通过第三方的 Claude 路径(AWS Bedrock、Azure Foundry)回退到 provider 自己的缓存默认值。xAI Grok 使用单独的会话固定对话 ID 机制 —— 参阅 [xAI prompt 缓存](/integrations/providers#xai-grok--responses-api--prompt-caching)。 不存在禁用此功能的旋钮 —— 缓存始终开启,即使在单轮对话中也能节省费用,因为仅系统提示词就占输入 token 数的相当大比例。 ## 辅助模型 Hermes 使用"辅助"模型处理图像分析、网页摘要、浏览器截图分析、会话标题生成和上下文压缩等附带任务。默认情况下(`auxiliary.*.provider: "auto"`),Hermes 将每个辅助任务路由到您的**主聊天模型** —— 与您在 `hermes model` 中选择的相同 provider/模型。您无需配置任何内容即可开始,但请注意,在昂贵的推理模型(Opus、MiniMax M2.7 等)上,辅助任务会增加显著成本。如果您希望无论主模型如何都使用便宜且快速的附带任务,请显式设置 `auxiliary..provider` 和 `auxiliary..model`(例如,在 OpenRouter 上使用 Gemini Flash 进行视觉和网页提取)。 :::note 为什么 "auto" 使用您的主模型 早期版本将聚合器用户(OpenRouter、Nous Portal)分流到便宜的 provider 端默认值。这令人惊讶 —— 付费购买聚合器订阅的用户会看到不同的模型处理其辅助流量。`auto` 现在对所有人使用主模型,`config.yaml` 中的每任务覆盖仍然优先(见下方[完整辅助配置参考](#full-auxiliary-config-reference))。 ::: ### 交互式配置辅助模型 无需手动编辑 YAML,运行 `hermes model` 并从菜单中选择**"配置辅助模型"**。您将获得交互式的每任务选择器: ``` $ hermes model → Configure auxiliary models [ ] vision currently: auto / main model [ ] web_extract currently: auto / main model [ ] title_generation currently: openrouter / google/gemini-3-flash-preview [ ] 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 ``` 选择任务,选择 provider(OAuth 流程打开浏览器;API 密钥 provider 提示输入),选择模型。更改持久化到 `config.yaml` 中的 `auxiliary..*`。与主模型选择器相同的机制 —— 无需学习额外语法。 ### 视频教程