Examples
Three scenarios ship in examples/ and double as the acceptance fixtures:
| scenario | what it models | knobs in params | metrics |
|---|---|---|---|
prisoners_dilemma | an LLM player against a rule opponent over 10 rounds; the module, both actions and the opponent strategies live in rules.ts as a plugin template | framing canonical · moralized · risk, opponent titForTat · random · alwaysCooperate · alwaysDefect | cooperationRate, averagePayoff |
echo_chamber | 100 people on a power-law social graph with homophily rewiring and hub assignment, posting and reposting through a recommender feed | homophily, hub, activation, memoryWindow, feedSize | stanceAssortativity, sameGroupRatio, postShare |
echo_chamber/cohort.yaml | the same population as a columnar cohort of 100,000 with vectorized opinion dynamics | n | meanStance |
referendum | 200 voters loaded from a CSV survey file decide a local levy; an intervene step asks 20 of them to advocate, a questionnaire is the ballot, and a plugin metric turns the answers into a support share | homophily, activation, feedSize, memoryWindow | supportShare, stanceAssortativity |
Each has an audit.yaml next to it. Programmatic examples in examples/programmatic/ run against the public API and are executed by the test suite:
| file | shows |
|---|---|
01-run-and-inspect.ts | run a scenario, read metrics and integrity, query the event log with SQL, print one agent's causal chain |
02-custom-plugin.ts | define a module, two actions and a rule provider in code and run a scenario built from a YAML string |
03-audit.ts | run an audit from code, read the evidence grade and sensitivity ranking, render the HTML report |
04-replay-recordings.ts | replay the shipped DeepSeek recordings offline and confirm two replays share a digest |
05-cohort-scale.ts | override the population size of the cohort scenario and measure throughput |
bun examples/programmatic/01-run-and-inspect.tsThe core of the first one:
import { inspect, loadScenario, runScenario, withRunLog } from "@misakaikato/simulacra";
const scenario = loadScenario("examples/echo_chamber/scenario.yaml");
if (!scenario.ok) throw new Error(JSON.stringify(scenario.error));
const result = await runScenario(scenario.value, "runs/echo", {
providerOverride: "mock",
ticksOverride: 5,
});
if (!result.ok) throw new Error(result.error.message);
console.log(result.value.metrics, result.value.integrity);
const counts = withRunLog("runs/echo", (log) => ({
ok: true as const,
value: log.sql<{ kind: string; n: number }>(
"select kind, count(*) as n from events group by kind",
),
}));
const trace = inspect("runs/echo", { agentId: someAgentId, tick: 2 });Copying an example
bun run simulacra examples lists the built-in examples with their scenario.yaml paths. bun run simulacra examples <name> --out <dir> copies the whole directory, scenario, audit plan and recordings included, so the relative paths inside keep working from the copy.
Prisoner's dilemma
Repeated prisoner's dilemma: an LLM-driven player against a rule-driven opponent (params.opponent: titForTat, random, alwaysCooperate, alwaysDefect; params.framing: canonical, moralized, risk). The pd world module, its cooperate/defect actions and the pdRule provider live in rules.ts, declared by the scenario's plugins field and loaded automatically.
Run without an LLM: bun run simulacra run examples/prisoners_dilemma/scenario.yaml --seed 1 --provider mock --out ./pd-run
Run against the configured endpoint (needs SIMULACRA_LLM_API_KEY): drop --provider mock; then bun run simulacra inspect ./pd-run --agent <id> --tick 3 shows one round's observation, prompt, decision and effects.
Files: scenario.yaml, audit.yaml, rules.ts and the recordings/ directory. The audit plan perturbs persona format, framing and memory representation, three representation axes with three levels each; it is the plan behind the live report.
Echo chamber
Files: scenario.yaml (100 focal agents on a power-law graph with a recommender feed), cohort.yaml (the same population as a columnar cohort of 100,000 with a vectorised opinion-dynamics transition), audit.yaml (five design axes: homophily, hub assignment, activation, memory window and feed size) and the recordings/ directory.
Programmatic examples
The five programs in examples/programmatic/ import the public API and run with bun examples/programmatic/<file>; the test suite executes each of them. The plugins page embeds the second one in full.
Referendum
Files: scenario.yaml, audit.yaml, ballot.ts and voters.csv.
Two hundred voters, loaded from a CSV rather than sampled, debate a transit levy on a homophilous social graph. Twenty of them are asked to advocate publicly: in the control arm they are drawn at random, in the treatment arm only from committed supporters. A questionnaire then puts the ballot to everyone, and the supportShare metric in ballot.ts reads the answers back out of the event log.
It is the example that exercises the parts the other two leave out: a population from a file, an intervention step with selectable arms, a questionnaire instrument, a hypothesis with a control and a treatment, and a metric that ships as a plugin. Its audit plan is the one case here that claims a policy effect, so the evidence grade demands axes at all three levels: the intervention arm at the macro level, homophily and activation at the meso level, persona and memory format at the micro level.