Skip to content

Quick Start

Run the demo

bash
npm install worldsim
OPENAI_API_KEY=sk-... npx worldsim demo
# Open http://localhost:4400 — watch a village react to water rationing

Or with Docker:

bash
OPENAI_API_KEY=sk-... docker compose up
# Open http://localhost:4400

Minimal TypeScript world

typescript
import {
  WorldEngine,
  ConsoleLoggerPlugin,
  InMemoryMemoryStore,
  InMemoryGraphStore,
  resolveLlmEnv,
} from "worldsim";

const llm = resolveLlmEnv();
if (!llm) throw new Error("Set OPENAI_API_KEY or OPENROUTER_API_KEY");

const world = new WorldEngine({
  worldId: "my-village",
  maxTicks: 20,
  llm,
  memoryStore: new InMemoryMemoryStore(),
  graphStore: new InMemoryGraphStore(),
});

world.use(ConsoleLoggerPlugin);

world.addAgent({
  id: "maria",
  role: "person",
  name: "Maria Rossi",
  iterationsPerTick: 2,
  profile: {
    name: "Maria Rossi",
    personality: ["practical", "stubborn"],
    goals: ["Save the harvest"],
  },
  systemPrompt: "You are Maria, a farmer worried about water rationing.",
});

await world.start();

That is the smallest useful loop: create a world, add at least one person agent, run ticks, inspect logs or attach report/Studio plugins.

OpenRouter

WorldSim uses an OpenAI-compatible LLM adapter. To run via OpenRouter:

bash
export OPENROUTER_API_KEY=sk-or-v1-...
export LLM_MODEL=mistralai/mistral-nemo
export OPENROUTER_APP_NAME=worldsim
export OPENROUTER_HTTP_REFERER=https://github.com/francemazzi/worldsim
npx worldsim demo

Or programmatically with resolveLlmEnv():

typescript
import { WorldEngine, resolveLlmEnv } from "worldsim";

const llm = resolveLlmEnv();
if (!llm) throw new Error("Set OPENAI_API_KEY or OPENROUTER_API_KEY");

const world = new WorldEngine({ worldId: "demo", llm, /* ... */ });

Supported env vars: OPENAI_API_KEY, OPENROUTER_API_KEY, LLM_BASE_URL, LLM_MODEL, OPENROUTER_HTTP_REFERER, OPENROUTER_APP_NAME.

If both OPENROUTER_API_KEY and OPENAI_API_KEY are set, resolveLlmEnv() uses OpenRouter. Pass an explicit llm config to WorldEngine when you want to force another provider.

Emergence-style cross-vendor integration test

A scaled-down reproduction of the Emergence World cross-LLM study runs three parallel micro-worlds (homogeneous model A, homogeneous model B, mixed population) via OpenRouter.

Copy .env.example to .env, set OPENROUTER_API_KEY, then:

bash
npm run test:integration:emergence

Optional env vars:

VariableDefaultPurpose
EMERGENCE_MODEL_Agoogle/gemini-2.5-flashModel for homogeneous A / half of mixed
EMERGENCE_MODEL_Banthropic/claude-3-haikuModel for homogeneous B / other half of mixed
EMERGENCE_MAX_TICKS8Simulation length
EMERGENCE_MAX_CONCURRENT2Parallel agent cap (rate-limit friendly)

Without OPENROUTER_API_KEY the test suite is skipped automatically.

To regenerate the README example assets (writes docs/public/emergence-study-overview.*, emergence-m2-example.json, .svg, and .png):

bash
npm run emergence:chart          # live OpenRouter run
npm run emergence:chart:render   # render SVG from committed JSON only

What To Build First

GoalStart here
Watch a ready-made scenarionpx worldsim demo or npx worldsim studio
Build your own policy simulationCopy evaluation/scenarios/water-rationing/
Test realistic location/senses behaviorRead Perception Layer and copy evaluation/scenarios/village-realistic/
Compare legacy vs perceptionnpm run eval:compare-perception
Integrate WorldSim in an appUse WorldEngine, stores, plugins and the generated SimulationReport

Released under the MIT License.