Skip to content

Your first context

One memory, written three ways.

curl -sX POST https://api.venkai.fr/api/memory \
  -H "Authorization: Bearer $VENKAI_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{
    "project_id": "billing-service",
    "agent_id": "planner",
    "type": "decision",
    "importance": 0.9,
    "confidence": 0.95,
    "content": "We use Postgres, not MongoDB, because the ranking query needs joins.",
    "metadata": {"ticket": "ARCH-14"}
  }'
from venkai.sdk.client import VenkaiClient

client = VenkaiClient(api_key=..., base_url="https://api.venkai.fr",
                      project="billing-service")

client.memory.remember(
    "We use Postgres, not MongoDB, because the ranking query needs joins.",
    type="decision",
    agent="planner",
    importance=0.9,
    confidence=0.95,
    metadata={"ticket": "ARCH-14"},
)
venkai_remember(
  content="We use Postgres, not MongoDB, because the ranking query needs joins.",
  project="billing-service",
  type="decision",
  importance=0.9
)

The fields, and which ones matter

Field Required Default What it does
project_id Your project key. Created on first write.
agent_id Who wrote this. Stored as agent_key, filterable on read.
content 1–8000 characters. This is what gets embedded.
type fact One of the six types. Invalid → 422.
importance 0.5 0–1. Contributes 25 % of every retrieval score.
confidence 0.8 0–1. Stored and returned; does not affect ranking today.
metadata {} Free-form JSON. Stored and returned; not indexed, not ranked.

Two of those deserve attention.

importance is the one dial you control

It is 25 % of the score, forever, and it never decays. recency fades with a 14-day half-life; importance does not. A constraint set to 0.9 still outranks a stale 0.2 fact a year later.

Use the range deliberately:

Value For
0.9–1.0 Hard constraints, irreversible decisions
0.6–0.8 Decisions with a stated reason
0.4–0.5 Ordinary facts (the default)
0.1–0.3 Nice-to-know, preferences, ephemera

Setting everything to 0.9 is the same as setting nothing.

content is what gets matched

The embedding is computed from content alone — not from metadata, not from type. A memory whose content is "see ticket ARCH-14" is unfindable by anything except the word "ticket". Write the statement, not the pointer.

Good:

We use Postgres, not MongoDB, because the ranking query needs joins.

Bad:

DB decision — see ARCH-14

Choosing a type

flowchart TD
  A{"Is it a rule that<br/>must not be broken?"} -->|yes| C["constraint"]
  A -->|no| B{"Was a choice made<br/>between options?"}
  B -->|yes| D["decision"]
  B -->|no| E{"Did it happen<br/>at a point in time?"}
  E -->|yes| F["event"]
  E -->|no| G{"Is it a soft rule<br/>someone wants respected?"}
  G -->|yes| H["preference"]
  G -->|no| I{"Does it link two<br/>entities?"}
  I -->|yes| J["relationship"]
  I -->|no| K["fact"]

Types do not change ranking. They change what you can filter on: GET /api/context/{project}?type=decision and the decisions array in every list response.

Verify it landed

curl -s "https://api.venkai.fr/api/context/billing-service?limit=5" \
  -H "Authorization: Bearer $VENKAI_API_KEY"
{
  "project_id": "billing-service",
  "context": [ { "id": "ctx_fd7e76ac9ed0", "type": "constraint", "…": "…" } ],
  "decisions": [ { "…": "only the type=decision entries" } ],
  "count": 1,
  "total": 2,
  "offset": 0
}

count is the size of this page; total is the number of matches after filters — the one to paginate against.

Next: First retrieval.