# Frontend Multi-Agent / MCP Process UI Change ## 1. 目标 前端聊天页要从“单一消息流”升级成“可视化协作工作台”,让用户在一次聊天里同时看到: 1. 主对话区里的用户问题与最终总结回复。 2. 每个 sub-agent / A2A agent / MCP server 的独立处理框。 3. agent 之间的流式进展、状态变化、问答片段。 4. MCP 工具调用产物,例如文本结果、结构化 JSON、文件、链接、图片。 5. 一个固定的结果侧栏,用来汇总当前运行中的过程结果与最终产物。 6. 独立的 Agent 管理页和 MCP 管理页,体验上与现有 `skills` / `plugins` 页面一致。 这个需求本质上不是“把聊天页面做复杂一点”,而是要把聊天 UI 的数据模型从 `messages[]` 升级成 `messages[] + process runs[] + artifacts[] + actor registry[]`。 ## 2. 当前现状 ### 2.1 前端现状 当前前端的核心限制如下: - 聊天页集中在 `/home/ivan/xuan/steven_project/nanobot-fronted/app/page.tsx`。 - 聊天状态只在 `/home/ivan/xuan/steven_project/nanobot-fronted/lib/store.ts` 里维护: - `messages` - `isLoading` - `isThinking` - `streamingContent` - WebSocket 只在 `/home/ivan/xuan/steven_project/nanobot-fronted/lib/api.ts` 里处理非常薄的一层消息: - `type=status` - `type=message` - 类型定义 `/home/ivan/xuan/steven_project/nanobot-fronted/types/index.ts` 没有“运行事件 / agent 卡片 / artifact / process timeline”概念。 - 顶部导航 `/home/ivan/xuan/steven_project/nanobot-fronted/components/Header.tsx` 目前没有 `Agents` / `MCP` 页入口。 - 现有 `skills` / `plugins` 页面适合复用作管理页风格参考: - `/home/ivan/xuan/steven_project/nanobot-fronted/app/skills/page.tsx` - `/home/ivan/xuan/steven_project/nanobot-fronted/app/plugins/page.tsx` ### 2.2 后端现状 后端已经具备部分多 agent 能力,但还不够支撑前端过程可视化: - 已有统一 agent 列表接口:`GET /api/agents` - 位置:`/home/ivan/xuan/steven_project/nanobot-backend/nanobot/web/server.py` - 已有 A2A / group delegation 逻辑: - `/home/ivan/xuan/steven_project/nanobot-backend/nanobot/agent/delegation.py` - 已有 A2A streaming / resubscribe / cancel: - `/home/ivan/xuan/steven_project/nanobot-backend/nanobot/a2a/client.py` - 但当前对前端暴露的实时消息仍然只有: - `status=thinking` - `assistant message` - `DelegationManager` 现在对外发布的也只是普通 `_progress` 文本,例如: - `[AgentName] ...` - MCP 目前只有后端连接配置和工具注册,没有独立的 Web 管理接口,也没有结构化 MCP 运行事件。 结论: 前端可以先做布局和状态层改造,但如果想真正展示“每个 agent 的框、每个 MCP 的产物、agent 间问答”,后端必须补一层结构化 process event 协议。只靠现在的纯文本 progress 不够。 ## 3. 推荐的界面形态 桌面端建议改成三栏工作台,而不是继续沿用现在的单栏聊天布局。 ### 3.1 桌面布局 ```text ┌──────────────┬───────────────────────────────────────┬──────────────────────────┐ │ 会话侧栏 │ 主聊天 + 过程泳道 │ 结果侧栏 │ │ Sessions │ │ Results / Artifacts │ │ │ 用户消息 │ 当前运行摘要 │ │ │ assistant 最终总结 │ agent 产物列表 │ │ │ ─────────────────────────────────── │ MCP 产物列表 │ │ │ Agent A 卡片 │ 文件/图片/JSON 预览 │ │ │ Agent B 卡片 │ 错误/告警 │ │ │ MCP github 卡片 │ 最终汇总结论 │ │ │ MCP browser 卡片 │ │ └──────────────┴───────────────────────────────────────┴──────────────────────────┘ ``` ### 3.2 移动端布局 移动端不要硬保留三栏: 1. 主聊天区保留为默认视图。 2. 过程泳道和结果侧栏改成底部 `Tabs` 或 `Drawer`。 3. 正在运行时,顶部显示一个 `Process (3)` 悬浮入口。 ### 3.3 视觉原则 不要把过程信息混成普通 assistant markdown。 应明确区分三类对象: 1. `Chat Message`:用户问题、最终总结。 2. `Process Card`:某个 agent 或 MCP 的运行容器。 3. `Artifact`:某个步骤产出的结构化结果。 建议: - Agent 卡片用清晰的状态边框和标题区。 - MCP 卡片强调“工具/服务器”属性,避免与 agent 混淆。 - 结果侧栏始终可见,展示当前选中卡片的详细结果。 ## 4. 目标交互 ### 4.1 单 Agent 用户发出问题后: 1. 主聊天区出现用户消息。 2. assistant 进入 `thinking`。 3. 若命中 `spawn` / A2A delegation,过程泳道新增一个 Agent 卡片。 4. 卡片内部流式更新: - 状态:queued / running / waiting / done / error / cancelled - 文本片段 - agent 生成的中间消息 - 关键参数或结果摘要 5. 如果 agent 调了 MCP,再在该卡片内部挂子步骤,或在泳道新增 MCP 卡片。 6. 右侧结果栏展示: - 当前 agent 的最新摘要 - 产物列表 - 可预览文件 7. 所有 agent 结束后,主 assistant 再给一条最终总结回复。 ### 4.2 多 Agent Group 如果是 group delegation: 1. 过程泳道里要同时出现多个 Agent 卡片。 2. 每个卡片独立流式刷新,不要合并成一条文本。 3. 结果侧栏支持切换: - `All` - `Agent A` - `Agent B` - `MCP Outputs` 4. 最终 assistant 总结要包含: - 共识 - 分歧 - 失败项 - 最终建议 ### 4.3 Agent 间“一问一答” 如果未来后端能发出 agent-to-agent message event,前端直接把这些消息渲染到卡片里的 transcript 区。 建议 UI 表现: - 卡片头:agent 名称、来源、状态、耗时 - 卡片体: - `Transcript` - `Steps` - `Artifacts` - 卡片尾:最终摘要 / 错误信息 ## 5. 前端改造点 ## 5.1 先不要继续把逻辑堆进 `app/page.tsx` 当前 `/home/ivan/xuan/steven_project/nanobot-fronted/app/page.tsx` 已经过大。这个需求如果继续直接堆,会很快失控。 建议拆分。 ### 5.2 建议新增的组件与文件 建议新增目录: - `components/chat-workbench/ChatWorkbench.tsx` - `components/chat-workbench/ProcessLane.tsx` - `components/chat-workbench/ProcessRunCard.tsx` - `components/chat-workbench/ProcessTranscript.tsx` - `components/chat-workbench/ArtifactSidebar.tsx` - `components/chat-workbench/RunSummaryPanel.tsx` - `components/chat-workbench/AgentBadge.tsx` - `components/chat-workbench/McpBadge.tsx` - `components/chat-workbench/StatusPill.tsx` 建议职责: - `ChatWorkbench.tsx` - 负责三栏布局组合。 - `ProcessLane.tsx` - 渲染当前 session 的所有 process run。 - `ProcessRunCard.tsx` - 渲染单个 agent / MCP 卡片。 - `ProcessTranscript.tsx` - 渲染步骤流、问答片段、进度文本。 - `ArtifactSidebar.tsx` - 渲染右侧产物栏。 - `RunSummaryPanel.tsx` - 展示当前 run 的状态概览和最终摘要。 ### 5.3 对现有文件的插入建议 #### `/home/ivan/xuan/steven_project/nanobot-fronted/app/page.tsx` 保留职责: - session 列表 - 输入框 - 顶层页面组织 减少职责: - 不再在这里直接渲染复杂过程 UI - 不再在这里直接解析 process 事件 建议修改为: 1. 左侧会话侧栏基本保留。 2. 中间改成 ``。 3. `MessageBubble` 可以保留,但只负责普通 `user/assistant` 消息。 4. 新增一个 `selectedRunId` / `selectedArtifactId` 的页面级状态,或者放进 Zustand store。 #### `/home/ivan/xuan/steven_project/nanobot-fronted/lib/store.ts` 这里需要从“聊天 store”升级成“聊天 + 过程 store”。 建议新增状态: - `processRuns: ProcessRun[]` - `processEvents: ProcessEvent[]` - `artifacts: ProcessArtifact[]` - `selectedRunId: string | null` - `selectedArtifactId: string | null` - `activeRunIds: string[]` - `agentRegistry: UiAgentDescriptor[]` - `mcpRegistry: UiMcpServerDescriptor[]` 建议新增 action: - `resetProcessState(sessionId)` - `upsertProcessRun(run)` - `appendProcessEvent(event)` - `appendProcessArtifact(artifact)` - `finishProcessRun(runId, status)` - `cancelProcessRun(runId)` - `setSelectedRunId(runId)` - `setSelectedArtifactId(artifactId)` - `setAgentRegistry(agents)` - `setMcpRegistry(servers)` #### `/home/ivan/xuan/steven_project/nanobot-fronted/types/index.ts` 这里需要新增完整类型层。 建议新增: ```ts export type ProcessActorType = 'agent' | 'mcp' | 'system'; export type ProcessRunStatus = 'queued' | 'running' | 'waiting' | 'done' | 'error' | 'cancelled'; export type ProcessEventKind = | 'run_started' | 'run_progress' | 'run_message' | 'run_artifact' | 'run_status' | 'run_finished' | 'run_cancelled'; export interface UiAgentDescriptor { id: string; name: string; description: string; source: 'workspace' | 'plugin' | 'skill' | 'builtin'; kind: string; protocol: string | null; tags: string[]; aliases: string[]; support_group: boolean; support_streaming: boolean; } export interface UiMcpServerDescriptor { id: string; name: string; transport: 'stdio' | 'http'; url?: string; command?: string; enabled: boolean; tool_count?: number; tool_names?: string[]; status?: 'connected' | 'disconnected' | 'error'; last_error?: string | null; } export interface ProcessRun { run_id: string; parent_run_id?: string | null; session_id: string; actor_type: ProcessActorType; actor_id: string; actor_name: string; title: string; status: ProcessRunStatus; started_at: string; finished_at?: string | null; summary?: string | null; source?: string | null; } export interface ProcessEvent { event_id: string; run_id: string; parent_run_id?: string | null; kind: ProcessEventKind; actor_type: ProcessActorType; actor_id: string; actor_name: string; text?: string; status?: ProcessRunStatus; message_role?: 'system' | 'user' | 'assistant' | 'tool'; metadata?: Record; created_at: string; } export interface ProcessArtifact { artifact_id: string; run_id: string; actor_type: ProcessActorType; actor_id: string; title: string; artifact_type: 'text' | 'json' | 'file' | 'image' | 'link' | 'markdown'; content?: string; data?: Record | unknown[]; file_id?: string; url?: string; created_at: string; } ``` #### `/home/ivan/xuan/steven_project/nanobot-fronted/lib/api.ts` 这里要扩展三类能力: 1. Agent 管理 API 2. MCP 管理 API 3. WebSocket process event 订阅 建议新增: - `listAgents()` - `addAgent()` - `deleteAgent()` - `refreshAgents()` - `listMcpServers()` - `addMcpServer()` - `updateMcpServer()` - `deleteMcpServer()` - `testMcpServer()` 同时把 `WsMessageHandler` 从现在的宽松结构,升级成联合类型: ```ts export type WsEvent = | ChatAssistantEvent | ChatThinkingEvent | ProcessRunStartedEvent | ProcessRunUpdatedEvent | ProcessArtifactEvent | ProcessRunFinishedEvent | ProcessRunCancelledEvent; ``` #### `/home/ivan/xuan/steven_project/nanobot-fronted/components/Header.tsx` 导航中建议新增: - `/agents` - `/mcp` 放在 `skills` / `plugins` 旁边,不要塞进聊天页内部。 ### 5.4 建议新增页面 - `/home/ivan/xuan/steven_project/nanobot-fronted/app/agents/page.tsx` - `/home/ivan/xuan/steven_project/nanobot-fronted/app/mcp/page.tsx` Agent 页面参考 `skills + plugins` 的中间态: - 列表视图 - 支持新增、删除、刷新 - 展示来源:workspace / plugin / skill / builtin - 展示协议:a2a / local - 展示标签、别名、streaming/group 支持 MCP 页面建议分两块: 1. `Configured Servers` 2. `Discovered Tools` 每个 MCP server 展示: - 连接方式:stdio / http - 地址或命令 - tool 数量 - 连接状态 - 最后错误 - 编辑/删除/测试按钮 ## 6. 聊天页的推荐逻辑链路 这是前端应当遵守的主链路。 ### 6.1 用户发消息 1. 用户在 `app/page.tsx` 输入消息。 2. 立即写入 `messages[]`。 3. 设置 `isLoading=true`。 4. 如果 WebSocket 已连接,消息通过 `wsManager.sendRaw()` 发出去。 5. 前端等待两类数据: - 普通 assistant reply - process events ### 6.2 触发 sub-agent / group / MCP 后端一旦进入 delegation / MCP tool 调用,应向前端发结构化 process event。 前端收到后: 1. `run_started` -> 创建卡片。 2. `run_progress` -> 更新卡片中的 transcript。 3. `run_artifact` -> 写入右侧侧栏。 4. `run_status` -> 更新状态 pill。 5. `run_finished` -> 收起 loading,保留结果。 6. 最终 `assistant message` -> 输出总结性回复。 ### 6.3 用户点击某个 Agent / MCP 卡片 1. 设置 `selectedRunId`。 2. 右侧 `ArtifactSidebar` 切换到该 run 的 artifact 列表。 3. 中间卡片高亮。 4. 若有 transcript,则显示完整流。 ### 6.4 用户取消运行 如果后端暴露 cancel 接口或 WebSocket cancel command: 1. 卡片上显示 `Cancel`。 2. 用户点击后发送 cancel 请求。 3. run 状态变为 `cancelled`。 4. 侧栏保留已有产物,但标记“未完成”。 ## 7. 后端必须补的事件协议 这是这次前端能否做成的关键。 当前后端只发普通文本 `_progress`,不够。 必须新增结构化 WebSocket 事件。建议统一成 `type=process_*`。 ### 7.1 建议的事件集合 #### `process_run_started` ```json { "type": "process_run_started", "session_id": "web:default", "run_id": "deleg-123", "parent_run_id": null, "actor_type": "agent", "actor_id": "repo-reviewer", "actor_name": "Repo Reviewer", "source": "workspace", "title": "Review auth refactor", "status": "running", "created_at": "2026-03-06T10:00:00Z" } ``` #### `process_run_progress` ```json { "type": "process_run_progress", "run_id": "deleg-123", "actor_type": "agent", "actor_id": "repo-reviewer", "text": "Scanning auth middleware and session lifecycle", "created_at": "2026-03-06T10:00:03Z" } ``` #### `process_run_message` 用于展示 agent 间问答或 agent 内部消息。 ```json { "type": "process_run_message", "run_id": "deleg-123", "actor_type": "agent", "actor_id": "repo-reviewer", "message_role": "assistant", "text": "I need the gateway config file before deciding.", "created_at": "2026-03-06T10:00:04Z" } ``` #### `process_run_artifact` ```json { "type": "process_run_artifact", "run_id": "mcp-456", "actor_type": "mcp", "actor_id": "github", "title": "Pull Request Diff Summary", "artifact_type": "markdown", "content": "...", "created_at": "2026-03-06T10:00:08Z" } ``` #### `process_run_status` ```json { "type": "process_run_status", "run_id": "deleg-123", "status": "waiting", "text": "Waiting for remote agent task completion", "created_at": "2026-03-06T10:00:10Z" } ``` #### `process_run_finished` ```json { "type": "process_run_finished", "run_id": "deleg-123", "status": "done", "summary": "Found 2 risks in auth token refresh flow.", "created_at": "2026-03-06T10:00:20Z" } ``` #### `process_run_cancelled` ```json { "type": "process_run_cancelled", "run_id": "deleg-123", "status": "cancelled", "created_at": "2026-03-06T10:00:12Z" } ``` ### 7.2 后端推荐插入点 如果你后面让我直接改前后端,我会从这些点切: #### `/home/ivan/xuan/steven_project/nanobot-backend/nanobot/agent/delegation.py` 这里最适合发 agent 级 process event: - `dispatch()` 开始时发 `process_run_started` - `_build_progress_callback()` 中把 A2A stream 文本转成 `process_run_progress` - `_run_group()` 中每个 descriptor 启动时发独立子 run - `_announce_single_result()` 之前发 `process_run_finished` - `_announce_group_result()` 之前发 group summary run finished - `cancel()` / `_announce_cancelled()` 发 `process_run_cancelled` #### `/home/ivan/xuan/steven_project/nanobot-backend/nanobot/a2a/client.py` 这里最适合补更细的远端 agent 消息: - `_consume_stream_method()` - `_resume_subscription()` 如果远端流里有 message chunk / state / artifact,就在这里归一化后向上抛给 `DelegationManager`。 #### `/home/ivan/xuan/steven_project/nanobot-backend/nanobot/agent/tools/mcp.py` 这里最适合发 MCP 级事件: - MCP 工具调用开始 -> `process_run_started` (`actor_type=mcp`) - 工具标准输出 / 中间结果 -> `process_run_progress` - 工具返回文本 / JSON / 文件 -> `process_run_artifact` - 工具调用完成 -> `process_run_finished` - 超时 / 失败 -> `process_run_status` + `process_run_finished(status=error)` #### `/home/ivan/xuan/steven_project/nanobot-backend/nanobot/web/server.py` 这里需要扩展 WebSocket 发送协议,而不是只发 `thinking/message`。 ## 8. Agent 管理页方案 ### 8.1 页面目标 让用户能像管理 `skills` 一样管理委派目标 agent。 ### 8.2 数据来源 直接用现有接口: - `GET /api/agents` - `POST /api/agents` - `DELETE /api/agents/{id}` - `POST /api/agents/refresh` ### 8.3 页面布局建议 参考 `plugins` 页的卡片布局,但要比 `plugins` 更偏“资源管理”。 建议字段: - 名称 - id - description - source - protocol - tags - aliases - support_group - support_streaming - endpoint / base_url / card_url 建议交互: 1. 顶部 `Refresh` 2. 顶部 `Add Agent` 3. 列表卡片 4. workspace agent 允许删除 5. plugin / skill / builtin agent 只读 ### 8.4 Add Agent 弹窗字段 - `id` - `name` - `description` - `protocol`,先只放 `a2a` - `base_url` - `endpoint` - `card_url` - `auth_env` - `tags` - `aliases` - `enabled` ## 9. MCP 管理页方案 ### 9.1 结论先说 这个页面前端不能单独完成,因为当前后端没有 MCP 管理 API。 所以文档给的是“前端页面方案 + 后端配套接口定义”。 ### 9.2 后端建议增加的 API 建议新增: - `GET /api/mcp/servers` - `POST /api/mcp/servers` - `PUT /api/mcp/servers/{id}` - `DELETE /api/mcp/servers/{id}` - `POST /api/mcp/servers/{id}/test` - `GET /api/mcp/tools` ### 9.3 MCP server 返回结构建议 ```json { "id": "github", "name": "github", "transport": "http", "url": "http://localhost:3001/mcp", "command": "", "args": [], "enabled": true, "tool_timeout": 30, "headers": {}, "status": "connected", "tool_count": 12, "tool_names": ["search_repos", "list_prs"], "last_error": null } ``` ### 9.4 页面布局建议 上半区:MCP servers - 卡片或表格 - 编辑 / 删除 / 测试连接 下半区:Discovered tools - 按 server 分组 - 展示工具名、说明、schema 摘要 ## 10. 建议的前端实现顺序 按这个顺序做最稳。 ### Phase 1: 先做前端数据结构重构 1. 扩 `types/index.ts` 2. 扩 `lib/store.ts` 3. 扩 `lib/api.ts` 的 ws event 类型 4. 把 `app/page.tsx` 拆出 `ChatWorkbench` 这一步即使后端结构化事件还没补,也可以先用 mock data 跑布局。 ### Phase 2: 落三栏工作台 UI 1. 中间主聊天区保留现有 message bubble 2. 加 `ProcessLane` 3. 加 `ArtifactSidebar` 4. 支持选中某个 run ### Phase 3: 接后端 process events 1. 给 `wsManager.onMessage()` 加 process 事件分发 2. store 按 event 更新 process state 3. 卡片流式刷新 ### Phase 4: 新增 Agent 管理页 1. `app/agents/page.tsx` 2. `lib/api.ts` 增 Agent API 3. `Header.tsx` 增导航 ### Phase 5: 新增 MCP 管理页 1. 后端先补接口 2. 前端 `app/mcp/page.tsx` 3. 管理 + 测试连接 + 工具查看 ## 11. 为什么我建议最好由同一个 Codex 连前后端一起改 如果只是做视觉壳子,另一个 Codex 在前端仓库里单独改也可以。 但如果目标是你描述的完整体验: - 每个 agent / MCP 弹出独立框 - 展示过程中的一问一答 - 展示 MCP 产物 - 最后再统一总结 那就不是纯前端问题,而是“后端事件模型 + 前端状态模型”联动问题。 结论: - 只写前端:可以先做静态布局和 store 重构。 - 真正做成:最好同一个人连续改 backend + frontend,避免事件协议和 UI 状态设计脱节。 ## 12. 给另一个 Codex 的明确施工指令 如果你把这份文档交给另一个 Codex,建议直接给它下面这段要求: 1. 先阅读: - `/home/ivan/xuan/steven_project/nanobot-fronted/app/page.tsx` - `/home/ivan/xuan/steven_project/nanobot-fronted/lib/store.ts` - `/home/ivan/xuan/steven_project/nanobot-fronted/lib/api.ts` - `/home/ivan/xuan/steven_project/nanobot-fronted/types/index.ts` - `/home/ivan/xuan/steven_project/nanobot-fronted/app/plugins/page.tsx` - `/home/ivan/xuan/steven_project/nanobot-fronted/app/skills/page.tsx` 2. 先把聊天页拆成三栏工作台,不要继续把复杂逻辑堆在 `app/page.tsx`。 3. 先做 `processRuns / processEvents / artifacts` 的前端数据模型。 4. 先接 `/api/agents` 做 Agent 管理页。 5. MCP 管理页先按文档搭 UI 壳子,但要显式标记“依赖后端 MCP API”。 6. 如果要做真实过程可视化,不要拿普通 markdown 消息硬解析,必须等结构化 WebSocket process events。 ## 13. 最小可交付版本 如果要先做一个能看的版本,建议这样收敛: 1. 聊天页先做三栏布局。 2. 用当前 `_progress` 文本先临时映射成 Agent 卡片日志。 3. 先接 `/api/agents` 做管理页。 4. MCP 页先做只读占位页,提示“等待后端 MCP API”。 5. 第二轮再补真正结构化 process events。 这条路径的好处是: - UI 先起来 - 后端协议第二轮再精修 - 不会一开始就卡死在全链路联调上 ## 14. 推荐文档结论 最合适的落地方式是: 1. 前端先重构成“聊天消息”和“过程运行”两套状态。 2. 聊天页改成三栏工作台。 3. 先接现有 `/api/agents` 做 Agent 管理页。 4. MCP 管理页需要后端先补接口。 5. 真正的过程可视化必须补结构化 WebSocket process events,核心后端插入点是: - `nanobot/agent/delegation.py` - `nanobot/a2a/client.py` - `nanobot/agent/tools/mcp.py` - `nanobot/web/server.py`