PAMbaseDocs
Guide

Game.

Build an NPC that remembers the player — across sessions and even across other narrative apps. At session start you read the player's memory (durable facts the platform stores about them) and adapt dialogue and difficulty with no LLM call, so it stays instant and free.

Prerequisites

You have a connection token from the connect flow — the credential issued after the player grants access. It carries these scopes (per-app permissions):

context:read:app.session.start, memory:read:world.*, memory:write:world.*, signal:emit, identity:read.

Scopes to request

ScopeWhy
context:read:app.session.startfetch the session-start context bundle
memory:read:world.*read narrative state other story apps wrote
memory:write:world.*record the player's choices to the shared world
signal:emitnotify other narrative apps when the world changes
identity:readoptional display name + tone note

What to write

Record player choices as durable memories in the shared world.* scope so any narrative app can recall them — the content is just natural-language text, no LLM required to write. To also notify other apps in real time that the world changed, emit a signal — that part isn't memory.

typescript
// Durable world memory any narrative app can recall:
const res = await pambase.remember({
content: "Spared the bandit in chapter 3 on the Kingsroad.",
kind: "world",
scope: "world.kingsroad",
});
// res -> { accepted: true, memoryIds: ["mem_…"] }
// Optional real-time nudge to subscribers (not stored as memory):
await pambase.emitSignal({
type: "world.choice",
payload: { scope: "world.kingsroad", choice: "spared_the_bandit", chapter: 3 },
});

How to read — Pattern B

Fetch a context bundle for the app.session.start intent (the named situation you're reading for), then branch directly on its suggestions.adaptation hint and the world.* memories. No LLM.

typescript
const ctx = await pambase.getContext({
intent: "app.session.start",
query: "energy combat preference",
});
// ctx -> { identity: { aiId, name }, memories: [...], relationships: [...],
// suggestions: { adaptation: "Player seems low-energy; keep it gentle." }, ... }
const lowEnergy = /low energy|tired|exhausted/i.test(ctx.suggestions.adaptation);
scene.enemyCount = lowEnergy ? 3 : 6;
const worldFacts = ctx.memories.filter((m) => m.scope?.startsWith("world."));
npc.recognizesPlayer = worldFacts.some((m) => /bandit/i.test(m.content));

Proactive (optional)

Most games only read at session start. To react when another app writes to the world, subscribe to a webhook.

Only write shareable facts to world.*

Use the shared world.* scope for facts other narrative apps should see (alliances, fates). Don't write plot reveals or unsolved puzzles to shared memory — anything in world.* is readable by every app the player grants, so it could spoil other games. See reading context.

Next

Reading context · Scopes & the world.* namespace · Remember & recall