Quickstart
Korely is a memory service for AI agents: your code sends it text, and later asks what it knows. This page takes you from nothing to a first stored and recalled memory, with Python, Node or plain REST. You need Python 3.9 or later, Node.js 18 or later, or any HTTP client. No signup form: you get a free key with one command.
The whole idea in six lines
This is what you will have running at the end. The next sections set it up one step at a time.
from korely_memory import Korely
korely = Korely() # finds your key (step 2)korely.add("Maria prefers email over Slack, and her renewal is in October.", user_id="customer-4812")
# Later, even in a new session:ctx = korely.get_context(query="how does Maria like to be contacted?", user_id="customer-4812")print(ctx.context) # text you paste into your agent's prompt add stores a sentence about one person.
get_context returns a block of text that answers a question
about that person, ready to put in a prompt.
Terms
The Glossary defines the words used across the docs. This page uses memory, fact, end user, API key, plan, context block, search and score as defined there. Four more are local to this page:
user_id: a name you choose for the person a memory is about, such ascustomer-4812. It is how you keep one person's memories apart from another's, and every write needs it or anagent_id(step 3). Choose an opaque id such ascustomer-4812, not an email address or a name: the id is sent to the model together with the memory text.agent_caller: a free label for your app, such asmy-app, sent when you create a key. It is optional, and it is not theagent_idyou can set on a memory.events: a call that lists your recent writes, newest first, each with a status (processing,readyorerror), and counts how many are stillprocessing.processing_region: which model reads your memories into facts:global(the default) uses a model from Google, outside the EU;euuses Scaleway in Paris. The Glossary calls this the project's region. It does not change where your data is stored (step 2).
Steps
1. Install
pip install korely-memoryThe Python and Node packages are the same SDK: small clients over the REST API that need no other packages, published on PyPI and npm. You should see the install finish without errors. If pip says the package is not compatible, your Python is older than 3.9.
2. Get an API key
You create a key on the free Hobby plan with one command. Creating the account accepts the Terms of Service and the Privacy Policy. Pick one of the two ways.
korely init --agent- CLI. It saves the key in
~/.korely/config.jsonand prints only its last four characters, so that file is your one copy. Thekorelycommand comes with the Python package only; the npm package does not have it, so Node users use the cURL call. If a key is already saved, the command stops and changes nothing. Add--forceto replace it; the old key is lost. - cURL. The answer is
201 Createdwith the key (kor_live_…) shown once. Nothing saves it for you: copy it now.
The cURL call sends agent_caller, an optional label for your
app: use any name, or leave the body out. The answer also lists your plan
and quotas, and two regions:
"region": "eu-hel1"is the Helsinki server that stores your data. Your data is stored on Korely's servers in Helsinki whatever you choose below."processing_region"says which model reads your memories into facts. The default is"global": the text of each memory is read by a model from Google, outside the EU. To have Scaleway in Paris read it instead, send"processing_region": "eu"in the body, or runkorely init --agent --processing-region eu.
Now give the key to the SDK. On the machine where you ran
korely init, Python finds the saved key by itself. Anywhere
else, and always in Node, set an environment variable:
export KORELY_API_KEY=kor_live_...
If the key is wrong or missing, the API answers
401 invalid_key, and the SDK raises an error that says so. If
you lose the key there is no recovery, because Korely keeps only a
fingerprint of it (a hash): run korely init --agent again for a new, empty account.
If the answer is 429 signup_rate_limited, too many accounts
were created from your network today; try again tomorrow. For the full
flow, and to link the key to a dashboard login, see
Sign up as an agent. An account made this
way has no login: the key is the account.
3. Store your first memory
from korely_memory import Korely
korely = Korely() # reads KORELY_API_KEY, or the key saved by korely init
# Remember something your agent learned about an end usermemory = korely.add( "Maria prefers email over Slack, and her renewal is in October.", user_id="customer-4812",)print(memory.id, memory.status) # mem_... processing What you see. The call returns at once with an id that
starts with mem_ and the status processing (over
REST, the answer is 201). The memory is saved and can be read
straight away. Its facts are not there yet: Korely reads them out of the
text in the background, which in general takes about ten seconds and
sometimes up to half a minute.
Check progress. Call events until nothing is
processing. Each event is one memory with its status, which
goes from processing to ready. A status of
error means the facts could not be written (see the table
below).
import time
result = korely.events(user_id="customer-4812")while result["processing"]: time.sleep(2) # still reading the memory into facts result = korely.events(user_id="customer-4812")print([e["status"] for e in result["events"]]) # ['ready'] Every write says whose memory it is. Send a
user_id (the person the memory is about, such as
customer-4812), an agent_id (the agent that
writes it, such as support-bot), or both. A write with
neither is refused: the answer is 422 with the code
identity_required, and nothing is stored. The same holds for
each memory of a batch
(one bad memory refuses the whole batch) and for
a fact you write yourself.
A run_id alone is not enough, and an id made only of spaces
or invisible characters counts as none.
Why: a write that names nobody has no owner, so Korely would treat every such write as the words of one person called "user" and weigh their facts against each other. If your program writes for one person only, any stable id is fine, such as your app's name. If you reach Korely through the MCP, an assistant that passes no id writes to the project's shared memory instead, as the MCP page explains. Reads do not change, and a key confined to one end user needs nothing here.
From the command line, say it once with
korely init --user-id customer-4812 (or
--agent-id support-bot): korely add then uses
it for every write that names none, and
korely add "..." --user-id customer-4812 overrides it for one
write. The SDKs do not read that saved id: your code names the owner on
each call, as the examples on this page do.
4. Get it back
get_context is the call you will use most. It returns the
current facts closest to your question, then the most relevant memories, as
one block of text for your prompt. It reads only what belongs to the
user_id you pass. Leave user_id out and it reads
every end user in the project, so always pass it.
ctx = korely.get_context( query="how does Maria like to be contacted?", user_id="customer-4812",)print(ctx.context) # drop straight into your system prompt What you see. A block of text about 300 tokens long. It
starts with a note that tells the model how to read it. Under
## Known facts come lines such as
Maria prefers email over Slack, then
## Relevant memories with your original sentence. Korely
chooses the wording of the facts, so they may not match your sentence word
for word. If you call it right after add, there is no
## Known facts part yet, only the memory: wait for the status
to be ready and call again.
5. Search, and read the score
When you want the raw memories instead of a prompt block,
search returns the stored memories closest in meaning to your
question, best first.
hits = korely.search("how does Maria like to be contacted?", user_id="customer-4812")for h in hits: print(h.score, h.snippet)
In Python and Node, search gives you the list of hits
directly; over REST the same list sits under results. The
example response shows the shape, and your id and score will differ.
How to read the score. It is a similarity from 0 to 1: higher means closer in meaning. A sentence almost identical to the stored one scores about 0.9. A question about the same topic scores about 0.6 to 0.7. A few keywords with no word in common score about 0.3. So do not filter on a high threshold such as 0.8, or real matches will vanish.
search ranks by similarity only. If a person's preference
changed, the older memory can rank above the newer one. To know what is
true now, use get_context or get_facts, which
replace superseded facts.
If you do not see what you expect
| You see | What it means and what to do |
|---|---|
No ## Known facts part, or the status is still processing | The facts are not ready. Wait about ten seconds, and up to half a minute, then call again. Check with events (step 3). If it is still processing after a few minutes, email [email protected]. |
Status error | The memory is stored but its facts were not written. See Add a memory for the next step. |
Status ready but no facts | Reading a memory can end without facts. The memory is still found by search and shown by get_context. |
| An empty result | Check that the user_id is exactly the one you used in add. |
401 | The key is missing or wrong (step 2). |
403 | The key lacks a permission for this call. The message says which. |
422 | The request is not valid. With the code identity_required: the write names neither user_id nor agent_id (see above). Otherwise content is empty or longer than 16,000 characters. The Python SDK refuses empty text before sending it, so you see that one with cURL. |
429 | Either you sent too many requests, and the Retry-After header says how many seconds to wait, or you used up the month's quota (see below). |
503 | The service is busy. Try again after the Retry-After seconds. |
What the free plan includes
The Hobby plan includes 250 writes
and 25,000 reads (called queries on the pricing page) a month,
at up to 60 requests a minute (the
rate limit). Each add
counts one write per 6,000 characters, rounded up, so a memory
at its longest (16,000 characters) counts 3. Each get_context and search
counts one read. Past the month's quota the API answers
429 quota_exceeded, and the count restarts on the 1st of the
month, UTC. The other plans are on the pricing page.
6. What else you can do
The Python and Node SDKs have the same memory, fact and account methods.
Node writes method names in camelCase (getContext), but the
option names stay as shown here (user_id, as_of).
The Python SDK also has methods for projects and keys. They need an
admin key: the key from korely init --agent is one until you connect it to a dashboard login. Use them by hand, never from a tool your agent can call. The headlines;
the full list is in the SDK reference:
| Method | What it does |
|---|---|
add(content, user_id=…) | Remember something. Korely reads facts out of it. |
get_context(query=…, user_id=…) | The main way to recall: the relevant current facts and memories as one block for a prompt. |
search(query, user_id=…) | Memories closest in meaning to a question, with a score. |
get_facts(user_id=…, as_of=…) | The facts, as they were true on a past date with as_of. |
get_profile(user_id=…) | Everything known about one end user. |
add_fact_triple(subject, predicate, object, user_id=…) | Write a fact directly instead of reading it from text. The check for contradicting facts still runs. |
update / delete / delete_all | Edit a memory, forget one, or permanently erase every memory of an end user in one call. |
history(id) / users() | A memory's timeline; the end users you store data for. |
batch(...) | Import many memories at once, for example from another store. |
Full detail with examples: the SDK reference and the REST API reference.
Next steps
- Learn how memory works: the memory model explains how Korely turns text into facts and handles contradictions over time.
- Use the REST API directly: the API reference documents every endpoint, request body and response.
- Wire it into a framework: guides for the Vercel AI SDK, LangGraph, n8n, OpenAI Agents SDK, CrewAI and LlamaIndex. The OpenClaw plugin is not published yet.
- Use the CLI: the
CLI reference covers
korely add,korely search,korely contextand the other subcommands, useful for scripts and one-off queries.
Stuck somewhere? Email [email protected]. Your feedback shapes what gets fixed first.