Clone
2
Getting Started
Shinwoo PARK edited this page 2026-05-15 13:27:29 +09:00

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.initialization is 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 -> offline
  • work, study, job-search, travel, commute -> do-not-disturb
  • rest, 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.initialized
  • persona.loaded
  • persona.schedule.daily.generated
  • persona.schedule.monthly.generated
  • persona.schedule.deleted
  • persona.availability.refreshed
  • persona.conversation.context.loaded
  • persona.conversation.rewrite.checked
  • persona.conversation.reply.generated
  • persona.conversation.started
  • persona.memory.sleep.persisted