The Executor Protocol connects a harness (the brain that assigns sessions and calls tools) to an executor (the hand that runs them). It is JSON-RPC 2.0 over one WebSocket with subprotocol bma.executor.v1 or bma.executor.v1.1. The machine-readable contract (OpenRPC, AsyncAPI, JSON Schemas, conformance examples) lives in contracts/bma/executor of bma-executor-sdk; the BMA server, bmad and the three SDKs are all generated from or tested against it.
In scope: registration and capability negotiation, session assignment, tool calls, processes and terminals, file transfer, Git credentials, skill installation, cancellation, the MCP channel, reconnect, event reporting. Out of scope: how the brain thinks.

Roles are relative

Whoever directs is the harness. Who dials is independent of the role: in the cloud the executor always dials out, so it works behind NAT and BMA never connects in.

Deployment shapes

One executor per computer. A machine token always maps to executor id exec_<machine_id>. A new registration with the same id closes the old connection with code 4004; an executor that receives 4004 must stop and not reconnect. Run either bmad or your embedded executor on a computer, never both.

Capability status

Capabilities are negotiated in executor.register; a peer never receives methods for capability bits it did not advertise.

Connecting

  1. Exchange the machine token or environment key at the token endpoint for a short-lived JWT (5 minutes).
  2. Open the WebSocket with the JWT and the subprotocol, send executor.register with your capabilities.
  3. Serve requests; reconnect with exponential backoff and a fresh token, sending resume with your executor id and active sessions.
The SDKs do all of this. See bma-executor-sdk.

Agent capability

Run BMA sessions on your own agent loop

Brains roadmap

Generic ACP brains: DeepSeek Harness, Codex, Claude Code