1. 从“点按钮”到“说意图”:Agentic 界面到底在解决什么问题
过去十几年,我们做交互设计基本围绕一个默认前提:用户知道自己要什么,并且愿意一步步操作。想订机票,就打开 App,选出发地、选目的地、选日期、选舱位、填乘机人、支付。每一步都是一个明确的按钮或表单,用户点一下,系统响应一下。这套范式在移动互联网时代被磨得极其成熟,成熟到我们几乎以为它会一直这样下去。
但大模型进来之后,事情变了。用户开始期望“我说一句话,你把事办了”。不是给我一堆筛选条件让我自己挑,而是直接告诉我“下周三去杭州,帮我订个早上到的航班,靠窗”。这时候如果界面还是弹出一个日期选择器加一个舱位下拉框,体验就断裂了。Agentic 界面要解决的,正是这个断裂——让界面从“等待指令的工具”变成“理解意图并主动推进的代理”。
我把它拆成三个层次来理解。第一层是意图理解,用户输入的是自然语言、模糊的、带上下文的,系统得能接住。第二层是任务编排,一个意图背后往往对应多个子任务,比如“订机票”背后有查航班、比价格、选座位、填信息、支付,Agent 要能自己拆解并串联。第三层是信任校准,这是最容易被忽略但最致命的——Agent 越主动,用户越慌。它凭什么替我做决定?它会不会乱花钱?我能不能随时叫停?这三个层次缺一个,Agentic 界面就立不住。
所以这篇文章不是讲怎么调 API,而是讲我在实际做 AI Native UX 探索时,对 Agentic 界面模式和实践的拆解。适合谁看?如果你正在做 AI 产品的交互设计、前端实现,或者你是一个想理解“下一代界面长什么样”的产品经理,这里的东西应该能直接拿去用。我会尽量说人话,把每个模式背后的“为什么”讲清楚,而不是甩一堆术语。
2. 核心模式拆解:Agentic 界面的四种交互骨架
2.1 对话式主界面:不是聊天框,是任务流容器
很多人一提到 Agentic 界面,第一反应就是“加个聊天框”。我一开始也这么干过,结果发现纯聊天框有个致命问题:它把所有的状态都藏在对话历史里,用户翻两屏就找不到刚才那个航班选项了。聊天框适合表达意图,但不适合承载任务状态。
我的做法是把对话作为意图输入层,但任务状态用卡片流来呈现。用户说“帮我订下周三去杭州的机票”,对话区出现一条用户消息,紧接着下面不是 Agent 的文字回复,而是一张“航班搜索卡片”,里面列出三个选项,每个选项有价格、时间、航司。用户可以直接点选,也可以继续说“第二个太早了,有没有十点以后的”。这时候卡片会刷新,而不是在对话里再堆一条文字。
这个模式的关键在于:对话负责模糊输入,卡片负责精确操作。两者是互补的,不是替代关系。我试过纯卡片,用户不知道怎么表达复杂意图;也试过纯对话,用户找不到操作入口。混合之后,任务完成率明显上来了。
注意:卡片流不要做成无限滚动。Agentic 界面的卡片应该是“当前任务上下文”的切片,任务结束就归档。否则用户会陷入“我到底在哪个任务里”的混乱。
2.2 生成式 UI:界面本身也是模型输出的一部分
这是我觉得最兴奋也最危险的方向。传统 UI 是设计师画好的,所有状态都是预设的。生成式 UI 的意思是,界面结构本身由模型根据当前任务动态生成。比如用户说“帮我分析一下上个月的销售数据”,模型不只是返回一段文字,而是直接生成一个包含折线图、筛选器、数据表格的界面。
我实测下来,生成式 UI 在探索型任务里特别香。因为探索型任务的需求边界模糊,用户自己也不知道要看什么,预设界面往往覆盖不全。但它在高频重复任务里就是灾难——每次都要重新生成,延迟高,而且用户会失去肌肉记忆。
所以我的策略是:高频路径固化,长尾路径生成。比如“查看今日订单”这种每天要看十次的操作,直接给固定入口。但“对比一下华东和华南上季度的退货率差异”这种低频复杂查询,就让模型生成一个临时分析面板。这样既保住了效率,又覆盖了长尾。
实现上,我一般让模型输出一个结构化的 UI Schema,比如 JSON 描述组件树,前端再渲染。这样比让模型直接吐 HTML 可控得多,也方便做安全过滤。
2.3 主动式建议:Agent 什么时候该开口
Agentic 界面和传统界面的另一个大区别是:传统界面等用户操作,Agentic 界面会主动说话。但主动说话是有代价的,说多了就是骚扰。我踩过的坑是:早期版本里 Agent 会在用户每次输入后都弹一个“我建议你……”的气泡,结果用户反馈“像有个销售在旁边盯着”。
后来我定了一个主动建议的三条触发规则,实测下来比较稳:
- 置信度高且后果低:比如用户输入“明天天气”,Agent 直接显示天气卡片,不需要问“你是要查天气吗”。这种低风险高确定性的,直接做。
- 置信度中等但可撤销:比如用户说“帮我订个会议室”,Agent 可以自动选一个空闲的并显示“已为你预订 A301,点击可更换”。因为可撤销,用户不会觉得被绑架。
- 置信度低或后果高:比如涉及支付、删除、发送给外部人员,Agent 必须停下来确认。这时候不是弹窗,而是在任务流里插入一个“确认卡片”,让用户点一下。
这套规则的核心是用可撤销性换主动性。Agent 越主动,用户越需要知道“我能反悔”。如果反悔成本高,那就别主动。
2.4 信任校准:让用户知道 Agent 的“能力边界”
信任校准这个词听起来学术,其实很简单:用户得知道 Agent 什么时候靠谱,什么时候不靠谱。我见过太多产品,Agent 明明不确定,却用非常肯定的语气输出,结果用户信了,出错了,信任直接崩盘。
我的做法是在界面上做置信度可视化。不是显示一个百分比数字,那太工程师思维了。而是用语言和视觉来区分:
- 高置信:直接陈述,“你的航班是 CA1234,明早 8 点起飞”。
- 中置信:带限定词,“我找到几个选项,其中这个比较符合你的时间偏好”。
- 低置信:明确求助,“我不太确定你要的是哪个,能再说一下吗?”
视觉上,高置信用实心卡片,中置信用带虚线边框的卡片,低置信用浅色背景加一个问号图标。用户不需要理解“置信度”这个概念,但能感觉到“这个答案的确定程度不一样”。
实操心得:置信度阈值不要拍脑袋定。我一般会跑一个小的标注集,让模型输出置信度,然后人工标正确/错误,画一条 ROC 曲线,找到那个“宁可多问一句也不要出错”的截断点。不同任务类型阈值不一样,支付类任务阈值要拉到 0.95 以上,查询类 0.7 就够了。
3. 实操落地:从零搭一个 Agentic 界面的关键步骤
3.1 任务建模:先把“意图-任务-操作”三层拆清楚
在写任何代码之前,我会先做一件事:把目标场景里的用户意图列出来,然后拆成任务,再拆成操作。这个拆解决定了后面 Agent 的编排逻辑和界面的卡片类型。
拿“订机票”举例:
| 层级 | 内容 | 对应界面元素 |
|---|---|---|
| 意图 | 下周三去杭州 | 对话输入框 |
| 任务 | 搜索航班、筛选、选座、填信息、支付 | 任务卡片流 |
| 操作 | 点击选项、输入乘机人、确认支付 | 卡片内交互控件 |
拆完之后你会发现,真正需要 Agent 自主决策的是“任务”层——怎么拆、按什么顺序、遇到分支怎么选。而“操作”层其实还是传统 UI 的活,按钮、输入框、下拉菜单,该用还得用。Agentic 不是把 UI 干掉,而是把 UI 重新组织在任务流里。
我一般会用一张状态机图来描述任务流转,但这里不画图,用文字说:搜索完成后进入“待选择”状态,用户选择后进入“待填写”状态,填写完成后进入“待支付”状态,支付完成进入“已完成”状态。每个状态对应一张卡片,状态之间的转移由用户操作或 Agent 建议触发。这个状态机是后面所有实现的基础,没它就会乱。
3.2 意图路由:怎么判断用户这句话该走哪条路
用户输入“下周三去杭州”,系统得知道这是订机票,不是订酒店,也不是查天气。我一般用两层路由:
第一层是规则匹配,用关键词和正则快速过滤。比如包含“机票”“航班”“飞”就进机票意图,包含“酒店”“住”就进酒店意图。这层覆盖 60% 到 70% 的常见表达,速度快,成本低。
第二层是模型分类,规则没命中的走模型。我会用一个小的分类模型,输入用户原话,输出意图标签和置信度。置信度低于阈值的,不猜,直接问“你是想订机票还是订酒店?”
这里有个坑:不要用大模型做第一层路由。我试过全部走大模型,延迟从 200ms 涨到 2s,用户体感差很多。规则能解决的,别上模型。
3.3 卡片渲染:用 Schema 驱动,别硬编码
Agentic 界面的卡片类型会随着任务扩展不断增加,如果每加一种卡片就写一个前端组件,维护成本会爆炸。我的做法是定义一套UI Schema,模型输出 Schema,前端有一个通用渲染器。
Schema 大概长这样:
{ "type": "flight_option_list", "title": "为你找到 3 个航班", "items": [ { "id": "CA1234", "airline": "国航", "depart": "08:00", "arrive": "10:15", "price": 680, "actions": [ {"label": "选择", "action": "select_flight", "payload": "CA1234"} ] } ] }前端渲染器根据type找对应的组件模板,把items填进去。这样新增卡片类型只需要加一个模板,不用动渲染逻辑。模型那边也只需要按 Schema 输出,不用关心前端怎么画。
注意:Schema 里不要放任何可执行代码。我见过有人让模型输出 JS 表达式来做动态计算,这是安全噩梦。所有计算逻辑放在前端或后端,Schema 只描述结构和数据。
3.4 状态同步:对话历史和任务状态怎么保持一致
这是实现上最容易出 bug 的地方。用户可能在对话里说“第二个”,也可能直接点卡片上的“选择”按钮。两条路径都得更新同一个任务状态。
我的方案是单一数据源:任务状态存在一个 store 里,对话消息和卡片操作都是对这个 store 的 action。对话解析出“第二个”之后,映射成select_flightaction,和点按钮走同一个 reducer。这样不管用户从哪进,状态变更逻辑只有一份。
另外,对话历史里要记录“当时展示了哪些选项”,否则用户说“第二个”的时候,如果卡片已经刷新了,就不知道指的是哪个。我一般会在消息里存一个context_snapshot,记录当前可见的选项 ID 列表。
4. 常见问题与排查技巧实录
4.1 Agent 过度主动,用户觉得被冒犯
现象:Agent 在用户还没说完的时候就抢答,或者频繁弹建议。
排查:先看触发规则是不是太宽。我早期设的是“只要意图置信度大于 0.6 就主动”,后来发现 0.6 太低了,很多模糊输入被误判。调到 0.8 之后好很多。另外加一个冷却时间,同一个任务里 Agent 主动建议不超过两次,除非用户明确要求。
解决:把主动建议做成可关闭的开关,默认开启但用户能关。别小看这个开关,它给了用户控制感,反而让用户更愿意留着它。
4.2 生成式 UI 渲染慢,用户等得焦躁
现象:用户输入后,界面空白 2 到 3 秒才出现卡片。
排查:看模型输出 Schema 的 token 数。我测过,一个复杂分析面板的 Schema 可能有 800 到 1000 token,生成时间确实长。
解决:分两步渲染。先输出一个骨架 Schema,比如“标题 + 加载占位”,前端立刻渲染出来,让用户知道系统在干活。然后模型继续输出完整 Schema,前端做增量更新。这样感知延迟从 2s 降到 300ms 左右。
4.3 用户不知道 Agent 能做什么
现象:用户进来之后不知道说什么,或者只问一些简单问题。
排查:这是能力可见性问题。Agent 的能力如果只藏在文档里,用户不会去翻。
解决:在对话输入框下面放一排建议 chip,比如“订机票”“查订单”“分析数据”。用户点一下就直接填入输入框。另外在 Agent 回复里偶尔带一句“你也可以试试让我……”,但别每句都带,会烦。
4.4 多轮对话后上下文丢失
现象:用户说“那第二个呢”,Agent 回“什么第二个?”
排查:看上下文窗口是不是超了,或者任务状态有没有被重置。
解决:我会把当前任务的关键实体(航班号、日期、乘客数)抽出来存成一个task_context,不依赖对话历史。每轮对话都把task_context注入 prompt。这样即使对话历史被截断,核心信息还在。
4.5 常见问题速查表
| 问题 | 可能原因 | 快速修复 |
|---|---|---|
| Agent 答非所问 | 意图路由错误 | 检查规则匹配,调低模型分类阈值 |
| 卡片不刷新 | 状态未同步 | 检查 action 是否走同一 reducer |
| 用户找不到操作入口 | 卡片流太长 | 限制当前任务卡片数,归档旧卡片 |
| 信任度低 | 置信度表达不清 | 加限定词和视觉区分 |
| 响应慢 | Schema 太大 | 分步渲染,先骨架后内容 |
5. 信任校准的进阶实践:让 Agent 学会“认怂”
信任校准不是一次性设计,而是一个持续的过程。我后来发现,最有效的信任建立方式不是让 Agent 显得多聪明,而是让它在该认怂的时候认怂。
具体怎么做?我在 Agent 的输出里加了一个不确定性表达层。当模型内部置信度低于阈值时,不是直接输出答案,而是输出一个“我不确定”的模板。比如用户问“帮我订明天最便宜的航班”,如果模型不确定“最便宜”是指含税还是不含税,它会回:“我找到几个选项,价格从低到高排列。不过我不确定你说的‘最便宜’是否包含税费,需要我按含税价重新排吗?”
这句话看起来啰嗦,但用户反馈很好。因为它把决策权交还给了用户,而不是替用户猜。Agentic 界面的终极目标不是让 Agent 替用户做所有决定,而是让 Agent 把用户从繁琐操作里解放出来,同时在关键决策点上保留用户的控制权。
另一个实践是操作预览。在 Agent 准备执行一个不可逆操作之前,比如发送邮件、提交订单,界面会显示一个“即将执行”的卡片,列出 Agent 打算做什么,用户点“确认”才执行。这个卡片不是弹窗,是任务流里的一步。用户看得到上下文,不会觉得被打断。
实操心得:预览卡片里的文字要用第一人称,比如“我将为你预订 CA1234,明早 8 点起飞,价格 680 元”。用“我将”比“系统将”更有代理感,用户更容易理解这是 Agent 在做事,而不是系统在弹窗。
6. 我踩过的三个大坑和对应的解法
第一个坑是把 Agent 当万能接口。早期我试图让一个 Agent 处理所有意图,结果 prompt 越来越长,准确率越来越低。后来拆成多个专职 Agent,每个负责一个领域,用一个路由层分发。准确率上来了,维护也简单了。
第二个坑是忽略空状态。用户第一次进来,对话历史是空的,卡片区也是空的。我一开始没设计空状态,用户看到一片空白,不知道干嘛。后来加了一个引导卡片,写着“试试对我说:帮我订下周三去杭州的机票”,点击直接填入。空状态转化率提升了三倍。
第三个坑是置信度阈值一刀切。所有任务用同一个阈值,结果查询类任务太保守,支付类任务太激进。后来按任务类型分了四档:查询 0.6,建议 0.75,操作 0.85,支付 0.95。每档都跑标注集验证过,心里有底。
7. 后续可以扩展的方向
这套模式跑通之后,我发现有几个方向值得继续挖。一个是多 Agent 协作,比如订机票的 Agent 和订酒店的 Agent 能互相沟通,用户说“帮我安排下周三去杭州的行程”,两个 Agent 自己协调时间和预算。另一个是跨会话记忆,用户这次订了靠窗,下次 Agent 主动问“还是靠窗吗”。这些都不难实现,难的是信任校准——Agent 记得越多,用户越需要知道“它记得什么”和“怎么让它忘掉”。
我目前在做的是把信任校准做成一个可配置的模块,不同产品可以调不同的保守程度。比如企业内部工具可以激进一点,消费级产品保守一点。这个模块还在迭代,等稳定了再单独写一篇。
最后分享一个小技巧:如果你刚开始做 Agentic 界面,别一上来就搞生成式 UI。先从对话加固定卡片开始,把意图路由和状态同步跑通,再逐步引入动态生成。我见过太多团队一上来就追求“全动态”,结果连基本的任务完成率都保不住。先把确定性的部分做扎实,再让模型去处理不确定的部分,这个顺序不能反。