iT邦幫忙

2026 iThome 鐵人賽

DAY 8
0
AI Engineering

打造具備記憶與執行能力的常駐 AI Agent:Hermes Agent × Gemini × MCP 的 Harness 設計系列 第 8 篇

【Day 8】Profile 的隔離邊界:狀態各自獨立,檔案系統共用

  • 分享至 

  • xImage
  •  

一台機器上要同時養幾個 agent,最直接的做法是開多個 profile。Hermes 把組態、記憶、排程與 session 各自分開,切換只需要一個旗標。這種隔離的涵蓋範圍決定了其中一個 profile 能掛上多高權限的工具。以下逐項確認邊界落在哪裡。


profile 隔離了哪些狀態

hermes profile 自己的說明是「多個互相隔離的 Hermes 實例」。每個 profile 是根目錄底下 profiles/<名稱> 的一整棵目錄,結構與根目錄同構:

路徑 內容
config.yaml 模型、工具與 MCP 掛載清單
.env 該 profile 專用的金鑰與平台 token
SOUL.md 身分宣告
memories/ 跨 session 保存的狀態
sessions/、state.db 對話歷史與全文檢索索引
cron/ 排程定義
skills/、hooks/ 技能與 hook
gateway.pid、gateway_state.json 該 profile 的 gateway 執行狀態

切換用 -p 或 --profile,兩個旗標等效。在同一台機器上對不同 profile 讀同一個鍵,拿到的是各自的值:

hermes config get model.default             # 目前作用中的 profile
hermes -p work config get model.default     # 指定 profile

建立 profile 時會順手在 ~/.local/bin 放一支同名的包裝腳本,內容是帶好旗標再呼叫 hermes,於是 work <指令> 等同 hermes -p work <指令>。加 --no-alias 可略過這支腳本。


三種建立方式複製的範圍不同

方式 複製什麼
無旗標 空 profile,只帶內建技能
--clone 組態、身分與記憶索引
--clone-all 來源 profile 的完整副本,扣掉歷史與基礎設施

--clone 的清單寫死在原始碼裡,共五個檔案:

  • config.yaml、.env、SOUL.md
  • memories/MEMORY.md、memories/USER.md

註解說明記憶檔為何列在這一組:它們與 SOUL.md 同屬 agent 的身分,複製 profile 時一併帶走才有延續性。

--clone-all 排除兩組東西。

第一組是歷史類,任何來源都排除:

  • state.db 與它的 wal、shm 檔
  • sessions、backups、state-snapshots、checkpoints

原始碼給的理由有兩個,一是在新 profile 裡還原來源 profile 的快照會把來源的狀態整個救回來,二是這些目錄可以膨脹到數十 GB。

第二組是基礎設施類,只在來源是根目錄時排除:

  • hermes-agent、node_modules、bin
  • profiles、.worktrees

複製完再刪掉 gateway.pid、gateway_state.json、processes.json 三個執行期檔案,避免新 profile 一開機就以為自己有 gateway 在跑。

另外 --no-skills 會在 profile 根目錄寫一個 .no-bundled-skills 標記檔,hermes update 的全 profile 技能同步看到這個檔案就跳過。

複製的範圍是身分與組態,歷史留在原 profile


HERMES_HOME 的邊界止於狀態

profile 的實作方式是把 HERMES_HOME 指到 profiles/<名稱>。這條邊界管的是 Hermes 自己讀寫的狀態,工具子行程的權限由另外三個組態值決定:

鍵 預設值 效果
terminal.backend local 工具指令在本機直接執行
terminal.cwd . 工作目錄是啟動 hermes 時所在的目錄
terminal.home_mode auto 本機安裝維持作業系統使用者的真實 HOME

三個值合起來的結果是:工具子行程以目前這個作業系統使用者的身分執行,看到的是完整的家目錄與完整的檔案系統。一個 profile 裡的 agent 讀得到另一個 profile 的 .env,也讀得到這台機器上該使用者讀得到的任何檔案。

SOUL.md 裡寫「只在某個目錄底下工作」是 prompt 層的指示,遵守與否取決於模型,越界的讀寫在檔案系統層照常執行。


檔案系統隔離來自 terminal backend

terminal.backend 換掉才會出現檔案系統邊界。除了 local 之外,Hermes 認得的遠端 backend 有 docker、singularity、modal、daytona、ssh、managed_modal、vercel_sandbox。

遠端 backend 建立的沙箱從空的檔案系統開始。 要讓 agent 用得到憑證檔、技能目錄與上傳快取,得在建立沙箱時明確掛載或同步進去。Hermes 為此維護一份 session 範圍的檔案通行登記,來源有兩處:

  • 技能自己宣告的 required_credential_files
  • 使用者組態的 terminal.credential_files

兩個 Docker 相關的預設值看得出取向:

鍵 預設值 說明
terminal.docker_mount_cwd_to_workspace false 原始碼註解寫明預設關閉的理由是把 host 目錄傳進沙箱會削弱隔離
terminal.docker_network true 設為 false 時 docker run 帶 --network=none,容器的對外連線全部斷開

隔離程度由 terminal backend 決定


同一組平台憑證同時只有一個 profile 持有

Gateway 連上 Discord 或 Telegram 這類平台時會先取一把 scoped lock。鎖檔放在整台機器共用的 ~/.local/state/hermes/gateway-locks(可用 HERMES_GATEWAY_LOCK_DIR 覆寫),檔名是 <範圍>-<憑證的 SHA-256 前 16 碼>.lock。

實際的鎖檔內容:

{
  "pid": 11304,
  "kind": "hermes-gateway",
  "start_time": 178865880330,
  "hermes_home": "...\hermes",
  "scope": "discord-bot-token",
  "identity_hash": "<16 碼雜湊>",
  "metadata": {"platform": "discord"},
  "profile": "<profile 名稱>"
}

檔名只留雜湊的前 16 碼,token 本身留在 .env。 兩個 profile 填同一個 token 才會算出同一個檔名而相撞,填不同 token 的兩個 profile 可以同時跑 gateway。

鎖被占用時的錯誤訊息會指名持有者是哪一個 profile,並附上停掉它的指令。原始碼註解說明為何要多印這個名稱:scoped lock 是整台機器共用的,持有者可能是另一個 profile 的 gateway,只給 PID 時,維運者要另外查出它對應哪一個 profile。

這把鎖放在 HERMES_HOME 外面,因為被保護的資源是平台那一側的連線。同一個 bot token 在平台那一側只對應一條連線,兩個 gateway 同時連上去,同一則訊息會被處理兩次。

殘留鎖檔在下一次取鎖時會被查核。 取鎖時做兩道查核:

  1. 記錄的 PID 是否還存在
  2. 該行程的啟動時間指紋是否與記錄相符

兩者都相符才認定是有效持有者。PID 被系統回收再指派給別的行程時,指紋隨之改變。

Day08ProfileIsolationBoundary


心得

這台機器的 gateway-locks 目錄裡躺著兩個鎖檔,Discord 與 Telegram 各一把,記錄的 PID 是 11304、時間戳是九天前,登記的 profile 也不是現在作用中的那一個。那個行程早就結束了,鎖檔還在。

鎖檔留著,後續啟動仍會經過 PID 與啟動時間的驗證。直接看這個目錄會讀成現在有 gateway 正在跑,而且跑的是鎖檔上登記的那個 profile,實際作用中的是另一個。

要知道哪個 profile 的 gateway 正在跑,看 hermes profile list 的 Gateway 欄位,它逐一顯示 running 或 stopped。

鎖檔記錄的是憑證占用,行程存活由 PID 與啟動時間決定,正常關閉時兩者一致,強制終止時鎖檔會留下


明天

Gemini provider 的組態,以及原生 API 與 OpenAI 相容層的差別。


上一篇
【Day 7】技術選型、安裝與組態結構
下一篇
【Day 9】Provider 組態:原生 API 與 OpenAI 相容層的差別
系列文
打造具備記憶與執行能力的常駐 AI Agent:Hermes Agent × Gemini × MCP 的 Harness 設計 共 13 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言