beeos-ai/bma-executor-sdk implements the Executor Protocol bma.executor.v1.1 (it also accepts v1). Protocol types are generated from the contract in contracts/bma/executor; the runtimes are handwritten. The BMA server and bmad speak the same contract, so a harness built with the SDK cannot be told apart from BMA by an executor, and vice versa.
Install
Credentials
Pass the API origin without a path as the base URL (
https://api.staging.bma.beeos.ai on staging); the SDK adds the route. The built-in default https://api.bma.beeos.ai is not live yet.
The long-lived credential is only sent to the token endpoint, which returns a 5-minute JWT; only the JWT goes on the WebSocket. Model credentials of a local brain are separate and never read or forwarded by the SDK.
Executor quick start
An executor connects out to BMA and answers tool calls.tool.cancel(and the deadline) cancels the handler; the result is reported withoutcome: "canceled". A repeatedtool.callid is acknowledged but not run twice.tool.resultis retried onexecutor_busy(-32009),timeout(-32004) orretryable: true, idempotent bytool_call_id. If every attempt fails,OnToolResultLost/onToolResultLost/on_tool_result_lostreceives the result so you can persist it. Results are never dropped silently.- Call
SessionReadyafter workspace and MCP setup andSessionEndedafter cleanup; only your code knows when those are done. - Close code
4004means another executor with the same identity replaced this one: stop, do not reconnect.
Use the execution core (Go)
Core gives you a complete hand without writing tool handlers. One Core can serve the BMA cloud and a local brain at the same time, with per-brain workspaces and session isolation:
bash is not a sandbox: every brain runs as the executor’s OS user. Only attach brains you trust with that machine. CoreOptions.DenyEnv keeps executor secrets (for example the machine token) out of every child process.
Harness quick start
Be the brain: accept executors and drive their tools, for example a local agent that uses a local hand without a round trip to the cloud.CallTool is idempotent by tool_call_id. A disconnected executor keeps its sessions and pending calls for the lease (60 s by default); after that, pending calls fail with “tool outcome unknown”.
Transports: WebSocket (ws://, wss://), WebSocket over a Unix socket (unix://) or Windows named pipe (npipe://), and in-process. Messages are identical on every transport.
Agent capability (Preview)
An executor that runs its own model loop serves theagent capability: BMA sends natural-language turns, the executor streams Managed Agents events back. See Agent capability.
session.status_running and a final session.status_idle.
Examples
TypeScript projects that type-check dependencies need
@types/ws (the SDK’s transport types import ws), or skipLibCheck.