接入外部工具 (MCP)
你可以把任意一个符合 MCP (Model Context Protocol) 的外部服务挂到 Agent 上,让它在对话里调用你自己的工具——查订单、改仓库、拉数据都行。SDK 更进一步:让每个终端用户都用「他自己的」凭据去调,而不是全员共用一把后台密钥。 这对内嵌到你自己产品里的场景尤其重要。
自定义连接器是进阶能力,需要为你的账号开通后才能配置。如果你在「应用」里看不到自定义连接器入口,请联系 OpenHex 团队开通。
一个连接器,三种凭据来源
把外部 MCP 挂到 Agent 上,叫做配置一个连接器 (Connector)。配置时最关键的一个选择是:注入给外部服务的那个 Token 从哪来?
凭据来源 tokenSource | Token 从哪来 | 适用场景 |
|---|---|---|
owner(默认) | 所有者配置一次的共享密钥 | 不区分用户的后台工具,如一个内部只读 API |
perUser | 每个终端用户在对话里通过卡片自助填写 | 用户有 OpenHex 账号、愿意自助填 Token 的 BYOK 场景 |
session | 你的应用在每次发送时通过 SDK 带上该用户的 Token | 企业内嵌:用户在你自己的站点登录,你的后端已持有他的 OAuth Token |
三种来源注入到外部服务的形状完全一致(都是往同一个鉴权头里塞 Token),区别只在"值从哪取"。所以你随时能切换来源,而不用改外部服务。
Token 全程不落库、不进 Prompt、也不进入模型上下文——平台只在需要时短暂持有,由连接器网关在出站调用时注入。
session:让每个用户用自己的 Token(推荐用于内嵌)
这是企业内嵌的首选:终端用户在你的站点登录、可能没有 OpenHex 账号,而你的后端已经握着他的第三方 Access Token。用 SDK 的 mcpTokens 在每次发送时带上即可,用户全程无感。
mcpTokens 的 key 是连接器的 slug,value 是该用户的 Token:
slug 在哪看? 它就是下方代码里
mcpTokens返回对象的 key——本页示例中的'custom-crm'。 到网页端复制:打开该 Agent 的管理后台,左侧导航进入**「应用」→「自定义应用」,每个连接器卡片的名称旁都有一个 slug 徽章(标注「Slug(SDK 集成标识)」),点旁边的复制按钮,粘贴进代码即可。 创建连接器时也可以在「Slug(SDK 集成标识)」输入框自定义一个好记的后缀**——例如填crm,实际 slug 即为custom-crm(固定带custom-前缀,弹窗会实时预览);留空则按名称自动生成。slug 创建后不可修改。
import { OpenhexClient } from '@openhex-ai/agent-sdk';
const client = new OpenhexClient({
apiKey,
agentId,
// 用回调,每次发送前重新求值——轮换中的 OAuth Token 自动保持最新
// key 'custom-crm' = 连接器 slug,在「应用 → 自定义应用」的连接器卡片上复制
mcpTokens: () => ({ 'custom-crm': currentUser.acmeAccessToken }),
});
const turn = await client.sendMessage('帮我查一下我名下所有未结的工单');
console.log(turn.text);
也可以按单轮覆盖(单轮优先于客户端级):
await client.sendMessage('同步我的日历到本周任务', {
mcpTokens: { 'custom-crm': oneOffToken },
});
优先级:单轮 opts.mcpTokens > 会话级 > 客户端级。
处理"需要重新授权"
当某用户的 Token 过期或从未提供,平台会返回一个刷新信号。平台不会偷偷改用所有者的密钥替他调用(那是跨身份越权),而是让你刷新后重发:
import { getRefreshSessionTokenSignal } from '@openhex-ai/agent-sdk';
try {
await convo.send('查一下我的工单');
} catch (err) {
const need = getRefreshSessionTokenSignal(err);
if (need) {
const token = await refreshUserToken(need.connectorSlug); // key 就是连接器 slug
await convo.send('查一下我的工单', { mcpTokens: { [need.connectorSlug]: token } });
} else {
throw err;
}
}
perUser:让用户自助填写(BYOK 卡片)
当连接器配成 perUser 时,若用户还没填过 Token,Agent 首次调用该工具会在对话里放出一张连接卡片。SDK 提供工具解析它、并把用户填的凭据存到他自己的账户下:
import { OpenhexClient, extractConnectorSetup } from '@openhex-ai/agent-sdk';
const client = new OpenhexClient({ apiKey, agentId });
const convo = client.conversation();
await convo.send('用我的 Notion 建一个页面');
// 从消息历史里解析出连接卡片
const { entries } = await client.chat.messages(convo.id);
let setup;
for (const e of entries) {
const cards = extractConnectorSetup(e.data);
if (cards.length) { setup = cards[0]; break; }
}
// 用户填好后提交(存到该用户自己的账户),再让 Agent 重试
if (setup) {
await convo.submitConnectorSetup(setup, { token: userTypedToken });
await convo.send('好了,请继续');
}
在 React 里使用
会话级凭据可直接挂在聊天连接上,hook 会在每次发送时自动带上:
import { useOpenhexChat } from '@openhex-ai/agent-sdk/react';
const chat = useOpenhexChat({
connection: {
apiKey,
agentId,
// key = 连接器 slug(见上文「slug 在哪看?」)
mcpTokens: () => ({ 'custom-crm': currentUser.acmeAccessToken }),
},
});
外部服务需要满足什么
你的 MCP 服务(或你指向的第三方 MCP)需要:
- 协议:MCP 的
streamable-HTTP(一个POST端点)。 - 鉴权:从请求头读取网关注入的凭据(如
Authorization: Bearer <token>)。 - 公网可达:HTTPS。
不想自建?可以直接指向成熟的托管 MCP。
下一步
- 对话 (Chat) — 发消息、流式接收与多轮对话
- 支付宝收款 (Payments) — 让 Agent 在对话里向用户收款
- API 参考 — 客户端配置、类型与错误处理