
一个多智能体系统上线后业务方经常拿着一条失败对话来问“这单到底是谁搞砸的”你打开日志第七步 A 智能体调了一个库存查询接口第九步 B 智能体开始生成补偿方案第十六步 C 智能体给出了最终答复。从最终回复看系统拒绝了用户但用户不认可这个结果。问题在哪一步如果你把这条轨迹拿去训练模型应该加强哪一步、削弱哪一步面对十几个执行步骤很少有人能给出明确答案。这不是工程日志写得不够详细的问题而是多智能体系统里一个非常底层的问题当最终结果较好或较差时系统无法把这份“好坏”回溯到每一个中间决策上去。在强化学习里这个问题叫信用分配credit assignment。CREST 论文所做的事就是尝试用验证器verifier来约束这种信用分配先让一个外部验证器判断每一步到底对最终结果贡献了多少再根据判断结果去训练多轮智能体。我看完这个题目后一个很直接的判断是多智能体的瓶颈正在从“模型能不能生成”转向“系统能不能知道错在哪”。提示词工程解决的是单次决策质量而信用分配解决的是整条轨迹的训练效率。两者不在一个维度。本文会先拆解这个问题的来源再分析 CREST 的思路落到训练系统和工程调试里分别意味着什么最后给出普通开发者现在就能借鉴的做法。1. 为什么“跑得通但训不好”是多智能体项目的隐形瓶颈1.1 先理解多轮智能体的信用分配所谓多轮智能体有两种常见形态。一种是单个智能体需要连续执行多步任务比如“先查资料、再写方案、最后发邮件”每一步都依赖上一步的结果。另一种是多个智能体分工协作比如一个负责理解用户意图一个负责调用业务系统一个负责生成回复。这两种形态常常叠加形成时间维度上的多轮决策和空间维度上的多智能体分工。信用分配说的就是当一条完整的执行轨迹最终获得成功或失败的反馈时如何把这份整体反馈合理地回溯到每一步上。如果任务是“杀毒软件扫描文件并删除病毒”最后一步成功清除病毒那么前面的扫描步骤、隔离步骤分别贡献了多少如果是团队协作任务团队赢了MVP 应该给谁这两类问题本质上是同一个问题。问题难在哪里第一奖励信号是稀疏的。多智能体系统通常只在任务最终完成或失败时拿到一个清晰结果中间每一步是没有天然分数的。第二状态空间是长期依赖的。第八步的错误可能源于第三步的某个错误决定如果只看第八步本身根本发现不了问题。第三多智能体场景下各智能体之间还会相互“推锅”。A 智能体可以说“我生成的内容没问题是 B 拿到的上下文不对”B 可以说“上下文没问题是 A 没有把关键信息传给我”从各自局部视角看它们都说得通。1.2 一个让所有开发者头疼的业务场景假设你正在做一个售后退换货助手流程拆成了三个角色意图识别智能体、订单查询智能体、方案生成智能体。用户问“我上周买的耳机坏了想换一个新颜色的”最终系统回复“无法换货只能维修”。用户很不满意。如果从这个结果反推意图识别智能体可能把“更换颜色”识别成了“维修申请”订单查询智能体可能没有找到符合条件的在保订单方案生成智能体可能误解了售后政策。只看最终结果三个智能体都有嫌疑。传统做法是什么开发者在本地拿这条日志逐个智能体重新跑一遍观察中间输出最后猜测问题集中在哪一步再修改对应提示词。这个方法能做但无法规模化。训练模型时也一样。如果最终结果失败就给这条轨迹里所有智能体的所有动作打一个相同的负分那么真正没有犯错的那几步也会被削弱。一段时间之后你会发现整个模型都变得“不敢动作”多智能体协作反而退化了。这就是信用分配失败带来的典型后果。2. 提示词调不动时强化学习为什么也救不了2.1 LLM Agent 训练的特殊困难很多团队一开始尝试用提示词调优多智能体。调提示词能解决一部分问题但很快会碰到天花板同一个任务换一种问法结果就不一样同一条失败轨迹你修改了某个智能体的提示词结果整体变好了但你分不清是提示词本身变好了还是下游智能体碰巧适应了新输出。这种“盲调”在单个智能体场景里还能忍受在多智能体场景里成本会指数上升。于是大家开始考虑用强化学习微调 Agent 模型。传统强化学习处理信用分配已经有比较成熟的思路引入价值函数、计算优势函数、用时间差分回溯奖励。但 LLM Agent 加入后动作空间不再是几个离散动作而是自然语言和工具调用。一个动作是否合理常常需要结合大量上下文才能判断。这让传统方法里的“状态价值估计”变得非常不稳定。更麻烦的是自然语言动作很容易钻奖励函数的空子。如果你给每一步都打一个“过程奖励”模型会学会说一些看起来在推进任务、实际上没有帮助的废话。如果你给每一步都打高分它甚至可能反复调用同一个工具假装在工作。这类行为在强化学习里叫 reward hacking奖励攻击在文本 Agent 里远比在游戏环境里常见。2.2 只看最终结果的方案无法完成归因不少实际训练项目采用的方案是任务最终成功给正奖励最终失败给负奖励然后让策略梯度算法自己去回溯。听起来合理但放在多轮智能体场景里问题非常明显。一条轨迹可能包含 20 步其中 18 步都做得很好但第 15 步选错了工具最终任务失败。如果给整条轨迹打负分那前 18 步那些本来值得保留的行为也被一视同仁地惩罚了。强化学习算法的优化信号噪声很大最终可能导致两种结果要么模型变得过度保守只做最有把握的动作不去尝试解决复杂问题要么模型因为某个偶然成功的轨迹把大量错误的中间行为也固化下来形成了一种“运气好才成功”的策略。这背后的根源是一样的没有把整体结果拆成可验证的中间信号。模型只知道“结局不好”但不知道“哪里开始不好”更不知道“哪一步即使结局不好本身也是必要的探索”。2.3 多智能体场景让归因更混乱如果只是单个智能体的长任务信用分配还可以通过“哪一步之后状态变差了”来近似判断。但在多智能体系统里每一个智能体都只掌握自己的局部上下文很难判断自己输出之后下游发生了什么。A 智能体觉得自己输出得很好但它不知道 B 智能体在处理它的输出时暴露了理解偏差。当所有智能体共享同一个最终奖励时谁该为失败负责这件事就变成了一个协作难题。这也是为什么许多多智能体研究最终都会回到一个问题上你能不能为整条轨迹提供一个足够可信的“过程裁判”。没有过程级信号算法层面的改进空间非常有限。3. 现有办法与各自的边界在讨论 CREST 之前有必要把目前业界常用的几种信用分配方案放在一起比较。它们各自解决了一部分问题但都存在比较明显的缺陷。3.1 结果级奖励与人工逐步标注最朴素的办法是只看最终结果。实现简单但信号稀疏很难支撑长轨迹训练。为了缓解稀疏问题有些团队改成人工标注把每条轨迹拆开让标注员给每一步打分。这个做法能提供高质量信号但成本很高而且不同标注员对“这一步贡献了多少”的理解很难统一。标注员只能看到当前步骤和上下文无法知道如果换一种动作下游会不会更好。所以人工标注其实也是在猜测。3.2 让模型自己反思另一种常见做法是让 Agent 在失败后自己看一遍轨迹反思哪一步出了问题。这个方案实现成本低但在实践中非常不稳定。模型缺少外部事实依据时反思很容易变成自我辩解。让它解释“为什么失败”它很可能生成一个逻辑通顺但完全错误的原因。把它写进训练信号相当于用错误标注训练数据效果很难保证。3.3 从 reward model 到 verifier为了获得更可靠的过程信号研究社区开始引入 reward model奖励模型和 verifier验证器。这两个概念经常被混用但在方法论上有区别。reward model 通常是一个打分模型给一条回复或者一个状态估计一个数值verifier 则更强调“对错判断”它的输出往往带有更强的确定性语义比如“这个答案是否正确”“这一步推导是否合理”。在数学推理任务里结果级验证器已经比较成熟。你让模型生成解题过程最后用一个能够可靠检查答案的验证器判断最终结果是否正确。这个过程监督process supervision的思想也由此而来不再只验证最终答案而是逐步骤判断逻辑是否存在错误。这里就出现了一个关键转机如果验证器能够判断“每一步是否合理”那它就具备了成为信用分配信号的基础。CREST 的方法名中同时出现了“验证器”和“信用分配”指向的正是这个方向。3.4 现有方案小结方案信号来源优点主要问题最终结果奖励任务成功/失败实现简单、无标注成本信号稀疏无法定位失败步骤人工逐步标注人工评估每一步信号质量高、可解释性强成本高、标注标准难统一模型自我反思Agent 回顾自身轨迹实现成本低容易自我确认错误归因率高LLM-as-JudgeLLM 对步骤做整体评估可扩展、带自然语言理由存在位置偏差、校准不稳定CREST 思路验证器约束信用分配能区分步骤贡献、可约束训练验证器自身质量决定上限表格里的前四种方案解决的是“如何获得过程信号”而 CREST 更接近一种训练框架它不只让验证器去评价轨迹还让验证器的判断去约束每一步信用值的分配方式。理解这一层才算真正抓到它的重点。4. CREST 思路拆解验证器如何约束信用分配4.1 验证器的真实身份从题目本身看CREST 最核心的机制是“验证器约束信用分配”。要理解它先要看清验证器在这条链路里到底扮演什么角色。在团队协作里一个优秀的管理者做绩效评估时不会只给团队一个整体结果。他会观察每个人的具体行为比如谁在关键节点提供了关键信息谁在推进过程中制造了阻塞然后根据这些观察分配奖惩。验证器在多智能体训练里的作用可以类比成这位管理者它并不直接完成业务任务而是逐轮观察智能体的行为给出“这一步对最终结果有多重要、是否合理”的判断。与直接打分模型不同的是验证器的结果通常要能被解释。比如验证器可以说“第 4 步调用查询接口时参数中的订单号格式错误导致后续所有步骤都基于空数据执行”。这种级别的原因输出对后续训练信号非常关键因为它把一条轨迹的失败定位到了具体步骤而不是把责任平均分摊给所有人。4.2 “约束”而不是“替代”理解 CREST 的关键在于“约束”这个词。验证器并没有替代最终的全局奖励信号而是在全局奖励分配回每一步时提供了一个约束条件。传统的策略梯度方法会把最终奖励通过某种方式回溯到每一步。问题在于回溯过程经常是盲目的所有中间步骤共享同一个信号的缩放版本。CREST 的思路是在回溯之前先让验证器评估每一步。如果验证器认为某一步非常可疑是导致后续失败的重要原因那么这一步就应该承担更大的负反馈如果验证器认为某一步虽然处于失败轨迹但本身没有错误那么这一步的信用损失就应该被压低。这样最终奖励和历史步骤之间就不再是一刀切的关系而是一种“被验证器校正后的关系”。验证器在这里不是替代奖励而是给信用分配加上了一种外部约束防止模型把偶然失败归因到无关步骤上也防止把偶然成功归因到错误行为上。从方法名称来推测CREST 想要完成的是一种比较典型的“两步走”先用验证器产出过程级的验证分数再把验证分数引入信用分配的计算。对强化学习算法来说这相当于在策略梯度更新时把一个全局奖励拆解成若干个“经过验证的分量”每个分量都带有明确责任主体。这样训练信号会干净很多。4.3 一个通俗类比羽毛球比赛里记分牌只会显示最终比分。你输了这场比赛但你想知道输在哪记分牌帮不了你。教练能告诉你第三局 15 比 15 的关键分你不该选择挑高球因为对手的杀球成功率很高第五局你连续两次放网前小球虽然失分但战术选择本身没问题只是执行质量有波动。教练在做的就是把你从比赛中获得的“输赢信号”分解成具体到某个时间点、某个动作的信用分配。验证器在多轮智能体里的位置和羽毛球教练非常像。结果信号是记分牌价值函数是技术统计验证器则是那个能指出具体动作合理性的复盘者。CREST 做的事情就是让这位复盘者不仅仅在赛后被动点评而是把它的点评结果直接用于后续战术调整。5. 一个概念性训练循环示例非官方实现说明一下CREST 论文的官方代码和公式细节需要以原论文发布版本为准。下面这段代码不是 CREST 的官方实现只是我按照“验证器约束信用分配”这个思路整理的训练框架概念示意用来帮助你理解它在一个真实训练循环里应该插在哪个位置。5.1 先看传统做法的问题这是一段没有验证器约束的信用分配伪代码# 文件路径tradition_credit.py # 概念示例传统做法把最终奖励平均回溯到每一步 def assign_credit(trajectory, final_reward): # 每条轨迹包含若干步骤最终只拿到一个全局奖励 for step in trajectory.steps: # 不管这一步实际贡献如何都获得相同的全局奖励缩放 step.credit final_reward print(f步骤{step.id} 获得信用{step.credit})这段代码最大的问题是当 final_reward 是负数时所有步骤都被惩罚。一个本来产生关键价值的中间步骤可能因为最终失败而被压制。长此以往模型中原本好的行为模式也会被削弱。5.2 引入验证器后的训练数据流接下来看引入验证器约束以后的版本# 文件路径verifier_constrained_credit.py # 概念示例用验证器分数约束每个步骤的信用分配 class Verifier: 验证器判断某个步骤对最终结果的贡献方向和程度。 def verify(self, step, final_reward): # 返回一个结构化的结果 # score 表示该步骤对结果的贡献取值建议在 -1 到 1 之间 # reason 表示可解释的原因方便人工复盘 return Verdict(score0.6, reason该步骤给出的数据是后续决策的必要前提) def assign_credit_with_verifier(verifier, trajectory, final_reward): weights [] for step in trajectory.steps: # 1. 验证器先判断这一步的贡献 verdict verifier.verify(step, final_reward) # 2. 用一个系数调节验证器分数与全局奖励的权重 # 这里使用 0.7 只是示意在实际研究中会作为超参参与训练 lambda_v 0.7 # 3. 约束后的信用分配 step.credit lambda_v * verdict.score (1 - lambda_v) * final_reward # 4. 保留理由便于后续日志分析 step.credit_reason verdict.reason weights.append(step.credit) return weights这段示意里最关键的是第三步步骤的信用不再等于全局奖励而是由验证器分数和全局奖励共同决定。如果最终奖励为 -1验证器判断某一步的贡献是 0.6那么这一步骤的惩罚会被大幅减小。如果最终奖励为 1验证器判断某一步是明显的负贡献例如输出了错误格式导致后续解析失败这一步的奖励也会被压低。这种方式相当于给信用分配装了一个“外部校正器”。5.3 验证器分数处理策略还有一个值得注意的细节验证器分数是直接当作奖励使用还是作为价值函数的监督信号两种选择会带来完全不同的训练稳定性。直接当作奖励使用相当于让策略优化立刻响应验证器的判断风险是验证器的单步误差会被放大。作为价值函数的监督信号则会在多次采样中取平均稳定性更好但相应也会慢一些。CREST 这类方法具体选择哪一种仍然要看原始论文的算法设计但对工程实现者来说两种思路代表的是完全不同的代码结构需要尽早确认。6. 没有训练集群的团队怎么借鉴这个思路看到这里很多读者可能会想我又不做大模型训练CREST 离我是不是太远了实际上验证器约束信用分配的思想即使没有训练集群也能直接借鉴到 Agent 工程调试里。6.1 用验证器生成可解释的过程复盘大部分 Agent 项目现在已经有了很详细的日志系统会记录每一步的模型输入输出、工具调用参数和返回结果。问题在于这些日志只是“记录”没有“判断”。CREST 给出的实际启发是在日志之上增加一层逐步骤验证器让验证器不只是把过程记录下来而是对每一步给出明确判断。假设我们为一个多智能体客服系统增加一个 offline 复盘脚本# 文件路径agent_review.py from dataclasses import dataclass dataclass class StepRecord: step_id: int agent_name: str action: str observation: str dataclass class Verdict: is_ok: bool score: float issue: str def review_steps(steps, final_status, verifier): 对多智能体执行轨迹做逐步骤验证找到最可疑的失败环节。 注意verifier 的输入和输出都建议先做好脱敏并且只做离线分析 不要直接用它触发线上操作。 suspicious_steps [] for step in steps: verdict verifier.verify(step) if not verdict.is_ok: suspicious_steps.append((step, verdict)) print(f最终状态{final_status}) print(f发现 {len(suspicious_steps)} 个疑似风险步骤\n) for step, verdict in suspicious_steps: print(f步骤{step.step_id}{step.agent_name}) print(f动作{step.action[:80]}) print(f验证器判断{verdict.issue}\n) # 如果最终失败但没发现任何风险步骤说明问题可能出在上下文传递环节 if final_status failed and not suspicious_steps: print(提示所有单步看起来都正常建议检查智能体之间的上下文传递。) # 使用示例 trace [ StepRecord(1, intent_agent, 分析用户意图, 意图申请换货), StepRecord(2, order_agent, 查询订单, 返回空数据), StepRecord(3, solution_agent, 生成售后方案, 基于空数据给出保守策略), ] verifier Verifier() review_steps(trace, final_statusfailed, verifierverifier)这里的 Verifier 可以是一个单独的 LLM API 调用也可以是你内部训练的验证模型。关键是它输出的必须是对“每一步是否合理”的判断而不是对整个对话的整体评价。跑完以后你会得到类似这样的一段复盘最终状态failed 发现 1 个疑似风险步骤 步骤2order_agent 动作查询订单 验证器判断订单查询参数中缺少订单来源标识导致返回空数据。后续步骤基于空数据继续执行。这个复盘脚本看起来很简单但它隐含着一个很大的改变你不再靠自己肉眼逐行看日志定位问题而是让验证器先把所有候选风险步骤筛出来。在多智能体系统出现“假阴性”“模型互相矛盾”这类问题时这个能力能节省大量排查时间。6.2 把复盘结果沉淀为训练数据更进一步的玩法是把每一轮验证器的复盘结果存下来形成一份“失败轨迹-问题步骤-问题原因”的结构化数据。这些数据既可以在你准备微调 Agent 时作为训练语料也可以在以后接入强化学习训练时充当初始的过程监督信号。很多团队都在抱怨找不到高质量的多智能体训练数据。实际上每一次线上失败都可能是一份训练数据只是缺一个可靠的标注者。验证器在这个流程里相当于一个自动化的初步标注器。它的标注不一定完美但可以显著降低人工排查范围。这也是普通开发者能落地的方向。7. 必须小心的边界验证器不是银弹7.1 验证器自身偏差会被放大CREST 逻辑上的优势来自于验证器的外部性但也正因为如此验证器的质量会直接决定整个训练的成败。如果验证器系统性偏向某类输出比如它对格式规范但内容空洞的步骤给高分那么模型经过若干轮迭代后会慢慢学会迎合验证器的偏好而不是真正做好任务。这其实是一种升级版的 reward hacking。过去模型钻的是奖励函数空子现在它钻的是验证器空子。想缓解这个问题通常需要定期用人工评估校准验证器或者在验证器训练集里不断加入对抗性样本。这意味着验证器并不是一个可以放养的工具它本身需要维护和迭代。7.2 成本与算力压力不能忽视逐步骤验证意味着每一条训练轨迹都要额外交给验证器处理一遍。如果轨迹很长验证器的分析成本会成倍增加。在多智能体协作场景里步骤之间还常带有复杂的工具调用结果验证器要分析的信息量比单轮问答大很多。如果训练任务又需要大量采样验证成本可能占到整个训练预算的很大比例。团队在评估方案时不能只看到效果提升的潜力还要把验证器调用成本计入总账。7.3 它解决的是训练信号问题不是 Agent 架构问题CREST 的贡献集中在“如何把信用分配做得更准”而不是“如何让智能体更好地规划”。如果你的系统连基础的工具调用、状态管理、上下文传递都还没理顺那么即使引入验证器它也只会指出一堆你已经知道的问题不会让系统突然变智能。把 Agent 架构本身做好仍然是所有训练改进的前提。8. 常见问题与排查建议问题现象可能原因排查方式解决方案验证器判断结果与人工复盘不一致验证器缺少关键上下文或提示词不够聚焦检查输入到验证器的上下文是否覆盖了多智能体之间传递的信息补充智能体之间传递的中间数据让验证器能看到完整依赖链模型训练后变得更保守探索变少验证器对失败步骤惩罚过重模型不敢冒险检查验证器分数分布观察是否存在系统性负偏调整验证器分数与全局奖励的融合权重对探索性步骤降低惩罚过程指标提升了但最终任务成功率没有提升模型学会了迎合验证器偏好对比验证器高分段和低分段轨迹的最终真实成功率引入对抗性验证集定期评测验证器与真实结果的关联度逐步骤验证成本过高每条轨迹步骤太长验证器调用频率过高查看验证器分析日志找到高成本长轨迹先做步骤聚合或风险步骤粗筛再对可疑步骤做细粒度验证多智能体之间的上下文传递错误被误判为单步错误验证器只看到当前步骤不知道问题源于上游让验证器同时接收步骤级上下文和来源标识对验证结果增加“根因是否在上游”的分类维度这套排查思路的本质是一致的先把验证器的输出当作可疑信号再拿最终结果去校验。不要因为验证器返回了“某一步有问题”就直接相信而是要把它当成一条值得调查的线索。9. 哪些团队适合跟进从哪里开始如果团队主要做大模型应用的提示词编排短期内不一定需要马上上 CREST 这类训练方法。更务实的做法是先照第 6 节的方式搭建一个验证器复盘层把线上失败轨迹的结构化归因沉淀下来。这能立刻帮团队定位多智能体交互问题也能为未来微调积累数据。如果团队已经在做 Agent 的强化学习训练可以重点关注两点一是验证器的设计是否足够独立二是信用分配规则里验证器分数与全局奖励如何融合。CREST 论文的价值在于提供了一个更系统化的框架而不只是某个特定实现。你可以先复现它的核心逻辑再用自己的业务场景做小规模对照实验。如果是个体开发者可以从一个很小的实验开始拿一个现成的多智能体框架把每一次运行记录下来用 LLM 验证器逐步骤打分。坚持一段时间你会获得一份非常难得的“多智能体行为归因数据集”。这个数据集本身就是独立于任何论文价值的积累。后续值得继续深入的方向还包括过程监督与结果监督各自的适用场景、reward hacking 在 Agent 训练中的表现形式、多智能体强化学习里的合作型信用分配机制。理解了这些概念再看 CREST 类方法时你会更容易判断哪些改动是真正重要的哪些只是锦上添花。多智能体系统的开发已经过了“能跑就行”的阶段。当系统开始承担真实业务时稳定性和可追溯性才是最重要的。把一个失败结果归因到具体步骤这件事正在从人工复盘走向自动化验证。CREST 提示了一个关键趋势未来 Agent 训练系统里最值钱的可能不是生成模型本身而是那个知道每一步值多少分的验证器。