信息收集卡片 (Info Collection)
当 Agent 需要知道访客是谁——公司、职位、联系方式——它会在对话里放出一张填空卡片;SDK 负责把这张卡片渲染出来,并把用户填的内容回传给平台写进联系人档案。 你不用自己设计表单、不用管字段校验与落库,卡片什么时候出现由 Agent 判断。
前提:Agent 的所有者需先在「联系人」里配置好要收集的字段。字段的名称、类型、是否必填都在那里定义,SDK 侧不需要重复声明。
收集是怎么发生的
- 你像平常一样用 SDK 发消息(见 对话 (Chat))。
- Agent 判断当前访客缺少某些已配置的字段时,平台向对话流里推一条
info_collection事件,里面带着这张卡片的数据(标题、说明、待填字段列表)。 - 你把卡片渲染给用户,用户填完点提交。
- 提交的内容以
info_collection_submit回传,平台写入该访客的联系人记录;用户选择「稍后填写」则回传info_collection_skip,只记录这个行为、不写任何字段。
卡片只会问当前缺失的字段。已经填过的不会重复问——判断在平台侧完成,你不需要自己比对。
卡片的数据结构
info_collection 事件里的 InfoCollectPayload:
| 字段 | 类型 | 说明 |
|---|---|---|
fields | InfoCollectField[] | 待填字段列表 |
cardTitle | string? | 卡片标题,如「完善信息,让 Agent 更好地了解你」 |
cardDescription | string? | 标题下的一句说明,交代为什么要收集 |
每个 InfoCollectField:
| 字段 | 类型 | 说明 |
|---|---|---|
key | string | 字段标识,回传时作为 key |
label | string | 展示给用户的中文名,如「公司」 |
type | string? | 控件类型,缺省为 text |
required | boolean? | 是否必填 |
placeholder | string? | 输入框占位提示 |
options | string[]? | select 的候选项 |
type 与控件的对应关系:
type | 渲染为 |
|---|---|
text | 单行输入框 |
email | 输入框,唤起邮箱键盘并做格式校验 |
phone | 输入框,唤起电话键盘 |
select | 下拉框,选项取自 options |
textarea | 多行输入框 |
select若没有配options,会降级成文本输入框而不是渲染一个选不了的空下拉框;未知的type同样降级为文本框。这样即使字段配置有疏漏,用户也总能作答。
在原生 JS / TS 里处理
用事件工具从流里识别卡片:
import { OpenhexClient, extractInfoCollect, isInfoCollect } from '@openhex-ai/agent-sdk';
const client = new OpenhexClient({ apiKey, agentId });
for await (const record of client.runTurn('我想了解你们的服务')) {
const card = extractInfoCollect(record);
if (card) {
renderForm(card); // 你的渲染:遍历 card.fields
}
}
用户填完后,把结果作为工具动作回传:
import { infoCollectSubmitMetadata, infoCollectSkipMetadata } from '@openhex-ai/agent-sdk';
// 提交
await client.chat.send({
conversationId,
message: '',
toolAction: true,
metadata: infoCollectSubmitMetadata({ company: '蓝色光标', role: '运营总监' }),
});
// 或者稍后填写
await client.chat.send({
conversationId,
message: '',
toolAction: true,
metadata: infoCollectSkipMetadata(),
});
也可以用 isInfoCollect(record) 只做布尔判断。
在 React 里处理
React 集成把这套都封装好了:卡片自动挂到对应消息上,<ChatBox> / <ChatWidget> 直接渲染,提交与跳过也已接好。
import { ChatBox } from '@openhex-ai/agent-sdk/react';
export function SupportChat({ token }: { token: string }) {
return <ChatBox agentId="ce9382ad-…" token={token} />;
}
不需要任何额外配置——平台推卡片时它自己出现。
自定义文案
卡片上所有面向用户的文字都可以覆盖。默认是中文,与平台自有界面一致:
<ChatBox
agentId="ce9382ad-…"
token={token}
infoCollectLabels={{
title: '请补充以下信息',
submit: '提交',
skip: '稍后填写',
submitted: '信息已收到,感谢填写',
skipped: '已跳过,稍后可在对话中补充',
optional: '选填',
selectPlaceholder: '请选择',
}}
/>
自己渲染转录
如果你用 useOpenhexChat 自己画对话界面,卡片会以 infoCollect 挂在消息上。可以直接用内置卡片组件,也可以基于载荷自己实现:
import { InfoCollectCard, useInjectStyles, useOpenhexChat } from '@openhex-ai/agent-sdk/react';
function Transcript({ token }: { token: string }) {
useInjectStyles(true); // 页面上没有 ChatBox 时必须调用,否则卡片没有样式
const { messages, submitInfoCollect, skipInfoCollect } = useOpenhexChat({
agentId: 'ce9382ad-…',
token,
});
return (
<>
{messages.map(m =>
m.infoCollect ? (
<InfoCollectCard
key={m.id}
payload={m.infoCollect}
onSubmit={submitInfoCollect}
onSkip={skipInfoCollect}
/>
) : (
<MyBubble key={m.id} message={m} />
)
)}
</>
);
}
⚠️
onSubmit/onSkip必须如实反映发送结果。 只有返回的 Promise resolve,卡片才会翻成完成态;reject 时保持可编辑,让用户能重试。发送失败却显示「已收到」,用户会以为信息存下了。
让卡片和网页端长得一样
SDK 的默认配色刻意保持中性——它嵌入的是你自己的站点,套用我们的品牌色未必合适。卡片的版式(圆角、内边距、最大宽度、纵向间距)默认就与网页端一致,差异只在配色。
想让嵌入效果与 OpenHex 网页端完全一致,套用内置预设:
import { ChatBox, PLATFORM_TOKENS } from '@openhex-ai/agent-sdk/react';
<ChatBox agentId="ce9382ad-…" token={token} tokens={PLATFORM_TOKENS} />;
tokens 开放的是全部设计变量,可以在预设基础上只改一项,也可以完全按自己的品牌来:
<ChatBox tokens={{ ...PLATFORM_TOKENS, accent: '#0f766e' }} />
<ChatBox tokens={{ bg: '#fff', fg: '#1a1a1a', border: 'rgba(0,0,0,0.08)' }} />
自己画转录时用 tokenStyle(),把变量设在任意外层元素上,内部卡片会继承:
import { tokenStyle, PLATFORM_TOKENS, InfoCollectCard } from '@openhex-ai/agent-sdk/react';
<div style={tokenStyle(PLATFORM_TOKENS)}>
<InfoCollectCard payload={payload} onSubmit={onSubmit} onSkip={onSkip} />
</div>;
字体是个例外:网页端用的中英文字体是站点自身加载的,嵌入方引用不到。预设里给的是同一套回退字体,字形可能仍有细微差别。需要完全一致的话,自行加载那两款字体并排在前面即可。
下一步
- 对话 (Chat) — 发消息、流式接收与多轮对话
- 支付宝收款 (Payments) — 对话内收款卡片的渲染与结算
- API 参考 — 客户端配置、类型与错误处理