高效能VC
一句话不足以让AI干活
所谓的一句话生成一个网站、app,一句话做完一个需求,说白了都是营销。
“一句话沟通”的本质矛盾在于:信息输出方压缩了全部上下文,而信息接收方缺乏解码依据,双方对“完整信息”的预期不一致,从而产生理解鸿沟。几乎丢了把任务做对的全部依赖信息。
—— 所谓 prompt 写得好,本质上就是把这些只有你知道的信息,完整地搬到 Agent 面前。这跟措辞漂不漂亮、有没有用什么魔法咒语,关系不大。
case
bad
帮我重构一下这个模块,代码不够简洁good
所谓的一句话生成一个网站、app,一句话做完一个需求,说白了都是营销。
“一句话沟通”的本质矛盾在于:信息输出方压缩了全部上下文,而信息接收方缺乏解码依据,双方对“完整信息”的预期不一致,从而产生理解鸿沟。几乎丢了把任务做对的全部依赖信息。
—— 所谓 prompt 写得好,本质上就是把这些只有你知道的信息,完整地搬到 Agent 面前。这跟措辞漂不漂亮、有没有用什么魔法咒语,关系不大。
帮我重构一下这个模块,代码不够简洁
这些信息应该沉淀到 Agent 每次都会自动读取的地方,不应该每次都这样一大段沟通。
瓶颈在于“指挥 Agent 干活的人”。
人和 Agent 的协作,本质上是一条流水线:人派活、它产出、人验收。
当人自己是整条流水线的瓶颈时,模型再怎么升级都无济于事。
真正限制产出的,从来不是模型的智力,是如何调度它、管理它的能力。
用 Agent 的那一刻,”人”不再是执行者,是管理者。
跟 Agent 协作,其实是门管理学。
幻觉靠模型升级是没有办法解决的。
OpenAI 在 2025 年发过一篇论文: Why Language Models Hallucinate,里面从数学上证明了一件事:就算训练数据完全干净、没有一条错误信息,模型也必然会产生幻觉。
因为模型本质上是根据下一个 token 的概率分布来生成的,这个概率具有天然的随机性,所以总是有概率会生成一些冷门或者不那么正确的知识。
论文里还指出了另一个更现实的原因:现在整个行业的评测体系,都在奖励"自信地猜"。你想想,模型在这种考试规则下训练出来,它学到的策略必然是:不确定的时候也要给出一个像样的答案,同时自信满满、绝不认怂。
要做的事情是如何在工程上把一个会议固定概率出错的组件用的可靠。
计算机科学家 David Wheeler:"All problems in computer science can be solved by another level of indirection”。任何问题都可以通过增加一个中间层来解决
!review-middle-layer.png
假设:模型单次产出的正确率是 90%,那么有 10% 的概率,产出里藏着问题。
加一轮 review,理想情况下可以把残留错误率干到 1%。
再来一轮,理想情况下可以干到 0.1%。
几轮线性增长的 review 可以换来错误率的指数级衰减。
所以:幻觉不能消除,但可以工程化的衰减。
上面错误率的指数级衰减成立的前提是:每轮 review 的错误,都与上一轮不相关。
论文 Large Language Models Cannot Self-Correct Reasoning Yet,结论是:让模型在没有外部反馈的情况下检查自己的推理,性能不升反降,它甚至会把本来对的答案改成错的。
自我纠错盲区:同样一个错误,模型检查自己的输出时发现不了;但你把这段内容当成"别人写的"递给它,它一眼就能挑出毛病。
就像学生时期大家的共识:自己检查自己的试卷咋看咋对,给其他同学看,一眼就能看出问题在哪。
同样的思路,自然得出同样的结论。
防止模型陷入自己之前的思路。
心理学家 Kahneman 提过一个概念叫
WYSIATI(What You See Is All There Is):大脑会基于手头有限的信息编一个自洽的故事,完全意识不到还有信息缺失。模型也一样,它给你的输出永远看起来"完整",你不问,它绝不会主动说"其实还有几种情况我没考虑"。
让检查者看不到生产者的思考过程,只拿到产出本身(比如
git diff)和审查指令。
要说:
- 这个实现有什么安全风险
- 这个方案什么情况下会失败
- 你还漏掉了什么
- xxxx 情况下,这个设计还成立吗
- xxx 情况下会出现什么错误
- …
不说:
- 你确定吗 之类的话OpenAI 内部实践:harness-engineering; 他们做了一件几乎所有人都会做的事:写了一个巨大的
AGENTS.md,把所有规则、约束、架构原则、编码规范全塞进去。
!image.png
以 CC 为例,CLAUDE.md(以及通用标准 AGENTS.md)是唯一能让它每次开工就"记住"你的东西——可以把它理解成给 Agent 的入职文档。
写好了,一句话就能让 agent 知道该怎么干活。
写砸了,每次对话都会是在重复纠错。
根源:试图在启动时把所有信息一次性灌给 Agent。
信息越多,稀释越严重,腐烂越快。
结合 OpenAI 的失败原因来分析的话有两点:
简单来说就是:如果所有规则都同样重要,那就都不重要了。
业界实测的经验 - 前沿模型大概能遵循 150 - 200条指令。
超出之后发生的事情比较反直觉:受影响的不只是新增的规则,是所有规则的遵循质量都一起下降。
代码天天在变,架构在演进,但那个几百行的文件没人想去更新——写的时候人人都觉得"以后会维护的”。
Agent 不知道哪些还有效、哪些早就过时了,人也搞不清楚。
在合适的时机给出合适的信息。主要是解决时机的问题。
OpenAI 团队做了一个关键转变:把 AGENTS.md 从"百科全书"改成了"目录"。
不再试图把所有规则都写进 AGENTS.md 中,而是只干一件事:告诉 Agent它需要的东西都在哪里。
真正的知识放在一个结构化的 /docs 目录里, 有清晰的索引和分类。
他们管这个模式叫 Progressive Disclosure(渐进式披露):Agent 从一个小的、稳定的入口开始,在需要的时候才去读更深层的信息,而不是一开始就被所有东西淹没。
AGENTS.md
ARCHITECTURE.md
docs/
├── design-docs/
│ ├── index.md
│ ├── core-beliefs.md
│ └── ...
├── exec-plans/
│ ├── active/
│ ├── completed/
│ └── tech-debt-tracker.md
├── generated/
│ └── db-schema.md
├── product-specs/
│ ├── index.md
│ ├── new-user-onboarding.md
│ └── ...
├── references/
│ ├── design-system-reference-llms.txt
│ ├── nixpacks-llms.txt
│ ├── uv-llms.txt
│ └── ...
├── DESIGN.md
真正的杠杆从来不在于你给 Agent 的信息量多大,而在于在对的时间,只给它需要的那一份。
🌟 每次想往 Agent 的启动上下文里加东西时,先问一句:这个信息是每次会话都需要,还是只有特定任务需要?后者就不该放在默认的上下文里面,该放在目录里按需读取。
WHAT(项目是什么、技术栈、目录结构)
WHY(每个模块的职责、为什么选这个方案)
HOW(怎么跑测试、怎么构建、用什么包管理器)
围绕这三个维度写,基本不会漏关键的东西。
Agent 猜不到你用 pnpm 还是 npm,更猜不到你希望它跑单个测试文件。
"注意测试性能"这种话等于没说,pnpm test src/xxx.test.ts 才是它能执行的指令。
避免不必要的xxx,agent 无法理解什么是不必要的。
写你脑子的东西,或者会议纪要、聊天记录等
为什么这个目录不能碰
当年踩了什么坑
哪个看起来冗余的逻辑其实是兼容老业务的
CLAUDE.md 支持 @path/to/file 语法。但直接 @ 引用会在每次启动时把整个文件嵌进上下文。
例如:xx 改动,读 docs/xx.md 。xxxx 改动,读 docs/xxxx.md 。
试试在某条指令前面加 IMPORTANT: 或者 YOU MUST:
但要克制,都重要 = 都不重要。
上下文快满的时候 CC 会自动压缩对话历史,你可以在文件里写清楚压缩时必须保留的信息。
团队里工具不统一的话,别维护好几份重复内容——把规则全放进 AGENTS.md(它本来就是通用标准),然后在各个工具的配置文件里只写一行引用:
Include: @./AGENTS.mdCC:
| 场景 | 选择 |
|---|---|
| 同一任务,上下文还有用 | Continue |
| Agent 走错了路 | Rewind |
| 会话很长但还要继续工作 | /compact |
| 要开始一个新任务 | /clear(清之前先写 HANDOFF.md) |
| 上下文很好,想多开一条线 | /branch |
| 下一步会产生大量中间输出 | Subagent |
Codex
| 操作 | Claude Code | Codex |
|---|---|---|
| 继续对话 | 直接打字 | 直接打字 |
| 回退 | /rewind(双击 Esc) | 双击 Esc 编辑上一条消息并 fork |
| 压缩 | /compact | /compact |
| 清空 | /clear | /clear |
| 分支 | /branch | /fork |
| 子会话 | Subagent(自动或手动) | /side(轻量探索)/ /fork(重分支) |
让 Agent 读一个大文件、跑一个会输出几百行的命令之前,先问一句:
这些内容,我真的需要它完整地留在上下文里吗?还是我只需要其中的一个结论?
如果只要结论,那就是 subagent 的活,你应该直接说"用 subagent 帮我 xxx"。
上下文管理最反直觉的一点是——你最需要它的时候,恰好是它最不可靠的时候。
等到上下文快满了、模型开始犯迷糊了,这时候触发的 autocompact 质量最差;
这时候让 Agent 写交接文档,它也已经记不清前面的细节了。
所有的清理动作都要提前:
会话到 40%-50% 就写交接文档
觉得有点长就主动 /compact
换任务立刻 /clear 或者 /branch
不要等模型提醒你,等它提醒就晚了。
用文件做交接:最可靠的上下文桥接方式
在 /compact 或 /clear 之前,让 Agent 先把当前状态落到一个文件里:
把当前的进展、待办事项、已知的坑写进 HANDOFF.md,
要具体到我打开一个全新会话,只读这个文件就能接着干。上下文是容易丢的——compact 会丢、/clear 会丢、会话关了开新会话也会丢。但文件是持久的。
软件工程的老前辈 Brooks 在《人月神话》里提过一个概念,叫第二系统效应:讲的是工程师做第一个系统时小心谨慎,做第二个时就忍不住把所有攒下来的"好想法"全塞进去,结果造出一个过度设计的"怪东西"
所以要学会给 AI 做减法。
prompt 里明确写上:
*用最简单的方式实现,不要考虑本次需求之外的扩展性,能用现有依赖就不要造轮子。*功能跑通之后,追加一轮:"这段实现里,哪些代码是可以删掉的?哪些抽象是本次需求用不到的?”
“提前做好抽象、避免日后重构”这套思维在 AI 时代不成立了,AI 重构成本低到几乎可以忽略。
等需求真的出现了再重构,才是 AI 时代更加务实的选择。
"优先使用项目现有的工具函数和依赖"
"不要为单一实现引入接口抽象"
——这类规则固化到 CLAUDE.md。
能被机器自动感知并拦下的错误,就永远不该消耗你的注意力。
错误的发现和修复在 Agent 的循环内部就消化掉了,根本到不了人跟前。
CLAUDE.md 是软约束,Agent 大概率遵守,但并不能保证 100%。而验证却必须是 100% 需要的。
hooks 是在 Agent 工作流的固定节点自动触发的脚本:编辑文件之后、提交之前、会话结束时。
跟 CLAUDE.md 的区别是:规则要靠模型的理解和遵守,而 hook 是代码,必然执行。
所以用 hook 来挂验证闭环。
挂一个 PostToolUse hook,Agent 每次编辑完文件,lint 自动跑,有问题立刻把报错回灌给它。
这一层解决的是"小错即时清",不让风格和低级错误堆积到最后一起爆。
// .claude/settings.json{
"hooks": {
"PostToolUse": [
{
"matcher": "Edit|Write",
"hooks": [
{
"type": "command",
"command": ".claude/hooks/lint-changed.sh"
}
]
}
]
}
}#lint-changed.sh
#!/bin/bash
# 取出本次被改动的文件路径
file=$(jq -r '.tool_input.file_path')
# 只对 TS 文件跑 lint
if [[ "$file" == *.ts || "$file" == *.tsx ]]; then
pnpm eslint "$file" >&2 || exit 2
fi
# 在 Claude Code 的 hook 协议里,退出码 2 表示"把 stderr 的内容回灌给模型"
# 也就是说 lint 报错会直接出现在 Agent 眼前,它看到报错就会自己动手修指令里固定一条——
每写完一个新功能,必须先 build 一遍,再把对应的 e2e 测试跑通,两个都绿才算"做完了"。
功能验收的核心是清单。
工具只会在自己维修执行完告诉你结果对不对,但产出的标准还得人类来把关。
比如:
catch,要么处理要么往上抛checklist 定义"什么算合格",工具负责"怎么检查"。
清单是长出来的,不是一次性给全的,每次踩一个坑就补充一条进去。