Project API Keys for Agents: Isolate Memory per Repo
One shared key across every repo means every agent reads every project's context. This guide sets up project api keys the isolated way: one project per repo, one ak_ key per agent, and scoped at_ tokens for management.
On this page
Why one shared key across projects leaks context
Every agent session starts with an empty context window. Anything the last session learned — the package manager, the deploy order, the migration that must run before the seed script — is gone unless it lives outside the conversation. Audaxic Memory keeps those facts in a shared memory layer: the plugins save decisions as you work and inject the relevant ones when a session starts, and the data-plane API is mem0-like, with POST /add, POST /search, GET /list, PUT /update, and DELETE /delete/{memory_id}.
That layer only helps if each repo gets its own slice. Point every repository at one project and one ak_ key, and every search pulls from a mixed pool: a convention from the billing service surfaces in the marketing site's session, a note from a weekend experiment outranks the deploy checklist, and deleting a stale fact risks removing something another repo still needs. The symptom is an agent applying another project's rules with confidence — the test command from repo A run in repo B, a schema constraint that does not exist here.
One shared credential is an access problem too. The same key ends up on every laptop, in every CI job, and in every contractor sandbox. There is no smaller unit to hand out and no way to cut off one machine without touching all of them. A throwaway experiment writes into the same namespace as production work. When that key rotates, every agent stops until its config is updated.
Isolation fixes both problems. Data is isolated per organization with namespace-scoped vector search, and the project is the practical boundary inside the organization: an agent using one project's key works with that project's memories only. Your project api keys enforce that boundary — one project per repo, one key per agent — so a search in repo B never sees repo A's facts.
Project API keys: one project per repo
Use one project per repository, service, or agent workflow. Name the project after the repo so the mapping survives team changes — checkout-service, billing-worker, marketing-site — and group related projects in one workspace per team or product area. A new teammate reads the project name and knows exactly which memory their agent will read.
Splitting costs nothing. Projects are unlimited on every plan from Hobby through Enterprise, and the account ceilings — 500,000 projects and 1,000,000 keys per account — leave far more headroom than per-repo scoping will use. If the payments service and the docs site share one project today, split them: every retrieval then searches one codebase's context instead of two. The team guide to shared agent memory for teams shows the same workspace-first layout for larger setups.
Create the project where you manage the workspace. The dashboard is the usual path, and dashboard sessions authenticate with a Clerk session JWT for dashboard use. Decide on day one what belongs in the new project's memory: preferences like the package manager, decisions with their reasons, and constraints such as a required staging deploy. Temporary debugging state and secrets do not belong in memory; store the lesson, not the token.
Seed the project in its first session while conventions are fresh. Have the agent record the test command, the lint rules that block merges, and one or two gotchas from the current sprint. Write one fact per memory, phrased the way a future session would search for it. Small atomic facts also cost less: an add request counts per memory extracted from a message batch, so one /add call that extracts five memories counts as five adds.
Create ak_ keys per agent or machine
Project keys use the ak_ prefix and authenticate against the data plane at https://api.memory.audaxic.com. A key reaches one project, so an agent working in checkout-service touches only that project's memories when ten other projects sit in the same workspace. Agents on the same repo share the project's memory — Claude Code, Codex, and OpenCode can all read what each other saved — while each agent keeps its own credential.
Issue one key per agent per project. Never copy one key across machines. Separate keys keep the blast radius to one machine: a lost laptop or a departing contractor affects one credential, and every other agent keeps running while you replace that one. The authentication guide documents which key goes where. Make no exceptions for "temporary" shared keys.
Run one install command on each machine, using that machine's key:
npx @audaxic/memory-claude install
npx @audaxic/memory-codex install
npm install -g @audaxic/memory-opencode
For Claude Code specifics, follow the per-agent plugin setup for Claude Code to install and verify recall on that machine. For OpenCode, follow the OpenCode plugin path for persistent memory instead of reusing a Claude key across tools.
Agents that connect over MCP use the same per-project key as a Bearer header against https://memory-mcp.audaxic.com/mcp over Streamable HTTP. That is the supported path for Claude Desktop, Cursor, Windsurf, and any MCP-compatible client, since Cursor connects through MCP only and there is no Cursor plugin. Point two machines at keys for the same project and they read and write the same memories with no files to sync. Point them at keys for different projects and their memories never mix.
Pin the API version in anything automated with the date-based X-Api-Version header — the current version is 2026-09-25 — so scripts fail loudly instead of silently when the API moves. Confirm a key reaches the intended project with GET /list, which is paginated with limit and offset. If the listing shows the other repo's facts, the key is wrong, not the search. The quickstart has the request formats for the data-plane endpoints.
Manage projects and keys with scoped at_ tokens
Project keys move memories; they do not manage the account. Anything that creates projects or issues keys goes through the management plane at https://memory-api.audaxic.com with an at_ workspace auth token. Every token carries explicit scopes: projects:read, projects:write, keys:read, keys:write. A provisioning script that only inventories projects gets projects:read and nothing else.
| Credential | Prefix | Plane | Use it for |
|---|---|---|---|
| Project key | ak_... |
Data plane (api.memory.audaxic.com) |
Agent add/search, MCP Bearer |
| Auth token | at_... |
Management plane (memory-api.audaxic.com) |
Create and manage projects and keys |
| Dashboard session | Clerk JWT | Dashboard only | Browser sessions in the dashboard |
Scope automation to the smallest job that works. A nightly job that provisions review sandboxes might hold projects:write, while a reporting job that lists project metadata holds projects:read alone. Neither needs a data-plane key unless it also reads or writes memories. Scopes draw the line between "automation can set up one workflow" and "automation can do anything the workspace can."
Keep every token to its documented scopes: the published scopes cover projects and keys (projects:read, projects:write, keys:read, keys:write). Let tokens handle only the project-and-key automation their scopes allow. The auth token docs list every scope and the operations it unlocks. Check there before widening a token that already works.
Management create operations are limited to 100 per hour per IP, and responses carry RateLimit-Limit, RateLimit-Remaining, RateLimit-Reset, and RateLimit-Policy headers. Read those headers in provisioning scripts and back off before hitting the wall instead of retrying blindly. When a script starts failing, first check whether its token still carries the scope the failing call needs.
Test isolation with a wrong-key check
Trust the boundary only after you test it. Run the wrong-key test: write a canary fact with one project's key, then search for it with another project's key and confirm it never surfaces. Name the canary so its origin is obvious — "checkout-service canary: refunds require a staging deploy first" — and search the exact wording.
- Save the canary with Project A's key via
POST /add(request body shape per the quickstart). - Confirm it is visible from Project A with
POST /search. - Repeat the identical search with Project B's key and confirm the canary is absent.
- Delete the canary with
DELETE /delete/{memory_id}so test data never becomes team lore.
# Store the canary with Project A's key (body shape per the quickstart)
curl https://api.memory.audaxic.com/add \
-H "Authorization: Bearer $PROJECT_A_KEY" \
-H "X-Api-Version: 2026-09-25" \
-d @canary-add.json
# Search the same wording with Project B's key — expect no canary
curl https://api.memory.audaxic.com/search \
-H "Authorization: Bearer $PROJECT_B_KEY" \
-H "X-Api-Version: 2026-09-25" \
-d @canary-search.json
Run the canary in the other direction too when two repos share a workspace: store in B, search from A. If either direction leaks, the keys are crossed — one agent uses the other project's key — and GET /list on each key shows which project it reaches. Fix the config, not the query.
Hold every key in an environment variable — one per agent per machine — and never commit keys to the repo, the docs, or the chat transcript. A key pasted into a remembered conversation becomes a fact any session can recall. Tight queries also spend less: the first 10 memories in a search count as one retrieve request and each additional 10 counts as one more, so a 25-memory search costs three requests.
Respect one guardrail while testing: the data plane allows 100 failed authentication attempts per 4 hours per IP, and 429 responses include Retry-After. A wrong-key test uses two valid keys, so it never trips that guard. A script hammering a revoked or mistyped key will trip it — fix the credential, do not retry faster. When the canary stays invisible from the wrong project and visible from the right one, isolation is proven. Repeat this project api keys pattern for every new repo to keep it that way.
FAQ
How do project api keys keep one repo's memory out of another?
Each ak_ key reaches a single project, and data is isolated per organization with namespace-scoped vector search. An agent searching with repo B's key never sees repo A's facts. The wrong-key test in this guide proves it: store a canary with one key and confirm the other key cannot find it.
When do I need an at_ token instead of an ak_ key?
Use an ak_ key for data-plane work such as add, search, list, update, and delete, and an at_ token for management-plane work such as creating projects and issuing keys. Tokens carry only the scopes you grant: projects:read, projects:write, keys:read, keys:write. Keep each token to the smallest set of scopes its job needs.
How many projects and keys can I create?
Accounts support up to 500,000 projects and 1,000,000 keys, and projects are unlimited on every plan from Hobby through Enterprise. There is no cost reason to share one project across repos. Give every repo its own project and every agent its own key.
What should I do if a project key is exposed?
Create a new key for that project and update the one agent or machine that used the exposed key, leaving every other agent untouched. Because each agent holds its own credential, exposure stays limited to one machine. Never commit the replacement to the repo — hold it in an environment variable.
Written by Efe — Oct 11, 2026 · More articles · X @AudaxicTech