H繁中版
文件user-guidecode execution
<!-- Source: https://hermesbible.com/docs/user-guide/features/code-execution -->

Section: Core Features · URL: https://hermesbible.com/docs/user-guide/features/code-execution

程式碼執行(Programmatic Tool Calling)

execute_code 工具讓 agent 撰寫 Python 腳本,以程式化方式呼叫 Hermes 工具,將多步驟工作流程壓縮為單一 LLM 回合。腳本在 agent 主機上的子程序中運行,透過 Unix domain socket RPC 與 Hermes 通訊。

運作原理

  1. Agent 使用 from hermes_tools import ... 撰寫 Python 腳本
  2. Hermes 生成包含 RPC 函數的 hermes_tools.py 模組存根
  3. 開啟 Unix domain socket 並啟動 RPC 監聽執行緒
  4. 腳本在子程序中運行——工具呼叫透過 socket 回傳至 Hermes
  5. 只有腳本的 print() 輸出會回傳給 LLM;中間的工具結果不會進入 context window
# Agent 可以撰寫這樣的腳本:
from hermes_tools import web_search, web_extract

results = web_search("Python 3.13 features", limit=5)
for r in results["data"]["web"]:
    content = web_extract([r["url"]])
    # ... 篩選與處理 ...
print(summary)

腳本中可用的工具: web_searchweb_extractread_filewrite_filesearch_filespatchterminal(僅前台模式)。

使用時機

Agent 會在以下情況使用 execute_code

  • 需要 3 次以上工具呼叫且呼叫之間有處理邏輯
  • 需要大量資料篩選或條件分支
  • 需要迴圈遍歷結果

關鍵優勢:中間的工具結果不會進入 context window——只有最終的 print() 輸出會回傳,大幅降低 token 使用量。

實際範例

資料處理管線

from hermes_tools import search_files, read_file
import json

# 找出所有設定檔並擷取資料庫設定
matches = search_files("database", path=".", file_glob="*.yaml", limit=20)
configs = []
for match in matches.get("matches", []):
    content = read_file(match["path"])
    configs.append({"file": match["path"], "preview": content["content"][:200]})

print(json.dumps(configs, indent=2))

多步驟網路研究

from hermes_tools import web_search, web_extract
import json

# 在一個回合中搜尋、擷取並摘要
results = web_search("Rust async runtime comparison 2025", limit=5)
summaries = []
for r in results["data"]["web"]:
    page = web_extract([r["url"]])
    for p in page.get("results", []):
        if p.get("content"):
            summaries.append({
                "title": r["title"],
                "url": r["url"],
                "excerpt": p["content"][:500]
            })

print(json.dumps(summaries, indent=2))

大量檔案重構

from hermes_tools import search_files, read_file, patch

# 找出所有使用已棄用 API 的 Python 檔案並修復它們
matches = search_files("old_api_call", path="src/", file_glob="*.py")
fixed = 0
for match in matches.get("matches", []):
    result = patch(
        path=match["path"],
        old_string="old_api_call(",
        new_string="new_api_call(",
        replace_all=True
    )
    if "error" not in str(result):
        fixed += 1

print(f"Fixed {fixed} files out of {len(matches.get('matches', []))} matches")

建構與測試管線

from hermes_tools import terminal, read_file
import json

# 執行測試、解析結果並報告
result = terminal("cd /project && python -m pytest --tb=short -q 2>&1", timeout=120)
output = result.get("output", "")

# 解析測試輸出
passed = output.count(" passed")
failed = output.count(" failed")
errors = output.count(" error")

report = {
    "passed": passed,
    "failed": failed,
    "errors": errors,
    "exit_code": result.get("exit_code", -1),
    "summary": output[-500:] if len(output) > 500 else output
}

print(json.dumps(report, indent=2))

執行模式

execute_code 有兩種執行模式,透過 ~/.hermes/config.yaml 中的 code_execution.mode 控制:

模式工作目錄Python 解釋器
project(預設)Session 的工作目錄(與 terminal() 相同)使用啟用中的 VIRTUAL_ENV / CONDA_PREFIX python,若無法使用則退回 Hermes 自身的 python
strict與使用者專案隔離的暫存目錄sys.executable(Hermes 自身的 python)

何時保持 project 當你希望 import pandasfrom my_project import foo 或相對路徑如 open(".env") 的運作方式與 terminal() 中相同。這幾乎總是符合需求的選擇。

何時切換至 strict 當你需要最大程度的可重現性——每次 session 都使用相同的解釋器,不論使用者啟用了哪個 venv,且腳本與專案目錄樹隔離(不會因相對路徑而意外讀取專案檔案)。

# ~/.hermes/config.yaml
code_execution:
  mode: project   # 或 "strict"

project 模式的退回行為:若 VIRTUAL_ENV / CONDA_PREFIX 未設定、損壞或指向低於 3.8 的 Python 版本,解析器會平順地退回至 sys.executable——永遠不會讓 agent 沒有可用的解釋器。

兩種模式的安全關鍵不變量完全相同:

  • 環境變數清理(移除 API key、token、憑證)
  • 工具白名單(腳本不能遞迴呼叫 execute_codedelegate_task 或 MCP 工具)
  • 資源限制(逾時、stdout 上限、工具呼叫上限)

切換模式只會改變腳本的運行位置和使用的解釋器,不會改變它們能看到的憑證或能呼叫的工具。

資源限制

資源限制說明
逾時5 分鐘(300 秒)腳本先收到 SIGTERM,5 秒緩衝後收到 SIGKILL
Stdout50 KB輸出被截斷並附上 [output truncated at 50KB] 提示
Stderr10 KB非零退出碼時包含在輸出中,方便除錯
工具呼叫每次執行最多 50 次達到上限時回傳錯誤

所有限制均可透過 config.yaml 設定:

# In ~/.hermes/config.yaml
code_execution:
  mode: project      # project(預設)| strict
  timeout: 300       # 每個腳本最大秒數(預設:300)
  max_tool_calls: 50 # 每次執行最大工具呼叫次數(預設:50)

腳本內工具呼叫的運作方式

當你的腳本呼叫如 web_search("query") 的函數時:

  1. 呼叫被序列化為 JSON,透過 Unix domain socket 傳送至父程序
  2. 父程序透過標準的 handle_function_call 處理器進行分派
  3. 結果透過 socket 傳回
  4. 函數回傳解析後的結果

這表示腳本內的工具呼叫與正常工具呼叫的行為完全相同——相同的速率限制、相同的錯誤處理、相同的能力。唯一的限制是 terminal() 只支援前台模式(不支援 backgroundpty 參數)。

錯誤處理

當腳本失敗時,agent 會收到結構化的錯誤資訊:

  • 非零退出碼:stderr 包含在輸出中,讓 agent 看到完整的堆疊追蹤
  • 逾時:腳本被終止,agent 看到 "Script timed out after 300s and was killed."
  • 中斷:若使用者在執行期間發送新訊息,腳本會被終止,agent 看到 [execution interrupted — user sent a new message]
  • 工具呼叫上限:達到 50 次呼叫上限時,後續的工具呼叫會回傳錯誤訊息

回應一律包含 status(success/error/timeout/interrupted)、outputtool_calls_madeduration_seconds

安全性

警告——安全模型

子程序在最小化環境中運行。API key、token 和憑證預設會被移除。腳本透過 RPC 通道存取工具——除非明確允許,否則無法從環境變數中讀取機密。

名稱中包含 KEYTOKENSECRETPASSWORDCREDENTIALPASSWDAUTH 的環境變數會被排除。只有安全的系統變數(PATHHOMELANGSHELLPYTHONPATHVIRTUAL_ENV 等)會被傳入。

Skill 環境變數透傳

當 skill 在 frontmatter 中宣告 required_environment_variables 時,那些變數會在 skill 載入後自動透傳execute_codeterminal 子程序。這讓 skill 能使用其宣告的 API key,而無需削弱任意程式碼的安全性。

對於非 skill 的使用情境,你可以在 config.yaml 中明確允許清單變數:

terminal:
  env_passthrough:
    - MY_CUSTOM_KEY
    - ANOTHER_TOKEN

詳見安全性指南

子程序中的 HERMES_* 變數

子程序只會接收一小組固定的運作用 HERMES_* 變數(依名稱精確匹配):

  • HERMES_HOME
  • HERMES_PROFILE
  • HERMES_CONFIG
  • HERMES_ENV

(以及 HERMES_RPC_DIR / HERMES_RPC_SOCKET / TZ / HOME,由 Hermes 明確注入以確保 RPC 通道正常運作。)

注意——行為變更

早期版本會將所有名稱以 HERMES_ 開頭的變數傳入子程序。該寬泛的前綴已因安全性強化而移除:它可能洩漏不符合機密子字串的 HERMES_* 命名設定(例如 HERMES_BASE_URLHERMES_KANBAN_DBHERMES_*_WEBHOOK 端點)至任意沙箱化程式碼中。

如果 execute_code 腳本——或其在匯入時載入的 repo/plug-in 模組——依賴上述四個運作名稱之外的 HERMES_* 變數,現在會發現該變數在子程序中未設定。這是刻意的移除,不是 Bug。

解決方法——將變數重新加入允許清單。 兩種途徑都會將變數透傳至 execute_code terminal 子程序,且都不會削弱機密移除保證(Hermes 管理的 provider 憑證永遠無法透過此方式重新允許):

  1. 每台機器,在 config.yaml——將確切的變數名稱加入透傳允許清單:

    terminal:
      env_passthrough:
        - HERMES_KANBAN_DB
        - HERMES_BASE_URL
    
  2. 每個 skill,在 skill 的 frontmatter 中——宣告它,以便在該 skill 載入時自動註冊:

    required_environment_variables:
      - HERMES_KANBAN_DB
    

診斷方式。 當子程序移除一個或多個未加入允許清單的 HERMES_* 變數時,Hermes 會發出一行 debug 日誌,列出變數名稱並指向 env_passthrough 逃脫機制。以偵錯日誌運行(hermes logs --level DEBUG,或檢查 ~/.hermes/logs/agent.log),搜尋 execute_code: dropped N non-allowlisted HERMES_* var(s) 即可判斷腳本是否因 HERMES_* 變數缺失而異常。

Hermes 會將腳本和自動生成的 hermes_tools.py RPC 存根寫入暫存目錄,執行完畢後清理。在 strict 模式下,腳本也在該目錄中執行;在 project 模式下,腳本在 session 的工作目錄中執行(暫存目錄會保留在 PYTHONPATH 上,因此 import 仍可正常解析)。子程序在自己的程序群組中運行,以便在逾時或中斷時能被乾淨地終止。

execute_code 與 terminal 的比較

使用情境execute_codeterminal
需要多步驟工作流程且工具呼叫之間有處理邏輯
簡單的 shell 指令
篩選或處理大量工具輸出
執行建構或測試套件
迴圈遍歷搜尋結果
互動式/背景程序
需要環境變數中的 API key⚠️ 僅透過透傳✅(大多數會透傳)

經驗法則: 當你需要以程式化方式呼叫 Hermes 工具且呼叫之間有處理邏輯時,使用 execute_code。執行 shell 指令、建構和程序時,使用 terminal

平台支援

程式碼執行需要 Unix domain socket,僅支援 Linux 和 macOS。在 Windows 上會自動停用——agent 會退回至一般的順序工具呼叫。



Event Hooks