对话辅助填表
用户在左侧说“申请两台云服务器,地域选北京”,右侧表单自动填入数量和地域。用户可以继续对话,也可以直接修改表单,检查后再确认提交。
这项功能不依赖 OpenAI,也不限定某一种 Agent。 ChatKit 显示对话,业务应用负责表单,Agent 提出修改。需要接通的是“修改请求”和“执行结果”的往返。
先点击 Demo 的第一条推荐问题,看右侧字段发生什么变化。本例用本地规则模拟 Agent,没有连接真实模型或业务后端;“确认提交(本地)”不会创建真实资源。
窄屏下对话与表单上下排列,可在预览中滚动;也可以打开全屏。完整源码与预览一致,下载工程时同时下载旁边的本地 SDK。
先看一遍完整流程
- 用户说需求:“两台服务器,地域选北京。”
- Agent 提出修改:让应用把数量改为 2,地域改为北京。
- 应用执行:检查字段和当前表单版本,更新草稿,右侧显示新值。
- 应用告知结果:把“填写成功”或“未能填写及原因”返回给 Agent。
- Agent 继续:成功时说明已填哪些内容;失败时解释原因或让用户补充信息。
第 4 步不可省略。 右侧界面变了,只能说明应用里的表单状态变了;Agent 收到执行结果后,才知道这次修改是否成功。填写草稿成功和提交业务单据成功也要分别告知。
谁负责什么
功能、工具和协议是什么关系
这三个词说的是不同的事情:
协议不决定用户的表单长什么样,也不等于这项功能。 同一套填表功能可以接不同 Agent,但接入代码需要适配它们传请求、收结果的方式。就像同一个表单能连接不同的业务接口,页面功能相同,请求参数和返回格式可能不同。
前面提到 OpenAI,只是因为当前仓库有一个现成适配器支持“在浏览器执行工具并回传结果”。它是可选接法,不是填表功能的前提。业务已经有 Agent 后端时,直接对接该后端提供的工具调用或人工交互接口,无需为了这个功能换模型或后端。
Agent 如何知道该调用前端
应用先把可用动作的名称、用途和允许的参数告诉 Agent。Agent 返回工具名称和参数后,应用根据名称找到执行函数。这个函数可以在前端更新表单,也可以调用后端接口;执行位置由应用决定,Agent 不需要查找 DOM 或 React 组件。
在本例中,“更新表单草稿”对应的是 store.apply(...)。正文里的“已填好”只是解释;表单的实际变化来自这个执行函数。
调用闭环:前端工具与 HITL
HITL(Human-in-the-loop)就是流程中需要人来决定或补充信息。它与自动工具的共同点是:Agent 发出请求,等待结果,收到结果后继续。
例如,“Agent 建议买两台,用户可以改成三台,再点确认”,回传的应是用户最终确认的三台,而不是 Agent 原先建议的两台。取消、拒绝或填写失败也要明确回传,让 Agent 知道该怎样继续。
当前 Demo 做到了哪一步
当前 Demo 的“确认提交(本地)”没有让真实 Agent 等待或继续。 它只是改变页面内存状态。生产如果要求点确认后 Agent 继续,就需要把该按钮的处理结果接到 Agent 的结果接收接口。
接入 SOP
1. 由应用管理右侧表单
把聊天区和表单放在同一个业务页面,表单只保存一份草稿。用户手动编辑和 Agent 修改都更新这份草稿。
本例 form-assist.tsx 负责布局和表单组件,form-assist-store.ts 保存字段与版本。每次修改递增版本,避免较早的 Agent 结果覆盖用户的新修改。
2. 发送时告诉 Agent 当前表单内容
onSend 读取最新草稿,合并到输入的 metadata。本例的业务数据结构为:
这段数据表达“当前是哪张表、哪个版本、有哪些值”。它由业务定义,不是 SDK 内置的表单类型。接真实后端时,还要让适配器把这些信息放到该后端实际读取的位置;只给前端加 metadata,Agent 不会自动知道。
3. 接收修改请求,校验后执行
应用收到工具名称和字段修改后,调用对应的草稿更新函数。这里负责检查:表单标识是否匹配、字段是否允许修改、数量和地域是否有效、版本是否还是发送时的版本。
本例 form-assist-adapter.ts 用 plan() 的固定规则模拟修改请求:只识别数量、北京/上海/广州和“用途:…”等输入,等待两秒后调用 store.apply(...)。无法识别时给提示,不修改表单。生产用真实 Agent 的请求替换这一步,并在业务服务端执行权限与数据校验。
4. 把执行结果交回 Agent
本例草稿服务返回:
应用应把结果关联到原来的那次修改请求再送回 Agent,不能只画一张“成功”卡片。发生冲突时回传 applied: false、原因和当前版本,保留用户的新值。实际接入可以返回校验后的完整字段,方便 Agent 理解最终表单。
当前本地 Demo 直接用该结果更新聊天回执,并按固定规则生成后续文字;此处没有真实 Agent 的结果回传请求。换成真实服务时,需要补上接收修改请求和返回结果这两个连接点。聊天回执渲染和 onEvent 埋点不能代替这个连接。
5. 如果必须人工确认,就把回传放到确认之后
Agent 提出建议后,应用先展示待确认内容。用户确认或修改后,重新校验当前表单,再回传用户决定和真实执行结果;拒绝、取消和超时也需要结束对应等待。
本地 Demo 的确认按钮只检查必填项并锁定表单。生产中的提交、持久化、等待恢复和重复执行处理由业务服务负责。更新草稿不能自动代表已经创建资源。
验证结果
常见问题
- 工具显示成功,表单没变:检查业务执行函数是否真的更新了草稿,以及页面是否订阅正确的表单。聊天展示不会代替业务写入。
- 表单变了,Agent 不知道:检查是否把执行结果交回对应请求;
setState、画回执和更新metadata都不会自动发送工具结果。 - 总提示版本冲突:重新读取最新草稿后再发起,不重试旧补丁。本例整次拒绝,不自动合并字段冲突。
- 换会话后写错表单:每个请求要绑定正确的会话和表单。本例固定一个会话,不演示多会话目录。
- 刷新后数据消失:本例只在内存中。生产应恢复草稿和聊天历史,恢复显示时不能重新执行业务写入。
- 需要动态表单或撤销:字段定义、校验、修改记录和撤销接口由业务应用提供,不属于本例的内置功能。
开发参考:不同后端如何接入
先完成上面的业务流程,再根据自己已经使用的 Agent 后端选择下面的接法。
展开:当前本地适配器的相关能力与调用时序
查看技术调用时序大图。实线表示请求,虚线表示结果;等待是 Agent 的逻辑状态,不要求一个 HTTP 请求始终保持连接。
- 业务后端运行完整 Agent:需要提供向浏览器发工具请求、接收执行结果、恢复任务的通道。应用按工具名称路由到允许执行的函数,并回传原请求标识。仅在聊天流中看到工具片段,不表示这些通道已经接好。
- 直接接 OpenAI 兼容模型接口:当前
createOpenAiAdapter({ tools })可以按名称执行tools[name].execute,把返回值交回对应工具调用,再请求模型继续。这只是现成实现之一;执行函数、参数校验、业务操作、鉴权和请求代理仍由业务提供。 - 工具中等待用户确认:浏览器工具循环可以让
execute返回等待用户操作的 Promise,再用用户决定作为结果。需要处理取消和页面关闭;刷新后仍可恢复的任务需要后端保存等待状态。 - 使用内置追问或审批卡片:后端给出交互请求、适配器提供
respond后可以接收用户答复。actions.respond(toolCallId, response)会作为新的一轮发送,有一轮在运行时不受理。原请求通过toolCallId关联,不保证沿用原 UIrunId;也不能把它当成任意表单对象的通用回传接口。
完整代码与相关参考
上方切换“代码”可以查看布局、草稿服务、适配器和样式;完整下载包含入口与项目配置。也可以进入示例工作区。