workspace/ files existed on disk but were not included in previous incremental commit, causing git to record them as deleted. Re-adding all workspace card components, AgentWorkspace, ActivityTimeline, and WorkspaceCardRenderer to properly track them. Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
9.8 KiB
langgraphjs-gen-ui-examples 实跑与代码核对记录
1. 这次我实际做了什么
这次不是只看 README,我实际做了下面这些事:
- clone 仓库
- 路径:
/Users/gongzhiyong/go/langgraphjs-gen-ui-examples
- 路径:
- 安装依赖
- 执行:
pnpm install - 已成功
- 执行:
- 读取关键配置与代码
README.mdpackage.json.env.examplelanggraph.jsonsrc/agent-uis/index.tsxsrc/agent-uis/writer/index.tsxsrc/agent/writer-agent/index.tssrc/agent/open-code/index.tssrc/agent/pizza-orderer/index.ts
- 核对该项目“交互到底由哪里承接”
2. 这次我没有做到什么
我还没有把它完整跑到真实可交互演示画面,原因不是偷懒,而是这个仓库本身不是一个“装完直接开网页就能看完整交互”的纯前端 demo。
它依赖:
- LangGraph server
- 模型 API key(OpenAI / Google,部分示例还要 Anthropic)
- Agent Chat UI 这一套承接壳
所以它的“完整交互形态”不是只靠本仓库单独就能闭环展示的。
因此这次能确认的是:
- 代码结构
- 交互承接机制
- gen-ui 的真实工作方式
但不能假装说:
- 我已经把所有示例一条条真实点过并完整体验完
这点必须说明白。
3. 关键结论:这个仓库不是独立完整聊天产品,而是“LangGraph + UI 组件映射层”
从 README 和代码看,langgraphjs-gen-ui-examples 的定位很明确:
这是给 Agent Chat UI 使用的一组 LangGraph.js generative UI 示例。
也就是说,它不是:
- 一个完整成品聊天应用
它更像:
- 一组 graph
- 一组 UI component map
- 一套 graph 向 UI 推送结构化组件的示例实现
这点非常关键。
证据 1:README 直接写明
README 原文核心意思是:
This repository contains a series of agents intended to be used with the Agent Chat UI
这已经说明:
- 真正承接聊天壳和交互主框架的是 Agent Chat UI
- 这个 repo 负责的是 agent + generative UI 示例
证据 2:langgraph.json
代码里:
{
"graphs": {
"agent": "./src/agent/supervisor/index.ts:graph",
"email_agent": "./src/agent/email-agent/index.ts:agent",
"chat": "./src/agent/chat-agent/index.ts:agent"
},
"ui": {
"agent": "./src/agent-uis/index.tsx"
}
}
这说明:
- graph 在后端/agent 侧
- UI 映射入口在
src/agent-uis/index.tsx
也就是它的核心不是“前端页面布局”,而是:
- graph 运行时能推送什么 UI
- UI 名字如何映射到 React 组件
4. 真实的 generative UI 工作方式
这是这次最重要的发现。
4.1 它不是 trace panel 升级版
它不是:
- tool_start
- tool_end
- 然后前端自己把这些事件渲染成卡片
它更接近:
- graph 在执行过程中直接推一个“UI 组件实例”
- 前端按 name + props 渲染这个组件
4.2 ComponentMap 是关键
src/agent-uis/index.tsx:
const ComponentMap = {
"stock-price": StockPrice,
portfolio: PortfolioView,
"accommodations-list": AccommodationsList,
"restaurants-list": RestaurantsList,
"buy-stock": BuyStock,
"code-plan": Plan,
"proposed-change": ProposedChange,
writer: Writer,
} as const;
这个文件明确说明:
- gen-ui 的核心单位不是“通用 trace item”
- 而是“命名组件”
- graph 推什么组件名,前端就渲染什么组件
这和我前面只讲“timeline + result card”的说法相比,更接近真实代码。
也就是说,如果你要无限接近它:
- 不能只做通用 workspace + 通用卡片系统
- 还要有“组件注册表 / 组件协议 / 组件 props 约定”
5. Writer 示例说明了什么
src/agent/writer-agent/index.ts 和 src/agent-uis/writer/index.tsx 是最关键的例子。
5.1 后端/graph 侧是怎么做的
writer graph 里用了:
import { typedUi } from "@langchain/langgraph-sdk/react-ui/server";
然后在 graph 执行过程中:
ui.push(
{ id, name: "writer", props: { ...tool, isGenerating: true } },
{ message, merge: true },
);
后面内容流式生成时继续:
ui.push(
{ id, name: "writer", props: { content, isGenerating: true } },
{ message: lastMessage, merge: true },
);
最后结束时:
ui.push(
{ id, name: "writer", props: { isGenerating: false } },
{ message: lastMessage, merge: true },
);
这说明它的机制不是:
- 前端根据工具结果“猜”出该渲染什么
而是:
- graph 明确 push 一个叫
writer的 UI 组件 - 并且持续 merge 更新它的 props
5.2 前端组件侧是怎么承接的
src/agent-uis/writer/index.tsx 中:
- 组件会根据
isGenerating显示生成中 - 有
Artifact侧边面板 - 内容流式写进 textarea
- 生成过程中还能自动打开 artifact panel
这个交互不是“消息上的 trace 面板”能替代的。
它本质上是:
- 聊天消息只是触发器/上下文
- 真正的内容承接在独立 artifact/workspace
这对 SOC 的启发非常大。
6. Pizza / Open Code / Email 示例分别说明什么
6.1 Pizza
README 和代码都说明:
- pizza 示例主要展示 tool call/result UI
这说明它有一条路线是:
- 工具调用本身也能被 UI 组件化展示
6.2 Open Code
Open Code 是一个假的代码生成 agent,用来演示:
- plan
- proposed changes
- 审批/继续
- 多步 UI 交互
这说明它不是只有“卡片展示”,还有:
- 多步状态机 UI
- 用户确认后继续 graph
6.3 Email Agent
Email agent 用的是 interrupt / HumanInterrupt 标准 schema。
说明它还支持:
- graph 中断
- 前端自动渲染 HITL UI
- 用户处理后恢复 graph
这比“只展示 trace”又高了一个层级。
7. 对 SOC 的真实结论
这部分必须收得很实。
7.1 现在 SOC 最接近的不是它的“完整形态”,而是最外层轮廓
SOC 现在已有:
- chat
- SSE token
- status
- tool trace
- message 绑定
这些只对应到它的最外层轮廓。
SOC 现在还没有真正拥有的,是下面这几层:
第一层:UI 组件注册机制
类似:
writerstock-priceportfoliocode-planproposed-change
SOC 现在没有这种“组件名 -> React 组件”的标准化注册表。
第二层:后端主动 push UI 组件实例
这个 repo 的关键能力是:
- graph 直接
ui.push({ id, name, props })
SOC 当前没有这层。 SOC 现在还是:
- 发 status/tool/token
- 前端自己猜怎么显示
这两者差异很大。
第三层:artifact/workspace 是一等公民
writer 示例里,artifact 侧边面板是正式交互层。 SOC 现在没有真正的一等 workspace / artifact 层。
第四层:interrupt / HITL / resume 机制
SOC 目前也没有把这一层做成产品 UI。
8. 历史消息 gen-ui 持久化,为什么会变成大问题
现在可以更准确回答你前面那个问题。
因为在这个例子里,gen-ui 不是简单 trace,而是:
- 一个或多个具名 UI 组件实例
- 每个实例都有 props
- props 还会增量更新
- 还可能挂在某条 message 上 merge
所以历史消息持久化时,最稳的不是只存 trace,而是要存:
{
"message_id": "...",
"ui_instances": [
{
"id": "...",
"name": "writer",
"props": {
"title": "...",
"content": "...",
"isGenerating": false
}
}
]
}
也就是:
- 存“组件实例快照”
- 不只是存“工具事件日志”
否则历史消息重开时,根本无法接近它那个交互。
9. 我现在对“能不能无限接近它”的新判断
在实际读过这些代码后,答案比之前更明确:
9.1 如果 SOC 只是把现在的 trace panel 升级成右侧栏
那不能无限接近。
因为这只是在 UI 布局层面模仿。 没有触及它真正的核心机制:
- 后端推具名 UI 组件
- 前端组件注册映射
- artifact / workspace 一等化
- message 级别的 UI merge
9.2 如果 SOC 允许新增一层“GenUI 协议 + 组件注册 + workspace 持久化”
那可以高相似度接近。
但前提不是“小修小补”,而是要补以下能力:
- 后端 UI 事件协议
- 前端 component registry
- workspace / artifact 容器
- message -> ui instance 绑定
- 历史会话快照恢复
9.3 所以结论不能再说虚的
最准确的话是:
- 单靠当前那套 status + trace + answer 方案,不能无限接近
langgraphjs-gen-ui-examples - 如果把协议层升级为“具名 UI 组件实例流”,再加 workspace 持久化,才有资格说高相似度接近
10. 对我前面方案的修正
我前面那版 uigoto.md 有一个本质问题:
我把目标抽象成了:
- timeline
- result cards
- workspace
这没错,但还不够贴这次真实读到的代码。
缺的关键一层是:
gen-ui 不是“结果卡片集合”这么简单,而是“后端驱动的具名 UI 组件实例系统”。
这会直接影响:
- 前后端协议怎么设计
- 持久化怎么做
- 组件如何注册
- 历史消息如何恢复
- 后续交互复杂度能否提升到 interrupt / HITL / artifact 级别
所以如果接下来重写 SOC 方案,必须把这一层补进去。
11. 当前可以下的最硬结论
结论 1
langgraphjs-gen-ui-examples 不是单纯展示 trace 的项目,它的核心是:
- graph 执行时直接推 UI 组件实例
- 前端按组件注册表渲染
结论 2
它的完整交互壳很大程度依赖 Agent Chat UI,不是这个 repo 自己单独包办全部页面壳。
结论 3
SOC 如果想无限接近它,不能只升级 trace panel,必须升级成:
- UI 组件协议
- component registry
- artifact/workspace
- message 绑定持久化
结论 4
历史消息 gen-ui 持久化,最稳方案不是只存 trace,而是存“message 级 UI 组件实例快照”。