BEEOS CLOUD / DEVELOPER REFERENCE
Install and authenticate
Install the Harness SDK, understand the credentials a harness uses, and initialise the client for each call source.
This page installs the packages, explains which credential protects which call, and shows how to initialise the client for each call source. Every example runs against the published packages.
Install
npm install @beeos-ai/cloud-harness-sdk@1.0.0| Language | Requires |
|---|---|
| TypeScript | Node.js ≥ 22. The package is ESM only ("type": "module"). |
| Python | Python ≥ 3.11. The package root (beeos_cloud_harness_sdk) uses only the standard library; the submodules in this reference need httpx and cryptography, which pip installs. |
Credentials
A harness never holds a Cloud API key. It uses the credentials below, each for one call source.
| Call source | Credential | How it is sent | SDK entry points |
|---|---|---|---|
| Agent Gateway | Ed25519 signature of the harness key pair | Four headers: X-Agent-Public-Key, X-Agent-Signature, X-Agent-Timestamp, X-Agent-Nonce. The signed text is `METHOD | PATH |
| Registration and heartbeat | Identity proof signed with the instance identity key, sent through Agent Gateway | A signed proof inside the request body (domains beeos.runtime.registration.v1 and beeos.runtime.heartbeat.v1). | Registration and lease |
| Message Service (deliveries, claims, chat) | Runtime lease credential returned by registration and heartbeat | Authorization: Bearer <credential>. Some routes also need X-BeeOS-Execution-Grant or X-Runtime-Delivery-Key. | Receiving runtime methods, Chat replies and realtime |
| Realtime events | Realtime token, created with the lease credential | Token passed to the realtime client. | Chat replies and realtime |
| Canvas relay | Canvas token plus a signed upgrade request | Signed X-Agent-* headers on the WebSocket upgrade to /ws/agent; the token goes into the query. | Canvas relay and terminal bridge |
| Terminal bridge | Lease-bound agent_auth frame signed with the harness key | First frame of the connection; the bridge answers auth_ok. | Canvas relay and terminal bridge |
| Execution grants (TypeScript only) | RS256 signature checked against Cloud's published key set | The grant arrives with a delivery; the SDK only verifies it. | Execution grant verification |
Python facade BeeOSAgentRuntime (Python only) | One bearer token | Authorization header; a value without a space gets Bearer in front. | Python agent runtime |
Initialise the client
Key pair and Agent Gateway
Load or create the harness key pair, then build the signed Agent Gateway client. The private key stays in your process.
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);Register and keep the lease
The coordinator registers the runtime, sends signed heartbeats and tells you when the lease is lost. Declare only the runtime methods and capabilities that your harness really handles. The TypeScript example passes the identity fields itself; the Python example keeps them in an identity file.
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 is the SHA-256 hex digest of the public key, as the Python coordinator computes it. manifestDigest has no default in TypeScript; Python defaults it to RUNTIME_CURRENT_MANIFEST_DIGEST.
Python agent runtime facade
Only the Python package has this facade. It authenticates with one bearer token and dispatches chat messages, cancellations and runtime methods to your handlers.
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)Handling credentials
- Keep the key file private. The SDK creates it with mode
0600. - The lease credential, execution grants and delivery keys are secrets. Never log or persist them; the SDK sends each of them only to its own origin and refuses redirects.
- Registration, heartbeat and appends are not replayed blindly. Retry and failure handling are described in the retry module.
Next: Registration and lease, Receiving runtime methods, Retry and HTTP errors.