Skip to content

Agent 工作原理中的 Message、Part 与 Span ​

本文通过一次天气查询,解释 Agent 如何组织模型调用、工具执行与消息历史,帮助读者理解 LLM Trace 中的内容层级和 Span 边界。

0x01 Agent 的执行循环 ​

Message(消息)是一条带角色的消息,Part(片段)是消息内部的内容单元。一条模型消息可以同时包含文本和工具调用请求;这些片段属于同一条消息,但承担不同用途。

Agent 通常运行在一个循环里:

text
用户提出问题
   ↓
Agent 将指令、历史消息和可用工具发给模型
   ↓
模型返回消息
   ├─ 给出答案 → 结束
   └─ 请求调用工具
          ↓
      Agent 执行工具
          ↓
      把工具结果加入消息历史
          └────────→ 再次调用模型

模型生成工具调用请求后,Agent 程序负责执行工具,再将结果加入消息历史,发起下一次模型调用。每次模型请求和每次工具执行分别记录为独立 Span。

0x02 一次天气查询的完整调用 ​

用户提问:“深圳明天天气怎么样,需要带伞吗?”假设 Agent 查询一次天气后给出回答,这段执行包含三个子 Span:

text
Agent Span
├─ 模型调用 Span A:生成工具调用请求
├─ 工具调用 Span B:执行天气查询
└─ 模型调用 Span C:读取工具结果,生成最终回答

示例按执行顺序展开,省略可用工具定义等请求参数。

a. 模型调用 Span A:决定查询天气 ​

第一次模型调用的输入包含系统指令和用户消息:

text
消息 [0] · 系统指令
  片段 [0] · 文本:“你是天气助手。”

消息 [1] · 用户消息
  片段 [0] · 文本:“深圳明天天气怎么样,需要带伞吗?”

Span A 返回的一条模型消息包含两个片段:

text
输出消息 [0]
  片段 [0] · 文本:“我先查询一下天气。”
  片段 [1] · 工具调用:
              name = get_weather
              arguments = {"city": "深圳", "date": "明天"}

此时模型只生成了 get_weather 的调用请求,还没有获得天气结果。文本片段和工具调用片段都属于 Span A 的输出。

b. 工具调用 Span B:执行天气查询 ​

Agent 程序识别到 tool_call 片段后,调用天气工具。实际执行过程记录在独立的工具 Span B 中:

text
工具:get_weather
输入:{"city": "深圳", "date": "明天"}
输出:{"weather": "雨", "rain_probability": 0.9}

Agent 将 Span B 的输出包装成工具消息,与 Span A 的模型输出一起加入消息历史。

c. 模型调用 Span C:读取结果并回答 ​

第二次模型调用使用新的 Span C。它的输入携带前面的消息历史,包括模型发出的工具调用请求和刚获得的工具结果:

text
消息 [0] · 系统指令
  片段 [0] · 文本:“你是天气助手。”

消息 [1] · 用户消息
  片段 [0] · 文本:“深圳明天天气怎么样,需要带伞吗?”

消息 [2] · 模型消息
  片段 [0] · 文本:“我先查询一下天气。”
  片段 [1] · 工具调用:
              name = get_weather
              arguments = {"city": "深圳", "date": "明天"}

消息 [3] · 工具消息
  片段 [0] · 工具返回:{"weather": "雨", "rain_probability": 0.9}

模型读到查询结果后,在 Span C 的输出中生成“预计有雨,建议带伞”的最终回答。

工具结果同时出现在 Span B 的输出和 Span C 的输入,分别记录工具返回与模型接收这两个环节。工具只执行了一次,输入历史里的工具消息本身不会额外创建一个 Span。

消息 [3] 表示它在 Span C 输入消息列表中的位置,编号从 0 开始。它是该列表的第四条消息,不是 Trace 中的第四个 Span,也不代表 Agent 的第四轮执行。

0x03 在 Trace 详情中理解内容层级 ​

概念在执行过程中的含义
Agent Span一段 Agent 执行过程,可能包含多次模型和工具调用
模型调用 Span一次模型请求及响应;输入可能携带很多历史消息
Message/消息一条带角色的消息,例如用户、模型或工具消息
Part/片段消息内部的一个内容单元,例如文本、图片、工具调用或工具返回
工具调用 SpanAgent 实际执行一次工具的过程

按用户消息、推理过程、规划的工具调用等分类打平,是在单个 Span 的输入或输出内对 Part 重新分组。类内保留原有消息和片段的先后顺序,并用“消息编号+片段编号”标明来源位置。

模型 Span 输出中的“规划的工具调用”表示模型发出了调用请求;工具 Span 记录该请求的实际执行。保留两者的关联,可以从模型决策定位到工具执行,同时保持各个 Span 的独立边界。