最近有一个视频标题在技术社区里转得比较凶:OpenAI just proved AI has no idea what it’s doing。意思是,OpenAI 的演示视频反而证明了 AI 根本不知道自己在做什么。这个说法有点标题党,但也不是完全没有道理。如果你最近在用 Codex、Cursor、Claude 这类 AI 编程工具,大概率遇到过类似情况:模型一步步把任务做完了,最后结果却是错的;或者它很自信地调用了工具,但路径、参数、输出目录全都不对。这不是某个模型的偶然 bug,而是当前大模型驱动的 Agent 的基本运行方式决定的。
这篇文章不打算争论 AI 是不是真的有意识。我想从工程实践角度,把“AI 不知道自己在做什么”这句话翻译成一个可以解决的问题:怎么设计任务边界、观测性、结果验证和失败重试,让一个并没有稳定自我认知的模型,也能在可控范围内帮你干活。
1. 这个视频真正值得讨论的不是“翻车”,而是 Agent 的运行方式
1.1 视频里所谓的“翻车”为什么能引发共鸣
这类视频在社区里流传时,通常会被剪得很碎,但核心讨论点基本一致:模型在一个多步骤任务里表现得非常自信,最终却偏离了目标。比如它以为自己已经完成了修改,实际上改错了文件;或者它在收到工具返回的错误之后,不是停下来检查,而是继续生成下一步,让错误越滚越大。
这种画面很容易被解读成“AI 不行”。但真正引发程序员共鸣的,不是“模型能力不够”,而是“模型看起来懂了,实际上没懂”。在日常使用 AI 编程工具时,这种错位感非常常见。你给模型一个任务,它说得头头是道,代码结构也完整,但放到真实项目里一跑,发现它把接口名写错了,把异步流程写成了同步,或者把一个只在测试环境存在的路径当成了生产路径。
如果只看单次输出,你会觉得模型还挺聪明。但如果你给同一个模型同一个任务,让它连续跑五次,五次结果可能都不一样。其中一次能跑通,另外四次各有各的问题。这个现象恰恰说明,模型并不是在“执行一个意图”,而是在“预测一堆 token”。
1.2 大模型不是“理解意图”,而是“预测下一个 token”
GPT 这类模型的核心是语言模型。训练目标很简单:给定前面的内容,预测下一个 token 的概率。到了推理阶段,它会根据你给的系统提示、用户指令、历史对话、工具返回结果,一步步生成后续内容。
这里的关键是:模型没有一个独立的“目标记忆区”。你说的目标、它自己上一步生成的步骤、工具返回的错误信息,都只是上下文里的文本。上下文一旦变长,或者某个工具返回内容把原始目标冲掉,模型的注意力就会偏移。这不是它故意装傻,而是它的架构本来就没有“我当前要完成什么”这种自省机制。
所以当视频里展示“AI 不知道自己在做什么”时,我理解的意思是:模型对任务目标的把握是非常脆弱的。它没有全局状态来维护“用户最终想要什么”,只能靠上下文里的线索维持一个表面的方向感。
1.3 对做工程的人意味着什么
这个认知非常重要。如果你还停留在“AI 应该能理解我的意图”这个假设上,那么遇到翻车时会很困惑。你会觉得是自己没说明白,或者模型版本不行,于是一直改提示词。但改提示词只能缓解,不能根治。
更稳妥的工程思路是把模型当成一个“随时可能跑偏的协作者”。你要在提示词里写清楚边界,在外部系统里保留状态,在关键节点做校验。不要把任务目标只放在模型脑子里,因为它没有真正的脑子可以用来长期保存目标。
这个前提,是所有 Agent 工程化的起点。
2. 把“AI 不知道自己在做什么”翻译成工程问题
2.1 先定义任务边界:能做什么、不能做什么
很多 Agent 任务翻车,不是因为模型不会写代码,而是任务边界太模糊。你让它“帮我把数据处理一下”,它确实会处理,但处理方式可能是你完全没预料到的。它可能把原始文件覆盖了,可能改变了编码格式,可能把数值类型自动转换了。
正确做法是把任务描述限制到“可验收”的程度。如果是一次数据处理,至少要说清楚:
- 输入文件路径和格式
- 输出文件路径和格式
- 哪些字段需要保留
- 哪些字段允许修改
- 遇到缺失值怎么处理
- 不允许修改哪些文件
不要觉得这样很啰嗦。对于人来说,很多隐含规则可以靠常识补齐。但模型没有稳定的常识一致性,它依赖的只有你给它的上下文。你写得越具体,它的随机性越能被约束住。
这里有个常见的误区:提示词写得长,不等于边界清晰。长提示词里如果塞了大量无关信息,反而会干扰模型对关键约束的注意。更有效的做法是把约束放在单独段落里,用清晰的“必须”“禁止”“遇到异常时”结构。
2.2 观测性:给 Agent 每一步留下可检查日志
我见过不少 AI 编程项目,跑的时候看起来很顺利,出了问题就完全无法排查。原因很简单:没有日志。模型做了什么,调用哪个工具,工具返回了什么,最终改了哪些文件,这些信息都没记录。
没有观测性的 Agent 其实不适合进入生产环节。因为模型的输出不是确定性的,你无法靠“代码看了没问题”来判断结果正确。你必须能够回答这几个问题:
- Agent 在什么时候开始执行这个任务
- 它按什么顺序调用了哪些工具
- 每个工具的输入和输出是什么
- 它在哪一步产生过自我修正
- 最终输出是否满足预设的验收条件
最轻量的做法是维护一份 JSONL 日志,每个事件一行。比如:
{"time": "2026-07-14T10:00:01Z", "event": "tool_call_start", "tool": "read_file", "args": {"path": "./data/input.csv"}} {"time": "2026-07-14T10:00:02Z", "event": "tool_call_end", "tool": "read_file", "result": "ok", "line_count": 1200} {"time": "2026-07-14T10:00:05Z", "event": "model_message", "content": "发现第 37 行缺失值,准备用空字符串填充"}有了日志,你就能在任务失败时往回追溯。否则整个 Agent 就像一个黑盒,成功了不知道为何成功,失败了不知道从哪一步开始错的。
2.3 结果验证:不能只看“过程看起来顺利”
模型在执行任务时,可能会很流畅地调用工具、给出解释、显示成功截图。但这些都不能代替结果验证。你必须定义“成功长什么样”。
比如让 Agent 修改一个 Python 文件,成功标准不能只是“文件被修改了”。你应该验证:
- 修改后的文件能否正常导入
- 语法检查是否通过
- 原有测试用例是否仍然通过
- 是否产生了意料之外的文件变更
- 变更范围是否严格限定在允许修改的目录内
验证可以交给脚本,也可以人工抽查。但不管怎样,验证必须独立于生成过程。不能让生成代码的模型同时负责验证自己生成的代码,因为它的验证标准和生成标准来自同一个随机过程,容易出现“自己检查自己觉得没问题”的假象。
3. 从 OpenAI Codex harness 开源看 Agent 工程化思路
3.1 Codex 和 harness 到底是什么
Codex 是 OpenAI 的编程型 Agent。它可以跑在终端里,用自然语言指令完成读代码、改代码、执行命令、查看测试结果这类任务。它不是一个单纯补全代码的模型,而是一个“模型 + 工具调用 + 环境控制”的组合系统。
harness 这个词可以理解成“模型外面那层工程壳”。模型本身只负责生成文本,harness 负责把模型生成的文本解析成工具调用、把工具返回内容传回模型、处理循环终止条件、管理权限和沙箱、记录日志。没有 harness,模型只是一个对话窗口;有了 harness,模型才能变成 Agent。
从社区讨论来看,OpenAI 把 Codex 的 harness 相关代码公开后,最值得关注的不是某个具体函数,而是它展示了一个 Agent 系统的内部结构:模型循环不是魔法,而是一套工程流程。所有你能想到的问题——该不该执行命令、要不要用户确认、日志保留到哪、错误怎么回传——都需要显式编码进去。
这里先说明一下:具体仓库的维护状态和版本变化很快,不建议大家照着某篇博客里的快照代码直接部署。更好的方式是把仓库当作学习材料,理解它的组织方式,再根据自己的场景重写。
3.2 一个最小可运行的 Agent 循环
如果你想自己实现一个最简 Agent,核心循环其实不复杂。下面的伪代码展示了基本结构:
def run_agent(instruction: str, tools: dict, max_steps: int = 10): messages = [{"role": "user", "content": instruction}] for step in range(max_steps): response = model_call(messages) tool_calls = parse_tool_calls(response) if not tool_calls: return response.content for call in tool_calls: result = execute_tool(call, tools) messages.append(tool_result_message(call, result)) return "max_steps exceeded"这个循环有四个关键点:
第一,模型返回的内容需要被解析。OpenAI 的 API 里,模型可能返回 tool_calls 字段,也可能直接返回文本。harness 要能区分这两种情况。
第二,工具执行结果必须作为消息追加到上下文里。如果不追加,模型就不知道工具运行得怎样,下一步就会瞎猜。
第三,必须有最大步数限制。否则模型可能会无限循环,反复调用同一个失败工具。
第四,工具调用列表可能要支持并行。有些工具互相独立,可以一次执行多个,减少来回调用的时间。但并行也会带来副作用,比如两个工具同时写同一个文件。工程上需要在速度和安全性之间做取舍。
3.3 Codex CLI 与 API 的取舍
Codex 提供了 CLI 使用方式,也可以作为 API 接入自己的系统。两种方式适用场景不同。
CLI 适合交互式操作。你想在本地仓库里快速跑一个修改任务,让模型在终端里一步步执行命令,遇到敏感操作时人工确认。这种模式对个人开发者非常友好。缺点是自动化程度有限,你很难在 CLI 里做精细化权限控制、批量队列和自定义审计。
API 适合嵌入到自己的业务系统。你可以控制每次调用的上下文、并发、超时、重试和日志。虽然需要写更多代码,但可定制性更高。如果你的目标是每天跑几千个不同仓库的修改任务,用 CLI 手动点肯定不现实,应该把 Agent 循环封装成服务。
无论哪种方式,API key 的保管都要特别注意。不要把 key 硬编码在代码里,不要提交到 GitHub,不要写在博客示例里。推荐放在环境变量或密钥管理服务中。网上流传的“api key 分享”内容风险很大,不要追求这种方便,一旦 key 泄露,损失的是自己和团队的额度与数据安全。
3.4 权限、沙箱与人工确认
Agent 能执行命令,这意味着它有能力删除文件、修改配置、提交代码、调用外部服务。如果让模型在全局环境里自由发挥,风险很高。你必须给它设置边界。
一个比较稳妥的分级方案:
- 默认情况下,Agent 只能读取指定目录
- 修改文件前先输出 diff,等人工确认
- 执行命令时使用容器或虚拟环境
- 禁止访问网络,除非任务明确需要
- 对高权限命令单独设置白名单
这些限制会让 Agent 变得“不那么自动”,但换来了可控性。尤其是当模型“不知道自己做什么”的时候,权限控制是最后一道安全网。
4. 落地时最容易被忽略的边界与坑点
4.1 资源占用:上下文长度比模型大小更值得关注
很多人在评估 Agent 时,先关心用的模型是 70B 还是 400B,显存够不够,内存多大。这些确实重要,但真正容易忽略的是上下文长度对任务稳定性的影响。
Agent 每执行一步,工具返回结果都会追加到上下文里。比如一个文件有 5000 行,模型读取了一次,上下文就多出 5000 行文本。如果再读五个文件,上下文轻松超过几万 token。上下文一长,成本上升,响应变慢,而且模型对早期指令的注意力会下降。
如果你要做批量任务,不要一次性把所有文件都塞给 Agent。比较合理的做法是拆分任务:先列出文件清单,再逐个处理,每个子任务使用独立的上下文。处理完成一个,就把结果写回磁盘,再清空上下文开启下一个。
这里给一个经验判断标准:如果你的 Agent 上下文经常超过模型最大上下文的一半,就要考虑换任务边界,而不是继续硬撑。超过一半后,模型漏指令的概率会明显上升。
4.2 “支持 API”不等于“支持生产级并发”
很多工具页面上写着支持 API 调用,但这不意味着你可以不假思索地开 100 个并发。API 服务通常有速率限制、超时限制、单次请求大小限制。忽略这些限制,你的批量任务会大量报错。
生产级接入要处理的问题包括:
- 并发数多少才不会触发限流
- 单次请求超时设置多久
- 失败后是重试还是跳过
- 重试是否需要退避
- 如何避免重复消耗费用
我建议从 1 个并发开始,先跑通一个小批量任务,统计平均耗时和错误率。再逐步增加并发,同时观察日志。不要一上来就开最大并发,因为你不知道服务端的限制,也不知道自己的代码在压力下会不会出问题。
还有一个容易被忽略的点:单位时间内的 token 消耗。即使 API 没有明确报错,大量长上下文的请求也可能让你的项目消耗速度快得惊人。批量任务上线前,最好先算一笔账:单次任务平均多少 token,计划跑多少次,总预算大概多少。
4.3 失败重试不能盲目“多试几次”
遇到 Agent 任务失败,很多人第一反应是重试。如果模型只是偶尔采样出问题,重试确实有效。但如果问题出在提示词、输入文件或工具定义上,盲目重试只会浪费时间和资源。
一个比较有效的做法是给错误分类:
- 可重试错误:网络波动、API 超时、偶发采样异常
- 需要修输入的错误:文件路径不对、格式不支持、内容缺失
- 需要修配置的错误:权限不足、依赖版本不对、工具参数错误
- 需要修提示词的错误:模型反复做同一个错误动作,说明上下文没有给足边界
重试前,先看日志里是哪种错误。如果是模型反复调用同一个失败工具,不要继续重试,应该停下来检查工具参数或提示词约束。如果是阶段性超时,可以增加超时时间或降低单次任务规模。
这里有另一个经验:同一个任务连续失败两次后,不要继续自动重试,改成交给人工检查。自动重试最多三次,再往上基本没有收益,反而会把错误模式放大。
4.4 评测:多次运行是否稳定,比单次完美更重要
既然模型有随机性,评估一个 Agent 就不能只看一次运行结果。你必须用多次运行的数据来判断,它到底是真的能完成任务,还是偶尔碰巧成功了一次。
最简单的评测方法是定义一个固定任务集,让 Agent 依次跑 N 次,统计这些指标:
- 成功次数占总次数的比例
- 平均耗时和最长耗时
- 失败时错误类型分布
- 输出文件与预期结果的一致性
- 是否产生越权修改
比如一个任务在一个模型上运行 10 次,成功 8 次,失败 2 次。剩下的两次为什么失败?如果都卡在某一步的权限检查上,那说明任务环境还有问题。如果分布在完全不同的环节,说明模型的随机性影响比较大,可能需要加更多校验或人工抽查。
评测的最终目的不是追求 100% 成功,而是让你知道这套 Agent 流程在什么情况下能信,什么情况下不能信。你只有掌握了失败模式,才能决定要不要上线、要不要增加人工复核节点。
5. 我的实测建议:先跑小规模,再谈“理解”
5.1 最小可运行样例怎么设计
如果你之前没接触过 Agent 开发,我建议不要一上来就搭一个大平台。先把一个最小任务跑通,比如:让 Agent 读取一个 CSV 文件,统计某列缺失值,把结果写到一个新的文本文件里。
这个任务不大,但足够覆盖 Agent 的核心流程:理解指令、调用工具、处理返回值、生成最终结果。你可以用任意方式实现,无所谓是 Codex CLI 还是自己写的 API 循环。关键是先跑通一遍。
我一般会先用一条数据做测试,再把数据扩展到 100 条。这个顺序看起来慢,但能最快暴露问题。不要在一开始就用完整数据跑批发任务,因为一旦 Agent 对文件格式理解错误,批量处理只会快速生产一堆错误结果。
5.2 单任务验证清单
单任务跑完之后,不要只看屏幕上的答复文字,按下面的清单做一次完整检查:
| 检查项 | 怎么检查 | 通过标准 |
|---|---|---|
| 输入文件是否被读取 | 看日志里的 read_file 调用 | 路径正确,文件存在 |
| 输出文件是否生成 | 查看输出目录 | 文件存在,非空 |
| 输出格式是否符合要求 | 打开文件检查 | 列名、分隔符、编码正确 |
| 是否修改了额外文件 | git diff 或对比目录 | 没有越权改动 |
| 失败时是否有日志 | 查看 JSONL 日志 | 关键步骤有记录 |
| 单次任务耗时 | 统计开始到结束时间 | 在自己可接受范围内 |
| 资源占用 | 看 CPU/内存/网络 | 没有异常高峰 |
如果这些检查都通过,再进行下一步。否则,先修复问题,不要带着问题跑批量。
5.3 批量任务与队列设计
批量任务比单任务复杂很多。你不仅要把每个子任务跑出来,还要管理任务状态、输出文件命名、失败记录和断点续跑。
最简单的状态机是四态:pending、running、done、failed。每个任务开始前写入 pending,开始后写入 running,成功写 done,失败写 failed。这样就算程序中途崩溃,你也能从日志和状态文件里看出哪些任务还没完成。
输出文件命名要避免覆盖。比如按时间戳或任务 ID 命名,或者把每次运行结果放到独立目录。不要让多个任务同时写同一个文件,否则会产生竞态问题。如果任务本身不支持并发,就老老实实按顺序跑。
批量跑完后,建议增加一个人工抽查环节。尤其是首次跑一个全新任务类型时,至少抽查 10% 的结果,确认 Agent 的输出风格和处理逻辑符合预期。
5.4 怎么判断一个 Agent 是否值得上生产
不是所有任务都需要 Agent 化。有些任务逻辑固定、输入输出格式明确,用传统脚本处理更稳定、更快、更便宜。Agent 的价值在于处理那些“规则边界不清晰”的任务,比如根据自然语言修改代码、分析一段日志并给出建议、整理非结构化文本。
判断一个 Agent 是否值得上生产,我认为主要看四个指标:
- 成功率是否达到可接受水平
- 失败后人工修正成本是否低于自己做
- 单次任务的资源和费用是否可控
- 日志和观测性是否足够支撑排查
如果成功率很高,但失败后需要大量人工介入,那整套流程的收益可能并不高。如果成功率一般,但任务本身具有探索性质,人工修正成本也不高,那 Agent 依然可以带来价值。
关键是要算清楚账。不要因为“用了 AI”就觉得一定划算,最后变成把简单问题复杂化。
6. 回到视频:AI 到底知不知道自己在做什么
6.1 说“不知道”不等于否定 AI
回到那个视频标题:OpenAI just proved AI has no idea what it’s doing。我的判断是,这个说法确实抓住了当前 AI 的一个本质:模型没有稳定的自我认知与目标自省能力。但这并不等于 AI 没有用。
我们换一个类比。一个人体工程机器人可以按照传感器数据不断调整机械臂位置,但它并不知道“自己在组装一台汽车”这个宏大目标。它只是在一个很小的控制循环里稳定地执行操作。Agent 也是一样。模型在最底层只做 token 预测,但外层工程把这种预测能力封装成了工具调用、任务循环和结果验证,最终也可以完成复杂任务。
所以正确的结论不是“AI 是骗子”,而是“AI 需要外部系统来帮它兜住目标和状态”。
6.2 正确心态:把 AI 当成随机性很强的协作者
如果你把 AI 当成一个“知道自己在做什么”的资深工程师,你会经常失望。因为它会犯新手都不会犯的错误。但如果你把它当成一个“语言能力很强、但方向感很弱”的协作者,你的使用方式就会完全不同。
你会给它更明确的任务边界,会在关键节点设计检查,会要求它每一步留下记录,会在它连续失败时及时干预。这些做法不是对 AI 的苛责,而是对真实系统稳健性的保障。
我见过很多成功的 AI 落地案例,它们的共同点不是模型特别聪明,而是工程约束特别清楚。它们把模型放进了很小的任务盒子里,让模型在这个盒子里自由发挥,然后用日志、校验、权限和重试机制把风险兜住。
6.3 今天就能做的事
如果你读完这篇文章,想立刻把“AI 不知道自己在做什么”这个认知变成行动,可以从这几件事开始:
- 挑一个你经常交给 AI 的小任务,把输入输出和约束写成明确清单
- 给 Agent 加上日志,至少记录每次工具调用和返回结果
- 不要只跑一次,同一个任务跑三到五次,观察成功率
- 如果一个任务连续失败两次,停下来看日志,而不是继续重试
- 把批量任务的输出目录从“默认输出”改成“任务 ID + 时间戳”
这些事不需要花很多时间,但对提升可靠性非常明显。踩过几次坑之后你会发现,很多问题不是模型能力不够,而是我们默认它“应该知道自己在做什么”,却没有给它足够的边界、观测和验证机制。
我个人的结论很明确:当前大模型确实没有稳定的自我认知,但只要不再要求它“知道”,而是给足边界、观测和验证,它就能在大量普通任务里做出稳定贡献。真正值得警惕的,不是 AI 不知道自己做什么,而是人类把“看起来会做”当成了“真的会做”。