用 Modal 和 OpenAI Agents SDK 构建
Building with Modal and the OpenAI Agents SDK
OpenAI 发布 Agents SDK 后,Modal 示例用其构建 coding agent harness,接入 Modal Sandboxes 与 GPUs,面向 Parameter Golf 实验。方案包含 Sessions 记忆、orchestrator/subagents、async SubAgentPool、GPU quotas、Filesystem Snapshots 和 Skills plugins,并提供完整 GitHub 项目代码。
新闻
2026 年 4 月 15 日 • 8 分钟阅读
今天,OpenAI 发布了他们的 Agents SDK,这是一个用于构建 agent harness(agent 运行框架)的强大工具,适用于 coding、deep research 等场景。
Internal agents 是一个新兴话题,像 Ramp 这样的公司正在 Modal 上构建一组后台 coding agents,它们现在已经负责创建超过一半的 PR。
虽然许多企业已经开始熟悉 Codex、Claude Code 和 OpenCode 这类现成的 agent harness,但仍有不少团队在思考,如何像 Ramp 那样定制这些 agents,并将它们构建成功能强大的内部工具。
我们很高兴看到 OpenAI Agents SDK,因为我们认为它为团队在内部构建自己的 agentic systems 提供了合适的基础模块。这个 SDK 可以通过 sandbox extension 很自然地接入 Modal,让 agents 拥有一台可工作的“主机”,并且配备了真正利用 Modal 规模化能力所需的工具。
今天我们会展示如何基于 OpenAI Agents SDK,从零开始构建一个自定义 agent harness。我们会集成 Modal Sandboxes,为这些 agents 提供可运行的计算环境(甚至是 GPUs)。到最后,我们将得到一个通用的 coding harness,能够在后台大规模并行处理任务。

我们的示例会使用 OpenAI 的 Parameter Golf 挑战。该挑战要求参与者用尽可能少的参数,达到一个基准智能阈值。我们的 agent harness 将能够处理这个任务,并将其并行分发给许多运行在 GPUs 上的 subagents;每个 subagent 都会进行 coding 和 training,目标是发现新的高效 SOTA 方法。
我们会在过程中分享相关代码块作为示例,但你也可以随时参考完整项目代码。
从最基础的 coding agent 开始
首先,我们会用 OpenAI Agents SDK 构建一个最小化的 coding agent。这种做法并不安全,也不推荐,但为了简化说明,我们从这里开始。
一个 Agent 本质上是一个带有 LLM 的 for-loop,它会运行 tools(函数)直到任务完成。围绕核心 Agent 循环构建的一组 tools 和 state,通常被称为 “Harness”。
最简单的 coding agent 是一个拥有 exec(command) 函数的 agent,它可以调用该函数在宿主机上运行任意 shell command:
虽然简单,但如果遇到恶意 prompt 或低质量模型,这很快可能演变成安全灾难。
将 agent 移入 Sandbox
Sandboxes 是构建在 VMs 或经过安全加固的 containers 之上的隔离 Linux 环境。我们可以通过在这个环境中运行 exec command,让它更安全;实际上是让 LLM 看到 sandbox,而不是我们的宿主机。
OpenAI Agents SDK 提供了一个方便的 SandboxAgent class,它是 Agent 的超集,预置了可连接到远程运行 sandbox 的 tools。它还提供了一个 ShellTool class,为我们的 commands 增加额外 guardrails。在底层,它管理一个 ModalSandboxSession,也就是远程 sandbox 的 client。
这些 sandbox tools 的一个主要区别在于,它们现在是有状态的,绑定到某个特定的 ModalSandboxSession 实例。因此我们定义了一个 Capability,用于将一组 tools 绑定到一个实例上。
我们还希望给 sandbox 挂载 GPUs,这是 Modal 独有的能力。我们可以使用 ModalSandboxClientOptions 为 sandbox 请求 GPUs。
用 One-Shot prompt 训练 MNIST
现在,我们的 agent harness 已经具备 sandbox capability 和 shell tool,完全能够端到端运行一个 coding task。让它在 MNIST dataset 上训练一个 image model 吧!
开箱即用,这应该就能正常运行。
构建最终版 harness
Harness 是 agent loops 周围的一切,它为 agents 提供所需的 context 和 tools。构建 harness 有点像 product engineering,因为作为程序员,你可以完全控制它。OpenAI Agents SDK 让围绕核心 agent loop 构建额外 capabilities 变得很容易。
接下来,我们会逐步给 harness 添加新功能,直到它能够稳定运行 Parameter Golf experiments。
使用 Sessions 添加 Memory
默认情况下,Agents 是无状态的。run method 接收 string context,并返回 string output。如果你把一个默认 agent 放到带有用户 prompt 输入的循环中,模型_不会_看到累积的对话。
Sessions 是我们的解决方案——它们是可以在多次 agent runs 之间传递的对象,用于累积 context window;可以跨多个 user prompts,甚至如果你愿意,也可以跨 agent instances。
让我们在 run 中加入 session:
在解决多轮 memory 的同时,我们引入了一个新的挑战:context management 和 context rot。既然 memory 会无限累积,我们就需要更聪明地控制和重置它。
接下来我们做的大部分工作,都会聚焦于_保护_我们的主工作线程,避免 context bloat。
添加 Subagents,用于更高层规划和 context delegation
Coding agents 在探索和修改 codebase、摄入 stdout/stderr 时,可能会消耗大量 tokens。这类 agent 的有效生命周期很短。
为了支持 long-horizon work,我们将 agent 拆成两个 agents:一个 orchestrator 和一个 subagent。
o0ddm_4o_c267737c.webp)
Orchestrator 是我们的主 chat agent,它会为整个任务累积 memory。它有一个 tool——invoke_subagent——而这个 tool 本身就是一个拥有全新 context window 和 Session 的 agent。这样,工作就可以被拆分成短时间的任务片段;orchestrator 只关注高层细节,而 subagents 会被创建出来处理短暂且聚焦的任务,并在任务完成后丢弃它们的 session memory。
任务描述输入进去后,subagent 会返回已完成工作的摘要,从而保持 orchestrator 的 context 精简,并且不关心实现细节。
使用 Subagent Pool 让它 async 并行运行
与其让 subagent runs 阻塞并暂停 orchestrator,我们可以通过让 orchestrator 使用 worker pool 管理_多个_并行 subagents,来提高 experiment throughput。
我们实现了一个 SubAgentPool class,它是一组 active subagents 的 key:value 集合,并将其挂载到 orchestrator instance 上。借助它,我们可以修改 invoke_subagent,让它改为存储一个 asyncio.Future,并暴露新的 tools,使 orchestrator 能够选择性地等待特定工作线程完成:
现在 orchestrator 默认不再阻塞,我们需要让 orchestrator 能够看到 subagents 中正在发生什么。
我们通过两种方式实现这一点:使用 Hooks 跟踪每个 subagent 当前 active tool;并添加一个 set_status tool,让 subagent 可以周期性更新自身状态,而不必完全退出并返回 orchestrator。
这些 subagent fields 会通过 list_subagents tool 暴露给 orchestrator:
为了避免 orchestrator 在 async tasks 完成前退出,我们做了大量“鼓励”。未来的改进可以作为读者练习:实现一个特殊的 “self thought” tool 或 subagent,让 orchestrator 在等待 subagent results 或提前退出之外,有一个用于思考/规划的有效出口。
使用 quotas 限制 GPU 开销
有了 async tasks 后,我们等于把一种潜在昂贵的能力交给了 LLM:它可以启动无限数量的 GPU subagents。我们可以简单地为 subagent pool 添加 quota system,确保同时使用的昂贵 8x H100s 数量有固定上限。
现在我们可以并行训练 MNIST
既然 orchestrator 可以管理并行工作,我们就用类似下面的 prompt,尝试在不同 backends 上并行化 mnist:
Orchestrator 访问 coding environments 的唯一方式,是通过它的 async subagent spawn interface。因此,它会很自然地为三个 ML frameworks 分别启动三个并行 subagents。
使用 Filesystem Snapshots 去重工作
现在,我们可以开始把 Parameter Golf 的 context 放进 prompt 里。
但我们很快遇到了另一个挑战!
由于所有 subagents 都从基础 sandboxes 启动,它们会浪费宝贵的 GPU 时间做相同的 setup work:拉取 repo、安装 dependencies。对于更长周期的任务,你可以想象出各种“checkpoint”时刻:你会希望存储 sandbox state,让未来全新的 subagents 可以从该位置开始。
我们添加了 Filesystem Snapshots,将一个 active sandbox session 冻结成一个 ID,orchestrator 之后可以将其作为新 subagent 的 starting image,从而允许它从已知 checkpoint 分支出新的工作。
除了节省时间,filesystem snapshots 的另一个好处是 context management。Filesystems 可以用来卸载 memory!
就像我们在 Session state 中保持 context hot 一样,live sandbox 的 filesystem 在通过 shell tools 查看时,也充当了一种隐式 memory。
有状态 filesystem 让先前 agent 产生的 artifacts 可以被所有未来 agents 使用,即使未来 agents 的 context Sessions 中没有显式加入这些内容。这种 on-disk memory 可以显式实现,例如写入 skills/memory files;也可以隐式存在,因为 codebase 已经被整理到可工作的状态。
现在,orchestrator 可以推进工作线程,snapshot 该 filesystem,然后把新的 subagents 放入这个 snapshot,并提供基本的后续指令。subagent 将很快掌握情况并继续工作,而不需要携带导致当前状态的那段工作所产生的 context bloat。
添加 skills subsystem
为了高效运行 Parameter Golf,我们的最后一步是 prompting!
目前,想让 orchestrator 有效使用它的 async research tools,并理解我们交给它的具体 Parameter Golf 挑战,需要大量 prompting。我们可以把这些 prompts 加进核心 harness,但为了保持 harness 的通用性,我们改为给 orchestrator 提供 tools,让它通过一组 Skills plugins 选择性地加入这些 context。
我们现在已经在 GPUs 上构建了并行自动研究系统!
我们从一个基础的、本地执行的 agent loop 开始。用远程 sandboxes 保障其安全。用 async workers 扩展其规模。并为它提供可插拔 skills,使其能够并行、自主地运行 Parameter Golf research。
运行方式:
如果你只从这篇博客中带走一件事,那就是:你可以在基础 agent loops 之上_组合_系统,让它适配你的任务。
在我们的例子中,我们构建了一个 harness:它让 orchestrator 的 context 保持精简,并充分利用 Modal sandbox platform 的并行能力。得益于 OpenAI Agent SDK,所有这些都变得非常简单且易于组合。构建这个项目的过程很有意思,我们也希望你能从中获得灵感,构建自己的东西!
在构建过程中,记得参考完整示例 repo。当你需要 sandboxes 和 GPUs 时,可以注册 Modal,并获得 $30 免费额度来开始构建。