API Console
test
Sign in with BES

接入 AI service

做完后,AI service 带证书以渠道身份换取委托令牌,代表发消息的人调产品 tools。

环境登录地址带证书调用的接口地址
localhttps://id.local.globalbes.sghttps://id.local.globalbes.sg:19443
testhttps://id.test.globalbes.sghttps://id.test.globalbes.sg:9443
staging待定待定
prod待定待定

Sign in to send requests to see which of these steps are done. Sign in

1. 拿到证书
1.1

生成私钥和证书请求

在哪里做:AI service 服务器

跑一条 openssl 命令,得到私钥 ai-service-key.pem 和证书请求 ai-service.csr。证书请求拿去签发;私钥留在 AI 服务器上,不发给任何人。

CERT_DIR="$HOME/bes-certs/ai"
mkdir -p "$CERT_DIR"
SERVICE_ACCOUNT_ID=$(uuidgen | tr A-Z a-z)
openssl req -new -newkey ec -pkeyopt ec_paramgen_curve:P-256 -nodes \
  -subj "/CN=AI" \
  -addext "subjectAltName=URI:urn:bes:service:$SERVICE_ACCOUNT_ID" \
  -addext "basicConstraints=critical,CA:FALSE" \
  -addext "keyUsage=critical,digitalSignature" \
  -addext "extendedKeyUsage=clientAuth" \
  -keyout "$CERT_DIR/ai-service-key.pem" -out "$CERT_DIR/ai-service.csr"
  • SERVICE_ACCOUNT_ID 每次新生成,写进证书唯一的 URI SAN urn:bes:service:<uuid>;登记平台账号后它就是账号的 service_account_id。
  • 私钥 ai-service-key.pem 放进 AI 部署的密钥存储。
1.2

签发证书

在哪里做:客户端 CA 所在的机器

用客户端 CA 给证书请求签名,得到证书 ai-service.pem。证书拷回 AI 服务器,和私钥一起调 Control;登记平台账号时也要用它。

前提:OpenSSL 3.0 及以上,openssl version 显示 OpenSSL 3.x。Mac 自带的 /usr/bin/openssl 是 LibreSSL,不认 -copy_extensions:先执行 brew install openssl@3,再执行 export PATH="$(brew --prefix openssl@3)/bin:$PATH"。

本环境(test)

  • CA_DIR:待定,test 环境的客户端 CA 位置未定。
  • 签发前把 ai-service.csr 拷到客户端 CA 所在机器的 ~/bes-certs/ai/;签发后把 ai-service.pem 拷回 AI 服务器的同一目录,和私钥放在一起。
CERT_DIR="$HOME/bes-certs/ai"
mkdir -p "$CERT_DIR"
CA_DIR="待定"
openssl x509 -req -days 825 -sha256 -in "$CERT_DIR/ai-service.csr" \
  -CA "$CA_DIR/client-ca.pem" -CAkey "$CA_DIR/client-ca-key.pem" \
  -CAserial "$CERT_DIR/ai-service.srl" -CAcreateserial -copy_extensions copy \
  -out "$CERT_DIR/ai-service.pem"
其他环境

local

本地的客户端 CA 在本机,证书请求不用拷,在本机执行:

CERT_DIR="$HOME/bes-certs/ai"
mkdir -p "$CERT_DIR"
CA_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/bes/local/stack/secrets/control"
openssl x509 -req -days 825 -sha256 -in "$CERT_DIR/ai-service.csr" \
  -CA "$CA_DIR/client-ca.pem" -CAkey "$CA_DIR/client-ca-key.pem" \
  -CAserial "$CERT_DIR/ai-service.srl" -CAcreateserial -copy_extensions copy \
  -out "$CERT_DIR/ai-service.pem"

staging

  • CA_DIR:待定,staging 环境的客户端 CA 位置未定。
  • 签发前把 ai-service.csr 拷到客户端 CA 所在机器的 ~/bes-certs/ai/;签发后把 ai-service.pem 拷回 AI 服务器的同一目录,和私钥放在一起。
CERT_DIR="$HOME/bes-certs/ai"
mkdir -p "$CERT_DIR"
CA_DIR="待定"
openssl x509 -req -days 825 -sha256 -in "$CERT_DIR/ai-service.csr" \
  -CA "$CA_DIR/client-ca.pem" -CAkey "$CA_DIR/client-ca-key.pem" \
  -CAserial "$CERT_DIR/ai-service.srl" -CAcreateserial -copy_extensions copy \
  -out "$CERT_DIR/ai-service.pem"

prod

  • CA_DIR:待定,prod 环境的客户端 CA 位置未定。
  • 签发前把 ai-service.csr 拷到客户端 CA 所在机器的 ~/bes-certs/ai/;签发后把 ai-service.pem 拷回 AI 服务器的同一目录,和私钥放在一起。
CERT_DIR="$HOME/bes-certs/ai"
mkdir -p "$CERT_DIR"
CA_DIR="待定"
openssl x509 -req -days 825 -sha256 -in "$CERT_DIR/ai-service.csr" \
  -CA "$CA_DIR/client-ca.pem" -CAkey "$CA_DIR/client-ca-key.pem" \
  -CAserial "$CERT_DIR/ai-service.srl" -CAcreateserial -copy_extensions copy \
  -out "$CERT_DIR/ai-service.pem"
1.3

登记平台账号

在哪里做:Control 服务器

执行 bes-control seed-trusted-caller,得到 AI 的平台账号,状态 active。之后 AI 带这张证书调查询接口,Control 按这个账号放行。

  • 账号带 Control 的 ai-runtime 角色(role),命令输出应为 role=ai-runtime;列表不返回角色码,自动检查按显示名、product_id: null 和状态判断。
  • --display-name 写 AI:测试台按这个名字找 AI 的平台账号。
  • 重复执行保留同一个账号。

本环境(test)

  • 在 Control 服务器上执行 bes-control 的方式:待定,test 环境的 Control 部署方式未定。
  • ai-service.pem 拷到 Control 服务器上的路径:待定。
bes-control seed-trusted-caller --role ai-runtime --certificate "待定/ai-service.pem" --display-name AI
其他环境

local

本地 Control 在容器 control-api 里,先把证书拷进 ~/.local/share/bes/local/stack/secrets/control/,每次执行时它被复制成容器里的 /run/bes/control/ai-service.pem。在本机执行:

BES_INFRA="$HOME/Projects/bes-infra"   # bes-infra 仓的路径
cp "$HOME/bes-certs/ai/ai-service.pem" "${XDG_DATA_HOME:-$HOME/.local/share}/bes/local/stack/secrets/control/ai-service.pem"
"$BES_INFRA/envs/local/dev" stack compose exec -T control-api /bin/sh /opt/bes/stack-entrypoint.sh \
  bes-control seed-trusted-caller --role ai-runtime --certificate /run/bes/control/ai-service.pem --display-name AI

staging

  • 在 Control 服务器上执行 bes-control 的方式:待定,staging 环境的 Control 部署方式未定。
  • ai-service.pem 拷到 Control 服务器上的路径:待定。
bes-control seed-trusted-caller --role ai-runtime --certificate "待定/ai-service.pem" --display-name AI

prod

  • 在 Control 服务器上执行 bes-control 的方式:待定,prod 环境的 Control 部署方式未定。
  • ai-service.pem 拷到 Control 服务器上的路径:待定。
bes-control seed-trusted-caller --role ai-runtime --certificate "待定/ai-service.pem" --display-name AI --confirm-production

做完这一部分,手里有:AI 的证书、私钥和平台账号。每次换取委托令牌时带证书和私钥。

2. 代表发消息的人调产品
2.1

为发消息的人换委托令牌

在哪里做:AI service 代码

AI service 每次调产品 tools 之前,以自己的 ai-runtime 平台账号,代表 Marcus Lim 向 BIM 换取一张五分钟以内的委托令牌。

POSTDelegation Exchange

程序里发这个请求(id 用前面步骤返回的):

带:证书

请求:

POST https://id.test.globalbes.sg:9443/oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Atoken-exchange&subject_token_type=urn%3Abes%3Aparams%3Aoauth%3Atoken-type%3Achannel-identity&subject_token=whatsapp%3A6591234567&tenant_id=7c0e2a5e-3b1f-4d6a-9a53-1f2f6d0c8a11&project_id=e2f7a1c4-0d35-4b8e-a6c9-7d18f4b2a903&audience=b41d9a70-6c2e-4a0f-8e7d-52a9c3f0d614&scope=document.read

返回:

HTTP/1.1 200 OK

{
  "access_token": "<delegation_token>",
  "issued_token_type": "urn:ietf:params:oauth:token-type:jwt",
  "token_type": "Bearer",
  "expires_in": 300,
  "scope": "document.read"
}
  • 样例使用 Marcus Lim 的 WhatsApp 地址 6591234567 和 BIM 产品;该地址须已在 Control 验证,且人、成员、项目与业务授权均有效。
  • 同一租户、项目须有闸门产品的有效授权;Control 设置 channel_exchange_gate_product_code 默认是 ai-service。
  • BIM 的 active 服务账号对应 svc-<service_account_id> 客户端须登记 deployment_version 和 document.read scope;最终 scope 还受 Marcus 的当前产品权限限制。
  • 每次调产品 tools 前现换,用完即弃,不缓存令牌,不传 context_id,不需要用户令牌。channel_assurance 说明身份怎么建立;是否按它限制动作由产品决定。
  • 群到项目的绑定由 会话服务 判断,不推进 Control 的 binding_version。
2.2

带令牌调产品 tools

在哪里做:AI service 代码

将新换取的委托令牌原样放进 Authorization: Bearer 调产品 tools,用完即弃。

  • 将委托令牌原样放在 Authorization: Bearer <delegation_token>,交给对应目标产品的 tools 接口。
  • 每次调用前都换一张新令牌,用完即弃,exp - iat 不超过 300 秒。
  • 撤权在下一次换令牌时生效;Control 按当时的人、绑定、成员关系和授权状态校验。

做完这一部分,手里有:AI service 每次调产品 tools 前取得一张新令牌,带令牌调用后即丢弃。

3. 身份上下文名称
3.1

展示上下文名称

在哪里做:AI service 代码

显示 Control 返回的租户与项目名称;租户级项目名为 null。

身份上下文的显示名称来自 identity.resolve:每项包含 tenant_name 与 project_name;租户级 project_name 为 null。示例:{product_id: "<产品 UUID>", tenant_id: "<租户 UUID>", tenant_name: "Acme Construction", project_name: null}。

做完这一部分,手里有:按 Control 当前上下文展示租户与项目名称。

其他功能
接入会话服务