Memories

The core unit of knowledge in Cortex.

A memory is a scoped, cited, and auditable piece of knowledge stored in Cortex. Unlike traditional search indexes, memories carry semantic context with full provenance.

Memory Structure

{
  "id": "uuid",
  "title": "API Rate Limiting Policy",
  "content": "All external API endpoints must implement rate limiting...",
  "scope": "engineering",
  "category": "policy",
  "source": "GitHub",
  "source_url": "https://github.com/org/repo/pull/123",
  "author": {
    "id": "uuid",
    "name": "John Doe"
  },
  "tags": ["api", "security"],
  "clearance_min": "Contractor",
  "status": "active",
  "valid_from": "2025-01-15T10:30:00Z",
  "valid_until": null
}

Lifecycle

stateDiagram-v2
    [*] --> Active: remember()
    Active --> Superseded: Newer memory supersedes
    Active --> Redacted: redact()
    Superseded --> [*]
    Redacted --> [*]
StatusDescription
activeCurrently searchable and recalled
supersededReplaced by a newer, more authoritative memory
redactedRemoved from search; row retained for provenance

Writing Memories

Memories can be written via:

MethodUse Case
MCP remember toolAI agents storing knowledge
REST APICI/CD pipelines, integrations
CLIManual file uploads
ConnectorsGitHub PRs, Slack messages

How content is stored

A memory is always one row with one whole-content copy and one citation, but its content is chunked for embedding: long content is split into overlapping, paragraph-aware chunks (~1.2k chars, ~150-char overlap) and each chunk is embedded as its own vector, all tagged with the same memory_id. Short content (≲1.4k chars) stays a single chunk, so nothing changes for the common case. A best-effort graph extraction then runs on the memory.

Chunking means a specific fact buried deep in a long document can still be matched on recall, while the memory list, citations, and audit trail stay one-per-memory. When several chunks of the same memory match a query, recall returns that memory once (highest-scoring chunk wins). Redaction, supersession, and deletion apply to every chunk of a memory.

How connectors sync

ConnectorModeFirst-run backfillPer-run cap
GitHubWebhook (real-time)none — merged PRs going forward only
SlackWebhook (real-time)up to ~50 recent messages per synced channel50
GmailScheduled pull (~15 min)messages from the last 3 days8
Google DriveScheduled pull (~15 min)Docs modified in the last 3 days4
NotionScheduled pull (~15 min)pages edited in the last 30 days8

GitHub and Slack push events as they happen. Gmail, Drive and Notion have no webhook for this content, so a scheduled job (Upstash QStash → /api/cron/ connectors) pulls what changed since each connector's stored cursor. Every connector card also has a Sync now button for an on-demand run. Per-run caps are deliberately small (each item costs an embed + a graph-extraction LLM call); subsequent runs pick up more incrementally. Raise the caps for a one-time backfill.

Scope Resolution

When writing, the scope is determined by:

  1. Explicit scope parameter (highest priority)
  2. Source-based heuristic (e.g., GitHub → engineering)
  3. Default scope (public-docs)

An agent can only write into scopes its acting user can read. This prevents "write-up" permission leaks.

Meeting notes (online or offline)

Memories → Add Memory → Meeting Brief is built for any meeting, not only recorded calls. Fill in a written summary and/or upload a real transcript file (.txt, .md, .docx, .pdf) — there is no audio-upload option; text only.

Extract Decisions (AI) runs your summary + transcript through the LLM (POST /api/memories/extract-decisions) and returns decisions actually grounded in that text — nothing is templated or guessed. Extracted decisions are appended to the saved memory's content alongside your summary and transcript.

Reading Memories

Memories are retrieved via:

MethodDescription
MCP recall toolSemantic search with citations
REST APIProgrammatic access
MCP list_memoriesRecent memories (no search)

Permission Filtering

Every read operation:

  1. Resolves the caller's allowed scopes
  2. Filters results to those scopes only
  3. Re-checks clearance level (defence-in-depth)
  4. Drops expired memories
  5. Returns only active status memories

Ranking

Results are ranked by a blend of semantic relevance (70%) and recency (30%), not recency alone — a strong exact match can still outrank a pile of recently-synced but loosely-related items.

Conflict Detection

When a new memory is written, Cortex checks for near-neighbours with similarity > 0.75. Conflicts are classified as:

KindDescription
contradictionConflicting information
duplicateSame information, different source
staleOutdated information

Conflicts are resolved by authority (role level) or recency, with dissent retained.