2025年年中,Fabien Sanglard 第一次让 LLM 写代码。任务是用 Rust 实现 mDNS,结果连编译都过不了,他当场判定"不能用"。
半年多后,2026年1月他又试了一次。模型这次写出了一个复杂的索引二叉堆,还揪出了 polling 库在 Windows IOCP 实现里的一个隐蔽 bug。能力明显上了一个台阶,但代码本身没结构、没注释,读起来很累。
真正让这套工作流跑起来的,不是模型又聪明了多少,而是他后来在项目根目录放的一份 agent.md——把自己反复念叨的编码规矩,写成一份每次开工前自动加载的清单。
三次尝试,变的是什么
| 时间 | 发生了什么 | 代码质量 |
|---|---|---|
| 2025年中 | 用 Rust 写 mDNS | 编译不过,判定不能用 |
| 2026年1月 | 写出索引二叉堆,揪出 polling 库隐蔽 bug | 能力够,但没结构没注释 |
| 2026年3月 | 换用 Antigravity、VS Code 的 Claude Code 插件逐条迭代 | 质量上台阶,但每个新会话都要重复提醒 |
| 加 agent.md 之后 | 规则常驻,不用每次重新念叨 | 风格问题大减,审查转向架构 |
这条时间线对个人开发者的意义很直接:模型能力涨了,不代表代码风格会自动变好。真正管用的是流程和约束,不是等模型自己开窍。
agent.md 管住了什么,又管不住什么
机制很简单:会话开始时,编码工具加载这份文件,注入到 prompt 里。放项目根目录就够用;想让 claude.md、gemini.md 也生效,软链接指向同一份文件即可。但这套加载机制因工具而异,不同 agentic IDE 的实现细节和版本可能不完全一致,目前也没有统一标准。
里面写的多是硬约束:
| 规则 | 目的 |
|---|---|
| 少用魔法数字,减少嵌套缩进 | 降低阅读成本 |
| 分层边界:上层只跟相邻一层说话,不许跨层直连底层 I/O | 防止架构被打散 |
| 改动尽量小,别顺手重构没关系的代码 | 减少审查负担 |
| 修 bug 先写一个失败的测试,再动手改 | 把回归风险摆到明面上 |
这些规则大多是他在 Rust、C++ 项目里磨出来的个人偏好。换一门语言、换一个团队,细节大概率要重新调,他自己也没把这份清单当成通用标准。
agent.md 不是模型训练,更不是 fine-tuning。它只是会话启动时塞进上下文的一份指令文件,模型的底子没变。生成的代码依然要逐行核实,幻觉不会因为一份文件消失。
省下来的是重复劳动,不是工程判断
以前每开一个新会话,都要把"别用魔法数字"这类话再讲一遍。现在规则常驻,他把精力挪到了架构和设计判断上——这是这份文件带来的直接收益,也是它唯一能保证的收益。
代码质量的天花板,还是压在审查这一步。agent.md 拉高了地板,没有动天花板。
上下文一长,模型对中间那部分指令会越来越不上心。这是 Lost in the Middle 那篇论文提过的现象:开头结尾记得清楚,中段容易被糊弄过去。目前能用的应对办法只有两条:按功能拆分会话,别把上下文堆成一锅粥;发现代码质量下滑,直接要求"重新加载 agent.md"。这两条本质都是人在盯着机器的注意力,不是机器学会了长期记忆。
个人开发者可以直接照搬这套清单,放进项目根目录试一试,成本很低。团队负责人要多想一层:如果让 agent 自己往 agent.md 里加新规则,省事是真的,但这份"规矩"会在不知不觉中被机器改写。个人项目隔段时间自己翻一遍就行,团队协作的话,谁来审批规则变更得先定下来——规则膨胀比代码风格混乱更难查。
从编译不过,到能定位 Windows IOCP 里的隐蔽 bug,LLM 写代码的能力确实在涨。但决定代码能不能进生产的,从来不是模型多聪明,是审查这道关卡有没有人真的把住。agent.md 顶多算把老师傅的经验写成了操作手册——新手照单子能干出八成,剩下那两成,还得有人拍板。
