bma.executor protocol. bma-sdk drives and uses agents; bma-executor-sdk connects hands or brains to BMA.
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.
Set machine_id (Go Options.MachineID, TypeScript machineId, Python machine_id; default BMA_MACHINE_ID) for a machine; without it a machine token still works through the legacy POST /api/v1/executors/token alias, which the server serves until contract 2.0. machine_id and the environment id are alternatives.
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.- Each built-in tool has its own typed handler (
client.Tools.Bash.Handle/client.tools.bash.handle/@client.tools.bash.handler) receiving that tool’s input (BashInput,ReadInput, …); input missing a required member fails before the handler runs.shellandfilesare advertised while a handler of the group is registered, unless you setenabled: false; a handler registered after start is announced withexecutor.capabilities.update, and a call for a tool without a handler is refused with-32012. Thecomputer_*tools have no handler slot yet. Return text, content blocks or a bash result (rendered as stdout, stderr,exit_code: N, cut to a preview beyond 48 KiB); aToolErroris reported to the model withis_error: true, any other error isoutcome: "failed". Other protocol methods are typed by the contract:onRequest('process.start', …)/on_request(methods.PROCESS_START, …)/bmaexecutor.Requests.ProcessStart.Handle(client, …). 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
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.Naming
Why the SDK is calledbma-executor-sdk:
- It is named after its protocol. The SDK implements the
bma.executorprotocol, and its executor, harness and agent ends are that protocol’s roles. Protocol SDKs follow the same rule: the MCP SDK (@modelcontextprotocol/sdk), the ACP SDK (@agentclientprotocol/sdk) and the A2A SDK (a2a-sdk) each cover every role of their protocol. - OpenAI uses the same word for the same part. In the OpenAI Agents API, the process you run in a self-hosted environment,
codex exec-server, is called “the executor”: it registers with an environment ID and a restricted API key, connects outbound over WebSocket, and reconnects when the connection drops (OpenAI: self-hosted environments). - It is not an “agent SDK”. In the industry an agent SDK (OpenAI Agents SDK, Claude Agent SDK, Google ADK) is a framework that runs the agent loop inside your application. This SDK contains no agent loop: bring your own, for example one built with one of those SDKs, and connect it with the agent end.