🚀💻🚀
让 AI 写 Python:Code Execution 完全玩梗指南
—— 从手动点点点到一键脚本化,AI 终于学会了自己干活
📄 基于官方文档整理 | 玩梗版 | 原汁原味不缩水
一、啥是 Code Execution?
简单说,execute_code 这个工具就是让 AI 代理自己写 Python 脚本,然后脚本里调用 Hermes 的各种工具(搜索、读文件、改代码……),把原本需要多次来回的繁琐流程,压缩到一次 LLM 对话里搞定。脚本在宿主机器上作为一个子进程运行,通过 Unix domain socket 和 Hermes 通信。
以前你让 AI 干活的流程是:你发指令 → AI 调用一个工具 → 返回结果 → AI 再调另一个工具 → 再返回……来回好几轮,context window 都快被塞爆了。现在好了,AI 自己写个脚本,一次搞定,中间结果全部不进 context,只把最后的 print() 输出发回来。省 token 省到哭。
💡这就好比以前你要去超市买十样东西,得跑十趟;现在直接列个清单一次性买完。
二、它到底咋工作的?(五步上链式讲解)
整个流程可以拆成五步,每一步都像是 AI 在给自己搭积木:
✅第一步:AI 写 Python 脚本,通过 from hermes_tools import ... 导入工具 ✅ 第二步:Hermes 自动生成一个 hermes_tools.py 存根模块,里面全是 RPC 函数 ✅ 第三步:Hermes 打开 Unix domain socket,启动 RPC 监听线程 ✅ 第四步:脚本在子进程里跑起来——工具调用通过 socket 发回给 Hermes ✅ 第五步:只有脚本的 print() 输出返回给 LLM,中间结果绝不污染 context window
来段示例脚本看看:
# AI 可以写这样的脚本: 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_search, web_extract, read_file, write_file, search_files, patch, terminal(仅前台模式)
三、啥时候该用这个工具?
AI 代理不是啥活儿都往上凑的,它有自己的判断标准。当遇到以下情况时,execute_code 就会闪亮登场:
✅3+ 次工具调用,且每次调用之间需要处理逻辑 ✅ 大批量数据过滤或条件分支 ✅ 循环遍历结果
核心优势:中间工具结果从不进入 context window——只有最后的 print() 结果回来,token 使用量直接断崖式下降。
四、实战演练:四个场景教你做人
4.1 场景一:数据处理流水线 🛠️
想象一下,你要从一堆 YAML 配置文件里把数据库配置全拎出来。传统做法:搜 → 读 → 解析 → 拼接,一轮接一轮。用 execute_code:
from hermes_tools import search_files, read_file import json # 找到所有包含 database 的 yaml 配置 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))
搜文件、读文件、循环处理、JSON 打包输出——一个脚本全干完。
4.2 场景二:多步网络研究 🔍
你要对比 Rust 的 async runtime,得先搜、再抓、最后总结。以前要好几轮对话,现在:
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))
搜索、抓取、循环过滤、截取摘要、JSON 输出——一气呵成。
4.3 场景三:批量重构代码 🔄
项目里有 N 个 Python 文件用了废弃的 API,你不想一个个手动改,让 AI 帮你批量搞定:
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} 个文件,共 {len(matches.get('matches', []))} 个匹配")
搜索、循环、patch 替换、计数统计——批量操作就是这么不讲武德。
4.4 场景四:构建和测试流水线 🧪
跑完 pytest 测试后解析结果、统计通过率、生成报告,以前要分好几步。现在脚本里一次搞定:
from hermes_tools import terminal 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))
五、执行模式:project vs strict,你选谁?
execute_code 提供两种执行模式,由 ~/.hermes/config.yaml 中的 code_execution.mode 控制:
📌project(默认):工作目录和 terminal() 一样,可以用 pip install 装依赖,import 自己的模块。99% 的情况选这个。
📌strict:脚本运行在隔离的临时目录,用 Hermes 自带的 Python。适合需要最大可重复性的场景,完全隔离项目文件,不怕误读。
# ~/.hermes/config.yaml code_execution: mode: project# 或 "strict"
项目模式下,如果 VIRTUAL_ENV / CONDA_PREFIX 没设置或指向低于 3.8 的 Python,系统会自动回退到 Hermes 自己的 python。永远不用担心跑着跑着断了。
六、安全:你的密钥安全吗?
🚨子进程运行在一个精简环境中,API keys、tokens、credentials 默认全部被剥离。脚本只能通过 RPC 通道访问工具,没法从环境变量里读密钥。
名字里包含 KEY、TOKEN、SECRET、PASSWORD、CREDENTIAL、PASSWD、AUTH 的环境变量全被过滤掉,只有 PATH、HOME、LANG、SHELL、PYTHONPATH、VIRTUAL_ENV 等安全变量会透传。
Skill 环境变量透传
如果你的 skill 在 frontmatter 里声明了 required_environment_variables,这些变量会自动透传给 execute_code 和 terminal 子进程。这样 skill 用的 API key 不会被误删,同时又不会让整个系统的密钥暴露。
自定义白名单
非 skill 场景下,你可以在 config.yaml 里手动加白名单:
terminal: env_passthrough: - MY_CUSTOM_KEY - ANOTHER_TOKEN
Hermes 始终将脚本和自动生成的 hermes_tools.py 存根写到临时目录,执行完就清理。子进程有自己的进程组,超时时可以干净地杀掉。
七、execute_code vs terminal:到底该用哪个?
简单说,这是两个工具的不同赛道:
📌execute_code 适用:多步工具调用 + 中间处理逻辑 / 过滤大批量结果 / 循环遍历 / 条件分支
📌terminal 适用:简单 shell 命令 / 构建或测试套件 / 后台进程 / 交互式会话
规则很简单:需要调 Hermes 工具并且中间有逻辑处理的,用 execute_code;单纯跑个 shell 命令的,用 terminal。
八、资源限制:别把 AI 累死
✅超时:5 分钟(300s),超时后先 SIGTERM 再 SIGKILL ✅ Stdout 上限:50 KB,超出部分截断并标注 [output truncated] ✅ Stderr 上限:10 KB,非零退出时包含用于调试 ✅ 工具调用上限:每次执行 50 次,超限返回错误
所有限制都可以在 config.yaml 里配置修改。
九、脚本里的工具调用到底咋回事?
当脚本里调用 web_search("query") 时,实际发生的事:
✅调用被序列化发往父进程(通过 Unix domain socket) ✅ 父进程通过标准 handle_function_call 分发处理 ✅ 结果通过 socket 返回 ✅ 函数返回解析后的结果
这意味着脚本里的工具调用和正常工具调用行为一致——相同的速率限制、相同的错误处理、相同的能力。唯一的限制是 terminal() 仅支持前台模式,不支持 background 或 pty。
十、报错怎么办?别慌,有结构化错误信息
脚本挂了的时候,AI 代理会收到结构化的错误信息:
✅非零退出码:stderr 会包含进输出,AI 能看到完整的 traceback ✅ 超时:脚本被杀,AI 收到 "Script timed out after 300s and was killed." ✅ 中断:用户在新消息下发时,脚本被终止,AI 收到 [execution interrupted] ✅ 工具调用超限:50 次上限被打满时,后续调用返回错误
每次响应都包含 status(成功/错误/超时/中断)、output、tool_calls_made 和 duration_seconds。
十一、平台支持:Linux 和 macOS 专属
🚨Code Execution 依赖 Unix domain socket,只在 Linux 和 macOS 上可用。Windows 上自动禁用,AI 代理会退回到普通的顺序工具调用模式。
🚀💻🚀
搞定。拿去用吧!
夜雨聆风