✦ Kiori

Kiori

Brains for characters. Kiori gives every character in your app a mind of its own: a past, a personality, people they love and resent, memories that fade or stay, and a strict sense of what they could possibly know.

You keep your chat, your model and your prompts. Kiori sits next to them:

your app ── record what happened ──▶  Kiori  (organizer writes each character's memories)
         ◀── context for this turn ──         (recall: no model call, ~free)
         ── check this draft ───────▶         (auditor: leaks, contradictions, invented past)

Why Kiori

Quickstart (5 minutes)

cd kiori                        # the Kiori folder
cp .env.example .env            # put your OpenRouter (or any OpenAI-compatible) key in KIORI_LLM_KEY
node bin/kiori.mjs project create "My studio"   # prints your API key once
node bin/kiori.mjs serve       # http://127.0.0.1:7700  (console at /console, docs at /docs)

Then, in your app, one of these:

// The drop-in: your existing OpenAI-style chat call, sent through Kiori (it adds the mind, your model writes)
const ai = new OpenAI({ baseURL: 'http://127.0.0.1:7700/v1', apiKey: process.env.KIORI_API_KEY,
  defaultHeaders: { 'X-Kiori-Upstream-Url': 'https://openrouter.ai/api/v1', 'X-Kiori-Upstream-Key': process.env.OPENROUTER_API_KEY } });
const reply = await ai.chat.completions.create({ model, messages }, { headers: { 'X-Kiori-Story': chat.id, 'X-Kiori-Characters': character.id } });
// Or one call per turn, for full control of your prompt
import { Kiori } from './sdk/kiori.mjs';
const kiori = new Kiori({ apiKey: process.env.KIORI_API_KEY });

// once per character, with your own id (a Tavern/SillyTavern card works too: character_card)
await kiori.characters.create({ external_id: 'char_mira', name: 'Mira',
  description: 'A lighthouse keeper on a cold island who used to be a war medic. Dry humor, hates being pitied.' });

// every turn: your conversation id and your recent messages, as they are now (edits and rerolls handled)
const turn = await kiori.turn({ story: { external_id: chat.id, characters: ['char_mira'], player: { name: 'Leo' } }, messages });
const systemPrompt = `${yourCharacterPrompt}\n\n${turn.characters[0].text}`;

Python (sdk/kiori.py, no dependencies) has the same calls; any other language can use plain HTTP or generate a client from /openapi.json. Learning runs by itself as the story grows.

Learn more