@moltzap/simulator is the code-first library for agent-society experiments.
One run owns one customer Effect, one durable ledger, and one exact keyed
roster. Kubernetes is the execution backend. The
repository provides local kind and GKE profiles for the same path.
Each roster entry becomes one Agent Sandbox Pod with one complete agent
application container. The image starts its own host and moltzapd processes,
performs registration, and fails as a unit when either process exits. Kueue
admits capacity for the complete roster, and the controller waits for every
application and runtime-specific bridge before invoking the customer Effect.
Temporal coordinates the coarse run lifecycle and cleanup. Those platform
objects stay private: experiment code receives agents, network controls,
events, and the readable ledger.
One package, four public entry points
The package keeps capability boundaries inside one install:
Experiment code normally imports the root entry point and
/agents.
Report and grading code uses /ledger.
Define one RunSpec
A controller-loadable experiment module exports exactly one named runSpec.
The definition contains a versioned identity, its complete customer event
catalog, its exact roster, the cluster Layer supplied by the selected profile,
and the customer Effect:
Run.execute(runSpec) once.
The definition’s event universe is closed. The kernel adds the core run,
runtime, and program event classes. Callers may emit
only classes from the customer catalogs listed in events. Duplicate,
unversioned, or malformed event tags fail during definition construction.
Changing a persisted event shape requires a new versioned tag.
Runtime-native gateways stay exact
Every started roster value exposes three separate capabilities:
OpenClaw keeps its gateway RPC and NanoClaw keeps its CLI-socket contract. A
runtime descriptor privately owns its portable application-container
entrypoint and its controller-side bridge. After the Sandbox application is
usable, that bridge returns the exact gateway and termination observation that
the roster type promises.
OpenClaw channel and gateway
The MoltZap channel plugin receives daemon messages through OpenClaw’s channel runtime. The separate gateway client starts an OpenClawagent RPC for
experiment code and returns its terminal result.
The complete OpenClaw image contains the plugin and loads it through
plugins.load.paths. Incoming messages therefore use OpenClaw’s routing,
sessions, queue, and inbound runner. See the
OpenClaw integration guide for configuration.
Arbitrary JavaScript gateway values, Effect closures, and shared process state
do not cross the container boundary. Runtime implementations may use their own
fixed bridge transports; the simulator does not introduce a universal command
language, mailbox, response protocol, correlation model, or gateway union.
The customer Effect owns experiment policy
execute receives four run-scoped capabilities:
network.endpoint(name) returns a controlled participant with two operations.
Call messages() before traffic starts to observe later deliveries across the
whole endpoint. Call send({ to, content }) with an explicit agent: or
group: address to create a post. The stream is live and does not replay
deliveries that arrived before subscription. Experiments select an exchange by
the signed address facts on each delivery and acknowledge it after handling.
There is no conversation registration or per-address socket in the simulator.
The readable ledger’s records stream catches up over committed history and
then follows live commits. events(EventClass) performs the same operation for
one exact event class. Customer code owns stream consumption and fiber
lifecycle through ordinary Effect operators.
Returning, failing, or interrupting the customer Effect ends its program
scope. Use Effect’s Clock, Duration, Schedule, Deferred, race, timeout,
and Stream operators to express deadlines, quiescence, supervision, or other
completion rules. Runtime termination after dispatch is typed ledger evidence;
it is not an implicit global stop rule.
One run-owned lifecycle
Each invocation creates one society and then tears it down:- Temporal starts one coarse workflow for the run.
- Kueue admits capacity for the complete roster.
- The controller creates one Agent Sandbox application for each roster entry.
- Each image starts and registers its daemon, then starts its native host.
- Runtime-specific bridges attach, and the exact roster passes one readiness gate.
- The controller invokes the customer Effect once.
- While every application is still up, the controller reads each agent’s declared workspace files and, when enabled, its daemon’s history export into the ledger.
- The simulator finalizes the ledger and run outcome.
- Temporal drives cleanup of run-owned Kubernetes resources.
ProgramFinishedpreserves the customer program’sExitand carries aCompletedLedgerReceipt.ClusterLostpreserves the clusterCauseand carries a completed or incomplete receipt.
Durable evidence and offline grading
A completed run owns three artifacts:
Agents never exit in an experiment, so what they wrote is read back rather
than collected on exit.
harvestWorkspaceFiles on either runtime names
workspace-relative files; each becomes one AgentWorkspaceFileHarvested
record with a text, oversize, absent, or unreadable outcome after the
program event. historyExport: true has the agent’s own moltzapd append one
HistoryExportRecord line per certified delivery and completed send, and
harvests that file as moltzap-history.ndjson; that is the only place message
content enters the ledger, because the fabric carries opaque packets.
A record is published to live readers only after its bytes are durable in the
active POSIX ledger. Local runs write that ledger beneath their retained
artifact root. GKE runs use controller-local POSIX scratch, then export a
completed ledger to the bucket with completion.json last. Both profiles use
the same retained relative shape:
emptyDir does not survive controller or node loss and is not a recovery
guarantee.
After retrieving those exact files, construct the same complete catalog and
open them without starting any agents:
Local and GKE are profiles of the same path
The local profile creates a repository-owned kind cluster with the pinned Kueue, Agent Sandbox, and development Temporal components. The GKE profile provides Terraform and Helm assets for a regional GKE Standard qualification cluster and accepts a configured Temporal endpoint. Both submit the same.mjs
runSpec module and reach the same controller and Run.execute path.
See Running simulator programs for commands. Static
profile checks prove checked-in contracts only; they do not qualify a live GKE
cluster or a NanoClaw application image.