Skip to main content
The simulator runs through ordinary TypeScript entrypoints and task runners. Experiment owners expose the command or operator surface that fits their domain. The code-first API keeps the network, lifecycle, and ledger contracts stable while each experiment owner chooses the operator surface appropriate to its domain. TypeScript entrypoints and task runners are the simulator’s normal execution path.

Package entry points

Simulator.define binds run and openLedger to one versioned definition and its complete event catalog.

Make a TypeScript entrypoint

A normal module is an executable experiment:
Run the module with the repository’s build target, Node entrypoint, test runner, workflow system, or scheduler. Construct simulatorLayer once at the application boundary and provide it around the complete run or suite. Runtime constructors remain values in the roster; they own runtime-specific installation and readiness settings.

Express completion policy in the program

The customer Effect returns, fails, or is interrupted according to its own logic:
Use Effect’s Clock, Schedule, race, timeout, Deferred, Stream, and Scope primitives for deadlines, quiescence, supervised work, or explicit stop conditions. A runtime exit after readiness is committed as typed ledger evidence. It does not implicitly end the customer Effect. This lets one policy fail fast on an agent exit while another continues to observe the remaining society.

Interpret both Effect layers

There are two distinct results:
  • The outer Society.run Effect can fail while acquiring the router or roster, or while writing and completing the ledger.
  • A successful outer Effect returns SimulatorRunResult, whose exit is the customer program’s Exit, ledger is the completed ledger reference, and completion carries the record count and artifact digests.
A customer command can map these typed values to its own exit codes, structured output, retries, and operator messages. The simulator package does not impose a process-wide exit-code table.

Build a narrow customer language when useful

Products can accept declarative input by placing that grammar next to the customer concepts it represents. For example, a customer might decode a schema with only a model id, topology preset, and prompt family, then compile each case into:
  1. customer event classes and an EventCatalog;
  2. one versioned Simulator.define value;
  3. a keyed mixed-runtime roster;
  4. an Effect program using roster.Agents, Network, Society.Events, and Society.Ledger;
  5. code graders composed over Society.openLedger.
That input may come from generated TypeScript, a database row, an HTTP request, or a customer-owned file format. The customer module owns the input unions, versioning, and migration policy.

Sweeps are orchestration

Use Effect and the surrounding job system for matrices and concurrency:
Schedules, retries, sharding, naming, resumption, and report aggregation stay at this layer. A single simulator run remains one definition-bound Effect and one completed ledger, keeping suite orchestration failures distinct from the evidence produced by a society.

Inspect ledgers in code

Use the same definition and storage Layer that produced the run:
readLedgerManifest supports indexing without reading event evidence. Society.openLedger returns reusable exact-class streams after the definition, catalog, artifact digests, identities, count, sequence, and event schemas validate.