본문으로 건너뛰기

Nix 与 NixOS 设置

Hermes Agent 提供了一个 Nix flake,支持三个集成级别:

级别适用对象获得内容
nix run / nix profile install任意 Nix 用户(macOS、Linux)预构建二进制文件,包含所有依赖——随后使用标准 CLI 工作流
NixOS 模块(原生)NixOS 服务器部署声明式配置、加固的 systemd 服务、托管密钥
NixOS 模块(容器)需要自我修改的 Agent上述所有内容,外加一个持久的 Ubuntu 容器,Agent 可在其中执行 apt/pip/npm install
与标准安装的区别

curl | bash 安装程序自行管理 Python、Node 和依赖项。Nix flake 则取代了这一切——每个 Python 依赖项都是通过 uv2nix 构建的 Nix 派生,而运行时工具(Node.js、git、ripgrep、ffmpeg)则被打包到二进制文件的 PATH 中。不存在运行时 pip、venv 激活,也没有 npm install对于非 NixOS 用户,这仅改变了安装步骤。之后的所有操作(hermes setuphermes gateway install、配置编辑)与标准安装完全一致。

对于 NixOS 模块用户,整个生命周期完全不同:配置位于 configuration.nix 中,密钥通过 sops-nix/agenix 管理,服务是 systemd 单元,CLI 配置命令被阻止。你管理 hermes 的方式与管理任何其他 NixOS 服务相同。

前提条件

  • 启用 flake 的 Nix — 推荐使用 Determinate Nix(默认启用 flake)
  • 你想要使用的服务的 API 密钥(至少需要:一个 OpenRouter 或 Anthropic 密钥)

快速开始(任何 Nix 用户)

无需克隆。Nix 会自行获取、构建并运行所有内容:

# 直接运行(首次使用构建,之后缓存)
nix run github:NousResearch/hermes-agent -- setup
nix run github:NousResearch/hermes-agent -- chat

# 或者持久安装
nix profile install github:NousResearch/hermes-agent
hermes setup
hermes chat

执行 nix profile install 后,hermeshermes-agenthermes-acp 会加入你的 PATH。此后,工作流程与标准安装完全相同——hermes setup 会引导你选择提供商,hermes gateway install 会设置 launchd(macOS)或 systemd 用户服务,配置文件位于 ~/.hermes/

从本地克隆构建
git clone https://github.com/NousResearch/hermes-agent.git
cd hermes-agent
nix build
./result/bin/hermes setup

NixOS 模块

该 flake 导出了 nixosModules.default —— 一个完整的 NixOS 服务模块,可以声明式地管理用户创建、目录、配置生成、密钥、文档以及服务生命周期。

노트

此模块需要 NixOS。对于非 NixOS 系统(macOS、其他 Linux 发行版),请使用 nix profile install 以及上述标准 CLI 工作流程。

添加 Flake 输入

# /etc/nixos/flake.nix (or your system flake)
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
hermes-agent.url = "github:NousResearch/hermes-agent";
};

outputs = { nixpkgs, hermes-agent, ... }: {
nixosConfigurations.your-host = nixpkgs.lib.nixosSystem {
system = "x86_64-linux";
modules = [
hermes-agent.nixosModules.default
./configuration.nix
];
};
};
}

最小配置

# configuration.nix
{ config, ... }: {
services.hermes-agent = {
enable = true;
settings.model.default = "anthropic/claude-sonnet-4";
environmentFiles = [ config.sops.secrets."hermes-env".path ];
addToSystemPackages = true;
};
}

仅此而已。运行 nixos-rebuild switch 会创建 hermes 用户、生成 config.yaml、接入密钥,并启动网关 —— 一个长期运行的服务,用于将 Agent 连接到消息平台(Telegram、Discord 等)并监听传入消息。

需要密钥

上面的 environmentFiles 行假定你已经配置了 sops-nixagenix。该文件至少应包含一个 LLM 提供商密钥(例如 OPENROUTER_API_KEY=sk-or-...)。完整配置请参见密钥管理。如果你还没有密钥管理器,可以先使用一个普通文件作为起点 —— 只需确保它不能被其他用户读取: --- END DOCUMENT CHUNK ---

echo "OPENROUTER_API_KEY=sk-or-your-key" | sudo install -m 0600 -o hermes /dev/stdin /var/lib/hermes/env
services.hermes-agent.environmentFiles = [ "/var/lib/hermes/env" ];
addToSystemPackages

addToSystemPackages = true 设置会做两件事:把 hermes 命令行工具放到系统 PATH 中,并且在全局设置 HERMES_HOME,使交互式 CLI 与网关服务共享状态(会话、技能、定时任务)。如果不设置这一项,你在 shell 中运行 hermes 会创建一个独立的 ~/.hermes/ 目录。

容器感知的 CLI

정보

container.enable = true 并且 addToSystemPackages = true 时,主机上每一个 hermes 命令都会自动路由到受管理的容器中运行。这意味着你的交互式 CLI 会话会在与网关服务相同的环境中执行——可以访问所有容器中安装的包和工具。

  • 路由是透明的:hermes chathermes sessions listhermes version 等命令实际上都在容器内部执行
  • 所有 CLI 标志都会原样传递
  • 如果容器没有运行,CLI 会短暂重试(交互模式显示旋转动画并等待 5 秒,脚本模式静默等待 10 秒),然后报出清晰的错误——不会无声地降级
  • 对于在 hermes 代码库上进行开发的开发者,设置 HERMES_DEV=1 可以跳过容器路由,直接运行本地检出代码

--- END DOCUMENT CHUNK --- 设置 container.hostUsers 以创建指向服务状态目录的 ~/.hermes 符号链接,这样宿主机 CLI 和容器就能共享会话、配置和记忆:

services.hermes-agent = {
container.enable = true;
container.hostUsers = [ "your-username" ];
addToSystemPackages = true;
};

hostUsers 中列出的用户会自动添加到 hermes 组,以便获取文件权限访问。

Podman 用户: NixOS 服务以 root 身份运行容器。Docker 用户通过 docker 组套接字获得访问权限,但 Podman 的 rootful 容器需要 sudo。为你的容器运行时授予免密码 sudo 权限:

security.sudo.extraRules = [{
users = [ "your-username" ];
commands = [{
command = "/run/current-system/sw/bin/podman";
options = [ "NOPASSWD" ];
}];
}];

CLI 会自动检测何时需要 sudo 并透明地使用它。如果没有这个配置,你需要手动运行 sudo hermes chat

验证是否生效

执行 nixos-rebuild switch 后,检查服务是否正在运行:

# 检查服务状态
systemctl status hermes-agent

# 查看日志(按 Ctrl+C 停止)
journalctl -u hermes-agent -f

# 如果 addToSystemPackages 设为 true,测试 CLI
hermes version
hermes config # 显示生成的配置

选择部署模式

该模块支持两种模式,由 container.enable 控制:

原生模式(默认)容器模式
运行方式宿主机上基于 systemd 的强化服务持久化 Ubuntu 容器,挂载 /nix/store
安全性NoNewPrivilegesProtectSystem=strictPrivateTmp容器隔离,内部以非特权用户运行
Agent 能否自行安装包否——仅限 Nix 提供的 PATH 中的工具是——aptpipnpm 安装的内容在重启后持久保留
配置界面相同相同
何时选择标准部署,最高安全性,可复现性Agent 需要运行时包安装、可变环境、实验性工具

要启用容器模式,添加一行:

{
services.hermes-agent = {
enable = true;
container.enable = true;
# ... rest of config is identical
};
}
정보

容器模式会通过 mkDefault 自动启用 virtualisation.docker.enable。如果你改用 Podman,请设置 container.backend = "podman" 并保持 virtualisation.docker.enable = false


配置

声明式设置

settings 选项接受任意 attrset(属性集),并会渲染为 config.yaml。它支持跨多个模块定义进行深层合并(通过 lib.recursiveUpdate),因此你可以将配置分散到多个文件中:

# base.nix
services.hermes-agent.settings = {
model.default = "anthropic/claude-sonnet-4";
toolsets = [ "all" ];
terminal = { backend = "local"; timeout = 180; };
};

# personality.nix
services.hermes-agent.settings = {
display = { compact = false; personality = "kawaii"; };
memory = { memory_enabled = true; user_profile_enabled = true; };
};

两段配置在求值时会进行深层合并。Nix 声明的键始终优先于磁盘上已有 config.yaml 中的键,但 用户添加而 Nix 未涉及的键会被保留。这意味着如果 Agent 或手动编辑添加了诸如 skills.disabledstreaming.enabled 这样的键,它们在执行 nixos-rebuild switch 后依然存在。

模型命名

settings.model.default 使用你的提供商所期望的模型标识符。使用 OpenRouter(默认)时,这些标识符形如 "anthropic/claude-sonnet-4""google/gemini-3-flash"。如果你直接使用某个提供商(Anthropic、OpenAI),请将 settings.model.base_url 指向其 API,并使用它们原生的模型 ID(例如 "claude-sonnet-4-20250514")。当未设置 base_url 时,Hermes 默认使用 OpenRouter。

发现可用的配置键

运行 nix build .#configKeys && cat result 可查看从 Python 的 DEFAULT_CONFIG 中提取的所有叶子配置键。你可以将现有的 config.yaml 粘贴到 settings 属性集中——结构是一一对应的。

完整示例:所有常用自定义设置
{ config, ... }: {
services.hermes-agent = {
enable = true;
container.enable = true;

# ── Model ──────────────────────────────────────────────────────────
settings = {
model = {
base_url = "https://openrouter.ai/api/v1";
default = "anthropic/claude-opus-4.6";
};
toolsets = [ "all" ];
max_turns = 100;
terminal = { backend = "local"; cwd = "."; timeout = 180; };
compression = {
enabled = true;
threshold = 0.85;
summary_model = "google/gemini-3-flash-preview";
};
memory = { memory_enabled = true; user_profile_enabled = true; };
display = { compact = false; personality = "kawaii"; };
agent = { max_turns = 60; verbose = false; };
};

# ── Secrets ────────────────────────────────────────────────────────
environmentFiles = [ config.sops.secrets."hermes-env".path ];

# ── Documents ──────────────────────────────────────────────────────
documents = {
"USER.md" = ./documents/USER.md;
};

# ── MCP Servers ────────────────────────────────────────────────────
mcpServers.filesystem = {
command = "npx";
args = [ "-y" "@modelcontextprotocol/server-filesystem" "/data/workspace" ];
};

# ── Container options ──────────────────────────────────────────────
container = {
image = "ubuntu:24.04";
backend = "docker";
hostUsers = [ "your-username" ];
extraVolumes = [ "/home/user/projects:/projects:rw" ];
extraOptions = [ "--gpus" "all" ];
};

# ── Service tuning ─────────────────────────────────────────────────
addToSystemPackages = true;
extraArgs = [ "--verbose" ];
restart = "always";
restartSec = 5;
};
}

逃生舱:自己托管配置文件

如果你希望完全在 Nix 之外管理 config.yaml,可以使用 configFile

services.hermes-agent.configFile = /etc/hermes/config.yaml;

这会完全绕过 settings——不合并、不生成。每次激活时,该文件会原样复制到 $HERMES_HOME/config.yaml

自定义速查表

Nix 用户最常需要的自定义操作快速参考:

我想要……选项示例
更改 LLM 模型settings.model.default"anthropic/claude-sonnet-4"
使用不同的提供商端点settings.model.base_url"https://openrouter.ai/api/v1"
添加 API 密钥environmentFiles[ config.sops.secrets."hermes-env".path ]
为 agent 赋予个性${services.hermes-agent.stateDir}/.hermes/SOUL.md直接管理该文件
添加 MCP 工具服务器mcpServers.<name>参见 MCP 服务器
将宿主机目录挂载到容器中container.extraVolumes[ "/data:/data:rw" ]
向容器传递 GPU 访问权限container.extraOptions[ "--gpus" "all" ]
使用 Podman 替代 Dockercontainer.backend"podman"
在宿主机 CLI 与容器之间共享状态container.hostUsers[ "sidbin" ]
向 agent 提供额外工具extraPackages[ pkgs.pandoc pkgs.imagemagick ]
使用自定义基础镜像container.image"ubuntu:24.04"
覆盖 hermes 包packageinputs.hermes-agent.packages.${system}.default.override { ... }
更改状态目录stateDir"/opt/hermes"
设置 agent 的工作目录workingDirectory"/home/user/projects"

密钥管理

切勿将 API 密钥存放在 settingsenvironment

Nix 表达式中的值会落入 /nix/store,该目录全局可读。请始终将 environmentFiles 与密钥管理器配合使用。

environment(非机密变量)和 environmentFiles(机密文件)在激活时(nixos-rebuild switch)都会被合并到 $HERMES_HOME/.env 中。Hermes 每次启动时都会读取此文件,因此只需执行 systemctl restart hermes-agent 即可生效——无需重新创建容器。

sops-nix

{
sops = {
defaultSopsFile = ./secrets/hermes.yaml;
age.keyFile = "/home/user/.config/sops/age/keys.txt";
secrets."hermes-env" = { format = "yaml"; };
};

services.hermes-agent.environmentFiles = [
config.sops.secrets."hermes-env".path
];
}

机密文件包含键值对:

# secrets/hermes.yaml (encrypted with sops)
hermes-env: |
OPENROUTER_API_KEY=sk-or-...
TELEGRAM_BOT_TOKEN=123456:ABC...
ANTHROPIC_API_KEY=sk-ant-...

agenix

{
age.secrets.hermes-env.file = ./secrets/hermes-env.age;

services.hermes-agent.environmentFiles = [
config.age.secrets.hermes-env.path
];
}

OAuth / 授权信息预置

对于需要 OAuth 的平台(例如 Discord),请使用 authFile 在首次部署时预置凭据:

{
services.hermes-agent = {
authFile = config.sops.secrets."hermes/auth.json".path;
# authFileForceOverwrite = true; # 每次激活时强制覆盖
};
}

只有当 auth.json 不存在时才会复制该文件(除非设置了 authFileForceOverwrite = true)。运行时的 OAuth 令牌刷新会写入状态目录,并在重新构建后保留。


Documents

documents 选项将文件安装到 agent 的工作目录(即 workingDirectory,agent 将其读取为工作区)。Hermes 按照约定查找特定的文件名:

  • USER.md — 关于与 agent 交互的用户上下文信息。
  • 放置在此处的任何其他文件对 agent 来说都是工作区文件。 Agent 身份文件是独立的:Hermes 从 $HERMES_HOME/SOUL.md 加载其主要 SOUL.md,在 NixOS 模块中对应 ${services.hermes-agent.stateDir}/.hermes/SOUL.md。将 SOUL.md 放入 documents 只会创建一个工作区文件,不会替换主角色文件。
{
services.hermes-agent.documents = {
"USER.md" = ./documents/USER.md; # 路径引用,从 Nix store 复制
};
}

值可以是内联字符串或路径引用。每次执行 nixos-rebuild switch 时都会安装这些文件。


MCP 服务器

mcpServers 选项以声明方式配置 MCP(模型上下文协议) 服务器。每个服务器使用 stdio(本地命令)或 HTTP(远程 URL)传输方式。

Stdio 传输(本地服务器)

{
services.hermes-agent.mcpServers = {
filesystem = {
command = "npx";
args = [ "-y" "@modelcontextprotocol/server-filesystem" "/data/workspace" ];
};
github = {
command = "npx";
args = [ "-y" "@modelcontextprotocol/server-github" ];
env.GITHUB_PERSONAL_ACCESS_TOKEN = "\${GITHUB_TOKEN}"; # 从 .env 解析
};
};
}

env 值中的环境变量会在运行时从 $HERMES_HOME/.env 解析。请使用 environmentFiles 注入密钥——绝对不要把 token 直接写在 Nix 配置中。

HTTP 传输(远程服务器)

{
services.hermes-agent.mcpServers.remote-api = {
url = "https://mcp.example.com/v1/mcp";
headers.Authorization = "Bearer \${MCP_REMOTE_API_KEY}";
timeout = 180;
};
}

带 OAuth 的 HTTP 传输

对使用 OAuth 2.1 的服务器,请设置 auth = "oauth"。Hermes 实现了完整的 PKCE 流程——元数据发现、动态客户端注册、令牌交换和自动刷新。

{
services.hermes-agent.mcpServers.my-oauth-server = {
url = "https://mcp.example.com/mcp";
auth = "oauth";
};
}

令牌存储在 $HERMES_HOME/mcp-tokens/<server-name>.json 中,在重启和重建后依然持久存在。

在无头服务器上进行首次 OAuth 授权

首次 OAuth 授权需要基于浏览器的同意流程。在无头部署中,Hermes 不会打开浏览器,而是将授权 URL 输出到标准输出/日志中。

选项 A:交互式引导 — 通过 docker exec(容器)或 sudo -u hermes(本机)运行一次流程:

# 容器模式
docker exec -it hermes-agent \
hermes mcp add my-oauth-server --url https://mcp.example.com/mcp --auth oauth

# 本机模式
sudo -u hermes HERMES_HOME=/var/lib/hermes/.hermes \
hermes mcp add my-oauth-server --url https://mcp.example.com/mcp --auth oauth

容器使用 --network=host,因此主机浏览器可以访问 127.0.0.1 上的 OAuth 回调监听器。

选项 B:预置令牌 — 在工作站上完成流程,然后复制令牌:

hermes mcp add my-oauth-server --url https://mcp.example.com/mcp --auth oauth
scp ~/.hermes/mcp-tokens/my-oauth-server{,.client}.json \
server:/var/lib/hermes/.hermes/mcp-tokens/
# 确保:chown hermes:hermes,chmod 0600

采样(服务器发起的 LLM 请求)

某些 MCP 服务器可以向 Agent 请求 LLM 补全:

{
services.hermes-agent.mcpServers.analysis = {
command = "npx";
args = [ "-y" "analysis-server" ];
sampling = {
enabled = true;
model = "google/gemini-3-flash";
max_tokens_cap = 4096;
timeout = 30;
max_rpm = 10;
};
};
}

管理模式

当 hermes 通过 NixOS 模块运行时,以下 CLI 命令会被阻止,并显示一条指向 configuration.nix 的描述性错误提示:

被阻止的命令原因
hermes setup配置是声明式的——请改为在 Nix 配置中编辑 settings
hermes config edit配置由 settings 生成
hermes config set <key> <value>配置由 settings 生成
hermes gateway installsystemd 服务由 NixOS 管理
hermes gateway uninstallsystemd 服务由 NixOS 管理

这可以防止 Nix 声明的状态与磁盘上的实际状态不一致。检测机制依赖两个信号:

  1. HERMES_MANAGED=true 环境变量——由 systemd 服务设置,对网关进程可见
  2. .managed 标记文件(位于 HERMES_HOME 目录下)——由激活脚本设置,对交互式 shell 可见(例如,docker exec -it hermes-agent hermes config set ... 也会被阻止)

如需更改配置,请编辑你的 Nix 配置并运行 sudo nixos-rebuild switch

容器架构

정보

本节仅在你使用 container.enable = true 时相关。原生模式部署可跳过此部分。

当启用容器模式时,Hermes 运行在一个持久的 Ubuntu 容器内,Nix 构建的二进制文件以只读方式从宿主机绑定挂载到容器中:

宿主机                                   容器
──── ─────────
/nix/store/...-hermes-agent-0.1.0 ──► /nix/store/... (只读)
~/.hermes -> /var/lib/hermes/.hermes (符号链接桥,按 hostUsers 配置)
/var/lib/hermes/ ──► /data/ (读写)
├── current-package -> /nix/store/... (符号链接,每次重建时更新)
├── .gc-root -> /nix/store/... (防止 nix-collect-garbage 清理)
├── .container-identity (sha256 哈希,触发容器重建)
├── .hermes/ (HERMES_HOME)
│ ├── .env (由 environment + environmentFiles 合并生成)
│ ├── config.yaml (Nix 生成,激活时深度合并)
│ ├── .managed (标记文件)
│ ├── .container-mode (路由元数据:backend、exec_user 等)
│ ├── state.db, sessions/, memories/ (运行时状态)
│ └── mcp-tokens/ (MCP 服务器的 OAuth 令牌)
├── home/ ──► /home/hermes (读写)
└── workspace/ (MESSAGING_CWD)
├── SOUL.md (来自 documents 选项)
└── (Agent 创建的文件)

容器可写层 (apt/pip/npm): /usr, /usr/local, /tmp

Nix 构建的二进制文件可以直接在 Ubuntu 容器内运行,这是因为 /nix/store 被绑定挂载——它自带了所需的解释器和所有依赖,因此不依赖容器的系统库。容器的入口点通过一个 current-package 符号链接来解析:/data/current-package/bin/hermes gateway run --replace。当执行 nixos-rebuild switch 时,只会更新符号链接——容器仍然继续运行。

各操作对持久化的影响

事件容器是否重建?/data(状态)/home/hermes可写层(apt/pip/npm
systemctl restart hermes-agent持久保留持久保留持久保留
nixos-rebuild switch(代码变更)否(符号链接更新)持久保留持久保留持久保留
主机重启持久保留持久保留持久保留
nix-collect-garbage否(GC 根)持久保留持久保留持久保留
镜像变更(container.image持久保留持久保留丢失
卷/选项变更持久保留持久保留丢失
environment/environmentFiles 变更持久保留持久保留持久保留
容器仅在其身份哈希(identity hash) 发生变化时才会重建。该哈希覆盖:模式版本(schema version)、镜像(image)、extraVolumesextraOptions 以及入口脚本(entrypoint script)。对环境变量、设置、文档或 hermes 包本身的更改不会触发重建。
可写层数据丢失

当身份哈希发生变化(镜像升级、新增卷、新增容器选项)时,容器会被销毁,并从最新的 container.image 拉取中重建。任何在可写层中通过 apt installpip installnpm install 安装的包都会丢失。/data/home/hermes 中的状态会保留(这些是绑定挂载)。

如果 agent 依赖特定包,可以考虑将它们打包到自定义镜像中(container.image = "my-registry/hermes-base:latest"),或者在 agent 的 SOUL.md 中编写安装脚本。

GC 根保护

preStart 脚本会在 ${stateDir}/.gc-root 创建一个指向当前 hermes 包的 GC 根。这可以防止 nix-collect-garbage 删除正在运行的二进制文件。如果 GC 根意外损坏,重启服务即可重新创建。

插件

NixOS 模块支持声明式安装插件——无需执行 hermes plugins install 命令。

目录插件(extraPlugins

适用于那些仅包含 plugin.yaml + __init__.py 源码树的插件(例如 hermes-lcm):

services.hermes-agent.extraPlugins = [
(pkgs.fetchFromGitHub {
owner = "stephenschoettler";
repo = "hermes-lcm";
rev = "v0.7.0";
hash = "sha256-...";
})
];

插件会在激活时被符号链接到 $HERMES_HOME/plugins/ 目录。Hermes 会通过常规的目录扫描来发现它们。从列表中移除某个插件并运行 nixos-rebuild switch 即可删除对应的符号链接。

入口点插件(extraPythonPackages

适用于通过 [project.entry-points."hermes_agent.plugins"] 注册的 pip 打包插件(例如 rtk-hermes):

services.hermes-agent.extraPythonPackages = [
(pkgs.python312Packages.buildPythonPackage {
pname = "rtk-hermes";
version = "1.0.0";
src = pkgs.fetchFromGitHub {
owner = "ogallotti";
repo = "rtk-hermes";
rev = "v1.0.0";
hash = "sha256-...";
};
format = "pyproject";
build-system = [ pkgs.python312Packages.setuptools ];
})
];

该包的 site-packages 会在 hermes 包装器中被添加到 PYTHONPATH。importlib.metadata 会在会话启动时发现入口点。

可选依赖组(extraDependencyGroups

对于已在 hermes-agent 的 pyproject.toml 中声明的可选扩展(例如 hindsighthoncho 等记忆提供者),可以使用 extraDependencyGroups 在构建时将其包含在密封的虚拟环境中:

services.hermes-agent = {
extraDependencyGroups = [ "hindsight" ];
settings.memory.provider = "hindsight";
};

此配置由 uv 与核心依赖项一次性解析完成——无需 PYTHONPATH 修补,无冲突风险。可用组与 pyproject.toml 中的 [project.optional-dependencies] 键对应(例如 "hindsight""honcho""voice""matrix""mistral""bedrock")。

何时使用哪种选项:

需求选项
启用 pyproject.toml 中的可选扩展extraDependencyGroups
添加 pyproject.toml 中未声明的外部 Python 插件extraPythonPackages
添加系统二进制文件(pandoc、jq 等)extraPackages
添加基于目录的插件源码树extraPlugins

两者结合

一个带有第三方 Python 依赖的目录插件需要同时配置这两个选项:

services.hermes-agent = {
extraPlugins = [ my-plugin-src ]; # 插件源码
extraPythonPackages = [ pkgs.python312Packages.redis ]; # 其 Python 依赖
extraPackages = [ pkgs.redis ]; # 所需的系统二进制文件
};

使用 Overlay

外部 flake 可以直接覆盖该包:

{
inputs.hermes-agent.url = "github:NousResearch/hermes-agent";
outputs = { hermes-agent, nixpkgs, ... }: {
nixpkgs.overlays = [ hermes-agent.overlays.default ];
# 然后:
# pkgs.hermes-agent.override { extraPythonPackages = [...]; }
# pkgs.hermes-agent.override { extraDependencyGroups = [ "hindsight" ]; }
};
}

插件配置

插件仍然需要在 config.yaml 中启用。通过声明式设置添加它们:

services.hermes-agent.settings.plugins.enabled = [
"hermes-lcm"
"rtk-rewrite"
];
노트

构建时的冲突检查会阻止插件包覆盖核心 hermes 依赖。如果某个插件提供了密封 venv 中已有的包,nixos-rebuild 会失败并显示明确的错误信息。


开发

开发 Shell

该 flake 提供了一个开发 shell,包含 Python 3.12、uv、Node.js 以及所有运行时工具:

cd hermes-agent
nix develop

# Shell 提供:
# - Python 3.12 + uv(首次进入时依赖项安装到 .venv)
# - Node.js 22、ripgrep、git、openssh、ffmpeg(均在 PATH 中)
# - 戳文件优化:如果依赖项未更改,重新进入几乎是瞬间完成

hermes setup
hermes chat

direnv(推荐)

附带的 .envrc 会自动激活开发 shell:

cd hermes-agent
direnv allow # 一次性操作
# 后续进入几乎是瞬间完成(戳文件跳过依赖安装)

Flake 检查

该 flake 包含构建时验证,可在 CI 和本地运行:

# 运行所有检查
nix flake check

# 单项检查
nix build .#checks.x86_64-linux.package-contents # 二进制文件存在 + 版本
nix build .#checks.x86_64-linux.entry-points-sync # pyproject.toml ↔ Nix 包同步
nix build .#checks.x86_64-linux.cli-commands # gateway/config 子命令
nix build .#checks.x86_64-linux.managed-guard # HERMES_MANAGED 阻止变更
nix build .#checks.x86_64-linux.bundled-skills # 包中包含的技能
nix build .#checks.x86_64-linux.config-roundtrip # 合并脚本保留用户键
每个检查项验证的内容
检查项测试内容
package-contentshermeshermes-agent 二进制文件存在且 hermes version 可运行
entry-points-syncpyproject.toml 中的每个 [project.scripts] 条目在 Nix 包中都有一个对应的包装二进制文件
cli-commandshermes --help 暴露 gatewayconfig 子命令
managed-guardHERMES_MANAGED=true hermes config set ... 打印出 NixOS 错误
bundled-skills技能目录存在,包含 SKILL.md 文件,HERMES_BUNDLED_SKILLS 在包装脚本中已设置
config-roundtrip7 种合并场景:全新安装、Nix 覆盖、用户密钥保留、混合合并、MCP 加法合并、嵌套深度合并、幂等性

选项参考

核心

选项类型默认值描述
enableboolfalse启用 hermes-agent 服务
packagepackagehermes-agent要使用的 hermes-agent 包
userstr"hermes"系统用户
groupstr"hermes"系统组
createUserbooltrue自动创建用户/组
stateDirstr"/var/lib/hermes"状态目录(HERMES_HOME 的父目录)
workingDirectorystr"${stateDir}/workspace"Agent 工作目录(MESSAGING_CWD
addToSystemPackagesboolfalsehermes CLI 添加到系统 PATH 并全局设置 HERMES_HOME

配置

选项类型默认值描述
settingsattrs(深度合并){}声明式配置,渲染为 config.yaml。支持任意嵌套;多个定义通过 lib.recursiveUpdate 合并
configFilenullpathnull现有 config.yaml 的路径。若设置,将完全覆盖 settings

密钥与环境变量

选项类型默认值描述
environmentFileslistOf str[]包含密钥的环境文件路径。在激活时合并到 $HERMES_HOME/.env
environmentattrsOf str{}非密钥环境变量。在 Nix 存储中可见 — 请勿在此放置密钥
authFilenullpathnullOAuth 凭据种子。仅在首次部署时复制
authFileForceOverwriteboolfalse激活时始终从 authFile 覆盖 auth.json

文档

选项类型默认值描述
documentsattrsOf (either str path){}工作区文件。键为文件名,值为内联字符串或路径。在激活时安装到 workingDirectory

MCP 服务器

选项类型默认值描述
mcpServersattrsOf submodule{}MCP 服务器定义,合并到 settings.mcp_servers
mcpServers.<name>.commandnullstrnull服务器命令(stdio 传输)
mcpServers.<name>.argslistOf str[]命令参数
mcpServers.<name>.envattrsOf str{}服务器进程的环境变量
mcpServers.<name>.urlnullstrnull服务器端点 URL(HTTP/StreamableHTTP 传输)
mcpServers.<name>.headersattrsOf str{}HTTP 头,例如 Authorization
mcpServers.<name>.authnull"oauth"null认证方法。"oauth" 启用 OAuth 2.1 PKCE
mcpServers.<name>.enabledbooltrue启用或禁用此服务器
mcpServers.<name>.timeoutnullintnull工具调用超时时间(秒,默认:120)
mcpServers.<name>.connect_timeoutnullintnull连接超时时间(秒,默认:60)
mcpServers.<name>.toolsnullsubmodulenull工具过滤(include/exclude 列表)
mcpServers.<name>.samplingnullsubmodulenull服务器发起的 LLM 请求的采样配置

服务行为

选项类型默认值描述
extraArgslistOf str[]传递给 hermes gateway 的额外参数
extraPackageslistOf package[]可供 Agent 使用的额外软件包。会添加到 hermes 用户的个人配置文件中,使得终端命令、技能和 cron 任务都能访问到它们
extraPluginslistOf package[]要符号链接到 $HERMES_HOME/plugins/ 的目录插件包。每个包必须包含 plugin.yaml
extraPythonPackageslistOf package[]添加到 PYTHONPATH 中用于入口点插件发现的 Python 包。使用 python312Packages 构建
extraDependencyGroupslistOf str[]pyproject.toml 中的可选额外依赖组,包含在密封的虚拟环境中(例如 ["hindsight"])。由 uv 解析——没有冲突
restartstr"always"systemd 的 Restart= 策略
restartSecint5systemd 的 RestartSec=

容器

选项类型默认值描述
container.enableboolfalse启用 OCI 容器模式
container.backendenum ["docker" "podman"]"docker"容器运行时
container.imagestr"ubuntu:24.04"基础镜像(运行时拉取)
container.extraVolumeslistOf str[]额外的卷挂载(宿主机:容器:模式
container.extraOptionslistOf str[]传递给 docker create 的额外参数
container.hostUserslistOf str[]交互用户会获得一个指向服务 stateDir 的 ~/.hermes 符号链接,并自动添加到 hermes

目录布局

本地模式

/var/lib/hermes/                     # stateDir(由 hermes:hermes 拥有,权限 0750)
├── .hermes/ # HERMES_HOME
│ ├── config.yaml # Nix 生成(每次重建时深度合并)
│ ├── .managed # 标记:CLI 配置变更被阻止
│ ├── .env # 从 environment 和 environmentFiles 合并
│ ├── auth.json # OAuth 凭证(初始注入后自行管理)
│ ├── gateway.pid
│ ├── state.db
│ ├── mcp-tokens/ # MCP 服务器的 OAuth 令牌
│ ├── sessions/
│ ├── memories/
│ ├── skills/
│ ├── cron/
│ └── logs/
├── home/ # Agent HOME
└── workspace/ # MESSAGING_CWD
├── SOUL.md # 来自 documents 选项
└── (Agent 创建的文件)

容器模式

布局相同,挂载到容器内:

容器路径宿主机路径模式说明
/nix/store/nix/storeroHermes 二进制文件及所有 Nix 依赖
/data/var/lib/hermesrw所有状态、配置、工作区
/home/hermes${stateDir}/homerw持久的 agent home — pip install --user、工具缓存
/usr, /usr/local, /tmp(可写层)rwapt/pip/npm 安装 — 重启后持续存在,重新创建后丢失

故障排查

Podman 用户

以下所有 docker 命令在 podman 下同样适用。如果你设置了 container.backend = "podman",请相应替换。

服务日志

# 两种模式都使用相同的 systemd 单元
journalctl -u hermes-agent -f

# 容器模式:也可直接使用
docker logs -f hermes-agent

容器检查

systemctl status hermes-agent
docker ps -a --filter name=hermes-agent
docker inspect hermes-agent --format='{{.State.Status}}'
docker exec -it hermes-agent bash
docker exec hermes-agent readlink /data/current-package
docker exec hermes-agent cat /data/.container-identity

强制重建容器

如果需要重置可写层(恢复为全新 Ubuntu):

sudo systemctl stop hermes-agent
docker rm -f hermes-agent
sudo rm /var/lib/hermes/.container-identity
sudo systemctl start hermes-agent

验证密钥是否已加载

如果 Agent 启动后无法与 LLM 提供商认证,请检查 .env 文件是否已正确合并:

# 原生模式
sudo -u hermes cat /var/lib/hermes/.hermes/.env

# 容器模式
docker exec hermes-agent cat /data/.hermes/.env

GC 根验证

nix-store --query --roots $(docker exec hermes-agent readlink /data/current-package)

常见问题

症状原因解决方案
Cannot save configuration: managed by NixOSCLI 保护机制已启用编辑 configuration.nix 并执行 nixos-rebuild switch
容器被意外重建extraVolumesextraOptionsimage 发生变化这是预期行为——可写层会重置。请重新安装软件包或使用自定义镜像
hermes version 显示旧版本容器未重启执行 systemctl restart hermes-agent
/var/lib/hermes 权限不足状态目录权限为 0750 hermes:hermes使用 docker execsudo -u hermes
nix-collect-garbage 删除了 hermesGC 根缺失重启服务(preStart 会重新创建 GC 根)
no container with name or ID "hermes-agent"(Podman)普通用户无法看到 Podman 根容器为 podman 添加无密码 sudo(参见 容器模式 一节)
unable to find user hermes容器仍在启动(入口点尚未创建用户)等待几秒后重试——CLI 会自动重试
通过 extraPackages 添加的工具在终端中找不到需要执行 nixos-rebuild switch 更新用户级配置文件重建并重启:nixos-rebuild switch && systemctl restart hermes-agent