像Claude Opus 4.8这样的前沿模型可以驱动跨语言的智能体编程,从Python到C++再到GDScript;但在生产规模下,它们的每token成本会迅速累积。DigitalOcean的推理路由器(Inference Router)直接解决了这个问题:它将常规任务路由给较小的开源模型,仅在任务需要时才升级到前沿模型。为了在真实的多文件代码库上衡量差异,我们完全通过OpenCode构建了一个完整的Godot 4游戏——PK Shootout。在本次构建中,OpenCode在83次助手交互中完成了596个路由任务。该项目大约使用了410万token,通过路由器的花费约为8.25美元。大多数任务路由到了MiMo V2.5和GLM-5.2,596个任务中只有2个需要回退。同样的构建如果仅使用前沿模型,预计花费为123美元(假设生成相同数量的token)。
PK Shootout是使用OpenCode在几个小时内开发完成的。为了驱动模型,我们通过OAuth登录将OpenCode连接到DigitalOcean的Serverless Inference,然后创建了我们自己的推理路由器作为后端。有了这两个部件,我们构建了一个完整的Godot 4点球大战游戏(瞄准、力量计、门将AI、对手模拟、突然死亡、结束画面和重新开始),而我们从未在工作流中指定模型名称。路由器为每个任务选择模型。但更有用的发现并不是节省成本:而是发现路由器并不总是运行你配置的模型。它会做出自己的成本驱动选择,而实际运行的模型让我们感到惊讶。
本文将逐步介绍我们创建游戏所采取的每一步,从连接OpenCode到在App Platform上托管。请跟随我们详细了解进展顺利的地方、我们不得不介入的地方,以及开发过程实际花费的时间和成本。
这是整个过程中最简单的部分之一。我们登录DigitalOcean账户,打开推理路由器部分,创建了一个名为game-designer的路由器,包含四条不同的路由:
这个路由器处理了游戏开发100%的任务。将其连接到OpenCode只需一步:在终端中安装OpenCode,运行/connect,选择使用DigitalOcean登录(OAuth路径:这是暴露你的路由器的选项),并授权。运行/models,你会看到你的路由器带有router:前缀。我们选择了router:game-designer并开始构建。
从那时起,循环就是普通的智能体开发:用自然语言描述更改,让智能体读取相关文件,提出编辑并应用。不同之处在于底层:对于每个请求,路由器决定哪个路由和模型应该处理它,而我们的提示词中没有任何模型名称。本文的其余部分将探讨我们从依赖这种设置端到端构建PK Shootout中学到了什么。
这个问题诚实的版本不是“我们选了哪个模型?”。我们从未选过。而是“路由器将哪些模型分配给了哪些类型的工作,每个模型在该角色中表现如何?”这种重新定义很重要,因为这是路由器支持的工作流的全部前提:你描述任务,由路由决定模型。

在整个构建期间,路由器将596个任务解析为五个类别:chore335个任务(56.2%),design207个(34.7%),debug41个(6.9%),repo-qa11个(1.8%),以及2个回退(0.3%)。这种分布形态正是你在真实开发中所期望的:大量小编辑的长尾、扎实的设计工作核心、较窄的真调试带,以及几乎没有纯粹的仓库问答。
将其映射到模型分布上,故事比单纯看配置更有趣。三个模型基本上承载了所有流量:MiMo V2.5约为56%,GLM-5.2约为42%,Gemma 4约为2%。我们在每个路由池中列出的许多其他模型,如Deepseek、Kimi、Qwen、Ministral等,从未需要替补上场。实际上,两个主力模型就完成了工作。
GLM-5.2的行为与我们的配置完全一致。它约42%的份额与它作为主要模型的两条路由几乎完美吻合:design(34.7%)加上debug(6.9%)约为41.6%。这是一个清晰的信号,表明design和debug路由按照我们设计的方式工作,并且GLM-5.2是一个足够有能力的智能体,可以同时承担架构工作和逐步调试:这两个地方是薄弱指令遵循会最快暴露的地方。

chore路由是配置与现实产生分歧的地方,值得坦白说明。Chore是我们最大的类别,占所有任务的56%,而Gemma 4只服务了约2%的调用,而MiMo V2.5(没有声明为任何路由的默认模型)却吸收了约56%。这是因为MiMo V2.5实际上更便宜,导致路由器选择它而不是Gemma 4。换句话说,对于低风险编辑,路由器的实际选择是MiMo V2.5,而不是我们名义上设定的Gemma 4。对于评估这种方法的创始人来说,这是一个有用的提醒:路由表达意图,但实际应答的模型由路由器决定,并且值得关注你的分布情况以确认真正运行的是什么。
这些模型都没有遇到困难的,正是代理协议本身。在整个会话中,背后的模型可靠地串联工具调用:读取文件、grep 搜索过时的引用、应用有针对性的 str_replace 风格编辑,而不仅仅是倾倒文本然后希望成功。它们执行了多文件一致性检查(验证场景文件、脚本和调用代码在更改后保持一致),并正确推理了不明显的控制流,包括 async match-end 函数中 await 的顺序,以及状态在函数挂起之前是否已设置。这才是“此模型能否驱动编码代理”的真正标准,而且它比基准分数更高的标准:不是模型是否了解 GDScript,而是它能否操作工具、将仓库记在脑中,并且不破坏它未查看的东西。在这个标准上,路由器的两个主力模型都通过了。
一款可运行的游戏是重中之重,但背后的数字才是让整个工作流程一目了然的关键。
构建过程用了 83 次助手回合对 17 次用户回合,才达到完整且有文档记录的游戏:约五比一的代理工作与人工输入比例。17 条提示将项目从空的 Godot 项目带到瞄准、力量计、守门员 AI、对手模拟、突然死亡、结束画面、重新开始流程和完整的 README。
将所有 83 个回合相加,代理累计生成了约 74.5 分钟——即模型实际工作的时间,不包括我们花在阅读、在 Godot 中测试或决定下一步提问的时间。单次回合差异很大,从 2.1 秒的一行修复到 529.6 秒的完整 README 写入。这种分布反映了路由工作的实际分布方式:一系列快速编辑的尾部,穿插着少数繁重的多文件生成。就挂钟时间而言,PK Shootout 在几小时内完成,其中大约一小时十五分钟是模型生成时间。
路由器增加了一个硬编码单一模型所没有的成本:决定每个请求去向的时间。这个开销很小且可测量。路由器解析延迟在此期间保持在约 0.27–0.30 秒,游戏设计者在 6 月 25 日测得 0.276 秒。每次请求约四分之一秒,这就是不自己指定模型的字面代价。延迟曲线在两天窗口内保持平稳,只在最后才上升,因此路由不会随着项目增长而退化。
由于大部分流量解析到低成本模型,即 MiMo 和 GLM 而不是前沿 API,总花费远低于在纯前沿设置上执行同样 596 项任务的成本。用实际数字来说,完成所有事情大约需要 410 万 token——构建应用、设计计划、编写 README 文件,并回答一些关于已完成工作的问题。对于所有操作,调用 MiMo v2.5 总计约 0.65 美元,GLM-5.2 调用累计约 7.56 美元,Gemma 4 调用约 0.04 美元,合计约 8.25 美元。相比之下,如果我们在没有路由器的情况下单独运行 GLM-5.2,累计估计成本为 18.04 美元,或者使用前沿模型如 ChatGPT 5.5 在相同 token 数量下成本高达 123.00 美元。虽然这些模型可能比路由器方法更高效、用更少的 token 完成任务,但这不足以抵消使用这些更大模型时每 token 成本的大幅增加。将昂贵的工作路由到昂贵的模型,将所有其他工作留在更便宜的模型上,是整个工作流程的经济论点所在,而任务分布正是实现这一点的关键。
只展示有效部分的演示价值不大。路由器独自承担了 PK Shootout 的大部分工作,但有三个时刻需要人类介入,它们是构建过程中最有启发性的部分。两个是代理很好地完成了工作;一个是你在信任此工作流处理任何关键任务之前需要理解的局限。
第一个是真正的 bug,代理处理得很干净。在一次早期构建后,游戏看起来正常但没有响应:按下鼠标左键没有力量条,也没有射门。我们用简单的语言描述了症状,并让代理找到原因。它读取了输入处理器,追踪了事件流,并推断出输入根本没有到达 _unhandled_input。罪魁祸首是全屏 Background 节点,一个 ColorRect,像 Godot 4 中的每个 Control 一样,默认使用 MOUSE_FILTER_STOP,会在鼠标事件传播前静默消耗它们。修复方法是将背景的鼠标过滤器设置为 ignore 的一行更改。值得注意的是,我们从未指向原因;我们只报告了症状。代理自己诊断出了根本原因,这正是调试路由旨在提供的逐步推理。
第二个时刻是摩擦,但具有启发性:是我们的错,不是模型的错。我们要求将球门“移到屏幕约 1/3 处”。代理将其理解为从上往下三分之一,并将球门向上移动,与我们的想象相反。我们告诉了它,然后澄清为“从屏幕底部算起 1/3”,它在下一次尝试中将球门放到了我们想要的位置。教训不在于模型失败;而在于自然语言的空间指令是模糊的,这种模糊的代价是多几个回合。第一次给出精确指令本可以省去双方的来回。这就是代理式开发的常态:人类的工作从编写代码转变为编写明确意图,而且你会随着实践越来越好。
第三个时刻是必须认真对待的,因为它暴露了次前沿后端真正边界。当我们要求代理编写通过 DigitalOcean 的 Serverless Inference 生成图像资产的命令时,它不知道实际的 API。在推理过程中,它提出了几个看起来合理的端点 URL,但没有一个正确,然后它做了正确的事:它标记了自己的不确定性,询问我们真实的端点和令牌,而不是贸然猜测,并生成一个通用的 OpenAI 兼容脚本,将具体细节留作占位符。这种避险策略确实值得称赞。但底层事实才是重要的。该模型不能可靠地了解当前的外部 API 细节,如果我们按表面价值接受它的第一个猜测,我们会交付一个损坏的命令。我们提供了真实配置,这在本文的最后一部分有文档记录。
综合来看,这三个时刻划出一条清晰的界线。代理擅长在它能看到的代码上进行推理:仅凭症状诊断鼠标 bug,应用有针对性的修复,并从模糊指令中优雅恢复。它恰恰在没有任何模型在缺乏检索的情况下都不擅长的方面薄弱:对无法检查的当前外部系统的权威知识。知道任务落在界线的哪一边,是善用此工作流的大部分关键。
到构建结束时,我们已经有足够的证据对基于路由器、由DigitalOcean托管的方案适合什么、不适合什么,形成一个有理有据的观点。
当工作大多是常规性时,选择它。我们的任务拆分很能说明问题:大约56%是琐碎工作,35%是设计,只有一小部分是真正的调试,几乎没有纯粹的仓库问答。这就是普通开发的真实样子:大量小而边界明确的编辑,加上稳定的设计工作核心,而这正是路由器被设计来利用的形态。廉价任务会解析到廉价模型,昂贵任务只在路由需要时升级,你永远不会为文档字符串或变量重命名支付前沿价格。成本数字直接证明了这一点:整个构建约8.25美元,而仅使用GLM-5.2估算为18.04美元,使用前沿模型则更高。当你的大部分工作是实现而非新颖推理时,路由器的混合配置就是关键所在。
当任务依赖于对外部系统准确、最新知识的了解,或需要跨多个步骤保持连贯的长期架构推理时,请使用前沿API。我们遇到的最明显信号是后端凭空捏造了一个它其实并不了解的DigitalOcean端点。没有检索能力的次前沿模型会自信地填补其在当前API和SDK知识上的空白,而这正是让你在最意想不到的时候付出代价的失败模式。边界很简单:常规实现,可以;权威外部事实,要么验证,要么升级。如果任务取决于模型无法在你的仓库中检查的细节,要么自己提供事实,要么将其路由到你信任拥有这些事实的模型。
这两种情况背后是相同的权衡,而且是有利的权衡。你放弃了一点速度(路由器为每个请求增加了大约四分之一秒的解析延迟),并接受偶尔的回退(596个任务中有2个,当路由的主模型没有返回可用输出时,池中的下一个模型介入)。作为交换,你永远不会硬编码模型,永远不会为琐碎工作支付过高费用,并且在单个响应出错时获得内置的安全网。对于PK Shootout所代表的那类工作负载,这是一个值得做的交易。
PK Shootout 在几个小时内从一个空的Godot项目变成了一个完整、可玩的点球决战游戏(瞄准、力量条、守门员AI、对手模拟、突然死亡、结束画面和重新开始),完全通过DigitalOcean Serverless Inference上的OpenCode构建,由Inference Router为596个任务中的每一个选择模型,并且我们的提示中从未出现过模型名称。
结果清晰地展示了此工作流擅长什么。代理能够对其可见的代码进行有效推理:它仅凭症状就诊断出鼠标输入错误,跨多个文件应用了针对性修复,并从含糊的指令中优雅恢复。路由器将廉价工作保留给廉价模型,将能力强模型保留给设计和调试,以约8.25美元完成了整个构建。它的局限性同样明显,而且与任何没有检索能力的模型一样:对于它无法检查的当前外部系统,缺乏权威知识。知道任务处于这条线的哪一侧,是善用此设置的大部分要点。
对于常规、边界明确(这是大多数开发)而言,路由器后端、DO托管的方案是一种真正实用的构建方式,而且比默认使用前沿API便宜得多。

此构建中的所有内容都可以通过DigitalOcean账户、OpenCode和几分钟的设置复现。以下是将OpenCode与DigitalOcean配合使用的确切配置:
/connect
搜索 DigitalOcean 并选择“使用 DigitalOcean 登录”。这就是 OAuth 路径,也是至关重要的路径:它会请求 genai:read 和 inference:query 作用域,同时获取你的基础模型和路由器。另一种方式“粘贴模型访问密钥”也能正常完成身份验证,但不会显示你的路由器——所以如果你已经构建了路由器,请使用 OAuth。在浏览器中完成授权后,运行:
/models
您的路由器以router:为前缀显示。我们选择了router:game-designer并开始构建。这就是整个设置过程。 直接调用端点。如果您更愿意从自己的代码驱动Serverless Inference,而不是通过OpenCode,它是与OpenAI兼容的。将任何OpenAI客户端指向固定的基础URL,并将您的模型访问密钥作为Bearer令牌传递:
from openai import OpenAI
import os
client = OpenAI(
base_url="https://inference.do-ai.run/v1/",
api_key=os.getenv("MODEL_ACCESS_KEY"),
)
resp = client.chat.completions.create(
model="game-designer", # a router name, or a foundation model id
messages=[{"role": "user", "content": "Summarize this repo's architecture."}],
)
print(resp.choices[0].message.content)
相同的base URL、密钥和请求格式适用于cURL、Gradient Python SDK、LangChain或LlamaIndex——更换后端后,现有代码无需修改即可运行。
——
一个热爱技术的程序员,喜欢分享前沿AI知识和开发经验。