跳转到主要内容

为分解过程埋点:为什么 Agent 轨迹成本是一项规划器指标

运行成本通常以 token 总量来报告,但主导变量是规划器如何分解任务。按计划节点记账,能把预算变成调度输入。

一块电路板的微距照片,显示浅景深下的走线、焊点和元件。

成本并非来自模型

token 总量是结果,不是原因。当同一任务的两个 agent 运行在工具调用次数上相差一个数量级时,差异很少来自模型。它来自分解:规划器创建了多少子任务、每个子任务的范围有多窄、以及每个节点被要求重新读取多少上下文。一个把检索任务拆成五个重叠子任务的计划,会为同一份文档付五次钱。一个把它拆成一个范围明确的节点的计划,只付一次。

失败模式会聚集。重试集中在那些从未说明成功条件的子任务上。上下文重读集中在那些被给予过宽工具面、不得不重新推导已知内容的节点上。当规划器无法判断某个子任务是否完成时,就会出现冗余的验证步骤,于是它添加一个重复工作的检查器节点。这些在单次运行总量中都不可见。总量把成本归因于模型,因为账单行写的是模型。真正花钱的是计划。

计划节点记账

机制很直接:给每个计划节点一个稳定标识符,并把每次模型调用和工具调用分配给发起它的节点。节点标识符不是 span 名称。它是规划器自己的工作单元,作为每个出站请求上的字段贯穿整个运行。

plan_node_id: "retrieve_policy_clauses"
parent_node:  "assemble_compliance_answer"
model_calls:  [...]
tool_calls:   [...]
status:       "retried"

跨运行聚合后,每个节点都会获得一个分布:成本、延迟、重试率、失败率。分布才是重点。每个节点的平均成本告诉你一个节点通常花费多少。长右尾告诉你哪个节点偶尔会爆炸。这是不同的工程问题。前者是预算问题。后者是分解缺陷。

大多数 agent 可观测性就停在这里。trace 被收集,span 被渲染,成本视图是按运行汇总的总量,并按模型拆分。这种拆分回答了一个没人问的问题:哪个模型花了 token。真正重要的问题是计划的哪一部分产生了这些工作。节点级视图能回答它,而且能跨运行回答,这是区分坏计划和坏日子的唯一方法。

分布揭示了什么

Aerial view of countryside with cultivated fields and a calm lake

有三种模式反复出现。

一个平均成本低、尾部很重的节点,通常是成功条件定义不足的节点。它大多数时候成功,偶尔会循环。修复方法不是换更便宜的模型。修复方法是给节点更严格的契约:它必须返回什么,以及什么算完成。

一个平均成本高、方差低的节点在做真正的工作。它是收窄工具面或换更便宜模型的候选,因为它的行为足够可预测,可以在不危及运行的情况下优化。

一个重试率高、成本平稳的节点,是一个总是以同样方式失败、并被没有更好选择的规划器重试的节点。在这里增加预算只会让失败更昂贵。重写该节点才能消除它。

这些区分都无法在聚合到运行总量后保留下来。它们需要以节点作为记账单位。

让它成为调度输入

一旦成本被归因到节点,约束就可以附着到节点而不是运行上。按运行设上限是一种钝器:触发时,整条轨迹都会死掉,包括那些表现正常的节点。按节点设上限,可以让失控的子任务被停止、标记为失败并报告回规划器,然后规划器可以围绕它重新规划。运行的其余部分继续。

这改变了规划器的工作。收到节点级成本反馈的规划器,可以基于预期成本而不只是预期正确性来选择分解。高方差的节点会得到更窄的工具面,因为更小的工具面会减少节点可能出错的空间。总是重试的节点会在获得更多预算之前被重写,因为预算不是约束。便宜且可靠的节点可以获得更大自由度,因为它们的成本有界,行为已知。

预算约束成为调度输入。不再是月底Close-up of bridge cables stretching toward a bright blue sky with fluffy clouds

权衡是真实存在的。节点级记账要求规划器发出稳定的节点标识符,这意味着规划器的分解必须可观测且可复现。每次运行都生成自由形式分解的规划器,会产生无法聚合的标识符。这种埋点迫使做出选择:要么分解足够稳定、可以度量,要么不稳定,成本仍然无法归因。想要第二种规划器——完全自由形式、最大程度自适应——的团队,要为此放弃控制回路。这是一个合理的选择。但它不是免费的。

这取代了什么

事后成本仪表盘是一种报告产物。它们告诉你上个月在总体上发生了什么,而且是在钱花完之后。它们对财务有用,对工程无用,因为当数字可见时,运行已经结束,导致它的计划也已经消失。

计划节点记账是一个控制回路。它在规划器实际控制的单元上度量,跨运行聚合,使方差可见,并反馈到下一次分解。区别不在于图表的粒度。而在于度量能否改变下一次运行。

实际形态

最小实现包含四个部分。

  • 规划器在分解时发出节点标识符,运行时在每次模型和工具调用上携带它们。
  • 收集器跨运行按节点聚合成本、延迟、重试次数和失败状态。
  • 策略层读取每个节点的分布,并在节点边界应用上限、模型选择和工具面限制。
  • 规划器在选择下一次分解时消费策略层的先验。

困难的部分不是管道。而是接受分解是一种带有成本特征的工程产物,并且度量它是让预算成为设计决策而非会计事件的唯一方法。

封面照片:Jakub Pabis / Pexels。

分享XLinkedIn永久链接5 分钟阅读

相关阅读

这能回答的问题

Why is a per-run token total insufficient for agent cost control?

It aggregates over the whole trajectory, so it cannot distinguish a node that is cheap and reliable from a node that occasionally explodes. It attributes cost to the model rather than to the decomposition that generated the work, which is the variable engineering can actually change.

What is a plan node identifier and why does it matter?

It is a stable label the planner assigns to each unit of work in its decomposition, carried on every model and tool call the node issues. Without it, calls cannot be aggregated per node across runs, and the cost distribution that reveals pathological decompositions is unavailable.

How does plan-node accounting change budget enforcement?

Caps attach to the node rather than the run. A runaway subtask is stopped and reported to the planner, which can re-plan around it, instead of the whole trajectory failing when a run-level cap trips.

What is the main trade-off of node-level cost instrumentation?

It requires the planner's decomposition to be stable and reproducible enough that node identifiers aggregate across runs. Fully free-form planners that generate a new decomposition every time give up that control loop in exchange for adaptability.