Org in a Box
Features

Semantic Memory

How Org in a Box stores, retrieves, and injects long-term memory into every agent turn.

How It Works

Every piece of information an agent learns about you is stored in the memories table with a 1536-dimensional embedding vector. Before each agent turn, the memory plugin fetches the most semantically similar memories and injects them into the system prompt.

User message → embed via OpenAI/Azure → cosine search → top-K memories → system prompt

When no embedder is configured, the plugin falls back to recency-ordered recall (most recent first).

Memory Kinds

KindWhen Used
factExplicit facts: "Alice is the VP of Engineering at Acme."
preferenceAuto-extracted: "I prefer dark mode", "call me Bob"
eventTime-anchored events: "Board meeting on Thursday"
skill-noteReflections from the learning loop

Visibility

ScopeWho Sees It
private (default)Only the owning user
teamAll users in the same tenant
orgAll users in the organisation

Visibility is enforced by RBAC: memory.read_team and memory.read_org permissions must be granted.

System Prompt Injection

The experimental.chat.system.transform hook fires before every turn. It:

  1. Reads the last user message text (cached by the chat.message hook)
  2. Embeds it using buildEmbedderFromEnv() (Azure OpenAI preferred, OpenAI fallback)
  3. Runs cosine similarity against all stored embeddings (threshold: 0.3)
  4. Takes the top 8 results
  5. Truncates to a 2000-token budget
  6. Wraps the block in <memory-context>...</memory-context>

Adding Memories

Agents can add memories directly:

memory add fact "The customer's renewal date is Q3 2026"
memory add preference "User wants all reports in bullet-point format"

Via REST API:

POST /v1/memories
Authorization: Bearer <token>
Content-Type: application/json

{
  "kind": "fact",
  "content": "ACME Corp uses Salesforce for CRM",
  "visibility": "team"
}

Backfilling Embeddings

Memories created before an embedder was configured have embedding = NULL. Enqueue a backfill job:

POST /v1/jobs
{ "kind": "embed-memories", "payload": { "limit": 500 } }

Or schedule it as a nightly cron trigger.

Configuration

OptionDefaultDescription
recallLimit8Max memories injected per turn
similarityThreshold0.3Minimum cosine similarity to include
tokenBudget2000Max tokens of memory context

Pass as plugin options in opencode.jsonc:

{
  "plugin": ["@orginabox/plugin-memory"],
  "pluginOptions": {
    "@orginabox/plugin-memory": {
      "recallLimit": 12,
      "similarityThreshold": 0.25
    }
  }
}

On this page