Hermes Agent 附帶一個 Nix flake,提供三個層級的整合:
| 層級 | 適用對象 | 你獲得的 |
|---|---|---|
nix run / nix profile install | 任何 Nix 使用者(macOS、Linux) | 包含所有相依性的預建二進位檔——然後使用標準 CLI 工作流程 |
| NixOS 模組(原生) | NixOS 伺服器部署 | 宣告式設定、加固的 systemd 服務、管理的密鑰 |
| NixOS 模組(容器) | 需要自我修改的代理 | 以上所有內容,加上一個持久的 Ubuntu 容器,代理可以在其中執行 apt/pip/npm install |
資訊——與標準安裝有什麼不同
curl | bash安裝器自行管理 Python、Node 和相依性。Nix flake 取代了所有這些——每個 Python 相依性都是由 uv2nix 建置的 Nix derivation,運行時工具(Node.js、git、ripgrep、ffmpeg)被包裝到二進位檔的 PATH 中。沒有運行時 pip、沒有 venv 啟動、沒有npm install。對於非 NixOS 使用者,這只改變了安裝步驟。之後的所有操作(
hermes setup、hermes gateway install、設定編輯)都與標準安裝完全相同。對於 NixOS 模組使用者,整個生命週期都不同:設定存在於
configuration.nix中,密鑰透過 sops-nix/agenix 處理,服務是一個 systemd 單元,CLI 設定指令被封鎖。你像管理任何其他 NixOS 服務一樣管理 hermes。
前置需求
- 啟用了 flakes 的 Nix — 建議使用 Determinate Nix(預設啟用 flakes)
- 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 後,hermes、hermes-agent 和 hermes-acp 都會在你的 PATH 上。從這裡開始,工作流程與標準安裝完全相同——hermes setup 引導你選擇供應商,hermes gateway install 設定 launchd(macOS)或 systemd 使用者服務,設定存在於 ~/.hermes/ 中。
<details> <summary><strong>從本地複製建置</strong></summary>警告——訊息平台(Discord、Telegram、Slack)
預設套件不包含訊息平台函式庫——它們已被移至隨選安裝,這在 Nix 的唯讀環境中無法運作。如果你打算將代理連接到 Discord、Telegram 或 Slack,請安裝
messaging變體:nix profile install github:NousResearch/hermes-agent#messaging對於所有可選的附加元件(語音、所有供應商、所有平台):
nix profile install github:NousResearch/hermes-agent#full
full變體會為 closure 增加約 700 MB。如果你只需要訊息平台,#messaging只增加約 33 MB。
git clone https://github.com/NousResearch/hermes-agent.git
cd hermes-agent
nix build
./result/bin/hermes setup
</details>
NixOS 模組
flake 匯出 nixosModules.default——一個完整的 NixOS 服務模組,以宣告方式管理使用者建立、目錄、設定產生、密鑰、文件和服務生命週期。
注意
此模組需要 NixOS。對於非 NixOS 系統(macOS、其他 Linux 發行版),請使用
nix profile install和上面的標準 CLI 工作流程。
新增 Flake 輸入
# /etc/nixos/flake.nix(或你的系統 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、接上密鑰並啟動閘道——一個長時間運行的服務,將代理連接到訊息平台(Telegram、Discord 等)並監聽傳入訊息。
警告——密鑰是必需的
上面的
environmentFiles那行假設你已經配置了 sops-nix 或 agenix。該檔案應包含至少一個 LLM 供應商金鑰(例如OPENROUTER_API_KEY=sk-or-...)。參閱密鑰管理了解完整設定。如果你還沒有密鑰管理器,可以使用純文字檔案作為起點——只需確保它不是世界可讀的:echo "OPENROUTER_API_KEY=sk-or-your-key" | sudo install -m 0600 -o hermes /dev/stdin /var/lib/hermes/envservices.hermes-agent.environmentFiles = [ "/var/lib/hermes/env" ];
提示——addToSystemPackages
設定
addToSystemPackages = true會做兩件事:將hermesCLI 加入你的系統 PATH 並且全域設定HERMES_HOME,使互動式 CLI 與閘道服務共享狀態(工作階段、技能、定時任務)。沒有它的話,在你的 shell 中執行hermes會建立一個獨立的~/.hermes/目錄。
容器感知的 CLI
資訊
當
container.enable = true且addToSystemPackages = true時,主機上的每個hermes指令都會自動路由到管理的容器中。這意味著你的互動式 CLI 工作階段在與閘道服務相同的環境中運行——可以存取所有容器安裝的套件和工具。
- 路由是透明的:
hermes chat、hermes sessions list、hermes version等底層都 exec 到容器中- 所有 CLI 標誌都原樣轉發
- 如果容器未運行,CLI 會短暫重試(互動式使用時 5 秒並顯示旋轉器,腳本中靜默 10 秒),然後以清晰的錯誤失敗——沒有靜默回退
- 對於在 hermes 程式碼庫上工作的開發者,設定
HERMES_DEV=1以繞過容器路由並直接執行本地簽出設定
container.hostUsers以建立一個指向服務狀態目錄的~/.hermes符號連結,使主機 CLI 和容器共享工作階段、設定和記憶:services.hermes-agent = { container.enable = true; container.hostUsers = [ "your-username" ]; addToSystemPackages = true; };列在
hostUsers中的使用者會自動加入hermes群組以取得檔案權限存取。Podman 使用者: NixOS 服務以 root 身分運行容器。Docker 使用者透過
docker群組 socket 存取,但 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 以唯讀方式綁定掛載 |
| 安全性 | NoNewPrivileges、ProtectSystem=strict、PrivateTmp | 容器隔離,以無權限使用者身分在內部運行 |
| 代理可以自我安裝套件 | 否——只有 Nix 提供的 PATH 上的工具 | 是——apt、pip、npm 安裝在重啟間持久存在 |
| 設定介面 | 相同 | 相同 |
| 何時選擇 | 標準部署、最大安全性、可重現性 | 代理需要運行時套件安裝、可變環境、實驗性工具 |
要啟用容器模式,新增一行:
{
services.hermes-agent = {
enable = true;
container.enable = true;
# ... 其餘設定相同
};
}
資訊
容器模式透過
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 不觸及的使用者新增鍵會被保留。這意味著如果代理或手動編輯新增了像 skills.disabled 或 streaming.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。
<details> <summary><strong>完整範例:所有常見自訂設定</strong></summary>提示——發現可用的設定鍵
執行
nix build .#configKeys && cat result查看從 Python 的DEFAULT_CONFIG提取的每個葉節點設定鍵。你可以將現有的config.yaml貼到settingsattrset 中——結構是 1:1 映射的。
{ config, ... }: {
services.hermes-agent = {
enable = true;
container.enable = true;
# ── 模型 ──────────────────────────────────────────────────────────
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; };
};
# ── 密鑰 ────────────────────────────────────────────────────────
environmentFiles = [ config.sops.secrets."hermes-env".path ];
# ── 文件 ──────────────────────────────────────────────────────
documents = {
"USER.md" = ./documents/USER.md;
};
# ── MCP 伺服器 ────────────────────────────────────────────────
mcpServers.filesystem = {
command = "npx";
args = [ "-y" "@modelcontextprotocol/server-filesystem" "/data/workspace" ];
};
# ── 容器選項 ──────────────────────────────────────────────
container = {
image = "ubuntu:24.04";
backend = "docker";
hostUsers = [ "your-username" ];
extraVolumes = [ "/home/user/projects:/projects:rw" ];
extraOptions = [ "--gpus" "all" ];
};
# ── 服務調整 ─────────────────────────────────────────────────
addToSystemPackages = true;
extraArgs = [ "--verbose" ];
restart = "always";
restartSec = 5;
};
}
</details>
逃生艙口:帶你自己的設定
如果你更想完全在 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 ] |
| 給代理一個個性 | ${services.hermes-agent.stateDir}/.hermes/SOUL.md | 直接管理檔案 |
| 新增 MCP 工具伺服器 | mcpServers.<name> | 參閱 MCP 伺服器 |
| 啟用 Discord/Telegram/Slack | extraDependencyGroups | [ "messaging" ] |
| 將主機目錄掛載到容器中 | container.extraVolumes | [ "/data:/data:rw" ] |
| 將 GPU 存取傳遞給容器 | container.extraOptions | [ "--gpus" "all" ] |
| 使用 Podman 代替 Docker | container.backend | "podman" |
| 在主機 CLI 和容器之間共享狀態 | container.hostUsers | [ "sidbin" ] |
| 讓額外工具對代理可用 | extraPackages | [ pkgs.pandoc pkgs.imagemagick ] |
| 使用自訂基礎映像 | container.image | "ubuntu:24.04" |
| 覆蓋 hermes 套件 | package | inputs.hermes-agent.packages.${system}.default.override { ... } |
| 變更狀態目錄 | stateDir | "/opt/hermes" |
| 設定代理的工作目錄 | workingDirectory | "/home/user/projects" |
密鑰管理
危險——永遠不要將 API 金鑰放在
settings或environment中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(使用 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 token 刷新會寫入狀態目錄並在重建間保留。
文件
documents 選項將檔案安裝到代理的工作目錄(workingDirectory,代理將其讀為工作區)。Hermes 按慣例尋找特定檔名:
USER.md— 關於代理互動使用者的上下文。- 你放在這裡的任何其他檔案對代理來說都是工作區檔案。
代理身份檔案是分開的:Hermes 從 $HERMES_HOME/SOUL.md 載入其主要的 SOUL.md,在 NixOS 模組中是 ${services.hermes-agent.stateDir}/.hermes/SOUL.md。在 documents 中放入 SOUL.md 只會建立一個工作區檔案,不會取代主要的個性檔案。
{
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注入密鑰——永遠不要在 Nix 設定中直接放入 token。
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 流程——元資料發現、動態客戶端註冊、token 交換和自動刷新。
{
services.hermes-agent.mcpServers.my-oauth-server = {
url = "https://mcp.example.com/mcp";
auth = "oauth";
};
}
Token 儲存在 $HERMES_HOME/mcp-tokens/<server-name>.json 中,並在重啟和重建間保留。
初始 OAuth 授權需要基於瀏覽器的同意流程。在無頭部署中,Hermes 會將授權 URL 印到 stdout/日誌而不是開啟瀏覽器。
選項 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:預先種入 token——在工作站上完成流程,然後複製 token:
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
</details>
採樣(伺服器發起的 LLM 請求)
一些 MCP 伺服器可以向代理請求 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 install | systemd 服務由 NixOS 管理 |
hermes gateway uninstall | systemd 服務由 NixOS 管理 |
這防止了 Nix 宣告的內容和磁碟上的內容之間的漂移。偵測使用兩個訊號:
HERMES_MANAGED=true環境變數——由 systemd 服務設定,對閘道程序可見.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 token)
├── home/ ──► /home/hermes (讀寫)
└── workspace/ (代理工作目錄)
├── SOUL.md (來自 documents 選項)
└── (代理建立的檔案)
容器可寫入層(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 root) | 持久存在 | 持久存在 | 持久存在 |
映像變更(container.image) | 是 | 持久存在 | 持久存在 | 遺失 |
| 卷/選項變更 | 是 | 持久存在 | 持久存在 | 遺失 |
environment/environmentFiles 變更 | 否 | 持久存在 | 持久存在 | 持久存在 |
容器只在其身份雜湊變更時重建。雜湊涵蓋:結構描述版本、映像、extraVolumes、extraOptions 和進入點腳本。環境變數、設定、文件或 hermes 套件本身的變更不會觸發重建。
警告——可寫入層遺失
當身份雜湊變更時(映像升級、新卷、新容器選項),容器會被銷毀並從
container.image的全新拉取重建。可寫入層中的任何apt install、pip install或npm install套件會遺失。/data和/home/hermes中的狀態會保留(這些是綁定掛載)。如果代理依賴特定套件,考慮將它們烘焙到自訂映像中(
container.image = "my-registry/hermes-base:latest")或在代理的 SOUL.md 中腳本化它們的安裝。
GC Root 保護
preStart 腳本在 ${stateDir}/.gc-root 建立一個 GC root,指向目前的 hermes 套件。這防止 nix-collect-garbage 移除正在運行的二進位檔。如果 GC root 以某種方式損壞,重啟服務會重新建立它。
外掛
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 中宣告的可選附加元件,使用 extraDependencyGroups 在建置時將它們包含在密封的虛擬環境中。這是任何不在預設 [all] 集合中的附加元件所需要的——在 Nix 上,運行時安裝到唯讀 store 是不可能的。
# 啟用 Discord、Telegram、Slack
services.hermes-agent.extraDependencyGroups = [ "messaging" ];
# 啟用記憶提供者
services.hermes-agent = {
extraDependencyGroups = [ "hindsight" ];
settings.memory.provider = "hindsight";
};
這由 uv 與核心相依性一起解析——沒有 PYTHONPATH 修補,沒有衝突風險。可用群組:
| 群組 | 啟用的內容 |
|---|---|
messaging | Discord、Telegram、Slack |
matrix | Matrix/Element(mautrix 帶加密;僅 Linux) |
dingtalk | DingTalk |
feishu | Feishu/Lark |
voice | 本地語音轉文字(faster-whisper) |
edge-tts | Edge TTS 提供者 |
tts-premium | ElevenLabs TTS |
anthropic | 原生 Anthropic SDK(透過 OpenRouter 時不需要) |
bedrock | AWS Bedrock(boto3) |
azure-identity | Azure Entra ID 驗證 |
honcho | Honcho 記憶提供者 |
hindsight | Hindsight 記憶提供者 |
modal | Modal 終端機後端 |
daytona | Daytona 終端機後端 |
exa | Exa 網路搜尋 |
firecrawl | Firecrawl 網路搜尋 |
fal | FAL 圖片生成 |
或使用預建的 #messaging 或 #full flake 套件代替逐個附加元件的配置(參閱快速開始)。
何時使用哪個:
| 需求 | 選項 |
|---|---|
| 啟用 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 相依性。如果外掛提供了密封虛擬環境中已有的套件,
nixos-rebuild會以清晰的錯誤失敗。
開發
開發 Shell
flake 提供了一個帶有 Python 3.12、uv、Node.js 和所有運行時工具的開發 shell:
cd hermes-agent
nix develop
# Shell 提供:
# - Python 3.12 + uv(首次進入時相依性安裝到 .venv)
# - Node.js 22、ripgrep、git、openssh、ffmpeg 在 PATH 上
# - Stamp 檔案優化:如果相依性未變更,重新進入幾乎即時
hermes setup
hermes chat
direnv(建議)
內含的 .envrc 會自動啟動開發 shell:
cd hermes-agent
direnv allow # 一次性的
# 後續進入幾乎即時(stamp 檔案跳過相依性安裝)
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 # 合併腳本保留使用者鍵
<details>
<summary><strong>每個檢查驗證什麼</strong></summary>
| 檢查 | 測試什麼 |
|---|---|
package-contents | hermes 和 hermes-agent 二進位檔存在且 hermes version 可執行 |
entry-points-sync | pyproject.toml 中每個 [project.scripts] 進入點在 Nix 套件中都有一個包裝的二進位檔 |
cli-commands | hermes --help 暴露 gateway 和 config 子指令 |
managed-guard | HERMES_MANAGED=true hermes config set ... 印出 NixOS 錯誤 |
bundled-skills | 技能目錄存在、包含 SKILL.md 檔案、HERMES_BUNDLED_SKILLS 在包裝器中設定 |
config-roundtrip | 7 個合併場景:全新安裝、Nix 覆蓋、使用者鍵保留、混合合併、MCP 加法合併、嵌套深層合併、冥等性 |
選項參考
核心
| 選項 | 類型 | 預設值 | 說明 |
|---|---|---|---|
enable | bool | false | 啟用 hermes-agent 服務 |
package | package | hermes-agent | 要使用的 hermes-agent 套件 |
user | str | "hermes" | 系統使用者 |
group | str | "hermes" | 系統群組 |
createUser | bool | true | 自動建立使用者/群組 |
stateDir | str | "/var/lib/hermes" | 狀態目錄(HERMES_HOME 父目錄) |
workingDirectory | str | "${stateDir}/workspace" | 代理工作目錄 |
addToSystemPackages | bool | false | 將 hermes CLI 加入系統 PATH 並全域設定 HERMES_HOME |
設定
| 選項 | 類型 | 預設值 | 說明 |
|---|---|---|---|
settings | attrs(深層合併) | {} | 渲染為 config.yaml 的宣告式設定。支援任意巢狀;多個定義透過 lib.recursiveUpdate 合併 |
configFile | null 或 path | null | 現有 config.yaml 的路徑。設定時完全覆蓋 settings |
密鑰與環境
| 選項 | 類型 | 預設值 | 說明 |
|---|---|---|---|
environmentFiles | listOf str | [] | 含密鑰的 env 檔案路徑。在啟動時合併到 $HERMES_HOME/.env |
environment | attrsOf str | {} | 非機密環境變數。在 Nix store 中可見——不要把密鑰放在這裡 |
authFile | null 或 path | null | OAuth 憑證種子。僅在首次部署時複製 |
authFileForceOverwrite | bool | false | 每次啟動時始終從 authFile 覆蓋 auth.json |
文件
| 選項 | 類型 | 預設值 | 說明 |
|---|---|---|---|
documents | attrsOf (either str path) | {} | 工作區檔案。鍵是檔名,值是內聯字串或路徑。啟動時安裝到 workingDirectory |
MCP 伺服器
| 選項 | 類型 | 預設值 | 說明 |
|---|---|---|---|
mcpServers | attrsOf submodule | {} | MCP 伺服器定義,合併到 settings.mcp_servers |
mcpServers.<name>.command | null 或 str | null | 伺服器指令(stdio 傳輸) |
mcpServers.<name>.args | listOf str | [] | 指令參數 |
mcpServers.<name>.env | attrsOf str | {} | 伺服器程序的環境變數 |
mcpServers.<name>.url | null 或 str | null | 伺服器端點 URL(HTTP/StreamableHTTP 傳輸) |
mcpServers.<name>.headers | attrsOf str | {} | HTTP 標頭,例如 Authorization |
mcpServers.<name>.auth | null 或 "oauth" | null | 驗證方法。"oauth" 啟用 OAuth 2.1 PKCE |
mcpServers.<name>.enabled | bool | true | 啟用或停用此伺服器 |
mcpServers.<name>.timeout | null 或 int | null | 工具呼叫逾時(秒)(預設:120) |
mcpServers.<name>.connect_timeout | null 或 int | null | 連線逾時(秒)(預設:60) |
mcpServers.<name>.tools | null 或 submodule | null | 工具過濾(include/exclude 清單) |
mcpServers.<name>.sampling | null 或 submodule | null | 伺服器發起的 LLM 請求的採樣設定 |
服務行為
| 選項 | 類型 | 預設值 | 說明 |
|---|---|---|---|
extraArgs | listOf str | [] | hermes gateway 的額外參數 |
extraPackages | listOf package | [] | 代理可用的額外套件。加入 hermes 使用者的使用者設定檔,使終端機指令、技能和定時任務都能看到它們 |
extraPlugins | listOf package | [] | 要符號連結到 $HERMES_HOME/plugins/ 的目錄外掛套件。每個必須包含 plugin.yaml |
extraPythonPackages | listOf package | [] | 加入 PYTHONPATH 的 Python 套件,用於進入點外掛發現。使用 python312Packages 建置 |
extraDependencyGroups | listOf str | [] | 要包含在密封虛擬環境中的 pyproject.toml 可選附加元件(例如 ["hindsight"])。由 uv 解析——無衝突 |
restart | str | "always" | systemd Restart= 策略 |
restartSec | int | 5 | systemd RestartSec= 值 |
容器
| 選項 | 類型 | 預設值 | 說明 |
|---|---|---|---|
container.enable | bool | false | 啟用 OCI 容器模式 |
container.backend | enum ["docker" "podman"] | "docker" | 容器執行環境 |
container.image | str | "ubuntu:24.04" | 基礎映像(運行時拉取) |
container.extraVolumes | listOf str | [] | 額外的卷掛載(host:container:mode) |
container.extraOptions | listOf str | [] | 傳遞給 docker create 的額外參數 |
container.hostUsers | listOf 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 token
│ ├── sessions/
│ ├── memories/
│ ├── skills/
│ ├── cron/
│ └── logs/
├── home/ # 代理 HOME
└── workspace/ # 代理工作目錄
├── SOUL.md # 來自 documents 選項
└── (代理建立的檔案)
容器模式
相同的佈局,掛載到容器中:
| 容器路徑 | 主機路徑 | 模式 | 備註 |
|---|---|---|---|
/nix/store | /nix/store | 唯讀 | Hermes 二進位檔 + 所有 Nix 相依性 |
/data | /var/lib/hermes | 讀寫 | 所有狀態、設定、工作區 |
/home/hermes | ${stateDir}/home | 讀寫 | 持久的代理 home——pip install --user、工具快取 |
/usr、/usr/local、/tmp | (可寫入層) | 讀寫 | apt/pip/npm 安裝——在重啟間持久存在,重建時遺失 |
更新
# 更新 flake 輸入(從包含 flake.nix 的目錄執行)
cd /etc/nixos && nix flake update hermes-agent
# 重建
sudo nixos-rebuild switch
在容器模式下,current-package 符號連結會更新,代理在重啟時取得新的二進位檔。無需重建容器,不會遺失已安裝的套件。
疑難排解
提示——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
驗證密鑰已載入
如果代理啟動但無法與 LLM 供應商驗證,檢查 .env 檔案是否正確合併:
# 原生模式
sudo -u hermes cat /var/lib/hermes/.hermes/.env
# 容器模式
docker exec hermes-agent cat /data/.hermes/.env
GC Root 驗證
nix-store --query --roots $(docker exec hermes-agent readlink /data/current-package)
常見問題
| 症狀 | 原因 | 修正 |
|---|---|---|
Cannot save configuration: managed by NixOS | CLI 保護啟動 | 編輯 configuration.nix 並 nixos-rebuild switch |
No adapter available for discord(或 telegram/slack) | 密封的 Nix 虛擬環境中缺少訊息相依性 | 安裝 #messaging 變體:nix profile install ...#messaging。對於 NixOS 模組:extraDependencyGroups = [ "messaging" ]。檢查 journalctl -u hermes-agent 以了解底層錯誤的 FeatureUnavailable 或 requirements not met。 |
| 容器意外重建 | extraVolumes、extraOptions 或 image 變更 | 預期行為——可寫入層重置。重新安裝套件或使用自訂映像 |
hermes version 顯示舊版本 | 容器未重啟 | systemctl restart hermes-agent |
/var/lib/hermes 權限被拒 | 狀態目錄為 0750 hermes:hermes | 使用 docker exec 或 sudo -u hermes |
nix-collect-garbage 移除了 hermes | GC root 缺失 | 重啟服務(preStart 會重新建立 GC root) |
no container with name or ID "hermes-agent"(Podman) | Podman rootful 容器對一般使用者不可見 | 為 podman 新增無密碼 sudo(參閱容器模式章節) |
unable to find user hermes | 容器仍在啟動(進入點尚未建立使用者) | 等待幾秒並重試——CLI 會自動重試 |
透過 extraPackages 新增的工具在終端機中找不到 | 需要 nixos-rebuild switch 來更新使用者設定檔 | 重建並重啟:nixos-rebuild switch && systemctl restart hermes-agent |