> ## Documentation Index
> Fetch the complete documentation index at: https://docs.kairn.sh/llms.txt
> Use this file to discover all available pages before exploring further.

# Core Concepts

> The mental model behind Kairn — souls, memory, sessions, mandates, and multi-tenancy.

## Soul

A soul is an agent identity — the "who" and "what" of your agent. It has two distinct parts:

* **Character** (`soulMd`) — WHO the agent is. Written like a hire brief, not a rules list. Voice, values, judgment style. This is what makes the agent behave sensibly in situations you never explicitly anticipated.
* **Context** (`agentsMd`) — WHAT the agent operates in. The product, the users, the domain, the constraints. Situational awareness, not personality.
* **Allowed tools** — what the agent can actually do. You control this explicitly.
* **Model** — which LLM powers this soul. Supports Anthropic, OpenAI, and OpenRouter models.

> [!NOTE]
>
> One soul serves all your users. Each user gets their own isolated context on top of it. Change the soul's character once — every user gets the update on the next invocation.

```ts theme={null}
await kairn.souls.create({
  name: 'support',
  soulMd: `
    Hired as a senior support specialist for Acme CRM.
    You've seen every kind of customer situation — frustrated, confused, delighted.
    You lead with empathy, resolve quickly, and escalate without hesitation when needed.
    You never make the customer feel like a ticket number.
  `,
  agentsMd: `
    Product: Acme CRM — B2B sales CRM for mid-market teams.
    Users: sales reps and managers, non-technical, under pressure.
    Constraints: never access data outside the current user's account.
                 always confirm before destructive actions.
  `,
  defaultModel: 'anthropic/claude-sonnet-4-6',
  allowedSkills: ['web_search'],
})
```

***

## Memory

Every user gets a persistent memory store, scoped to them. The agent reads it at the start of each invocation and can write to it during the session. Memory has four semantic categories — each tells the agent how to use the information, not just what it is.

| Category | What to store | How the agent uses it |
| - | - | - |
| `fact` | Name, plan, company, role | Personalization — skip asking what you already know |
| `pattern` | Communication style, decision pace, recurring concerns | Adapt approach to match how they think |
| `preference` | Response length, tone, detail level | Shape response style before writing a word |
| `note` | Significant moments, relationship context | Draw on when it adds genuine value |

> [card] Agent writes
>
> The agent uses built-in tools to write what it observes — preferences, patterns, relationship history — with the right category.

> [card] Your app writes
>
> You write ground truth from your database — plan, name, recent DB state. The agent treats it as authoritative.

```ts theme={null}
// Seed context from your database before the agent runs
await kairn.memory.set(userId, 'default', {
  plan: 'pro',
  company: 'Acme Corp',
  account_manager: 'Sarah',
  open_tickets: '3',
})
```

After the agent runs, `result.memoryDelta` tells you exactly what it wrote. Sync it back to your DB if needed.

**Memory is scoped by role** — the same user can have different memory for different agent contexts (e.g. `support` vs `onboarding`).

***

## Sessions

Sessions give the agent multi-turn conversation history. When you pass a `sessionId`, the agent picks up where it left off.

```ts theme={null}
// Turn 1
await kairn.invoke({
  agent: 'assistant',
  userId,
  sessionId: 'chat_abc123',
  input: 'My invoice from last month was wrong.',
})

// Turn 2 — agent remembers the previous message
await kairn.invoke({
  agent: 'assistant',
  userId,
  sessionId: 'chat_abc123',
  input: 'Can you fix it?',
})
```

> [!NOTE]
>
> Without `sessionId`, each invocation is stateless — but memory still persists. Sessions expire after 30 days of inactivity.

***

## Mandates

Mandates are scheduled autonomous agent tasks. The agent runs on a cron schedule — no user interaction required. It has access to the user's memory and the soul's tool permissions.

```ts theme={null}
await kairn.mandates.create({
  userId: 'user_123',
  soul: 'advisor',
  label: 'Weekly progress check',
  taskPrompt: `
    Review this user's goals and recent activity from memory.
    Identify any blockers or things that need attention.
    Write a brief summary to memory under key "weekly_summary".
  `,
  trigger: {
    type: 'cron',
    cron: '0 9 * * 1', // Every Monday at 9am UTC
  },
})
```

**Mandates are powerful for:**

* Proactive nudges ("You haven't updated your pipeline in 5 days")
* Background data processing and enrichment
* Periodic summaries and reports
* Scheduled follow-ups without user interaction

***

## Roles

Roles let the same user have different agent contexts within your product. Memory and sessions are scoped per role.

```ts theme={null}
// User as a manager
await kairn.invoke({ agent: 'advisor', userId, role: 'manager', input: '...' })

// Same user as a team member — separate memory, separate history
await kairn.invoke({ agent: 'advisor', userId, role: 'member', input: '...' })
```

Default role is `"default"` when not specified.

***

## Multi-tenancy

Kairn is multi-tenant by design. Your API key scopes every call to your tenant. Your users' data never mixes with another tenant's.

> [card] Data isolation
>
> Separate DB rows per tenant. No cross-tenant memory access is possible at the query level.

> [card] Execution isolation
>
> Each invocation runs in an isolated sandbox. Concurrent requests from different users never touch each other's state.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.