把 Agent 工具调用收成一条 Codex 轨迹

一轮 Agent 对话可能连续调用多个工具。旧页面把每次调用都显示成一张大卡片,8 次调用就能占满一屏,最终业务结果反而被推到下面。

这次选择的是 A:Codex 轨迹。下面把用户问题、工具过程和助手结果放进同一次对话;演示默认展开,便于看清三者关系,真实产品仍在任务结束后收成一句“已调用 8 个工具”。

用户

帮我查一下物料 A 最近的库存变化,并总结最近一次入库情况。

助手 · 处理过程
8 个工具 1 个未完成

已核对物料库存、库存变化和最近入库记录。

查询物料库存完成
查询库存变化完成
核对仓库信息完成
读取一项业务记录未完成
查询采购入库完成
查询调拨记录完成
汇总最近入库记录完成
生成结果摘要完成
助手

已完成库存、库存变化和最近入库记录的查询。其中一项历史业务记录未读取成功,但不影响本次库存结论。

为什么不用一堆工具卡片

工具过程是辅助信息,不是页面主角。用户首先要看业务结果,只有在等待、核对或排错时才需要过程。

因此这版只保留三条原则:

  • 结果优先:执行结束自动收起,不挤压最终回答。
  • 过程可解释:只显示业务名称和完成状态,不展示隐藏推理、调用参数、原始返回值或内部英文工具名。
  • 异常不隐藏:收起态保留未完成数量,展开后能定位具体步骤。

这不是 Prompt 补丁

轨迹来自结构化事件,不靠模型临时组织文案。当前链路是:

1
2
3
4
5
6
7
8
9
10
11
12
Pi Agent Runtime
└─ tool_execution_start / tool_execution_end
↓ SSE
Java Gateway
└─ 注入可信业务上下文并透传事件

页面事件投影
├─ 按 toolCallId 合并开始与结果
├─ 读取安全的 presentation 文案
└─ 把连续工具消息组成一条轨迹

运行时展开,agent_settled 后收起

Pi 在真正执行工具前发出 tool_execution_start,完成后用同一个 toolCallId 发出 tool_execution_end。Java Gateway 不改写过程语义,只处理可信上下文和流式转发。页面拿到事件后,才负责状态合并、文案投影和视觉分组。

这样做的关键是职责没有压进 Prompt:工具提供安全的 details.presentation,运行时提供事实事件,页面负责展示。即使模型换了表达方式,工具轨迹仍然稳定。

状态与边界

轨迹只需要三种状态:进行中、完成、未完成。开始事件先建立进行中步骤;结束事件关闭同一条步骤;会话稳定后,整组轨迹默认收起。

系统通知、网络错误和模型错误不会伪装成工具,也不会进入“已调用 X 个工具”的计数。历史消息同样只读取持久化的安全展示字段,避免刷新页面后泄露原始参数。

当前实现按一轮对话中连续出现的真实工具消息分组,它不是工作流 DAG,也不试图展示模型思维链。这个边界刻意保持简单:足够解释“系统做了什么”,但不把调试日志直接交给普通用户。

验证结果

  • Java 侧 9 个聚焦测试通过。
  • 页面事件投影测试通过。
  • 页面生产构建通过。

最终变化很直接:8 张纵向卡片变成一行摘要;需要时仍能展开查看完整过程,最终业务回答重新成为页面主视觉。


把 Agent 工具调用收成一条 Codex 轨迹
https://willfordzhan.github.io/2026/08/20/agent-tool-trace-codex-timeline/
作者
詹文杰
发布于
2026年8月20日
许可协议