← 返回博客
系统设计

AI Agent 的 21 种交互范式

当 AI 从“回答问题”走向“替你干活”,一个聊天气泡已经装不下它做的事。思考、调用工具、跑命令、等你批准、交出来源——每一步都需要被看见、被理解、被控制。

2026.10.17AI Agent交互设计shadcnuiAI Elements25 分钟
六张 shadcn/ui AI Elements 官方演示截图拼图:推理过程、工具调用、计划、确认审批、引用来源与子智能体

这两年和 AI 打交道越多,我越觉得一个问题被低估了:我们到底应该怎样“看”一个 Agent 工作?

早期的 AI 产品几乎都是一个样子:左边是我的问题,右边是 AI 的回答,一问一答,像发微信。这种形态对“问答”来说足够了。可是当 AI 开始真的替我们干活——读代码、跑命令、改文件、查资料、再派一个子智能体出去调研——问题就来了。

它在想什么?它刚才执行了什么命令?那条命令失败了没有?它引用的资料是哪里来的?它准备删掉一个目录,我能不能先拦一下?

这些问题,聊天气泡回答不了。

10 月 15 日(北京时间),shadcn/ui 发布了两个新组件 Trace 和 Code Block,同时推出了 AI Elements:一套为智能体界面准备的交互范式,一共 21 种。它将取代 Vercel 之前维护的 AI SDK Elements。

我把这 21 种范式在官方文档的在线演示里逐个点了一遍,截下它们在不同状态下的样子。这篇文章想做的,就是把它们一个个拆开来看:它是什么,长什么样,怎么交互,以及它到底解决了用户的什么问题。

聊天气泡,装不下一个会干活的 Agent

先说为什么需要“范式”。

一个 Agent 在一次回复里做的事情,往往远比它最后说的那段话多。以官方 Trace 文档里的演示为例,用户只问了一句“为什么 CI 里 pnpm install 会失败”,Agent 在给出答案之前,先思考了一轮,接着运行了 pnpm --version,又查看了最近一次提交对 package.json 和 pnpm-lock.yaml 的改动,然后尝试 pnpm install --frozen-lockfile 并且失败了,最后引用了两篇 pnpm 官方文档。

如果把这些全塞进一段文字,用户要么看不到过程,只能盲信结论;要么被淹没在大段日志里,找不到重点。

Agent 界面真正要解决的,是“过程”的表达问题。过程要可见,但不能喧宾夺主;要能折叠,也要能随时展开追查;正在进行的要有动静,失败的要一眼看出来,需要人拍板的要停下来等人。

这就是 AI Elements 的出发点。按官方的说法,AI Elements 是“用 shadcn/ui 组件搭出来的智能体界面范式”。它没有需要安装的包,每个范式都是一段组合代码,复制进项目,代码就归你。每个页面都演示了如何从 AI SDK 的消息 part 渲染出这个范式,而且每个页面都有 Markdown 版本,可以直接丢给你的编程 Agent,让它照着加。

一行:Trace 是这套范式的公分母

在拆 21 种范式之前,得先看懂 Trace,因为其中 11 种都是用它搭的。

官方说,他们研究了数百个智能体界面里的组件,把它们的共同点提炼成了一个可以复用的组合。这个共同点很朴素:推理、工具调用、来源、计划、子智能体运行,本质上都是同一种东西——Agent 做了一件事,以及这件事的结果。

所以在 Trace 里,每一步都是“一行”:一个图标,一个标题,可选的描述和状态。

我很喜欢文档里的几条写作约定。比如状态不能只靠颜色和动画表达,标题本身就要说清楚:进行中写现在时“Running pnpm build”,失败写“Failed to run pnpm build”,完成写过去时“Ran pnpm install”,还没开始的计划步骤写祈使句“Run pnpm test”。用户如果开启了“减少动态效果”,shimmer 会停下来,但标题依然说明了正在发生什么。

另一个新组件 Code Block 负责展示这些步骤产生的代码、终端输出、日志和 diff。它有带标题和操作按钮的头部,支持行号、自动换行、diff 和高亮行,还有一个专门用于放进 Trace 的小尺寸。几个细节很能说明它是为 Agent 场景设计的:

Trace 和 Code Block 支持 Base UI、React Aria 和 Radix 三套底层,覆盖全部八种风格。它们和 6 月发布的那批聊天组件——Message Scroller、Message、Bubble、Marker、Attachment、Questionnaire——一起,组成了一个智能体界面的全部零件。

下面进入正题。我把 21 种范式分成五组:对话的骨架、让思考可见、工具与执行、人在回路中的控制、信任与来源。分组是我自己的理解,官方文档是按字母顺序排列的。

对话的骨架

这一组是所有 AI 产品都绕不开的基础设施:线程、单个回合、输入框,以及帮用户“少打字”的两个小部件。

01 Chat:对话线程

Chat 是整个会话的线程。每一个回合是一条 Message,放在 Message Scroller 里,下方的输入框是 Prompt Input。

演示里,空线程顶部是“New Thread”标题和一个重置按钮,中间是空状态提示“What should we build?”。点击发送后,用户的消息成为滚动锚点,停在靠近顶部的位置,Agent 的回复在它下方流式展开:思考、工具调用、Markdown 和代码块依次出现。

Chat 空线程:标题栏、重置按钮与“What should we build?”空状态
Chat 的空状态:标题栏 + 重置按钮,中间提示 What should we build?
Chat 发送后:用户消息贴近顶部,回复在下方流式输出,包含思考、工具调用、Markdown 与代码块
发送之后:用户消息成为滚动锚点,回复在下方流式完成

它解决的问题:流式输出最烦人的体验之一,是页面一边长一边乱跳,或者你往上翻着看历史,它又把你拽回底部。官方的做法是 scrollAnchor 放在用户那一轮上,autoScroll 只在用户停留在最新位置时才跟随回复。Message Scroller 加载历史记录时也不会跳动。你在哪儿读,它就让你留在哪儿。

02 Message:单个回合

Message 是线程中的一个回合。用户的话是右对齐的气泡(Bubble);Agent 的回复是 Markdown,下面跟着一排操作。

Message:右侧用户气泡,左侧 Markdown 回复与带行号的代码块,底部是复制、赞、踩、重试按钮
一个完整的回合:用户气泡、Markdown 回复、代码块,以及底部的操作按钮

操作都是带提示(tooltip)的幽灵图标按钮:复制会把回复写进剪贴板,图标变成对勾两秒;好评和差评是切换按钮,用 aria-pressed 让读屏软件读出状态;重试会重新跑这一轮;用户那一轮上的编辑会把原文放回输入框。回复中的代码块交给 Streamdown 渲染,再路由到 Code Block,于是有了行号和复制按钮。

它解决的问题:回复不是终点。用户需要复制结果、表达满意与否、让它重来一次,或者改一下自己的问题再问。把这些动作固定在每个回合下方,用户不用去想“怎么重来”。

03 Prompt Input:输入框

Prompt Input 是用户给 Agent 发消息的输入区域。它是一个 Input Group:多行文本框、附件按钮、两个模型选择菜单,以及发送按钮。

Prompt Input:多行输入框,左下角附件按钮,右下角模型菜单、推理强度菜单与发送按钮
输入框的四件套:文本、附件、模型与强度、发送

附件按钮会打开一个隐藏的文件选择框,选中的文件以 Attachment 小卡片的形式显示在文字上方,每个都可以移除。键盘上,Enter 发送,Shift+Enter 换行。

它解决的问题:给 Agent 布置任务,往往不只是一句话,还有截图、文档、代码文件,以及“用哪个模型、想多深”的选择。输入框把这些都收在一个地方,发送前一眼就能确认“我交代了什么”。

04 Suggestion:建议提示

Suggestion 是不用打字就能发送的提示。每一个都是一个按钮,按钮上的文字就是要发送的消息,一排放在输入框上方。

Suggestion:输入框上方一排提示按钮,如 Add a dark mode toggle、Fix the failing build,右侧渐隐
放不下时横向滚动,有更多内容的那一侧边缘渐隐

放不下时这一排可以横向滚动,scroll-fade-x 会让还有内容的那一侧边缘渐隐,shrink-0 保证每个标签不折行。

它解决的问题:面对空白输入框,很多人不知道该问什么,也不知道这个 Agent 能做什么。几个现成的提示,既是快捷方式,也是一份无声的“能力说明书”。

05 Model Selector:模型选择器

Model Selector 是两个下拉菜单:一个选 Agent 用哪个模型,另一个选它想得多用力。

Model Selector 模型菜单展开:按 OpenAI、Anthropic 分组,当前选中 GPT-5
模型菜单按提供商分组,勾选当前模型
Model Selector 推理强度菜单展开:Low、Medium、High 三档,当前为 Medium
Effort 菜单:Low / Medium / High

演示里,模型菜单按提供商分组(OpenAI 下有 GPT-5、GPT-5 mini,Anthropic 下有 Claude Sonnet 4.5、Claude Haiku 4.5),当前模型带对勾;Effort 菜单有 Low、Medium、High 三档。选择会随消息一起发送,在服务端路由里映射成模型和 providerOptions,每个提供商只读取属于自己的那部分配置。

它解决的问题:“快而便宜”和“慢而深入”之间,没有一个永远正确的答案。把选择权放在输入框旁边,用户可以按任务的分量随手调整,而不必进设置页。

让思考可见

这一组回答的是:Agent 在想什么,打算怎么做,做到哪一步了?它们都建立在 Trace 上,长得很像,但各自回答的问题不一样。

06 Reasoning:推理过程

Reasoning 是给 Agent 思考过程准备的一行。模型思考时,它显示“Thinking”并自动展开,思考文字流式出现在里面;思考结束后,它变成“Thought”并收起,还可以显示用了多久。

Reasoning 进行中:Thinking 标题闪烁,思考文本流式出现
思考中:Thinking 带 shimmer,自动展开
Reasoning 完成后展开:标题为 Thought for 5s,下方是完整思考文本和最终回答
思考结束:标题变为 Thought for 5s,可随时展开回看

几个细节值得一提。在第一段文字到来之前,它只是一个普通的 TraceLine,因为还没有东西可以展开。思考时长 AI SDK 并不统计,需要在服务端测量后作为消息元数据发过来。如果用户手动展开或收起了它,用户的选择优先,自动行为不会再覆盖。

它解决的问题:思考过程很有价值,但大多数时候用户只想看结论。默认收起、需要时能展开,既保住了透明度,也保住了阅读的清爽。

07 Chain of Thought:思维链

Chain of Thought 是一行摘要,展开后是 Agent 走过的各个步骤。摘要说明发生了什么,比如“Researched in 3 steps”;每一步都是独立的一行,还可以继续展开。

Chain of Thought 进行中:摘要 Researching 闪烁,步骤逐个出现,最后一步 Searching the code 仍在运行
进行中:摘要显示 Researching,最新一步还在运行
Chain of Thought 全部展开:构建日志、网页搜索结果链接、代码搜索命中的文件徽章
全部展开:每一步都能继续展开,看到日志、搜索结果和命中的文件

演示里的三步很有代表性:读构建日志,展开后是一张耗时表(install 41s、compile 38s、images 3m 52s);搜索网页,结果是可以点开的链接;搜索代码,命中的文件以徽章(Badge)列出。步骤的标题时态同样有讲究:进行中写“Searching for…”,完成写“Searched for…”,失败写“Failed to search for…”。摘要的内容加上 keepMounted 后,收起摘要再打开,里面各步骤的展开状态都还在。

它解决的问题:一个调研型的回答,结论之下是一串证据链。思维链让用户可以从结论一路往下追,追到具体是哪一行日志、哪一个网页、哪一个文件支撑了它。

08 Plan:计划

Plan 是 Agent 动手前就定好的步骤清单,比如一次迁移要走的几步。每一步是已完成、进行中或待办,标题统计完成了几步。

Plan 进行中:标题 Plan: migrate to Base UI 2 of 4 done,步骤有完成、进行中、待办三种状态
进行中:2 of 4 done,最后一步仍是灰色的待办
Plan 收起后:只剩一行 Plan: migrate to Base UI 4 of 4 done 和最终结论
完成后收起,只留一行进度和结论

计划作为一个带固定 id 的数据 part 流式发送,AI SDK 会替换同 id 的 part,所以计划是“原地更新”的,而不是每次追加一份新的。

它解决的问题:对于一个长任务,用户最关心的往往不是每一步的细节,而是“还剩多少”。计划一开始就把全貌摊开,等于先和用户对齐了预期。

09 Task:任务

Task 是 Agent 正在做的一件具体工作,比如“找到项目文件”或者“更新页面元数据”。每一个步骤——一次搜索、一次读取、一次编辑——在 Agent 实际做了之后才出现在任务下面。

Task 进行中:Finding the project files 闪烁,下方逐条出现搜索与读取步骤
进行中:标题是现在时,步骤边做边出现
Task 完成后展开:Found the project files 与 Updated the page metadata 两个任务及其步骤
完成后:标题改为过去时,展开可见每一步做了什么

Task 和 Plan 看起来很像,官方专门做了区分:区别在于步骤是什么时候知道的。Plan 的步骤一开始就全部确定,有待办;Task 的步骤来自工作本身,Agent 做完上一步才知道下一步是什么,所以没有待办。Plan 的标题是“目标 + 进度”,Task 的标题是“正在做什么,然后是做了什么”。一次回复里只有一个 Plan,但可以有多个 Task,正在运行的保持展开,做完一个收起一个。

它解决的问题:探索型的工作没法预先列计划,但用户依然需要知道它在干嘛。Task 用“边做边记”的方式,把不可预知的过程变成一份可回看的工作日志。

10 Queue:待办队列

Queue 是 Agent 的 todo 列表,分成“To do”和“Completed”两个可折叠分组,每一项的图标表示状态:空心圆是待办,带点的圆是进行中,对勾是完成。Agent 边做边更新列表,做完的事项会从一组移到另一组。

Queue 进行中:3 to do 与 1 completed 两组,进行中的事项标题闪烁
进行中:完成的事项实时移入 Completed 分组
Queue 收起后:只剩一行 4 completed 与最终结论
全部完成后收起为一行

演示里,Agent 用一个叫 writeTodos 的工具写 todo,每次调用都发送完整列表,所以界面只渲染最后一次调用。进行中那一项的 shimmer 只在聊天仍在流式输出时出现,Agent 停下来,闪烁也就停了。

它解决的问题:Plan 是一份固定的计划,Queue 更像一块随时在变的看板。Agent 中途增删事项、调整顺序,用户都能看到“还剩什么、做完了什么”。

工具与执行

这一组是 Agent 真正“动手”的部分:调用工具、执行命令、跑测试、处理报错、派出子智能体、改动文件。

11 Tool:工具调用

Tool 是 Agent 的一次工具调用,比如运行一条命令或读取一个文件。这一行从输入跟到输出,包括出错的情况和等待批准的情况。

Tool 进行中:前两条命令已完成,第三条 Running pnpm --version 闪烁
运行中:Running … 带 shimmer
Tool 完成:Ran node --version、Ran npm --version,以及红色的 Failed to run pnpm --version 展开显示 command not found
失败的调用标红,展开就能看到错误输出

官方给了一张完整的状态映射表,我觉得是整套文档里最“干”的部分:输入流式中或已就绪时,聊天仍在进行就是“Running …”,聊天停了还没结果就是“Failed to run …”;有输出是“Ran …”;出错是“Failed to run …”;被拒绝是“Denied …”;等待批准时它不是一行,而是放在 Trace 外面的一个带 Approve 和 Deny 按钮的 Item。工具运行时是一行普通的 TraceLine,有了输出才变成可以展开的 TraceCollapsible。还有一个容易踩的坑:在客户端执行的工具,聊天停下后会一直停在 input-available,直到你调用 addToolOutput,这时应该视为“等待中”,而不是“失败”。输出很长时,可以把这一行包进 Sheet 的触发器里,在侧边抽屉里看。

它解决的问题:工具调用是 Agent 和真实世界接触的地方,也是最容易出问题的地方。每一次调用都有名字、有状态、有输出,用户就能判断它到底做了什么,哪里出了错。

12 Terminal:终端命令

Terminal 是 Agent 运行的一条 shell 命令,比如 lint、测试或构建。这一行显示命令本身,运行时输出在下面流式出现。

Terminal 进行中:Running pnpm build,下方终端输出正在流式出现
运行中:第一段输出到达时自动展开
Terminal 完成:Ran pnpm lint、Ran pnpm test、Ran pnpm build,最后一条展开显示构建输出与路由表
完成后:三条命令都是 Ran …,最后一条展开显示构建结果

退出码 0 显示为“Ran pnpm build”;非 0 就是失败,标题写成“pnpm lint exited with code 1”。第一段输出到达时这一行自动展开,之后展开还是收起交给用户。技术上有个细节:工具结果要等命令退出才会到达,所以想边跑边看,需要在工具里把输出作为数据 part、用工具调用的 id 写出去,AI SDK 会替换同 id 的 part,输出就在原地不断变长。

它解决的问题:一次构建可能要跑几十秒。如果界面在这段时间里什么都不显示,用户只能干等,甚至怀疑它卡住了。实时滚动的终端输出,就是最好的“进度条”。

13 Test Results:测试结果

Test Results 是 Agent 跑的一次测试。摘要行统计通过和失败的数量,展开后可以看到每个测试套件、其中的测试,以及每个失败的错误信息。

Test Results 展开:Ran 5 tests, 1 failed 标红,按文件分组的套件,失败用例展开显示断言错误与位置
有失败时摘要标红;失败的套件默认展开,失败用例可继续展开看断言

测试按文件分组,每个套件是一行可折叠的 Trace;有失败的套件默认展开。演示里,失败用例 “retries a declined card” 展开后是断言错误“Expected 2 charge attempts, received 1”和出错位置。

它解决的问题:测试结果最重要的信息是“哪里挂了”。通过的折起来,失败的摊开,用户和 Agent 的注意力都被引到真正要修的地方。

14 Stack Trace:堆栈追踪

Stack Trace 是一次失败的工具调用。错误本身就是标题,比如“Failed: TypeError”;展开后是堆栈帧,可以链接到具体的文件和行号。

Stack Trace 展开:红色 Failed: TypeError 标题,完整错误信息,可点击的自身代码帧,以及展开的 4 framework frames
标题被截断,所以完整错误在内容顶部重复一次;框架帧单独折叠

因为标题会被截断,完整的错误信息要在内容顶部再写一次。来自 node_modules 的帧保持弱化,自己代码的帧可以点击跳到文件对应的行,框架帧则折叠成单独一行(演示里是“4 framework frames”),让你能修的那几帧排在最前面。默认情况下 AI SDK 的 errorText 只有错误消息,要看到堆栈,需要在 onError 里返回 error.stack;由于堆栈里有服务器上的文件路径,官方提醒只在开发环境发送。

它解决的问题:报错信息对开发者来说是线索,对界面来说却常常是噪音。Stack Trace 把“信号”和“噪音”分了层:先告诉你错在哪,再给你通往代码的路,最后才是框架内部的细节。

15 Subagent:子智能体

Subagent 是 Agent 交给子智能体去做的一份工作。这次运行本身就是标题,比如“Ran the research subagent”;展开后是子智能体调用过的工具,以及它的发现。

Subagent 进行中:Running the research subagent 闪烁,嵌套的子工具调用逐条出现
运行中:嵌套的工具调用随子智能体的进展出现
Subagent 全部展开:三个子工具调用各自展开显示输出,最后是子智能体的结论
两层嵌套:子智能体 → 它的工具调用 → 每次调用的输出

运行中这一行是 running 状态,内容里显示到目前为止的工具调用,子智能体结束后再补上结果。官方还建议在内容顶部写明交给它的任务,用 Badge 标出它用的模型和工具,在标题后用 TraceDescription 显示运行时长。在 AI SDK 里,子智能体就是一个工具,它的 execute 在流式过程中不断产出子智能体的 UIMessage,这些中间产出带着 preliminary: true,所以在显示“Ran”之前要先确认它不是中间态。

它解决的问题:多智能体协作越来越常见,但主 Agent 把活派出去之后,用户很容易失去对“谁在做什么”的感知。Subagent 用嵌套把委派关系画了出来:外层是“谁去做了”,里层是“它具体做了什么”。

16 File Tree:文件树

File Tree 是 Agent 改动过的文件,以可展开的文件夹树呈现。文件夹是 Collapsible,文件是按钮。

File Tree:app、components、ui 等文件夹展开,文件可点击,当前选中 button.tsx
文件夹可折叠,文件可点击;演示中默认全部展开

官方特别说明:如果只是 Agent 读取或编辑的单个文件,用 Tool 那样的一行就够了,文件树是给“改了一批文件”的场景准备的。

它解决的问题:Agent 一口气改了十几个文件,平铺的列表很难看出它动了哪些模块。按目录组织,改动的范围和结构一目了然,也方便逐个点开审查。

人在回路中的控制

前面三组讲的是“让人看见”,这一组讲的是“让人能管”。Agent 越能干,人的控制感就越重要:关键操作要我批准,走错了要能退回去,资源用了多少要心里有数。

17 Confirmation:确认审批

Confirmation 在工具运行之前,向用户要一个“是”或“否”。问题是一个带 Deny 和 Approve 两个按钮的 Item;用户回答后,这次调用就变回一行 Tool。

Confirmation 待审批:卡片标题 Run rm -rf dist?,说明 The command runs in this project.,右侧 Deny 与 Approve 按钮
待审批:命令、说明和两个按钮,Agent 停在这里等你
Confirmation 批准之后:卡片变为 Ran rm -rf dist 工具行,下方是 Removed the dist folder.
批准之后:审批卡片变回一行普通的工具记录

演示里的命令是 rm -rf dist,一个典型的“删了就回不来”的操作。批准后,工具输出流式出现;拒绝则变成 output-denied,显示为“Denied …”。在 AI SDK 里,给 useChat 传入 sendAutomaticallyWhen: lastAssistantMessageIsCompleteWithApprovalResponses,所有审批都有了答复后,对话会自动继续。

我觉得这里有一个很漂亮的设计判断:待审批的请求是在问人,而不是 Agent 做过的一步,所以它不放在 Trace 里。它在视觉上和步骤列表区分开,就是在告诉用户:这件事需要你。

它解决的问题:把不可逆的操作交给 AI,人最需要的是一道闸门。Confirmation 让 Agent 在危险操作前停下来,把决定权交还给人。

18 Checkpoint:检查点

Checkpoint 是对话中一个可以回到的点。它是放在某一回合之后的一条 Marker(分隔标记),带一个 Restore 按钮。

Checkpoint:回合之后一条写着 Button renamed 的分隔线,旁边是 Restore 按钮,下方还有后续对话
回合之后的检查点,旁边是 Restore
Checkpoint 恢复之后:只保留到 Button renamed 这一回合,后续消息被移除
点击 Restore 之后:该回合之后的所有消息都被移除

点击 Restore,会保留这一回合,删除它之后的所有消息。然后发一条新消息,就从这里重新开始。

它解决的问题:和 Agent 协作,最怕的是“越改越歪”。检查点给了用户一颗后悔药:不满意后面的走向,就回到上一个确定的状态,换个方向再来。

19 Context:上下文用量

Context 显示这段对话已经用掉了多少模型上下文窗口。它是一个悬停卡片(Hover Card)加一个进度条。

Context 悬停展开:胶囊按钮 8% context,卡片显示 10.7k / 128k、进度条,以及 Input、Output、Reasoning 的分项 token 数
平时只是一颗写着 8% context 的胶囊,悬停才展开明细

演示里,胶囊上写着“8% context”;悬停后,卡片显示已用和上限(10.7k / 128k)、进度条,以及 Input 8.4k、Output 1.3k、Reasoning 980 的分项。用量从 Agent 消息的元数据里读取,在流式结束时写入;上下文上限 AI SDK 不会告诉你,需要按你用的模型自己设置。

它解决的问题:上下文窗口是 Agent 的“工作记忆”,满了就会出错,或者开始遗忘。把这个看不见的预算变成一个百分比,用户就知道什么时候该开一个新对话,什么时候该让它先总结一下。

信任与来源

最后一组只有两个,但我认为它们决定了用户敢不敢相信 Agent 说的话。

20 Sources:引用来源

Sources 是一行汇总,列出 Agent 在这次回复里用到的链接。它先说有几个,比如“Used 3 sources”,展开后每个来源是一个链接。

Sources 展开:Used 3 sources 下列出 Install Astro | docs.astro.build、create-astro | npmjs.com、pnpm create | pnpm.io 三个链接
收起时是一行计数,展开是“标题 | 域名”的链接列表,带外链箭头

链接在新标签页打开,为此要加一段只给读屏软件看的“(opens in a new tab)”;箭头图标是装饰,链接的名字是标题。同一个页面可能被引用多次,所以要按 url 去重;source-url part 的标题是可选的,没有就退回显示域名。官方还特别点出:触发行里的计数,让人在点开之前就知道里面有什么。

它解决的问题:没有出处的答案,只能选择信或不信。有了来源列表,用户可以自己去核实,Agent 的回答才从“断言”变成“有据可查的结论”。

21 Inline Citation:行内引用

Inline Citation 是嵌在句子里的来源,就放在它所支撑的那句话旁边。它是一个按钮加一个悬停卡片。

Inline Citation 悬停:句末 nextjs.org 小胶囊上方弹出卡片,显示 Linking and Navigating 标题、简介与域名
句末的域名胶囊,悬停弹出页面标题、简介和域名

演示里,每句话末尾跟着一个域名小胶囊(nextjs.org、react.dev、developer.mozilla.org……),悬停就弹出卡片,显示页面标题、简介和域名。数据同样来自 source-url part,在 toUIMessageStreamResponse() 上设置 sendSources: true 即可。如果想在回复后面统一列出来源,官方建议用上面的 Sources。

它解决的问题:Sources 回答的是“这篇回答参考了什么”,Inline Citation 回答的是“这一句话凭什么这么说”。粒度越细,核实的成本越低,信任也就越具体。

写给已经在用旧版的人

如果你之前用过 Vercel 的 AI SDK Elements(elements.ai-sdk.dev),有几件事值得知道。

shadcn/ui 的 AI Elements 将取代 AI SDK Elements。Vercel 在 AI SDK Elements 的仓库说明里写明,这个项目将在 2026 年 11 月底被弃用,新项目应改用 shadcn/ui 的版本。

但你不需要马上迁移。当初从 AI SDK Elements 安装的组件,代码本来就复制进了你的项目,它们会继续工作。准备好之后,每个范式页面都有一段迁移提示词,粘贴给你的编程 Agent,它会在 components/ai-elements 里基于 Trace、Code Block 和其他 shadcn/ui 组件重建这个封装,每个导出的名字和 props 都保持不变,用到它的代码不用改。

也有一些旧元素没有被重建,比如 artifact、canvas 一系列节点组件、web-preview、语音输入等。官方的理由很坦率:看过使用频率,数字很低,而且它们都能用现有的 shadcn/ui 组件简单拼出来。确实需要的话,可以去 GitHub 提 issue,官方表示会帮忙一起搭。

结语:界面,是人和 Agent 之间的契约

把这 21 种范式看完,我最大的感受是:它们的价值不在于“好看”,而在于把一种新的人机关系固定成了可以复用的形状。

过去的软件,界面展示的是“结果”:一张表、一份报告、一个按钮按下去之后的状态。而 Agent 的界面,要展示的是“过程”和“意图”:它在想什么,打算怎么做,正在做什么,哪里出了问题,什么时候需要我。

回头看这五组范式,其实对应着人和 Agent 协作时的五个基本诉求:

而 Trace 那个看似朴素的“一行”,其实是整件事的关键:当每一步都有同样的形状,用户只需要学会读一次,就能读懂 Agent 做的所有事。这和我们设计好的工作流是同一个道理——规则统一了,人的注意力才能留给真正需要判断的地方。

在我看来,未来的 AI 产品,竞争的可能不只是模型有多聪明,还有它能不能让人放心地把事情交出去。而“放心”这两个字,很大一部分,是由界面写成的。

参考链接

文中截图均来自 ui.shadcn.com 官方文档的在线演示(Base UI 版本、浅色模式),采集于 2026 年 10 月 17 日。