面试知识库

M1 · AgentLoop 主循环与终止安全#

简历 Bullet Point: 设计 Think→Act→Observe→Reflect 有状态 AgentLoop,四层终止机制(深度闸 / 超时+迭代上限 / 结果截断 / 循环检测)替代 prompt 祈祷确保弱模型不死循环不爆 token;从固定购物链路重构为意图驱动能力菜单(planner 输出 tasks 按需组合工具子集),planner 确定性预置省一轮 LLM 往返


开场钩子#

场景#

项目早期用 Flash 系列做子 Agent 跑端到端测试,五个平台并行检索”旅行三件套”。其中两个子一直不收尾——不停换关键词重搜 item_search。更糟的是第五个子自己调了 shopping_summary 输出完整推荐清单——主 loop 期望 JSON 候选列表,拿到的是自然语言文案。5 分钟超时,用户什么都没拿到。

这次事故逼出了核心设计原则:对 LLM 的行为约束,prompt 是辅助,机制才是兜底。

面试官切入#

“你简历上写了’四层终止机制’——能展开讲讲为什么 prompt 不够用,需要四层机制?“


一、模块运作流程#

1.1 一句话定位#

主 AgentLoop 是系统执行核心:有状态 Think→Act→Observe→Reflect 循环,不写死步数,模型自判够了就调终结性工具收尾。四层机制兜底弱模型。

1.2 全景流程图#

1.3 分步详解#

主循环组装

_build_main_agent() 核心调用:create_agent(model, tools=FULL_TOOL_SET, system_prompt, middleware)。主与子用同一份工具集(13 个)、同 prompt、同中间件栈。区别只在 thread_id 隔离和模型档位(子用 get_fast_llm() 关 reasoning)。

终结性工具

TERMINAL_TOOLS = {"shopping_summary", "chat_fallback"}。LangGraph 检测到被调用后不再调度下一轮。留最后一轮让模型把结构化结果转成收尾文案,自然终止不丢文案。

四层终止机制

机制解决的失控类型
① 深度闸MAX_FORK_DEPTH=1,ContextVar 跟踪递归 fork 指数爆炸
② 超时+迭代上限主 300s/30 轮,子 90s/6 轮跑太久/转太多圈
③ 结果截断每次工具返回 ≤4000 token单工具撑爆上下文
④ 循环检测滑动窗口 6 次内同名工具 4 次反复刷同一工具

四层互不依赖、层层递进。④ 是软提示(不硬停),不行还有 ② 硬的兜底。

planner 确定性预置

开局第一轮模型几乎 100% 会调 planner,所以直接在 run_agent 入口确定性预置 planner 调用,省掉”模型花一轮只为说出 planner 这个词”的 LLM 往返。延迟减法的一刀。

reasoning_boost

pre_think Hook 在第一轮开 reasoning(开思考、降温度),后续轮关闭。因为第一轮意图拆解最需要推理,后续轮工具驱动不需要深度思考。追问轮 reuse 复用候选时也不开 reasoning。

收尾流式

shopping_summary 调用后不等模型完整生成收尾文案再推送——items_preview 事件先推商品卡(先出货),summary_delta 事件流式推文案(后出文案)。用户感知延迟大幅降低。

1.4 技术选型决策表#

组件选了什么为什么选它什么情况下换
Agent 框架LangGraph create_agent原生 middleware + recursion_limit + 终结工具检测需条件分支/审批节点 → StateGraph
终止策略终结工具 + 四层兜底模型自判收尾(正常)+ 机制保底(异常)确定性极高 → 固定步数 DAG
循环检测滑动窗口(6,4)5 平台各搜 1 次不误判工具种类极多 → embedding 行为相似度
控制面禁用执行层哨兵(工具表恒定)保 prompt cache 前缀匹配不依赖 cache → 摘工具更彻底

二、踩坑实录#

坑 1:Prompt 级终止纪律对弱模型约等于”祈祷”#

  • 现象:Flash 做子 Agent 无视”找够用就停”,重搜 7 圈或自行调终结工具输出推荐文案。
  • 修法:四层 fork 安全 + 阶段状态机 + 检索预算。prompt 降级为辅助。
  • 教训机制打底,prompt 辅助

坑 2:recursion_limit 是 super-step 数不是迭代数#

  • 现象:设 30 只跑了 15 轮被截断。
  • 修法recursion_limit = MAX_ITERATIONS * 2 + 1(一轮 = 两个 super-step + 1 最终响应)。
  • 教训:框架参数语义不要想当然,看源码怎么消费的。

坑 3:<termination> 放 prompt 开头等于没写#

  • 现象:终止规则放 prompt 开头,5-6 轮后被工具结果”稀释”,模型不收尾。
  • 修法:挪到末尾 + item_picker 返回时定点注入 SUMMARY_NUDGE
  • 教训:prompt 的位置时机比内容更重要。

坑 4:意图驱动改造时哨兵文案里藏着固定链#

  • 现象:prompt 改成能力菜单但模型仍走全链——middleware 5 条哨兵命令”依次 price_compare → shipping_calc → …”。
  • 修法:哨兵文案泛化成”按需”,刻意不把 tasks 注入做硬约束。机制管失控,不管品味

三、验收与量化#

回归测试#

场景验证点覆盖机制
递归 fork 被拦子调 dispatch_tool → 深度超限错误①深度闸
子超时/超限90s/6 轮 → 异常转字符串回传②超时+迭代
结果截断>4000 token → 尾部截断③截断
循环检测窗口内同工具 4 次 → 换策略提示④循环
终结纪律重发纯文字收尾 → 追加提示重发terminal_enforcer
终结后硬停调完终结工具再调 → 哨兵拦下terminal_reached_gate
子越权被拦子调 shopping_summary → 深度闸拦depth_gate

四层机制加入后,弱模型子 Agent 的”不收尾死循环”和”越权自行终结”类失败从 ~30% 降到零——不是弱模型变听话了,是每次越界都被机制拦住。


四、面试问答#

Q1: 主循环怎么判断”该终止了”?#

正常路径:模型自判调终结性工具。异常路径:四层机制逐层兜底。两条互不依赖。

追问:循环检测是硬中断还是软提示? 软提示——5 平台各搜 1 次不是循环。软的不行有超时/迭代硬的兜底。

Q2: 只想推荐几个商品却比价算运费全跑——是披着 loop 的 workflow?#

早期确实半 workflow 半 loop。流程次序没有一行代码强制,但 prompt 和哨兵隐含固定链。改造成意图驱动后 planner 输出 tasks,模型按需组合。哨兵文案也从”必四步”泛化成”按需”。

Q3: 四层之外还有什么防失控?#

三道”动机层面的防护”——fork 预算(max_parallel=1)、检索预算(TREE_RETRIEVAL_BUDGET=8,module dict 按 session_dir 共享)、token 预算(三级 ok/soft/hard)。和四层正交:四层管”怎么失控”,三道管”为什么失控”。

追问:检索预算为什么不用 ContextVar? 子 set 了新值父读不到——asyncio.create_task 复制 context 快照。改 module dict + session_dir 做 key。隔离用 ContextVar,共享用 module dict

Q4: terminal_enforcer 为什么必须当轮重发?#

模型没产 tool_call,框架判定”该结束了”——不会有下一轮。所以 post_reflect 置 retry_nudge,同一次 awrap_model_call 里追加提示重发。子 Agent 不受约束——子的正常收尾就是吐文字返回主 loop。

Q5: 哨兵拦截 vs 摘工具——浪费一次 tool_call 值吗?#

值。摘工具改 prompt 内容破坏 cache 前缀。cache miss 多付 ~11000 token 输入费 vs 一次无效 tool_call ~50-100 token。statewright 说”缩小工具空间效果更好”——哨兵实现了等效效果,选择空间被等效缩小,只是”调了被拦”而非”看不到”。


五、前沿概念#

5.1 AgentLoop vs Workflow vs ReAct vs Plan-and-Execute#

AgentLoop 核心优势是自适应步数 + 收敛判断。配合意图驱动,同一套代码处理 2 步品类查询和 15 步跨平台全链路。Workflow 步数写死;ReAct 缺 Reflect 收敛判断;Plan-and-Execute 计划可能过时。

5.2 机制优于 Prompt#

代码级确定性 + prompt 灵活性互补。prompt 覆盖正常路径(80%),机制兜底异常(20%)。

5.3 终结性工具模式#

把”终止判断”转化为”工具选择”——模型选工具的能力远强于遵守格式约定。shopping_summary 既是终结信号又是功能工具,一个工具承担”判断够了”和”产出结果”两个职责。


六、诚实边界#

维度做了没做什么时候该做
终止安全四层机制 + 终结纪律 + 终结后硬停纯 prompt 方案已验证不可靠
意图驱动planner tasks + 能力菜单 + 哨兵泛化middleware 不感知 tasks偶发方差影响分数时
循环检测滑动窗口同名工具计数语义行为相似度检测工具种类极多时
checkpointer未挂中途续跑/human-in-the-loop需可恢复任务时
多模型校准参数对 Flash/GPT 有实测调优无 per-model 自动参数调节接入新模型时