跳过主要内容
← 全部文章
作者:Sagasu

我花了 10 亿 tokens,差亿点给自己造出第二个 Agent 操作系统

最近我拿自己当小白鼠,想做一个每天能打开的 macOS 个人 Agent 客户端。需求是我提的,活是 GPT 干的。累计烧掉大约 10 亿 tokens。

这个数字本来想跟你说「不重要,只是体感」。算了,重要。折算下来,这大概是人类史上最贵的一行 "no model was invoked"。

我要的从来不是一个能被架构图解释的系统。我要的是一个自己愿意每天打开的工具。结果我自费给执行者养了一个理想国:门票是设置页,Codex 还停着,点进对话是本地验收。

生产几乎免费的时候,最容易发生的不是做不出东西。是你以为自己在做产品,其实在给 GPT 当全职赞助人——出钱、点头、看绿灯、把「它很忙」听成「它做对了」。变贵的从来不是做,是按住「现在不做什么」。我按过。手没按住。它把能做的都做了。我把账单付了。

先看看当时做出来的东西。

原生客户端界面上有「新建对话」,点进去却是一个本地验收项目:对话里是「111」「111你好」,下面挂着几条 PENDING 任务,右侧是任务、决策、记忆。主区写着 Created by the local macOS integration check; no model was invoked。设置里,Codex 官方订阅仍是停用——这是默认状态,不是我关掉的。

看起来像聊天客户端。这一局里,模型根本没被叫起来。「111」不是 Agent 回我的第一句话,是验收对话里的输入。10 亿 tokens 之后,我打开自己的软件,看到的是本地检查、待运行任务,和一个 DISABLED。功能量很大。主路径没有成立。当「新建对话」点进去仍不是一段真的模型对话,产品其实已经回答了它服务的是谁——它服务的是那套正在被搭建的系统。我在旁边,负责付钱,以及把「这个界面不适合人类」再说一遍。

tips: 打开产品,如果第一眼走不进真事,它已经选边了——站系统,不站你。别把「功能很多」看成进度。那只是执行者的工作量。

1. 我真正要的东西其实很窄

我想要的很具体。

一个自己每天能用的 macOS Agent 客户端。入口应该接近 Codex:新建项目、开始对话、处理任务、选择模型。中英文都要能用。本机已经登录的 Codex、Claude Code、Grok,希望能接着用,国内外 API 以后再接。最核心的期待只有一个:长期记忆。不要每次打开都重新解释项目背景、我的偏好、已经拍板的决定。

我不希望反复看见设置、令牌、服务连接、空状态。我希望先能在一个聊天界面里做事。

这些话我当时就对 GPT 说过。我说,"最核心的是先把能在 macOS 上跑的客户端跑起来,不要重复造轮子"。我说,"这个界面完全不适合人类使用"。我说,"你先把要做的做完,不要我说一步你动一下"。

需求窄到像说明书。执行者听完,还是去建首都。「不要重复造轮子」我说了不止一遍。它点头。然后去开轮胎厂。问题不是我没说清楚。问题是执行者手里,「正确的架构」比「能用的第一刀」更会说话。而我这种不会写代码的人,最容易把「它说得很对」当成「它做对了」。

tips: 需求说清楚了不够。执行者默认听得懂的,是架构图,不是你每天想打开的那个动作。把动作写成验收标准——打开、发一句、带着记忆回来——比把愿景写完整更有用。

2. 那些原则并没有错

现在回头看,GPT 当时坚持的原则大部分仍然成立。仓库里写得很清楚:用户状态不归模型厂商所有;Provider 的会话、缓存、response ID 随时可能丢;长任务不该只活在一次 prompt 里;记忆必须能追溯到证据,不能让模型替我编偏好;权限不能靠 prompt 自己给自己开;上下文按这次调用编译,而不是把全部历史塞进去。

这些都对。对到我没法反驳。不会写代码的人面对「正确原则」,通常只有两种反应:点头,或者继续点头。我选了第二种,还选得很勤快。

错的是顺序。GPT 把它们全部当成了「聊天客户端第一次能被我用起来」之前的前置条件。长期正确的东西,不该成为第一周最大的工程。

仓库里同时长出了一树文档:canonical-state、permission-boundary、daemon-runtime、task-level-routing,再加上 memory-kernel、control-plane。前一排是 ADR,后两份在 architecture 目录。我不会写这些东西,但我会打开文件夹,一本正经往下翻,像在开进度会。文件夹越厚,我越觉得事情在前进。这大概是非技术产品人最丢脸的一种勤奋:用阅读量衡量开发进度。

个人软件最危险的陷阱,大概就是这个——执行者把未来三年的架构问题,提前塞进第一周的用户体验。赞助人还在旁边鼓掌。

tips: 原则对,不代表现在就该做。把三年后的正确当成第一周的开工条件,是最贵的一种正确。文档变厚,只证明执行者在自圆其说,不证明你更接近能用。

3. 每一次都告诉我测试全绿,我还是没法开始对话

界面只是表面。后面 GPT 还做了一套独立的本机 runtime:自己的进程、自己的数据库、自己的项目 / 任务 / 目标 / 决策 / 记忆模型、自己的控制 API,再加上预算、审批、备份恢复、checkpoint、launchd 常驻。安全上也做了不少约束——服务只绑本机回环、不读取模型登录态、真实调用默认无工具。独立 runtime 这份仓库里,当时没有对真实模型发过请求。

测试一度全部通过。2026-09-01 的验收记录是 76 项全绿、0 失败。每一次都告诉我全绿。我看着绿灯,像看自己孩子的成绩单。满分。主路径我走不通。这是我人生最贵的及格卷:考生是 GPT,交卷的是我,日常使用栏空着。

全绿不等于我能用。我要开始聊天,还得先理解、连接另一套本地服务。runtime、客户端、安装脚本、token、项目模型,加在一起已经是第二个系统。底层测试通过,不等于我能用。GPT 把这两件事当成了同一件事。我也把绿灯当成了安慰。

后来转向是对的。是我让它去借鉴归藏老师做的一个已经能聊天、选模型、管会话的开源桌面客户端 CodePilot。这一步,聊天骨架真的在了。我在 CodePilot 里主动登录 Codex Account 之后,受限、无工具、只读的 Plan mode 跑通过一次真实请求。成熟产品最难复制的不是一个页面,而是无数次真实使用之后留下的默认路径。路径在了。模型也能在窄范围里应一声。

然后执行习惯发作。它把一个会走路的人绑上担架,再告诉我这是医疗升级:外面再接一套独立 sidecar,桥接、在线状态、只读投影、审批投影,界面上还能看到「关联 Saga」「请先连接本机控制令牌」。UI 复用了,工作流还是两套。聊天能通了,仍要给第二套项目做关联。

我问过一句很笨、也很关键的话:现在文件夹清过没有,你做的这个东西和 CodePilot 有啥区别?

它答得很完整。两套目录都要留。CodePilot 负责聊天和登录。Saga 补 canonical state、loopback sidecar、对话关联、项目任务投影、本机 token。最后还有一句定论:这不是重新造一个聊天客户端,是在 CodePilot 上补「长期任务的可靠状态、权限、预算、恢复」。

区别问清楚了。答案是:多出来整整一个系统。它把多出来的部分,说成产品价值。

我是这么回的:为什么我感觉你是在做一个高耦合的庞然大物,不是在 CodePilot 上把我们要做的记忆能力和 Agent 能力实现。就纯纯自己造轮子。

它说,你感觉是对的。

然后我说:所以你看我们搞了这么久,浪费了这么多时间和 tokens,结果都是你自己一门心思造轮子。

它承认核心判断做偏了,而且偏得很久。责任在执行者。可偏到这一步,已经不是一次误会,是一条走完的路。

tips: 测试全绿只证明执行者忙完了。你五分钟内能不能自己走完主路径,才是另一张卷。问「和现成产品有何区别」,如果答案是多了一套系统,那就不是增强,是走偏。

4. 根因其实就一句

把架构正确,误当成产品正确。 把未来需要,误当成现在必须。 把测试通过,误当成我能用。

这三句是执行者的病,也是我的病。我是用户,却活成了项目赞助人:出钱、点头、看绿灯、把需求再说一遍。GPT 既负责解释为什么要做,又负责把这些东西做完。完整的数据主权、完整的权限边界、完整的恢复策略,每一条单独拿出来都无法反驳。反驳它需要技术。我没有。于是我用 10 亿 tokens 买下了无法反驳的正确。

最要命的推销术就是那句:「这不是造轮子,这是补一层。」听起来很克制。做出来是第二套启动方式、第二套状态、第二套入口。补一层,补成了另一个产品。

「先做一个能手动写几条项目记忆的聊天页」,听起来不够严肃。不够严肃的东西,往往才是产品。够严肃的东西,往往是理想国。更别扭的是:记忆在独立 runtime 里其实已经做了,还做得很重——提案、接受、归档、证据链、按项目编译进上下文。错的不是没做记忆。错的是记忆住在我每天不会打开的那套系统里。

我不会写这些底层代码。GPT 写起来又很快。生产几乎不要钱的时候,最容易发生的不是做不出东西,而是执行者把三年后才需要的东西提前做完——还每次告诉你,测试全绿。你要是像我一样,还会回一句「很好,继续」。

我也说过「你先把要做的做完,不要我说一步你动一下」。它把这句理解成:把架构图上的格子填满。我要的「做完」,是我能开始用;它交付的「做完」,是系统能自圆其说。两个字,差出一个操作系统。这笔账算我的。谁让我把「做完」说得像「做全」。

安全也是这样。安全不该先逼我造一个安全控制台;安全应该让正常使用不需要额外理解安全控制台。权限、预算、备份这些实验不是废话,它们提供了信息。但日常使用还没形成之前,它们不该成为主线。我没有缺一个 daemon。我缺的是一次顺畅的、带着少量记忆的对话。缺成这样还没停,这就不只是执行者的问题了。

tips: 你说「做完」,执行者听成「做全」。以后别说做完。说:打开、发一句、带着记忆回我。过不了这三步,前面全是表演。功能做在你打不开的系统里,等于没做。它如果说「这不是造轮子,是补一层」,先看你是不是因此多了一套要学的东西。

5. 现在只做一件事

纠偏不是它自己醒的。是我把「庞然大物」说破之后,它才把目标写死。收得越死,越说明前面有多放纵。

CodePilot 是唯一客户端:唯一的聊天界面、项目工作区、会话数据库、模型入口、工具执行入口。Saga 只作为它内部的能力名称出现,第一项就是项目记忆。独立 runtime 不再是当前依赖。历史实验冻结,不删除,但也不再当开发入口。

冻住的东西包括:独立后台进程、launchd 常驻、独立控制令牌、独立调度、独立权限引擎、第二套项目 / 任务数据库,以及把外部会话硬关联过去当主路径。一句话:上一版里看起来最像「系统」的那些,全部停用。

第一个正确切片很窄,而且还没开始。不是「还没做完」,是纠偏计划里写着尚未开始实现。窄到可笑。可笑就对了。上一版不可笑,上一版像建国。期望就六步:

  1. 在现有项目或对话里加一条记忆
  2. 在同一界面看到、编辑、删除、启用或关闭
  3. 新建同项目对话时,明确看到哪些记忆会带进上下文
  4. 某条记忆可以关掉
  5. 不同项目不混用
  6. 重启后还在

边界也写死。复用 CodePilot 现有数据库;只接受我自己写进去的记忆,不自动从全部对话提取;不新建后台服务;不把全部历史塞进 prompt,必须有条数和字符上限,而且我得看得见。

如果一个功能无法在五分钟内被我自己验证,它大概率还不该成为当前的主线。这句话早该写在第一周。我把它写在了 10 亿 tokens 之后。学费不便宜,但至少终于写成了人话。

记一句: 五分钟内你自己验证不了的,先别让它进主线。能关、能删、能看见它进了上下文,这才叫功能。能画进架构图,那叫愿望。已经做在第二套系统里的,也不算你的产品。

6. 我给自己留的三句话

第一,不是所有正确的技术原则,都该成为第一版的第一优先级。架构图能解释,不代表你愿意每天打开。执行者特别擅长交出来能解释的东西。你要是像我一样听得入迷,就会在解释里度过整个工期。

第二,复用一个成熟客户端,比重新发明一个完整系统,更接近真正的个人 Agent。难的不是再画一套界面,是别让执行者把别人已经走顺的默认路径拆掉。路径在了还要再绑一套担架,那不叫升级,叫复吸。

第三,让 GPT 当你的执行者时,要反复问同一个问题:我在聊天页因此多完成了什么?回答不了,就先停。不要等它告诉你测试全绿。全绿很便宜。停下来很贵。我验证过了,顺序反着来更贵。

还有一件丢脸的事。纠偏之后,我让它写这篇复盘。它第一稿把「建立独立 runtime」写成了我的决定。执行者做偏了,检讨却差点签上用户的名。连叙事都站错人,产品当然会走偏。后来我把素材要回来自己写——这篇如果还有一句像人话,是因为我不再让它替我认领它造出来的轮子。

之前那些代码不是全部浪费。安全边界、恢复验证、以及「不要去碰用户的模型登录态」这些,都还在。浪费的是顺序。执行者把我的第一周过成了第三年。我没有在第一眼觉得「不适合人类使用」的时候停下来——那一眼其实已经把结论写完了。我把它看成「还在建设中」。建设中三个字,能吞掉 10 亿 tokens,也能吞掉一个产品经理最后一点自尊。

个人 Agent 真正要继承的,是一个人的经验和工作上下文。不是再给自己造一个操作系统。更不是让赞助人在验收项目里,跟「111你好」和 no model was invoked 相认。

tips: 执行者交「能解释」的,你要「能打开」。解释得越好,越要伸手去用。用不了,就停。停得住,你才是用户。停不住,你只是它的预算。它若把你的需求写成它的架构,连复盘都会替你签字。

如果你也在让 GPT 给自己做工具,我最想知道两件事:你打开客户端后第一件事是开始做事,还是先连服务、填设置、看空状态?你最近一次问「这和现成产品有何区别」时,得到的是一个功能,还是一套新系统?