AI 编程 Agent 不需要更聪明
它们需要一张地图
形式化架构声明作为 AI Coding Agent 的导航原语

arXiv:2604.13108 — 一个看不懂代码的人,如何让 AI Agent 的导航步数降低 33–44%。
作者:靳若琦 (Independent Researcher)
我为什么要做这件事
我看不懂代码。
这不是谦虚。我是一个视频剪辑师,靠着 AI Agent(Claude Code)写 Rust 来搭建整套软件系统。我审 diff、批 PR、部署上线。这套模式一直运转良好——直到项目超过一万五千行。
到了这个规模,崩溃的不是代码,而是 Agent 的导航能力。Claude Code 开始反复 grep 三轮前已经找到的函数、重复读同一个文件、猜模块边界而不是确定它们。我眼睁睁看着它烧掉 10 次工具调用去定位一个函数——而那个函数我 5 秒钟就能指出来,如果我看得懂 Rust 的话。
我管理 20 个项目。最小的两万行,最大的四十七万行。如果 Agent 一半时间都在迷路,那我一半时间都在等它。
我需要的不是一个更聪明的 Agent。我需要一张地图。
intent.lisp:架构声明文件
我开始用 S 表达式(Lisp 的括号语法)编写架构描述文件。不是因为觉得 Lisp 有什么魔法,而是因为括号能强制结构化。你没法在 S 表达式里含糊其辞——而 Markdown 可以。
(intent jarvis(design-constraints(three-pillars (memory control tools))(communication (must-use EventBus))(db-access (only memory/storage)))(pillar memory(purpose "数据采集、存储、分析")(component storage(role "唯一的数据库网关")(invariants "此模块外禁止裸 SQL")(data-flow "Event → Storage → PostgreSQL"))))
组件包含在支柱(pillar)内部,符号包含在组件内部。这不是格式偏好——这是语法强制。两个人(或两个 LLM)描述同一个项目,产出的文件在结构上是收敛的。Markdown 做不到这一点。
我为所有项目都写了 intent.lisp。一个 11 万行的 Rust 守护进程被压缩到 1,587 行。一个 47 万行的 monorepo 被压缩到 7,877 行(32 个文件)。跨 64.6 万行生产代码的加权平均压缩比是 34:1。
我不手写它们。我用自然语言描述我想要的架构,Claude Code 翻译成 S 表达式。另一个 Claude Code 会话在后续工作中读取它。
让我意外的实验结果
我原本想证明 S 表达式比 Markdown 更适合 AI Agent。所以做了对照实验:24 个代码定位任务,四种条件(无上下文、S 表达式、JSON、Markdown),Claude Sonnet 4.6,温度 = 0。
我期望的结果:有架构上下文显著减少导航步数。验证了——步数减少 33–44%(Wilcoxon p = 0.009,Cohen’s d = 0.92)。
我没有预料到的结果:格式完全不重要。
S 表达式、JSON、YAML、Markdown——LLM 在四种格式上达到了一模一样的 95% 准确率。没有显著差异。Agent 根本不在乎你用括号还是用 bullet point 还是用花括号写架构。它读什么都一样。
这彻底推翻了我的论文假设。如果格式无所谓,那为什么还要用 S 表达式?
真正重要的三件事
1. 形式化重要。格式不重要。
有架构文件就能减少 33–44% 的导航步数。没有就意味着 Agent 在盲走。内容是信号,括号是噪音。
但更深层的发现来自田野研究(7,012 个 Claude Code 会话):读了 intent.lisp 的会话和没读的会话,效率完全一样(explore/edit 比 1.65 vs 1.65)。改善是系统性的,而非逐会话的。
变的不是 Agent 消费了文件。变的是我写了它。形式化架构的过程迫使我想清楚自己的系统——哪个模块负责数据库、事件怎么流转、约束在哪里。这种清晰度渗透到了更好的提示词、更清晰的代码边界、更显式的 CLAUDE.md 引用。我称之为开发者自明效应(developer self-clarification effect)。
2. 文件本身有直接价值——即使自动生成。
为了排除"是写文件帮了忙还是文件本身帮了忙",我在一个从未重构过代码的项目上做了第二个实验。工具自动扫描代码库,生成了一份 170 行的架构摘要——零人工编辑、零代码重构。
自动生成:100% 任务完成率。无上下文:80%。(p = 0.002,d = 1.04)
文件本身就能帮忙。你不需要亲自写它来受益。机器生成、机器消费。开发者自明效应是附加值,不是全部。
更出乎意料的是:自动生成的 170 行版本在准确率上跑赢了我手工精修的 698 行版本(100% vs 87%)。Less is more——至少在导航这件事上,更短的描述消耗的 token 更少,留给 Agent 更多的工具调用预算。
3. 失败模式才是格式真正分野的地方。
如果 LLM 读所有格式都一样好,那为什么要选其中一个?因为 LLM 也会写描述文件,写的时候会犯错。犯错的方式才是关键:
- JSON
原子性失败——少一个花括号,整个文件不可解析,内容全损。 - YAML
静默损坏——缩进错误会把组件悄悄挂到错误的父节点下,没有任何警告。 - Markdown
无法检测——没有解析器,100% 的错误不可见。 - S 表达式
优雅降级——所有结构错误都能被检测到,错误之前的内容完好无损。
我选择 S 表达式,不是因为 LLM 读它更好。而是因为它坏得更好。
实验数据总览
全部实验使用 Claude Sonnet 4.6,温度 = 0。总计 317 次 API 调用,花费约 $27。
forge survey:60 秒生成架构地图
基于上述研究,我构建了一个开源工具——Forge。它的核心命令只有一个:
cargo install forge-cliforge survey /path/to/your/project
它用 tree-sitter 扫描代码库的 AST,组装结构化提示词,调用 Claude 生成 S 表达式架构描述,然后通过内置的 S 表达式解析器验证输出。整个过程约 60 秒。生成的 intent.lisp 文件随代码一起进入版本控制。
对我来说,这就是管理 20 个项目和被 20 个项目淹没之间的区别。Agent 拿到一张地图,我拿到可预测性。
坦诚的局限性
- N=1 开发者 ——
所有田野观察来自一个人的项目,生态效度有限。 - 效果量对模型敏感 ——
Sonnet 4 时 d=1.70,Sonnet 4.6 时 d=0.92。模型越强,盲走效率越高,地图的边际收益越小。但在 47 万行项目上,强模型也会迷路。 - 格式比较的统计功效不足 ——
仅 3–6 个有效配对差异,不足以证明格式真正等价,只能说我没检测到差异。 - 只测了代码定位 ——
多文件修改和架构决策场景未验证。
对 Context Engineering 争论的回应
整个 Context Engineering 社区都在争论 CLAUDE.md / AGENTS.md / Cursor Rules 里应该用什么格式。YAML frontmatter?Markdown 标题?JSON Schema?
至少对于架构上下文来说,答案似乎是:格式无所谓。重要的是你形式化了你的架构。用你工具链支持的任何格式写。如果你需要下游的自动验证,选一个可解析的格式。如果不需要,Markdown 就够了。
更有生产力的问题不是「LLM 偏好什么格式」,而是「什么格式在 LLM 读写时都能避免灾难性失败」。我们的实验没有检测到显著的格式偏好。d = 0.92 是在一个 2.2 万行项目上测出的,而 Sonnet 4.6 在这个规模上已经能高效盲走。在 10 万行以上的项目中,盲走本质上更难——34:1 的压缩比意味着恒定成本的架构可达性,不受代码库规模影响。
关于作者
我是一个 33 岁的中国视频剪辑师,高中毕业,没有 CS 学位。我从 2012 年开始做影视后期,交付了 100 多个项目。2024 年,我开始自学 Rust、编译器和分布式系统——因为我管理的 AI Agent 编程系统越来越大,我需要一种方式来掌控我自己看不懂的代码库。
intent.lisp 就是这种方式。它最初是为了解决我个人的痛点——后来发现,对所有使用 AI 编程 Agent 的开发者都有效。
论文: arxiv.org/abs/2604.13108
代码: github.com/RuoqiJin/forge
DOI: doi.org/10.5281/zenodo.19500105
网站: ruoqijin.com
微信: Jinstudio626
如果你也在用 Claude Code / Cursor / Copilot 管理大型项目,欢迎交流。这张地图也许能帮你少走一些弯路。
夜雨聆风