Developer Quickstart
Working code in 60 seconds. MockProvider by default. Zero paid inference required.
4 Steps to a Living Society
Clone & Install
Get the code and install dependencies
git clone https://github.com/M4G3LL4N0/grokbot-society.gitcd grokbot-societypnpm installVerification:
pnpm typecheck && pnpm testRun the Demo
Boot a live society on MockProvider ($0)
pnpm devVerification:
Output shows 5 persons, 29 roles, 11 circles, 1 model call, $0 costUse the CLI
Persistent database with full operator control
pnpm society start --db ./my-society.dbpnpm society status --db ./my-society.dbpnpm society people --db ./my-society.dbpnpm society chat "Hello everyone!" --circle <INNER_CIRCLE_ID> --db ./my-society.dbVerification:
Interactive REPL with 3-speaker bounded scenes at $0Explore the Society
Inspect persons, relationships, circles, landmarks, sessions
pnpm society person Emma --db ./my-society.dbpnpm society circles --db ./my-society.dbpnpm society landmarks Emma --db ./my-society.dbpnpm society session start evening_social --db ./my-society.dbpnpm society simulate --db ./my-society.dbVerification:
Identity cards, relationship dims, landmarks, cost simulator outputCode Examples
Create a Person
Zero inference — pure structured state
const kernel = createKernel(
{ maxPersons: 1000 },
{ clock: new SimulatedClock() }
);
const person = kernel.createPerson({
name: "Aria Chen",
biography: "Urban explorer and street photographer.",
identity: { core: "curious, observant, quietly intense" },
personality: { summary: "notices what others miss" },
interests: ["photography", "urban exploration", "coffee"],
currentState: { mood: 0.3, availability: "available", socialIntensity: "normal" },
});
console.log(person.id); // p_...Assign Roles
Composable behavior at zero cost
kernel.assignRole(person.id, "friend");
kernel.assignRole(person.id, "creative_friend");
kernel.assignRole(person.id, "storyteller");
kernel.assignRole(person.id, "listener");
// At scene time, only context-relevant roles compose into the Actor
const actor = kernel.composeActorContext(
person.id,
"event:123",
[person.id, otherPerson.id],
circleId
);
// actor.roles = [friend, creative_friend, storyteller, listener]Run a Group Scene
One inference, multiple speakers, bounded context
const innerCircle = kernel.circles.list()
.find(c => c.name === "Inner Circle");
const event = await kernel.tell(
"Anyone up for a spontaneous road trip this weekend?",
{ circleId: innerCircle.id }
);
// event.payload.sceneResult.output.messages = [
// { personId: "p_...", text: "Sounds good — tell me more...", person: "Sam" },
// { personId: "p_...", text: "Ha, that's a vibe. I'm in.", person: "Emma" },
// { personId: "p_...", text: "I've been thinking about exactly that...", person: "Leo" }
// ];
console.log(`Model calls: ${kernel.stats().modelCalls}`); // 1
console.log(`Est. spend: $${kernel.stats().totalCost.toFixed(6)}`); // 0.000000Inspect the Society
Full introspection at zero cost
// Person identity card
const card = kernel.identityCard(person.id);
console.log(card.name, card.archetype, card.essence, card.voice);
// Relationships
const rels = kernel.relationship.relationshipsFor(person.id);
rels.forEach(r => console.log(
r.otherName, r.status, r.interactions,
`${r.dims.familiarity.toFixed(2)}/${r.dims.trust.toFixed(2)}/${r.dims.affection.toFixed(2)}`
));
// Landmarks (shared history)
const landmarks = kernel.memory.landmarksFor(person.id);
landmarks.forEach(l => console.log("•", l.content));
// Cost simulator
const sim = kernel.cost.simulate({ population: 5000 });
sim.forEach(s => console.log(
s.name, s.modelCalls, `$${s.estimatedSpend.toFixed(4)}`, s.note
));MockProvider — The Default
The entire system boots and runs through MockProvider with no paid model configured. It is a deterministic, zero-cost stand-in that still exercises the full structured single-inference scene protocol: one call in, one SceneOutput (multi-message) out.
- Deterministic structured output (SceneProviderPayload)
- Exercises full gateway → cache → budget → provider → validation pipeline
- Returns multi-message scenes with memory/relationship/timeline/followup candidates
- Subject to all budget rules (kill switch, caps, token limits, tier gate)
- Cost: $0.000 per call, forever
Key APIs at a Glance
kernel.tell(prompt, { circleId })
Main interaction entry. Returns SocietyEvent with sceneResult.
kernel.ensureSeeded()
Idempotent seed (5 persons, 29 roles, 11 circles, 10 rels, 5 landmarks).
kernel.proactiveTick(circleId?)
Explicit proactive pass. Default off → 0 calls. Configurable relevance/cooldown/budget.
kernel.identityCard(personId)
Compact frozen Person snapshot (name, archetype, essence, voice, interests, goals).
kernel.composeActorContext(...)
Bounded Actor for one scene. Person + Roles + Relationships + Memory + SceneRef.
kernel.usage()
Telemetry: calls, tokens, spend per person/circle/provider, blockedCalls, escalations, trips.
kernel.setKillSwitch(true)
Fail-closed kill switch. All inference blocked → deterministic fallback. blockedCalls increments.
kernel.sessionStart/Context/End
Long-session abstraction. Rolling window (6 msgs) + participant cards (4).