切换主题
在对话中展示业务组件
UI 能力让智能体输出结构化组件数据,由业务前端负责渲染。服务端登记“允许输出什么”,前端登记“如何展示”,两端通过组件标识与精确版本协商。
1. 注册服务端能力
在后台清单增加 CapabilityDefinition("ui-capabilities", "order-card", "1.0.0", definition),并使用清单注册发布。definition 如下:
json
{
"description":"展示当前订单摘要",
"propsSchema":{"type":"object","properties":{"orderId":{"type":"string"},"status":{"type":"string"}},"required":["orderId","status"],"additionalProperties":false},
"fallback":"当前客户端无法展示订单卡片,请查看文字回复。"
}这是一项可选高级能力,默认 ChatPanel 的文字、历史与确认不需要自定义 UI。定义发布后,用新的智能体版本加入 allowedUi。前端声明的能力与智能体允许列表取交集,具体字段见数据结构。
2. 注册前端渲染器
ts
import { UIRendererRegistry } from '@sparktide/frontend-sdk'
const renderers = new UIRendererRegistry()
renderers.register({
component: 'order-card', version: '1.0.0',
validate: (props: unknown) => {
if (!props || typeof props !== 'object') return false
const p = props as Record<string, unknown>
return typeof p.orderId === 'string' && typeof p.status === 'string'
},
render: (props: unknown) => {
const p = props as { orderId: string; status: string }
const card = document.createElement('article')
card.textContent = `订单 ${p.orderId} · ${p.status}`
return card
}
})SDK 已提供 React / Vue ChatPanel。自定义 Renderer 的 DOM、React 或 Vue 返回值由业务布局挂载;默认 ChatPanel 不会自动嵌入任意业务卡片,需要在自定义状态层中消费这些事件。
3. 声明能力并消费事件
调用 client.chat(content, {uiCapabilities: renderers.manifest()}) 声明客户端能力。收到 ui.created 后:
ts
const output = document.querySelector('#agent-ui')!
for await (const event of client.events(run.id)) {
if (event.event === 'ui.created') {
try {
const element = renderers.render(
String(event.data.component), String(event.data.version), event.data.props
)
if (element instanceof Node) output.append(element)
} catch {
output.append(document.createTextNode('暂时无法展示此卡片。'))
}
}
}本段中的 client 和 run 来自前端 SDK。版本不匹配或客户端未声明能力时,平台使用文字 fallback。
安全与交互
Renderer 只能调用业务已编写的组件。不要用模型输出执行 HTML、脚本或任意页面跳转。卡片中的“付款”“删除”等动作必须走原有业务鉴权或平台危险操作确认流程,UI 事件本身不是执行授权。
