利益相关声明:作者与文中产品有直接的利益相关(开发者、自家产品等)

聊天很适合告诉 Agent“我想做什么”。但当任务涉及时间、空间和相互影响的选择时,与其继续用文字描述操作,不如让 Agent 临时做出一个界面:人直接动手,它在下一轮读懂这些改变。

有一次,我让 Agent 帮我安排一个周六。

上午去西岸美术馆,中间想沿滨江走走,18:30 约了晚餐。花园如果下雨就跳过,但不想来回折返。

第一版文字计划很快就有了。真正麻烦的是之后:入馆想往后挪半小时,餐厅临时换了一家,花园先留着,天气等我需要时再查。

这些都不难,可每改一处,我都要重新写一句话。Agent 再把整条路线重写一遍,我又从头看,看它有没有把 18:30 的晚餐、雨天条件或前面改过的时间弄丢。

我突然觉得,我们把太多力气花在了“描述操作”上。

如果眼前是一张路线,我本来只要拖一下、改一个时间、关掉一个地点。为什么非得先把这些动作翻译成文字?

直接改时间和餐厅,不必把每次操作重新说一遍

这成了 DeepSeek Harness GenUI 的起点。我的想法不是让每个回答都变成网页,而是:当文字不再是最合适的来回方式时,Agent 可以为当前任务做一个界面。

人先用自然语言说目的。Agent 给出必要说明,再把难处理的关系放进一个能操作的页面。人直接在里面选择、输入、拖动和修改。保存后的结果回到当前任务;下一轮只要说“按刚才的安排继续”,Agent 能读到刚才的操作。

界面是 Agent 的表达,操作是人的回应。

页面不是终点

这和“AI 帮我做个网站”看起来很像,差别却发生在页面做完以后。

普通网页生成把页面当成交付物。你拿到页面,任务大致结束。GenUI 里的页面只是当前对话的一部分。它服务于眼前的问题,也把你的操作留给下一轮。

在那条周六路线里,我把入馆时间改成 10:30,把餐厅改成龙华会(滨江店)。页面明确告诉我已经保存。最后我没有把这些变化再说一遍,只问:“按当前行程确认一下。”Agent 读回了 12:30 离馆、18:30 晚餐和新餐厅。

页面操作成为下一轮上下文

我认为这才是整件事的核心。不是 Agent 会不会画一张漂亮卡片,而是人的操作能不能成为它下一轮理解的一部分。

有些回答,本来就应该被操作

并不是问题越复杂,越需要界面。

问一个事实、改一句话、概括一篇文章、列五个建议,文字通常更快。为了显得高级而弹出一套控件,只会让人多走一步。

真正适合界面的,是另一类事情:

一条路线里,地点顺序、时间和天气互相影响;两套户型里,床、桌子、窗户和走道要放在一起看;一个科学关系里,几个量会随着拖动同时变化;一条代码路径跨过多个文件和分支,用户需要看见自己选中了哪一段。

文字擅长说目的和解释结果。界面擅长让人试、比较和直接作出选择。二者不必争谁替代谁。

调用其他工具,但是权限收紧

这个插件生成的页面还有一大特点是,它能调用 Agent 原有的一些工具,比如说,查天气,帮你找 Github 的 PR,亦或是安排你的个人日程。

但是我也做了一个严格的权限系统。

所以只有当我点“检查天气”时,Harness 才会说明页面准备访问哪里、用什么方式、是读取还是写入,以及权限只对当前任务有效。

我第一次点了拒绝。已有路线没有消失,页面也没有把我逼进死路;我可以重试。第二次允许以后,真实降雨结果回来,花园才从路线里被跳过。

页面申请当前任务权限

生成页面只能调用事先声明的 Harness、MCP 或 Skill 工具,或者事先声明、无需凭据的公开 HTTPS 接口。有凭据的能力留在工具一侧,不塞进临时生成的代码里。

不想把创造力锁进一套组件清单

其实现在也有类似的插件,像 Google 的 A2UI,dsh-genui,但他们主要是让 Agent 去拼他们已经写好的组件,填入数据进去。

如果这种界面只能从预设组件树里拼出来,它最后很容易只剩表格、表单和仪表盘。

我选择让 Coding Agent 写普通 React + TypeScript。不是因为每个用户都关心技术栈,而是它直接决定了 Agent 可以怎么表达。

为了验证这一点,我又让它解释季节。请求很普通:“我知道季节不是因为地球离太阳远近,但还是想不明白。给我一个能拖动地球的界面。”

它做出一个轨道模型。地球从夏至拖到春分,南北半球的日照一起变,页面保存我停下的位置。这个例子没有工具数据,也不是效率软件,但它说明了另一件事:界面也可以是解释本身。

界面本身就是很好的解释

同样的机制还可以用在代码上。从终端提出问题,Agent 读真实仓库,返回一个 localhost 上的调用图;用户打开链接,与之交互,点选一条路径,下一轮再问“我选的这条在哪儿停住”,Agent 能接着回答。

终端也能用!
代码解释

这让我更确定,它不该被讲成一个“个人助理页面生成器”。它更像是 Agent 多了一种表达方式,而人也多了一种回答方式。

界面还可以继续长

当前任务里的页面不是一次性的截图。

用户可以用自然语言继续说:“保留我刚改的时间,把拒绝授权后的提示改成中文。”“天气没更新时保留上次结果,但写清楚。”“把跳过花园后的时间线做得更直观些。”

Agent 先读当前状态,再更新同一个应用。之前的时间、餐厅和天气不应该因为一次改版消失;失败的更新也不应该覆盖当前能用的版本。

设计风格也不必每次重说。DESIGN.md 在插件设置里选一次,后面新建的界面默认继承。它规定的是设计语言,而不是页面结构;地图、时间线、模拟器和代码图仍然可以各长各的样子。

人说出目的,Agent 用界面表达;人直接操作,Agent 在下一轮读懂。聊天没有消失,它只是终于不必承担所有交互。

项目已开源(MIT):https://github.com/pengyue-polaron/deepseek-harness-genui