Agent Activity Timeline:怎样把 Agent 事件流设计成用户看得懂的执行界面
Agentic Chat 里那条承载 reasoning、tool call、approval、artifact 和最终答案的界面,最准确的产品名称是 Agent Activity Timeline,工程上则是 Agent Execution Trace UI。本文从 HCI、可观测性和事件投影视角解释它为什么难设计,并给出事件分层、状态机、视觉语法与 Assistant UI 落地方法。
- 创建时间
- 更新时间
- 阅读时长
- 16 分钟

#先把名字叫对:它不是聊天记录,而是 Agent Activity Timeline
如果站在产品设计视角,我会把这类界面称为 Agent Activity Timeline:它按照时间与因果关系,向用户解释 Agent 当前在做什么、已经做了什么、哪里需要人介入。若站在工程与可观测性视角,更准确的叫法是 Agent Execution Trace UI 或 Agent Trace Viewer;若只描述渲染层,可以叫 Agent Event Stream Renderer。Chain of Thought UI 只是其中一个局部组件,不足以概括工具、审批、产物和恢复动作。
这几个词不是互相替代,而是三个层次:Event Stream 是输入,Execution Trace 是结构化运行记录,Activity Timeline 是面向任务用户的可读投影。Raw Event Inspector 面向开发者逐条看协议;Trace Viewer 面向工程师定位调用链;Activity Timeline 面向最终用户建立信任与控制。把三者画成同一个列表,通常就是界面难看的第一原因。
学术语境里,它属于 Human-Agent Interaction 与 Mixed-Initiative Interaction。后者强调人和 Agent 在合适时机分别贡献判断或执行能力;所以 UI 的职责不只是“展示模型说了什么”,还要让控制权可以在 Agent 与人之间平滑交接。
#为什么总设计不得要领:你在渲染日志,用户却在理解任务
最常见的实现是 event.type 到组件的一对一映射:reasoning.delta 变一段灰字,tool.started 变一张卡,tool.progress 再加一行,tool.completed 再加一个绿色勾。协议很完整,体验却像 CI 日志,因为后端事件的粒度服务于传输和恢复,不服务于人的阅读。
用户真正想回答的只有五个问题:目标是什么;现在处于哪一步;系统为何采取这个动作;我是否需要介入;结果与证据在哪里。任何事件如果不能改变这五个答案,就不应该默认占据主时间线。它可以进入折叠详情、调试 Inspector 或遥测系统。
因此设计对象不应是 Event,而应是 Projection。与 Event Sourcing 类似,同一条 append-only event log 可以生成多个 read model:对话正文、活动时间线、任务状态、审批队列、Artifact 工作区和 Raw Inspector。高级感首先来自信息职责分离,而不是阴影、渐变或卡片圆角。
#建立三层模型:事实事件、语义步骤、界面投影
第一层是事实事件,例如 run.started、reasoning.delta、tool.started、tool.progress、tool.completed、approval.requested、artifact.created、run.failed。它们需要稳定 ID、sequence、timestamp、parentId 和 visibility,保证流式合并、重放、审计与跨端一致。事件只陈述发生了什么,不携带“渲染成黄色卡片”这类视觉决定。
第二层是语义步骤。十几次 search、fetch 与 parse 可能共同构成“检索公开资料”;连续的 edit、typecheck 与 test 可以构成“实现并验证修改”。步骤聚合器根据 parentId、tool category、时间窗口和 Agent plan,把底层事件压缩为用户能理解的工作阶段。这里才产生 started、running、waiting、completed、failed、cancelled 等稳定状态。
第三层是界面投影。同一个 approval.requested 会让顶部状态变为“等待审批”、在时间线插入阻塞节点、在 Composer 附近出现操作卡,并在任务列表显示未处理标记。它们共享同一个 approvalId,而不是各自维护 loading。事件模型解决真实性,Projection 解决可理解性。
生产实现还需要 sequence 去重、乱序缓冲、terminal 状态保护和持久化 replay。关键点是用稳定 ID 原位更新 Projection,不把每个 transport event 追加成一条新消息。
#用可观测性的 Trace / Span 思维组织 Agent,而不是平铺所有事件
OpenTelemetry 把一次完整操作表示为 Trace,把其中的子操作表示为 Span;Span 具有父子关系、开始结束时间、属性和状态。Agent UI 可以借用这个心智模型:一个 user turn 是 root span,计划步骤是 child span,tool call 是更细的 span,progress 与日志是附属 event。这样搜索、代码执行和文件修改不再是同级噪声,而是可折叠的执行树。
但不要把生产可观测性后台直接搬给用户。面向最终用户的时间线应默认显示语义步骤、耗时、结论和异常;args、stdout、token、provider payload 留在展开层。开发者模式才显示 traceId、raw JSON 与精确时间戳。这叫 Progressive Disclosure:先交付判断,再允许审计。
线性任务用 Timeline,存在并行与分支时才升级为 DAG / Trace Graph。研究型 Agent 的近期工作也表明,结构化 trace visualization 能提高专家对工作流的理解和可检查性;但图结构的认知成本更高,不能因为后端是 graph 就默认画 graph。
#定义一套视觉语法:内容、活动、阻塞、产物各用自己的形态
正文答案属于 Content,应该像文档一样排版:Markdown 标题、段落、列表、表格与代码块完整渲染,阅读宽度稳定,不套大面积卡片。Reasoning 属于可选解释层,默认折叠并给简短摘要;不要把内部 token 流伪装成用户必须阅读的文章。
Tool 与 Step 属于 Activity,适合紧凑行或纵向时间线:图标表达类别,动词短语表达目的,右侧固定展示状态和耗时。运行中使用单一有限动画,完成后停止。连续低风险调用自动合并;失败、超时和重试才提升视觉权重。不要让每个 tool 都长成一张带标题、边框、背景和大段 JSON 的卡。
Approval 属于 Blocking Decision,必须打断但不能含糊:显示动作、目标、影响范围、权限持续时间和撤销方式。Artifact 属于 Work Product,应进入独立预览或工作区,而不是挤在消息气泡。Raw Events 属于 Debug Surface,默认离开主叙事。四种信息使用四种形态,页面自然会安静下来。
#状态机先于组件:每个节点必须有明确的进入与退出
一个活动节点至少需要 queued、running、waiting-for-user、completed、failed、cancelled 六种状态。queued 不应持续闪烁;running 显示当前动作和可停止入口;waiting-for-user 把 owner 明确切换为用户;completed 提供结果摘要;failed 保留输入与恢复点;cancelled 区分用户停止和系统中断。
流式更新必须原位修改同一个节点,不能 tool.started 新增一行、tool.progress 再新增一行、tool.completed 又新增一行。稳定 toolCallId 决定 identity,sequence 解决乱序,terminal event 决定状态收口。若停止后 UI 还在转,多半不是按钮样式问题,而是 cancel 没有进入同一状态机。
状态文案应该采用“动词 + 对象”:正在检索 12 个来源、等待批准修改 3 个文件、已运行 8 项测试。避免 Thinking、Working、Processing 这类不能帮助判断的抽象词。超过预期时长后显示阶段与替代动作,而不是无限 spinner。
#Assistant UI 的正确用法:消费 Message Parts,不是把所有内容拼成 text
Assistant UI 是 headless runtime 与 primitives,不是一套安装后自动变美的聊天皮肤。默认 Text renderer 只保证基础输出;Markdown 需要 @assistant-ui/react-markdown。Reasoning、tool-call、data、file 和 source 都应保留为独立 message part,再由 MessagePrimitive.Parts 或 GroupedParts 选择 renderer。
工具事件要在 Adapter 层合并为同一个 tool-call part:started 建立 toolCallId 与 args,progress 更新局部 result 或状态,completed 写入 terminal result,approval 则挂到对应 part。然后 UI 用 ToolFallback 或业务 Tool UI 渲染。若先把所有事件拼成一段 reasoning string,后续就无法获得原位更新、审批恢复、工具分组与语义样式。
官方当前推荐用 MessagePrimitive.GroupedParts 把相邻 reasoning 与 tool-call 聚合成可折叠的 thinking section。这个区域应是执行摘要,不是 Raw Event Inspector;最终 answer 仍然作为独立 Markdown Text part 出现在其后。
#一套可以直接照抄的设计流程
第一步,不画 UI,先列出 Provider 的事件全集,并为每类事件标记 audience、risk、frequency、duration、terminal 和 recoverability。第二步,把事件聚合为 5—8 个用户语义步骤。第三步,为每个步骤写状态机和唯一 ID。第四步,再决定它投影到主线、时间线、审批区、Artifact 还是 Inspector。
第五步,用真实长任务压测:至少包含 20 次工具调用、一次审批、一次失败重试、一个产物和一次用户停止。第六步做“删除测试”:删除一个 UI 元素后,用户是否仍能判断当前状态、下一步和恢复路径;若可以,它很可能只是装饰。第七步做“折叠测试”:默认折叠 80% 底层事件,任务是否仍然讲得通;若不行,说明摘要层没有设计好。
最终验收不看卡片是否漂亮,而看五个指标:用户 3 秒内能否说出当前阶段;是否能区分系统运行与等待自己;高风险动作是否在执行前可控;失败后是否能从安全点恢复;最终结论能否追溯到步骤与证据。达到这五条,视觉细节才值得继续打磨。
#我的判断框架:什么时候用 Chat、Timeline、Trace Graph 与 Artifact
只有问答与短生成时,用 Chat;任务超过一个工具或持续数秒时,加 Activity Timeline;需要工程排障与审计时,加 Trace Viewer / Raw Inspector;出现并行依赖和多 Agent 协作时,才考虑 Trace Graph;产生代码、文档、图片、网页或视频时,把 Artifact 提升为一级工作表面。
值得上:稳定事件协议、Step 聚合、状态机、Markdown、Tool UI、Approval 和恢复动作。可以再等:为所有任务绘制 DAG、把每个 reasoning token 可视化、追求复杂动效。重点关注:visibility 与权限——内部 reasoning、敏感参数和系统日志不应因为“事件流可见”就默认暴露。
参考脉络包括 Microsoft 的 Mixed-Initiative Interaction 与 Human-AI Interaction Guidelines、OpenTelemetry Trace API、assistant-ui 的 Message / Chain of Thought / Tool UI 文档,以及面向 Agent execution trace visualization 的研究。它们共同指向同一结论:Agent UI 的核心不是让执行过程看起来热闹,而是把不确定的自主行为变成可观察、可干预、可恢复的协作过程。
把判断变成项目里的检查节点
先用本文的第一个判断定义目标,再用第二个判断检查过程,最后把第三个判断写成验收条件。这样文章不会停在审美结论,而会进入需求、设计评审和上线复盘。
- 01把它叫作 Agent Activity Timeline
- 02先做 Event → Step → Projection
- 03用状态机、分层与恢复能力验收