文档Harness SDK

BEEOS CLOUD / DEVELOPER REFERENCE

安装与鉴权

安装 Harness SDK,了解 harness 使用的各种凭据,并按调用来源初始化客户端。

本页安装这两个包,说明哪种凭据保护哪类调用,并按调用来源演示如何初始化客户端。所有示例都针对已发布的包。

安装

npm install @beeos-ai/cloud-harness-sdk@1.0.0
语言运行环境
TypeScriptNode.js ≥ 22. The package is ESM only ("type": "module").
PythonPython ≥ 3.11。包根(beeos_cloud_harness_sdk)只使用标准库;本参考涉及的子模块需要 httpx 和 cryptography,pip 会一并安装。

凭据

harness 不持有 Cloud API 密钥。它使用下面的凭据,每种凭据对应一类调用来源。

调用来源凭据发送方式SDK 入口
Agent Gatewayharness 密钥对的 Ed25519 签名四个头:X-Agent-Public-Key、X-Agent-Signature、X-Agent-Timestamp、X-Agent-Nonce。签名原文为 `METHODPATH
注册与心跳用实例身份密钥签名的身份证明,经 Agent Gateway 发送请求体中的签名证明(域为 beeos.runtime.registration.v1 与 beeos.runtime.heartbeat.v1)。注册与租约
Message Service(投递、认领、聊天)注册与心跳返回的运行时租约凭据Authorization: Bearer <凭据>。部分路由还需要 X-BeeOS-Execution-Grant 或 X-Runtime-Delivery-Key。接收运行时方法(投递), 会话回复与实时通道
实时事件实时令牌,用租约凭据创建令牌交给实时客户端使用。会话回复与实时通道
画布中继画布令牌加带签名的升级请求WebSocket 升级到 /ws/agent 时带上签名的 X-Agent-* 头;令牌放在查询串里。画布中继与终端桥
终端桥用 harness 密钥签名、与租约绑定的 agent_auth 帧连接的第一帧;桥回复 auth_ok。画布中继与终端桥
执行授权(仅 TypeScript)用 Cloud 发布的公钥集校验 RS256 签名授权随投递到达;SDK 只负责校验。执行授权校验
Python 门面 BeeOSAgentRuntime(仅 Python)一个 bearer 令牌Authorization 头;不含空格的值会自动加上 Bearer 前缀。Python 智能体运行时

初始化客户端

密钥对与 Agent Gateway

加载或创建 harness 密钥对,再构建带签名的 Agent Gateway 客户端。私钥始终留在你的进程里。

import { AgentGatewayClient, agentIdentityFromKeyPair, loadAgentKeyPair } from "@beeos-ai/cloud-harness-sdk";

const keys = loadAgentKeyPair("./harness-key.json");
const gateway = new AgentGatewayClient({
  baseUrl: process.env.AGENT_GATEWAY_URL!,
  identity: agentIdentityFromKeyPair(keys),
});

// Every call is signed with the harness key and re-signed on each retry.
const canvasToken = await gateway.canvas.token();
console.log(canvasToken.relayUrl);

注册并保持租约

协调器负责注册运行时、发送带签名的心跳,并在租约丢失时通知你。只声明你的 harness 真正处理的运行时方法和能力。TypeScript 示例自己传入身份字段;Python 示例把它们保存在身份文件里。

import { createHash, randomUUID } from "node:crypto";
import {
  AgentGatewayClient,
  InstanceAuthorityRuntimeRegistrationTransport,
  RuntimeRegistrationCoordinator,
  agentIdentityFromKeyPair,
  loadAgentKeyPair,
} from "@beeos-ai/cloud-harness-sdk";

// 1. Harness key pair. The file is created with mode 0600 when it does not exist.
const keys = loadAgentKeyPair("./harness-key.json");
const identity = agentIdentityFromKeyPair(keys);

// 2. Signed client for Agent Gateway.
const gateway = new AgentGatewayClient({
  baseUrl: process.env.AGENT_GATEWAY_URL!,
  identity,
});

// 3. Register and keep the lease alive. Persist registrationId and journalStoreId between restarts.
const registrationId = randomUUID();
const coordinator = new RuntimeRegistrationCoordinator(
  new InstanceAuthorityRuntimeRegistrationTransport({ gateway, registrationId }),
  {
    registrationId,
    handlerIdentity: "my-harness-1",
    contractRevision: "2026-07-14.3",
    runtimeMethods: ["session/prompt"],
    capabilities: ["transport", "conversation.control"],
    manifestDigest: process.env.RUNTIME_MANIFEST_DIGEST!, // SHA-256 digest of the method manifest you implement
    journalStoreId: randomUUID(),
    journalGeneration: "1",
    instanceIdentityKeyId: createHash("sha256").update(keys.publicKey).digest("hex"),
    targetInstanceId: process.env.BEEOS_INSTANCE_ID,
    signIdentityProof: message => identity.sign(message),
  },
  (reason, cause) => console.error("runtime lease lost:", reason, cause),
);

const lease = await coordinator.start();
if (lease) console.log("lease expires at", lease.leaseExpiresAt);
// ... later: coordinator.stop();

instanceIdentityKeyId 是公钥的 SHA-256 十六进制摘要,与 Python 协调器的计算方式一致。TypeScript 的 manifestDigest 没有默认值;Python 默认使用 RUNTIME_CURRENT_MANIFEST_DIGEST。

Python 智能体运行时门面

只有 Python 包提供这个门面。它用一个 bearer 令牌鉴权,并把聊天消息、取消事件与运行时方法分发给你的处理函数。

import os
from typing import Any

from beeos_cloud_harness_sdk import BeeOSAgentRuntime

runtime = BeeOSAgentRuntime(
    agent_gateway_url=os.environ["AGENT_GATEWAY_URL"],
    message_service_url=os.environ["MESSAGE_SERVICE_URL"],
    instance_id=os.environ["BEEOS_INSTANCE_ID"],
    agent_id=os.environ["BEEOS_AGENT_ID"],
    token=lambda: os.environ["BEEOS_RUNTIME_TOKEN"],  # a string or a function that returns the current one
)

def on_chat_message(event: dict[str, Any]) -> None:
    # Cloud pre-creates the reply message; complete it with the answer.
    runtime.chat.complete_reply(event["conversationId"], event["replyMessageId"], "You said: " + event["text"])

runtime.register(on_chat_message=on_chat_message)

凭据的使用须知

  • 保管好密钥文件。SDK 创建它时权限为 0600。
  • 租约凭据、执行授权和投递密钥都是机密。不要写入日志或持久化;SDK 只会把它们发给各自的来源,并拒绝重定向。
  • 注册、心跳和追加操作不会被盲目重放。重试与失败处理见重试模块。

下一步: 注册与租约, 接收运行时方法(投递), 重试与 HTTP 错误.