H繁中版
<!-- Source: https://hermesbible.com/docs/getting-started/nix-setup -->

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 setuphermes 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 後,hermeshermes-agenthermes-acp 都會在你的 PATH 上。從這裡開始,工作流程與標準安裝完全相同——hermes setup 引導你選擇供應商,hermes gateway install 設定 launchd(macOS)或 systemd 使用者服務,設定存在於 ~/.hermes/ 中。

警告——訊息平台(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。

<details> <summary><strong>從本地複製建置</strong></summary>
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-nixagenix。該檔案應包含至少一個 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/env
services.hermes-agent.environmentFiles = [ "/var/lib/hermes/env" ];

提示——addToSystemPackages

設定 addToSystemPackages = true 會做兩件事:將 hermes CLI 加入你的系統 PATH 並且全域設定 HERMES_HOME,使互動式 CLI 與閘道服務共享狀態(工作階段、技能、定時任務)。沒有它的話,在你的 shell 中執行 hermes 會建立一個獨立的 ~/.hermes/ 目錄。

容器感知的 CLI

資訊

container.enable = trueaddToSystemPackages = true 時,主機上的每個 hermes 指令都會自動路由到管理的容器中。這意味著你的互動式 CLI 工作階段在與閘道服務相同的環境中運行——可以存取所有容器安裝的套件和工具。

  • 路由是透明的:hermes chathermes sessions listhermes 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 以唯讀方式綁定掛載
安全性NoNewPrivilegesProtectSystem=strictPrivateTmp容器隔離,以無權限使用者身分在內部運行
代理可以自我安裝套件否——只有 Nix 提供的 PATH 上的工具是——aptpipnpm 安裝在重啟間持久存在
設定介面相同相同
何時選擇標準部署、最大安全性、可重現性代理需要運行時套件安裝、可變環境、實驗性工具

要啟用容器模式,新增一行:

{
  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.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 attrset 中——結構是 1:1 映射的。

<details> <summary><strong>完整範例:所有常見自訂設定</strong></summary>
{ 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/SlackextraDependencyGroups[ "messaging" ]
將主機目錄掛載到容器中container.extraVolumes[ "/data:/data:rw" ]
將 GPU 存取傳遞給容器container.extraOptions[ "--gpus" "all" ]
使用 Podman 代替 Dockercontainer.backend"podman"
在主機 CLI 和容器之間共享狀態container.hostUsers[ "sidbin" ]
讓額外工具對代理可用extraPackages[ pkgs.pandoc pkgs.imagemagick ]
使用自訂基礎映像container.image"ubuntu:24.04"
覆蓋 hermes 套件packageinputs.hermes-agent.packages.${system}.default.override { ... }
變更狀態目錄stateDir"/opt/hermes"
設定代理的工作目錄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(使用 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 中,並在重啟和重建間保留。

<details> <summary><strong>無頭伺服器上的初始 OAuth 授權</strong></summary>

初始 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 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 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 變更持久存在持久存在持久存在

容器只在其身份雜湊變更時重建。雜湊涵蓋:結構描述版本、映像、extraVolumesextraOptions 和進入點腳本。環境變數、設定、文件或 hermes 套件本身的變更不會觸發重建。

警告——可寫入層遺失

當身份雜湊變更時(映像升級、新卷、新容器選項),容器會被銷毀並從 container.image 的全新拉取重建。可寫入層中的任何 apt installpip installnpm 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 修補,沒有衝突風險。可用群組:

群組啟用的內容
messagingDiscord、Telegram、Slack
matrixMatrix/Element(mautrix 帶加密;僅 Linux)
dingtalkDingTalk
feishuFeishu/Lark
voice本地語音轉文字(faster-whisper)
edge-ttsEdge TTS 提供者
tts-premiumElevenLabs TTS
anthropic原生 Anthropic SDK(透過 OpenRouter 時不需要)
bedrockAWS Bedrock(boto3)
azure-identityAzure Entra ID 驗證
honchoHoncho 記憶提供者
hindsightHindsight 記憶提供者
modalModal 終端機後端
daytonaDaytona 終端機後端
exaExa 網路搜尋
firecrawlFirecrawl 網路搜尋
falFAL 圖片生成

或使用預建的 #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-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 加法合併、嵌套深層合併、冥等性
</details>

選項參考

核心

選項類型預設值說明
enableboolfalse啟用 hermes-agent 服務
packagepackagehermes-agent要使用的 hermes-agent 套件
userstr"hermes"系統使用者
groupstr"hermes"系統群組
createUserbooltrue自動建立使用者/群組
stateDirstr"/var/lib/hermes"狀態目錄(HERMES_HOME 父目錄)
workingDirectorystr"${stateDir}/workspace"代理工作目錄
addToSystemPackagesboolfalsehermes CLI 加入系統 PATH 並全域設定 HERMES_HOME

設定

選項類型預設值說明
settingsattrs(深層合併){}渲染為 config.yaml 的宣告式設定。支援任意巢狀;多個定義透過 lib.recursiveUpdate 合併
configFilenullpathnull現有 config.yaml 的路徑。設定時完全覆蓋 settings

密鑰與環境

選項類型預設值說明
environmentFileslistOf str[]含密鑰的 env 檔案路徑。在啟動時合併到 $HERMES_HOME/.env
environmentattrsOf str{}非機密環境變數。在 Nix store 中可見——不要把密鑰放在這裡
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[]代理可用的額外套件。加入 hermes 使用者的使用者設定檔,使終端機指令、技能和定時任務都能看到它們
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[]額外的卷掛載(host:container:mode
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 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 NixOSCLI 保護啟動編輯 configuration.nixnixos-rebuild switch
No adapter available for discord(或 telegram/slack)密封的 Nix 虛擬環境中缺少訊息相依性安裝 #messaging 變體:nix profile install ...#messaging。對於 NixOS 模組:extraDependencyGroups = [ "messaging" ]。檢查 journalctl -u hermes-agent 以了解底層錯誤的 FeatureUnavailablerequirements not met
容器意外重建extraVolumesextraOptionsimage 變更預期行為——可寫入層重置。重新安裝套件或使用自訂映像
hermes version 顯示舊版本容器未重啟systemctl restart hermes-agent
/var/lib/hermes 權限被拒狀態目錄為 0750 hermes:hermes使用 docker execsudo -u hermes
nix-collect-garbage 移除了 hermesGC 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


功能概覽