Elea Notes.

词条 · AI · 入门

Agent

把模型放进一个循环里:做一步、看结果、再决定下一步,直到收工。

也称:agent、智能体、AI agent、agentic、工具调用、tool use

下面从一个你自己每天都在手动做的麻烦讲起,一步步走到为什么它必须长成一个循环。

先看一个麻烦:有些任务,你在动手之前问不完整

你的项目跑测试报错了,你想让一个只会输出文字的程序替你修。

试着把这个请求写完整。“帮我修 bug”——修哪个?你得先跑一遍测试,看报错。报错指向某个文件的某一行——那你得先打开那个文件。看完才知道问题出在它调用的另一个函数里——于是又要去找那个函数。

停下来看看刚才发生了什么:你需要提供哪些信息,取决于你还没做的那一步的结果。这不是你懒得写清楚,而是问题本身在开始时并不存在完整形式,它只能一层层剥出来。

一次性的问答对付不了这种任务。不是因为答得不够好,是因为提问这个动作本身就完成不了

朴素尝试为什么都不够

顺着”想办法把问题问清楚”这个思路往下走,很自然会试这几招。它们全都会失败,而失败的方式恰好凑出了解法的形状。

招数一:把所有可能相关的东西一次性贴进提问里。 整个仓库贴进去——十万行代码远超上下文窗口,而”哪些相关”恰恰是待求的答案。更要紧的是,报错信息根本不在磁盘上:它得跑一次才存在。有些信息只能通过动作产生。

招数二:让它一次性输出完整的操作剧本,人照着执行。 剧本第 3 步该怎么写,取决于第 2 步的输出。要覆盖所有可能,剧本就得写成一棵树;每步 3 种可能结果、走 10 步就是 3^10 约 6 万条分支。剧本的长度先爆炸了。

招数三:人来当循环——模型说一步,人执行一步,把输出粘回去。 这一招是对的,大量人每天就这么用。它恰好证明了缺的不是智力:能力已经够了,缺的是有人守着把结果送回去。代价是每一步都占一个人。

招数四:写死一条固定流水线。 跑测试 → 读文件 → 改 → 再跑。终于自动了,但它只覆盖预想的那条路。测试因为缺依赖根本起不来时,流水线里没有”先装依赖”这一格,它会拿着一个空报错继续往下改。

四次失败凑出三条硬要求。这个循环必须:

  1. 动作真的落到世界上,且结果能回流——有些信息只有动过才存在;
  2. 控制流在运行时决定,不能预先写死——下一步是什么,看上一步返回了什么;
  3. 有停下来的条件——完成、放弃,或者用光预算。

满足这三条的程序就叫 agent。注意这三条里没有一条是关于模型的:它们全都在描述模型外面那一圈。

机制:观察—决定—执行—回流

一个 agent 就是这样一个不停转的圈:

        ┌──────────── 观察 ────────────┐
        │   目标 + 到目前为止的记录     │
        └──────────────┬───────────────┘

                 决定下一个动作          ← 模型在这里,只在这里

        ┌──────────────┴───────────────┐
        │  执行:跑命令 / 读写文件 /     │
        │  搜索 / 调 API                │
        └──────────────┬───────────────┘

              结果追加进记录 ────────────┘

              停了吗?完成 / 放弃 / 超预算

三个部件缺一不可,而且各自坏起来的样子不同:

  • 工具:动作的出口。工具集决定了它的能力上限——没有执行命令的工具,它永远读不到报错。
  • 记录(也叫轨迹、scratchpad):每一轮把新结果追加进去,再整份喂给模型。这是循环唯一的记忆,也是它最贵的部分:轮次越多,记录越长,每一轮的推理成本随之上涨。这个”越往后越贵”的性质,正是 KV Cache 要处理的问题。
  • 停止条件:没有它,循环就不会结束。实践中三种停法——判定完成、判定无解放弃、撞上步数或花费上限。第三种是兜底:前两种判断本身也可能出错。

关键在于模型只出现在”决定下一个动作”这一格。其余三格是普通程序,没有一点智能。所以同一个模型换个外壳,表现可以差得很远——这也让下一节那个区分变得要紧。

为什么值得知道:读 agent 新闻时,先分清哪一层变强了

“某 agent 在 SWE-bench 上从 33% 提到 55%“——这句话有两种完全不同的读法,而榜单本身不会替你区分。

  • 模型层变强:同样的循环、同样的工具,“决定下一步”这一格判断更准了。能力边界移动了。
  • 框架层变强:模型一个字没换,外面那圈工程变好了。允许更多步数、失败自动重试、把手工点击换成写脚本、任务拆解更细、给它更好的工具。

两者都能推高分数,含义天差地别。一个框架把现有模型的成绩提二十个百分点,是了不起的工程,但模型的能力边界一寸没动;换一个任务分布,这二十个点可能整个消失。反过来,模型层的进步会让所有框架同时受益。

同一个循环视角还能解释三件表面无关的事:

  • 为什么 agent 的失败常常很难看。一次问答答错就是答错;循环里第 3 步判断错了,后面每一步都建立在错误的观察上,最后交出一个自信、完整、方向完全错的结果。错误会沿着循环累积。
  • 为什么”给它更多步数”有时管用、有时纯烧钱。步数只在它有能力从结果中纠偏时才值钱。如果它读不出报错的真实含义,多给一百步就是把同一个错误重犯一百次。
  • 为什么权限是这里的核心问题,不是附加题。让循环有用的前提,是动作真的落到世界上——真的写文件、真的发请求。这和”可撤销”直接冲突:一次问答说错话没有后果,一个 agent 判断错了会留下真实的痕迹。
  • 为什么多个 agent 协作没有天然的加成。把两个循环接起来,只是让第一个的输出成为第二个的观察。它不改变任一循环的纠偏能力,却把累积误差的路径拉长了一倍。协作有用的场合通常是任务本身可切分、且每段有独立的验证手段。

一个反过来的判断也成立:如果一个任务能一次问清、一次答完,就不该套上循环。 循环的每一格都在花钱和引入出错机会。它换来的只有一件事——让动作的结果参与后续决策。任务里不需要这件事,循环就是纯粹的开销。

所以对 agent 该问的问题不是”它聪明吗”,而是:它能做哪些动作,它怎么知道自己错了,以及它撞上什么会停。 三个问题分别对应第二节那三条要求,答不出任何一个,这个 agent 就还处在前面某一招数的失败状态里。