问答题12/1816前端如何实现 Agent 对话系统?

难度:
2026-06-08 创建

参考答案:

前端实现 Agent 对话系统,核心不是做一个普通聊天框,而是把“多轮对话、流式响应、工具调用、任务状态、用户确认、结果呈现”这些能力组合成一个稳定的交互系统。

比较合理的架构是:前端只负责交互、状态展示和用户输入,真正的 Agent 编排放在后端。前端向后端提交一次用户输入,后端负责调用模型、检索知识库、执行工具、管理上下文和权限。前端通过 SSE 或 WebSocket 接收流式事件,例如文本增量、工具调用开始、工具执行结果、需要用户确认、任务完成、任务失败等。这样可以避免把模型 Key、工具凭证、业务权限暴露在浏览器里。

在数据模型上,不能只把消息当成一段字符串。一个对话回合通常包含用户消息、Agent 的回复、若干执行步骤、工具调用记录、引用来源、产物文件和错误状态。前端最好设计一套事件驱动的消息结构,比如:

1type AgentEvent = 2 | { type: 'message_delta'; runId: string; content: string } 3 | { type: 'tool_call_start'; toolCallId: string; name: string; input: unknown } 4 | { type: 'tool_call_result'; toolCallId: string; output: unknown } 5 | { type: 'approval_required'; approvalId: string; detail: unknown } 6 | { type: 'artifact_created'; artifact: Artifact } 7 | { type: 'error'; message: string } 8 | { type: 'done' };

前端消费这些事件后,再映射成 UI 状态。这样 Agent 后续增加新工具、新步骤、新产物类型时,不需要重写整个对话界面。

流式输出是体验重点。SSE 更适合单向持续输出,实现简单,也天然支持重连;WebSocket 更适合需要双向实时控制的场景,比如执行中插入指令、暂停、继续。前端渲染 token 时不能每个字符都触发一次完整渲染,可以做 buffer 合并,用 requestAnimationFrame 或节流批量更新,避免长回复时页面卡顿。Markdown 渲染要处理半截代码块、表格未闭合等情况,同时必须做 XSS 过滤,不能直接信任模型输出。

Agent 对话系统还需要明确的状态机。普通聊天只有发送中、完成、失败,但 Agent 会出现更多状态:等待模型响应、执行工具、等待用户授权、生成文件、被取消、可恢复等。比如执行删除、发送邮件、修改数据这类高风险工具时,前端应该展示确认卡片,让用户明确批准后再继续。这里的确认不是装饰,而是安全边界的一部分。

UI 上,一般会把主回复和执行过程分层展示。用户主要关注最终答案,所以默认突出回答内容;工具调用、检索过程、日志、错误详情可以折叠展示。对于 Agent 生成的代码、报表、图片、文档等结果,最好不要只放在消息气泡里,而是以 artifact 面板、预览区或下载入口展示,这样更符合真实工作流。

上下文管理也很关键。前端需要支持会话列表、历史恢复、消息编辑、重新生成、分支对话、附件上传、引用资料展示等能力。每次请求最好带上 conversationIdrunId、客户端幂等 ID,避免网络重试导致重复执行工具。长任务场景下,还要支持刷新页面后恢复任务状态,而不是所有状态只存在内存里。

工程实现上,可以把对话系统拆成几层:API 层负责提交消息和订阅事件;store 层维护会话、消息、运行状态;渲染层展示文本、工具卡片、确认卡片和产物;交互层处理取消、重试、继续、审批。React 里可以用 Zustand、Redux 或 React Query 管理状态,但重点不是工具选型,而是事件模型和状态边界要清晰。

最后还要考虑稳定性和安全性。网络断开要能重连或提示恢复;用户取消要通过 AbortController 或后端 cancel API 真正终止任务;Markdown、HTML、链接、文件预览都要做安全过滤;敏感工具必须有权限校验和二次确认;前端日志不能记录隐私内容和密钥。

最近更新时间:2026-06-09

赞赏支持

题库维护不易,您的支持就是我们最大的动力!