背景
2025年是 coding agent 快速起步的一年,同时 OpenAI 公布了 Codex cli 的源码。初次试用时我仿佛在看科幻电影:Codex 仿佛一个程序员自主探索,修改我写的 json 库并且添加新语法。大模型技术仿佛从聊天对话框,一跃成为了真正的人工智能。我不禁好奇,Codex cli 为整个 agent 的智能贡献了多少百分比?
先定义术语:其中 agent 指的是大模型+ agent cli。大模型作为纯粹的文字输入和输出,并不具备操作和读取计算机环境的能力,需要依靠 agent cli。而 agent cli 里面包括客户端 UI 部分(如登录,沙盒,插件),还有 harness 技术,harness 技术被认为可以增强整个 agent 的智能,让 agent 做更难的任务,做得更快。最常见的 harness 技巧就是上下文压缩。
本文想要探索的主题是,一个大模型+最小 agent cli,相较于大模型+最小 agent cli + codex 中的各种 harness 技巧,有多大区别?
最后的结论出乎我的意料:codex 中我选取的 harness 技巧对 agent 的智能影响很有限。现在的大模型依靠极少的 harness 技术就可以做很多。这样 agent cli 本身更多成为了一个 UI 软件,作为光鲜亮丽的果皮,整个 agent 的“果肉”还是藏在大模型里面。
研究方法
首先需要一个 bench 来测量 agent 的智能度,我选择了 DeepSWE。这里主要考量是,写本文时,GPT5.6 和 K3、deepseek 4.1刚刚发布,他们在评测报告里面都用了 DeepSWE。之前多用 SWE-bench 系列,但是 OpenAI 博客提到过这个系列的“泄题率”已经很高了,大模型很多时候仿佛都在背题。这些任务作为公开的 github 数据,疑似已经在训练中被新一代的大模型背下答案了。
DeepSWE 为了解决这个问题,雇佣了人类专家来编写题目,程序本身都是 github 上比较流行的开源仓库,然后人类出题和编写验证程序,再由团队的人审核题目。这个评测效果很好,刚发布的时候,各大主流模型通过率都远远低于 SWE-bench,非常具有区分度。值得一提的是,大模型评测很像人类考试,需要在一定的资源约束之下来完成任务。首先是金钱,很多论文都会有一个约束,单个任务不能超过多少钱,其次是时间,DeepSWE 的每个任务官方自定义的时间上限为1.5小时。
任务完成做验证时,有些任务验证超时了,我用 AI 检测,发现是死锁了,所以验证超时也被我判定为失败。
大模型我选择了 deepseek-v4.1-flash,因为它是开源的,性价比高,且通过率约在 50% 上下。太高了没有 harness 提升空间,太低了可能 harness 也无法补救,我希望选择一个智能度中等的模型。
agent cli 我选择了 Codex,因为它有大规模的 production 使用,而且完全开源。
这里还需要一个极简的 agent cli 来控制变量,一个极简的 agent cli 做的很少,就是发送请求给大模型然后接收响应,还有拿到大模型的指令之后在操作系统上执行。本来我打算自己写一个,但是调研时发现 SWE-bench 团队为了方便做实验,已经开源了一个极简的 agent cli:mini-swe-agent(下文简称 mini agent)。源码只有几百行,高度可扩展,可以使用继承和 jinja 模板改写各种参数,有齐全的实验设施,比如能够记录token消耗。
但在这里,我产生了一种直觉: agent cli 对智能的影响很有限。因为 DeepSWE 官方的榜单本身就是用 mini-swe-agent 来做的,在本文编写时,可以看到主流旗舰模型,几乎不需要复杂的 cli 就可以跑出 70% 以上的成功率。而 DeepSWE 里面的任务已经非常复杂了,基于的仓库都是来自多种语言的底层库,比如 Python 的静态检查器。后续的实验结果确实符合我的直觉。
在阅读 mini agent 源码的时候,我发现它并非一个没有 harness 的 agent,虽然官方自称它只有一个 shell 工具调用。但是我还是发现了两个 harness 技术,第一就是它做了工具截断,上限10000个字符;第二就是它有一套 workflow,在初始化的 prompt 中,它告诉大模型希望能够分解问题,编写测试等等,这里可以算作 prompt engineering。
关于智能度的指标,除了最常见的成功率之外,我还统计了 token 消耗量,还有 step,因为成本也是智能的一部分,step 可以展现大模型在路径探索上的高效。
harness 选择
研究的关键在于,到底要选取哪些 harness 技巧?这里我从 Codex 中选取了三个 harness 技术:
- 工具截断:很多工具的输出会产生巨量的上下文,比如打开大文件,使用工具截断可以防止一次 agent 执行命令就塞满整个上下文窗口。
- 结构化编辑(apply_patch):mini agent 使用 sed 来写文件,它的命令对于人类很难读,本质上就是字符串替换;而 Codex 自己实现了一套工具,用类似 git diff 的语法来编辑文件,能够让整个命令可读性更强。
- 上下文压缩:老生常谈的技术,就是当上下文膨胀之后,模型会难以把握要点,所以要对上下文做压缩。
我将把这些 harness 技术迁移到 mini agent 中,然后分别和原始的 mini agent 在 DeepSWE 任务的通过表现作对比。
过程和结论
工具截断
工具输出截断,在 mini agent 已经有了,恰恰是两个极简的 harness 技巧之一。
而且 Codex 和 mini agent 都选择了 10000 作为上限。这里我很好奇,如果调大或者调低这个上限会怎样?我分别调成了 1000 和 30000,最后的结果是整体的智能度都下降了。
截断 1000个字符:成功率下降7.08%,input token 增加 25.42%,agent steps 增加 69.31%。这里的 agent 明显有种迷失的感觉,需要很多探索才能做出任务。
截断 30000 个字符:成功率下降 7.96%,input token 减少 -11.64%,agent steps 减少 -4.30%。每个工具的输出增加之后,虽然成功率还是下降了,但是 token 消耗和 steps 也下降了,起到了一种 trade-off 的作用。这也符合我们的直觉,每次模型和环境交互,适当增加工具提供的上下文可以减少走弯路。在实际生产环境中,如果考虑节省成本,也是一种选择。
我的猜测是可能大模型厂商在训练时本身就是设置为 10000个字符,所以这里有些“过拟合”了。增加了工具输出时,虽然成功率下降,但是可以看到模型的效率提升。
这里要注意的是,要统计截断发生的次数,从 baseline 任务看,发生截断的任务有105个,总共675次。说明截断还是非常普遍的现象,值得去优化。截断下调到1000,任务数量为113,截断次数为 12,223;截断上调到30000,任务数量为 37,截断次数为 49.
结构化编辑
这里是我最感兴趣的部分,先讲讲结构化编辑和 mini agent 用 shell 直接编辑的区别。
如果要改程序中的一行,mini agent 会用命令行自带的 sed命令,它长这样
cd /app && sed -i \
's/ aliases=(),/ aliases={},/' \
src/adaptix/_internal/morphing/facade/retort.py
它表达的是:
- aliases=(),
+ aliases={},
而 Codex 编写了叫做 apply_patch 的工具,它会用自己定制的一套语法来编辑:
*** Begin Patch
*** Update File: /app/src/adaptix/_internal/morphing/facade/retort.py
@@
map=[
SkipPrivateFieldsNameMappingProvider(),
],
+ aliases={},
+ alias_style=(),
trim_trailing_underscore=True,
*** End Patch
可以看到改动一目了然。
于是我不禁想到,如果把这个技术迁移到 mini agent 会如何?毕竟按照我日常使用 chat bot 的经验看,人类读起来困难的内容,往往大模型也会觉得困难。
这里有个注意事项,就是 OpenAI 的 ChatGPT 在使用这个工具时,使用了一种叫做约束编码的技术。它能够现场教会大模型语法,然后约束大模型在推理阶段按照这种语法来生成,但前提是 Context Free Grammar。并非用 prompt 教会大模型,然后让大模型直接输出,因为这样无法保证 100% 语法正确性。
但是 deepseek 并没有这个技术,所以我只能用 prompt 的方法教会 deepseek 使用这个工具。不过后来在评测时并未发现 deepseek 产生 apply_patch 的语法错误。
Codex 中的 apply_patch 作为一个独立的库,还有测试用例,所以直接可以移出来,当做一个二进制给 mini agent 调用。
此外需要在 mini agent 的 prompt 里面标注,不要使用命令行来编辑文件,要使用 apply_patch。
最后的结果让我很意外:成功率下降 15.04%,input token 和 steps 几乎不变。
我怀疑还是过拟合的问题,deepseek 自己训练用的 agent 是用命令行,而 OpenAI 用了 apply_patch 。
于是我在这里引入一个支线任务,添加 ChatGPT 5.6 luna ,然后研究 apply_patch 的影响。最后的结果验证了我的想法:成功率下降 2.65%,input tokens 提升 28.11%,steps 提升 28.43%。
奇怪的是虽然成功率可以看做接近(考虑随机性),但是效率却下降了,所以这个工具的引入到底能产生多大的效益,还需要打一个问号。sed 这种编辑方法虽然对于人类很粗暴,但是对于大模型却可以轻松适应。
上下文压缩
上下文压缩是大模型中非常常见的 harness 技巧,虽然 DeepSWE 不是长程任务,总的上下文不会触及 deepseek模型的窗口上限,但是我在实际观测中,发现在单轮交互中,上下文的最大可以达到 223,852。我之前用大模型解读文档,发现虽然窗口生成1M,但是在到了十万字之后很明显出现注意力涣散,丢三落四。所以我猜想,虽然上下文小,如果在中间超过十万时压缩一次,是否也能产生效益,减少注意力的涣散?
于是我将压缩的阈值设置为15万。这里我想研究 Codex 的上下文压缩技巧,却发现 Codex 把它藏到了服务端,在服务端专门有一个 API 来做压缩,说好的开源呢?
不过在仓库中,发现 Codex 仓库中对于其他模型,写了一个本地用来压缩的 prompt。于是我便借鉴了这里的逻辑,这里的逻辑也有有趣。它会假装自己是另一个模型,要求大模型对当前的任务做一个摘要,方便自己接手。而且有比较细致的要求:
COMPACTION_PROMPT = """You are performing a CONTEXT CHECKPOINT COMPACTION. Create a handoff summary for another LLM that will resume the task.
Include:
- Current progress and key decisions made
- Important context, constraints, or user preferences
- What remains to be done (clear next steps)
- Any critical data, examples, or references needed to continue
Be concise, structured, and focused on helping the next LLM seamlessly continue the work.
Do not call any tools. Return only the handoff summary as text.
"""
最后运行的结果是成功率下降7.08%,input token 下降 15.78%,step 上升 13.48%。看来压缩后,agent 成功率下降,而且有种迷失感,就像之前工具输出截断调低了一样。
值得一提的是,虽然 input tokens 下降了,但是价格却微微上升,因为 output token 上升了。
看来目前对于大模型的压缩方式还是很难无损,这也和我使用 coding agent 的体验一致。 agent 做完上下文压缩,我经常会发现它忘掉了一些约束或者我提供的内容,需要我重新讲一遍。
总结
截止本文发布,我认为 agent cli 并未给 agent 提供多少智能的价值,更像是一个 UI,供用户交互。agent 真正的干货还是在大模型厂商那里。
技术难点
研究的程序都是用 GPT5.6 和 Kimi 2.8 写的。这里主要的难点是大模型经常会给出一个极度复杂的方案,然后迷失其中。比如 mini agent 接入各种 harness 之后,要在 DeepSWE 指定的 docker 环境中运行,而大模型提示我去给 harness 单开一个仓库,还有发布源码,提供一个 URL。最后在我的把关下改成直接使用 wheels 打包,比较方便简洁实现了功能。
再就是中间我想确定,reasoning effort 这个参数是否传递成功,因为 DeepSWE 的技术栈很厚,按照我之前的工业界经验,这种情况下传参数很容易丢。后来我亲自做了实验发现这个参数居然丢了,因为 DeepSWE 背后的技术栈依赖 Litellm,而它有个bug,会丢失传递给 deepseek 的 reasoning effort。而且当时还没有修好,只能用另外一种扩展 API 的方法传入。
我用了默认的 reasoning effort,如果有其他研究者使用其他强度,没有检查出这个 bug,过于信任 AI,那么整个研究就都失去地基了。
这里本质还是人机协作的问题,对大模型要信任到什么程度,仍然是个待讨论的难题。每个人有不同的答案。
局限性
按照 DeepSWE 官方的评测方法,每个任务应该跑四次,最后取均值来消除随机性。但是本实验预算有限,所以我只跑了一次。
此外尝试的大模型数量也有限。而且本文评测基于 DeepSWE 这样的短时任务,真正的现实中的开发是长期的,一个 session 可能要开一周。所以 skills 这样的 harness 技巧无法进行测评。这也是本文最大的局限性。
但是 DeepSWE 本身的难度和工作量,本身已经非常拟合程序员真实的工作,所以我认为这次评测还是具有一定的启发价值。
附录:技术栈
开发过程:
| 技术 | 版本或配置 | 用途 |
|---|---|---|
| Python | >= 3.12 | Harness、配置生成和实验分析 |
| uv | 0.12.3 | Python 环境、依赖和命令管理 |
| Hatchling | >= 1.27 | 将自定义 Harness 打包成 wheel |
| PyYAML | >= 6.0.3 | 读取任务和 Harness 配置 |
评测:
| 组件 | 版本 | 职责 |
|---|---|---|
| DeepSWE | v1.1,113 个任务 | Coding Agent 测试集 |
| DeepSWE commit | 435ee89ec2f2e2289f33b0da4f992f0b7b7266b9 | 固定数据集版本 |
| Pier | 0.3.1 | 创建任务、运行 Agent、执行 verifier、收集结果 |
| mini-swe-agent | 2.4.6 | 基线 Coding Agent |
| LiteLLM | 1.96.2 | 统一模型 API、usage 和费用数据 |
| Docker / Compose | 服务器环境快照为 Docker 29.1.3 | 隔离任务环境和依赖 |
整个项目部署在 Ubuntu24.04 上面。
其中 Codex 源码版本为:commit: 728cb12fe5794b0c3a8e776fb4994b1650b973a8 date: 2026-09-03 title: Expose thread originators through the app-server API (#42458)