Skip to content

Context

A context is one stored record. In the API the words context and memory refer to the same object: POST /api/context and POST /api/memory are two routes onto one handler, and the stored table is contexts.

Use whichever reads better in your code. This documentation says memory when talking about the concept and context when talking about the stored row or the endpoint path.

Shape

{
  "id": "ctx_cc55e4a7bbc5",
  "org_id": "org_1f200d429c50",
  "project_id": "billing-service",
  "agent_key": "planner",
  "type": "decision",
  "content": "We use Postgres, not MongoDB, because the ranking query needs joins.",
  "confidence": 0.8,
  "importance": 0.9,
  "access_count": 0,
  "last_accessed_at": null,
  "created_at": 1787007131.3763673,
  "updated_at": 1787007131.3763673,
  "metadata": {"ticket": "ARCH-14"}
}
Field Type Notes
id string ctx_ + 12 hex chars. Stable for the life of the record.
org_id string Owning organization.
project_id string Your project key, not the internal id — the API substitutes it on every read.
agent_key string The agent_id you sent at write time.
type string One of six. See below.
content string 1–8000 characters. The only field that is embedded.
confidence float 0–1. Stored, returned, not used in ranking.
importance float 0–1. 25 % of every retrieval score.
access_count int Explicit-feedback counter. Not incremented by retrieval — see Ranking.
created_at / updated_at float Unix epoch seconds, with fractions.
metadata object Free-form JSON. Not indexed, not ranked, not embedded.

embedding appears on writes only

POST /api/context and POST /api/memory echo the raw embedding vector back. Read paths strip it. Do not depend on it — its length changes with the configured provider.

Identity and addressing

Two different identifiers, and mixing them up is a 404:

flowchart LR
  PK["project key<br/>'billing-service'<br/><i>you choose it</i>"] -->|"resolved per request"| PID["internal id<br/>'proj_878b0d7ab961'"]
  PID --> ROW["context row"]
  ROW -->|"on the way out"| PK
  • Endpoints taking {project_id} want your project key.
  • Endpoints taking {context_id} want the ctx_… id.

The internal proj_… id never leaves the API — it is swapped back to your key on every response, so a client can never accidentally couple to it.

Types

Type Meaning
fact Something true about the system
decision A choice that was made
preference A soft rule to respect
event Something that happened
constraint A hard rule
relationship A link between entities

Validation is strict: an unrecognised type returns

{"detail": "type must be one of fact|decision|preference|event|constraint|relationship"}

with status 422. Nothing is coerced to fact.

Types do not influence the ranking score. They influence what you can filter on, and they give a reader of the timeline something to scan.

Lifecycle

stateDiagram-v2
  [*] --> Stored: POST /api/memory
  Stored --> Stored: PATCH (content or metadata)
  Stored --> Versioned: PATCH creates a version entry
  Versioned --> Stored: POST .../restore
  Stored --> Retrieved: GET .../relevant
  Retrieved --> Stored: no mutation

Created by a write. Modified only by PATCH /api/context/{id} — which recomputes the embedding when content changes, and records a version. Never modified by a read: retrieval leaves access_count, last_accessed_at and updated_at untouched.

There is no expiry and no TTL. A memory lives until you PATCH it or delete the organization. Ageing is handled by the recency term in Ranking, not by deletion.