
墙不是一个瞬间
我用 Claude Code 的方式,就像一些人用构建系统一样:持续、结构化,而且零部件多到有点不合理。多个 agent 在各自的 git worktree 里并行跑;我自己搭了 CI runner,因为托管额度几个月前就烧光了;底层用 Temporal 做持久化工作流,再垫一层 Redis;还接了一个浏览器自动化服务,好让 agent 能亲眼看看自己刚构建出来的东西。
我本来想跟你讲我撞墙的那一天。但我讲不出来,而这恰恰是整件事里最诚实的一部分。
没有墙。也没有哪个下午,工具断然拒绝了我,我气得啪地合上笔记本。真正发生的——真正在发生的——是一种累积。一次小小的“咦,我想改改这个逻辑”,我绕过去了。一个月后又一次,我也绕过去了。然后是第三次。到那时,绕路已经不再像临时补救,而开始像这个工具本身的形状。这就是一座好围墙花园的特点:你不会把墙当成墙来体验。你只会把它当成“你原本以为自己想要的东西”的边界。
我是在后来通过对比才注意到这种累积的——大多数这类事情,也都是这样被注意到的。
“万物皆插件”
八月,DeepSeek 发布了一个 harness。仓库是 deepseek-ai/deepseek-harness,MIT 协议,收获了大约 17.9 万颗 star——这个数字与其说代表架构多牛,不如说代表有多少人正在绞尽脑汁思考同一个问题。它的口号只有四个字:万物皆插件。
我读了之后,短暂地,不为所动。
README 说,模型适配器、工具注册表、会话日志,甚至 agent 循环本身,全部可替换,说“没有需要修补的特权核心”。旁边还附了一篇 88 页的论文,标题是 A Programming Paradigm for Spatiotemporal Composability(时空可组合性的编程范式)。我直接被这个短语劝退。我诚实的第一个反应是:有人把插件——插件啊!——包装在了最长的词里。
这里我要小心一点,因为我的第一反应是错的,而它错的方式,比这个反应本身更有意思。
插件架构老掉牙了。Eclipse 有扩展点;OSGi 做动态模块加载的时间,比有些同事学会打字还早;Erlang 热换代码已经几十年了;Spring 从 2003 年就在注入依赖。如果他们的宣称是“我们发明了可替换组件”,那等于什么都没说。
但这不是他们的宣称,如果我早读论文再对仓库反应,就会知道。第 7 节把所有这些前期工作都列了出来——OSGi、Eclipse、VS Code 扩展宿主、Erlang 热代码加载、Spring 和 Guice、代数效应处理器、事件溯源——逐一点名,并承认了这一点。作者们并没有说插件是新东西,白纸黑字写着呢。
他们的主张要窄得多。在所有那些老系统里,清理是一种义务。你注册了什么,就被默认会去注销它。论文里对这种现象的说法是:被遗忘的清理“悄无声息地泄漏资源”。如果你曾经追查过一个比创建它的东西活得更久的监听器,你就知道这不是纯粹的理论抱怨。他们的贡献在于:让每个副作用的逆操作在结构上被强制要求,并且自动推导出来——你不可能忘记清理,因为你根本不用写清理——然后从形式上证明:一个系统无论以什么顺序加载和卸载,最终都会稳定到和“只干净地加载一次、再也不碰”完全一样的状态。他们把这个性质叫做“合流”(confluence)。论文大部分篇幅都在证明这一点。
所以真正新鲜的东西是元理论。证明。而这恰恰是最不适合放在仓库横幅上的东西。
我觉得,这就是我第一反应糟糕的真正解释。包装在卖那个四十年前就有的部分,因为“万物皆插件”四个词就能看懂,而“我们把效应反转变成结构上强制的要求,并证明了合流性”不行。我被营销劝退,得出结论说底下没东西,可底下的东西恰恰花了 88 页。
另外,我之前对“他们”是谁也很草率。harness 是 DeepSeek 的。论文是 DeepSeek-AI 和北京大学的。而它所形式化的运行时 Cordis,既不新鲜也不属于 DeepSeek——它曾作为开源聊天机器人框架 Koishi 的内核存在了四年,之后才被泛化并配上元理论。这个故事不像“一个实验室从零发明了什么”那么有电影感,但它更好:人们建立在开放的基础上,把学到的东西形式化,然后又以 MIT 协议放了出来。
我能读到代码
这是整篇文章围绕的那句话,而且它跟合流证明一点关系都没有。
我能读到代码。
不是“API 文档写得很好”,也不是“扩展点给得很大方”。而是真正的 agent 循环——那个决定接下来发生什么的东西——就待在一个我能打开的文件里。如果我不同意它,这种不同意是可以付诸行动的。我可以 fork 它,然后以自己的方式犯错。
我注意到自己有多渴望这个,而正是这种渴望告诉了我一些事。只有当你一直在悄悄想念某种东西时,你才会感到那种震动。那些我从来没费心去数的绕路,原来一直在某个地方累积。
然后我注意到另一件事:我其实并不想切换过去。也就是从这一刻起,这篇文章不再只是关于架构了。
三把椅子
我坐在三把椅子上,它们彼此意见不合。
在开发者的椅子上,我想要整台机器,而不是某些人决定暴露给我的那组控制按钮。每个抽象都是一次关于我未来会想要什么的赌注,这个赌注通常是对的,而当它错了时,我想要一条能下到地板的路。不是因为我经常用——我从来不需要 fork Postgres——而是因为知道地板可以到达,会改变我在上面构建的方式。
在用户的椅子上,我爱围墙花园。我想诚实一点,因为开发者们常常在这件事上不诚实。Claude Code 是一款杰出的产品。它的连贯性,就像一小群有品味的人做决定、而且不用向邮件列表为每一个决定辩护时,事物所呈现出的那种连贯性。这种连贯性是有代价的,代价就是我的灵活性,而大多数日子里我都很乐意付这个代价,甚至一次都没想过。一个从不逼我打开源码的工具,一定在某些地方做对了。
在创始人的椅子上——这是我反复琢磨的那把——我完全理解那堵墙。
我可以轻松构建一个高尚版本:开放平台,赢得生态,让社区去发现你永远也雇不到人的那些用例。我相信这个版本。但我也见过足够多的公司被这种开放“淘空”,知道它不是免费的,而且“我们把核心开源了”这句话,有时候是裁员的前奏。
所以当我问自己我会怎么做——面对我自己的产品,那个我花了几年时间和真金白银打造的产品,那个一旦开放核心就等于给资金雄厚的竞争对手送上起跑优势的产品——我得不到我想要的答案。我得到的是:我没法自信地说我会做出不同的决定。
我和这个念头坐了一会儿,然后决定不给自己一个偏袒的答案。大声坚持开发者的观点很容易,因为对别人的生意要求开放,不花自己一分钱。创始人的椅子,是观点被贴上价签的地方,而我宁愿承认我不知道自己会付多少,也不愿假装已经付过了。
理解一个决定,不等于喜欢它的结果。这两者可以同时成立,而我觉得在我身上,它们都成立。
我不知道的,以及不打算装知道的
我不知道 DeepSeek 为什么开源这个。
我可以罗列一些貌似合理的理由——针对封闭实验室的战略定位、招聘、真正的研究文化,以及一个简单的事实:Cordis 本来就是开放的,把它关掉才奇怪。这些都是可能性。我对任何人的动机都没有窥探的窗口,而从一份许可证文件出发,给一家公司的灵魂编造一个讨喜的故事,正是我在互联网上不想再看到的那种事。
相关地:我看到有人暗示,这可能是 Anthropic 用来回应的招式。据我所知,Anthropic 对 DeepSeek 的 harness 完全没说过什么,我不想为了把故事讲得更顺就去编造一场竞争。真相其实更有趣,而且方向正好相反——DeepSeek 的论文把 Anthropic 自己关于 harness 设计的工程文章作为前期工作来引用,和 OpenAI 的并列。封闭实验室发表了思考,开放项目引用了它,并交付了一个附带证明的实现。关于开放/封闭的分界线到底在哪里,这幅图景比双方通常讲的故事都更奇怪,也更准确。
有一件事我可以毫不含糊地说:开源这个是一个选择,它看起来不是最有利可图的那个,而我注意到了。
我正走向的那把椅子
我也在构建一些东西。不是那种规模,还没有,也许永远不会。但一旦你有了值得保护的东西,这个问题就不再抽象;而我宁愿在那之前想清楚,而不是在过程中才想。
所以我故意留着这个问题不解决,因为现在解决它,只会是一场表演。我手里有的是三句同时为真的句子,这也是我目前能占据的最诚实的位置:
作为用户,我欣赏一座美丽的围墙花园。
作为开发者,我一直在找那扇门。
作为创始人,我完全理解那堵墙为什么在那里。
而当有人选择让一扇门敞开着,我会注意到。这不是一个论点,只是我手里所有的东西。
我们不应该害怕表达观点。我们应该害怕的是那些被装饰成真理的观点——包括,尤其是,我们对自己讲的那些讨喜的观点。
免责声明:本文由人类撰写,在适用处使用 AI 改进。