构建更佳的 Agent UX:使用 LangChain 实现流式进度、状态和文件操作
发布: (2026年1月16日 GMT+8 02:38)
3 min read
原文: Dev.to
Source: Dev.to
你将构建的内容
一个简单的模式:
- 你的工具在运行时发出事件(进度/状态/文件操作)
- 前端订阅这些事件并立即渲染
- 类型守卫 让 UI 逻辑安全且可预测
无需轮询循环。无需猜测。无需 “thinking…” 占位符。
1) 从工具调用中发出带类型的自定义事件
在工具调用内部,随着工作进展写入自定义事件:
config.writer?.({
type: "progress",
id: analysisId, // stable id => update in place
step: steps[i].step,
message: steps[i].message,
progress: Math.round(((i + 1) / steps.length) * 100),
totalSteps: steps.length,
currentStep: i + 1,
toolCall: config.toolCall,
} satisfies ProgressData);
这就是关键转变:工具不只是函数——它们是事件生产者。
2) 在 React 中接收这些事件
在 UI 中,将处理函数传入流 Hook:
onCustomEvent: handleCustomEvent,
现在,工具发出的每个事件都会在客户端 实时 到达。
3) 缩窄事件类型并可预测地更新 UI 状态
将传入的事件视为 unknown,然后使用类型守卫进行缩窄,并根据 id 更新状态映射:
if (isProgressData(data)) {
/* update progress */
} else if (isStatusData(data)) {
/* update status */
} else if (isFileStatusData(data)) {
/* update file ops */
}
这让前端保持稳定:
- 进度更新 就地 进行
- 最小化重新渲染
- 没有字符串化的事件乱象
为什么这很重要(不仅仅是“好看的 UI”)
当 UI 真实反映执行过程时:
- 用户对代理的信任度提升
- 调试变得极其容易
- 失败可以在不翻日志的情况下被理解
- 你可以构建更好的用户体验:步骤指示器、时间线、文件操作流等
🎥 视频: