Getting Started
This page shows the shortest path from installation to a working BoxBrain persona.
Requirements
- Bun
>= 1.2.0 - TypeScript
- A model adapter object that implements BoxBrain's provider-agnostic interfaces
- Optional but recommended: a SQLite-backed IdentityDB store via
createSqliteIdentityMemoryStore
Install
For local development inside the repository:
bun install
bun run test
bun run check
bun run build
For a consuming app, install the package normally if it is available in your registry:
bun add boxbrain
If consuming directly from the Gitea repository, pin a commit for reproducibility:
bun add git+https://git.psw.kr/p-sw/BoxBrain.git#49f75af
1. Create a memory store
Use InMemoryMemoryStore for tests and demos:
import { InMemoryMemoryStore } from 'boxbrain';
const memory = new InMemoryMemoryStore();
Use SQLite + IdentityDB for persistent persona memory:
import { createSqliteIdentityMemoryStore } from 'boxbrain';
const memory = await createSqliteIdentityMemoryStore('.data/personas.sqlite');
2. Provide model adapters
BoxBrain does not hard-code OpenAI, xAI, OpenRouter, Anthropic, or any other provider. The host app supplies objects that match the model interfaces.
A minimal conversation model:
import type { ConversationModel } from 'boxbrain';
const conversation: ConversationModel = {
async generateReply(input) {
// Call your LLM here.
// input.instruction contains BoxBrain's chat-like send_message guidance.
// input.context contains message history, memory, schedule, and availability.
return {
messages: ['I was just studying a bit.', 'How about you?'],
reasoning: 'Short casual reply matching the persona.',
};
},
};
A minimal memory extraction model:
import type { MemoryExtractionModel } from 'boxbrain';
const memoryExtraction: MemoryExtractionModel = {
async extract(input) {
// Call your LLM here and return durable, objectivized facts.
return [
{
statement: 'The user started TypeScript in 2025.',
topics: ['user', 'TypeScript', '2025'],
confidence: 0.9,
},
];
},
};
Optional model hooks:
models.initialization: extracts initial persona facts from the seed message.models.rewrite: decides whether to discard a stale draft if new messages arrived while generating.
3. Create a persona
import { Persona } from 'boxbrain';
const persona = new Persona(
'Mina',
'Mina is a careful student who likes quiet cafes and is preparing for exams.',
{
memory,
models: { conversation, memoryExtraction },
now: '2026-05-01T10:00:00.000Z',
debug: (event) => console.log(event),
},
);
const space = await persona.ready();
console.log(space.id);
Creation behavior:
new Persona(displayName, seedMessage, options)creates a new isolated persona space.- The seed message is the freeform source for personality, history, likes, dislikes, relationships, and other persona facts.
- If
models.initializationis provided, BoxBrain asks it for initial facts. - If no initialization model is provided, BoxBrain stores a minimal seed fact.
- If the initialization model intentionally returns an empty list, BoxBrain does not add the fallback fact.
Load an existing persona:
const loaded = new Persona(space.id, { memory, models: { conversation, memoryExtraction } });
await loaded.ready();
4. Generate schedules
Create tomorrow's 10-minute schedule:
const entries = await persona.createDailySchedule(
'2026-05-01T10:00:00.000Z',
'Keep a normal work day.',
);
console.log(entries.length); // 144
Create a 30-day day-level outline, starting tomorrow:
await persona.createMonthlySchedule(
'2026-05-01T10:00:00.000Z',
'Mostly study, with occasional rest.',
);
The default schedule helper is deterministic:
- sleep before 07:00 and after 23:00
- meal blocks around 07:00, 12:00, and 18:00
- commute around 08:00 and 17:00
- work/study/job-search/travel based on keywords in the message
- rest/free-time in the evening
5. Read availability
const availability = await persona.getTodayScheduledAvailability('2026-05-01T12:00:00.000Z');
The snapshot covers:
- today 00:00
- through tomorrow 24:00
For example, if datetime is May 1, the window is May 1 00:00 through May 3 00:00.
Availability is derived from schedule entries:
sleep->offlinework,study,job-search,travel,commute->do-not-disturbrest,meal,exercise,social,errand,free-time->online
6. Reply to a user message
const reply = await persona.sendMessage({
datetime: '2026-05-01T12:00:00.000Z',
messageHistory: [
{ sender: 'persona', time: '2026-04-30T23:00:00.000Z', content: 'See you later.' },
{ sender: 'user', time: '2026-05-01T12:00:00.000Z', content: 'What are you doing?' },
],
});
for (const message of reply.messages) {
await deliverToMessenger(message);
}
BoxBrain formats the structured history for the model as:
Mina@2026-04-30T23:00:00.000Z: See you later.
user@2026-05-01T12:00:00.000Z: What are you doing?
7. Start a proactive conversation
const opener = await persona.startConversation({
datetime: '2026-05-01T20:00:00.000Z',
messageHistory: [],
});
The same mandatory context pipeline is used, but the model input mode is start-conversation.
8. Run sleep memory at midnight
Recommended cadence: run once near midnight with the previous day's messages.
await persona.sleepMemory({
datetime: '2026-05-02T00:00:00.000Z',
messageHistory: messagesFromMay1,
});
sleepMemory asks the memory extraction model to objectivize durable facts, then persists them to the persona's memory store.
9. Add debug tracing
const persona = new Persona('Mina', seed, {
memory,
models,
debug(event) {
// Write to a log file, messenger admin channel, dashboard, etc.
console.log(`[${event.time}] ${event.name}`, event.data);
},
});
Common debug events:
persona.initializedpersona.loadedpersona.schedule.daily.generatedpersona.schedule.monthly.generatedpersona.schedule.deletedpersona.availability.refreshedpersona.conversation.context.loadedpersona.conversation.rewrite.checkedpersona.conversation.reply.generatedpersona.conversation.startedpersona.memory.sleep.persisted