跳到主要内容

Tambo 是什么 · 全景与阅读地图

30 秒导读: Tambo 是一套给 React 的开源生成式 UI(generative UI)工具包。你把自己写的组件用 Zod schema 注册进去,LLM 会按用户那句话挑出该显示哪个组件,并流式地把 props 填进去,前端就渲染出一个活的、可交互的界面。一句话:让 AI 说你自己的 UI。


1. 这是什么(零基础也能懂)

一句话定义。 Tambo 是"让 LLM 按用户意图调用、更新你自己 React 组件"的一套前后端一体工具包(README.md:44)。

它解决谁的什么问题。 传统聊天式 AI 只会吐一段文字或 Markdown。但很多场景里,用户真正想要的是一个界面:一张图表、一个可勾选的任务板、一个能改的购物车。以前你得手写一堆"如果模型说 X 就渲染组件 Y"的胶水代码;Tambo 把这套胶水标准化了。

  • 给谁用: 想在 React 应用里加"AI 生成界面"的前端/全栈开发者。
  • 典型例子: 用户说"给我看看各区域的销售额",渲染出你的 <Chart>;用户说"加个任务",更新你的 <TaskBoard>(README.md:46)。

它能做什么(功能一览):

能力说明
生成式组件模型按用户消息挑组件、填 props,渲染一次(图表、摘要、可视化)
可交互组件组件持久存在、随对话反复更新(购物车、表格、任务板)
流式 propsprops 边生成边流入组件;取消、错误恢复、重连都替你处理好
内置 Agent后端替你跑完 LLM 对话循环,自带你的 API key(OpenAI / Anthropic / Gemini / Mistral 等)
本地工具 & MCP组件之外还能注册浏览器里跑的函数,或接 MCP 服务器(Linear、Slack、数据库)
Cloud 或自托管同一套后端既可用官方托管的 Tambo Cloud,也能 Docker 自托管

用起来什么样(最小示例)。 三步:注册组件 → 包一层 Provider → 用 hook 读消息。下面是 README 里的真实用法(README.md:95-141,示意精简):

// ① 用 Zod schema 把你的组件描述成"AI 能理解的东西"
const components: TamboComponent[] = [
{
name: "Graph",
description: "用 Recharts 把数据画成图表", // 这段描述会喂给模型,决定它何时选这个组件
component: Graph,
propsSchema: z.object({
data: z.array(z.object({ name: z.string(), value: z.number() })),
type: z.enum(["line", "bar", "pie"]),
}),
},
];

// ② 包一层 Provider(必须给 userKey 或 userToken 标明 thread 归属)
<TamboProvider apiKey={API_KEY} userKey={currentUserId} components={components}>
<Chat />
</TamboProvider>;

// ③ 在任意子组件里用 hook 读消息和流式状态
const { messages, isStreaming } = useTambo();

一句话直觉/类比。 把你的每个 React 组件想成一个**"按钮",按钮上写着"我能显示天气"。Tambo 把这排按钮的说明书递给模型;模型看用户想要啥,就去按对应的按钮**(内部叫 show_component_天气),同时把该显示的数据从按钮的插槽塞进去。你不再写"if 模型说 X"的分发逻辑,模型自己会按。


2. 顶层全景(它大概怎么转)

Tambo 是一个 Turborepo monorepo,同时装着"框架"(给开发者用的 SDK)和"云平台"(跑对话的后端)。理解它,先抓住一条四层主线——从你的浏览器一路到 LLM。

2.1 四层架构图

怎么读这张图: 从上到下是一次请求的流向。虚线是浏览器 / 服务器的边界——上半在用户浏览器里跑,下半在 Tambo Cloud 或你自托管的机器上跑。左边标的是包名。

用户在聊天框里打字 / 点建议

┌─────────────▼──────────────────────────────┐
│ ① React 胶水层 @tambo-ai/react │ react-sdk/src/index.ts
│ TamboProvider / useTambo / 组件注册表 │ (当前只导出 v1)
└─────────────┬──────────────────────────────┘
│ 依赖
┌─────────────▼──────────────────────────────┐
│ ② 框架无关内核 @tambo-ai/client │ packages/client
│ TamboClient(状态)+ TamboStream(流) │ Node/Vue/Svelte 也能直接用
└─────────────┬──────────────────────────────┘
│ HTTP / SSE(text/event-stream)
- - - - - - - - -│- - - - 浏览器 ╱ 服务器 边界 - - - - - - - - -

┌─────────────▼──────────────────────────────┐
│ ③ HTTP / 流式接口 apps/api (NestJS) │ apps/api/src/v1/v1.controller.ts
│ /v1/threads/runs → SSE 吐 AG-UI 事件 │ Cloud 或自托管
└─────────────┬──────────────────────────────┘
│ 调用 runDecisionLoop()
┌─────────────▼──────────────────────────────┐
│ ④ 决策循环大脑 @tambo-ai-cloud/backend │ packages/backend
│ 把组件变成 show_component_* 工具喂给模型 │ tambo-backend.ts
└─────────────┬──────────────────────────────┘


LLM(自带你的 API key)

一句话:react-sdk 是给 React 用的糖,client 是真正的引擎,apps/api 是它对外的 HTTP 门面,backend 是门后决策的大脑。 react-sdk 在依赖上包着 client(react-sdk/package.json:80),client 通过生成的 HTTP SDK 打到 apps/api,apps/api 再调 backend 的 runDecisionLoop(apps/api 依赖 @tambo-ai-cloud/backend,apps/api/package.json:50)。

2.2 每个包 / 应用一句话职责

框架侧(给开发者用的,发到 npm):

包 / 应用npm 名一句话职责
react-sdk@tambo-ai/reactReact SDK:Provider、hooks、组件/工具注册表——开发者主要碰的就是它
packages/client@tambo-ai/client框架无关内核:流式、工具执行、thread 状态,不依赖 React
packages/react-ui-base@tambo-ai/react-ui-base无头(headless)基础组件 / 原语,供上层 UI 拼装
packages/ui-registry@tambo-ai/ui-registry预制生成式 UI 组件库(图表、地图、消息线程等)的源
clitambo脚手架 CLI:初始化项目、生成组件、同步组件注册表
create-tambo-appcreate-tambo-appnpm create tambo-app 的引导器,一键起新项目

云平台侧(跑对话的后端,Cloud 或自托管):

包 / 应用npm 名一句话职责
apps/api@tambo-ai-cloud/apiNestJS 服务:对外的 HTTP / SSE 接口,承载 thread、运行、流式
apps/web@tambo-ai-cloud/webNext.js 控制台(项目管理、API key 等仪表盘)
apps/docs-mcpdocs-mcp把文档暴露成 MCP 服务器,供 AI 查 Tambo 文档
packages/backend@tambo-ai-cloud/backend决策循环大脑:把组件转成工具、跑 LLM、流式吐结果
packages/core@tambo-ai-cloud/core纯工具函数(校验、JSON、UI 工具名前缀等),不碰数据库
packages/db@tambo-ai-cloud/dbDrizzle ORM schema + 迁移 + 数据库操作

2.3 主线走一遍(高层,不进代码)

一次"用户说话 → 界面出现"大致这样流动:

  1. 用户发消息。 前端 useTamboThreadInput().submit() 把这句话交给 client。
  2. 组件被当成工具喂给模型。 后端把每个注册组件转成一个名叫 show_component_<组件名> 的"工具",组件的 props schema 就是这个工具的参数表(packages/backend/src/services/tool/tool-service.ts:100 convertComponentsToUITools)。
  3. 模型决策。 决策循环(runDecisionLoop)让模型看用户意图,选择调用哪个 show_component_X,并按 props schema 生成参数——这就是"选组件 + 填 props"。
  4. props 流式回传。 生成的内容以 AG-UI 事件(一种标准化的流式事件语言)通过 SSE 一点点推回浏览器;client 的累积器把碎片拼成完整的 thread 状态。
  5. 前端渲染。 react-sdk 在注册表里按名字找到真正的 React 组件,把流进来的 props 灌进去,渲染成活的、可继续交互的界面。

3. 巧妙之处索引(读后续章节会展开)

这些是 Tambo "值得学"的设计点,先给你一个索引,细节在对应章节:

  • 组件即工具(component as tool)。 不发明新协议,直接复用 LLM 原生的 "tool/function calling":一个组件 = 一个 show_component_<Name> 函数,props schema = 函数参数(tool-service.ts:100-122)。前缀常量集中在一处 UI_TOOLNAME_PREFIX = "show_component_"(packages/core/src/ui-tools.ts:1)。→ 见 01
  • 决策循环是可迭代的流。 runDecisionLoop 是个 async generator,吐出 DecisionStreamItem(既含遗留的组件决策、又含 AG-UI 事件),支持连续调用多个 UI 工具(decision-loop-service.ts:115、decision-loop-prompts.ts:14)。→ 见 02
  • 借 AG-UI 做流式语言。 不自造流协议,直接用生态里的 @ag-ui/core 事件类型;累积器把 delta 拼成完整状态(backend / client / react-sdk 三处都依赖 @ag-ui/core)。→ 见 03
  • SSE 而非 WebSocket。 运行接口是普通的 POST /v1/threads/runs,响应是 text/event-stream,每个 AG-UI 事件一行 data: <json>(v1.controller.ts:315、:366)。→ 见 04
  • 可交互组件靠 HOC 包一层。 withTamboInteractable 把普通组件升级成"AI 能反复改状态"的组件(react-sdk/src/v1/index.ts:282)。→ 见 05

4. v1 与遗留:当前 API 边界(读代码前必看)

Tambo 1.0 已发布,v1 是当前唯一对外的 API。这条边界很关键,否则你在 react-sdk/src/providers/ 下会看到一堆同名 provider 而困惑:

  • 对外入口只导出 v1。 react-sdk/src/index.ts:7 只有一行 export * from "./v1/index";凡是从 @tambo-ai/react 能 import 到的,都在 react-sdk/src/v1/index.ts 里(约 300 行的导出清单)。
  • react-sdk/src/providers/ 下的非 v1 provider 是过渡/遗留实现。 它们中一部分被 v1 复用(如 tambo-registry-providertambo-client-provider 被 v1/index.ts:83-89 重新导出),但顶层的 TamboProvideruseTambo 等已经是 v1 版本(来自 ./v1/providers/tambo-v1-provider./hooks/use-tambo-v1,见 v1/index.ts:75、:126)。读代码时以 v1/ 目录为准,v1- 前缀的文件是现役实现。

5. 代码地图(导航索引 · agent 跳转表)

用符号名 grep 比行号更抗漂移;下面每行指向后续章节会深挖的锚点。

主题文件符号
React SDK 唯一对外入口react-sdk/src/index.tsexport * from "./v1/index"
v1 公共 API 清单react-sdk/src/v1/index.tsTamboProvider / useTambo / withTamboInteractable
主 Provider(现役)react-sdk/src/v1/providers/tambo-v1-provider.tsxTamboProvider
组件/工具注册表react-sdk/src/providers/tambo-registry-provider.tsxregisterComponent / TamboRegistryProvider
框架无关内核packages/client/src/tambo-client.tsTamboClient
流式可迭代对象packages/client/src/tambo-stream.tsTamboStream
UI 工具名前缀packages/core/src/ui-tools.tsUI_TOOLNAME_PREFIX / isUiToolName
组件 → 工具 转换packages/backend/src/services/tool/tool-service.tsconvertComponentsToUITools
决策循环入口packages/backend/src/tambo-backend.tscreateTamboBackend / runDecisionLoop
决策循环实现packages/backend/src/services/decision-loop/decision-loop-service.tsrunDecisionLoop / DecisionStreamItem
决策循环 system promptpackages/backend/src/prompt/decision-loop-prompts.tsUI tools 说明(:14)
组件流式追踪packages/backend/src/util/component-streaming.tsCOMPONENT_TOOL_PREFIX / isComponentTool
HTTP / SSE 运行接口apps/api/src/v1/v1.controller.ts@Post("threads/runs")(:315)

想深入某一块,顺着上表的符号名跳进克隆源码;想系统学,按 frontmatter 的 chapters 顺序读 0105