Agent 背后的工程现实:Skill 编排和 Sandbox 执行环境

大部分人第一次接触 Agent,都是从那些看起来很酷的 Demo 开始的:会自己调用工具,会自己点网页,仿佛无所不能。
但一旦你想把 Demo 变成生产环境的代码,就会撞上一堵墙。你会问:“它到底是怎么被约束的?代码到底是在哪儿跑的?”
这时候,仅仅谈论 Prompt 和 LLM 已经不够了。在工程落地时,我们必须把 Agent 背后最容易混淆的两块积木拆开来看:Skill(技能) 和 Sandbox(沙箱)。
这篇文章不谈未来,只谈这两个核心组件在工程架构里的位置。
先对齐一下概念
在一个严肃的 Agent 系统架构里,通常会有这样几层分工:
- Agent / Orchestrator:这是大脑,负责接收指令、规划路径、选择工具。
- Tool:这是原子能力,比如发一个 HTTP 请求、执行一条 bash 命令、点击一下浏览器。
- Skill:这是经验的沉淀。它告诉 Agent 针对某类任务,应该“怎么干”。
- Sandbox:这是执行的环境。Tool 最终是在这里运行的,它解决了“在哪儿干”的问题。
接下来的内容,我们都基于这四个词来展开。
Skill:把“老司机的经验”打包
Skill 不仅仅是接口定义
很多人刚开始设计 Agent,容易把 Skill 理解成一种“协议”:定义好入参、出参、错误码,扔给 Agent 去调就完事了。
但在实际工程中,Skill 更像是一份“经验 + 约束 + 资源入口”的说明书。
试想一下,如果你要在团队里推广一个新的运维操作,你不会只给新人一个 API 文档,你通常会给一份 Wiki 或者 README,里面写着:
- 这类问题通常怎么排查(流程)。
- 日志在哪个目录,脚本在哪个路径(资源)。
- 千万别动哪个配置项(约束)。
Skill 就是这份 Wiki 的机器可读版本。
它更像是“README + Makefile + scripts”的打包,或者是 Terraform 的 module。它描述了一类操作的最佳实践(SOP),而不是简单的函数调用。
一份合格的 Skill 包含什么?
如果把 Skill 压缩到最小集合,它至少要回答三个问题:
- 任务域说明:我能干什么?(例如:排查线上 5xx 错误)。我需要什么前置条件?(例如:日志路径、代码仓库权限)。
- 推荐流程:这一类任务,老手通常先干什么、后干什么?比如“先看监控面板,再搜错误码,最后才去改代码”。
- 工具与约束:在这个 Skill 里,允许用哪些工具?有没有顺序限制?(比如:必须先读文件,确认无误后才能执行写操作)。
从实现角度看,Skill 可能就是一份被加载到 Context 里的 Markdown 文件,它把团队里那些“默认的行规”显式地告诉了 Agent。
Sandbox:给 Tool 一个安全的“肉身”
Skill 解决了“怎么干”,Sandbox 则负责解决“能干”和“安全地干”。
Agent 本身只是运行在服务器上的 Python/Node.js 进程,它不能直接在宿主机上随心所欲。它需要一个受控的执行环境,这就是 Sandbox。
工程上最常见的两类 Sandbox:
1. 计算机沙箱 (Computer Sandbox)
当 Agent 需要读写文件、grep 日志、运行 Python 脚本或执行 bash 命令时,它需要一个类 Unix 的环境。
通常这个 Sandbox 会暴露三种接口:
- File 能力:读写文件、列目录。
- Bash 能力:执行 shell 命令,捕获 stdout/stderr。
- Code 能力:在一个隔离的 Runtime(如 Docker 容器)里运行代码片段。
无论接口叫 text_editor 还是 bash_exec,本质上都是在同一个 Computer Sandbox 里开了不同的操作窗口。
2. 浏览器沙箱 (Browser Sandbox)
当 Agent 需要像人一样操作网页时(点击、输入、滚动、抓取 DOM),它需要一个浏览器环境。
这通常由 Headless Chrome、Playwright 或者专门的浏览器容器提供。对 Agent 来说,它看到的是 click、type、scroll 这样的工具,但这些工具产生的作用,全部发生在 Browser Sandbox 这个隔离的实例里。
一张图看懂关系
如果我们把这一层关系画出来,大概是这样的:

简单总结这张图的逻辑:
- 用户看到的只是 Agent 在“想办法”。
- 中间层靠 Skill 注入经验,约束它“怎么干”
- 底层靠 Sandbox 提供物理环境,决定它“在哪儿干、能干到什么程度”。
还原一次真实的执行链路
把抽象概念落地,我们看一个具体的“线上故障排查”任务,Agent 是怎么跑完的:
- 任务接入:用户扔进来一句话:“帮我定位最近订单接口的 5xx 问题,产出一份排查笔记。”
- 加载 Skill:Agent 识别出这是“故障排查”类任务,于是加载了对应的 Skill。
- Skill 提示:日志在
/var/log/app,推荐先搜ERROR关键字,再看代码。
- 进入 Sandbox:
- Agent 根据 Skill 的指引,调用
file_read工具(动作发生在 Computer Sandbox)。 - Agent 在代码库里搜索错误堆栈(动作发生在 Computer Sandbox)。
- Agent 发现需要去 Grafana 看一眼趋势,于是调用
browser_open工具(动作发生在 Browser Sandbox)。
- 产出结果
- Agent 依据 Skill 要求的格式,把 Sandbox 里拿到的执行结果汇总,生成最终笔记。
在这个链条里,Skill 是剧本,Sandbox 是舞台。
为什么工程上一定要拆开?
在写 Demo 时,我们往往把 prompt、tool 和执行逻辑写在一起,反正能跑通就行。但在工程化开发中,拆分 Skill 和 Sandbox 意义重大:
- 复用与沉淀:Skill 是一个天然的“经验沉淀点”。不会写 Prompt 的同事,也可以直接复用既有的 Skill,用团队统一的流程去处理任务。
- 确定性测试:Sandbox 让环境隔离成为可能。我们可以通过录制/回放、Mock 网络等方式,针对 Sandbox 做确定性测试,而不用担心 Agent 把宿主机搞挂。
- 边界清晰:写复杂 Agent 时,心智负担会小很多。你只需要问自己两个问题:这事儿有没有套路(Skill)?这事儿需要什么环境(Sandbox)?
看懂了这两层,再去看市面上各种眼花缭乱的“智能体平台”或“Agent 框架”,你会发现很多设计其实都是殊途同归:
上面那层在玩 Skill 的编排,下面那层在搞 Sandbox 的容器化。

