第 13 章 AI AgentAgentic Patterns代码执行

第 13 章 代码执行与沙箱:先写码,再跑码

跑代码,比看起来危险

上一章讲了命令怎么跑。这一章聚焦一个更精确的环节:代码执行。Agent 不只是跑现成命令,它经常要自己写代码、自己跑。而"让模型写代码再跑"这件事,有两个绕不开的问题。

第一个是审计。Agent 的"想清楚再动手"(plan-and-act)循环,关键决策都藏在自然语言的推理里,外人根本没法验证它有没有把不可信数据流进危险操作(发外部邮件、付款、执行破坏性命令)。文本计划太弱,做不了形式化校验。

第二个是注入。会话中途,Agent 经常要查看本来没载入上下文的文件。手动把整个文件复制粘贴进提示词,又繁琐又费 token,还打断节奏。

这一章讲三个模式:

  1. Code-Then-Execute(先写码后执行):让模型先输出一段沙箱程序,静态检查通过再执行。
  2. Dynamic Code Injection(动态代码注入):按需把文件内容注入上下文,别整篇复制。
  3. Agent SDK for Programmatic Control(程序化控制 SDK):把 Agent 的核心能力暴露成 SDK,供程序调用。

模式一:先写码后执行(Code-Then-Execute)

问题

安全敏感的工作流里,团队需要可验证的保证:被污染的输入(tainted inputs)不能流进危险出口(外部消息、支付、破坏性命令)。但自由形式的 plan-and-act 循环做不到这一点,因为控制决策都在自然语言推理里,没法形式化验证。

方案

让 LLM 输出一段"沙箱程序"或 DSL 脚本,把"推理动作"变成"编译动作"。动作一旦变成代码,策略引擎和静态分析器就能在执行前强制数据流规则。

三步走:

  1. LLM 写代码:写一段调用工具和不可信数据处理器的代码。
  2. 静态检查 / 污点分析:验证数据流,比如"没有脏变量流入 send_email.recipient"。
  3. 沙箱解释执行:代码在锁定的沙箱里跑。

核心转变:从"推理动作"转向"把动作编译成可检查的产物"

x = calendar.read(today)              # 读日历
y = QuarantineLLM.format(x)           # 用 LLM 格式化(不可信输出)
email.write(to="john@acme.com", body=y)  # 检查: y 是否干净? 能进邮件吗?

这段 DSL 里,静态检查器可以确认:从 QuarantineLLM.format 出来的 y 属于"不可信"来源,如果要流进 email.writebody,必须先过隔离/净化逻辑,否则直接拒绝。

这个模式还有个附带价值:token 优化。工具调用在沙箱内执行,不经过特殊 token,只有精简后的结果回流 LLM 上下文。生产部署中,数据重的工作流 token 能省 75%-99%。

证据

  • 来自 DeepMind CaMeL(Beurer-Kellner 等人,2025,emerging),提出了"代码增强语言模型"做安全工具使用。
  • Anthropic Engineering 的 Code Execution with MCP(2024)验证了"沙箱内执行 + 结果回流"的 token 收益。

怎么用

  • 适合多步骤、审计很重要的 Agent:SQL 助手、软件工程机器人、工作流自动化。
  • 从小的 DSL 和明确的禁止流开始,随着检查逻辑成熟再扩展语言特性。
  • 别一上来就做大而全的 DSL,先覆盖最小安全边界。

取舍

  • 好处:形式化可验证;可重放日志;数据重工作流 token 成本下降。
  • 代价:要设计 DSL 和静态分析基础设施;沙箱执行有额外开销。

模式二:动态代码注入(Dynamic Code Injection)

问题

交互式编码会话里,用户或 Agent 经常要查看一开始没载入主上下文的文件。手动把整个文件复制粘贴进提示词:

  • 繁琐、容易出错。
  • 浪费 token 在样板内容上(比如大型配置文件)。
  • 打断节奏:编辑器 / 聊天之间来回切换,工作流就断了。

方案

用特殊语法(@filename/load file)支持按需文件注入,自动完成三步:

  1. 取文件:从磁盘或版本控制拉取请求的文件。
  2. 摘要/提取:文件大就只提取相关部分(函数体、AST 解析的定义、指定行范围)。
  3. 注入:把片段注入 Agent 当前上下文,直接扩展它"对任务的记忆"。

具体来说:

用户输入: /load src/components/Button.js:10-50
  或: @src/setup/db.js

预处理: 拦截命令 → 读文件(或行范围)→ 用文件内容替换命令
其余提示词不变 → Agent 无需重启会话继续推理

语法约定:

  • @path/to/file.ext:整个文件载入(小于 2,000 token),否则跑启发式摘要。
  • /load path/to/file.ext:10-50:只载入第 10-50 行。
  • /summarize path/to/test_spec.py:跑摘要例程(提取 docstring + 测试名)。

实现步骤:

  1. 在聊天前端或 CLI 里建一个监听器,识别 @/load 标记。
  2. 把标记映射到文件路径;校验权限,解析符号链接(防止越出项目根目录)。
  3. 读文件文本,需要时跑行范围解析器或 AST 片段提取器(tree-sitter 支持多语言)。
  4. 在发出的提示词里,把标记替换成 /// BEGIN <filename> …内容… /// END <filename>
  5. 把增强后的提示词发给 LLM 推理。

常见坑:

  • 路径穿越:必须校验并拒绝 @../../../etc/passwd、项目外的绝对路径、恶意符号链接。
  • 大文件:超过 4,096 token 自动跑摘要子例程,只提取函数/方法定义。
  • 敏感文件.env*.key 这类要拦。

证据

  • 来自 Anthropic 的常见工作流(Claude Code 的 at-mention),established(成熟)。
  • 各大 AI IDE 插件都在用:GitHub Copilot Workspace、Cursor;Aider 的 /add/drop 命令配 tree-sitter AST 解析。

怎么用

  • 适合任何编码类 Agent 和 AI IDE 插件。
  • 前端/代理要有本地文件系统访问权限。
  • 安全三件套不可妥协:路径校验、敏感文件拦截、沙箱。

取舍

  • 好处:不出聊天环境就能探索代码;消灭手动复制粘贴;确保最相关的代码直接可见,Agent 更准;token 省 10-100 倍(相对全量载入),有记录显示开发效率提升 3 倍以上。
  • 代价:界面/代理要能访问本地文件系统;安全校验是硬要求;摘要启发式可能漏掉微妙上下文(比如私有辅助函数)。

模式三:程序化控制 SDK(Agent SDK for Programmatic Control)

问题

交互式终端和聊天界面适合很多 Agent 任务,但不是所有。把 Agent 能力集成进自动化工作流(CI/CD 流水线、定时任务、批处理),或者在核心 Agent 功能之上构建更复杂的应用,需要一个程序化接口。你不能在 CI 里开个聊天窗口。

方案

提供一个 SDK,把 Agent 的核心功能暴露成程序化访问。 开发者可以:

  • 从代码里调用 Agent 动作(处理提示词、用工具、访问记忆),用 Python、TypeScript。
  • 以非交互方式配置 Agent 行为和工具访问。
  • 把 Agent 逻辑集成进更大的软件系统。
  • 自动化涉及 Agent 的重复任务。
  • 构建由 Agent 后端驱动的自定义 UI 或应用。
  • 控制资源限制(token 预算、执行时间、成本上限)。
  • 实现细粒度权限管理和授权范围。

SDK 通常包含库、用于脚本化的 CLI、以及无头(headless)/嵌入使用的文档。

# Claude Code SDK 风格的 CLI 示例
$ claude -p "我这周干了啥?" \
  --allowedTools Bash(git log:*) \
  --output-format json

程序化调用,非交互,输出 JSON,权限提前限定好。

怎么用

什么时候用:

  • CI/CD 流水线集成和自动化工作流。
  • 跨多个文件或项目的批处理。
  • 构建由 Agent 后端驱动的自定义应用或 UI。
  • 性能敏感场景(缓存和低开销重要)。
  • 外部开发者集成和标准化需求。

什么时候别用:

  • 微服务架构(用 REST/gRPC API 更合适)。
  • 语言和框架独立性是硬要求。
  • 高频调用(每秒 >100 次)或实时流式。

实施建议: 从窄工具面开始,参数校验严格;加可观测性(延迟、失败、回退路径);代码执行做沙箱隔离。

取舍

  • 好处:能自动化、能接 CI/CD;权限、资源、可观测性都能细粒度控制;支持批处理和自定义 UI。
  • 代价:集成耦合和环境维护成本;失去对话式交互和澄清能力;要用代码处理错误,重试/回退逻辑要写扎实。

三个模式怎么选

场景 推荐模式
安全敏感,要验证数据不流进危险操作 先写码后执行(DSL + 污点分析)
会话中要按需查看大文件 动态代码注入
要把 Agent 接进 CI/CD 或构建应用 程序化控制 SDK

三个模式回答"代码执行"的三个问题:先写码后执行管"怎么安全地跑",动态代码注入管"代码上下文从哪来",程序化 SDK 管"怎么让程序来驱动"。它们和上一章的虚拟机、智能 Bash 组合起来,就是完整的执行层。

这里也呼应一下第 10 章:Code-Over-API 说的是"让代码去调工具省 token",先写码后执行说的是"让代码可审计"。同一个"代码优先"思路的两个侧面,一个为省钱,一个为安全。

实践清单

  • 安全敏感工作流:让模型输出 DSL/沙箱程序,静态检查通过再执行
  • DSL 从小做起,先明确"禁止流",再扩展语言特性
  • 代码执行前跑污点分析:脏数据不能流进邮件/支付/破坏性命令
  • 会话里按需注入文件:@file / /load file:10-50,大文件自动摘要
  • 文件注入必须校验路径:拒绝穿越、项目外绝对路径、恶意符号链接
  • 敏感文件(.env、*.key)拦截,超 4K token 自动摘要
  • 要自动化:暴露 Agent SDK / CLI,非交互、JSON 输出、权限前置
  • SDK 配资源限制(token 预算、执行时间、成本上限)和沙箱隔离
  • 加可观测性:延迟、失败率、回退路径

本章小结

  • 先写码后执行:动作变成可检查的代码,静态分析先于执行,token 还省 75%-99%。
  • 动态代码注入:@ / /load 按需注入文件片段,省 token、保节奏、Agent 更准。
  • 程序化 SDK:把 Agent 核心能力暴露成代码可调,接 CI/CD、做应用、控资源权限。
  • 代码执行三件事:安全地跑、按需取上下文、程序化驱动。
  • 到这里,第三部分"工具与环境"就讲完了:接口设计(10)→ 工具发现(11)→ 执行环境(12)→ 代码执行与沙箱(13),一条"让 Agent 动手"的完整链路。

下一部分进入"让它可靠":评测与观测,让 Agent 稳定可用。先从第 14 章结构化输出与契约开始。

📑 Agent 模式实战:生产级 AI Agent 的工程模式

1 第 1 章 什么是 Agent 模式 2 第 2 章 规划-执行-观察:先想清楚,再动手 3 第 3 章 反思闭环:让 Agent 学会检查自己的作业 4 第 4 章 委派:让主 Agent 学会把活分出去 5 第 5 章 上下文预算治理:把 token 当成钱来管 6 第 6 章 上下文压缩与精选:装不下怎么办 7 第 7 章 上下文最小化:别让脏东西留在脑子里 8 第 8 章 记忆体系:让 Agent 记得住过去 9 第 9 章 学习沉淀:让 Agent 和团队一起变聪明 10 第 10 章 工具接口哲学:让 Agent 能用、好用、用得起 11 第 11 章 工具发现:让 Agent 在几百个工具里找到对的 12 第 12 章 执行环境:Agent 在哪动手、怎么动手 13 第 13 章 代码执行与沙箱:先写码,再跑码 14 第 14 章 结构化输出与契约:让 Agent 的输出能接住 15 第 15 章 验证循环:Agent 怎么检查自己的作业 16 第 16 章 评测基建:怎么系统地检验 Agent 17 第 17 章 可观测性:看见 Agent 在想什么、在干嘛 18 第 18 章 韧性工程:扛得住部分失效 19 第 19 章 威胁模型:先看风险长什么样,再谈防御 20 第 20 章 控制流隔离:把"谁做决定"和"谁执行"分开 21 第 21 章 权限与审批:谁有权干什么、谁点头 22 第 22 章 凭据与出口:Agent 手里的钥匙和门 23 第 23 章 多智能体信任:多个 Agent 之间怎么互信、怎么审计 24 第 24 章 反馈信号设计:给 Agent 的是信号,不是更大的提示词 25 第 25 章 评测驱动的改进:让 Agent 在真实使用和对抗测试里变强 26 第 26 章 强化学习:把反馈变成训练信号 27 第 27 章 复合式进化:让 Agent 系统越用越值钱 28 第 28 章 多智能体协调:让一群 Agent 一起干活不掉链子 29 第 29 章 模型路由:谁用哪个模型,怎么用得起 30 第 30 章 推理搜索结构:让 Agent 多想想,而不是一条道走到黑 31 第 31 章 控制谱系:从自动补全到完全自主的滑动条 32 第 32 章 团队与产品:把 Agent 变成团队资产,而不是个人玩具
← 返回本书大纲