Korely for AI Agents
Memory for AI agents that knows what's still true.
Typed bi-temporal facts, contradictions resolved instead of overwritten, and as_of queries for what was true on any past date.
Hosted in the EU as a Cloud API (choose the Europe region to keep processing in the EU), or Self-hosted on your own infrastructure.
# 1. Connect (reads KORELY_API_KEY from the env)
from korely_memory import Korely
korely = Korely()
# 2. Remember what your agent learns about a user
korely.add("Maria is on the Pro plan, billed yearly.", user_id="maria")
# 3. Later it changes, and Korely resolves the contradiction
korely.add("Maria downgraded to Free.", user_id="maria")
# Facts are extracted after add() returns; korely.events(user_id="maria") says when they are ready
# 4. Pull a prompt-ready block: current facts first, superseded facts left out
ctx = korely.get_context(query="what plan is Maria on?", user_id="maria")
# e.g. ctx.context → "...## Known facts\n- The user subscribes_to Free plan (since ...)"
# (the relation name is chosen by the extractor)
# the Pro fact is invalidated, not deleted // 1. Connect (reads KORELY_API_KEY from the env)
import { Korely } from "korely-memory";
const korely = new Korely();
// 2. Remember what your agent learns about a user
await korely.add("Maria is on the Pro plan, billed yearly.", { user_id: "maria" });
// 3. Later it changes, and Korely resolves the contradiction
await korely.add("Maria downgraded to Free.", { user_id: "maria" });
// Facts are extracted after add() returns; await korely.events({ user_id: "maria" }) says when they are ready
// 4. Pull a prompt-ready block: current facts first, superseded facts left out
const ctx = await korely.getContext({ query: "what plan is Maria on?", user_id: "maria" });
// e.g. ctx.context → "...## Known facts\n- The user subscribes_to Free plan (since ...)"
// (the relation name is chosen by the extractor)
// the Pro fact is invalidated, not deleted # Install the CLI (it ships inside the Python package)
pip install korely-memory
# Remember, then recall: the same store as the SDK and REST
korely add "Maria downgraded to Free." --user-id maria
# Facts are extracted after add returns; korely events --user-id maria says when they are ready
korely context "what plan is Maria on?" --user-id maria
# e.g. ## Known facts
# - The user subscribes_to Free plan (since ...)
# (the relation name is chosen by the extractor)
# Time-travel: what was true back in March?
korely facts --as-of 2026-03-01 --user-id maria # Remember (facts + graph extracted server-side)
curl -X POST https://api.korely.ai/v1/memories \
-H "Authorization: Bearer kor_live_..." \
-H "Content-Type: application/json" \
-d '{"content": "Maria downgraded to Free.", "user_id": "maria"}'
# Recall a prompt-ready block: current facts first, superseded facts left out
curl "https://api.korely.ai/v1/context?query=what+plan+is+Maria+on%3F&user_id=maria" \
-H "Authorization: Bearer kor_live_..." One key authenticates the SDK, CLI, and REST API. Get your key → · Read the docs →
Wire it into the stack you already use
Any agent that speaks REST, the SDK, or the CLI. All integrations →
Proof, not promises
Storing a fact is easy. Returning the current one is where memory breaks.
A fact changes; the question is whether your agent serves the new value or last month's. We measure that on LongMemEval, the public benchmark for long-term agent memory, where two of the six question types, knowledge-update and temporal-reasoning, test exactly that.
Per-axis profile on LongMemEval.
-
Knowledge update
Serve the value that's true now, not last month's.
-
Temporal reasoning
What's latest, and what was true before a date.
-
Single-session · user
Recall what the user just told you.
-
Single-session · preference
Carry preferences into the next turn.
-
Single-session · assistant
Remember what your agent committed to.
-
Multi-session
Connect facts across many past chats.
How it is measured: the same LongMemEval questions on the oracle corpus (each question's evidence sessions, n=20 per question type), not the full-haystack test, and one reader model, graded by Groq gpt-oss-120b, with Gemini 2.5 Flash as a second judge on three axes, on engine versions earlier than the one in production. Every question, the memory it was tested on, the answer and the verdicts are on the benchmark page.
How it works
Your agent just chats. Korely keeps it on
what's true now.
Typed facts from plain conversation, contradictions resolved, recalled by any agent, the same store, across every session.
Why Korely
Memory your agent can trust.
Typed facts that resolve over time, so your agent answers from what is true now. The full history and the graph are one query away.
Each number above is how the product works today, not a benchmark score. Check them in the API reference and on the pricing page.
Typed facts, resolved over time, with a graph and an audit trail. One store, three surfaces, from €0.
What Korely does
One memory layer, every shape your agent needs
Semantic vector recall, a typed knowledge graph, and bi-temporal facts, in one store. REST, SDK, and CLI for any agent.
The memory
Memory model
Semantic vector recall over memories, a typed entity graph, and bi-temporal facts, in one store. Contradictions resolved on write.
Time + truth
Bi-temporal facts (valid_from / invalid_at). Point-in-time queries with as_of; contradictions invalidate, never delete.
Retrieval
Semantic vector search over stored memories, plus deterministic lookup of typed facts and entity relations. No generative model on the read path.
Where memories live
A managed cloud store (Postgres + pgvector), stored in the EU (Helsinki). The model step runs in the region you pick per project: Europe (Scaleway) or Global (Google Gemini).
The integration
Agent integration
REST API, Python + Node SDK, and a CLI (it ships inside the Python package).
SDKs
Python and Node.js, plus REST from any language. The CLI installs with the Python package.
Hosting
Stored in our EU cloud (Helsinki) on every tier. The model step runs in the region you pick per project: Europe (Scaleway) or Global (Google Gemini). No overage billing, ever.
Pricing model
Flat, predictable pricing. Graph and temporal facts on every plan, free included.
Trust & control
Efficient by default. Transparent by design. Yours to control.
The primitives a regulated team needs, on every tier, not gated behind an enterprise call.
Efficiency
A context block that fits the budget you set.
Each turn, your agent sends a block of current facts and relevant memories, capped at a token budget you choose, not the whole transcript.
- Current facts first, superseded memories marked as history
- 800 tokens by default, from 50 to 8,000
- No generative model on reads
conversation history
context block
Time travel
Ask what was true on any past date.
Every memory becomes a typed fact with its own validity window. When a value changes, the old one is kept, not overwritten, so you can replay your agent's knowledge as of any moment.
- Typed facts with valid_from and invalid_at
- Changes supersede the old value, never overwrite it
- as_of returns the truth at any past date
Control
Ask to be forgotten, and you really are.
When a user invokes their right to erasure, one call deletes their memories and facts from the live database (within the key’s project), with an audit record that keeps counts, never content. Encrypted backups drop their copy within 35 days. It was never baked into the model, so there is nothing left to unlearn.
- Erase everything about an end user with one call
- Every erasure is logged, so you can prove it
- Never trained on, never baked into the model
Use cases
Ten shapes of agent memory
One memory, scoped per agent. Each vertical ships with a code snippet you can copy.
Pricing
Flat, predictable pricing, with the graph included
Prices exclude VAT. Polar adds your country's VAT at checkout.
Changelog
What's new
- API
Korely 0.2.1: MCP reads narrow like REST, and bounded waits
The MCP tools korely_get_context, korely_search and korely_get_facts take agent_id, and korely_get_facts takes predicate, as their REST twins do. A NUL byte anywhere in a request, or a moment outside 0001-01-02 to 9999-12-30 UTC (a memory's timestamp, valid_from, as_of, known_as_of), answers 422 naming the field. A request that waits more than 5 s on a database lock answers 503 unavailable with Retry-After: 5. Creating or enabling a webhook endpoint answers 429 rate_limit_exceeded when the account's two webhook tests or address checks are already under way, and 400 when its host does not resolve within 5 s.
- API
Korely 0.2.0: the compatibility names and secrets retire
DELETE /v1/users/{end_user}/memories and the deletion of a project answer with memories_deleted and facts_deleted only: memories_forgotten and facts_invalidated, the same numbers under older names, are gone. Webhook endpoints created before 2026-09-28 (legacy_signature: true) are no longer sent; recreate one on the Webhooks page and it gets a secret the Standard Webhooks libraries verify. On Self-hosted a kor_live_ key, the Cloud's prefix, is refused on REST, MCP and the admin API; keys minted there begin with kor_self_. A batch body that holds more JSON values than 500 valid items can hold answers 413 before it is decoded. An account runs up to four MCP tool calls at once, and the next ones wait their turn instead of failing. The SDKs korely-memory 0.1.27 (Python) and 0.1.17 (Node) return kind on every memory and take it on batch items, and the CLI adds korely add --kind session and --exclude-sessions on search, context, facts, profile and list. GET /v1/ping answers region as a label the operator of the install sets: eu-hel1 on the Cloud, the Helsinki server that stores the data; on Self-hosted the REGION value in .env, eu when it is not set, which the service does not check. A memory the model refuses, or runs out of time on, five times while it goes on writing other memories ends in status error, and one account's refused memories no longer pause the writing of other accounts' memories. Deleting a project with erasure counts as erasing each of its end users: the answer is the same, one audit_id, and each end user gets an erasure record under their pseudonym, so what the audit trail writes about them afterwards names them by that pseudonym. An account runs up to four memory searches at once; a fifth sent meanwhile answers 503 search_unavailable on POST /v1/memories/search, to retry, and GET /v1/context answers 200 with degraded: true and the facts only. A batch body larger than 2 MiB that does not arrive whole within 120 seconds answers 408 request_timeout, and an account's large batches are taken one at a time. From 1.0, nothing published is removed without a 2.0.
- API
Declare a name for an end user
POST /v1/users/{end_user}/names declares that an end user is also called by a name: the id maria is Maria Rossi. The store never merges two names of a person by itself, because two people can share one; after the declaration the facts about the name in that end user's memory read as the end user's, the ones already written included. A name already declared for somebody else answers 409. The SDKs call it declare_name (Python 0.1.26) and declareName (Node 0.1.16), and the CLI korely init --name "Maria Rossi" --user-id maria.
Get started
Give your agent memory
that stays true.
Create your account and mint your first key, free to start. EU-hosted, no card required.