本文源于项目实践中的一份内部笔记,梳理了从接口调用到多Agent协作的核心工程问题。保持原文风格,略作整理扩充。
一、WorkFlow和Agent:两种流程控制模式
有了单个的接口调用,就需要对调用流程进行控制。根据控制流程角色的不同,分为两种模式:WorkFlow和Agent。
第一种:WorkFlow------流程引擎主导
使用流程引擎进行控制流程,比如在Activity这种流程引擎中添加一个由LLM进行决策的节点。
特点:
-
流程固定,流程版本化管理,每次修改后需要重新发布
-
可观测性强,执行流程有预期的
-
使用场景:有比较固定操作流程,修改频次比较少,比如审批流程。只有在特殊节点添加LLM进行路由决策
-
这种比较省Token
第二种:Agent------LLM主导
由LLM进行规划和控制下一步应该做什么。
特点:
-
流程不固定,下一步做什么不固定,没法实现预测。人工介入点不确定
-
比较费Token,全链路都需要LLM介入决策
-
工程上衍生出来一些问题:对提示词微调要求极高,上下文管理(上下文会超级大),执行日志记录,Loop次数控制,异常场景控制等
决策补充:确定性维度
除了成本和Token消耗,还有一个确定性维度值得关注:
| WorkFlow | Agent | |
|---|---|---|
| 行为边界 | 完全已知 | 不可穷举 |
| 责任归属 | 流程设计者负责 | LLM+提示词共同负责 |
| 回退策略 | 每个节点有明确的fallback | 可能无限发散 |
实际落地建议:从WorkFlow起步,仅在确定性流程中"开窗"给LLM做决策。只有当这个窗口的决策复杂度超出规则引擎可维护的范围时,才考虑将窗口扩大为Agent。渐进式策略比直接上全链路Agent要稳妥得多。
二、Agent控制模式
大模型的两个特点
-
输入提示词越大,结果越不准确
-
一次输出的文本越多,结果越不准确
解决思路:尽量将问题拆分为小任务完成。
-
如果任务可以拆分,比如编写不同的模块CRUD代码,那么就拆分为不同子任务进行
-
如果任务不可以拆分,比如写文章,拆分多次编写就会有明显的书写风格和理解的不同。可以先输出大纲和思路,再拆分为不同子任务编写
整体思路:ReAct
-
如果能够搜集信息满足规划需求,就可以先进行大体规划,然后一边执行一边看结果调整规划
-
如果刚开始不清楚怎么搞,严重依赖用户的反馈或者外部信息,那就做一步看一步。这种情况是第一种的简化,毕竟刚开始不清楚怎么走几步是胡诌
关于ReAct实现的补充:真正生产级的ReAct需要提示词模板(系统提示+工具描述+格式约束)+ 解析器(从LLM输出中提取Thought/Action/Observation)+ 执行器(工具调用+结果注入)+ 终止条件判断(最大步数、最终答案标记、置信度阈值)。这四层代码+提示词是耦合的,不是单纯"写好提示词"就完事。
多Agent协作模式
-
集中规划:思考和规划需要靠一个能力较强的LLM
-
编排器-工作者(Orchestrator-Workers):思考和执行对LLM要求不同,可以拆分
-
并行执行(Parallelization):如果任务可拆分,让几个Agent并行执行,最后收集总结结果
-
评估器-优化器(Evaluator-Optimizer):如果任务输出验收性不好,用一个Agent执行,另一个Agent进行验收
-
路由(Routing):如果任务对Agent的要求不同,高级的做高级任务,低级的做低级任务
-
完整链路:理解用户需求 → 思考怎么完成 → 规划步骤 → 执行 → 结果合并 → 验收
实现分层
-
WorkFlow:借助外部流程引擎完成
-
ReAct:借助提示词工程完成(配合解析器、执行器、终止判断)
-
Agent拆分和结果合并:用代码编写实现,这种交互模式没必要可配置
补充模式:哨兵-执行者
实践中还有一种常见模式:"哨兵-执行者"(Sentinel-Executor)。一个轻量Agent(甚至纯规则)负责"要不要调用重型Agent",只在必要时才触发大模型推理。典型场景:客服系统里先做意图分类+情绪判断,负面情绪+复杂问题才转给完整Agent。这本质上是路由模式的变体,但增加了一个"拒绝/跳过"选项,对控制成本很有帮助。
三、多Agent组织
三个核心问题
通讯协议:主Agent怎么描述任务;子Agent怎么回复任务结果
实践中建议强制结构化:
json
{
"task_id": "uuid",
"task_type": "query | generate | summarize | verify",
"context": { "scope": "...", "constraints": [...] },
"input": "...",
"expected_output_schema": {...}
}
子Agent回复必须严格遵循Schema,这样主Agent才能做结果合并和验收。Schema即合同,能减少大量解析异常。
任务图:可以让主Agent进行调用,将主上下文传入;也可以任务图透明,子Agent都可见,将结果写入上下文,写入后标记当前任务执行完成
隔离边界:类似MySQL事务隔离,不同子Agent需要进行逻辑隔离
重点:幻觉的叠加
示例:A → B → C
如果每次准确率有90%,叠加结果是 0.9 × 0.9 × 0.9 = 0.72
实际场景中,0.9³=0.72是乐观估计。错误会放大而非独立随机------A的错误可能导致B在错误前提上"合理推理",反而看起来更可信。
解决方案:
-
限制任务深度
-
后面节点对前面结果进行交叉验证
-
关键节点做"双盲并行"------同一个任务交给两个不同角色的Agent执行,结果比对
四、Agent评测
TDD在这里非常重要。
TDD(测试驱动开发)在Agent场景下不是简单的单元测试,建议分层:
| 层级 | 测试内容 | 方式 |
|---|---|---|
| 工具层 | 每个Tool的输入输出、异常处理 | 传统单测 |
| 提示词层 | 同一输入多次输出的一致性 | 回归测试集 + 语义相似度评估 |
| 链路层 | 多轮交互完整轨迹是否符合预期 | 黄金数据集 + 人工抽检 |
| 业务层 | 最终结果是否满足业务指标 | A/B测试、人工验收 |
关键原则:提示词变更必须有测试用例覆盖,否则线上漂移完全不可控。
五、Agent执行过程追踪
必须记录的内容
每次Agent运行需要记录:
-
完整Prompt,含系统提示
-
多轮交互的完整 messages\[\]
-
每次工具调用 + 参数 + 返回值
-
推理链,如有thinking模式
-
最终输出
-
Token消耗 + 延迟
实践补充:两个额外维度
-
决策时的备选方案:LLM在每一步除了选择的Action,还考虑了哪些备选?这对调试"为什么选错"很有价值
-
回放能力:记录的不只是数据,还要能重现执行环境(工具版本、外部API的mock状态),否则离线Debug时复现不了问题
存储建议
所有追踪数据结构化存储(JSONL),而不是散落在日志里。后续做评测、审计、可视化都会依赖这个。
写在最后
整个笔记贯穿着一条关键原则:不要把Agent当成黑盒。
-
WorkFlow模式把流程"白盒化"
-
多Agent协作把职责"白盒化"
-
评测把质量"白盒化"
-
追踪把过程"白盒化"
这四层白盒化叠加在一起,才能让Agent系统在生产环境里可维护。可维护性,是Agent工程和AI研究的根本区别。
本文基于项目实践笔记整理,希望对从事Agent工程落地的同学有所帮助。