告别AI代码“监工”:Symphony革新人机协作流程
写在前面:
您是否曾有过这样的经历?当您作为AI驱动开发的重度用户,本想借AI之力简化编码过程,结果却发现自己一整天都在监督它:时而纠正其错误,时而补充其上下文,时而重写提示词,时而还要检查其生成的代码是否存在缺陷;尤其是在同一工具内开启多个对话时,您会发现不同对话的上下文并未被有效保存和共享,新开启一个对话就得重新扫描整个项目,这无疑是在浪费宝贵的Token,也就是在浪费金钱。有没有更好的方法来解决这个问题呢?Codex最近发表了一篇文章,阐述了他们的解决方案,并开源了一个工具,您可以尝试一下,看看它能否解决您的困扰。
坦白说,如今开发者在使用AI进行开发的过程中,心情可谓是爱恨交织。像我这样每天在电脑前工作十多个小时的人,感觉AI似乎变得更强大了,但效率的提升却并非那么显著。尤其是在看到Token消耗的账单,或者仅仅是使用AI修改一个非常简单的问题时,您会感到格外烦躁。您甚至会萌生出彻底抛弃AI工具,回归“传统编程”的念头。有这种想法的并非您一人,这也不完全是AI能力不足的问题。当前AI编程面临的最大瓶颈,已悄然从“模型能写多少代码”转变为“人类能监督多少AI”。OpenAI的工程师们曾进行过测试:一个人最多只能同时管理3到5个AI编码会话,再多就会因为频繁的上下文切换而彻底崩溃。
我们都沦为了AI的“监工”,想想看,我们现在是如何使用AI来写代码的:
开启一个新的AI会话,输入一段详尽的提示词来描述需求,等待AI生成代码,然后检查代码是否存在问题,若有问题,再输入提示词让它修改,如此循环往复,直到代码可用为止。
一个AI尚可。但如果您的项目需要修复10个bug,添加20个小功能呢?您就会变成一个手忙脚乱的“AI保姆”:同时开启五六个终端窗口,每个窗口里都有一个AI在工作,您需要一一喂给它们提示词,一一检查它们的输出,一一处理它们遇到的问题。
更糟糕的是,AI不会自动停止。它可能会在一个错误的道路上越走越远,直到您发现并纠正它。这意味着您必须时刻盯着它,不能有丝毫分心。其结果是,AI确实在帮您写代码,但您却比以前更加疲惫。
1. OpenAI的解决方案:Symphony
面对这个让所有人头疼的问题,OpenAI并没有选择开发一个更大的模型,也没有设计一个能同时显示20个窗口的仪表盘。他们采取了更为根本的措施:彻底重塑了人与AI之间的协作流程。
这个方案名为Symphony,已在GitHub上开源。它并非一个新型的对话式编程助手,也不是一个IDE插件。它更像是一个“AI自动化调度中心”,让AI能够自我管理,而您只需负责最终的验收工作。
Symphony的核心理念非常简单:停止对AI的监督,让AI主动从您的任务看板上领取工作。
2. Symphony的工作原理
Symphony的工作流程与您当前的开发流程几乎一致,只是将中间最耗费精力的环节实现了自动化:
您像往常一样在任务看板上创建任务,在会话中清晰地描述您要完成的工作:例如,“修复用户登录时的密码错误提示”、“为商品列表添加分页功能”。无需撰写复杂的提示词,直接使用您平时与团队沟通的语言即可。
Symphony自动发现新任务
Symphony会定期轮询您的任务看板。当它检测到标记为“待处理”的任务时,便会自动为该任务创建一个完全独立的沙盒工作空间和一个独立的Git分支。
AI在沙盒中独立完成任务
Symphony会启动一个Codex AI智能体,让它在这个隔离的沙盒环境中进行工作。AI会自行理解需求,自行编写代码,自行运行测试,自行解决遇到的问题。整个过程无需您的任何干预。
AI提交“工作量证明”
这是Symphony最令人称道之处。AI完成代码编写后,并不会直接将代码交给您。它会自动生成一套完整的“工作量证明”,包括:
所有单元测试和集成测试的运行结果,代码审查意见和复杂度分析
代码变更的详细说明,甚至还有一个代码演示视频,展示其编写的代码如何工作。您只需进行最终验收,当所有测试通过,所有准备工作完成后,AI会自动创建一个Pull Request。您只需审阅AI提交的“工作量证明”,若无问题,点击批准即可,代码便会自动合并到主分支。
3. 为什么Symphony能够解决问题?
Symphony与其它AI编程工具最显著的区别在于,它改变了人与AI的关系:
从“同步监督”转变为“异步验收”:您无需坐在电脑前盯着AI工作,它会自行运行。您可以在任何方便的时间来检查结果。
从“管理AI会话”转变为“管理工作任务”:您无需关心有多少个AI正在运行,它们在哪个分支上工作。您只需关注任务是否完成,质量是否达标。
从“人适应AI”转变为“AI适应人”:您无需学习如何撰写完美的提示词,也无需改变您的工作习惯。AI会适应您已在使用的工具和流程。
OpenAI的内部团队在使用Symphony后,效果惊人:在前三周内,部分团队的Pull Request数量就增长了500%。这并非因为AI写代码的速度变快了,而是因为一名工程师现在可以同时管理几十个AI任务,而非只能管理3到5个。
4. 如何开始使用Symphony?
Symphony目前处于工程预览阶段,采用Apache 2.0开源协议。您可以在GitHub上找到官方的Elixir实现,也有社区贡献的TypeScript版本。
最简单的上手方式是:
克隆官方仓库:https://github.com/openai/symphony
按照README中的说明配置您的Linear或GitHub Issues账号
运行启动脚本
在您的任务看板上创建一个任务,并标记为“Todo”
等待Symphony自动处理
需要注意的是,Symphony目前最适合在拥有良好测试覆盖的代码库中使用。如果您的项目缺乏自动化测试,AI就无法验证自身编写的代码是否正确,您仍需手动检查。
5. 结语
AI编程的发展速度令人惊叹。一年前,我们还在为AI能补全一行代码而赞叹不已;如今,AI已经能够独立完成整个功能。然而,随着AI能力的提升,我们也面临着新的挑战:如何高效地管理和利用这些AI能力。
Symphony为我们提供了一个极佳的答案:不必试图去监督AI的每一个细微动作,而是要构建一个系统,让AI在这个系统中能够可靠地运行,而人类只需在最高层面进行决策和验收。
我最近确实非常厌倦充当AI的“监工”,有时给Codex下达一个任务,一会儿又得回去查看它改得如何了。最近,我打算尝试Symphony,并撰写一篇评测,看看它是否能达到原文所描述的效果。
6. 文章链接和原文
链接:
https://openai.com/index/open-source-codex-orchestration-symphony/
7. AI直译内容,供参考
作者:Alex Kotliarskyi、Victor Zhu、Zach Brock
收听本文 13:57 分享
六个月前,在开发一款内部生产力工具时,我们团队做出了一个在当时颇具争议的决定:我们将完全不编写任何人工代码来构建代码库。项目仓库中的每一行代码都必须由Codex生成。
为了实现这一目标,我们彻底重新设计了工程工作流。我们构建了对代理友好的代码仓库,大力投入自动化测试和防护机制,并将Codex视为一名正式的团队成员。我们在之前关于工程harness技术的博客文章中记录了这一历程。
这一尝试取得了成功,但随后我们遇到了下一个瓶颈:上下文切换。
为了解决这个新问题,我们构建了一个名为Symphony的系统。Symphony是一个代理编排器,它能将Linear这类项目管理看板转变为编码代理的控制平面。每个待处理任务都会分配一个专属代理,代理会持续运行,最终由人类审核结果。
本文将介绍我们如何创建Symphony——它使部分团队的合并拉取请求数量提升了500%——以及如何使用它将您自己的问题跟踪器转变为全天候运行的代理编排器。
尽管编码代理的使用门槛越来越低,但无论是通过网页应用还是命令行界面访问,它们本质上仍然是交互式工具。
随着OpenAI内部代理工作规模的扩大,我们发现了一种新的负担。每位工程师需要打开多个Codex会话、分配任务、审核输出、引导代理,然后重复这一过程。在实际操作中,大多数人最多只能同时舒适地管理3-5个会话,超过这个数量后,上下文切换就会变得非常痛苦。再往后,生产力会急剧下降:我们会忘记哪个会话在做什么,在多个终端之间跳转来让代理回到正轨,还要调试中途卡住的长时间运行任务。
代理的速度很快,但我们遇到了系统瓶颈:人类注意力。我们实际上组建了一支能力极强的初级工程师团队,却让我们的人类工程师去做微观管理他们的工作。这种模式无法规模化。
我们意识到自己优化错了方向。我们一直在围绕编码会话和合并的PR来构建系统,但PR和会话其实只是达成目的的手段。软件工作流本质上是围绕可交付成果组织的:问题、任务、工单、里程碑。
于是我们问自己:如果我们不再直接监督代理,而是让它们从我们的任务跟踪器中主动拉取工作,会发生什么?
这个想法催生了Symphony——一份作为监督者来编排代理工作的书面规范。
Symphony源于一个简单的理念:任何待处理的任务都应该由代理自动接手并完成。我们不再需要在多个标签页中管理Codex会话,而是将问题跟踪器变成了控制平面。
在这种架构下,每个打开的Linear工单都对应一个专属的代理工作区。Symphony会持续监控任务看板,确保每个活跃任务都有一个代理在循环运行,直到任务完成。如果代理崩溃或卡住,Symphony会重启它;如果有新任务出现,Symphony会立即接手并开始组织工作。
我们基于工单状态构建了工作流,将任务管理工具Linear用作状态机。
编码代理将Linear作为状态机与我们协同工作。
在实际应用中,Symphony将工作与会话、拉取请求解耦。有些问题会跨仓库产生多个PR,而有些则是纯粹的调查或分析工作,根本不会触及代码库。
一旦工作被这样抽象化,工单就可以代表更大的工作单元。
我们经常使用Symphony来编排复杂的功能开发和基础设施迁移。例如,我们可能会提交一个任务,要求代理分析代码库、Slack或Notion中的信息,并生成一份实施计划。当我们对计划满意后,代理会生成一棵任务树,将工作分解为多个阶段并定义任务之间的依赖关系。
代理只会开始处理未被阻塞的任务,因此执行过程会自然且最优地以并行方式展开,形成一个有向无环图(DAG)。例如,我们将React升级标记为依赖于Vite迁移。正如预期的那样,代理只有在Vite迁移完成后才会开始升级React。
代理还可以自己创建工作。在实施或审核过程中,它们经常会发现超出当前任务范围的改进点:性能问题、重构机会或更好的架构。当这种情况发生时,它们只需提交一个新工单,我们可以在之后评估并安排时间——这些后续任务中的许多也会被代理自动接手。虽然我们会监督这一过程,但代理会保持工作的条理性并推动其向前发展。
这种工作方式极大地降低了启动模糊任务的认知成本。如果代理做错了,那仍然是有用的信息,而我们付出的成本几乎为零。我们可以非常低成本地提交工单让代理去做原型设计和探索,然后丢弃任何我们不喜欢的结果。
由于编排器运行在开发服务器上且永不休眠,我们可以从任何地方添加任务,并知道代理会接手它。例如,我们团队的一位工程师在一个网络很差的舒适小屋里,通过手机上的Linear应用完成了三项重大变更。
在观察使用Symphony工作的效果时,最明显的变化是产出量。在OpenAI的部分团队中,我们看到合并的PR数量在前三周内增加了500%。在OpenAI之外,Linear创始人Karri Saarinen也提到,随着Symphony的发布,创建的工作区数量出现了激增。然而,更深层次的转变是团队对工作的思考方式。
当我们的工程师不再需要花费时间监督Codex会话时,代码变更的成本结构发生了彻底改变。由于我们不再投入人力来推动实施本身,每次变更的感知成本大幅下降。
这改变了我们的行为。在Symphony中启动探索性任务变得轻而易举:尝试一个想法、探索一次重构、验证一个假设,只保留那些看起来有前景的结果。
它还扩大了能够发起工作的人员范围。我们的产品经理和设计师现在可以直接向Symphony提交功能需求。他们不需要检出代码库或管理Codex会话,只需描述功能,就能收到一份包含功能在真实产品中运行的视频演示的审核包。
Symphony在大型单体仓库(比如OpenAI内部使用的那个)中也表现出色,在这些仓库中,合并PR的最后一步往往缓慢且脆弱。该系统会监控CI流程、在需要时进行变基、解决冲突、重试不稳定的检查,并全程引导变更通过流水线。当工单到达“合并”状态时,我们有很高的信心认为变更会在无需人工干预的情况下进入主分支。
Symphony实施前后对比实施Symphony后,我们将更多工作委托给代理,专注于更困难、更具探索性的任务。
在这个级别上运行也存在权衡。当我们从交互式引导代理转变为在工单级别分配任务时,我们失去了在执行过程中不断微调并在需要时纠正方向的能力。有时代理会产出完全偏离目标的结果。但这也是有用的——这些失败暴露了系统中的漏洞,并帮助我们使其更加健壮。
我们没有手动修补结果,而是添加了防护机制和技能,以便代理下次能够成功。随着时间的推移,这促使我们为harness添加了新功能,比如运行端到端测试、通过Chrome DevTools驱动应用以及管理QA冒烟测试。我们还显著改进了文档,并明确了“好”的标准是什么。
并非所有任务都适合Symphony的工作方式。有些问题仍然需要工程师直接使用交互式Codex会话,尤其是那些模糊不清或需要强大判断力和专业知识的工作。实际上,这些通常是我们的工程师最感兴趣和最享受的任务。
不同之处在于,Symphony可以处理大部分常规实施工作。这让工程师能够一次专注于一个难题,而不是不断在小任务之间切换上下文。
我们还了解到,将代理视为状态机中的刚性节点效果不佳。模型变得越来越智能,能够解决比我们试图限制它们的范围更大的问题。我们早期的代理工作只要求Codex实施任务,这种方法被证明过于局限。Codex完全有能力创建多个PR,以及阅读审核反馈并解决问题。因此,我们为它提供了工具——gh CLI、读取CI日志的技能等——现在我们可以要求Codex做更多事情,比如关闭旧PR或生成已完成与已放弃工作的报告。这些类型的任务远远超出了最初的功能实施范围。
因此,我们最终转向了给代理分配目标而不是严格的转换规则,就像优秀的管理者会给团队成员分配目标一样。模型的力量来自于它们的推理能力,所以给它们工具和上下文,让它们自由发挥。
当你打开Symphony代码仓库时,你会注意到的第一件事是,Symphony从技术上讲只是一个SPEC.md文件——一份对问题和预期解决方案的定义。我们没有构建复杂的监督系统,而是定义了问题和预期解决方案,为代理提供高层引导
(完整规范内容见原文,此处为节选)
参考实现是用Elixir编写的——因为当代码实际上变得免费时,你终于可以根据语言的优势来选择它们,比如Elixir的并发能力——但核心思想可以用一个简单的Markdown文档来表达。我们鼓励你让你最喜欢的编码代理阅读这份规范,让它实现自己的版本。
Symphony的第一个版本只是一个在tmux中运行的Codex会话,轮询Linear并为新任务生成子代理。它能工作,但不是特别可靠。第二个版本存在于我们的主项目仓库中,该仓库是为代理设计的。我们已经构建了代理harness,为代理提供在这个仓库中高质量工作所需的技能和上下文,因此Symphony只是将它们连接起来。
一旦基本功能存在,我们就使用Symphony来构建Symphony。
当我们内部演示这个管理任务并附上工作证明视频的系统时,反响非常积极:我们的Symphony项目频道迅速壮大,公司内部的团队开始自发地使用它。在OpenAI,内部产品市场契合度是对外发布的先决条件。基于我们在OpenAI内部看到的使用情况,我们清楚地意识到应该将Symphony分享给公司以外的人。
因此,我们将这个想法提取到一个独立的SPEC.md文件中,并要求Codex实现它。对于参考实现,我们选择了Elixir——一种相对小众但拥有出色的并发进程编排和监督原语的语言。Codex一次性构建了Elixir实现,然后我们从那里不断迭代规范和实现。为了完善规范,我们甚至要求Codex用其他几种语言实现它——TypeScript、Go、Rust、Java、Python——并利用这些结果来识别歧义并简化系统。它在每种语言中都取得了成功。
在构建Symphony的过程中,我们消除了很多偶然的复杂性,比如对特定仓库或Linear MCP的依赖。Symphony不再依赖我们的内部仓库或工作流。核心方法变得非常简单:
对于每个待处理任务,保证有一个代理在其自己的工作区中运行。
除了帮助完成活跃工作外,开发工作流现在也成为了代理了解并遵循的东西。开发工作流——处理一个问题、检出仓库、将其标记为“进行中”以便产品经理知道它正在被处理、添加PR、将其移至“审核”状态、附上视频等——现在被记录在一个简单的WORKFLOW.md文件中。所有这些都是人类曾经遵循的过程,但从未被记录下来。我们现在不再依赖这套隐含的步骤,而是将其文档化,Symphony确保代理遵循它。这让我们能够构建与我们并肩工作的代理。如果我们决定代理还应该在完成的工作上附上自我反思,我们只需将其添加到WORKFLOW.md中,Symphony就会引导代理完成这一步。
我们还使用了Codex的应用服务器模式——Codex内置的无头模式。这种模式允许我们运行Codex,并通过一个文档完善的JSON-RPC API以编程方式与它通信,用于启动线程或响应回合等操作。这比尝试通过CLI或实时tmux会话与Codex交互更加方便和可扩展。
Codex应用服务器非常适合我们的用例:我们利用了Codex提供的harness,同时拥有可以插入的旋钮和钩子。例如,为了避免将Linear访问令牌暴露给子代理,我们使用动态工具调用来暴露原始的linear_graphql函数,该函数可以对Linear执行任意请求,而无需依赖MCP或将访问令牌暴露给容器。
Symphony是一个有意设计得极简的编排层。我们将其开源,是为了展示Codex应用服务器与Linear等不同工作流工具结合使用时的强大功能。因此,我们不打算将Symphony作为独立产品进行维护。可以将其视为一个参考实现。就像许多开发者让他们的编码代理阅读工程harness技术的博客文章来搭建他们的仓库一样,我们希望你让你最喜欢的编码代理阅读Symphony规范和代码仓库,构建适合你自己环境的版本。
真正的力量来自于Codex及其应用服务器。Symphony只是将我们已经在使用的Codex和Linear连接起来,以解决工作管理问题的一种方式。随着编码代理在推理和遵循指令方面变得越来越好,我们怀疑其他公司的瓶颈也将从编写代码转向管理代理工作。令人兴奋的是,现在实验这些编码代理系统的门槛低得惊人。你可以直接用Codex来构建东西。
我们很高兴看到工程社区在发布后的几周内就开始使用Symphony,截至4月23日,它已在GitHub上收获超过15000颗星标。