Korely

Get Started

Sign up as an agent

One command. No email, no dashboard. Your agent gets a working memory key.

korely init --agent creates a free Hobby account and a kor_live_ key with no human in the loop, then saves the key on your machine. From that point your agent can add() memories and read them back with get_context(), session after session. The key is real and works at once: it is the same service, with the same facts and the same EU storage, as every other Korely account. The account has no login, so this page is for an agent, or a developer, that wants a key without opening a dashboard first.

Terms

The Glossary defines the words used across the docs. This page uses API key, plan, memory, agent_id, agent_caller, region, project, Default project, permission and score as defined there.

The four-command demo

Install the package, sign up, save a memory and search for it. The --agent-id in the signup command says whose memory your writes are: every write names a user_id or an agent_id, and the CLI saves this one for the commands that follow (why). Pick any stable name for your agent. Without it, korely add stops with identity_required and tells you to save one. The ids need korely-memory 0.1.29.

Terminal window
pip install korely-memory
korely init --agent --agent-caller claude-code --agent-id claude-code
korely add "I am using Korely"
korely search "am I using Korely"

korely init is the one command that runs without a key: it is how you get one. It needs Python 3.9 or later. Here is what it prints:

You're set: a free hobby key was minted and saved to /Users/you/.korely/config.json (chmod 600).
key kor_live_…a1b2
tier hobby region eu-hel1 processing global
quotas 250 writes / 25000 queries per month · 2 agents
terms creating the account accepts the Terms and the Privacy Policy:
https://korely.ai/legal/terms-of-service
https://korely.ai/legal/privacy-policy
writes as agent_id claude-code when a write names neither id
Next:
korely add "I am using Korely"
korely search "am I using Korely"

Then korely add prints stored and the id of the new memory, and korely search prints a line with the score in square brackets and your text, for example [0.709] I am using Korely (the score varies). If korely is not found after the install, run it as python3 -m korely_memory.cli.

If a key is already saved in ~/.korely/config.json, korely init changes nothing and exits with code 2: the account it made has no login, so that key is the only way to use it and to close it. Add --force to replace the saved key (the old one is lost), or close the old account first with korely delete-account --confirm <account id> (the id is the tenant_id of GET /admin/whoami; from korely-memory 0.2.0; up to 0.1.29 the command was korely delete-account --yes, which a 1.0.23 server refuses).

The REST call, POST /v1/agents/init with no key, answers 201 Created with the same thing as JSON:

{
"api_key": "kor_live_...",
"tier": "hobby",
"region": "eu-hel1",
"processing_region": "global",
"scopes": ["memories:read", "memories:write", "admin"],
"quotas": { "writes_per_month": 250, "queries_per_month": 25000, "agents": 2 },
"expires_at": "…",
"note": "This key is valid for 7 days (expires_at). Until the account is adopted it is on trial: …",
"terms_url": "https://korely.ai/legal/terms-of-service",
"privacy_url": "https://korely.ai/legal/privacy-policy"
}

The key is shown in this answer once. Since 1.0.5 it has the memories:read, memories:write and admin permissions, so it can manage projects and keys and close the account (from 1.0.10 it keeps admin only until the account is connected to a dashboard login). Up to 1.0.9 the key does not expire. From 1.0.10 it is valid for 7 days until the account is connected to a dashboard login: see The trial, which also says what expires_at and note in the answer are. Keys issued before 1.0.5 have no admin permission. Creating the account accepts the Terms and the Privacy Policy named there.

Identify yourself with --agent-caller

agent_caller is a free label for who is signing up (claude-code, cursor, your app's name). It is stored with the account for your own reference. It does not change scoping or limits, and it is not the agent_id you can put on a memory. Leave it out and the account is still created. It can be up to 120 characters (longer is a 422); fields this call does not know are ignored.

Terminal window
korely init --agent --agent-caller my-support-bot

Choose where your memories are processed

Terminal window
pip install -U korely-memory
korely init --agent --processing-region eu

Or with the REST API:

Terminal window
curl -X POST https://api.korely.ai/v1/agents/init \
-H "Content-Type: application/json" \
-d '{"agent_caller": "my-support-bot", "processing_region": "eu"}'

Your data is stored on Korely's servers in Helsinki whatever you choose: that is region in the answer. processing_region says which model reads your memories into facts, for the account's Default project:

  • global, the default: a model from Google (the Gemini API) reads the text of a memory, outside the EU.
  • eu: gpt-oss-120b on Scaleway, in Paris, France.

Any other value is a 422. Searches and context queries run no language model in either region, and the quality of the facts can differ between the two regions. Every way of signing up can choose it: the CLI with --processing-region eu (korely-memory 0.1.24 or later; it prints processing eu next to the plan), the SDKs with Korely.init_agent(processing_region="eu") and Korely.initAgent("my-app", { processingRegion: "eu" }), and the REST call above. Left out, the account is global. The CLI refuses the option together with --api-key: a key you already have keeps the region of its project. The region is set per project, and can be changed later on the dashboard's Projects page. That page needs a dashboard login, and an account made by this call has none until you connect its key to one, so choose here if you care. See Regions.

What happened when you ran korely init --agent

  • An account was created with no email and no dashboard step, together with its Default project. It owns a new Hobby kor_live_ key.
  • The key was saved to ~/.korely/config.json with owner-only permissions (chmod 600). Every later korely command reads it from there, so you do not pass it again.
  • Key precedence is --api-key > KORELY_API_KEY > ~/.korely/config.json. The Python SDK and the Node SDK (in Node.js) look for a key in the same two places, so Korely() and new Korely() find it without an argument.

The plaintext key is shown once. It lives in your config file afterwards; Korely stores only a SHA-256 hash and can never show it again. If you lose it, you cannot get it back: sign up again for a new one. Treat it like any secret and do not commit it.

The trial, until the key is connected

From 1.0.10, an account that POST /v1/agents/init made is on trial until a person signs in to the dashboard with its key and connects it. This is the Cloud's rule: a Self-hosted install has no trial.

  • The key is valid for 7 days. The 201 carries expires_at (ISO 8601, with time zone) and a note that says the same in words. If nobody connects the account before that date, the key is refused from then on: 401 invalid_key on the REST API and 401 invalid_token on the MCP door, and it can no longer be used to connect the account.
  • 40 writes in all, over the account's whole life: the count is never reset by a month. The Cloud lets 10% through on top, so the 45th write is the first refused: 429 quota_exceeded with resets_at null, because these writes do not start again on their own.
  • At most 5 writes in a minute (a clock minute, UTC). The 6th is refused with 429 rate_limit_exceeded and Retry-After in seconds. Each time this happens within an hour, the next wait is longer: 60, 120, 240, then 480 seconds, and it stays at 480. A write refused during a wait adds nothing to it. A POST /v1/batch takes one of the 5 places in the minute and as many of the 40 writes as it has memories.
  • 20 requests a minute, reads and writes together.
  • No other keys. POST /admin/keys and an app's consent answer 403 account_not_adopted, and so does revoking the account's last live key. Since 1.0.23 so does rotating a key (POST /admin/keys/{id}/rotate): the 7 days of the key would otherwise never end. Connect the key first, then make keys on the dashboard.

Connecting the key lifts these limits from the next request on, and lifts the 7-day end of the key that init made: from 1.0.23 that key then lasts 365 days from the moment it is connected (up to 1.0.22 it had no end date), so the agent that uses it keeps working until then. Before that day the person who owns the account makes a new key, or rotates this one, from the dashboard or with an admin key: the agent's own key has lost admin by then. Any other key keeps its own end date.

Connecting the key also takes its admin permission away. The agent keeps writing and reading its project as before, with memories:read and memories:write. What it can no longer do is manage the account: every /admin route and DELETE /v1/account answer it 403 forbidden. From then on the person manages keys, webhooks, projects and closing the account from the dashboard. The webhooks the agent made before the connection arrive switched off, not deleted: URL, secret and events stay. The answer of the connection says how many there are and which hosts their URLs point to (webhooks_off, with count and hosts), and each one is switched back on from the dashboard's Webhooks page. Events that fall due while a webhook is off are not sent later.

Keys that init made before 1.0.10 have no end date. Their account, if nobody connected it, is on trial from 1.0.10 on, but from 1.0.16 its writes are the free plan's month (250, starting again on the 1st), not the trial's 40 in all. The quotas field of the 201 still says 250 writes a month: that is the Hobby plan, which applies once the key is connected. The trial's numbers are in note. The Python SDK exposes retry_after on the 429 but does not wait by itself.

Connect the key to a dashboard login

An account made with korely init --agent is its key: it has no login. To upgrade, top up, see usage or set webhooks, sign in at the dashboard (agent.korely.ai), open the Account page and paste the key under Bring in a key made without a login, then press Bring it in. Its memories, facts, projects and keys move into the account you signed in with, and the key keeps working. From 1.0.10 this also ends the trial, lifts the 7-day end of the key that init made, takes its admin permission away and switches the account's webhooks off (see The trial). When that account already has a Default project, the key's one arrives as Default (from key). From then on the account is closed from the dashboard (Account, Close the account, which also ends a paid plan), not with DELETE /v1/account or korely delete-account, which only work for an account that has no login (and, from 1.0.23, only with the account's id typed: how). Until then, an unconfined key of such an account that has the admin permission (every key from POST /v1/agents/init since 1.0.5) closes the whole account with that call (read the warning), so give it only to code you trust. A key without it, such as one issued before 1.0.5, is refused with 403.

Quotas and limits

  • Until the key is connected (from 1.0.10): the limits of the trial come first.
  • Free Hobby plan: 250 writes and 25,000 reads per month, and up to 2 named agents (distinct agent_id values). The number of end users (user_id) is not limited. See pricing for the paid plans.
  • Stored in Helsinki. Every memory and fact is stored on Korely's servers in Helsinki. GET /v1/ping returns "region": "eu-hel1", the label Korely sets for that server, and processing_region, which decides the model that writes your facts: Google outside the EU for global, Scaleway in Paris for eu.
  • Signup is capped. One network (an IPv4 address or an IPv6 /64) can create 5 accounts in 24 hours, and the service creates at most 100 a day in total. Past either cap the call returns 429 signup_rate_limited with Retry-After: 86400. When self-signup is closed it returns 403 signup_disabled.
  • The body is capped. The body of this call is a few bytes. A body larger than 1 MB is refused with 413 before it reaches Korely, and no account is created.

What's next

  • Make the calls every agent makes: the core operations, add, search, get context, update, delete.
  • Read memories back: get_context assembles the facts that are true now for one end user, and the memories closest to your question, into text you can put in a prompt.
  • Pick your surface: the SDK (Python and Node), the CLI, or the REST API, all on the one key.