跳到主要内容

React 组件

@openhex-ai/agent-sdk/react 让你用一个组件把 Agent 的聊天界面放进自己的网站:流式回复、附件、打断重试、历史恢复、对话内卡片都已经做好,样式自带、无需引入 CSS。 它和核心 SDK 走同一套协议,只是多了一层界面。

三个层级,按需选择

入口是什么适合
<ChatWidget>右下角的浮动气泡 + 面板,桌面端是角落面板,手机端全屏网站客服、帮助中心,几行接入
<ChatBox>内嵌的聊天面板,填满父容器放进你自己的页面布局
useOpenhexChat()无界面的状态 Hook完全自定义 UI

安装

npm install @openhex-ai/agent-sdk react react-dom

react / react-dom(18 及以上)是 peer 依赖,用的是你项目里的那份。

快速接入

'use client';
import { ChatWidget } from '@openhex-ai/agent-sdk/react';

export default function Support() {
return (
<ChatWidget
agentId="你的-agent-id"
getToken={getToken}
persist
title="在线客服"
greeting="你好 👋 有什么可以帮你的?"
accentColor="#0f766e"
/>
);
}

getToken你自己的后端换取会话令牌。完整的前后端代码见示例:网站客服组件

鉴权:浏览器里只放会话令牌

⚠️ 不要把个人 API Key(mysta_…)或工作区 API Key(sk_…)放进浏览器。 它们等同于账号权限,打包进前端就等于公开。

组件接受三种连接方式,任选一种:

属性说明
getToken推荐。 返回会话令牌的函数,组件在每次请求前调用,令牌快过期时由你换新
token静态令牌,适合每次页面加载都重新签发的场景
client一个现成的 OpenhexClient(例如指向你自己的代理),设置后其他连接属性都被忽略

令牌由你的后端用工作区 API Key 签发,见会话令牌

常用属性

<ChatBox><ChatWidget> 共享下面这些属性,useOpenhexChat 接受其中的连接与对话部分。

对话

属性默认值说明
agentId新对话路由到的 Agent,获取方式见获取 Agent ID
conversationId接续一段已有的对话(会加载历史)
persistfalselocalStorage 记住对话,刷新页面后续上同一段对话。trueagentId 区分;传字符串作为自定义命名空间(例如按用户区分)
loadHistorytrue接续对话时是否加载历史
idleTimeoutMs180000连续多久没有事件判定超时
senderName / senderAvatar在对话记录里标注用户的名字 / 头像
mcpTokens会话级 MCP 凭据,见接入外部工具
onTurnComplete一轮结束时回调,参数是 Agent 的回复消息
onError出错时回调

外观

属性默认值说明
title / subtitle / avatarUrl头部信息
greeting还没开始聊时显示的欢迎语(只显示,不发送)
placeholder输入框占位文字
themelightlight / dark / auto(跟随系统)
accentColor主色(按钮、用户气泡、链接)
tokens覆盖任意设计变量,见下文主题
height / width填满父容器数字按 px
className根元素额外的 class
header内置头部替换头部;false 隐藏;传函数可拿到「新对话」动作
emptyState没有消息时显示的节点(优先于 greeting
footer「Powered by Openhex」输入框下方的小字,false 隐藏
injectStylestrue设为 false 不注入内置样式,完全自己写

功能开关

属性默认值说明
allowAttachmentstrue是否允许附件(选择、粘贴、拖拽)
acceptFileTypes任意文件选择框的 accept,如 "image/*"
showToolCallsfalse在回复下方显示 Agent 调用过的工具
showAudioControlstrue在回复上显示朗读按钮,见语音回复
autoPlayAudiofalse每条回复完成后自动朗读
showSubAgent / subAgentRenderer关闭标注回复出自哪个 Agent,见子 Agent 与委派
paymentLabels / infoCollectLabels中文覆盖卡片文案,见支付宝收款信息收集卡片
disabledfalse只读,禁止输入

<ChatWidget>

属性默认值说明
positionbottom-rightbottom-right / bottom-left
launcherIcon / launcherLabel内置图标 / Open chat气泡按钮的图标与无障碍标签
newConversationLabelNew chat头部「新对话」按钮的文字;false 去掉按钮
defaultOpenfalse初始是否展开
open / onOpenChange受控模式

新对话

<ChatWidget> 头部默认带一个「新对话」按钮:清空界面、忘掉记住的对话,下一条消息在服务端开一段全新的对话。

匿名访客场景请保留这个按钮。访客身份绑在浏览器 cookie 上,没有它,下一个用这台电脑的人会接着看到上一个人的对话。只有在用户已登录、对话属于账号本身时,才考虑用 newConversationLabel={false} 去掉。

自定义头部时,通过函数形式拿到这个动作:

<ChatBox
agentId=""
getToken={getToken}
header={({ newConversation }) => (
<div className="my-header">
<span>在线客服</span>
<button onClick={newConversation}>新对话</button>
</div>
)}
/>

主题

每一处颜色、圆角、字体都来自一个 --ohx-* 设计变量。accentColor 只是其中一个的快捷方式,tokens 开放全部:

<ChatBox tokens={{ bg: '#fff', fg: '#1a1a1a', border: 'rgba(0,0,0,0.08)', radius: '12px' }} />

可用的变量:accentaccent-contrastbgsurfacefgmutedborderuser-bguser-fgassistant-bgassistant-fgradiusfont

想和 OpenHex 网页端长得一样,套用内置预设,再按需改一两项:

import { ChatBox, PLATFORM_TOKENS } from '@openhex-ai/agent-sdk/react';

<ChatBox tokens={{ ...PLATFORM_TOKENS, accent: '#0f766e' }} />;

变量以内联样式设在组件根元素上,不需要 !important 就能覆盖内置样式。

无头 Hook:自己画界面

import { useOpenhexChat } from '@openhex-ai/agent-sdk/react';

function MyChat({ getToken }: { getToken: () => Promise<string> }) {
const { messages, send, isResponding, interrupt, retry, error } = useOpenhexChat({
agentId: '你的-agent-id',
getToken,
persist: true,
});

return (
<div>
{messages.map(m => (
<p key={m.id} className={m.role}>
{m.text}
{m.streaming && '▍'}
</p>
))}
{error && <button onClick={retry}>重试</button>}
{isResponding ? (
<button onClick={interrupt}>停止</button>
) : (
<button onClick={() => send('你好')}>发送</button>
)}
</div>
);
}

返回值:

字段说明
messages按时间排列的消息列表,见下表
statusidle / connecting / streaming / error
isRespondingAgent 是否正在回复
error最近一次错误,下次发送成功后清空
conversationId当前对话 id(发出第一条消息后才有)
send(text, { files?, parts? })发送消息,可带附件
interrupt()打断当前这一轮
retry()出错后重发上一条消息
clear()清空消息并忘掉对话 id
downloadAttachment(att)取回 Agent 产出的文件,返回 Blob
playAudio(message) / stopAudio() / audioPlayback朗读回复及其状态
submitInfoCollect(values) / skipInfoCollect()回应信息收集卡片
submitConnectorSetup(setup, values)回应连接器配置卡片

每条 ChatMessage

字段说明
id / role / text / createdAt基本信息;roleuser / assistant / system
streaming / pending / error正在输出 / 已发送但还没有文字 / 这一轮失败
attachments图片与文件(含 Agent 产出的文件)
toolCalls / delegations / agent工具调用、委派、发言的 Agent
paymentGate / infoCollect / connectorSetup对话内卡片的数据

页面上没有 <ChatBox>、却要用内置卡片组件(InfoCollectCardPaymentGateCard)时,调用一次 useInjectStyles(true) 注入样式表。

服务端渲染

组件依赖浏览器 API,在 Next.js App Router 里放进带 'use client' 的组件文件中使用。

下一步