MolrooWorld
Main entry point class — world creation, chat, events, ticking, mutations, and snapshots.
MolrooWorld
MolrooWorld is the main SDK class for interacting with a molroo world instance. It provides methods for chat, events, time progression, mutations, snapshots, and querying world state.
import { MolrooWorld } from '@molroo-ai/sdk';Static Methods
MolrooWorld.create(config, setup)
Create a new world on the molroo API and return a connected instance.
static async create(
config: {
baseUrl: string;
apiKey: string;
llm?: LLMAdapter;
storage?: StorageAdapter;
memory?: MemoryAdapter;
events?: EventAdapter;
},
setup: CreateWorldInput,
): Promise<MolrooWorld>Parameters:
| Parameter | Type | Description |
|---|---|---|
config.baseUrl | string | Base URL of the molroo API (e.g., 'https://api.molroo.io') |
config.apiKey | string | API key for authentication |
config.llm | LLMAdapter | Optional LLM adapter for generating responses |
config.storage | StorageAdapter | Optional storage adapter for snapshot backup |
config.memory | MemoryAdapter | Optional memory adapter for episode persistence |
config.events | EventAdapter | Optional event adapter for SDK-level events |
setup | CreateWorldInput | World definition, entities, spaces, and persona configs |
Example:
const world = await MolrooWorld.create(
{ baseUrl: 'https://api.molroo.io', apiKey: 'key', llm },
{
definition: {
identity: { name: 'Cafe World', genre: 'slice-of-life', tone: 'warm' },
},
entities: [
{ name: 'user', type: 'user' },
{ name: 'Sera', type: 'persona' },
],
personaConfigs: {
Sera: {
identity: { name: 'Sera', role: 'barista' },
personality: { O: 0.7, C: 0.6, E: 0.8, A: 0.9, N: 0.3, H: 0.8 },
},
},
},
);MolrooWorld.connect(config, worldId)
Connect to an existing world by ID. Verifies the world exists and fetches persona configs.
static async connect(
config: {
baseUrl: string;
apiKey: string;
llm?: LLMAdapter;
storage?: StorageAdapter;
memory?: MemoryAdapter;
events?: EventAdapter;
},
worldId: string,
): Promise<MolrooWorld>Example:
const world = await MolrooWorld.connect(
{ baseUrl: 'https://api.molroo.io', apiKey: 'key', llm },
'existing-world-id',
);MolrooWorld.listWorlds(config)
List all worlds for the authenticated tenant.
static async listWorlds(config: {
baseUrl: string;
apiKey: string;
}): Promise<{ worlds: WorldSummary[]; nextCursor?: string }>Example:
const { worlds } = await MolrooWorld.listWorlds({
baseUrl: 'https://api.molroo.io',
apiKey: 'key',
});
for (const w of worlds) {
console.log(w.id, w.definition.identity?.name);
}Properties
| Property | Type | Description |
|---|---|---|
id | string | Unique identifier for this world instance |
worldId | string | Alias for id |
Chat
chat(to, message, options?)
Send a message to an entity and get an emotion-processed response.
With LLM adapter: Fetches world context, generates a response via the configured LLM, then sends it to the API for emotion processing.
Without LLM adapter: Requires options.appraisal to be provided. Sends the message directly to the API for emotion-only computation.
async chat(
to: string,
message: string,
options?: ChatOptions,
): Promise<ChatResult>Parameters:
| Parameter | Type | Description |
|---|---|---|
to | string | Target entity name (e.g., 'Sera') |
message | string | The message text to send |
options.from | string | Sender name. Defaults to 'user' |
options.appraisal | AppraisalVector | Manual appraisal — skips LLM, uses emotion-only mode |
options.includeState | boolean | Include full internal state in result |
options.history | Array<{ role, content }> | Conversation history for LLM context |
options.propagateToSpace | boolean | Override world-level groupAwareness (false = whisper) |
Returns: ChatResult
Example (with LLM):
const result = await world.chat('Sera', 'How are you today?');
console.log(result.response.text);
// "I'm doing great! The morning rush was fun."
console.log(result.response.emotion.discrete.primary);
// 'joy'
console.log(result.response.emotion.vad);
// { V: 0.65, A: 0.42, D: 0.38 }Example (emotion-only, no LLM):
const result = await world.chat('Sera', 'Hello', {
appraisal: {
goal_relevance: 0.5,
goal_congruence: 0.8,
expectedness: 0.6,
controllability: 0.5,
agency: 0,
norm_compatibility: 0.7,
},
});
// result.response.text will be empty — only emotion data is returnedgetContext(entityNameOrId)
Get the world context from the perspective of a specific entity. Returns spatial awareness, nearby entities, recent events, and world state. This is the data the SDK uses to build LLM prompts.
async getContext(entityNameOrId: string): Promise<WorldContext>Returns: WorldContext
Example:
const ctx = await world.getContext('Sera');
console.log(ctx.whoAmI); // 'Sera'
console.log(ctx.whereAmI); // 'Main Cafe'
console.log(ctx.whoIsHere); // ['user', 'Mika']
console.log(ctx.whatHappened); // recent WorldEvent[]Events
event(input)
Dispatch a world event that affects one or more entities. Events can carry an appraisal (cognitive evaluation) or a direct stimulus (raw physiological/emotional manipulation).
async event(input: EventInput): Promise<EventResult>Parameters: See EventInput
Returns: EventResult
Example (appraisal-based):
const result = await world.event({
type: 'surprise_party',
target: 'Sera',
payload: { description: 'Everyone jumps out and yells surprise!' },
appraisal: {
goal_relevance: 0.8,
goal_congruence: 0.9,
expectedness: 0.1,
controllability: 0.2,
agency: -0.5,
norm_compatibility: 0.8,
},
});
console.log(result.affected[0].response.emotion.discrete.primary);
// 'surprise'Example (stimulus-based):
await world.event({
type: 'battle_start',
target: 'Sera',
stimulus: {
vadDelta: { A: 0.3, V: -0.2 },
bodyBudgetDelta: -0.1,
},
});Tick / Time
tick(seconds)
Advance world time by the specified number of seconds. Processes emotion decay, pending events, and phase transitions.
async tick(seconds: number): Promise<TickResult>Returns: TickResult
Example:
const result = await world.tick(60); // advance 1 minute
console.log(result.elapsedSeconds); // 60
console.log(result.phaseChanged); // undefined or { from, to, triggerId }timeJump(seconds, milestoneEvent?)
Jump forward in time with an optional milestone event. Unlike tick(), time jumps can span large periods.
async timeJump(
seconds: number,
milestoneEvent?: Record<string, unknown>,
): Promise<TickResult>Example:
// Jump 1 hour with a milestone
const result = await world.timeJump(3600, {
type: 'storm_arrives',
description: 'A sudden thunderstorm hits the area.',
});Query
query(include?)
Query world state, selecting which data sections to include. If include is omitted, returns all sections.
async query(include?: QueryInclude[]): Promise<QueryData>Parameters:
| Parameter | Type | Description |
|---|---|---|
include | QueryInclude[] | Data sections: 'entities', 'spaces', 'environment', 'definition', 'phase' |
Returns: QueryData
Example:
const data = await world.query(['entities', 'spaces']);
for (const entity of data.entities ?? []) {
console.log(entity.name, entity.type, entity.spaceId);
}Mutate
mutate(ops)
Execute one or more mutation operations on the world atomically. Supports adding/removing entities, moving entities, setting relationships, managing spaces/connections, updating environment, and managing facts/phases.
async mutate(ops: MutateOp[]): Promise<MutateResult>Parameters: Array of MutateOp operations.
Returns: MutateResult
Example:
const result = await world.mutate([
{ op: 'add_entity', name: 'Mika', type: 'persona' },
{ op: 'move_entity', target: 'Mika', toSpace: 'Kitchen' },
{ op: 'set_relationship', entityA: 'Sera', entityB: 'Mika', relationship: { type: 'colleague', trust: 0.7 } },
{ op: 'update_environment', environment: { weather: 'rainy' } },
]);
for (const r of result.results) {
console.log(r.op, r.ok, r.error);
}Entity Management
Convenience methods that wrap mutate() for common entity operations.
addEntity(input)
Add a new entity to the world.
async addEntity(input: {
name: string;
type?: string; // Defaults to 'secondary'
profile?: UserProfile;
spaceId?: string;
}): Promise<MutateOp & { data?: unknown }>Example:
await world.addEntity({
name: 'Mika',
type: 'persona',
spaceId: 'kitchen',
});removeEntity(target)
Remove an entity from the world.
async removeEntity(target: string): Promise<void>moveEntity(target, toSpace)
Move an entity to a different space.
async moveEntity(target: string, toSpace: string): Promise<void>Example:
await world.moveEntity('Sera', 'Kitchen');Space
addSpace(input)
Add a new space to the world.
async addSpace(input: {
name: string;
spaceType?: string;
capacity?: number;
}): Promise<MutateOp & { data?: unknown }>Example:
await world.addSpace({ name: 'Rooftop', spaceType: 'physical', capacity: 10 });Relationship
setRelationship(entityA, entityB, relationship)
Set a relationship between two entities.
async setRelationship(
entityA: string,
entityB: string,
relationship: RelationshipInput,
): Promise<void>Parameters: See RelationshipInput
Example:
await world.setRelationship('Sera', 'Mika', {
type: 'best_friend',
strength: 0.9,
trust: 0.85,
});Environment
updateEnvironment(environment)
Update the world environment (weather, location, ambiance, etc.).
async updateEnvironment(environment: Partial<EnvironmentInput>): Promise<void>Example:
await world.updateEnvironment({
weather: 'thunderstorm',
ambiance: 'tense and quiet',
});Definition
updateDefinition(definition)
Update the world definition (identity, rules, culture, etc.). Merges with existing definition.
async updateDefinition(definition: Record<string, unknown>): Promise<void>Example:
await world.updateDefinition({
identity: { tone: 'dark' },
rules: { narrative: { violenceLevel: 'high' } },
});Snapshot
snapshot()
Get a full snapshot of the world state, including all entities, spaces, environment, knowledge, progression, and persona snapshots.
async snapshot(): Promise<WorldSnapshot>Returns: WorldSnapshot
loadSnapshot(snapshot)
Restore the world state from a previously saved snapshot.
async loadSnapshot(snapshot: WorldSnapshot): Promise<void>Example:
// Save
const snap = await world.snapshot();
// ... later ...
// Restore
await world.loadSnapshot(snap);saveSnapshotToStorage(key?)
Save the current world snapshot to external storage. Requires a StorageAdapter to be configured.
async saveSnapshotToStorage(key?: string): Promise<WorldSnapshot>| Parameter | Type | Default | Description |
|---|---|---|---|
key | string | snapshots/{worldId}/latest.json | Storage key |
loadSnapshotFromStorage(key?)
Load a world snapshot from external storage and apply it. Requires a StorageAdapter to be configured.
async loadSnapshotFromStorage(key?: string): Promise<void>Throws MolrooApiError with code STORAGE_NOT_FOUND if the snapshot does not exist at the given key.
Persona Configs
fetchPersonaConfigs()
Fetch persona configs from the API and cache locally. Called automatically by MolrooWorld.connect().
async fetchPersonaConfigs(): Promise<Record<string, PersonaConfigData>>getPersonaConfig(entityName)
Get the cached persona config for a specific entity. Returns undefined if not cached.
getPersonaConfig(entityName: string): PersonaConfigData | undefinedExample:
const config = world.getPersonaConfig('Sera');
console.log(config?.personality); // { O: 0.7, C: 0.6, E: 0.8, ... }
console.log(config?.identity); // { name: 'Sera', role: 'barista', ... }Lifecycle
destroy()
Soft-delete this world. Can be restored with restore().
async destroy(): Promise<void>restore()
Restore a previously soft-deleted world.
async restore(): Promise<void>