How it works
A PlexaSpace is a single-process reactor. It owns a tick loop, a set of bodies, a brain, and a few caches.
Space
The orchestrator. Holds bodies, the brain, the tool registry, and the gates.space.stop().
BodyAdapter
A body is a class with one async method per tool. Thestatic tools map is the contract the brain sees.
BodyAdapter and SCPBody are the same class with two names. Anything you can do in scp-protocol you can do here.
Tools are method calls, not HTTP
When the brain returns{ target_body: "arm", tool: "move", parameters: { x: 1, y: 2 } }, Plexa looks up the body, calls body.invokeTool("move", { x: 1, y: 2 }), which calls arm.move({ x: 1, y: 2 }). Direct async method call. No serialization. No HTTP.
The only HTTP in the picture is brain to LLM and (optionally) Plexa to a remote body.
Inprocess vs network bodies
By default a body is in-process. To run it in another process, declare transport on the class:NetworkBodyAdapter that polls /state and /events, POSTs /tool, and (if static tools is empty) calls /discover to fetch the schema.
The four jobs
Plexa does four things and refuses to do anything else.| Job | Where | What |
|---|---|---|
| Translate | translator.js | Validate brain intent against the body’s tool schema. |
| Sequence | space.js | Order tick, brain, and dispatch each frame. |
| Aggregate | aggregator.js | Pack every body’s state into a token-budgeted prompt. |
| Gate | space.js | Safety rule, then approval hook, then dispatch. |