Your first retrieval¶
There are two read endpoints and they do very different things. Picking the wrong one is the most common integration mistake.
| Endpoint | Returns | Use it for |
|---|---|---|
GET /api/context/{project} |
Everything, paginated, newest first, optional q/type/agent filters |
Dashboards, audit, export |
GET /api/context/{project}/relevant |
Top-N ranked for a query, with scores | Building a prompt |
If you are putting memory into an LLM prompt, you want /relevant.
Ranked retrieval¶
Response:
{
"project_id": "billing-service",
"query": "which database did we pick",
"memories": [
{
"id": "ctx_cc55e4a7bbc5",
"type": "decision",
"content": "We use Postgres, not MongoDB, because the ranking query needs joins.",
"importance": 0.9,
"access_count": 0,
"created_at": 1787007131.3763673,
"metadata": {"ticket": "ARCH-14"},
"score": 0.4789,
"similarity": 0.1348,
"justification": "semantic similarity 0.13 (HashingEmbeddingProvider, 128d)"
}
]
}
Reading the three ranking fields¶
| Field | Meaning |
|---|---|
similarity |
Cosine similarity between the query embedding and this memory's embedding. 0.0 when no query was given. |
score |
The blended ranking value — what the sort is on. 0.40·similarity + 0.20·recency + 0.25·importance + 0.15·frequency. |
justification |
Human-readable note naming the provider and its dimension. |
Why similarity is often low¶
In the example above, 0.13 for a clearly on-topic memory looks wrong. It is
not — the default hashing provider maps tokens into 128 buckets by SHA-256.
It scores lexical overlap, not meaning. "database" and "Postgres" are
unrelated to it.
The memory still ranked first because importance (0.9) and recency supplied
most of the score. That is the ranking policy doing its job with a weak
relevance signal — and also the reason to switch providers before you rely on
paraphrase matching:
Details and the migration path: Embeddings.
Retrieval with no query¶
Omit query and every candidate gets similarity = 1.0, so the ranking falls
back to recency + importance + frequency alone:
curl -sG https://api.venkai.fr/api/context/billing-service/relevant \
-H "Authorization: Bearer $VENKAI_API_KEY" --data-urlencode 'limit=5'
That is a useful "what matters in this project right now" call — and it costs no embedding computation.
Choosing limit¶
limit is your context budget. There is no server-side token cap and no
truncation: ask for 50, you get up to 50 whole memories.
limit |
Reasonable for |
|---|---|
| 3–5 | A focused sub-task, a tool call |
| 5–10 | A planning step at the top of a run |
| 20+ | Analysis or export, not a prompt |
Filtering instead of ranking¶
For "show me every decision", use the list endpoint — it is not ranked, and that is what you want for an audit view:
curl -s "https://api.venkai.fr/api/context/billing-service?type=decision&limit=50" \
-H "Authorization: Bearer $VENKAI_API_KEY"
Query parameters: type, q (substring match), agent, order
(created_desc by default), limit (capped at 200), offset.
Next: Add Venkai to an agent.