从 Smithery 上翻到一个挺冷门的 skill,cloudflare/session-execution,21 次安装,说明写得像内部备注。开头就是一句“Read docs/SESSION_EXECUTION.md before working in this area”,这个语气反而勾起了我的兴趣。它明显不是写给普通用户看的,是 Cloudflare 沙箱团队写给 AI 开发 agent 看的。
这个 skill 挂在 cloudflare/sandbox-sdk 名下,一个让你在 Workers 边缘运行不受信任代码的 SDK。sandbox.exec(‘python3 -c “print(2+2)”’),API 简单到只有一行。但 session-execution 的存在说明,让 AI 去改这段代码之前,得先让它理解底层的五个硬问题。

我一开始以为这是个操作手册类的 skill,教 agent 按步骤办事。读完全部架构文档才发现,它更像一份工程契约:把 stdout/stderr 分离、完成信号、并发串行化这些容易踩坑的设计决策,固化成 agent 在开发和审查时必须遵守的规则。
这篇文章想把这份契约拆开讲清楚:这个 skill 到底在教什么,背后的架构决策为什么这么做,以及它对做沙箱、做 AI 代码执行、甚至做 agent 技能的人有什么可抄的。
老实说,一个项目级 skill 能写成这样,本身就说明 Cloudflare 把 agent 辅助开发当成了正经事。大多数仓库的 agent 配置还停留在“别忘了跑测试”的水平,而这个 skill 连审查时的误报边界都帮你划好了,值得单独拿出来看看。
这个 skill 解决什么
先看定位。frontmatter 里写得很直白,这个 skill 的适用范围是:
-
会话执行与会话状态管理 -
命令处理与 shell 进程管理 -
FIFO 流式传输 -
stdout/stderr 分离
它适用于 session.ts、exec/execStream 的修改或审查。安装也就一行命令:
npx skills add https://github.com/cloudflare/sandbox-sdk --skill session-execution
它锁定了三个关键文件:session.ts 是执行核心,SessionManager.ts 管互斥锁和生命周期,CommandClient.ts 是 SDK 暴露给用户的命令接口。agent 碰这几个文件时,skill 会强制它先读架构文档再动手。
真正让我服气的是 deep dive 文档里那句“Looks simple. Five hard problems are hiding underneath”。五个问题分别是:
-
跨命令的状态持久化:cd、export 要能延续到下一道命令 -
stdout 与 stderr 的可靠分离:两条流来自同一个进程 -
命令完成的确定性检测:bash 没有内建完成信号 -
后台进程树的清理:只杀父进程会留下孤儿进程 -
同会话内并发命令的串行化:交错执行会让状态不可预测
任何一个处理不好,都会表现为用户侧诡异的 bug。
这五个问题的解法,浓缩成了 session-execution 的核心内容。整个会话执行系统按分层看,结构非常清晰:

两种执行模式的架构拆解
核心设计是两条执行路径,各自为战。前台 exec 跑在主 shell 里,状态持久,用临时文件捕获输出;后台 execStream 和 startProcess 跑在子 shell 里,通过 FIFO 实时流式输出,可随时终止。两者差异用一个表就能看清:
| 维度 | 前台 exec | 后台 execStream / startProcess |
|---|---|---|
| 运行位置 | 主 shell(组命令) | 子 shell(子进程) |
| 状态持久 | 是 | 否 |
| 流式输出 | 否 | 是 |
| 可终止 | 否(只能超时) | 是(SIGTERM) |
| 输出机制 | 临时文件重定向 | FIFO + 后台 labeler |
为什么前台用临时文件而不是 FIFO?文档里的解释一针见血:文件重定向是同步的,bash 会等所有写入完成才继续;而 FIFO 和进程替换是异步的,bash 在写入开始时就会返回,大输出时读到一半就拿去读了。配合组命令 { } 而非子 shell ( ),cd、export 才能影响后续命令,状态持久才成立。
后台恰恰相反,要的就是并发。命令跑在子 shell 里,FIFO 是管道不是文件,TS 端读日志时命令还在写,两边互不阻塞。这两条路径谁也无法取代谁,强行统一只会两头不讨好,FAQ 里把这个决策说得非常直白。
输出分离靠的是二进制前缀契约。log 文件里每一行都带 3 字节前缀,stdout 是 \x01\x01\x01,stderr 是 \x02\x02\x02,TS 的 parseLogFile 根据前缀重建两条流。3 字节是为了尽量降低与真实输出撞车的概率,开销压得很小:
stdout: \x01\x01\x01 hello from python
stderr: \x02\x02\x02 Warning: deprecated API
完成信号是另一个容易翻车的地方。bash 没有“命令跑完了”的内建信号,会话 shell 还得活着等下一道命令。做法是让命令把退出码原子写入文件:先写 .tmp,再 mv 成正式文件。TS 端用 fs.watch 加 50ms 轮询的混合策略检测,fs.watch 快但在 tmpfs/overlayfs 上不可靠,轮询稳但慢,混搭兼顾两者。
后台模式的完成链路更复杂,labelers.done 标记要确保输出被完整捕获后才返回。整个时序用一张图能看清:

还有几个值得抄的 TypeScript 模式。shellExitedPromise 是个永不 resolve、只在 shell 死亡时 reject 的 Promise,跟正常完成信号做 Promise.race,shell 意外退出立刻能被感知。PID 获取也讲究,读 FIFO 是阻塞读,保证拿到完整 PID,而不是轮询 PID 文件跟半写状态赛跑。
这套实现是深度绑定 bash 的。文档明说它 spawn 的是 bash –norc,依赖组命令、FIFO 这些 bash 特性,可移植性不是它的目标。这算是有意的取舍,沙箱环境是自控的,牺牲通用性换可靠性,值。
把整个执行生命周期串起来,就是下面这张流程图。从命令请求到会话互斥锁,再到输出解析返回,每一步都有明确的设计意图:

审查规则里的门道
这个 skill 最特别的地方在“审查”部分。它没有停留在教你怎么写,而是给出了正确性检查清单和一份常见误报清单,在我看过的同类 skill 里极其少见。
误报清单很有意思。“并发读写 session 状态”会被判定为误报,因为会话内互斥锁已经串行化;“FIFO 操作可能竞争”也被排除,labeler 是每命令独立的,不共享。真正该担心的是跨 session 操作、清理动作误伤还在运行的命令、互斥锁保护范围外的文件操作。教 agent 什么不该报,比教它报什么更难。
审查硬规则也写得很细:
-
退出码写入必须原子,先写 .tmp 再 mv -
错误路径要检查 FIFO 清理 -
后台模式读最终输出前必须 await labelers.done
这些条条都是线上事故换来的,比如静默命令(cd、变量赋值)历史上就造成过挂起。
有个诚实的局限必须提。killProcess 只对直接进程发 SIGTERM,子进程不会被连带杀掉,文档明确标注这是 known limitation。要基于它做进程树级管理,得自己补一套进程组处理。这种把边界写明白的诚实,反而是它质量最高的地方。
洞察:契约化的技能
回头看,session-execution 的真正价值不在它本身,而在于它示范了一种技能的正确写法:把隐性经验显性化,再压缩成 agent 能遵守的契约。它不教你如何写 bash,它告诉你哪些决策不能动,为什么不能动,动了会踩什么坑。
这跟市面上大量操作手册式的 agent 技能形成鲜明对比。那些技能教 agent 按步骤执行,一旦遇到文档没覆盖的边界就抓瞎。这个 skill 反过来,把边界和反模式当成一等公民写进规则,agent 反而获得了更大的自主空间。
对做沙箱和 AI 代码执行的人,这套架构几乎是现成的参考答案:
-
双模式取舍:状态持久与流式输出不可兼得,分开设计 -
3 字节二进制前缀契约:极低成本实现流分离 -
原子退出码加混合检测:让完成信号可靠可见 -
互斥串行化:保证会话内状态一致性
每个决策都有明确的工程理由。对做技能开发的人,它的正确性清单加误报清单结构值得直接抄。
有一点要注意,这个 skill 绑定的是 bash 和 Cloudflare 的容器环境,换到别的 runtime 不能直接套用。但把它当成一份会话执行领域的问题清单来读,几乎可以迁移到任何代码执行产品。
另一个值得玩味的点是完成信号里的混合检测。fs.watch 加轮询这种“快路径加兜底”的思路,在分布式系统里随处可见,但放在一个容器的会话层,就显得特别务实。它不追求理论上的最优,只保证在 tmpfs、overlayfs 这些真实容器文件系统上不翻车。
资源地址
总结
exec 一行代码的背后,是五个硬问题加上一整套可靠性机制。session-execution 的价值,是让这套机制以契约的形式存在于代码库旁边,而不是躺在某个工程师的脑子里。
如果你在搭代码执行类的产品,建议直接去读 SESSION_EXECUTION.md 的 FAQ 部分,那里几乎每一问都是一次真实的架构取舍。如果你想给自己的项目写 agent 技能,试试契约化的写法:说清边界,列明误报,比堆操作步骤有用得多。
这个领域远没到尘埃落定的时候。随着 AI 原生应用越来越多地执行代码,会话执行这种看不见的工程会越来越值钱,而 Cloudflare 已经把它写成了文档。
