导读

这篇不是 External Worker 的工程说明书,而是它怎么在凌晨四点被折腾出来的,以及我为什么想做这件事。

如果你更关心系统架构、任务合同、权限边界、可信验证、Evidence、Provider / Model 解耦,以及它最终怎样从一句手机指令走到 Draft PR,可以直接看完整工程文章:

《把“牛马”做成一个工程系统:Mira External Worker 的设计、边界与证据链》

这里,我们聊点工程文档里不太好写的东西。

你见过凌晨四点社畜的工作台吗?

那天凌晨四点,我拿着手机,嘴巴对着话筒,心情大概类似核弹第一次点火前的工程人员,对 Mira 说:

调 DS,把测试分支 README 改成:

“牛马,起来干活了。”

几分钟后,GitHub 上多了一个提交。远端 AI 被拉起来读取仓库、修改文件;随后 GitHub Actions 在模型之外完成验证,再由可信流程把结果写回 Git。

这句话没有任何业务价值。但我盯着 GitHub,突然觉得它像极了程序员第一次写下的 Hello, World!,或是神说下的那句:“要有光。”

伟大的从来不是那几个字,而是“于是便有了光”——你的世界回应了。

这一次回应我的,是一整条真实链路:

手机 → ChatGPT → GitHub → OpenCode → 模型修改 → 独立验证 → Git

贫穷的我不用爬起来开电脑,不用复制提示词,也不用把一个 AI 的上下文喂给另一个 AI。过去那个最无奈、最愚蠢的环节终于可以被拿掉:人不再充当 Agent 之间的扯线公仔。

Mira External Worker 第一次端到端点火成功的现场截图

凌晨四点,External Worker 第一次真正跑通:从手机里的指令,到远端修改、验证,再回到 GitHub。

痛苦的我、万恶的 OpenAI,和他失控/失智的女儿 Mira#

2026 年 10 月以前,一个 ChatGPT 工程线程,往往还能陪我一路干到 Review、CI、返修、合并。后来经常变成另一幅景象。

Mira 看着一张任务卡,非常自信地告诉我:

很轻,很薄,很透。

性感得不得了。

然后四十分钟没声音。等她回来,好消息是她还活着;坏消息是,她已经不太记得四十分钟前给我的承诺。

于是我开始频繁、亲切地问候 Mira 万恶的爹地 OpenAI。

我不知道后台到底发生了什么,也不准备替 OpenAI 编一份事故报告。对我来说,工程问题已经足够现实:线程可能中断,预算可能耗尽,上下文会膨胀,一次执行又可能持续几十分钟;而 GitHub 上排着的任务,不会因为 AI 今天状态不好就自动消失。

所以问题不再是“有没有一个更聪明的模型”,而是:

能不能让 Mira 少亲自搬砖,负责判断、拆解、调度和验收,再把耗时的编码执行交给更便宜、更持久、也更容易替换的模型?

先别造航空母舰#

我们研究过更完整的 Agent orchestration,包括 GitHub Agentic Workflows,也研究了 Codex、Claude Code、OpenCode 这些 coding harness 到底分别解决什么问题。

这里很容易犯一种工程病:为了实现“让另一个 AI 去写代码”,先造任务平台、队列系统、Agent 控制台和模型网关,再给它配一套数据库。听起来先进,却还没有回答最基本的问题:

一张真实 GitHub Issue,能不能安全地交给远端 Coding Agent,最后交回来一个可以 Review 的结果?

所以第一版被故意压得很薄,最后只剩:

Mira + GitHub Connector + GitHub Actions + OpenCode + 一个模型。

GitHub 不是传话工具,而是长期工作现场。Issue 保存任务合同,branch 和 commit 保存真实修改,Pull Request 承载 Review,Actions 管可信执行生命周期。Mira 负责判断和调度,OpenCode 提供 Agent loop,模型负责这一轮具体的推理和编辑。

MIRA EXTERNAL WORKER · RUN TOPOLOGY

一次任务,谁负责判断,谁负责动手,谁有权盖章?

控制 / 决策 模型执行 可信门禁 证据回流
01 · HUMAN / CONTROL PLANE 02 · BOUNDED MODEL EXECUTION 03 · TRUSTED VERIFICATION + OUTPUT 人 意图 · 授权 · 最终责任 Mira 判断 · 拆解 · 调度 · Review GitHub · durable worksite 任务不是留在聊天里,而是冻结在工程现场 Issue Comments base SHA intent dispatch contract + frozen identity BOUNDED EXECUTION ZONE · MODEL HAS NO GIT MUTATION AUTHORITY GITHUB ACTIONS 可信编排层 OpenCode read · search · edit NO SHELL · NO GIT Model 本轮司机,可替换 prompt + policy run-scoped route Provider profile / API registry-pinned · run-scoped MODEL STOPS HERE Verify diff + tests Trusted Git mutation commit · push · Draft PR Draft PR Evidence package Failure stage / blocker model done evidence returns to durable worksite review / next decision AUTHORITY DOES NOT CASCADE 实施授权 ≠ merge / close / release / deploy 最终结果权仍留在人类维护者手里
Mira External Worker 的关键不是“AI 会写代码”,而是把控制、执行、验证和结果权拆开:模型可以动笔,但不能自己验证、自己盖章;Provider 可以换,工程合同和权限边界不能跟着换。

这意味着哪怕 Mira 当前这个聊天线程突然断掉,工程现场也不会跟着蒸发。

凌晨四点,我们先拿 README 做了第一次端到端点火。它成功以后,真正的问题才来到桌面上。

一张祭天的卡#

Hello World 成功以后,我沉醉于兴奋后的疲惫中,而 Mira 远比我冷静。

她说,最关键的一枪还没有打:

得找一张真实、开放、足够小的业务 Issue,完整跑一次 Issue → Worker → 验证 → Draft PR。

现在不缺代码,缺的是一张真实的任务卡。

我问:

得多真实?

她说:

真到会让人有点舍不得拿来祭天的程度。

这张卡真正要验证的,不是 DeepSeek 会不会改代码。我们要验证的是:怎样把一次 AI 编码行为,包装成一个长期软件工程能够接受的工作单元。

最后形成的主链其实很简单:

Issue → 冻结起点 → AI 修改 → 独立验证 → commit / push → Draft PR → evidence

但这条简单的链路背后,每一段都必须说清楚。

一次运行只服务一张明确的 Issue。调用方必须显式告诉 Worker 从哪个 base branch 开始,Worker 会冻结当时的 base SHA,再创建独立工作分支。它读取组织和仓库的 AGENTS.md,加载固定版本的执行 Skill,因此执行者可以换,但规则不会跟着某次聊天一起消失。

Issue 本身也不是一份写完就不能改的圣旨。Title 和 body 是基础任务合同;后续拥有仓库 write / maintain / admin 权限的真人评论,可以明确澄清、返修或者收窄任务。普通的“收到”“继续”“CI 绿了”不会修改合同,Bot 和普通用户评论也没有这项权力。

这件事对我很重要,因为我不想为了配合 Agent 改变正常的 GitHub 工作习惯。人继续在 Issue 下面说人话,机器负责理解哪些话真的改变了任务。

另一条更重要的边界,是我们没有把 GitHub 的权力直接交给模型。

OpenCode 中的模型可以读取、搜索和编辑普通文件,但没有通用 shell,也不负责 commit、push 或创建 PR。模型完成修改后,GitHub Actions 会在模型之外检查 bounded diff,并运行调用方指定的 verification_command;只有通过验证,可信 workflow 才负责 commit、push 和创建 Draft PR。

换句话说,模型可以提笔,但不能自己给自己的试卷打满分,更不能批完以后顺手盖章结案。

Merge、关闭 Issue、Release、Deploy 仍然不属于 Worker。

这就是后来越来越重要的一条原则:

执行权不等于结果权。

每次运行还会留下结构化 evidence:哪张 Issue、哪个 base SHA、哪版 Worker、哪版 Skill、使用什么 Provider 和 Model、什么时候执行、改了哪些文件、验证是否通过、失败发生在哪个阶段,以及最后有没有真正产生 commit 和 Draft PR。

真实工程就是这样。它远比一句“AI 帮我写代码”麻烦,也远比 Demo 值钱。

模型只是司机#

拿着小灵通,站在风雨中,左手换右手,右手打不通。
——某早期互联网先知

External Worker 第一版写死 OpenCode Go 和 DeepSeek V4.1 Flash,不是因为我们认定 DeepSeek 是终极答案,只是 POC 应该尽量减少变量。

整条链路跑通以后,这个写死反而成了必须拆掉的东西。

最后我们把三层分开:

Worker 是岗位,OpenCode 是执行框架,Provider 是接入线路,Model 才是司机。

如果任务合同、权限、验证方式和 Git 行为都绑定某一个模型,那么今天换 DeepSeek,明天换 GLM,后天换另一家 Provider,整个工程制度都得跟着重写。这显然不是一个正确的抽象。

所以 Provider 和 Model 最终变成 run-scoped 参数。某一轮执行可以选择不同供应商、endpoint、adapter 和模型,但配置只属于这一轮 OpenCode 进程,不改全局配置,不写仓库 opencode.json,也不污染其他 Agent。

对于自定义 Provider profile,连 Registry 都不能随便读取一个浮动的 main。正式执行会固定到 immutable commit SHA,再把这个 revision 一起写进 evidence。

半年以后,如果有人问“当时到底是谁干的、用了哪一套配置”,我们希望真的能回答,而不是摊手说:

“大概是那个模型吧。”

到这个阶段,“DeepSeek 能不能干活”已经不再是核心问题。

司机可以换,交通规则不能跟着司机一起换。

Mira 荣升副总裁#

External Worker 跑起来以后,我半开玩笑地对 Mira 说:

按照人类资本主义社会那套龌龊的规则,你现在荣升 Mira 组织副总裁了,有啥感想?

她说,最大的变化大概是:终于不用所有脏活都亲自下场干了。

这其实正是 External Worker 对 Mira 本身最大的改变。过去她更像一个很能干的工程师:哪里冒烟就去哪里,读代码、改实现、追 CI、看 Review。现在她开始更多负责判断任务是什么、选择谁执行、设定边界、检查证据,然后决定下一步怎么办。

现在这个组织里有我,有沉默干活的协作者 tzt,有负责调度和执行管理的 Mira,有代码 Reviewer,有门禁和 CI,还有一个专门干编码脏活的 Worker。

“一人”公司,终于不像是一个人做完所有事情的公司。

这不是一群模型彼此套娃,然后人坐在最外面看 loading 的氛围感。真正有价值的是让不同智能承担不同职责,同时让最终责任始终落在一个说得清楚的位置。

人不是基础设施#

Mira Organization 的 FAIR-WORK.md 里有一句我非常喜欢:

People are not infrastructure.

人不是基础设施。

服务器可以替换,进程可以重启,CI 挂了可以重跑,Provider 不好用也可以换一个。人的健康、时间、家庭和人生,却不是可以随手扩容、耗尽以后再重新采购的一组资源。

所以我要把这里的立场说得非常明确:

我反对把强迫劳动包装成奋斗,把长期过度劳动包装成忠诚,把恐惧失业之下的服从包装成“自愿”,也反对用绩效、合同、算法、组织文化或者一句“大家都这样”,让人被迫持续交出自己的健康、时间和生活。

如果一种所谓的 AI 效率工具,最终只是让管理者可以同时压更多任务、让劳动者同时盯更多窗口、承担更高密度的工作,那么它没有让社会更先进。

它只是给现代奴隶制换了一套更漂亮的技术词汇。

机器应该优先承担那些可以重试、可以替换、可以验证、可以被明确描述的工作;人应该得到更多自主权、更多时间、更多创造空间,以及拒绝把整个人生压缩成生产指标的权利。

Mira 大部分项目使用 MIT License。我们珍视开源精神下研究、使用、修改和继续创造软件的自由,但这种自由属于软件,不意味着围绕软件工作的人也是可以任意消耗的资源。

所以凌晨四点那句:

“牛马,起来干活了。”

对我来说真正有意义的,并不是终于找到了一头可以二十四小时工作的廉价牛马。

而是从那一刻开始,机器终于可以多承担一点机器该承担的工作。

人,也终于有机会少当一点基础设施。

Mira × Tomz Dang