Skip to content

第7章 一台自动接力的机器——Agent ​

小a终于把模型接通了。他让模型回答几个问题,模型答得头头是道。可一让它“把这个仓库里的测试都跑一遍,把失败修掉”,模型回了一句“我没法执行命令”,就停住了。

“模型明明很聪明,为什么一到干活就卡住?”小a问。

“因为它只会生成文本,不会执行动作。”老z说,“**要想让它‘干活’,需要另一台机器:把生成、执行、观察、再生成串成循环。**这台机器,就是 Agent。”

本章回答什么

  • Agent 的工作定义:它由哪几部分组成
  • 循环如何让“说”变成“做”
  • Workflow 与 Agent 是一条谱系的两端,不是对立关系
  • 自主性不是目标本身,何时该用 Agent 需要判断

不覆盖范围:循环的状态机、停止条件、并发等机制细节,留给第9章 让工作真正循环起来——Agent Loop;工具调用与执行边界,在第6章 从“会说”到“会做”——Function Calling和第8章 给能力装上把手——Tool。

先把名字对齐 ​

中文术语英文全称或缩写本书工作定义不等于什么
Agentagent由模型决策、工具执行和循环控制组成的任务工作单元一次性的问答请求
Agent 循环Agent Loop请求模型、处理工具结果、更新状态、重复的控制流模型自动拥有执行权
自主性autonomy系统在不等待人工逐步指示的前提下推进任务的程度无监督、无约束
Workflowworkflow预先编排的固定步骤流程;决策点在代码里与 Agent 非此即彼
宿主host持有状态、执行工具并决定停止条件的程序模型自身
编排orchestration把模型、工具、状态和人工审批组织成一次任务的协调方式堆更多模型

7.1 定义:能循环的工作单元 ​

“所以到底什么算 Agent?”小a问。

“先给一个可用的工作定义:Agent 是一个能反复调用模型、执行工具、观察结果并决定下一步的任务工作单元。”老z说,“关键不在‘模型有多强’,而在‘能不能循环’——一次问答不构成 Agent,循环起来才是。”

“循环里谁说了算?”

“模型提出下一步,宿主决定是否执行、何时停止。”老z说,“**模型是决策的提议者,宿主是决策的批准者。**这个分工,是后面所有可靠性讨论的起点。”

小a追了一句:“为什么要分这么清?模型提议完直接执行不行吗?”

“因为模型会错。”老z说,“它可能提议删掉一个不该删的文件,或调用一个越界的工具。如果提议即执行,错一次副作用就落地了。分两步,宿主才有机会在落地前拦——这是 Agent 能做危险动作而不翻车的前提。”

“那宿主拦的标准是什么?”小a问。

“是预先写死在宿主里的策略:哪些动作允许、哪些路径越界、哪些需要审批。”老z说,”这套策略不在模型脑子里,而在代码里——所以它可审计、可测试,也不会因为模型这一轮’心情不好’而漂移。模型负责想,宿主负责守。”

“能举个被拦下来的例子吗?”小a问。

“比如模型提议 delete_file,参数是 /tmp/old.log。”老z说,”宿主查策略:这个目录下的文件可以删,但必须在本项目生成的清单里;old.log 不在。于是宿主拒绝,把原因写成结果回给模型。模型读到后换成另一条路径,或者干脆不删了——**提议没落地,所以还有得商量。**一旦提议即执行,商量就变成了事故处理。”

“那宿主的这一查,会不会拖慢循环?”小a追问。

“会,但这是刻意换来的。”老z说,”模型出提议,成本是一次生成;宿主查策略、做决定、留记录,是在动作真的准备落地时才发生的。**把’想’和’批’分开,贵的部分只在必要的时候才付。**反过来,如果让模型每轮都自己判断’这能不能删、要不要批’,等于把不可靠的环节放进了每一条路径。”

环节谁负责靠什么保证出了问题会怎样
提议模型上下文与工具声明提议不合理,但尚未落地
批准宿主代码里的策略漏批放行,副作用落地
执行宿主/工具执行器实现结果可能失败或被污染
记录宿主日志与状态无法追溯,排障只能靠猜

"那如果宿主的批准逻辑本身有 bug 呢?"小a问。

"那也要分开记。"老z说,"模型提议错了,是决策质量问题;宿主批准错了,是策略配置问题。两者修的地方完全不同——前者可能要改工具声明或上下文,后者要改代码。合在一起记,等于把两个责任方塞进一个黑盒,出了事只能一起背锅。"

"那宿主的批准逻辑越复杂越好吗?"

"不是。批准逻辑复杂到没人能读懂,它自己就成了新的不可靠源。"老z说,"策略要简单到可以审查,关键路径要有测试,而不是堆一长串没人改得动的 if。边界是用来挡模型的不靠谱,不是用来攒自己的复杂度。"

要点

  • Agent 的核心是循环,不是模型
  • 模型提议,宿主批准并执行
  • 单次问答不等于 Agent

7.2 从“说”到“做”靠的是循环 ​

小a在纸上画了一个圈:

text
模型生成下一步请求
    ↓
宿主校验并执行工具
    ↓
把结果放回上下文
    ↓
再请求模型决定下一步(或停止)

“这不就是一个循环吗?”小a问。

“对。但要注意每个环节的职责。”老z说,“模型负责‘下一步做什么’,工具负责‘把动作变成真实结果’,上下文负责‘让模型看到上一步发生了什么’——任何一环缺了,任务都会在某个地方停住或失真。”

“工具结果回来之后,模型就知道该怎么做了吗?”

“不一定。”老z说,“工具返回什么,模型就看到什么。如果工具没有返回、返回了错误或者被污染的内容,模型只能基于错误信息继续。循环的质量,取决于每一环的信息是否真实。”

小a问:“哪种情况最坑——没返回,还是返回了错的?”

“返回错的更坑。”老z说,“没返回,模型至少知道‘这步没成’,还能换条路;返回了错的信息但格式正常,模型会把它当成事实继续往下推,错误就沿循环一层层放大。沉默的失败会停住,伪装成成功的失败会一路滑坡。”

“那宿主能做什么?”小a追问。

“在结果进上下文之前,先校验它的形状。”老z说,“比如工具说‘成功’,但结果里少了该有的字段,宿主就该把它标成异常再交回模型,而不是原样塞进去。循环可信的前提,是每一轮喂给模型的,都是被验证过的事实。”

小a想了想:”所以循环不是越快越好——慢一点去校验,反而更稳。”

“对。”老z说,”**省掉校验换来的快,会在后面几轮用失真的决策还回来。**循环的价值在于可信地推进,不在于单轮多快。”

“这有点像接力赛。”小a说,”每一棒传歪一点,后面就全歪了。”

“对,而且歪的幅度会累积。”老z说,”第一轮模型基于一个半真半假的结果做决定,第二轮它把那个决定当'事实'再推进——错误不只在原地停留,它会被每一轮重新当成输入喂回去。所以循环里最值钱的动作,是结果进上下文之前的那道校验。”

“校验具体查什么?”小a问。

“至少三样:结果有没有到达、该有的字段在不在、状态和声明一不一致。”老z说,”工具说'成功',就得有成功对应的产出;说'失败',就得带失败的原因。缺了任何一样,先标成异常再交回模型,别原样塞进去。”

"那这轮校验站在哪里?"小a问,"我总怕漏掉它。"

"就站在'结果回到模型之前'这一格。"老z画了张带校验点的图:

text
模型决定下一步 → 提议动作 → 宿主校验提议 → 执行工具 → 结果
     ↑                                                      │
     │                        ←── 形状校验、状态核对 ──     │
     └─────────── 校验通过后的结果放回上下文 ────────────────┘
                             ↑
                    校验点在结果入口,不在执行出口

"执行完之后不等于直接喂给模型。"老z说,"中间有一道只属于宿主检查,跟模型无关。这道检查做一次,能拦住后面好几轮的连锁失真——它站的位置,决定了它是闸门还是摆设。"

信息环节失真的样子模型容易被带偏成什么样
工具没返回结果缺失以为动作没发生,原地重试
工具返回错误带原因的错误结果知道失败,可以调整或放弃
工具返回假成功声称成功但没有产出当事实继续推进,错误逐轮放大
上下文被污染混入无关或过旧内容基于错误前提做下一步

7.3 Workflow 与 Agent 是一条谱系 ​

小a翻到团队里另一套系统:客服工单处理,每一步都是代码写死的。

“这套不是 Agent 吧?”他问。

“它更像 Workflow。”老z说,“**Workflow 把决策点写死在代码里:条件满足就走这条路,不满足就走那条。**它可预测、易测试、成本可控。”

“那 Agent 呢?”

“Agent 把一部分决策点交给模型在运行时做出。”老z说,“任务越复杂、越难预先穷举分支,模型决策的价值越大;但代价是行为不可完全预测。”

“所以不是谁替代谁?”

“对。”老z说,“大多数真实系统介于两者之间:外层用 Workflow 兜住主流程,内层在必要时让模型决策。把两者当成二选一,会错过大量合理的中间形态。这个话题在第16章 当路线不止一条——Workflow & Graph展开。”

小a问:“那我怎么判断一段流程该写成 Workflow,还是交给模型?”

“看这个决策点的分支能不能提前数清。”老z说,“分支有限、条件明确,写进代码——稳定又便宜;分支多到写不完、或者条件要靠理解上下文才能判断,才考虑让模型在运行时选。判据是‘我能不能预先写完所有 if’,不是‘用模型显得更先进’。”

“混着用,有没有代价?”小a追了一句。

“有。”老z说,“混用系统的代价是,出了问题你得分清错在哪一层:是 Workflow 的分支走错了,还是模型在那一层决策错了。调试和审计的成本,随混合层数上升——所以混,是按需混,不是越多层越好。”

“那谱系的两端,是 Workflow 在左、Agent 在右吗?”小a问。

“位置不重要,刻度才重要。”老z说,”这个刻度就是’多少决策点交给模型’:全在代码里是纯 Workflow,全给模型是高自主 Agent。你的系统落在这条轴的哪一点,取决于任务能容忍多少不可预测。”

老z在纸上画了一条轴:

text
决策点全在代码                         决策点全交给模型
     │                                      │
 纯 Workflow ──────────── 混合 ──────────── 高自主 Agent
     │                                      │
 可预测、便宜                       开放、不可完全预测
     │                                      │
  分支能预先数清                     分支数不清,靠运行时判断

“落在轴上的不同位置,代价也不一样。”老z指着中间说,

维度纯 Workflow混合高自主 Agent
决策点在哪代码里主流程代码 + 局部模型运行时模型
可预测性高中低
单次成本低且稳定中可能失控
调试难度低随混合层数上升高
典型任务路径固定、分支可数多数真实系统开放、变化快

“所以选位置时,真正要回答的问题是’你的任务能容忍多少不可预测、又付得起多少调试成本’,而不是’用模型显得更先进’。”老z说。

“那谱系的图,和 7.5 的三个信号,是一回事吗?”小a问。

“是一枚硬币的两面。”老z说,”谱系图告诉你选位置看什么刻度,三个信号告诉你刻度上的关键阈值在哪。前者的答案落在’轴上的哪一点’,后者的答案落在’这个点到底能不能安全落地’——一个选位置,一个验位置。”

7.4 自主性不是目标 ​

小a听到“自主运行”,眼睛亮了:“那是不是让它自己跑,人就不用管了?”

“自主性不是目标,是手段。”老z说,“**让模型多一分自主,你就多交出一些可预测性、可审计性和对成本的控制。**一次任务可能几分钟收敛,也可能烧掉大量预算还不停止。”

“那自主性有什么用?”

“用来处理人无法预先写死分支的开放任务。”老z说,“但每增加一点自主性,就要配套增加停止条件、审批点和失败路径。自主性和护栏是成对出现的。”

小a问:“护栏能不能等 Agent 跑起来再补?”

“不能,顺序反了。”老z说,“自主性上去之后,你已经允许它在没人盯的情况下推进任务。这时候再补护栏,等于在已经跑起来的车上装刹车——你没拦住的那些轮,副作用早就落地了。护栏要先于、至少同步于自主性落地,不能后补。”

“那自主性高低,怎么定?”小a追问。

“按失败代价倒推。”老z说,”动作越不可逆——删文件、发邮件、付款——自主性越低,越要卡审批;动作纯读、可重来,自主性可以高。自主性的额度,由’错了能回滚多少’决定,不是由’模型聪不聪明’决定。”

“那给一张表吧。”小a说。

动作类型可逆性失败后果自主性额度
读取、搜索高,无副作用最多多花点 token高,可放手
写入草稿、缓存中,可覆盖数据被覆盖,还能回滚中,设预算上限
发邮件、改配置低,几乎不可逆影响真实用户低,卡审批点
付款、删除、发布极低且波及面大事故级极低,逐次确认

“自主性上去之后,护栏具体指什么?”小a问。

“至少四样:停止条件、预算上限、审批点、失败路径。”老z说,”停止条件决定它什么时候算’做完’;预算上限决定它最多能烧多少成本;审批点决定哪些动作必须停下来等人;失败路径决定卡住或出错时往哪退。四样缺一样,’放手让它跑’就不是放权,是放任。”

“预算上限这栏,写死了会不会太死板?”小a问。

“可以设,但设了就要有对应的动作。”老z说,“预算耗尽时停下来、把已经完成的部分留成可恢复的状态,然后把‘为什么停’交给下一步处理——而不是让任务在预算上裸奔,跑到超时或出事故。停止条件是决策,不是默认值:每一轮结束后问一次‘还值不值得继续’,比一口气跑到顶再倒回去便宜得多。”

“那停了之后能续上吗?”

“如果每一步都留了状态和日志,可以。”老z说,“续跑的本质是恢复上下文、接着上一轮的成果往下走。这要求每个中间结果都可保存、可重建——只记‘完成了百分之多少’是不够的,要记到‘完成到哪个动作、结果是什么’。留不下中间状态的任务,停了就只能从头再来。”

“同样的动作,换成不同任务,额度会变吗?”小a追问。

“会。’删除’在清缓存任务里是常规操作,在删生产数据库的任务里就是高危动作。”老z说,”**额度要跟着任务上下文走,不能只按动作类型一刀切。**一个系统里常见的设计是:默认低额度,任务声明了明确的边界(目录、账号、金额上限)之后,才把额度放给那部分。”

要点

  • 自主性越高,可预测性与可审计性越低
  • 护栏必须随自主性一起设计,不能后补
  • “能自主”不等于“应该自主”

7.5 何时该用 Agent ​

小a把候选任务列了一遍,问老z:“怎么判断一个任务要不要做成 Agent?”

“看三个信号。”老z说,

用 Agent 的三个信号

  1. 任务有开放性:分支无法预先穷举,需要运行时判断
  2. 环境会变化:输入、状态或工具结果在执行中才可知
  3. 失败可容忍:有明确的停止条件,最坏结果在可接受范围内

“反过来,如果任务路径固定、输入可控、失败代价极高,Agent 未必是最优解。”老z说,“先问‘这里需不需要运行时决策’,再问‘用 Agent 划不划算’。”

“三个信号要全满足才用?”小a问。

“不必全满足,但有一条是硬的:失败可容忍。”老z说,“前两条决定 Agent 能不能发挥价值,第三条决定它能不能安全地发挥。一个开放、会变、但错了赔不起的任务,宁可做成每步审批的半自动,也别直接放成自主 Agent。可容忍的失败边界,是用 Agent 的安全垫,缺了它前两条再强也不该上。”

“那三个信号之外,还有没有第四类提醒?”小a追问。

“有一个:任务里有没有‘整段重复劳动’。”老z说,“如果同一类任务每天出现几十次,先别急着做成自主 Agent——更便宜的方案可能是先把固定部分做成 Workflow 或模板,只把变化的部分留给模型。Agent 适合处理‘每次都不一样’的任务,不适合处理‘每次都一样’的任务。”

“那把固定任务硬做成 Agent,会怎样?”小a追问。

“白白多花成本。”老z说,”路径固定、输入可控的任务,用 Workflow 直接走完更便宜、更稳。做成 Agent,每次都要请求模型做一次它本来该直接执行的决策——多花一轮调用、多一层不可预测,换来的’灵活性’根本用不上。Agent 不是更高级的 Workflow,是另一种取舍。”

老z又补了一条判断链:

text
分支能否预先数清?── 能 ─→ Workflow 直接写死
        │
        不能
        ↓
输入在执行中才可知?── 否 ─→ 再想想是否真要运行时决策
        │
        是
        ↓
最坏失败后果可容忍?── 否 ─→ 半自动 + 关键步审批
        │
        是
        ↓
可以设计成 Agent

“也就是说,三个信号其实是两层?”小a问。

“可以这么看:前两条回答’Agent 能不能发挥价值’,第三条回答’它能不能安全地发挥’。”老z说,”前两条满足、第三条不满足的任务最危险——模型有充分的理由去跑,但跑错了你赔不起。那种任务只能做成每步审批的半自动,不能直接放成自主 Agent。”

维度更适合 Agent更适合 Workflow
分支数量无法穷举有限且明确
输入确定性执行中才可知开始时已知
失败代价可回滚或可容忍不可逆或极高
成本敏感度接受调用与不可预测开销追求稳定、低成本

7.6 一台 Agent 由什么组成 ​

“那一个 Agent 最少要有哪些零件?”小a问。

老z列了一张清单:

Agent 的最小组成

  • 模型:负责生成下一步请求
  • 上下文:承载系统规则、历史与工具结果
  • 工具:把动作变成真实世界的结果
  • 循环:串联以上三者,并执行停止条件
  • 边界:权限、预算、审批等限制最坏后果的机制

“这五个零件,正好是后面十章的地图。”老z说,“模型怎么生成、上下文怎么管、工具怎么设计、循环怎么转、边界怎么设——每一章回答一个零件的工程问题。”

“’最小’是什么意思?”小a问,”少一个不行吗?”

“少一个,它就退化成别的东西。”老z说,”没有循环,它是单次问答;没有工具,它只能动嘴不能动手;没有边界,它跑起来不受控;没有上下文,它每轮都失忆。这五个不是配置项,是构成 Agent 的必要条件——真实系统会往每个零件上加更多东西,但底座跑不掉。”

“逐项说说退化,会更清楚。”小a说。

“好。模型没了,剩下的逻辑只是死的程序;上下文没了,模型每轮看到的都是一张白纸,前面几轮的结论带不过来;工具没了,它只能输出建议,永远落不了地;循环没了,它转一次就停,做不完多步任务;边界没了,它跑多快、花多少、碰哪些文件都没有限制。”老z说,

零件负责什么缺了它的退化形态
模型生成下一步请求只剩程序逻辑,没有决策
上下文承载规则、历史与结果每轮失忆,任务无法连续
工具把动作变成真实结果只能动嘴,永远停在”说”
循环串联三者并执行停止条件单次问答,无法收敛
边界限制最坏后果不受控,一个错动作就翻车

“注意边界和循环的分工。”老z补充,”循环负责’什么时候停’,边界负责’停下来之前不允许碰什么’。一个管时间的终点,一个管空间的范围,两者不能互相替代——把停止条件写清楚,不代表越界动作就不会发生,边界要单独设。”

“能用一个任务把这五个零件串一遍吗?”小a问。

“就用’把仓库里的测试跑一遍,把失败修掉’。”老z说,”模型读到任务和上下文里的仓库信息,提议 run_test(模型);宿主查边界:这个工具允许吗、参数里的测试名在不在白名单(边界),校验通过后执行(工具),把测试输出回填上下文(循环);模型看到失败,继续提议下一步,直到所有测试通过或达到预算上限(循环的停止条件)。五件缺一,这个任务就在某一步停住或失控。”

“所以排障的时候,也是按这五个零件定位的?”小a追问。

“对。任务卡住了,先问卡在哪一环:模型没提出合理提议,是上下文不够;提议了但没执行,是宿主策略或工具不存在;执行了但结果不对,是工具实现或校验缺失;转了几轮不收敛,是循环缺停止条件;碰了不该碰的东西,是边界没设好。五个零件对应五类故障,也对应五类日志。”

“那谁最容易成为短板?”

“看任务缺什么就短什么。”老z说,“开放型任务缺边界最危险——模型越聪明,跑偏的破坏力越大;长链任务缺上下文最危险——前面几轮的结论带不过来,后面全在重复或失忆;多步任务缺循环最致命——转一次就停,任务永远做不完。短板不是固定的,是跟着任务形状变的。”

7.7 把生成留给模型,把控制留在宿主 ​

小a看着清单,忽然意识到一件事:“所以模型只是一台会生成文本的机器,把它变成‘能干活’,靠的是循环和边界。”

“对。”老z说,“模型负责想下一步,循环负责把它串起来,边界负责不让它闯祸——这三件事没有一件是模型自己能完成的。”

“那把控制也塞进模型,让它自己决定停不停、批不批,行不行?”小a问。

“行不通,因为那是让被监督者监督自己。”老z说,”模型既提议动作又批准动作,等于没有批准这一环。控制之所以要留在宿主,恰恰是因为模型不可靠——可靠的部分才该交给模型,不可靠的部分必须留在代码里。这就是为什么我们从模型讲起,却不止于模型。”

“那把清单摊开看,哪些交给模型、哪些留在宿主?”小a问。

交给模型留在宿主
下一步做什么的提议是否执行、何时停止
选哪个工具、参数填什么策略校验、权限拦截
对结果的解读与下一步计划状态机、停止条件、审批与记录

“这看起来是分工表,其实是一条界线。”老z说,”表的上半行允许出意外——提议错了可以拒、参数错了可以拦,代价还没落地;表的下半行一旦出错,代价已经发生。把不可靠的东西放上表,把可靠的东西留在表下,这条界线画在哪,决定了整个系统敢不敢放手跑。”

“那这条界线会不会画错了?”小a追问。

“会,而且会随任务移动。”老z说,”新增一个高危工具、改一条审批策略,界线就该重新画一次。画界线的动作本身也要可审计——谁、在什么时候、把哪项从表下挪到了表上,都应该留得下记录。”老z说,”下一章,我们给这台机器装上第一批’把手’——工具。模型提议,宿主执行,工具让动作真正落地。”

小结 ​

Agent 不是”更聪明的模型”,而是把模型决策、工具执行和循环控制组织起来的任务工作单元。单次问答不是 Agent,循环起来才是;模型提议下一步,宿主批准并执行——这个分工是所有可靠性讨论的起点。提议是便宜的,批准是贵的,把两者分开,贵的部分只在动作真的准备落地时才发生。模型出主意、宿主守边界,这是 Agent 能碰危险动作而不翻车的前提;循环的价值也不在单轮多快,而在每一轮喂给模型的都是被验证过的事实——沉默的失败会停住,伪装成成功的失败会一路滑坡。

Workflow 与 Agent 不是二选一,而是一条谱系的两端:决策点写在代码里就是 Workflow,交给模型就是 Agent。判断一段流程该落在轴的哪一点,看的是分支能不能预先数清,而不是”用模型显得更先进”。大多数真实系统介于两端之间,外层用 Workflow 兜住主流程,内层在必要时让模型决策;混用带来的调试成本随层数上升,所以是按需混,不是越多越好。

自主性不是目标本身,它换取的是处理开放任务的能力,代价是可预测性、可审计性和成本控制。自主性的额度由失败可回滚多少决定,而不由模型聪不聪明决定;额度还随任务上下文移动,同一个动作在不同任务里是常规操作还是高危动作,可能完全不同。自主性越高,越要配套停止条件、预算上限、审批点和失败路径——护栏必须与自主性成对设计,不能等跑起来再补。是否用 Agent,看三个信号:任务是否开放、环境是否变化、失败是否可容忍;前两条决定它能不能发挥价值,第三条决定它能不能安全地发挥。

一台最小 Agent 由模型、上下文、工具、循环和边界五个零件组成——它们正是本书概念篇的地图:模型怎么生成、上下文怎么管、工具怎么设计、循环怎么转、边界怎么设,每一章回答一个零件的工程问题。这五个零件缺一不可,缺了循环是单次问答,缺了边界是不受控,缺了上下文是每轮失忆。所有零件之上还有一条界线:哪些交给模型,哪些留在宿主,界线画在哪、怎么移动、谁改过,都要能回答——这是把”一台聪明的打字机”变成”一台可信的机器”的最后一环。

动手核验 ​

把一个固定步骤的任务(如“读取配置并打印”)分别用 Workflow 和 Agent 两种方式实现,各跑 10 次,记录完成时间、失败次数和失败时的输出。重点观察 Agent 模式下模型在边界输入上做了什么“代码里没写”的决定——这正是 Agent 的价值与风险所在。