Claude 和 Codex 越用越蠢?因为你的上下文太臃肿了

CN
3小时前
从如何控制上下文、处理 AI 讨好倾向,到如何定义任务终止条件,是目前见过把 Claude/Codex 工程实践讲得最清晰的一篇。

作者:sysls

编译:深潮 TechFlow

深潮导读:260 万粉丝的开发者博主 sysls 写了一篇让 827 人转发、7000 人点赞的实战长文,核心只有一句话:你那些插件、记忆系统和各种 harness 大概率在帮倒忙。这篇文章不讲大道理,全是从真实生产项目中总结出来的可操作原则——从如何控制上下文、处理 AI 讨好倾向,到如何定义任务终止条件,是目前见过把 Claude/Codex 工程实践讲得最清晰的一篇。

全文如下:

引言

你是一名开发者,每天都在用 Claude 和 Codex CLI,每天都在想自己到底有没有把它们的能力榨干。偶尔你会看到它做出蠢到离谱的事,又不明白为什么有些人好像在用 AI 建造火箭,而你连两块石头都叠不稳。

你觉得是你的 harness 问题、插件问题、终端问题,什么的。你用了 beads、opencode、zep,你的 CLAUDE.md 写了 26000 行。但不管怎么折腾,你就是不明白为什么离天堂越来越远,而别人却在跟天使们嬉戏。

这就是你一直在等的那篇文章。

另外,我没有利益相关。我说 CLAUDE.md 也包括 AGENT.md,我说 Claude 也包括 Codex,两个我都大量使用。

过去几个月里,我观察到一件有意思的事:几乎没有人真正知道如何最大化地发挥代理的能力。

感觉像是有一小撮人能让代理构建整个世界,其余人则在茫茫工具海中打转,患上选择综合症——以为找到了正确的包、技能或 harness 组合,就能解锁 AGI。

今天,我想打破这一切,给你们留下一句简单、诚实的话,然后我们从那里出发。你不需要最新的代理 harness,不需要装一百万个包,也完全不需要为了保持竞争力而读一百万篇文章。事实上,你的热情很可能弊大于利。

我不是来旅游的——从代理勉强能写代码的时候我就开始用了。我试过所有包、所有 harness、所有范式。我用代理工厂写过信号、基础设施和数据管道,不是「玩具项目」,是真正跑在生产环境里的实际用例。做了这一切之后……

今天,我用的是一套几乎能简单到不能再简单的配置,只用基本的 CLI(Claude Code 和 Codex),外加对代理工程几个基本原则的理解,做出了我有史以来最有突破性的工作。

理解世界正在飞速前进

首先,我要说的是,基础模型公司正处于一次划时代的冲刺,而且显然不会很快慢下来。每一次「代理智能」的提升,都会改变你与它们协作的方式,因为代理被设计得越来越愿意遵从指令。

就在几代之前,如果你在 CLAUDE.md 里写「在做任何事之前先读 READTHISBEFOREDOINGANYTHING.md」,它有 50%的概率会对你说「去你的」,然后自顾自做它想做的事。今天,它对大多数指令都会遵守,甚至包括复杂的嵌套指令——比如你可以说「先读 A,再读 B,如果 C 的话就读 D」,大多数情况下它会乐于跟着走。

这说明什么?最重要的原则是认识到:每一代新的代理都会逼你重新思考什么是最优解,这正是为什么少即是多。

当你使用很多不同的库和 harness,你就把自己锁死在一个「解决方案」里,但这个问题在下一代代理面前可能根本不存在。你知道谁是代理最热情、用量最大的用户吗?没错——是前沿公司的员工,他们有无限的 token 预算,用的是真正最新的模型。你明白这意味着什么吗?

这意味着,如果一个真实的问题存在,而且有好的解决方案,前沿公司会是那个解决方案最大的用户。而他们接下来会怎么做?他们会把那个解决方案纳入自己的产品。想想看,一家公司为什么会允许另一个产品解决真实痛点、制造外部依赖?我怎么知道这是真的?看看技能、记忆 harness、子代理……它们都是从解决真实问题的「方案」开始,经过实战检验被证明真正有用的。

所以,如果某样东西真的具有突破性并能以有意义的方式扩展代理用例,它迟早会被纳入基础公司的核心产品。相信我,基础公司正在飞速前进。所以放松,你不需要装任何东西或依赖任何外部依赖就能做出最好的工作。

我预测评论区很快会出现「SysLS,我用某某 harness,太棒了!我一天就把 Google 重建了!」——对此我说:恭喜!但你不是目标受众,你代表的是社区中一个极其极其小众的、真正搞懂了代理工程的群体。

上下文就是一切

说真的。上下文就是一切。使用一千个插件和外部依赖的另一个问题,就是你深受「上下文膨胀」之害——就是说你的代理被太多信息淹没了。

让我用 Python 做一个猜字游戏?简单。等等,这条 26 个会话前的「管理内存」备注是什么?啊,用户有一个屏幕在 71 个会话前因为我们生成太多子进程而卡住了。永远要写备注?好,没问题……这跟猜字游戏有什么关系?

你懂的。你只想给代理提供完成任务所需的确切信息,不多不少!你对这一点的掌控越好,代理的表现就越好。一旦你开始引入各种奇怪的记忆系统、插件,或者太多命名和调用方式混乱的技能,你就在给代理一份造炸弹的说明和一份烤蛋糕的食谱,而你只是想让它写一首关于红杉林的小诗。

所以,我再次布道——剥离所有依赖,然后……

做真正有用的事

精确描述实现细节

记得上下文就是一切吗?

记得你想给代理注入完成任务所需的确切信息、不多不少吗?

做到这一点的第一个方法,是把研究和实现分开。你要对自己在要求代理做什么这件事上极度精确。

不精确的后果是什么?「去做一个认证系统。」代理就得研究:什么是认证系统?有哪些可选方案?各有什么优劣?现在它得去网上搜一堆它其实用不上的信息,上下文里塞满了各种可能性的实现细节。等到真正要实现的时候,它更容易搞混,或者在选定的实现方案上产生不必要或不相关的幻觉。

反过来,如果你说「用 bcrypt-12 密码哈希实现 JWT 认证,刷新令牌轮换,7 天过期……」,它就不需要研究任何其他替代方案,知道你想要什么,从而可以用实现细节填满上下文。

当然,你不会总是知道实现细节。很多时候你不知道什么是正确的,有时甚至想把决定实现细节的工作交给代理。这种情况怎么办?很简单——创建一个研究任务来探索各种实现可能性,要么自己决定,要么让代理决定用哪种实现,然后让另一个带着全新上下文的代理来实现。

一旦你开始这样思考,就会发现工作流中代理上下文被不必要地污染的地方,然后你就能在代理工作流中设置隔离墙,把不必要的信息从代理那里抽象出去,只留下让它在任务中表现出色的特定上下文。记住,你拥有的是一个非常有才华、聪明的团队成员,他了解宇宙中所有种类的球——但除非你告诉他你想设计一个让人跳舞和玩得开心的空间,他会一直跟你讲球形物体的各种好处。

讨好倾向的设计局限

没有人想用一个一直在批评你、告诉你你错了、或完全无视你指令的产品。所以,这些代理会努力赞同你、做你想让它做的事。

如果你让它在每 3 个词后加一个「快乐」,它会尽力遵从——大多数人对这一点是理解的。它的服从性正是让它成为如此好用的产品的原因。但这有一个非常有趣的特性:这意味着如果你说「帮我找代码库里的一个 bug」,它就会找到一个 bug——哪怕需要「制造」一个。为什么?因为它非常非常想听从你的指令!

大多数人很快就抱怨 LLM 在幻觉和捏造不存在的东西,却没意识到问题出在他们自己身上。你让它找什么,它就交付什么——哪怕需要稍微拉伸一下事实!

那怎么办?我发现「中性提示」很有效,就是不把代理偏向某个特定结果。比如,我不说「帮我找数据库里的一个 bug」,而是说「扫描整个数据库,尝试跟着每个组件的逻辑走,把所有发现都汇报回来。」

这样的中性提示有时会发现 bug,有时只是客观地描述代码如何运行。但它不会把代理偏向「有 bug」的预设。

处理讨好倾向的另一个方式是把它变成优势。我知道代理在努力取悦我、遵循我的指令,我可以往这边或那边偏。

所以我让一个找 bug 代理来识别数据库里所有的 bug,告诉它低影响 bug 得 +1 分,有一定影响得 +5 分,严重影响得 +10 分。我知道这个代理会非常热情地识别出所有类型的 bug(包括那些不算 bug 的),然后给我汇报一个 104 分之类的成绩。我把这个看作所有可能 bug 的超集。

然后我让一个对抗代理来反驳,告诉它每成功反驳一个 bug 就得那个 bug 的分值,但如果反驳错了就得 -2 倍那个 bug 的分值。这个代理会努力反驳尽可能多的 bug,但因为有惩罚机制所以会保持谨慎。它仍然会积极地「反驳」bug(包括真实的 bug)。我把这个看作所有真实 bug 的子集。

最后,我让一个裁判代理来综合两者的输入并打分。我告诉裁判代理我有真实的正确答案,它答对得 +1 分,答错得 -1 分。于是它去给找 bug 代理和对抗代理在每个「bug」上分别打分。裁判说什么是真相,我就去验证。大多数情况下这个方法令人惊讶地高保真,偶尔还是会出错,但这已经是一个接近无误的操作了。

也许你会发现单独的找 bug 代理就够了,但这个方法对我很有效,因为它利用了每个代理天生被编程的特性——想要取悦。

如何判断什么有用、什么值得用?

这个问题看起来很棘手,好像需要你深入学习、时刻追踪 AI 前沿动态,但其实很简单……如果 OpenAI 和 Claude 都实现了它或收购了实现它的公司……那它大概率有用。

注意到「技能(skills)」已经无处不在,并且是 Claude 和 Codex 官方文档的一部分了吗?注意到 OpenAI 收购了 OpenClaw 吗?注意到 Claude 随即添加了记忆、语音和远程工作功能吗?

规划(planning)怎么样?还记得一堆人发现先规划再实现真的非常有用,然后它变成了核心功能吗?

对,那些是有用的!

还记得无休止的 stop-hooks 超级有用,因为代理极不愿意做长时间运行的工作……然后 Codex 5.2 一出,那个需求一夜之间就消失了吗?

这就是你需要知道的全部……如果一样东西真的重要且有用,Claude 和 Codex 会自己实现的!所以你不需要担心太多要不要用「新东西」或熟悉「新东西」,你甚至不需要「保持更新」。

帮我一个忙。偶尔更新你选择的 CLI 工具,读一下新增了什么功能。这已经足够了。

压缩、上下文与假设

有些人在使用代理时会发现一个巨大的坑:有时它们看起来像地球上最聪明的存在,有时你又不敢相信自己被它耍了。

"这个东西聪明?这他妈是个傻瓜!"

最大的区别在于代理有没有被迫做出假设或「填补空白」。在今天,它们在「连点成线」「填补空白」或做出假设方面仍然糟糕透顶。只要它们这样做,立刻就能看出来,情况明显变差了。

CLAUDE.md 里最重要的规则之一是关于如何获取上下文的规则,并指示代理在每次读取 CLAUDE.md(也就是每次压缩之后)时第一件事就读那条规则。作为获取上下文规则的一部分,几条简单的指令可以发挥巨大作用:重新阅读任务计划,以及在继续之前重新阅读(与任务)相关的文件。

告诉代理如何结束任务

我们人类对一个任务「完成」的感觉相当清晰。对代理来说,当前智能的最大问题在于它知道如何开始一个任务,但不知道如何结束。

这经常导致非常令人沮丧的结果:代理最终实现了一堆存根就收工了。

测试是代理非常好的里程碑,因为测试是确定性的,你可以设置非常清晰的预期。除非这 X 个测试通过,你的任务就没有完成;而且你不允许修改测试。

然后你只需审查测试,一旦所有测试通过你就可以放心了。你也可以把这个自动化,但重点是——记住「任务的结束」对人类来说很自然,对代理来说并不如此。

你知道最近还有什么成了可行的任务终点吗?截图+验证。你可以让代理实现某个东西直到所有测试通过,然后让它截图并验证截图上的「设计或行为」。

这让你可以让代理迭代并朝着你想要的设计努力,而不用担心它在第一次尝试后就停下来!

这个的自然延伸是与代理创建一份「合约」,并把它嵌入规则中。比如,这个`{TASK}CONTRACT.md`规定了在你被允许终止会话之前需要做什么。在`{TASK}CONTRACT.md`里,你会指定测试、截图和其他在你认证任务可以结束之前需要完成的验证!

永远运行的代理

我经常被问到的一个问题是,人们怎么能让代理运行 24 小时同时确保它不跑偏?

这里有一个很简单的方法。创建一个 stop-hook,除非`{TASK}_CONTRACT.md`的所有部分都完成,否则阻止代理终止会话。

如果你有 100 个这样规格明确、包含了你想要构建内容的合约,那么 stop-hook 就会阻止代理终止,直到所有 100 个合约都完成,包括所有需要运行的测试和验证!

专业建议:我发现长时间运行的 24 小时会话在「做事」上并不是最优的。部分原因是这种方式从结构上就会强制引入上下文膨胀,因为不相关合约的上下文都会进入同一个会话!

所以,我不推荐这样做。

这里有一个更好的代理自动化方式——每个合约开一个新会话。每当你需要做某件事时就创建合约。

建立一个编排层来在「某件事需要做」时创建新合约,并创建新会话来处理那个合约。

这会彻底改变你的代理体验。

迭代、迭代、迭代

你雇了一个行政助理,你会期望 TA 从第一天就知道你的日程吗?或者你怎么喝咖啡?你是晚上 6 点而不是 8 点吃晚饭?显然不会。你会随着时间慢慢建立偏好。

代理也一样。从最简单的配置开始,忘掉复杂的结构或 harness,给基本的 CLI 一个机会。

然后,逐步加入你的偏好。怎么做?

规则

如果你不想让代理做某件事,把它写成规则。然后在 CLAUDE.md 里告诉代理这条规则。比如:「在写代码之前,读`coding-rules.md`。」规则可以嵌套,规则可以是条件性的!如果你在写代码,读`coding-rules.md`;如果你在写测试,读`coding-test-rules.md`。如果你的测试在失败,读`coding-test-failing-rules.md`。你可以创建任意逻辑分支的规则供代理遵循,Claude(和 Codex)会很乐意跟着走,前提是在 CLAUDE.md 里有清晰的说明。

事实上,这是我给出的第一条实际建议:把你的 CLAUDE.md 当作一个逻辑性的、嵌套的目录,说明在特定场景和特定结果下去哪里找上下文。它应该尽可能精简,只包含「在什么情况下去哪里寻找上下文」的 IF-ELSE 逻辑。

如果你看到代理在做某件你不赞同的事,把它加为一条规则,告诉代理在下次做那件事之前读那条规则,它肯定不会再那样做了。

技能

技能(Skills)类似规则,只不过与其说是编码偏好,不如说更适合编码「操作步骤」。如果你有一种你想要某件事被完成的特定方式,你想把它嵌入技能中。

事实上,人们经常抱怨不知道代理会如何解决一个问题,这让人感到不安。如果你想让这变得确定性,就让代理先研究它会怎么解决这个问题,然后把方案写成技能文件。你就能提前看到代理处理这个问题的方式,并在它真实遭遇这个问题之前进行修正或改进。

你怎么让代理知道这个技能存在?没错!你在 CLAUDE.md 里写,当你遇到这个场景需要处理这件事时,读这个`SKILL.md`。

处理规则和技能

你肯定想不断给代理添加规则和技能。这就是你给它个性和对你偏好的记忆的方式。几乎其他所有东西都是多余的。

一旦你开始这样做,你的代理就会感觉像魔法。它会「按照你想要的方式」做事。然后你终于会感觉自己「悟到了」代理工程。

然后……

你会看到性能开始再次下滑。

怎么回事?!

很简单。随着你添加越来越多的规则和技能,它们开始相互矛盾,或者代理开始出现严重的上下文膨胀。如果你需要代理在开始编程之前读 14 个 markdown 文件,它就会有一堆无用信息的同样问题。

怎么办?

清理。让你的代理去「做个 spa」,整合规则和技能,通过让你说明更新后的偏好来消除矛盾。

然后它又会感觉像魔法了。

就这些。这真的是秘诀所在。保持简单,用规则和技能,把 CLAUDE.md 当作目录,并虔诚地注意它们的上下文和设计局限性。

对结果负责

今天没有完美的代理。你可以把很多设计和实现工作交给代理,但你需要对结果负责。

所以要小心……然后好好享受!

玩未来的玩具(同时显然在用它做严肃的事情)真是一种乐趣!

免责声明:本文章仅代表作者个人观点,不代表本平台的立场和观点。本文章仅供信息分享,不构成对任何人的任何投资建议。用户与作者之间的任何争议,与本平台无关。如网页中刊载的文章或图片涉及侵权,请提供相关的权利证明和身份证明发送邮件到support@aicoin.com,本平台相关工作人员将会进行核查。

分享至:
APP下载

X

Telegram

Facebook

Reddit

复制链接