Projects
A project is an organizational workspace in your Korely account that groups your API keys. For an agent builder, projects answer a concrete ops question: how do you run a staging environment and a production environment under one account, with separate keys, separate usage views, and a clear promotion path, without risking a staging write leaking into the production memory your end users see? The answer is two projects, one key each. Every account starts with a Default project created automatically; you mint additional projects in the dashboard as your deployment topology grows.
Projects are an organizational layer on top of your keys. They do not change how your agents call Korely, and they are not something an agent ever sees. A project is resolved on the server from the key that authenticates the request.
flowchart TD
ACC["Your account"]
P1["Project: Staging"]
P2["Project: Production"]
K1["kor_live_staging_..."]
K2["kor_live_prod_..."]
A1["agent_id: support-bot-staging"]
A2["agent_id: support-bot"]
U1["user_id: test-customer-001"]
U2["user_id: customer-4812"]
ACC --> P1
ACC --> P2
P1 --> K1
P2 --> K2
K1 --> A1
K2 --> A2
A1 --> U1
A2 --> U2
style ACC fill:#1e293b,color:#e2e8f0,stroke:#6366f1
style P1 fill:#374151,color:#d1d5db,stroke:#4b5563
style P2 fill:#374151,color:#d1d5db,stroke:#4b5563
style K1 fill:#1e293b,color:#a5b4fc,stroke:#6366f1
style K2 fill:#1e293b,color:#a5b4fc,stroke:#6366f1
style A1 fill:#0f172a,color:#94a3b8,stroke:#334155
style A2 fill:#0f172a,color:#94a3b8,stroke:#334155
style U1 fill:#0f172a,color:#94a3b8,stroke:#334155
style U2 fill:#0f172a,color:#94a3b8,stroke:#334155
Managed from the dashboard
Projects live in the dashboard, not the public API. There is no
/projects endpoint and your agents never create or select a
project. From the dashboard you:
- Create, rename, archive, and delete projects.
- Create API keys inside a specific project, reading and writing or read only or write only.
- Move a key from one project to another. This is the staging → production path: promote a key once it is ready instead of minting a new one and re-deploying.
Deleting a project never deletes a live key. When you delete a project, its keys are re-pointed to the Default project and keep working, so a cleanup in the dashboard never takes a running agent offline. By default its memories and facts move to the Default project with them, so nothing is lost. If you choose to erase them instead, they are deleted for good, with an audit record.
Project vs agent_id vs user_id
Three different things group your data, at three different levels. They stack; they do not compete.
| Concept | Groups | Set where | Use it for |
|---|---|---|---|
| Project | Your API keys | Dashboard | Environment and product: staging vs production, one product vs another. |
agent_id | One application, within a project | API call | The app itself, e.g. support-bot. One project runs many agents. |
user_id | The memory of one end customer | API call | The person your agent serves (Mem0-style). Unlimited on every tier. |
Read it top to bottom: a project is the environment or
product container that holds your keys; agent_id is the
application within that project; user_id is the end
user that application is serving. Use projects for environment and product,
agent_id for the app, and user_id for the end
user.
What a project isolates
A project groups your keys, gives you a place to read usage per project,
lets you promote a key from staging to production, and
walls off the data. Every memory and fact carries the
project of the key that wrote it, and a key reads, searches, assembles
context from, corrects, forgets and erases only what belongs to its own
project. A staging key never sees production memory, and a fact in
another project answers 404, the same answer as an id that
never existed.
Erasing an end user is per project too. DELETE /v1/users/{end_user}/memories erases that end
user in the key's project. If the same end user lives in several
projects, call it once per project, with that project's key.
Quotas and the agent cap are account-wide. Staging and
production share one write pool and one read pool; there is no
per-project budget. The agent cap counts agent_id names
across the account: a name used in two projects holds one slot, and
GET /v1/agents lists the names of the key's project while
its used count covers the whole account.
The public API is unchanged
Projects do not touch the /v1 contract. There is no project
field in any request body, and there is nothing new to send. The project a
request belongs to is resolved server-side from the authenticating
key; agents stay exactly as they are.
# The same call from a staging key and a production key.# The project is resolved from the key: nothing changes in the request.curl https://api.korely.ai/v1/memories \ -H "Authorization: Bearer kor_live_..." \ -H "Content-Type: application/json" \ -d '{"content": "User prefers email follow-ups", "user_id": "customer-4812"}'Because the project is carried by the key, you get isolation simply by minting keys in different projects. Mint a staging key in a Staging project and a production key in a Production project, point each environment at its own key, and the separation follows automatically with no code change: separate keys, separate usage views, separate memory, and the staging → production promotion path.
Worked example: staging to production
The following shows the full lifecycle an agent builder goes through when moving a support bot from staging to production. The API calls are identical in both environments; only the key changes.
from korely_memory import Korely
# ── Staging environment ─────────────────────────────────────────────────────# Key is scoped to the "Staging" project in the dashboard.staging = Korely(api_key="kor_live_staging_...")
staging.add( "Test user verified the support-bot correctly recalled meal preference.", user_id="test-customer-001", agent_id="support-bot-staging",)
results = staging.search( "meal preference", user_id="test-customer-001", agent_id="support-bot-staging",)# results[0].snippet => "Test user verified the support-bot correctly..."
# ── Production environment ───────────────────────────────────────────────────# When staging tests pass, swap the key for the one in the "Production" project.# No code change required, the project is resolved server-side from the key.production = Korely(api_key="kor_live_prod_...")
production.add( "Customer-4812 prefers vegetarian meals. Mentioned nut allergy.", user_id="customer-4812", agent_id="support-bot",)
facts = production.get_facts( user_id="customer-4812", agent_id="support-bot",)# get_facts returns a flat list (newest first). Access fields by attribute.# facts[0].subject == "customer-4812"# facts[0].predicate == "likes" # normalized; raw verb in predicate_raw# facts[0].predicate_raw == "prefers"# facts[0].object == "vegetarian meals"# facts[0].invalid_at is None # still live (None == active)# facts[1].predicate == "allergic_to", facts[1].object == "nuts"
When the staging tests pass, the only change is in the environment variable
that holds the key. The same agent_id and user_id
values that worked in staging work in production with no modification, and
memories written by the staging key are invisible to the production key.
A distinct agent_id such as support-bot-staging
is optional; keep in mind that each distinct name holds one slot of the
account-wide agent cap.
See also
- The memory model, the three-layer architecture (managed store, session memory, cross-session facts) that sits underneath every key and project.
- The knowledge graph,
how entities and typed facts are extracted automatically from every
add()call and whyagent_idkeeps graph namespaces clean. - API reference, full
parameter docs for
POST /v1/memories,GET /v1/facts, and the rest of the/v1contract your agents call.