架构作为约束:缩小 AI 的解空间
在我过去这些年参与过的许多项目里,迟早都会出现一句话。说法可能不同,但意思往往一样:
“我们不需要架构师。”
有时,这句话说的确实就是这个岗位本身。有时,它表达的是另一种想法:架构反正会由团队自然形成,因此没有必要给予它特别的关注。更麻烦的是,这种方式在一开始往往真的能工作得相当不错。Feature 被实现,Release 被交付,技术决策则在它们刚好需要被做出的地方被做掉。
问题很少会在第二天暴露出来。它是在多年里逐渐形成的。
某个 Service 直接访问了本来应该位于另一条 Boundary 之后的内容。一个紧急 Use Case 让某次例外显得合情合理,而后来这次例外又成为下一次例外的参考。一个已有 Pattern 旁边出现了第二个,然后又是第三个。State 有了多个 Owner。Feature 开始使用其他 Feature 的内部实现。新加入的开发者几乎可以为任何结构性决策找到某个已经存在的例子,用来证明它是合理的。
到了某个时刻,已经没人能清楚说出:到底哪一条路才是原本想要的那一条。
这并不是 AI 时代才出现的新故事。几十年来,Software Engineering 一直在处理模块化、Information Hiding、Cohesion、Coupling、稳定接口、Dependency Direction 以及清晰职责这些问题。David Parnas 在 1972 年发表了关于模块划分的基础性工作。1974 年,Stevens、Myers 和 Constantine 在 Structured Design 中描述了通过功能模块降低复杂度的原则。到了 1990 年代末,Foote 和 Yoder 给一种特别极端的反面形态起了一个后来非常著名的名字:Big Ball of Mud。
Coding Agent 并没有发明这些问题。真正变化的是吞吐量。
Coding Agent 可以用一种纯人工团队很难达到的速度去修改代码、测试、配置和文档。OpenAI 在 2026 年 2 月的一篇实践报告中描述了一个内部项目:其中的代码全部由 Codex 生成,一个小团队在几个月里合并了大约 1,500 个 Pull Request。这些数字不是通用的生产力 Benchmark,但它们确实说明,系统可能发生变化的速度可以被显著放大。
于是,一个老问题突然变得更紧迫了。
Agentic Software Development 中的许多问题,其实是更高吞吐量下的老软件问题。
如果过去一个月只会做十次局部结构决策,而未来会做一百次,那么这些决策的性质本身未必发生变化。但不一致的决策会更快复制、更快成为新的范例,也更快改变系统结构——而下一个 Agent 又会从这个结构中提取自己的证据。
这正是为什么,在 Agentic Work 的语境里,我会因为一个非常具体的原因重新审视架构。不是因为“好的架构很重要”是什么新鲜结论,而是因为:
架构会缩小 Coding Agent 的决策空间。
Requirements 只是第一道边界
Section titled “Requirements 只是第一道边界”上一篇文章把 Requirements 描述为一道边界。Coding Agent 可以构造不同的解决路径,但这并不意味着每一种结果都可以接受。
Requirements 回答的是这样的问题:
业务上必须满足什么?
哪些状态是允许的?
什么叫成功?
哪些错误场景必须处理?
什么不属于 Scope?它们缩小的是业务结果空间。
但假设所有这些问题都已经被完美回答了。Agent 精确地知道 Feature 最终必须做什么。即便如此,要达到这个结果,结构上仍然可能存在很多不同的实现方式。
架构就是从这里开始的。
Requirements 限制的是业务结果空间。架构限制的是结构性解空间。
简化来看:
所有可能的解决方案↓Requirements↓业务上允许的解决方案↓Architecture Constraints↓结构上允许的解决方案↓更小的决策空间
这并不是说,架构应该为每一个具体 Task 提供一份完整的施工说明。
Agent 仍然应该能够做局部决策。它可以用不同方式拆一个辅助函数,可以用不同方式写一个循环,也可以在某个模块内部决定哪一种具体实现最适合当前问题。
架构真正定义的,是那些我不想在每一个 Feature 上重新做一遍的决策。
Presentation 能不能直接访问 Infrastructure?
Feature A 能不能 Import Feature B 的 Internals?
某个 State 到底由谁拥有?
一个模块应该通过哪个 Contract 被访问?
哪一种 Dependency Direction 是有效的?
这些都是具有更大结构性后果的决策,远比“一个局部函数该怎么写”影响范围更广。
好的架构不会替 Agent 拿走所有决策。它主要拿走那些本来就不应该在每个 Feature 上重新做出的决策。
当 Repository 给出六个正确答案时
Section titled “当 Repository 给出六个正确答案时”来看一个业务上很简单的改动:某个 Component 需要新的数据。
在一个长期生长出来的 Repository 里,Agent 也许会看到这些变体:
Component → API
Component → Shared Service → API
Component → Store → API
Component → Feature Service → API
Component → 其他 Feature → API
Component → 历史 Utility → API问题不一定是这六种方式都显然很差。
也许它们真的都存在。
也许它们都在某个地方稳定运行在生产环境中。甚至每一种都拥有一段完全说得通的历史。直接 API 调用来自系统初期。后来引入了 Shared Service。新的团队使用了 Store。另一个 Feature 拥有自己的 Application Service。最后,为了一个紧急的特殊场景,又复用了相邻 Feature 中已有的 Flow。
那么 Coding Agent 应该从这些代码里学到什么?
一个经常出现的指令是:
遵循现有 Pattern。在我们真正打开 Repository 之前,这句话听起来非常精确。可问题是:到底哪个 Pattern?Agent 可以打开不同的文件,并为互相矛盾的多个方案分别找到本地证据。Codebase 同时对它说:
我们这里就是这么做的。以及:
不,我们这里是这么做的。到这里,变异性 已经不再只是模型的属性。Repository 本身拥有一个含糊不清的结构性解空间。
“遵循现有 Pattern”只有在系统里确实存在可辨认的 Pattern 时才有意义。
Agent 可以尝试根据出现频率、新旧程度、空间邻近性或者 Naming 去判断哪个例子更相关。它可以继续查文档,也可以再打开更多文件。最后它甚至可能做出正确的判断。
但这些行为中的每一个,都意味着额外的解释工作。
全局的架构决策没有被提前做出,因此 Agent 只能在一个局部 Feature 的实现过程中把它重新推导出来。
架构消除的是不想要的 变异性
Section titled “架构消除的是不想要的 变异性”现在换一个系统。假设在这个区域中,下面的规则是明确且有效的:
Presentation↓Application↓Domain↓Infrastructure这套 Layering 不是一个普适的架构建议。另一个系统完全可能更适合 Vertical Slices、Ports and Adapters、Modular Monolith、Self-contained Systems,或者完全不同的结构。
关键并不是这个具体的图。
关键是,这个结构表达了一个明确的判断。
如果 Presentation 不允许直接访问 Infrastructure,那么一整类结构性方案就从可接受的空间中消失了。如果某个业务模块只能通过它的 Public Contract 被访问,又会有更多变体被排除。如果 State 有一个明确的 Owner,那么 Agent 就不需要在每个 Feature 上重新决定“在哪里再放一个第二事实源会比较方便”。
Agent 仍然是概率性的。它仍然可以在允许的结构里生成不同的解决方案。这正是我们想要的。
架构不会消除 变异性。它消除的是不想要的 变异性。
对我来说,这正是经典软件架构与 Agentic Development 之间最重要的连接之一。
我们不是在试图把 Coding Agent 变成一个确定性的 Compiler。我们是在定义:哪些自由有价值,哪些自由会制造结构风险。
更少的边,不只是更好看的图
Section titled “更少的边,不只是更好看的图”“模块化”很容易变得抽象。真正有意思的是把视角转向依赖关系。
想象一个业务模块:它有清晰定义的 Responsibility,自己控制自己的 State,只需要很少的 Dependencies,并且只能通过一个很小的 Public Contract 被使用。
它的结构邻域是有限的。
对于其中的一次修改,也许真正相关的是五个文件、两个 Contract 和一个外部 Adapter。当然,Agent 依然可以去调查其他区域。但架构已经提供了一个很强的先验判断:相关信息原则上应该在哪里。
直觉很简单:
允许的边更少↓结构性备选方案更少↓潜在相关的 Repository 区域更少↓更小的决策空间这不是数学定律。一个很小的模块在业务上也可能极其复杂。一个依赖很少的系统可能文档很差。低耦合也无法保证 Requirements 正确,更无法保证代码正确。
但架构会改变“看起来合理的结构路径”的数量。
相反,一个高耦合区域会拥有很多入口和出口。一次改动可能影响 State、Services、Utilities、其他 Features 和全局机制。即使最后真正只需要改三个文件,最开始“可能相关”的环境也会大得多。
Agent 需要先把更多东西排除掉。
因此在 Agentic Work 里,我认为 Loose Coupling 至少和“模块化”这个抽象目标同样重要。低耦合不仅会降低人的 Change Radius 和协调成本,它也会同时限制 Agent 在 Exploration 中必须考虑的结构关系数量。
经典研究在 LLM 出现之前很久就已经研究了这个方向。早在 1974 年,Stevens、Myers 和 Constantine 就把 Structured Design 描述为一种通过功能模块降低程序复杂度、从而让 Coding、Debugging 和 Modification 更容易的方法。Cohesion 与 Coupling 也由此成为 Software Design 的基础概念。
当然,如果说这些作者是在为 Coding Agent 设计原则,那会是完全不符合历史语境的说法。
他们设计的是软件原则。而正因为如此,今天的观察才有意思:那些帮助人类局部理解系统、并以受控方式修改系统的特性,也可能对 Agent 变得重要。
SCS 作为一个直观例子
Section titled “SCS 作为一个直观例子”Self-contained System 是一个很好的思维模型。
SCS 架构描述的是按业务切分、相对自治的系统。它们拥有自己的数据存储和 Business Logic,尽可能独立完成自己的职责,并有意识地降低与其他区域的耦合。共享 Business Logic 应该尽量避免,同步依赖也应该在合理范围内受到限制。
对于这里的论证,一个具体项目是不是真的采用 SCS 并不重要。
真正有意思的是边界本身的形状:
┌───────────────────────────────┐│ 业务领域 ││ ││ UI ││ Business Logic ││ State / Data ││ 技术 Adapter ││ │└───────────────┬───────────────┘ │ 少量显式 Contract │ ▼ 其他系统这样的区域会直观地给 Agent 一个相对清晰的工作空间。业务 Responsibility 有自己的位置。数据所有权有自己的位置。外部关系有限,而且可见。
我并不知道有任何可靠研究能够证明 Self-contained Systems 在科学意义上“对 LLM 更好”。如果这样说,会是过强的结论。
这里使用 SCS,只是把它作为一个更一般原则的架构例子:局部责任和少量显式的边。
同样的原则,在一个 Modular Monolith 内部也完全可以成立。
Big Ball of Mud 会提供互相矛盾的证据
Section titled “Big Ball of Mud 会提供互相矛盾的证据”它的反面我在这个网站上已经详细讨论过:Big Ball of Mud。
Foote 和 Yoder 用这个词描述一种结构松散、甚至只是偶然形成的系统。它的组织方式更多来自短期便利,而不是一致性的设计。他们描述了不受控制的增长、反复出现的临时修补、大范围共享或重复的信息,以及一种要么从未清晰过、要么随着时间不断侵蚀的结构。
对于 Agentic Work,我尤其关心其中一个属性:
Repository 本身会变成互相矛盾的证据。
一切都认识一切
很多可能路径
互相矛盾的 Pattern
历史特殊情况
不清晰的 Ownership
隐式 Dependencies
Agent 在这种系统里可能不是找不到例子,而是找到太多例子。
API 访问有五种方式。State 有三种模型。两个 Feature 通过它们的 Public Contract 互相访问,另外四个则直接 Import Internals。一个新 Pattern 被引入,却没有把旧 Pattern 完整替换掉。一些例外如今甚至比原来的规则出现得更频繁。
于是,任务从“实现”变成了“解释”。
哪段代码才是范本?
哪个文件只是历史包袱?
某种偏离是有意设计,还是偶然留下?
出现最多的 Pattern 是真正想要的,还是仅仅因为它最老?
第 6 篇文章已经解释过,为什么局部看起来合理的决策会参与制造 Drift。这里没有必要再次推导这个机制。新的结论是:
架构是一种机制,用来缩小 Drift 从一开始就可能发生的空间。
如果想更深入理解它与 Big Ball of Mud 的关系,可以阅读我现有 Big Ball of Mud 系列中的 AI 和 Big Ball of Mud。
这个想法比我们大多数编程语言都更老
Section titled “这个想法比我们大多数编程语言都更老”这条讨论的时间跨度,我觉得很有意思。
1972 年,David Parnas 比较了两种不同的系统模块划分方式。他的核心观察并不是一句简单的“模块很好”。真正重要的是:模块是按照什么标准形成的。模块化应该提升灵活性和可理解性;Information Hiding 应该把设计决策,尤其是那些困难或者很可能变化的决策,隐藏在合适的模块边界之后。
这个思想今天看起来仍然很现代:
一次修改不应该要求人重新理解整个系统。
某些知识应该有明确的 Owner。
其他区域应该尽可能少知道内部决策。
接口应该承载稳定的假设,而不是任意的实现细节。
两年后,Structured Design 又用模块内部的功能性绑定,以及模块之间尽可能受控的关系,表达了相近目标。此后的术语与方法不断变化。面向对象、组件模型、Services、Domain-Driven Design、Microservices、Modular Monolith 以及许多其他架构方式,都加入了新的抽象。
但最底层的愿望几乎没有变:
局部理解局部修改限制全局影响Coding Agent 带来了新的技术边界条件:有限 Context、Repository Retrieval、Tool Calls、概率性的解决路径,以及必须从已有代码中推导结构规则。
但它们撞上的系统问题,比这些技术都老得多。
那些几十年来帮助人类理解大型系统并安全修改系统的特性,对 Agent 同样值得关注。
不是因为 Parnas 预见了 AI。
而是因为,如果 Repository 的结构能够把相关关系与无关关系分开,Agent 也更容易在其中工作。
没有架构师,架构工作也不会消失
Section titled “没有架构师,架构工作也不会消失”在这里,完全可以从我的个人项目经验中构造出一个非常方便的岗位论证:
“你看,所以每个项目都需要一个 Software Architect。”
对我来说,这太简单了。
一个项目并不一定需要一个拥有这个精确 Job Title 的人。架构责任可以位于 Tech Lead,可以由团队共同承担,可以通过 Platform Ownership 分散,也可以通过清晰的 Engineering Process 与技术 Constraints 被制度化。
但有一种想法是不成立的:因为没有人正式负责架构,所以架构决策就会消失。
架构工作不会因为没人拥有“架构师”这个角色而消失。架构决策只会在其他地方被做出来——而且往往是局部的、隐式的、不一致的。
每一个新的 Import 都在做架构决策。
每一个新增的 State Writer 都在做一个。
每一个新的 Shared Library 都在做一个。
每一次直接跨越本来应该存在的 Boundary,也是在做一个。
唯一的问题,是这些决策究竟是在共同框架内被有意识地做出,还是随机散落在不同 Ticket 里。
因此,对我来说,架构不需要某个特定的岗位名称,但它需要责任。
架构是风险管理
Section titled “架构是风险管理”我对一致性有一个相对严格的个人标准。在我的项目里,这一点大概很快就能被看到。
如果某个 Feature 的结构和其他所有 Feature 都不一样,我会不舒服。如果一个 Layer 不再拥有明确 Responsibility,我会不舒服。如果 State 没有明确 Owner,或者某条 Dependency “只这一次”跨越了 Boundary,我也会不舒服。
这很容易被看成一种架构完美主义。但对我来说,背后真正的原因已经变成了另一件事。
架构是风险管理,不是完美主义比赛。
一条架构规则有价值,是因为它让某种糟糕的未来状态变得更不可能,甚至彻底不可能。
例如:
Feature A 不允许内部 Import Feature B。这条规则并不能保证软件一定好。但它会降低 Cross-Feature Coupling 在多年里悄悄增长的风险。
Presentation 不允许直接调用 Infrastructure。这条规则同样不能保证 Business Logic 的质量。但它会减少 UI Orchestration、技术访问逻辑与业务决策被混在一起的地方。
或者:
State 有一个明确的 Owner。这不会解决所有 State Management 问题。但它会减少互相竞争的事实,以及可能的写入路径数量。
这是我用来判断架构规则价值的尺度,比单纯看图更有意思。
它到底降低了什么风险?
如果我回答不了这个问题,也许这条规则本身也并没有那么有价值。
架构是 Codebase 的语法
Section titled “架构是 Codebase 的语法”在上一篇文章里,我写过一个个人原则:
项目应该读起来像是一个开发者写出来的。
从架构角度,我现在会把它再说得更精确一点。
架构就是 Codebase 的语法。
一种语言并不要求每个句子完全相同。不同作者可以表达不同内容,可以选择不同词汇,也可以用不同方式描述问题。但语言有规则:某些结构属于这门语言,另一些不属于。
映射到 Codebase 上,这意味着两个 Agent 并不需要生成完全相同的局部实现。Agent A 可以用不同于 Agent B 的方式写一个小的辅助函数。Agent C 也可以在自己的模块内部选择另一种算法,只要它们都满足相同的 Invariants。
我真正想避免的,是每一个模型都发明一套新的系统语法。
Architecture ↓ ┌───────────┼───────────┐ ↓ ↓ ↓ Agent A Agent B Agent C ↓ ↓ ↓ 不同的局部方案 ↓ 相同的结构语法正是在这里,架构帮助我们处理模型 变异性。
不同的生成不必导致不同的系统结构。
用 Invariants,而不是 Micromanagement
Section titled “用 Invariants,而不是 Micromanagement”这个边界很重要,因为 Architecture Constraints 很容易滑向另一个错误方向。
如果我把每个 Method Call、每个辅助函数、每个中间文件、每一个实现步骤都规定给 Agent,我当然也缩小了它的解空间。
但那样我主要是在把 Agent 当作一个非常昂贵的键盘。
更有意思的 Constraint 是这样的:
Invariant:Presentation 不允许直接调用 Infrastructure。
开放:在允许的 Layer 内部,局部辅助函数如何实现。或者:
Invariant:业务模块只能通过它的 Public Contract 被使用。
开放:模块内部如何实现这个 Contract。OpenAI 在自己的 Agent-first 实践报告中描述了非常类似的区分:Invariants 被固定下来并机械执行,而具体 Implementation Details 则被有意识地留出空间。例如,团队要求数据形态必须在系统边界被 Parse,但并不规定必须使用哪个具体 Library。
对我来说,这正是正确的抽象层级。
架构固定的是昂贵的决策,局部决策则保持开放。
这里的“昂贵”并不一定是金钱意义上的昂贵。它指的是拥有高结构性后续风险的决策:Dependency Direction、Ownership、模块边界、Contracts,以及某一种 Responsibility 到底可以出现在哪里。
这些事情如果每次都重新决定,创造的价值很少,制造的 变异性 却很多。
解释架构、让架构可见、让架构可执行
Section titled “解释架构、让架构可见、让架构可执行”这会带来一个很实际的问题。
一种架构可以真实存在,但对 Agent 来说依然几乎不可见。
第一层因此是文档:
Architecture DocsADRsAgent FilesLayering 说明Dependency Rules文档很重要。它可以解释为什么某条 Boundary 存在、考虑过哪些 Trade-off、哪些情况被有意识地特殊处理。
但文本有自己的限制。它可能被忽略、过时,或者被误解。在大型 Context 中,它也可能被 Task 描述、代码、Tool 输出和其他文档淹没。
例如 OpenAI 就提到,在它自己的项目里,一个庞大的单体 AGENTS.md 正因为这个原因而不好用:大量 Guidance 必须和 Task、Code 以及真正相关的文档争夺有限的 Context。后来,一个较短的 Agent File 更像是一张地图,把 Agent 引导到更深层的 Repository 文档。
因此,文档化架构是必要的,但它并不是最强的 Constraint。
第二层,是架构已经能直接从 Repository 中被看出来。
例如:
orders/ presentation/ application/ domain/ infrastructure/或者:
billing/catalog/identity/orders/模块之间通过清晰的 Public Contracts 连接。
具体的文件夹结构依然不是重点。关键在于,物理结构和架构结构不要互相矛盾。
如果所有 Infrastructure Adapter 都只包含技术转换和 I/O,Repository 本身就会产生局部证据。
一个突然包含 Business Rules 的新 Adapter 会非常显眼。
如果所有 Feature 都有一个小而清晰的 Public Entry Point,而且不允许直接 Import Internals,那么一次 Deep Import 就会显得很不寻常。
如果每个 State 都只有一个 Owner,那么第二个 Writer 会显得可疑。
一致性会让偏离变得可见。
这也是为什么我喜欢“无聊”的 Layer。
Infrastructure Layer 完全可以很无聊。API Adapter 完全可以长得很可预测。正是这种可预测性有价值,因为 Agent 不需要先从五十种创意变体里推断这个 Layer 的 Responsibility 到底是什么。
Codebase 越稳定地表达自己的语法,现有代码就越能成为可靠证据。
让架构可执行
Section titled “让架构可执行”第三层,会再次改变规则的性质。
我们不再只是解释:
Feature A 不应该内部 Import Feature B。而是让 Architecture Test 直接拒绝这个 Import。
我们不再只是写:
Presentation 不允许使用 Infrastructure。而是让 Dependency Constraint 把这种状态判定为无效。
我们也不只是希望 Contract 被遵守。
Type、Schema、Test 和 CI 会验证它们。
根据技术栈不同,可以使用不同工具:
- Dependency Constraints,
- Architecture Tests,
- Import Restrictions,
- Linter Rules,
- 模块边界,
- Type 与 Schema 检查,
- Structural Tests,
- CI Verification。
具体工具不如机制重要。
解释架构↓让架构可见↓让架构可执行
到了最后一层,架构规则会成为 Verification Loop 的一部分。
最强的架构规则,是 Agent 无法在不被发现的情况下违反的规则。
这和下面这样的说明,在性质上完全不同:
请不要做 X。Guidance 会变成:
X 不是系统的有效状态。Coding Agent 可以尝试越过 Boundary。Linter 会反对。Architecture Test 会失败。Build 会提供新的证据。然后 Agent 可以修正。
这时,架构不再只是 Context。
它变成了可执行反馈。
OpenAI Agent-first 开发中的一个当前实践案例
Section titled “OpenAI Agent-first 开发中的一个当前实践案例”正是这一点,让 OpenAI 的报告 Harness engineering: leveraging Codex in an agent-first world 对我来说非常有意思。
这篇报告不是科学研究,它描述的是一个非常特殊、极度 Agent-centric 的内部软件项目。因此,它的结论不能被当作普遍定律。
但作为实践案例,它依然非常值得注意。
OpenAI 在其中描述了业务 Domain 内固定的 Layer、被严格验证的 Dependency Direction,以及数量有限的允许边。Cross-cutting Concerns 通过显式机制进入 Domain,其他 Dependency Path 则被禁止。Custom Linter 和 Structural Tests 会自动执行这些规则。同时,团队明确提出一个原则:执行 Invariants,而不是 Micromanage Implementation。
报告从中总结出一个很强的实践经验:Agent 在具有严格边界和可预测结构的环境中工作得尤其有效。在这个具体项目里,OpenAI 甚至把这些 Constraints 描述为实现高吞吐量、同时避免结构退化或 Architecture Drift 的前提。
我不会由此得出这样的结论:
OpenAI 已经证明:严格 Layering = 最好的 AI 架构。这篇报告没有证明这一点。
它真正展示的是更有意思的事情:一个持续以 Agent-first 方式开发软件,并产生异常高 Generation Throughput 的团队,会非常早地投资于 少量允许的 Dependency Path 和可机械验证的 Invariants。
这与本文推导出的机制非常接近。
老原则遇上新的 Context 问题
Section titled “老原则遇上新的 Context 问题”目前关于 Coding Agent 的研究,也已经开始集中在 Repository 结构真正重要的那些地方:Context Selection、Fault Localization、Repository Navigation 和 Dependency Reasoning。
这些结果并不能证明,“干净”的架构方式一定会自动产生更好的 Agent 结果。
但它们确实表明,结构信息对 Agent 可以具有非常实际的价值。
2026 年的 Preprint Repository Intelligence Graph,例如会向 Agent 提供一张从 Build 与 Test 信息中确定性推导出来的架构图。在对三个商业 Agent 与八个 Repository 的研究中,结构性问题上的平均准确率相对提高了 12.2%,处理时间下降了 53.9%。同时,这项研究也有明显限制:只有八个 Repository,其中七个是 Synthetic;并且对于部分 Agent,它测量的是时间而不是真实 Token 消耗。更重要的是,它研究的是已有架构如何被表示出来,而不是架构本身的质量。
LLM Agents Can See Code Repositories 已被 ASE 2026 接收,它研究的是另一种结构性支持方式:除了普通的文本接口之外,再额外给 Agent 提供可视化 Repository Graph。在被研究的设置中,Input Token 使用量最多下降了 26%,Issue-Resolution Accuracy 则保持不变或提高。反过来,只使用视觉信息的方式效果更差,而且 Token 成本更高。同样,这里的结论并不是“模块化架构需要少 26% 的 Token”。这项研究考察的是如何向 Multimodal Agent 表示 Repository 结构。
DyRetriever 同样被 ASE 2026 接收。它使用 Partial Dependency Graph,在 Repository-Level Code Generation 中沿着 Dependency 有针对性地收集相关 Context。作者报告,与被比较的 RAG Baseline 相比,在 CoderEval 与 DevEval 上分别获得了 25.63% 和 59.73% 的相对 Pass@1 改善,同时相比需要静态构建 Dependency Graph 的 Baseline,速度高出 7.4 倍。这说明 Dependency Structure 可以帮助 Context Retrieval——并不说明某一种软件架构 Pattern 已经被证明更优。
其他最新工作也符合这个图景。Agent Retrieval Bench 把一个问题单独隔离出来:Agent 到底能不能找到下一步真正需要的文件。在分析过的 Logged Trajectory 中,有 27% 到 35% 的样本连一个 Gold File 都没有找到;与此同时,在受控 Intervention 中,Retrieval-based Initial Context 比随机的无关 Context 需要更少的后续 Exploration。
RepoMirage 则报告,Agent 在更依赖 Repository-Context Reasoning 的任务里可能显著掉分,并描述了一种作者称为 exploration drift 的模式:Agent 访问更多 Repository Context,却不能稳定地把更多 Exploration 转换成正确的结构理解。一个两阶段的 Structure-first 方法在实验设置中改善了结果。不过,这仍然是 2026 年的 Preprint 或 Workshop 工作,不能被当作通用架构规律的证明。
因此,研究目前还没有直接回答我们的架构问题。
但它已经很好地说明,为什么这个问题值得研究。
Repository NavigationContext SelectionDependency ReasoningFault Localization有限 Context是 Coding Agent 的新技术问题。
清晰模块少量 DependenciesInformation Hiding稳定 Contracts局部责任则是 Software Engineering 很早就给出的答案,用来解决另一个问题:为了安全修改系统的一部分,我们究竟需要理解多大范围的系统?
现在,这两条线开始相遇了。
更小的解空间是否也意味着更少的 Token?
Section titled “更小的解空间是否也意味着更少的 Token?”从这个连接出发,我会得到另一个假设。
想象两个系统,并尽可能保持其他条件一致:
相同 Model相同 Agent相同 Tooling相同 Test Quality相同 Linter可比的 TaskSystem A 强耦合、拥有很多可能的 Dependency Path,而且 Ownership 不清晰。
System B 有清晰边界、只有少量允许的 Dependency Path,并且 Ownership 明确。
我的计算机科学直觉是:
更大的结构性决策空间↓更多可能的 Exploration↓更多相关候选↓潜在上更多 Files / Tool Calls / Context↓更多错误路径↓更多 Rework对比:
更小的结构性决策空间↓更少结构候选↓潜在上更少 Exploration↓更小的相关 Working Set↓更少错误路径↓潜在上更低的总成本从机制上看,这对我来说很合理。但仍然必须强调:
到目前为止,我还没有找到可靠的直接测量来证明这一点。
现有研究测量的是相邻效应。结构化的 Repository 表示可以提高 Exploration 效率。Dependency-aware Retrieval 可以更好地选择相关 Context。论文 What Context Does a Coding Agent Actually Need to Act? 甚至在固定 Oracle Localization 的条件下证明,在 SWE-bench Verified 设置中,压缩后的 Context 可以用明显更少的 Context Token 达到接近整文件的结果。但恰恰因为它有意识地保持 Localization 不变,只改变代码表示方式,所以它仍然没有研究:一个更好的模块化 Codebase 本身,是否会降低 Token 需求。
因此,最谨慎的说法只能是:
在其他条件相同的情况下,更小的结构性决策空间可能需要更少 Exploration,因此带来更低的 Inference 成本。从机制上看,这个假设是合理的;但目前还没有直接的实证证明。
我很想有一天真正控制变量去测试它。
最有意思的实验,不是拿一个没有测试的 Big Ball of Mud 去和一个拥有完整 Agent Harness、文档完美的模块化系统比较。更合理的是比较同一个应用的两个结构变体。否则我们一次改变太多变量,最后根本无法知道真正测量到了什么。
更值得看的成本指标,在第一次 Run 之后
Section titled “更值得看的成本指标,在第一次 Run 之后”即使未来真的测量这个假设,我也不会只看单次 Generation 消耗了多少 Token。
一个 Agent 可以用很小的 Context,快速而便宜地生成一个方案,但之后需要三轮修复。
另一个 Run 初始使用更多 Context,更好地理解相关 Dependencies,却在第一次尝试时就生成一个可接受的改动。
因此,从长期来看,我更关心的是:
每一个经过验证、可以接受的改动,最终需要多少成本。
这里面不只有一次回答的 Token,还包括 Exploration、Tool Calls、Tests、Correction 和 Rework,直到达到一个真正可以接受的状态。
这个问题值得单独写一篇文章。在 《Agentic Work 的经济学》 中,我会更详细地回到它。
对本文来说,先保留这个假设就足够了:架构也许不仅能降低结构风险。一个更小的决策空间,在可比条件下也可能具有经济价值。
只是,这个第二层判断目前的证据明显弱于第一个。
高吞吐量让边界更有价值
Section titled “高吞吐量让边界更有价值”这样我们又回到了文章开头的问题。
在人们使用 Coding Agent 之前很久,人类就已经在制造 Architecture Drift。人把 Shared Service 做成垃圾场,打穿 Feature Boundary,把三种 State-Management Pattern 放进同一个系统,并用“这个 Ticket 很急”去解释每一个例外。
AI 没有发明一种新的结构性错误类型。它改变的是,这些决策可以多快地出现。
高变化吞吐量+大的结构性决策空间=更多制造局部不一致决策的机会这不是一篇末日论文章。
恰恰相反:我对今天 Coding Agent 已经能做到的事情非常惊讶,而且我自己也在高频使用它们。正因为如此,我才会在意:怎样把这种速度转化成即使经历另外一千次修改,依然可以理解的系统。
如果架构不设置边界,AI 在放大生产力的同时,也可能放大结构上的任意性。
吞吐量越高,我就越不希望依赖每一个单独的 Run 去“凭直觉”重建同一套没有写出来的架构。
我希望系统本身告诉我们:什么是有效状态。
架构不是每一句代码的说明书
Section titled “架构不是每一句代码的说明书”还有一个重要边界必须保留:我既不主张用规则包围 Coding Agent,直到它再也没有任何决策空间,也不主张把每一个应用都强行塞进同一种 Layering。
一个系统需要的是可理解、一致、可验证的边界。到底采用哪一种具体架构去创造这些边界,取决于问题本身。
一个很小的 CRUD Service,也许比拥有二十个业务 Domain 的应用需要少得多的结构。Modular Monolith 可能是正确答案,SCS-oriented 的划分也可能是正确答案;Layering 可能带来帮助,也可能只制造额外负担。Architecture Constraints 不是目的本身。
它们回答的是一个风险问题:
哪些结构性决策我们不想在每一次修改里重新协商?这些地方应该拥有强边界。
而在这些边界内部,Agent 可以工作。
这也连接回第 5 篇文章:不同的解决方案依然被允许。我们只限制那些不会带来新知识、只会增加系统 变异性 的差异维度。
架构不会消除 变异性。它消除的是不想要的 变异性。
解空间变得更小
Section titled “解空间变得更小”这一系列最近几篇文章现在已经组成了比较清晰的图景。第 4 篇说明 Agent 只能使用它拥有的 Context;第 5 篇说明 Agent 可以在其中选择不同的解决路径;第 6 篇说明一个看起来 Plausible 的路径仍然可能是错的。架构既不能替代 Context,也不能替代 Verification,但它可以缩小真正相关的工作空间,并通过机械规则拦截某些结构性错误。第 7 篇把 Requirements 引入为第一道边界。
现在,第二道边界出现了:
Requirements→ 必须满足什么?
Architecture Constraints→ 哪些结构路径是允许的?这不会把 Agent 变成确定性系统。
它只是给 Agent 一个更小、更有意义的工作空间。
而这正是我理解的 Agentic Software Development 中好架构的作用:
架构会缩小 Coding Agent 的决策空间。
它不是通过规定每一步该怎么做来实现这一点。
它通过 Modules、Contracts、Ownership、Dependency Direction 和 Invariants 来实现。
通过那些可以看出“哪些东西属于一起”的结构来实现。
在理想情况下,还通过那些不只是写在某个地方,而是会被系统自己验证的规则来实现。
项目应该仍然读起来像是一个开发者写出来的——即使 Agent A、Agent B 和 Agent C 都参与了开发。
也许在 Coding Agent 越来越强的世界里,好的架构并不会变得更不重要。
也许变化的只是:它真正产生杠杆的位置。
不再主要是向每一个开发者解释应该怎样写代码。
而是设计一个空间,让不同的参与者——人类和 Agent——都可以在局部工作,而不必在每一个 Feature 上重新发明整个系统的全局结构。
架构因此定义了一种边界:代码在系统内部允许做什么。
下一篇文章,我们要讨论另一种边界。
因为 Agent 不只会修改代码。它还能读取 Repository 内容、使用 Tools,并且跨越系统边界处理信息。
这时,问题不再只是:
代码可以跨越哪些 Dependencies?而会变成:
Agent 到底允许看到哪些信息?
这些信息允许跨越哪些Trust Boundaries?下一篇文章就是:数据隐私、保密性与 Trust Boundaries。
-
David L. Parnas – On the Criteria To Be Used in Decomposing Systems into Modules. Communications of the ACM 15(12), 1053–1058, 1972 年 12 月,DOI 10.1145/361598.361623。Parnas 研究不同的模块划分标准,并从可理解性、灵活性以及 Information Hiding 等角度解释模块化的价值。本文把它作为“好的边界能够局部化知识和修改后果”的历史基础。原文完全没有讨论 LLM 或 Coding Agent;这种连接属于今天的推导。
-
W. P. Stevens, G. J. Myers, L. L. Constantine – Structured Design. IBM Systems Journal 13(2), 115–139, 1974,DOI 10.1147/sj.132.0115。这篇工作描述了通过功能模块降低程序复杂度的技术,也是后来 Cohesion 与 Coupling 讨论中的经典来源之一。本文用它说明,受控依赖并不是 AI 时代的新发明。同样,它不能被用来直接推导 Agent Performance。
-
Brian Foote, Joseph W. Yoder – Big Ball of Mud. PLoP ’97, Technical Report WUCS-97-34;后来收录于 Pattern Languages of Program Design 4, Addison-Wesley, 2000。Foote 与 Yoder 描述了结构松散、甚至 haphazard 的系统:它们的组织更多来自务实增长与修补,而不是一致的设计。本文把 Big Ball of Mud 当作“受限结构性解空间”的反面例子。原作当然没有研究 Coding Agent。
-
OpenAI – Ryan Lopopolo: Harness engineering: leveraging Codex in an agent-first world. 2026 年 2 月 11 日。这篇 Engineering Report 描述了一个内部的、完全由 Agent 生成的软件项目。与本文尤其相关的是固定 Layer、被严格验证的 Dependency Direction、少量允许的 Edge,以及 Custom Linter 和 Structural Test。OpenAI 从中总结出一个实践原则:执行 Invariants,而不是 Micromanage Implementation。这是一份很有价值的实践材料,但不是受控科学研究,不能被泛化为普适架构定律。
-
Self-contained Systems – 官方 SCS 架构说明。 本文只把 SCS 用作一个直观例子,用来说明业务自治、自有数据和 Business Logic,以及少量外部依赖。本文没有从中推导“SCS 对 LLM 具有科学上已证明的优势”。
-
Tsvi Cherny-Shahar, Amiram Yehudai – Repository Intelligence Graph: Deterministic Architectural Map for LLM Code Assistants. arXiv:2601.10112, 2026。RIG 为 Coding Agent 提供从 Build 与 Test 信息推导出的架构图。在八个 Repository 和三个商业 Agent 上,作者报告结构性问题的准确率提高、处理时间显著降低。八个 Repository 中有七个是 Synthetic;对于部分 Agent,研究使用时间作为 Proxy,而不是实际 Token 消耗。最重要的是,这项工作研究的是显式的架构表示,不是底层软件架构本身的质量。
-
Dongjian Ma et al. – LLM Agents Can See Code Repositories. ASE 2026 / arXiv:2606.14061。这项研究考察可视化 Repository Graph 作为文本接口补充的效果。在被评估的设置中,Input Token 消耗最多下降 26%,同时 Accuracy 保持不变或提高;纯视觉使用方式则效果更差。它支持“结构化 Repository 信息可以提升 Exploration 效率”这一判断,但并不能证明“更模块化的架构本身节省 26% Token”。
-
Zhongxin Liu et al. – Effective and Efficient Context Retrieval via Partial Dependency Graph for Repository-Level Code Generation. ASE 2026 / arXiv:2608.01927。DyRetriever 会沿着一个按需构建的 Partial Dependency Graph 选择相关 Repository Context。CoderEval 与 DevEval 上的结果支持 Dependency-aware Retrieval 的价值。它研究的是 Retrieval 方法,不是其他条件相同的情况下不同软件架构的直接效果。
-
Bowen Qin, Yi Xie – Agent Retrieval Bench: Evaluating Repository Context Retrieval for Coding Agents. arXiv:2607.24882, 2026。这个 Benchmark 把真正 Patch Generation 之前的 Context Acquisition 单独隔离出来。它显示,真实 Agent Trajectory 经常不能完整找到相关文件,同时好的 Initial Context 可以减少后续 Exploration。这个 Benchmark 测量的是 Retrieval;更好的 Retrieval 并不自动意味着 Patch 正确或者架构更好。
-
Brian Sam-Bodden – What Context Does a Coding Agent Actually Need to Act? arXiv:2607.09691, 2026。这项工作通过 Oracle 固定要修改位置的 Localization,然后在 SWE-bench Verified 上比较不同的 Context Representation。压缩后的 Context 在这个设置里可以显著更节省 Token。正因为 Localization 被固定,这项研究无法直接证明“更小的架构决策空间会导致更少 Token”。因此它是一条相邻证据,而不是直接确认该假设的证据。
-
Hanyu Li et al. – RepoMirage: Probing Repository Context Reasoning in Code Agents with Perturbations. arXiv:2605.26177, 2026。作者研究了在结构发生变化但语义保持不变的扰动下,Agent 如何进行 Repository-Context Reasoning,并把 exploration drift 描述为一个观察到的问题。一个 Structure-first 原型在实验中改善了结果。该工作目前属于 Preprint 或 Workshop 级别的研究,因此应把这些结果视为早期证据,而不是已经确立的普遍规律。