《从零实现 Agent 系统》连载 03|控制循环:感知—决策—行动—反思

前两篇《Agent 系统是什么:问题空间与架构切片》《领域模型与状态:先把「名词」对齐》画了分层盒子、对齐了会话和轮次里该出现的东西。本篇接上:在一轮之内,运行时如何一圈一圈转起来------模型的多步工具循环、在哪儿停,以及打点该挂在哪儿。


一句话:这轮里系统在干什么

外行看聊天,内行看「在同一条会话状态上,谁先谁后地走完了哪些步 」。一次用户发来的 Turn (我们在连载 02 里说过的粒度)内里,往往不是「打一枪模型就收工」,而可能是:读当前上下文 → 模型出一招(可能要工具)→ 真去执行工具并把结果喂回去 → 再读、再出一招,直到模型决定收笔,或者被规则掐停。

老式教科书爱用 感知---决策---行动---反思
感知 :此刻模型和策略能「看见」什么(消息序列、上一轮工具产出、租户身份等);决策 :模型(再叠策略门禁)吐出「下一步说什么、要不要调哪个工具」;行动 :网关与注册表真正把工具跑了;反思 在这里不必玄乎,落地成:把行动的观测写回上下文 ,下一轮感知才能接续同一事实 。名字古典,本质是闭环


同步「轮」与内部的「tool 小节拍」

要分清两样东西:外层 :用户这一轮 Turn,在服务端可能是一个同步 handler 或服务过程里走完(对调用方看起来像一次请求在等待);内层 :为了完成这一次 Turn,while/for 出来的多圈 LLM ↔ 工具 往返,行业里常叫 tool loop

内层每一圈粗略是:

  1. 把当前 work 消息列表送进网关,附上当圈允许暴露给模型的工具 Schema;
  2. 模型回合结束:若没有工具调用,就带着最终 Assistant 话术收口,外层 Turn 完结;
  3. 若有工具调用:对每个调用走一遍批准与策略闸门 (可挡、可待人审),再通过控制面跑一次「执行 turn」,把结构化结果包成 role: tool 的消息 追加进 work
  4. 回到步骤 1

外层同步与否,不改变这个内层节拍;异步调度是后话,这里只管「这一轮里语义怎么闭合」。


与 LLM 的多轮交接:靠什么「对话态」连在一起

模型的 API 吃的是消息链表 一类的结构:system、user、assistant、夹杂 tool 角色的返回。Tool loop 不是 在服务外另开若干个无状态 HTTP;而是在同一个 work 副本上反复 append。谁负责维护这条链、谁负责截断与摘要,便是记忆层和网关要守的界线------本篇只假定「链在,且每一步追加是 deterministic 的」。

实战中还要注意:finish_reason 一类信号(停词、超长、提供商自定义)会与「有没有 tool_calls」一起决定走不走下一圈------具体字段依厂商而异,思想上都是「这轮模型声明自己停在哪」。


停下来:四类常见出口

不写代码也能先立规矩,轮到什么时候必须停

  1. 自然停 :本轮模型产出里不再有工具调用,Assistant 的最终文本已经可以返回给用户。
  2. 步数熔断 :工具圈数设有上限 (例如配置里的「最大工具轮数」);超出则宁可返回可读错误话术,也别无限转悠------防止费用与时间上不封顶,也方便测试预期。Agentium 的聊天 agent 在这条路上走到头时,会向用户退回一句交代「已到工具轮上限」类信息,并把内部原因记成 length/上限语义,留给日志与告警。
  3. 人等门 :中途某工具被要求 pending 审批,循环主动抛错或挂起,把控制权交给工单或另一条接口------这一轮不算悄悄成功。
  4. 故障与网关错误:提供商异常、超时、解析失败------应进入你们统一的错误通路,别把半条消息链默默丢了。

四类里,前两样是产品设计必谈;后两样是企业里区分「不可用」与「尚未批准」的分水岭。


观测打在哪儿:tracing / log 的落脚点

每一段值得单独计账:

  • 每一圈网关调用 :一次 span (或等价物),挂上 tenant_idrun_id/session_id、本轮索引。
  • 每一次工具派发 :再起子 span:工具名、参数摘要、成功与否、毫秒耗时------与连载 02 提到的工具调用记录字段应能对上账。
  • 策略门禁结果 :放行、拒绝、待人批,各占一条结构化日志,出事要能按 trace_id 串起来。

原则:打点跟着「感知---行动」边界走 ,比在业务代码里零散 printf 可维护得多。


一张循环示意

虚线熔断表示:每一圈都可能被配置或全局守卫掐断,图里不单画分叉,脑子里要有这根弦。


伪代码:最小 tool loop(带步帽)

照旧跑不起来 ,只表达结构;MAX_STEPS 即工程里的「最多工具轮」配置。

php 复制代码
function RunTurnToolLoop(initial_messages, deps) -> AssistantOutcome:

    work := copy(initial_messages)
    steps_used := 0

    while steps_used < MAX_STEPS:

        round := deps.llm.complete_one_round(work, tools=deps.tool_schemas_this_round(work))

        if round.has_final_text_without_tools():
            return ok(round.assistant_text, finish_reason=round.finish_reason)

        if round.tool_calls empty:
            return ok(round.assistant_text, finish_reason=round.finish_reason_or_stop)

        work.append(round.assistant_message_with_tool_calls())

        for each call in round.tool_calls:
            if deps.policy.blocks(call):          # 含待人工审批的路径
                return blocked_or_raise(call.reason)

            result := deps.execute_tool_via_control_plane(call)
            work.append(tool_message(result))

            deps.observe_tool_span(call, result) # tracing / latency / status

        steps_used += 1

        # 「反思」已通过 work 重写完成;下一轮感知自动看见新工具消息

    return cut_off("已达到工具循环步数上限", trace=deps.collected_trace)

deps 在真项目里是一大捆对象(网关客户端、注册表、控制面、RequestContext 工厂......),拆不拆是工程细节;环形结构不变


容易被低估的三件事

把「能用」当成「不会在第十二圈才爆」:没有步帽和费用意识,_demo 跑得越顺,投产越心惊。

tool 结果被人类悄悄改了再喂模型 :少了结构化边界,回放对不上。取消信号 如果只挂在 HTTP,内层长跑次工具卡住时,run_id 级的中断无从谈起(下一篇会与生命周期补缝)。

观测只做「最后一跳」:中间圈的延迟与失败全黑箱,出事只能猜。


收束一下,下一篇讲什么

现在你应能说清:外层 Turn 包住 内层 tool loop ;每一圈「模型---工具---写回」怎么闭;在哪儿自然停 、在哪儿熔断 、在哪儿把人接进回路 。下一篇轮到 调度与租约------如何把「跑得动」升级到「可多任务、可被抢占、可被治理地跑」(仍尽量保持同步心智,异步平面再往后放)。

相关推荐
王牌狮AIen1 分钟前
AI营销智能体实战:OPC如何重构自主获客闭环?
大数据·人工智能·重构·数据挖掘·geo·ai营销
代码有点萌2 分钟前
ComfyUI 新手实战记录:一次跑通 AI 绘图工作流
人工智能
元启数宇3 分钟前
机电设计AI不只是消防:给排水、暖通、强弱电如何进入自动化?
运维·人工智能·自动化
我登哥MVP5 分钟前
VS Code 安装 Claude Code 并接入 DeepSeek V4 Model
人工智能·python·node.js·agent·codex·deepseek·claude code
unique6 分钟前
AI Native 调研报告
人工智能
云烟成雨TD7 分钟前
Spring AI Alibaba 1.x 系列【73】两步 RAG
java·人工智能·spring
ai产品老杨8 分钟前
解耦视频高并发与边缘计算AI布控:基于Docker的高性能安防平台,破局GB28181/RTSP协议兼容与源码交付痛点
人工智能·音视频·边缘计算
CHrisFC9 分钟前
LIMS 系统 AI 建设路径:从自动化到智能化的演进之路
运维·人工智能·自动化
饼干哥哥10 分钟前
一口气搭了300个AI Agents并发处理跨境运营的dirty work
人工智能
AI行业学习10 分钟前
CC‑Switch v3.16.1-下载、配置、安装(2026‑06‑01 最新官方版)
开发语言·人工智能·windows·python