跳到主要内容

会话令牌 (Sessions)

会话令牌 (Session Token) 是交给你的用户端(浏览器、小程序、App)的短时凭据:它代表某一个成员,只能以这个成员的身份和 Agent 对话。 工作区 API Key 留在你的后端,客户端永远只拿会话令牌。

你的后端(持有 sk_…) 你的客户端
┌───────────────────────────┐ token ┌───────────────────────────────┐
│ 1. 认证你自己的用户 │ ────────▶ │ 3. new OpenhexClient({ apiKey: │
│ 2. startVisitorSession / │ │ token }) 或 <ChatWidget │
│ mintSession 换令牌 │ │ getToken={…} /> │
└───────────────────────────┘ └───────────────────────────────┘

本页示例都基于一个绑定了 slug 的工作区句柄:

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

const ws = new OpenhexClient({ apiKey: process.env.OPENHEX_WORKSPACE_KEY! })
.workspace(process.env.OPENHEX_WORKSPACE_SLUG!);

一步到位:startVisitorSession

绝大多数集成只需要这一个方法:它先按 sp_user_ref 幂等开通成员,再为他签发令牌。

const { token, user_id, expires_at } = await ws.startVisitorSession({
sp_user_ref: `web_${visitorId}`, // 稳定引用:同一个人 → 同一个成员 → 同一段对话
display_name: '网站访客', // 可选
ttl_seconds: 1800, // 可选,默认 3600,最长 86400
});

它等价于依次调用 provisionMembermintSession(两次 HTTP 请求)。sp_user_ref 一定要稳定:匿名访客用 httpOnly cookie 里的随机值,登录用户用你的用户 id,小程序用 openid。引用一变,平台就当成一个新成员,历史对话也就找不回来了。

为已开通的成员签发:mintSession

成员已经开通过(例如注册时调过 provisionMember),之后每次登录只需要签发:

const session = await ws.mintSession({
sp_user_ref: 'user-42',
ttl_seconds: 3600,
});
// → { token, user_id, expires_at }
参数类型说明
sp_user_refstring已开通成员的引用
ttl_secondsnumber?有效期(秒)。不传为 3600,最大 86400
返回字段说明
token会话令牌(JWT),交给客户端
user_id成员 id
expires_at过期时间(ISO-8601 字符串)

在客户端使用令牌

令牌就是一个 Bearer 凭据,直接当作 apiKey 传给 SDK:

const client = new OpenhexClient({ apiKey: token, agentId: '你的-agent-id' });
const turn = await client.sendMessage('你好');

在 React 里交给组件的 getToken,组件会在每次请求前调用它,令牌快过期时自动换新:

<ChatWidget agentId="你的-agent-id" getToken={fetchTokenFromYourBackend} persist />

完整的前后端示例见示例:网站客服组件

会话令牌能做什么、不能做什么:

不能
以该成员身份和 Agent 对话、上传附件、读取对话历史调用任何需要工作区 API Key 的方法(listAgents 返回 403
读取单个 Agent 的公开信息(GET /api/v2/marketplace/agents/{agentId}以所有者身份训练 Agent

有效期怎么定

  • 越短越安全。 令牌泄漏后在过期前一直可用;停用成员不会吊销已经签发的令牌。
  • 靠续期而不是长有效期来保证体验。 组件的 getToken 会自动换新,你的签发接口只需要做好限流(按 IP / cookie)。
  • 网页客服这类匿名场景常用 1800 秒;已登录用户可以放宽到数小时。

公开短信注册(无需鉴权)

如果你没有自己的用户体系,可以让用户用手机号 + 验证码直接成为工作区成员。这两个接口不需要任何密钥,可以从客户端直接调用,但要求工作区开启了公开短信注册。

// 客户端也要传一个 apiKey 占位——SDK 构造时需要它,这两个接口会忽略它
const pub = new OpenhexClient({ apiKey: 'public' });

await pub.workspaces.sendSmsCode('your-workspace', { phone: '13800000000' });

const session = await pub.workspaces.verifySmsCode('your-workspace', {
phone: '13800000000',
code: '123456',
});
// → { token, user_id, expires_at },首次验证会自动开通成员

不带国家码的 11 位大陆手机号会按 +86 处理,同一个号码始终对应同一个成员。

接口状态码含义
sendSmsCode204验证码已发送
400手机号格式不对(例如少于 7 位)
403该工作区没有开启公开短信注册
404工作区不存在或未启用
verifySmsCode200验证通过,返回会话令牌
401invalid_or_expired_code:验证码错误或已过期

常见错误

状态码message原因
400body/ttl_seconds Number must be less than or equal to 86400有效期超过上限
401workspace API key required签发会话只接受工作区 API Key
403member status is suspended成员已被停用
404member not found for sp_user_refmintSession 前没有开通这个成员(改用 startVisitorSession

下一步