第三章 只有起重机计算不可压缩与中间结构上一章把工具解释成了一种抽象边界。一个更根本的问题随之而来为什么复杂任务总会逼出边界为什么系统总会长出计划、模块、接口、测试这些中间层为什么一句话把事情说清楚一次对话把任务做完在很多场景里根本不成立如果这个问题不说透工具就很容易被理解成临时补丁——好像只是因为模型现在还不够强我们才不得不把流程拆开、把状态存下来、把验证放进系统里。可真正的问题不在这里。很多时候不是模型暂时不够强而是任务本身就不允许你把整个过程压扁成一次性的表达。AI 工程里有一种对天钩Skyhook的迷思。丹尼尔·丹尼特用天钩比喻那种悬在空中、不需要基础支撑、试图一步到位解决复杂问题的奇迹力量与之相对的是起重机Crane——它必须拔地而起依赖坚实的底座和一层层中间结构才能把重物吊到原本无法企及的高度。试图让 LLM 靠一次 zero-shot 的前向传播直接吐出一个修改了 50 个文件的完美 PR就是典型的天钩思维。但真实的工程和自然界的演化一样只能依靠起重机。起重机为什么不可绕过因为物理世界和代码环境的计算是不可压缩的Computational Irreducibility。这不是修辞是一种工程现实——你无法用一个公式直接算出重构一个复杂系统会遇到什么依赖冲突必须亲自去跑一遍。所谓不可压缩并不是说任何细节都不能封装而是说任务里总有一部分关键展开过程不能整体跳过你仍然要观察、判断、修改、验证、修正。中间结构就是在这个过程中被逐步构造出来、又能被后续继续利用的承载物——函数、模块、工具、计划、任务树、测试、回放入口都是中间结构。这解释了为什么本书不太相信一句话生成复杂系统。它当然能在演示里制造冲击感因为屏幕上确实会突然出现很多内容。但真正决定系统能不能成立的从来不是那句 prompt 写得多漂亮而是后面有没有足够多的中间结构去承接复杂性需求要被拆开边界要被明确局部结果要被保存失败要能被定位正确性要能被验证后续修改要有落点。被压缩的通常只是人类亲自参与每一步的比例而不是整个过程本身。换一个更日常的角度这件事并不难理解。人类写程序时从来不直接面对机器语言的全部复杂性——我们定义函数、用模块切分责任、用数据结构封装局部状态、用高级语言屏蔽底层指令、用测试保护已经成立的边界。做数学也一样你不会在每次推导时都回到底层公理重新开始而是先定义概念再证明引理再把引理当成后续推理的可靠前提。起重机能吊起远超个体力量上限的重量不是因为它突然拥有了某种神秘能力而是因为它把结构、杠杆、材料和分工组织成了一个稳定系统。复杂任务的推进靠的从来不是一次性整体掌握而是站在一层层已经成立的中间结构上继续往前搭。顺着起重机往下想会引出一个关于软件本质的判断软件不是一次性设计出来的而是带着历史演化出来的。赫伯特·西蒙曾指出没有历史的简单事物很容易被复制就像模具翻模但生物体和复杂系统不行。如果一个生物体完美适应环境人们看到的很大程度上只是环境的形状只有当它不适应、暴露出错误时内部结构才会显现。DNA 如此复杂的软件系统也是如此。软件演化本质上是一种搜索搜索空间由代码、架构、用户体验、运行环境和历史约束共同构成方向无法完全先验知道。这等价于把一个过于庞大的最优化问题转成判定问题——既然搜索最优解太复杂那就先给出大概的结构和假设再扔进真实 case 和运行环境中让环境的反馈、报错和运行结果充当那个最真实的判定函数。我们不再追求一次性推导出最优解而是通过环境对一个个 case 的不断判定一步步逼出可用的结构。这条路绕不开探索-利用的张力只探索系统不断试新方案却积累不下稳定结构只利用系统困在已有设计里无法吸收新知识。中间结构的作用就在这里——让探索不至于散掉让利用不至于僵死。测试、CI、日志、接口、模块、设计文档都在保存已经成立的局部结果也在暴露下一步需要调整的边界。复杂系统几乎从来不是纯粹自顶向下设计出来的也不是无约束自底向上长出来的顶层先给出若干边界、接口、验证方式和不可破坏的约束这就是判定标准底层再在具体 case 中不断试探、修正、收敛这就是接受判定。两条路线不是对立的是同一过程的两面。试图用大模型一步生成极致体验的软件违背了这个演化规律。极致软件之所以极致是因为它经历了无数次与真实环境的碰撞、报错、重构与打磨而且大部分极致的商业软件并没有公开源码供模型学习。Agent 设计软件不能走简单复制的模具路线必须走演化的生物路线通过行动获得反馈通过反馈修正方向通过中间结构把新知识融入系统。从这个角度看抽象的作用也清楚了。抽象不是为了让描述更优雅而是为了让每一个时刻需要同时关注的上下文更少。上下文始终是稀缺资源不管对人还是对模型都一样。没有人会在修改一个登录模块时把编译器实现、数据库存储格式、网络协议、UI 状态机、部署脚本和业务流程同时装进脑子里——模型也不会。可行的做法是把已经被理解、被验证的复杂性封装到边界之后让当前这一步只处理它真正需要面对的那部分。函数把一段局部实现藏在函数名之后模块把一组内部协作藏在 API 之后工具把和外部世界的交互藏在稳定接口之后——它们做的是同一件事缩小当前视界让上层不必重新展开底层过程。把这个过程画成一张图大致是这样复杂任务中间结构局部验证继续推进图很简单但表达了一个经常被忽略的事实复杂任务不是先想明白再一次做完而是先构造中间结构再验证中间结构再站在它上面继续推进。系统真正的前进方式不是整体压缩而是逐层展开、逐层收束。这也解释了为什么本书把函数、模块和工具看成同一条链上的不同层级。函数压缩的是局部操作模块压缩的是一组相关责任工具压缩的是可调用的外部能力——表现形式不同、抽象层级不同、使用场景不同做的却是同一件事把一部分已经能稳定处理的复杂性收束在边界之后让后续步骤不必再从零面对它。Agent 的价值也不只是多做了几步而是它开始能在过程中不断制造、利用和沉淀这些中间结构。现实里的项目已经把这条链长出来了。Superpowers 强调先澄清需求再收敛设计和计划再执行与验证——这不是流程偏好而是因为计划本身就是中间结构它把一整块模糊任务先压成一组较短、可验证、可交接的子任务。OpenHarness 里的resume不是重新规划而是把先前保存的会话重新装回运行过程让系统不必从空白上下文重新开始。长期会话里的自动压缩和 replay 负责的也不是一回事压缩负责把过长历史收束成较短摘要replay 负责把这份摘要和仍然保留的关键上下文重新组织起来变成后续运行真正要消费的入口。OpenClaw 的设计更能说明这一点——它不试图完整保留旧历史而是努力把历史压短同时保住一个后续还能继续工作的入口。这些实现各不相同但都在验证同一个判断任务足够复杂时系统一定会主动制造计划、摘要、回放入口和测试因为没有这些中间结构它根本无法连续推进。接受这一点之后很多看起来对立的说法就会清楚下来。比如有人会问既然模型越来越强为什么还需要这么多外部结构答案不是模型不重要而是模型再强也仍要面对展开过程本身。模型可以加速局部理解、压缩探索空间、帮助构造和选择中间结构但它不能让这些结构在一般情形下凭空消失。你可以减少人工介入的频率、缩短局部试错的成本、更快地生成候选方案但你仍然要有边界、有中间结果、有验证机制。否则系统得到的只会是一串看起来连续的输出而不是一个能真正成立、能继续演化的复杂系统。复杂系统之所以复杂不只是因为元素很多真正麻烦的是元素之间依赖很强而这些依赖不能被低成本地全部展开。大型代码库的行为不能从局部直觉推出分布式系统的表现不能仅靠接口文档预测长期运行的 Agent 下一步会怎么走也不能仅看 prompt、工具、上下文和模型单独的样子。复杂系统必须依赖分层不是人类偏爱层次结构而是不分层就根本无法继续操作——高层建立在低层之上但高层行为又不能在每次判断时都完整还原到底层。中间结构不是装饰是系统得以存在的条件。所以 Agent 工程最终不会收敛成更好的 prompt 写法。Prompt 是入口约束不是复杂度本身的解决方案。真正接住复杂度的是后面长出来的那一整套结构工具、状态、测试、回放、权限、验证、恢复。它们存在不是因为工程保守也不是因为模型太笨而是因为复杂任务本来就需要中间结构。Agent 压缩的是探索性计算里人类逐步试探的成本工具和抽象边界压缩的是已经可以被稳定表达和重复使用的部分。二者结合系统才能既保留灵活性又不失工程上的可控。既然复杂任务必须逐层推进系统在多步过程中到底靠什么维持连续性目标怎么不丢局部结果怎么不散先前做出的判断怎么在后续继续起作用只有先回答这些问题系统才谈得上把处理路径抽象成更高层的工作单元。