← 全部研究

Agent Debugger:通过 Agentic 工作流理解 Agent 轨迹

Lizhi Lin,与朝闻道团队共同完成

为什么要做 Agent Debugger?

Head Picture

Agent 越来越流行,而每个场景都希望构建 Agent:针对自己的业务设计工具和 system prompt 来构建 Agent,乃至使用 Agent 轨迹数据训练模型,使其掌握 Agent 能力。现在有了各种框架,构建和运行 Agent 非常容易,但迭代 Agent 反而变得困难:

  1. 我构建的 Agent 在哪里遇到了问题,应该如何改进?
  2. 如何找出 Agent 轨迹数据的问题并过滤,从而得到高质量的数据集?

可以看到,迭代 Agent 的重要方式就是理解 Agent 的轨迹:Agent 解决一个问题时调用了哪些工具,进行了哪些思考。但是 Agent 往往需要多轮调用工具才能解决问题,轨迹很长,单纯靠人力无法穷尽所有线上轨迹。我们需要借助语言模型强大的语言能力来帮我们找出轨迹中的问题,借用编程的术语来说,就是需要 Agent 的 Debugger。 Agent Debugger 应该做什么呢?从上述两个问题,我们会发现有两类需求:

  1. 问题回答(Question Answering):针对一条轨迹,回答开发者的一系列问题,比如写 SQL 的 Agent 做错了,我们会问“为什么 Agent 失败了”;在深度研究的场景中,看到某条消息,我们会想“这个事实是哪里找到的?” 这需要分析轨迹,前后跳转来找到轨迹中的相关片段并呈现给用户。呈现给用户的可能是一段对话,也可能是一个结构化的 JSON 方便后续处理。
  2. 质量检测(Quality Check):针对一条轨迹,判断是否存在某些类别的问题。比如要用 Agent 轨迹训练模型前可以扫描一遍,找出存在问题的轨迹并删掉,有些类别的问题必须删掉,有些类别的问题则可以保留;或者每天定时扫描线上 Agent 得到的轨迹去检视一些问题,发现出现工具问题就去修正一下。质量检测呈现给用户的就是一个问题列表,里面会标注问题的类别,问题所在回合的索引,以及问题内容。

这两类问题可以互相转换,比如针对轨迹批量问一个问题也可以是质量检测,但往往质量检测会有一个问题分类(Taxonomy),需要检查多个类别的问题,并且要保证足够的召回率和精确度,单纯依靠一次 QA 就有些力不从心了。

Agent Debugger 设计

问答式智能体调试器

如何设计 Agent Debugger 呢?最直接的想法就是把整条轨迹喂给模型。我们统计了评测中使用的轨迹的 token 数量,很多轨迹其实没有超过现在很多模型的上下文窗口限制。直接把轨迹喂给 LLM 是可行的。但是实际测试下来效果并不好:做 QA 时会在一些地方误判,做质量检测时会漏掉很多问题。 这可能要归结于 context rot 的问题,也就是 LLM 的能力随着上下文逐渐变长而下降的现象。然而轨迹里的问题可能出现在任意位置,而且不止一个。因此我们选择让 Agent Debugger 成为一个 Agent:将 Agent 轨迹变成一个“环境”,Agent 可以使用工具去探索环境,比如使用 grep 快速定位关键词出现的位置。

基于文件系统的环境

如何把轨迹呈现给 Agent?我们选择了依托文件系统的办法,因为所有现代模型都经过基于代码库环境的 RL 训练,非常擅长使用文件系统的工具,使用文件系统的方式描述轨迹能够复用 Agent 的能力。 考虑最简单的情况,一个 Agent 轨迹就是一个 messages 数组,里面按顺序排列了一系列 message。我们为一条轨迹建立一个目录,把每个 message 变成一个 JSON 文件并标号:

trace_XYZ/
    message_all.json
    message_01.json
    message_02.json
    message_03.json

基于这个环境,QA Agent 需要如下基础工具来查看轨迹:

  • trace_ls 查看当前目录内容,类似于 ls
  • trace_read 阅读某条 message,类似于 cat
  • trace_read_batch 一次性阅读多条 message,适合批量理解轨迹内容
  • grep 查找出现某关键词的消息(我们稍作封装以返回位置)

qa-debugger-trace

trace_ls 和 grep 都类似于 bash 命令,方便模型理解工具并使用。

此外我们还使用基于 LLM 的工具,这类似于最近提出的 Recursive Language Model 的思想(见 论文):

  • chunk_trace:将轨迹分块总结。我们将轨迹划分为若干批次,用 LLM 遍历并维护分块摘要,使主模型可以快速了解轨迹的主要内容。
  • filter_trace:按某一标准使用 LLM 过滤轨迹,输出符合标准的轨迹。

轨迹格式

一些框架的轨迹会比较复杂。比如 Claude Agent SDK 和 NexAU 这种现代比如 NexAU 会有 Sub Agent:某一次工具调用可以启动一个 Sub Agent 去完成子任务,这导致轨迹是树形结构。对于 Sub Agent,我们按照相同的办法将每个 Sub Agent 放到单独的文件夹里,并在原始调用 Sub Agent 的 tool call 中添加指代。

trace_XYZ/
    message_all.json
    message_01.json
    message_02.json  # 提供指向 Sub Agent 的指针
    message_03.json
    sub_agent_01/
        message_01.json
        message_02.json
        ...

对于更复杂的轨迹和未来潜在更多的框架,应该怎么处理呢?这些框架原生支持 OpenTelemetry 格式,这种格式中一次函数调用就是一次 span,span 可以嵌套 span。一种方式就是基于这些 span,这种方式能表达任何格式的 Agent 轨迹,当然可能对 Agent 不太友好。 我们对 span 做了一系列简化来降低上下文占用:

  1. 提取每个 span 的 child_spans,展平,按时间戳排序,并记录一个 span_tree 表示 span 的嵌套关系
  2. 清除冗余 span,方法是删除 span_attributes 里面没有任何属性的 span,这些 span 只记录了调用
  3. 清除 span 的冗余属性
    1. 对于 LLM 调用,清除冗余的 input.value/output.value、pat.*、mime_type 等属性;input.value 和 output.value 会被另外解析为 llm.input_messages.* 等字段,value 里面是原始输入的 JSON
    2. tool_schema 去重,替换为 <refer to <idx>:<tool_name>>
    3. 标记 LLM chain,也就是单纯逐轮追加 message 的一系列平级 span,这些 span 里面记录的冗余 messages 字段可以删掉

span-format

质检 Agent Debugger 设计

qc-debugger

质检 Agent Debugger 的设计和 QA 有所不同,并没有使用 Agent。质检需要保证每个类别的召回率(recall)。此外我们发现很多错误其实是局部的,比如工具错误,因此可以直接并行处理轨迹的所有消息。 质检 Agent Debugger 包含 Proposer 查找问题和后处理两个部分。Proposer 负责给定轨迹的一部分,按照给定标准去查找问题。Proposer 有不同类型,可能是一个单纯借助 LLM 去产出 issue 的工作流,也可能是调用 QA Debugger 以 agentic 的方式处理轨迹。所有 Proposer 彼此没有依赖、独立运行,产出的 Issue 汇总后进行后处理;后处理包含去重和过滤,比如去除不同 Proposer 发现的类似问题,以及过滤不符合标准的问题,最终得到结果。 这是一套非常灵活的系统:用户可以自定义问题分类并编写 prompt,针对不同问题类型使用不同类型的 Proposer;对于工作流 Proposer,使用不同的 batch size。在我们的实践中,工具错误往往适合更小的 batch,而指令遵循等更“语义化”的问题则可以用更大的 batch。

针对内部的 Agent 轨迹,我们提出了以下分类:

  • 工具错误:工具本身出现了问题,或设计上有问题。比如搜索工具无法正确返回结果,或者工具返回了过长的上下文。
  • 不遵循指令:模型没有遵循指令,比如突然中断手上的事情去做其他事。
  • 提前截断:在某一回合没有输出完整的工具调用或回复。
  • 编造事实:包括不根据查找的资料确定细节,也包括使用代码生成模拟数据而不从 API 获取真实数据的行为。
  • 行为循环:反复做某个事情,比如反复尝试某个命令而没有进展,或者是单纯的循环。

在迭代这套配置的过程中,我们发现有一些问题无法通过调整 prompt 来解决,因此添加了一些过滤器来剔除如下特点的问题:

  • 虚假日期:模型会认为 2025/2026 年是虚假年份,这个认识无法通过简单在 prompt 里添加日期来纠正。这可能是一个比较广泛的问题,很多模型似乎永远留在了 2024 年
  • 单元测试失败:有时候模型会认为单元测试失败是工具错误,但单元测试失败是调试的正常环节
  • 搜索结果无关:模型会认为搜索结果无关是工具错误,而没有理解搜索引擎返回的结果无关是很正常的

质检 Agent Debugger 的使用

一个质检 Agent Debugger 对应一个配置文件,主体结构为:

{
    "proposers": [{ ... }],
    "filters": [{ ... }], # 可选
    "issue_mergers": [{ ... }], # 可选
}

其中 proposer 的结构为:

{
    "name": "tool_error_full",
    "issue_category": "工具错误",
    "prompt": "path/to/your/prompt",
    "chunk_size": 2,
    "chunk_format": "xml",
    "context": {
        "iterate_by": "message",
        "lm_response": true,
        "tool_call": true,
        "user_input": true,
        "system_prompt": false
    }
}

字段说明:

  • issue_category 用于校验某一 proposer 能输出的 issue 类别,可以是单一类别也可以是多个类别
  • chunk_size 控制了 chunk 的大小,chunk_format 调整 chunk 的格式,可以是 xml 也可以是 markdown
  • context 字段控制每一 chunk 的内容,可用来调整来得到最合适的输出,比如对于工具相关错误,只需要展示 tool call 即可

Proposer 会输出 Issue 列表,一个 Issue 包含 issue_type, summary, message_index 和 evidence 四个字段,描述其类型,issue 总结,轨迹中相应回合的索引和证据。

Filter 用来过滤不符合要求的 Issue,主要有 name 和 prompt 字段,其中 prompt 就是用来传给 LLM 的 prompt,需要让 LLM 输出 JSON 结构,里面包含 keep 字段,keep: true 表示保留该 issue。

相关工作

关于 Agent 轨迹诊断的评估,TRAIL 测试模型阅读超长、结构化的 Agent 轨迹,做错误定位 + 错误类型识别的能力,包含了 148 条人工标注的轨迹、841 个错误;trace 平均输入 token 极长(论文/博客里提到平均 >200k、最长到百万级 token)。AgenTracer 主要关注多 Agent 系统的错误归因。AgentRewardBench 数据集由人类专家对 Web Agent 轨迹回答“是否成功/副作用/重复性”等问题,用来检验自动评估器是否靠谱。AgentErrorBench 包含了 200 条专家标注失败轨迹,覆盖 GAIA / ALFWorld / WebShop 等测试集。 至于 Agent 轨迹诊断的系统,AgentDiagnose 是一个开源诊断框架,提供多种轨迹能力指标(如任务分解、self-verification 等)和可视化;LangSmith 的 agent-evals 通过 LLM Judge 去评估轨迹;Google ADK 的 evaluation criteria 提供了可复用的评估标准;此外还有 Lunette 这类平台提供轨迹审计/诊断服务。

实验

我们测试了质检和 QA 两个方向。

使用 TRAIL 测评质检 Agent

我们在 TRAIL 上测试了质检 Debugger 的表现。TRAIL benchmark 原始的测试方式是将整条轨迹放到 prompt 里,而我们使用质检 Agent Debugger 针对不同类型的问题做了专门调优。由于 TRAIL 的 Taxonomy 的标签非常多,如果为每个标签都添加 proposer 会导致延迟过高,因此我们选择合并性质相似且数量较少的标签。

结果显示,在该评测中 gemini-2.5-pro 的表现显著优于 gemini-3-pro。这可能有两个原因:一是我们的 prompt 调优主要基于 gemini-2.5-pro 的行为;二是 gemini-3-pro 可能存在长上下文性能问题,仍需进一步调查。

HarnessModelGAIA Weighted F1GAIA Loc. accGAIA Joint accSWE Bench Weighted F1SWE Bench Loc. accSWE Bench Joint acc
TRAIL baselinegemini-2.5-pro38.954.618.314235
TRAIL baselinegemini-3-pro29351125.103.210.00
QC Debuggergemini-2.5-pro45.3580.2842.5965.9287.8327.17
QC Debuggergemini-3-pro57.4948.3618.7912.813.231.97

使用 QA Debugger 诊断 Skill 轨迹

这方面的 benchmark 比较少,因此我们主要以定性研究为主。随着 Anthropic 提出了 Skill 这一模块化的能力提供方式,我们也开始展开对 Skill 数据的训练,但如何筛选这些数据成了一个问题。我们从 Nex 模型训练中用于训练模型使用 Skill 的相关数据里抽取了 500 条轨迹,并向 QA Agent Debugger 询问模型是否使用了 Skill,发现有 68 条并没有真正使用 Skill。这些数据本身是经过筛选的,但据了解筛选比较简单:只是将整条轨迹放到 prompt 里来询问模型。由此可见 agentic workflow 的重要性。

我们进一步分析这些未使用 Skill 的轨迹,发现大致可以分为三类:

  • Skill 不可用:Skill 调用失败,缺少环境支持等。模型可能不会重试,而是直接用通用方案解决问题。
  • 加载但没有深入参考 Skill:只是加载了 Skill,但没有真正使用 Skill 里的特定代码,而是写了一般性代码。
  • 多次 Skill 切换中忽略先前 Skill:Skill 加载成功,但后续切换到另一个 Skill/路线,前一个 Skill 被搁置。

结论

随着 Agent 系统交互轮数增长、复杂度增加,人们需要更好的工具来理解 Agent 的行为。Agent Debugger 提供了问答和质检两种模式:既能回答关于轨迹的特定问题,也能批量扫描轨迹、进行回归性测试。在技术选型上,问答采取了 agentic workflow 的方式,将轨迹转化为一个基于文件系统的环境,让模型充分利用在代码库上训练出的探索能力,克服上下文限制来回答复杂问题;质检则采用批量扫描轨迹信息的方法,解耦不同问题类别来保证召回率和精度。

参考

← 返回全部研究