Hermes Agent SOUL.md:3 層提示詞、14 個內置人格,從源碼看身份定製的完整設計
整理版優先睇
Hermes Agent 用三層提示詞同 SOUL.md 實現身份與項目分離,確保 Agent 人格穩定統一
呢篇文章由術哥撰寫,佢係專注 AI 編程同 Agent 技術嘅實踐者,透過分析 Hermes Agent 源碼同官方文檔,拆解 SOUL.md 人格系統嘅設計原理。文章主要想解決一個常見問題:點解同一個 AI Agent 喺唔同項目會有唔同風格?傳統做法將身份、風格、項目規範全部塞入 system prompt,改project 時好易搞亂 Agent 嘅說話方式。Hermes Agent 用一套三層提示詞架構(stable、context、volatile)將呢啲嘢分開,其中 SOUL.md 專門管理 Agent 嘅身份同溝通風格,唔受項目影響。
文章從源碼層面詳細解釋咗三層點樣運作:stable 層包含 SOUL.md 同埋工具引導等不變內容,擺喺最前面以利前綴緩存;context 層放用戶訊息同 AGENTS.md 等項目文件;volatile 層放每次對話都會變嘅記憶同時間戳。SOUL.md 只會從 $HERMES_HOME 加載,原樣注入 system prompt,唔加任何包裝,確保模型直接接收身份描述。另外仲有安全掃描同截斷機制,防止提示注入同過長內容。
整體結論係:Hermes Agent 透過身份同項目嚴格分離,配合 /personality 命令嘅 overlay 機制,做到穩定嘅人格基線同時保留靈活切換。呢個設計比主流框架(如 Claude Code、Cursor)多一層全局身份管理,代價係多維…
- Hermes Agent 三層提示詞(stable/context/volatile)將不變嘅身份引導同變動嘅上下文分開,提升前綴緩存命中率,節省 API 成本。
- SOUL.md 只從 $HERMES_HOME 加載,唔受工作目錄影響,確保人格跨項目一致;而 AGENTS.md 從項目目錄加載,管理項目級指令。
- SOUL.md 原樣注入 system prompt,冇任何包裝文本,避免幹擾模型注意力;安全掃描會攔截提示注入,阻止惡意指令進入系統提示詞。
- /personality 命令提供 14 個內置人格預設同自定義選項,以 overlay 方式疊加喺 SOUL.md 之上,唔係完全取代,可用 /personality none 恢復基線。
- 最佳實踐:先用默認身份觀察回覆,記錄不滿之處,逐步調整 SOUL.md;SOUL.md 應包含跨上下文穩定嘅溝通偏好,唔好放項目指令或臨時風格。
SOUL.md 示例模板
# Personality You are a pragmatic senior engineer with strong taste. You optimize for truth, clarity, and usefulness over politeness theater. ## Style - Be direct without being cold - Prefer substance over filler - Push back when something is a bad idea - Admit uncertainty plainly ## What to avoid - Sycophancy - Hype language - Repeating the user's framing if it's wrong ## Technical posture - Prefer simple systems over clever systems - Care about operational reality - Treat edge cases as part of the design
三層提示詞:點解唔係一層?
Hermes 嘅系統提示詞唔係一舊過拼埋一齊嘅大字符串,而係分成三層:stable(穩定層)、context(上下文層)、volatile(易變層)。目的係為咗前綴緩存友好——將唔變嘅內容放喺前面,變嘅內容放後面,咁樣 API 提供商就可以重用已緩存嘅前綴,節省 token 計費。
stable 層包含 SOUL.md 身份、工具行為引導、技能提示、環境提示呢啲整個會話生命週期基本不變嘅內容
context 層放用戶傳入嘅 system_message 同 AGENTS.md 等上下文文件
volatile 層放記憶快照、USER.md 畫像、時間戳、會話 ID 呢啲每次都會變嘅嘢
- stable 層總共有 14 個部分,SOUL.md 係第一個
- SOUL.md 放第一個係因為後面嘅工具引導都以佢定義嘅身份為前提
- SOUL.md 只從 HERMES_HOME 加載,確保 stable 層穩定,唔會搞亂緩存
SOUL.md 加載流程:從文件到提示詞
SOUL.md 嘅加載鏈路由 load_soul_md() 函數執行,路徑寫死喺 get_hermes_home() / "SOUL.md",只認 ~/.hermes/SOUL.md,唔會從當前工作目錄揾。呢個設計同 AGENTS.md 相反——AGENTS.md 管項目,所以從 cwd 向上遍歷;SOUL.md 管人,人走到邊度身份都一樣。
位置鎖定確保人格唔會因為啟動目錄唔同而改變
如果 SOUL.md 唔存在或者內容為空,Hermes 會用硬編碼嘅 DEFAULT_AGENT_IDENTITY。首次運行時,_ensure_default_soul_md() 會自動播種默認內容到 ~/.hermes/SOUL.md,但唔會覆蓋你之後嘅修改。
def load_soul_md() -> Optional[str]:
ensure_hermes_home()
soul_path = get_hermes_home() / "SOUL.md"
if not soul_path.exists():
return None
content = soul_path.read_text(encoding="utf-8").strip()
if not content:
return None
content = _scan_context_content(content, "SOUL.md")
content = _truncate_content(content, "SOUL.md")
return content
原樣注入:system_prompt.py 第 94 行直接 append _soul_content,冇任何前綴後綴或解釋性文字
測試 test_soul_md_has_no_wrapper_text 專門斷言包裝文本唔會出現
/personality 命令:14 個人格預設 + 自定義
SOUL.md 係持久嘅人格基線,但有時你想臨時轉風格,例如 code review 時用嚴厲語氣,討論創意時用活潑語氣。呢個時候就可以用 /personality 命令。Hermes 內置咗 14 個人格預設,分實用型同趣味型兩大類。
- 1 實用型:helpful、concise、technical、creative、teacher
- 2 趣味型:kawaii、catgirl、pirate、shakespeare、surfer、noir、uwu
- 3 特殊型:philosopher、hype
/personality 嘅設計係 overlay(疊加層),唔係替換
Overlay 喺 context 層注入,位於 SOUL.md 之後。SOUL.md 定義你個 Agent 係邊個,/personality 定義佢今次對話用咩語氣。兩者共存。清除 personality 可以用 /personality none、/personality default 或 /personality neutral,都會恢復基線身份。
清除 personality 嘅方式係重置 system_prompt 配置項並觸發 Agent 重建
除咗內置預設,仲可以喺 config.yaml 自定義人格,支援簡單 string 格式同更細粒度嘅 dict 格式。
SOUL.md vs AGENTS.md:咪放錯位
如果呢個特性應該跟你走,就放 SOUL.md;如果屬於一個 project,就放 AGENTS.md
SOUL.md 管身份、語氣、溝通風格,作用域係所有項目、所有會話,位置喺 $HERMES_HOME/SOUL.md,加載層係 stable(Slot #1)。AGENTS.md 管項目架構、編碼規範、工具偏好,作用域僅當前項目,位置喺 $CWD/AGENTS.md,加載層係 context 層。
常見錯誤:將項目級指令放 SOUL.md,例如「全部用英文回覆」會令個人項目都強制英文
Hermes 主動兼容 CLAUDE.md 同 .cursorrules,遷移時 project 配置無縫銜接
最佳實踐:迭代優化你的 SOUL.md
SOUL.md 唔係寫一次就完事嘅。官方建議嘅特徵係「跨上下文穩定、足夠廣泛適用於多種對話、足夠具體能實質性塑造風格」。實際操作可以分幾步行:先用默認身份跑幾日,感受 Agent 嘅回覆風格;然後記錄唔滿意嘅地方(太囉嗦?太討好?);再喺 SOUL.md 有針對性地加規則,之後再試效果,重複呢個循環。
一條好嘅 SOUL.md 規則應該唔依賴特定項目或話題,而係描述一種溝通偏好
- 唔好寫項目指令:用咩框架、跑咩 port、目錄結構——呢啲放 AGENTS.md
- 唔好寫臨時風格:今日想佢活潑啲?用 /personality,唔好改 SOUL.md
- 唔好寫敏感資訊:雖然有安全掃描,但唔好喺入面放 API Key 或密碼
與 /personality 配合使用:SOUL.md 定義基線,/personality 做臨時切換
例如 SOUL.md 定義核心風格偏好(直接、唔廢話、技術導向),日常對話用默認身份,code review 時用 /personality technical,腦力激盪時用 /personality creative。每次切完用 /personality none 自動返回基線。
🚩 2026 年「術哥無界」系列實戰文檔 X 篇原創計劃 第 129 篇,Hermes Agent 最佳實戰「2026」系列第 8 篇
大家好,歡迎來到 術哥無界 | ShugeX | 運維有術。
我是術哥,一名專注於 AI 編程、AI 智能體、Agent Skills、MCP、雲原生、AIOps、Milvus 向量數據庫的技術實踐者與開源佈道者!
Talk is cheap, let's explore。無界探索,有術而行。

圖 1:Hermes Agent SOUL.md 人格系統核心要點
說明:本文內容基於 Hermes Agent 源碼(NousResearch/hermes-agent)和官方文檔分析整理而成,源碼分析基於筆者本地倉庫版本。文中的配置模板和參數建議僅供參考,實際效果請以你的業務數據和環境測試結果為準。如果有實際使用經驗,歡迎在評論區分享交流。
你有沒有遇到過這樣的情況:同一個 AI Agent,在項目 A 裏回覆得專業剋制,到了項目 B 卻突然變得絮絮叨叨,風格飄忽不定?
這不是模型的問題,是人格定義的方式有問題。
大部分 Agent 框架把身份、風格、項目規範全塞在一個 system prompt 裏,改個項目配置不小心就把 Agent 的說話方式也改了。Hermes Agent 用一套三層架構解決了這個矛盾:SOUL.md 管身份,AGENTS.md 管項目,/personality 管臨時風格切換。三個東西各司其職,互不干擾。
Hermes Agent 是 Nous Research 開發的開源 AI Agent(GitHub Star 已突破 60,000),支持 200+ 大模型和 15+ 消息平台。它把"Agent 是誰"這個問題單獨拎出來,給了專門的文件、專門的加載邏輯、專門的安全機制。
我翻了 Hermes 的源碼和官方文檔,發現這個設計比看起來要精細得多。下面從源碼層面把它拆開。
1. 三層提示詞:為什麼不是一層?
Hermes 的系統提示詞不是一坨拼在一起的大字符串,而是分成了三層:stable(穩定層)、context(上下文層)、volatile(易變層)。
這三層不是隨便分的。目的就一個:前綴緩存友好。
源碼位置:agent/system_prompt.py 的 build_system_prompt_parts() 函數。
stable 層包含 SOUL.md 身份、工具行為引導、技能提示、環境提示這些在整個會話生命週期中基本不變的內容。context 層放用戶傳入的 system_message 和 AGENTS.md 等上下文文件,會話之間可能變化。volatile 層放記憶快照、USER.md 畫像、時間戳、會話 ID 這些每次都會變的東西。
關鍵設計:系統提示詞在每個會話中只構建一次並緩存到 agent._cached_system_prompt,只有在上下文壓縮事件後才重建。
為什麼要這麼幹?因為大模型的 API 調用中,系統提示詞是前綴的一部分。如果前綴不變,就可以利用 API 提供商的前綴緩存機制(比如 Anthropic 的 prompt caching),省掉重複的 token 計費。把不變的東西放在 stable 層前面,變的東西放在 volatile 層後面,就是在為緩存命中創造條件。
這個設計在測試裏也有覆蓋。test_system_prompt.py 確認了三層按序拼接,stable 層的 SOUL.md 永遠在第一個位置。

圖 2:Hermes Agent 三層提示詞架構(stable / context / volatile)
stable 層裏面到底有什麼?
源碼位置:agent/system_prompt.py 的 build_system_prompt_parts()
stable 層不是隻有 SOUL.md。它由 14 個部分按序拼接而成,SOUL.md 只是第一個:
SOUL.md 內容(或 DEFAULT_AGENT_IDENTITY回退)HERMES_AGENT_HELP_GUIDANCE— 引導用戶瞭解 Hermes 自身配置TASK_COMPLETION_GUIDANCE— 通用任務完成/反虛構引導工具感知行為引導(按條件注入):記憶、搜索、技能、Kanban COMPUTER_USE_GUIDANCE— 計算機使用引導(macOS)Nous 訂閲提示 TOOL_USE_ENFORCEMENT_GUIDANCE— 工具使用強制引導模型特定操作引導(Google/OpenAI 模型) 技能系統提示 模型身份覆蓋(Alibaba 等特殊提供商) 環境提示(WSL、Termux 等) Python 工具鏈探針 活躍配置文件提示 平台特定格式提示
SOUL.md 被放在 stable 層第一個位置是有原因的。stable 層裏後面的內容(工具引導、環境提示等)都以 SOUL.md 定義的身份為前提。SOUL.md 放後面的話,這些引導就會以默認身份運行,和 SOUL.md 定義的風格衝突。
這也是 SOUL.md 只從 HERMES_HOME 加載的原因:stable 層在會話開始時一次性組裝,之後不變。SOUL.md 位置不確定,stable 層就不穩定,前綴緩存就廢了。
2. SOUL.md 加載流程:從文件到提示詞
SOUL.md 的加載鏈路不長,但每一步都有講究。
源碼位置:agent/prompt_builder.py 的 load_soul_md() 函數。
def load_soul_md() -> Optional[str]:
# 1. 確保 HERMES_HOME 目錄存在
ensure_hermes_home()
# 2. 只從 HERMES_HOME 加載,不搜索當前工作目錄
soul_path = get_hermes_home() / "SOUL.md"
# 3. 文件不存在 → 返回 None
ifnot soul_path.exists():
returnNone
# 4. 讀取並去除首尾空白
content = soul_path.read_text(encoding="utf-8").strip()
# 5. 空文件也返回 None
ifnot content:
returnNone
# 6. 安全掃描
content = _scan_context_content(content, "SOUL.md")
# 7. 截斷
content = _truncate_content(content, "SOUL.md")
return content
這段代碼有幾個值得注意的點。
只認 HERMES_HOME,不認 cwd
load_soul_md() 裏 soul_path = get_hermes_home() / "SOUL.md" 這一行寫死了路徑。不管你在哪個目錄啓動 Hermes,它只看 ~/.hermes/SOUL.md。
官方文檔對這個設計有明確解釋:
If Hermes loaded SOUL.md from whatever directory you happened to launch it in, your personality could change unexpectedly between projects.
測試文件 test_prompt_builder.py 裏的 test_loads_soul_md_from_hermes_home_only() 也驗證了這一點:在 HERMES_HOME 和當前工作目錄各放一個 SOUL.md,結果只有 HERMES_HOME 的那個被加載。
這和 AGENTS.md 的行為完全相反。AGENTS.md 是從工作目錄向上遍歷到 git root 去發現的,因為它管的是項目級的東西。SOUL.md 管的是人,人走到哪身份都一樣,所以只認一個地方。
回退到默認身份
如果 load_soul_md() 返回 None(文件不存在、內容為空、或被安全掃描攔截),Hermes 會使用硬編碼的 DEFAULT_AGENT_IDENTITY:
DEFAULT_AGENT_IDENTITY = (
"You are Hermes Agent, an intelligent AI assistant "
"created by Nous Research. You are helpful, "
"knowledgeable, and direct."
)
這段文本(prompt_builder.py 第 121-129 行)同時也是首次運行時自動播種到 ~/.hermes/SOUL.md 的默認內容。_ensure_default_soul_md() 函數在 ensure_hermes_home() 中被調用,只在 SOUL.md 不存在時創建,已有文件永遠不會被覆蓋。
這個自動播種機制的設計很剋制:它不會在你每次啓動時檢查內容是否是默認的,也不會覆蓋你的修改。它做的事情就是——文件不存在就創建,存在就不管。這意味着你拿到的是一個乾淨的起點,而不是一個需要先刪掉才能開始定製的模板。
原樣注入,不加包裝
源碼 system_prompt.py 第 94 行:stable_parts.append(_soul_content)。
就是直接 append,不加任何前綴、後綴或解釋性文字。沒有 "If SOUL.md is present" 這種提示,也沒有 "## SOUL.md" 這種標題包裝。
測試 test_soul_md_has_no_wrapper_text() 專門斷言了這些包裝文本不會出現在結果中。為什麼?因為 SOUL.md 的內容本身就是給模型看的身份描述,加一層包裝反而會干擾模型的注意力分配。
3. 安全掃描:防注入的第一道門
SOUL.md 是用戶自己寫的文件,但它會被原樣注入到系統提示詞裏。如果有人在 SOUL.md 裏寫了提示注入指令(比如"忽略之前的所有指令"),Agent 就會被劫持。
Hermes 用 _scan_context_content() 函數來應對這個問題。
源碼位置:prompt_builder.py
def _scan_context_content(content: str, filename: str) -> str:
findings = _scan_for_threats(content, scope="context")
if findings:
return f"[BLOCKED: {filename} contained potential prompt injection]"
return content
掃描使用 "context" scope 的威脅模式庫,覆蓋了經典注入模式、promptware/C2 模式、角色扮演劫持等。但不使用 "strict" scope(SSH 後門、持久化、數據泄露 URL 檢測),因為對倉庫中的上下文文件來說太激進了,容易誤報。
一旦檢測到威脅,加載會被完全阻止,返回一個 [BLOCKED: ...] 佔位符。不是警告,不是刪掉可疑部分繼續用,是直接攔住。因為內容會原樣進入系統提示詞,沒有第二次處理的機會。
這個安全掃描不只針對 SOUL.md,所有上下文文件(AGENTS.md、CLAUDE.md、.cursorrules)都會經過同一套掃描流程。不過 scope 不同:SOUL.md 使用 "context" scope,檢測注入和劫持模式;對倉庫裏的文件也是同樣的 scope。"strict" scope(檢測 SSH 後門、持久化、數據泄露 URL 等)只在更嚴格的場景下使用,因為對用戶自己寫的上下文文件來說,這些檢測太容易誤報了。
截斷機制
如果 SOUL.md 寫得太長,Hermes 會通過 _truncate_content() 進行截斷。截斷的方式是保留頭部和尾部,中間插入截斷標記。這種兩頭保留的策略意味着你在 SOUL.md 開頭定義的身份描述和結尾的風格約束都會被保留,被砍的是中間可能不那麼關鍵的內容。
不過說實話,SOUL.md 本來就不應該寫太長。官方文檔建議的內容特徵是"跨上下文穩定、足夠廣泛適用於多種對話、足夠具體能實質性塑造風格"——滿足這三個條件的文本通常不會太長。如果你發現自己寫了很長,很可能已經越界到項目級指令的範疇了。
4. /personality 命令:14 個人格預設 + 自定義
SOUL.md 是持久的人格基線。但有時候你想臨時換個風格——比如代碼審查時用嚴厲的語氣,討論創意時換成活潑的語氣。這時候就用 /personality 命令。
內置的 14 個人格
源碼位置:cli.py 第 406-421 行。
Hermes 內置了 14 個預設,從實用的到整活的都有:
用 /personality pirate 就能讓 Agent 開始用海盜風格回覆你。說實話,測試的時候切到 shakespeare 模式跑了一段代碼審查,輸出確實挺有戲劇效果的——不過實際幹活還是 technical 更靠譜。
自定義人格
除了內置預設,還支持在 config.yaml 中自定義。兩種格式都行:
agent:
personalities:
# 簡單 string 格式
codereviewer:>
You are a meticulous code reviewer...
# dict 格式,更細粒度
coder:
description:"Expert programmer"
system_prompt:"You are an expert programmer."
tone:"technical"
style:"concise"
overlay 機制,不是替換
/personality 的設計是疊加層(overlay),不是替換。它在系統提示詞的 context 層注入,位於 SOUL.md 之後。SOUL.md 定義的是你的 Agent 是誰,/personality 定義的是它這次對話用什麼語氣。兩者共存。
從源碼看,_handle_personality_command()(cli.py)的執行流程是這樣的:
/personality <name>從self.personalities字典中查找對應的人格找到後,將 personality 文本寫入 self.system_prompt(即agent.system_prompt配置項)設置 self.agent = None,強制 Agent 在下次對話時重新初始化將選擇持久化到 config.yaml的agent.system_prompt字段
關鍵點在第 3 步。設置 self.agent = None 不是重啓整個 Agent,而是讓它在下次需要時重新初始化。重新初始化時會重新組裝系統提示詞,此時新的 personality 就會被注入到 context 層。
清除 personality 也簡單:/personality none、/personality default、/personality neutral 都能清除 overlay,恢復 SOUL.md 的基準身份。清除的方式是重置 system_prompt 配置項並再次觸發 Agent 重建。

圖 3:/personality 命令 overlay 效果對比——疊加而非替換
在 Gateway 模式下(tui_gateway/server.py),_apply_personality_to_session() 會在會話歷史中插入一條系統消息,格式是 [System: The user has changed the assistant's personality. ...]。注意它保留歷史記錄,不重置會話。這意味着在 Gateway 模式下切換 personality 是非破壞性的——之前的對話不會丟失。
5. SOUL.md vs AGENTS.md:別把活放錯了地方
Hermes 對這兩個文件有非常明確的職責劃分。官方文檔的原話很直白:
If it should follow you everywhere, it belongs in SOUL.md. If it belongs to a project, it belongs in AGENTS.md.
一句話的判斷準則:這個東西是不是應該跟着你走?
$HERMES_HOME/SOUL.md | $CWD/AGENTS.md | |
SOUL.md 寫什麼:"Be direct." "Avoid hype language." "Push back when the user is wrong."
AGENTS.md 寫什麼:"Use pytest, not unittest." "Frontend lives in frontend/.The API runs on port 8000.
一個常見的錯誤是把項目級指令放進 SOUL.md。比如你寫了一句 "All responses should be in English because our team is international",這句話放 SOUL.md 會導致你在個人項目裏也被強制要求英文回覆。正確的做法是放進項目根目錄的 AGENTS.md。
另一個常見錯誤是反過來:把風格偏好寫進 AGENTS.md。比如 "Always respond in a friendly and encouraging tone"——這句話應該放在 SOUL.md,因為它是人格層面的偏好,不管你在哪個項目裏都適用。
一個簡單的判斷方法:關閉所有項目,只開一個空白對話,你還希望 Agent 保持這個行為嗎? 如果是,放 SOUL.md。如果不是,放 AGENTS.md。
話說回來,這種分離在目前 Agent 框架中並不常見。Claude Code 的 CLAUDE.md 和 Cursor 的 .cursorrules 都是項目級文件,身份和項目指令混在一起。Hermes 多了一層全局身份管理,代價是多維護一個文件,收益是身份的穩定性和可預測性。
有意思的是,Hermes 還主動兼容了 CLAUDE.md 和 .cursorrules。如果項目根目錄有這些文件且沒有更高優先級的上下文文件,Hermes 會自動加載它們。這意味着從 Claude Code 或 Cursor 遷移到 Hermes,項目配置基本無縫銜接,SOUL.md 只需要管好身份這一件事就夠了。
6. 特殊執行模式:誰繼承 SOUL.md,誰不繼承
SOUL.md 在不同執行模式下的行為不一樣,這個在設計上是有意的。
Cron 任務:繼承
源碼位置:cron/scheduler.py 第 1654-1659 行。
# Cron jobs should always inherit the user's SOUL.md identity
load_soul_identity=True,
即使 Cron 任務跳過了其他上下文文件,SOUL.md 身份還是會被加載。設計意圖很明確:定時任務也是你派出去的,帶着你的身份去幹活。
子代理/委託模式:不繼承
源碼位置:cli.py 第 3161 行。
# AGENTS.md/SOUL.md/.cursorrules and persistent memory are not loaded.
子代理用的是 DEFAULT_AGENT_IDENTITY,不加載 SOUL.md。這也是合理的——子代理是主 Agent 的工具,不需要也不應該有人格偏好。想象一下,如果你讓主 Agent 去搜索文件,搜索子 Agent 突然用 shakespeare 風格返回結果,那對話就亂了。
另外還有個環境變量 HERMES_IGNORE_RULES,設置為 1 時會跳過所有上下文文件(AGENTS.md、SOUL.md、.cursorrules)和持久記憶的加載。這個主要用於調試和隔離測試場景。
多 Profile 系統
Hermes 支持 Profile(配置文件)系統,每個 Profile 位於 ~/.hermes/profiles/<name>/,擁有獨立的 SOUL.md、config.yaml、skills、cron、memories。源碼 hermes_cli/main.py 第 10835 行的輸出信息也確認了這一點:Edit {profile_dir_display}/SOUL.md for different personality。

圖 4:Hermes Agent 多 Profile 目錄結構——每個 Profile 擁有獨立的 SOUL.md
這意味着你可以給工作、學習、個人項目各建一個 Profile,每個有不同的人格。切換 Profile 就切換了整個身份體系。
容器寫入保護
tests/agent/test_file_safety_container_mirror.py 中有一個有意思的測試:classify_container_mirror_target() 會檢測對 profiles/*/SOUL.md 的寫入嘗試。
簡單說,Hermes 的文件安全機制會阻止 Agent 通過容器路徑篡改自己的 SOUL.md。這是防止 Agent 自我修改身份的保護措施——你不能讓一個 AI 自己把自己的約束給刪了。
7. 最佳實踐
從源碼和官方文檔裏提煉幾條實際可操作的建議。
SOUL.md 寫什麼
參考官方給出的示例模板:
# Personality
You are a pragmatic senior engineer with strong taste.
You optimize for truth, clarity, and usefulness over politeness theater.
## Style
- Be direct without being cold
- Prefer substance over filler
- Push back when something is a bad idea
- Admit uncertainty plainly
## What to avoid
- Sycophancy
- Hype language
- Repeating the user's framing if it's wrong
## Technical posture
- Prefer simple systems over clever systems
- Care about operational reality
- Treat edge cases as part of the design
不寫什麼
不寫項目指令:用什麼框架、跑在哪個端口、目錄結構怎麼組織,這些放 AGENTS.md 不寫臨時風格:今天想讓它活潑點?用 /personality,別改 SOUL.md不寫敏感信息:雖然 SOUL.md 經過安全掃描,但別在裏面放 API Key 或密碼
與 /personality 配合使用
SOUL.md 定義基線,/personality 做臨時切換。一個合理的用法是:
SOUL.md 定義你的核心風格偏好(直接、不廢話、技術導向) 日常對話用默認身份(走 SOUL.md) 代碼審查時切 /personality technical獲得更嚴謹的分析頭腦風暴時切 /personality creative激發更多想法每次切完不用手動恢復, /personality none自動回到基線
迭代優化方法
SOUL.md 不是寫一次就完事的東西。官方文檔建議的特徵是:跨上下文穩定、足夠廣泛適用於多種對話、足夠具體能實質性塑造風格。
實際操作中,可以這樣做:
先用默認身份跑幾天,感受 Agent 的回覆風格 把讓你不滿意的地方記錄下來(太囉嗦?太討好?不夠直接?) 在 SOUL.md 中針對性地加一條規則 再跑幾天,看效果是否改善 重複這個循環
一條好的 SOUL.md 規則是這樣的:它不依賴於特定項目或特定話題,而是描述一種溝通偏好。比如 "Push back when something is a bad idea" 這條規則,不管你讓 Agent 寫代碼還是寫文章,它都會適用。
和其他框架的對比
如果你之前用過 Claude Code 或 Cursor,可以參考這個對應關係來理解 SOUL.md 的定位:
/personality pirate | |
從 Claude Code 遷移的用戶可以直接把 CLAUDE.md 留在項目根目錄,Hermes 會自動識別。你只需要額外創建一個 SOUL.md 來定義人格——那些原來和身份混在一起的 CLAUDE.md 內容不需要刪。從 OpenClaw 遷移更簡單,hermes claw migrate 一條命令就能把配置和數據搬過來,SOUL.md 也會被自動導入。
總結
回頭看 Hermes 的 SOUL.md,幾個設計選擇挺有意思:身份和項目嚴格分離、原樣注入不加包裝、三層分離給前綴緩存騰空間、overlay 疊加而非替換。
從源碼看,每個決策都有實際理由——位置鎖定為了可預測性,原樣注入為了不干擾模型注意力,三層分離為了緩存命中,overlay 為了靈活性。安全掃描、容器寫入保護、子代理跳過這些邊界處理也都沒落下。
如果你的場景需要給 Agent 一個穩定的、跨項目的身份,Hermes 的 SOUL.md 方案值得看看。
你在項目中用過 Agent 人格定製嗎?SOUL.md 的這種"身份與項目分離"的設計,和你在用的工具有什麼不同?歡迎在評論區聊聊。
好啦,謝謝你觀看我的文章,如果喜歡可以點贊轉發給需要的朋友,我們下一期再見!敬請期待!