Codex 校核(2026-10-09) Python 官方 exec 文档明确:限制 globals 或覆盖 builtins 并不是安全机制,执行代码仍可访问内建能力;原文“Python exec 限制命名空间更安全”不能理解为可运行不可信代码的沙箱。代码执行必须另外建立操作系统或虚拟机隔离与权限边界。 MCP 当前 2026-07-28 Tools 规范规定 tools/list 返回当前工具集,并可通过 subscriptions/listen 的 toolsListChanged 与 notifications/tools/list_changed 通知变化;“MCP 工具设计时定义、运行时不能变化”的对比不准确。动态造函数是本文方案的设计方向,不代表它比 MCP 的动态发现更通用或已具备安全隔离。对话持久化也不能单独证明运行时函数对象在重启后恢复。

An Agent in 100 Lines of Lisp — 深度消化

来源: HN: 126pts | 原文 | GitHub 作者: Jamie Beach 消化时间: 2026-07-12 16:00 UTC


核心发现

一个 AI agent loop 本质上只是一个 8 行递归函数。当模型被赋予 Lisp 的 eval 作为唯一的工具时,它能自己写出第二个工具(web search)、第三个工具(任意计算)——完全颠覆了”工具目录在设计时固定”的传统假设。

技术要点

1. Agent loop = 递归函数

(defun agent-loop (messages)
  (let* ((message (ref (call-model messages) "choices" 0 "message"))
         (tool-calls (gethash "tool_calls" message)))
    (if (and tool-calls (plusp (length tool-calls)))
        (agent-loop (append messages
                            (list message)
                            (map 'list #'execute tool-calls)))
        (append messages (list message)))))
  • 基本情况:模型回答 → 返回历史
  • 递归情况:模型要调用工具 → 执行工具 → 追加结果 → 递归
  • 无框架,无状态机,agent 的状态就是被递归折叠的消息列表

2. 唯一工具:eval

Lisp 是同像性(homoiconic)语言——代码就是数据,数据就是代码。模型写出 Lisp 表达式字符串,agent 直接 read 然后 eval。

* (agent:run "What is the 30th Fibonacci number? Compute it, don't recall it.")
  ⤷ (defun fibonacci (n) (if (<= n 2) 1 (+ (fibonacci (- n 1)) (fibonacci (- n 2))))) => FIBONACCI
  ⤷ (fibonacci 30) => 832040

模型没有”回忆”答案,它写了一个递归函数并运行了它。

3. 自我构建工具

作者给了 agent 一个 Brave Search API key。agent 用 eval 自己写了个 brave-search 函数:

(defun brave-search (api-key query &key (count 10))
  "Search using Brave Search API"
  (let* ((encoded-query (quri:url-encode query))
         (url (format nil "https://api.search.brave.com/res/v1/web/search?q=~a&count=~d" encoded-query count))
         (response (dexador:get url :headers `(("Accept" . "application/json")
                                               ("X-Subscription-Token" . ,api-key)))))
    (shasht:read-json response)))

从未构建 web search 工具。Agent 只有一个工具(eval),用这个工具写出了第二个工具。

4. 记忆 = 20 行文件 I/O

(defun remember (messages)
  (with-open-file (out *memory-file* :direction :output :if-exists :supersede)
    (shasht:write-json (coerce messages 'vector) out))
  messages)
 
(defun recall ()
  (if (probe-file *memory-file*)
      (coerce (with-open-file (in *memory-file*) (shasht:read-json in)) 'list)
      (list *system-message*)))

无 schema,无迁移,无向量数据库。序列化格式 = 运行时格式。

5. 技能即记忆

通过 eval 定义的函数在进程退出时消失,但 transcript 持久化了。在新会话中,agent 读取自己的历史并通过 eval 重新让能力”活”过来。

“An agent whose skills are literally stories it tells itself.”

对 Hermes 的启发

维度当前 Hermes可借鉴
Agent loop命令式状态机递归消息累积模式
工具扩展MCP 设计时协商Python exec() 作为运行时自建工具
技能系统SKILL.md 预编写技能作为”模型写给自己看的故事”
记忆gbrain / pgvector轻量场景可只用 JSON 文件
持久化多存储后端”remember-compress-recall” 模式

关键 insight: Hermes 已经在滑动这条光谱——代码解释器是第一代(模型写临时程序),SKILL.md 是第二代(能力存为文本运行时加载)。Lisp agent 把剩余的距离一下子拉平了:它的技能就存在自己的 transcript 里。

建议

  1. 🟡 P1 — 探索为 Hermes 添加 Python exec() 工具(沙箱化),让模型能直接写代码并执行,不需要绕道 terminal()。这比当前模式更安全(受限命名空间)且更自文档化(模型会追踪自己写的代码)
  2. 🟢 P2 — 研究 Hermes 的 agent loop 能否简化为递归消息累积模式
  3. 🟢 P2 — 将 “skills are memories” 洞察记录到 multi-agent-coordination skill