把 Agent 工具调用收成一条 Codex 轨迹
一轮 Agent 对话可能连续调用多个工具。旧页面把每次调用都显示成一张大卡片,8 次调用就能占满一屏,最终业务结果反而被推到下面。
这次选择的是 A:Codex 轨迹。下面把用户问题、工具过程和助手结果放进同一次对话;演示默认展开,便于看清三者关系,真实产品仍在任务结束后收成一句“已调用 8 个工具”。
帮我查一下物料 A 最近的库存变化,并总结最近一次入库情况。
✓ 8 个工具 1 个未完成 ⌄
已核对物料库存、库存变化和最近入库记录。
已完成库存、库存变化和最近入库记录的查询。其中一项历史业务记录未读取成功,但不影响本次库存结论。
为什么不用一堆工具卡片
工具过程是辅助信息,不是页面主角。用户首先要看业务结果,只有在等待、核对或排错时才需要过程。
因此这版只保留三条原则:
- 结果优先:执行结束自动收起,不挤压最终回答。
- 过程可解释:只显示业务名称和完成状态,不展示隐藏推理、调用参数、原始返回值或内部英文工具名。
- 异常不隐藏:收起态保留未完成数量,展开后能定位具体步骤。
这不是 Prompt 补丁
轨迹来自结构化事件,不靠模型临时组织文案。当前链路是:
1 | |
Pi 在真正执行工具前发出 tool_execution_start,完成后用同一个 toolCallId 发出 tool_execution_end。Java Gateway 不改写过程语义,只处理可信上下文和流式转发。页面拿到事件后,才负责状态合并、文案投影和视觉分组。
这样做的关键是职责没有压进 Prompt:工具提供安全的 details.presentation,运行时提供事实事件,页面负责展示。即使模型换了表达方式,工具轨迹仍然稳定。
状态与边界
轨迹只需要三种状态:进行中、完成、未完成。开始事件先建立进行中步骤;结束事件关闭同一条步骤;会话稳定后,整组轨迹默认收起。
系统通知、网络错误和模型错误不会伪装成工具,也不会进入“已调用 X 个工具”的计数。历史消息同样只读取持久化的安全展示字段,避免刷新页面后泄露原始参数。
当前实现按一轮对话中连续出现的真实工具消息分组,它不是工作流 DAG,也不试图展示模型思维链。这个边界刻意保持简单:足够解释“系统做了什么”,但不把调试日志直接交给普通用户。
验证结果
- Java 侧 9 个聚焦测试通过。
- 页面事件投影测试通过。
- 页面生产构建通过。
最终变化很直接:8 张纵向卡片变成一行摘要;需要时仍能展开查看完整过程,最终业务回答重新成为页面主视觉。