Sandcastle:让AI编码Agent无人值守运行的开源沙箱编排工具

让编码 Agent 真正「无人值守」运行
过去半年,知名 TypeScript 开发者、AI Hero 创始人 Matt Pocock 一直在追求一个目标:让他的编码 Agent 完全脱离人工监督(AFK, Away From Keyboard)运行。这些 Agent 会自动从待办清单里领取任务、实现功能、执行 QA,而且关键在于——它们是并行运行的,同时有多个 Agent 在工作。
AFK(Away From Keyboard)Agent 代表了一种新兴的软件开发范式:开发者不再逐行编写代码,而是定义任务、设定约束,然后离开让多个 Agent 并行工作。这种模式的理论基础来自于大语言模型(LLM)已具备足够的代码生成能力,瓶颈转移到了编排和质量保证环节。并行运行多个 Agent 类似于管理一个远程开发团队——每个 Agent 在独立的 Git 分支上工作,避免代码冲突,最终通过合并流程整合成果。这种并行架构涉及复杂的并发控制问题:每个分支本质上是一个独立的代码快照,利用了 Git 分布式版本控制的特性允许并行修改而不产生即时冲突。但当多个 Agent 同时修改共享依赖(如 package.json)或架构文件时,最终合并阶段的冲突解决成为关键挑战。这与分布式系统中的乐观并发控制(Optimistic Concurrency Control)思路一致:先允许并行执行,在提交时再检测和解决冲突。
但要实现这一点,绕不开一个核心难题:权限请求。如果你想让 Agent 无人值守跑起来,就必须处理它不断弹出的权限确认。你当然可以直接开启「YOLO 模式」完全绕过权限校验,但正如 Matt 所警告的,这样 Claude 可能会在你的系统上「干出疯狂的事」,比如删除你的用户主目录。在 Claude Code 等编码 Agent 中,YOLO 模式(又称 auto-accept 模式)会跳过所有权限确认对话框,允许 Agent 自主执行文件读写、网络请求、Shell 命令等操作。这种模式虽然消除了人工交互瓶颈,但也意味着 Agent 的任何「幻觉」或错误推理都会被立即执行。在企业场景中,这可能导致敏感代码被推送到公开仓库、API 密钥泄露到日志中、生产数据库被误操作等严重后果。
答案只有一个:沙箱化(Sandboxing)。只有把 Agent 关进隔离的沙箱里,它才能安全地放开手脚工作。沙箱化是一种安全机制,通过将程序的运行环境与宿主系统隔离,确保程序只能访问预先授权的资源。在容器技术中,Docker 利用 Linux 内核的 namespace 和 cgroups 机制实现进程、网络、文件系统的隔离——Namespace 提供了进程隔离(PID namespace)、网络隔离(Network namespace)、文件系统隔离(Mount namespace)等六种资源视图隔离;Cgroups 则限制容器可使用的 CPU、内存、I/O 带宽等资源量。对于 AI Agent 而言,沙箱的意义在于:即使 Agent 执行了危险命令(如 rm -rf /),影响也被限制在容器内部,不会波及宿主机。这与传统的虚拟机隔离相比,容器沙箱启动更快、资源开销更低,特别适合需要频繁创建和销毁的 Agent 工作负载。Docker 的分层文件系统(OverlayFS)还带来一个额外优势:多个 Agent 容器可以共享基础镜像层,只有各自的修改存储在独立的可写层中,大幅减少了并行运行多个 Agent 时的存储开销。对于 Agent 场景还需要特别注意网络策略——是否允许 Agent 访问外部 API、是否限制其只能访问特定的代码仓库,这些都是沙箱策略设计中的重要考量。
为什么现有沙箱方案不够好
市面上其实已经有不少沙箱方案,但 Matt 表示自己「没有一个特别满意」。他重点尝试并试图跑通的是 Docker 沙箱,然而在无人值守场景下问题层出不穷。
他真正想要的其实非常简单:一个 TypeScript 函数,调用时只需告诉它「用这个 Agent,在这个沙箱里,执行这段 prompt」即可。但他找到的工具几乎都在向他兜售某种第三方付费服务。
于是他决定自己动手,做出了 Sandcastle——一个用于编排沙箱脚本的 TypeScript 库。它的核心 API 极其简洁:sandcastle.run(),传入 Agent、传入沙箱、传入 prompt,就这么简单。这种设计体现了「基础设施即代码」(Infrastructure as Code, IaC)的理念——将 Agent 的运行环境和行为完全用可版本化、可复现的代码来描述,而非依赖图形界面或手动配置。IaC 最初由 Terraform、Ansible 等工具推广,核心价值在于获得版本控制、可复现性和自动化部署的能力。Sandcastle 将这一理念应用到 Agent 编排领域:Agent 的行为(prompt)、运行环境(Dockerfile)、任务来源(GitHub Issues)都被代码化,意味着你可以用 git blame 追溯某个 prompt 的修改历史,可以用 PR 流程审查 Agent 行为变更,甚至可以对不同的 prompt 版本进行 A/B 测试。

在 Matt 的任何一个开源仓库里,你都能看到一个 .sandcastle 目录,里面有一个 main.ts 文件,塞满了这些 sandcastle.run 小函数。别小看这个原语,用它可以搭建出相当复杂的系统:并行运行多个 Agent、让 Agent 审查自己的代码再合并入主干等等。
五分钟上手:从安装到跑通
初始化 Sandcastle 项目
接入 Sandcastle 的流程非常轻量:
- 运行
npm install ai-hero-sandcastle - 运行
npx sandcastle init
初始化时会引导你做几个选择:
- 选择 Agent:比如 Claude Code,也支持 Codex(OpenAI 的编码 Agent)
- 选择沙箱提供方:目前内置几个「一等公民」提供方,你也可以自己实现,Matt 计划未来加入更多。演示中选择的是 Docker
- 选择 Backlog 管理方式:因为 AFK Agent 需要某种机制来领取任务、判断下一步做什么。Matt 偏好用 GitHub Issues——这是一个巧妙的选择,因为 GitHub Issues 本身就是结构化的任务描述,支持标签过滤、优先级排序,且与代码仓库天然绑定。使用 GitHub Issues 作为任务 Backlog 相比传统的任务队列(如 RabbitMQ、Redis Queue)虽然性能较低,但提供了丰富的元数据:标签(Labels)可用于任务分类和优先级、里程碑(Milestones)可用于批次管理、评论区可记录 Agent 的执行日志、关联的 PR 可追溯实现过程。更重要的是,人类开发者和 AI Agent 可以在同一个界面上协作——开发者创建 Issue 描述需求,Agent 在评论区反馈进度,Reviewer 在 PR 中提出修改意见,实现了人机协作的无缝衔接
- 选择工作流模板:目前内置 5 个模板,演示中选择了功能最全的「带审查步骤的并行规划器(parallel planner with a review step)」
由于选择了 GitHub Issues,工具会创建一个 sandcastle 标签。此后只有带这个标签的 Issue 才会被 Agent 领取,实现了任务的精准过滤。
Docker 镜像构建与环境变量配置
初始化后,.sandcastle 目录里会生成一个 Dockerfile,这正是 Sandcastle 运行所依赖的容器定义。Dockerfile 是 Docker 镜像的构建配方,它以声明式的方式描述了容器内应该包含哪些工具、依赖和配置。每条指令(如 FROM、RUN、COPY)都会创建镜像的一个新层,Docker 的缓存机制确保只有变更的层需要重新构建,这对于 Agent 开发中频繁调试环境配置尤为重要。你可以在里面安装任何依赖——演示中安装了系统依赖、GitHub CLI(gh 命令行工具,用于在容器内直接操作 GitHub API),把 home 目录重命名为 agent,并装好 Claude Code。
随后运行构建命令生成默认镜像(速度很快),再配置 .sandcastle/.env 里的环境变量,主要是 ANTHROPIC_API_KEY 和 GITHUB_TOKEN。说个细节,如果你想用 Claude 订阅账号(Max Plan)而非 API Key,Matt 提醒 Anthropic 对这类用法「态度比较微妙」——因为订阅计划的定价模型是面向交互式使用的,大规模无人值守调用可能触及使用条款的灰色地带,仓库里有对应的 issue 说明最新建议。这涉及到 AI 服务定价模型的根本矛盾:按订阅收费的计划假设用户使用量有自然上限(人类打字速度和工作时长),而 AFK Agent 可以 24/7 不间断运行,单日 token 消耗量可能是人类用户的数十倍。
用一个 GitHub Issue 触发整条自动化流水线
配置完成后,只需在 GitHub 上创建一个带 sandcastle 标签的 Issue,例如:
「帮我搭建一个基础 TypeScript 模板,使用 Vitest 做测试、带类型检查、有一个用 Commander 实现的简单 CLI,并加上做类型检查和跑测试的 CI 脚本。」

这里提到的技术栈值得简要说明:Vitest 是基于 Vite 构建的新一代 JavaScript 测试框架,以极快的启动速度和原生 ESM(ECMAScript Modules)支持著称,它利用 Vite 的即时热更新(HMR)能力实现了测试文件的增量编译,相比 Jest 在大型项目中可提供数倍的速度提升;Commander 是 Node.js 生态中最流行的命令行参数解析库,用于构建 CLI 工具,它通过链式 API 定义命令、选项和参数,自动生成帮助信息。
然后在 package.json 里加一个脚本,用 npx tsx 运行 .sandcastle/main.mts,执行后整条流水线就自动跑了起来:
- Planner Agent 首先启动,在 Docker 沙箱里读取所有 open issues,输出一份 JSON 格式的计划(包裹在
plan标签内)。Planner 的角色类似于技术主管(Tech Lead),它分析所有待处理任务,决定执行顺序和依赖关系,并将复杂任务拆解为可独立执行的子任务。这种任务分解能力依赖于 LLM 对软件架构的理解——它需要判断哪些任务可以并行(如独立的功能模块),哪些存在前后依赖(如数据库 schema 必须先于 ORM 模型),从而生成一个有效的执行拓扑图 - Implementer Agent 随后被拉起,读取具体 Issue,在独立分支上写代码。演示中它甚至自发地做了「红-绿-重构」的 TDD 流程,先写测试再实现
- 全程你可以「去泡杯茶」,让它自己干活
红-绿-重构(Red-Green-Refactor)是测试驱动开发(TDD)的核心循环:首先编写一个必然失败的测试(红),然后编写最少量的代码使测试通过(绿),最后在测试保护下重构代码提升质量。Agent 自发采用这种流程意味着它已内化了软件工程最佳实践。在 AI 编码场景中,TDD 尤为重要——测试套件充当了自动化的验证层,让 Agent 能够自我检验实现的正确性,大幅减少对人工 review 的依赖。更深层次地看,测试文件还为 Agent 提供了明确的「完成定义」(Definition of Done):只要所有测试通过且类型检查无误,Agent 就有充分理由认为任务已完成,这种确定性反馈回路是 Agent 自主工作的基础。

核心设计哲学:不预设工作流,由开发者完全掌控
Matt 反复强调 Sandcastle 的哲学——它不对工作流做任何强制约定(unopinionated)。模板里的 planner、implementer、reviewer、merger 全都只是他自己「捣鼓出来」的一套工作流,你可以随意修改。这种设计理念在开发工具领域有着深远的传统——从 Unix 哲学的「做好一件事」到 Webpack 的插件架构,最成功的工具往往是提供强大的原语而非固化的流程。在 Agent 编排领域,这一点尤为重要:不同项目对质量、速度、安全的权衡各不相同——一个开源库可能需要严格的多轮审查,而一个内部原型项目可能只需要基本的类型检查就可以直接合并。
Prompt 即 Markdown:灵活的提示词管理
每个 Agent 都对应一个 Markdown prompt 文件(如 plan-prompt、implement-prompt、review-prompt),拥有非常好的编辑体验。其中一个亮点是 Matt 从 Claude Skills 借鉴的语法:在反引号前加感叹号,解析 prompt 时会实际执行该命令,比如自动运行 git diff 把代码变更注入到审查上下文里。
Claude Skills 是 Anthropic 为 Claude Code 设计的一种扩展机制,允许用户通过结构化的 Markdown 文件定义 Agent 的行为模式和工具使用规范。Matt 借鉴的「感叹号反引号」语法实现了「动态 prompt 注入」——在 prompt 被发送给 LLM 之前,先执行嵌入的 Shell 命令并将输出替换到 prompt 中。这意味着审查 prompt 可以自动包含最新的 git diff 输出,规划 prompt 可以包含当前的项目结构(如 tree 命令的输出或 package.json 的内容),实现了 prompt 与代码库状态的实时同步。这比静态的 system prompt 强大得多,因为每次执行时上下文都是动态生成的。从技术实现角度看,这本质上是一种模板引擎——类似于 Web 开发中的服务端模板渲染(如 EJS、Handlebars),但作用域从 HTML 生成扩展到了 AI prompt 组装。

Reviewer 与 Merger:模拟真实开发团队协作
这套工作流之所以强大,在于它模拟了一个真实团队的代码评审(Code Review)流程——这是现代软件工程中质量保证的核心环节。Google 的工程实践研究表明,代码评审能捕获约 15% 的缺陷,更重要的是它促进了知识共享和代码规范的一致性:
- Reviewer(审查者):Implementer 会犯错,但 Reviewer 通常能抓出来。你甚至可以做「对抗式审查」——让
sandcastle.codex(OpenAI 的 Agent)去审查 Claude 写的代码,或让多个不同 Agent 各自实现,再由另一个 Reviewer 挑选或融合最优方案。这种跨模型审查的思路类似于机器学习中的「集成方法」(Ensemble Methods),通过多个独立模型的交叉验证来提升整体输出质量。其有效性源于「模型多样性」原则:不同的 LLM 在不同的训练数据和架构下形成了各自的偏见和盲区——Claude 可能在某些设计模式上有偏好,而 Codex 可能在另一些方面更敏锐。交叉审查还能检测出「模型共谋」问题——如果同一个模型既写代码又审查,它可能对自身生成模式的缺陷视而不见 - Merger(合并者):所有分支最终交给一个 Merger Agent 合并回 main。之所以用 Agent 而非脚本,是因为分支间可能存在棘手的合并冲突(Merge Conflict),需要一个「资深合并开发者」来处理。合并冲突发生在多个分支修改了同一文件的同一区域时,自动合并工具(如
git merge)无法确定应保留哪个版本。传统做法需要人工判断代码语义来解决冲突,而 LLM Agent 凭借其代码理解能力,能够在大多数情况下做出合理的合并决策。具体来说,Agent 需要理解两个分支的修改意图,判断是保留一方、合并双方还是重写整段代码——这需要对项目上下文和代码语义有深层理解,正是 LLM 的优势所在
演示的最终结果:多个 Agent 并行提交到各自分支,Reviewer 判定代码「干净且结构良好」,Merger 跑通类型检查、合并分支并附评论关闭了 Issue。仓库里凭空多出了 tsconfig.json、vitest.config.ts 和 CLI 相关文件——一个完整的迷你软件工厂就此运转起来。
总结:把编码 Agent 变成可编程的构建块
Sandcastle 的价值在于,它把 Claude Code、Codex 这样的编码 Agent 变成了可编程调用的原语。你可以用简单的函数和优雅的 Markdown prompt,搭出分支合并流、PR 流等复杂工作流。这种「Agent 即函数」的抽象层次,与云计算中「Serverless 函数」的演进路径异曲同工——将复杂的基础设施封装为简单的可调用单元。正如 AWS Lambda 将服务器管理、扩缩容、负载均衡等复杂性隐藏在一个函数接口背后,Sandcastle 将容器管理、Agent 生命周期、分支操作等复杂性隐藏在 sandcastle.run() 这个简单的调用背后。
正如 Matt 所说:「这只是代码而已。」但正是这种「拥有自己的流程、不被第三方服务绑定」的能力,让他的开发速度大幅提升。对于正在探索 AFK Agent、并行编码工作流的工程师而言,Sandcastle 无疑是一个值得关注的开源新选择。它预示了软件开发的一个可能未来:开发者的角色从「写代码的人」转变为「编排 Agent 团队的架构师」——定义任务边界、设计质量门禁、优化 prompt 策略,而将具体的代码实现委托给 Agent 团队。这种转变并非替代开发者,而是将开发者推向更高层次的系统设计和决策角色。
核心要点
相关推荐

Cursor Agents窗口争议:AI编程效率与开发者控制权的博弈
Cursor力推Agents窗口引发开发者不满,并行运行多个AI Agent真的能提升编码效率吗?深入分析AI编程工具中效率与控制权的矛盾,探讨Agent工作流的真实边界与隐患。

AI时代学习法:90%的知识只需理解无需死记
在AI工具普及的时代,90%的学习材料只需理解原理无需死记硬背。本文探讨如何区分需要内化的核心知识与可按需调用的信息,帮助学习者摆脱内卷式记忆堆积,转向深度理解与高效学习。

Ox Alpha疑似谷歌Gemini:匿名模型测试背后的竞争策略
AI社区热议神秘模型Ox Alpha可能出自谷歌Gemini系列。本文深度解析匿名模型测试的战略意义、行业惯例及对AI竞争格局的影响,探讨谷歌是否正以隐身方式发起强势出击。