SCH:在 AWS 账户里给编程 Agent 搭一个低成本沙盒
简介
一个周五早上,我合上了笔记本电脑,而一个编程 Agent 还在云端的轻量容器里继续干活。几个小时后我重新打开电脑,分支已经可以审查了,运行环境早已自动销毁,远程算力只花了几美分。这个数字还不包括模型推理费用,那是单独计算的。
要做到这一点,我得先回答两个问题:
- 我真的需要让自己的电脑或一台远程机器跑满八小时循环吗?
- 能不能让 Agent 在无人值守的情况下工作,同时又不用自己搭一套沙盒系统?
这篇文章就是我的答案:SCH,一个基于 AWS AgentCore 的无服务器编程框架。
过去两年,冒出了不少以“工程”结尾的概念。上下文工程把注意力从单条提示词转向了下一步能拿到的信息。Geoffrey Huntley 的 Ralph Wiggum 循环——说白了就是 while :; do cat PROMPT.md | claude-code; done——展示了 bash 循环能做到什么程度:每次迭代都用全新的上下文,状态存在磁盘上。之后又出现了循环工程、图工程、框架工程。概念名字换得很快;我搭 SCH 主要需要三个概念:
-
状态:上下文窗口消失后,工作成果存在哪里——文件、规划文档、git 历史、检查点。每种循环技术都必须把足够多的状态外置,让下一次迭代能接着上一次继续干。
-
框架(Harness):模型调用之外的一切——工具、钩子、权限、检查,以及决定“完成”是否真的完成了的外层循环。粗略地说,“Agent” = “模型” + “框架”。
-
运行环境:跑框架的机器——文件系统、网络、凭证、生命周期。很多时候就是开发者的笔记本,随之而来的是各种限制。
更新的模型加上这三个要素的研究进展,也改变了工作单元的粒度。一个任务可以无人值守地跑几个小时,跨越多个会话和检查点,甚至跑上好几天。这就带来了两个实际问题。
-
总得有人守着机器。循环跑八小时,就意味着笔记本得开八小时,或者我得租一台远程服务器,还得更新它、记得关掉它。
-
长时间循环会助长 YOLO 模式。只要工具层弹出授权请求,无人值守的任务就停住了。开着权限校验时,很容易出现这种情况:回来一看,Agent 早在十二分钟前就卡住了,就等着你说一句“好的,继续”。于是很多人干脆用上
--dangerously-skip-permissions、--auto或--yolo这类选项。
会话越长,出意外状况的机会就越多。如果在笔记本上开着自动批准跑,那么维持循环的这台机器往往同时存着 SSH 密钥、云平台凭证和个人数据。一旦从单个会话扩展到跨不同分支和任务的三四个会话,问题就更明显了:笔记本变成了多个 Agent 共用的主机,可操作的空间很大。
隔离能缩小出错的波及范围,但前提是网络访问和权限要跟任务匹配。沙箱限制太严,Agent 会在第一条被拒的命令上停下;限制太松,无非是把问题挪到了别处。
过去几周,我一直在找一套方案,既能隔离运行时、跑异步的分离任务,又能至少兼容 OpenCode 和 Claude Code。我还希望不用自己维护服务器和沙箱规则。
由于我平时大量用 AWS,早就接触过 Amazon Bedrock AgentCore Runtime。最贴切的类比是:它是一个专门用来托管 AI Agent 的 Lambda——无服务器运行时,按量付费,会话彼此隔离。空闲超时一到,运行时消失,算力归零。后面我会贴出大约十天断续使用下来统计的数据。
SCH - Serverless Coding Harness 就是这么来的。现在已在 c-daniele/sch 公开。我需要的时候,AgentCore 会启动一个远程 harness,我可以从终端连上去。运行时干完活就终止;SCH 会保存状态,把改动带回本地工作副本或另一个分支。
架构设计上有一条原则:持久化应该落在检查点(checkpoint)里,而不是运行时(runtime)。只要仓库、agent 会话和 git 历史都能恢复,就没有理由让 microVM 一直跑着。SCH 目前还只是一个概念验证(proof of concept),保留了一些早期的设计决策,而且只能在 AWS 上运行。它的局限性我后面会讲。
比起 Claude Code on the web、Codex cloud 或 Copilot 的 coding agent,SCH 需要更多的配置工作。作为回报,仓库、会话、检查点和推理都留在我的 AWS 账户里,由我自己定义的 IAM 策略管控,也不会把我绑死在某一个 harness 或者服务商上。
我的工作流有哪些变化
SCH 把本地 CLI 和一个 ARM 镜像搭配起来,这个镜像在 AgentCore microVM 里运行 OpenCode、Claude Code 或 Pi。工作区状态存在 S3,改动通过 Git 回流,用不着的时候就把运行时删掉。
SCH 的三种用法:交接、工作台和批处理
下面的命令假设 SCH 已经部署完成。前置条件和首次部署参见 README 的快速上手部分。
1. 本地头脑风暴,交接出去,用手机盯进度
这是我处理正经活儿时最常用的模式。我先在笔记本上用 OpenCode 头脑风暴,直到目标、要改哪些文件、要跑哪些测试、什么算完成都定清楚。等上下文就绪、本地状态也适合启动任务时,我就把整段对话发到远程工作区,让 agent 接着做:
# Export the local OpenCode conversation, seed a branch from local HEAD,
# import the conversation remotely and start the headless task (implies --continue):
sch task my-project --handoff --branch change/plan-a \
"implement what we agreed, run the tests, fix what breaks"
#> a1b2c3... # returns immediately; laptop can go offline
# Any time later - reads S3, does not wake the microVM:
sch status my-project
#> state : succeeded
#> continuation : resumed prior session
#> checkpoint : confirmed
# The branch lands locally, fast-forward only; review at your pace:
sch fetch my-project
从现在起,笔记本可有可无。每个工作区在 Telegram 群里对应一个话题(topic),消息带 [workspace] 前缀。里程碑、待办清单更新、工具活动摘要、心跳失联告警,以及最后带检查点状态的任务结果,我都会收到。
无头任务按设计自动批准执行。交互式会话则多了一个中介式「分离模式」:会话启动后用 Ctrl+] 让它继续跑,agent 请求权限时,我手机上会收到「批准/拒绝」按钮。我的回复会送回 harness 钩子。如果十分钟内没响应(SCH_APPROVAL_TIMEOUT_S),就退回 harness 里配置的策略。在话题里输入自由文本,会通过 task --continue 变成后续提示词。我可以直接在手机上打一句「顺便把 README 也更新一下」,让 harness 接着干。

2. 隔离的 AWS 工作台
另一个场景是给主要用 AWS 服务的开发者准备一个隔离工作台。只要把合适的策略挂到 AgentCore Runtime 的 IAM 角色上,远程 harness 就能读取 CloudWatch 日志组、检查 IAM 策略、试做一个 Lambda、访问 DynamoDB 表,而不必继承工作站的凭据。
sch run aws-lab # fresh remote workspace, straight into the OpenCode TUI
sch web aws-lab # same backend, in a browser tab
sch acp aws-lab # same backend, from Zed over ACP
镜像里装了 AWS CLI、AWS MCP Server、AWS Documentation MCP Server 和常见开发工具。Bedrock 推理用的也是同一个执行角色。默认角色是 ReadOnlyAccess 加上调用 Bedrock 的权限:做 POC 很方便,但用于生产数据就太宽了,应该针对每个工作区收窄。会话结束,这个 microVM 就被销毁。
3. 跨多个 harness 与提供商的任务待办
第三个工作流,我从一批已经写好规格、测试和验收标准的任务开始。它们可以无人值守地运行,各自在自己的分支上,甚至换用不同的编码 agent:
sch task svc-a --branch change/a --harness opencode "implement change A per docs/specs/a.md"
sch task svc-b --branch change/b --harness claude "implement change B per docs/specs/b.md"
sch task svc-c --branch change/c --harness pi --model <bedrock-model-id> "port module C as planned"
sch dashboard # every workspace on one screen: task state, heartbeat age, checkpoint
sch fetch svc-a && sch fetch svc-b && sch fetch svc-c
工具(harness)在创建工作区时就固定下来了。默认走执行角色访问 Bedrock,但我也可以配置别的提供方,而不用把密钥塞进镜像或检查点里。每个并行会话各占一条分支,sch fetch 只接受快进式合并;真出了冲突,会在本地 git merge 时暴露出来。
运行(Run)与任务(Task)
交互式命令和无头命令提供的保证并不一样。
头脑风暴、探索各种可能方案时,我一般用交互式命令。等任务(一个或一组)定义得足够复杂,我就退出交互会话,改用 task,这样能腾出手做别的事,必要时还能把笔记本合上。完整命令一览见 README。
为什么 AgentCore 适合这套工作流
SCH 依赖 AgentCore Runtime 的四个特性。
每个会话相互隔离。 AgentCore 把每个会话跑在独立的 Firecracker 微虚拟机里,各自拥有内核、CPU、内存和文件系统。会话结束后,微虚拟机被销毁,内存也会清理干净。这样编码工具拿到的是一台用完即弃的机器:从已知镜像启动,与其他会话不共享任何状态。
权限通过 IAM 控制。 在虚拟机内部,CLI、SDK 和 MCP 服务器拿到的是运行时执行角色(execution role)的临时凭证。我可以授权调用 Bedrock、读取指定的 AWS API、写入某个 S3 前缀,而不用从笔记本上拷贝密钥。不过微虚拟机并不会让一个权限过大的角色变安全:真正的安全边界还取决于 IAM 策略和网络配置。
托管生命周期。AgentCore 会终止空闲会话。默认的 idleRuntimeSessionTimeout 为 15 分钟,最短可缩短到 60 秒;maxLifetime 将单个会话限制在 8 小时以内。忙碌中的会话会在健康检查时返回 HealthyBusy,从而避免计时器在 Agent 工作时打断它。8 小时的上限也迫使 SCH 必须支持检查点与重启机制。
适合 harness 运行的资源与启动速度。每个会话分配 2 个 vCPU 和 8 GB 内存;镜像必须是 linux/arm64,且不能超过 2 GB。这对我日常使用的编码 harness 和测试套件来说已经够用,但如果是特别重的构建任务,就需要换用别的运行时。实测下来,一个冷启动的 workspace 几秒内就能就绪,其中包括从 S3 恢复数据以及引导 harness。
CPU 只在真正运算时计费,而内存只要会话还活着就会持续产生费用。这种计费方式适合那种大部分时间都在等待 LLM 响应的进程,当然,等待也并非完全免费。具体数字在成本部分详述。
SCH 如何分离运行时与状态
整个架构分为三层:
-
Operator 层。sch CLI 可在 macOS、Linux 和 Windows 上运行,它把 AWS 调用委托给 aws CLI,因此能直接复用工作站上已经配置好的 AWS profile 和认证体系,包括 SSO 和外部凭据提供程序。
-
Runtime 层。每个 workspace 在 linux/arm64 微虚拟机中运行一个 harness。一个 Python shim 负责无头任务、就绪检测和检查点;带版本号的镜像里包含 OpenCode、Claude Code、Pi 以及各类开发工具。
-
Durability 层。SCH 使用了两套彼此独立的存储机制。L1 是 AgentCore 的会话存储,它让停止和恢复操作很快,但运行时版本一变就会重置,且闲置 14 天后过期。L2 使用带版本控制的 S3 存储桶,即便运行时被删除也能存活。如果 L1 为空,shim 会先从 L2 下载检查点并校验,然后才宣布 workspace 就绪。如果清单文件无法读取,恢复流程就会被阻断,避免 SCH 在已有数据之上初始化出一个空 workspace。
会话的生命周期是:sch shell → SigV4 调用 → microVM 启动 → L2 恢复 → harness 引导 → 工作 → 在停止或空闲时从 L1 到 L2 做检查点。下一条命令可以在新的 microVM 中从 L2 重启。
模型与供应商
镜像里每个 harness 都通过执行角色预先配置好了 Amazon Bedrock,因此默认用法无需任何外部供应商密钥。
要用其他供应商,SCH 只会把 ~/.sch/env 中明确列出的一组变量转发到运行时。shim 会把它们存放在一块不参与检查点的临时区域:密钥能到达 harness,但绝不会进入镜像或 S3。当工作区需要直接与 GitHub 交互时,同样的机制也能转发 GITHUB_TOKEN。
为什么默认用 OpenCode
这三个 harness 共享同一套基本的状态管理,但 SCH 是围绕 OpenCode 构建的,一些功能也反映了它的架构。同一个后端可以用本地 TUI 通过 sch attach 访问,用浏览器通过 sch web 访问,或用编辑器通过 ACP 和 sch acp 访问。Claude Code 可以通过一个适配器来配合 run、task 和 ACP 使用。Pi 最适合无头任务,目前在 SCH 中还不支持远程审批、替代界面或移交。
无头任务如何工作
提交后在不到一秒内返回一个 task_id,客户端随即关闭连接。shim 以无头模式启动 harness,并告诉 AgentCore 该会话正忙,这样空闲计时器在它工作时不会打断它。七小时的应用超时低于 AgentCore 的限制,也给 shim 留下足够时间记录结果、完成检查点。--model 选项可以更改单次调用的模型,选择结果会记录在状态里。
迁移代码:探索用同步,委派用 git
交互式会话我用文件同步;对于自主任务,git 原生模式更合适。
-
--sync .在本地和远端之间同步文件,默认排除.git。和智能体一起头脑风暴时我会用这个模式。 -
--branch <name>会用本地 HEAD 初始化工作区,并创建一个远程分支。工作完成后,sch fetch只以快进(fast-forward)方式把改动拉回来。这样,多个会话就能在各自独立的分支上并行工作,一旦出现冲突,会在本地git merge阶段暴露出来,仍由我掌控。
无论哪种模式,工作站的 git 凭据都不会被复制进去。代码包通过隧道的文件通道传输,远程 agent 不会主动推送,除非显式启用 GITHUB_TOKEN 直接访问 GitHub。
我最初并不打算开放任何对 GitHub 的直接访问。但这样一来就没法跟 GitHub Actions 和其他远程流水线交互,于是我把它改成按需开启:谁需要,就自己显式提供 GITHUB_TOKEN;否则,运行时依然只靠 Git 代码包工作。
大约十来天间断使用下来的成本
我从八月初就开始测试 SCH,但直到 8 月 28 日之前,使用都太零散,不足以反映我平时的流程。所以我把分析范围收窄到 2026 年 8 月 29 日到 9 月 9 日:一共 12 个自然日,其中 9 天有实际活动。
AgentCore 并没有发布类似“已用分钟数”的指标,所以我从 eu-west-1 区域 CloudWatch 的 AWS/Bedrock-AgentCore 命名空间里重建了用量数据。用 ActiveSessionCount 统计实际挂钟分钟数,用 CPUUsed-vCPUHours 和 MemoryUsed-GBHours 作为计费量。数据来自每日的 GetMetricData 查询,于 9 月 12 日导出,因此涵盖的每一天都是完整的。

计算中采用的价格是 每 vCPU 小时 $0.0895,只对实际用到的 CPU 计费;内存则是 每 GB 小时 $0.00945。内存按秒计费,依据会话到该时刻为止的峰值内存用量,最小计费量 128 MB。如果进程涨到 7 GB 后又把内存释放了,会话结束前计费值仍按 7 GB 算。
这些数字让我重新审视了 SCH 的优化优先级:
-
内存约占成本的 78%,CPU 约占 22%。编程代理大部分时间都在等模型响应。等待期间 CPU 不产生费用,但只要会话还活着,内存每秒都在计费。
-
闲置时间才是关键杠杆。SCH 会在无操作 15 分钟后停止会话,这个时间可以配置,从 60 秒到 8 小时都行。按大约 7.5 GB 内存算,每个因超时被终止的会话,那 15 分钟的尾巴要花掉约 0.018 美元;用
sch stop就能省下这笔钱。所以,缩短闲置超时和压缩内存占用,比优化 CPU 使用更有意义。
我拿这些数字和 at4g.large 做了对比,这是配置最接近的 EC2 规格,2 个 vCPU 加 8 GB 内存。在 eu-west-1 区域,它大约每小时 0.074 美元,再加上每月约 8.8 美元的 100 GB gp3 存储费用。同一时期内的对比如下:
实际使用的每一小时,AgentCore 大约贵 24%,0.092 美元对 0.074 美元。但按我这种间歇性的使用方式,会话之间不保留计算资源,让它比一台常开的虚拟机便宜大约七倍。按同样的费率折算到一个月,和一直开着的 t4g.large 相比,盈亏平衡点大约在每月 680 到 700 个会话小时。即便对比一台会认真关停的虚拟机,EBS 的固定成本也让 AgentCore 在每月约 490 个会话小时以下保持优势。这个计算还没算上打补丁的时间,以及难免有人忘了关虚拟机的情况。一个开发者或小团队每天用几个小时代理,离这些门槛还差得远。
这些数字是从 CloudWatch 指标里还原出来的,和 Cost Explorer 的汇总视图一致。在我的使用中,S3、日志和 Lambda 这些附带成本可以忽略不计。推理费用不在此列,而且往往占了大头,所以总成本主要取决于选了哪家提供商和哪个模型,而不只是运行时。
这算不上完整的基准测试:统计窗口很短,使用也是断断续续的,而且只覆盖了一个开发者。团队规模更大时,成本主要会随会话时长增长。AgentCore 的托管会话存储目前还是公开预览版,AWS 已经宣布正式版之前价格会调整。它现在还没有作为独立费用项显示,也不包含在 3.45 美元里。
为什么选 AgentCore 而不是其他方案
EC2 不是唯一的替代方案。Fargate、AgentCore Instances 和托管型 agent 各自解决同一问题的不同部分。
ECS Fargate。 Fargate 也能缩容到零,对这类工作负载价格区间也差不多:按 eu-west-1 的 ARM 费率,我这些 37.5 个会话小时估算下来,1 vCPU 大约 2.3 美元,2 vCPU 大约 3.5 美元,而 AgentCore 是 3.45 美元。所以价格并不是 SCH 的决定性因素。用 Fargate 的话,我得自己搭每会话寻址、空闲超时、忙碌信号、工作区存储和带认证的调用。这些基础能力 AgentCore 已经提供了,而且因为 microVM 是预先初始化好的,在我的测试里工作区几秒就能恢复。我没有做并排对比测试:这个比较是把服务文档和一次 AgentCore 的实测结果放在一起看。
AgentCore Instances。 这项服务也提供运行在你 AWS 账户中、由 AWS 管理的 EC2 实例上的 agent。你需要为实例、管理费和 EBS 存储付费,即使机器已经停止也要付存储费;作为交换,会话最长可以持续 14 天。这个选项更适合超过八小时或者需要保留大量本地状态的工作负载。对 SCH 来说,我反而更喜欢八小时的上限,因为它能强制频繁做检查点。
托管型智能体。Claude Code 网页版、Codex 云端版,以及 Copilot 的编码智能体,已经能让你合上笔记本、少折腾环境配置。而 SCH 满足的是我另一类需求:把代码仓库、会话、检查点和推理过程都留在自己的 AWS 账号里,受我自己定义的 IAM 策略管辖,同时还能自由选择执行框架和模型供应商。SCH 目前走的是带公网出口的网络。AgentCore 本身也支持 VPC、安全组、私有端点和 PrivateLink 入站,只是这套配置我还没在 SCH 上验证过。
今天哪些人可能用得上
-
在 AWS 上干活的开发者:想通过执行角色(execution role)用 Bedrock,沿用
awsCLI 的凭证链,并且限定这次部署能访问哪些模型和 API。 -
跑长时间、断断续续任务的人:比起让服务器 7×24 小时开着,他们更愿意用检查点和分支。
Ctrl+]、sch status、每个分支一个会话,再加上sch fetch,就能覆盖这套流程。 -
有标准化要求的开发团队:不想每个开发者一套配置。一份共享镜像里可以预置好经过审批的执行框架、模型、MCP 服务器、技能和插件。
团队场景目前还需要验证,这里并不是在推荐企业采用。SCH 只是把智能体的运行环境集中起来,它并不判断智能体的行为是否正确。就算跑在 microVM 里,给执行角色开过大的权限依然危险。Telegram 也只是我个人工作流里一个顺手的接入方式,不会是我建议当作公司标准的控制平面。
局限
-
概念验证阶段的约束。 SCH 假定单账号信任模型,默认角色的权限范围也偏大。部分 AgentCore API 还在预览阶段;会话存储有自己的限制,每个运行时最多接受 10 个并发交互式 shell,WebSocket 通道还有帧率和速率的配额。这些约束都写进了仓库,作为安全说明或规格约束记录下来。
-
不包含在内的成本。 ECR、存储桶和镜像仓库在会话间隔期间也可能产生费用。推理费用不包含在 3.45 美元里,而且往往是最大的一笔开销。会话存储只在预览期免费。运行时版本变更或 14 天后过期都会重建微虚拟机;L2 会从检查点恢复,但最后未保存的几秒会丢失。
-
各执行框架之间的差异。 在 SCH 里,Pi 没有审批通道,也没有
web、attach、acp、handoff模式,更没有 MCP 集成。Claude 的 JSONL 转录记录会不断累积,所以七小时超时也间接限制了转录文件的增长。OpenCode 依然是支持最完整的执行框架。 -
对 AWS 的依赖。 SCH 通过
awsCLI 直接调用 AWS 服务和 API。项目明确表示,多云抽象不是它的目标。这套架构模式可以移植到别处,但当前实现会把你锁定在 AWS 上。 -
只有一名维护者。 项目目前全靠一个人,所以它的持续性和维护节奏无法与有商业支持的产品相比。仓库里的规格说明和端到端检查能降低风险,但无法完全消除。
接下来要做什么:更精简的镜像、护栏、VPC 和身份
接下来的计划,大致按优先级排序:
-
在更大的团队中试用。 我想验证镜像仓库、按所有者隔离工作区,以及真正的 SSO,看看共享镜像在多名开发者使用时是否可行。
-
更精简的镜像。 内存约占成本的 80%,所以减少内存占用是首要的成本优化方向。
-
按工作区设置成本护栏。 目前我用任务超时、模型白名单和
sch stop来控制;按工作区设置的预算和告警还没有。 -
私有部署。 我需要验证 VPC 网络模式和 PrivateLink 在调用链路上的表现。
-
身份透传。 现在每个会话都在单一执行角色下运行。我希望会话能代入调用它的开发者身份,并保留该开发者的权限。AgentCore Identity 和 STS 会话标签可能是解决方案的一部分,但我还没设计好。
这个模式并非 AWS 专属:每个会话一个沙箱、检查点存放在对象存储、用云身份作为权限边界。不过,想移植到其他云就得重写 shim 和基础设施,这不在当前路线图的计划内。
完整的源代码、规格文档、架构图和验证脚本都在 c-daniele/sch。
想试试的话,可以从 sch run aws-lab 开始,它会创建一个用完即弃的工作台,然后在一个你可以随时丢弃的分支上跑 sch task --branch。最有价值的问题反馈请附上 sch status 的输出,尤其是恢复过程中的竞态问题和审批超时的情况。
参考资料
-
SCH - Serverless Coding Harness: https://github.com/c-daniele/sch
-
Context engineering(Lütke、Karpathy,2025 年 6 月),由 Simon Willison 整理:https://simonwillison.net/2025/Jun/27/context-engineering/
-
Geoffrey Huntley,Ralph Wiggum as a "software engineer":https://ghuntley.com/ralph/
-
Addy Osmani,Loop Engineering:https://addyosmani.com/blog/loop-engineering/ · Armin Ronacher,The Coming Loop:https://lucumr.pocoo.org/2026/6/23/the-coming-loop/
-
LangChain,3 Years of Graph Engineering with LangGraph:https://www.langchain.com/blog/3-years-of-graph-engineering-with-langgraph · The Anatomy of an Agent Harness:https://www.langchain.com/blog/the-anatomy-of-an-agent-harness
-
OpenAI,Harness engineering: leveraging Codex in an agent-first world:https://openai.com/index/harness-engineering/ · Anthropic,Harness design for long-running application development:https://www.anthropic.com/engineering/harness-design-long-running-apps · Birgitta Böckeler,Harness engineering for coding agent users:https://martinfowler.com/articles/harness-engineering.html