Projects
A project is a notebook somebody else can also read. Your assistant writes a fact on a page and names the people and things that fact is about; later, you — and every one of your Nirvai agents — open the same notebook and find the same page. It is not your assistant's private scratchpad. It is one brain, shared.
Everything on this page runs through nirvai_execute under the projects area. Read
the MCP reference first if the alias grammar is new to you.
Projects used to be called memories, and the actions were named memory.*. Those old names are
deprecated: calling one now returns a clear error naming its projects.* replacement and asking
you to re-download the projects skill package. Use projects.*.
What a project holds
| Piece | What it is |
|---|---|
| Observation | One atomic fact, with a stable slug that is its permanent address, plus a title, category, tags and the date it was observed. |
| Entity | A person, company or thing an observation mentions. Every observation must name at least one, each with a description — that description is what recall matches on. |
| Relationship | A typed link between two entities ("Acme signed MSA-2025"). |
| Appendix file | An original document kept beside the notes, addressed by a logical path. |
A project's embedding model — the thing that decides what "similar" means when you search it — is fixed when the project is created and can never change. Your assistant picks it from the listed models at creation and is refused if it guesses. Changing it later would mean rebuilding the project.
The verbs
| Verb | Scope | What it does |
|---|---|---|
projects.recall | read | Browse or search a project. Three modes — see below. |
projects.get_observation | read | Expand ONE observation to its full text, by slug. |
projects.list_files | read | List the appendix — path, filename, description, type, size. No file contents. |
projects.read_file | read | Get a short-lived download link for one appendix file. |
projects.add | write | Write one new observation directly, with its entities and relationships. |
projects.store_file | write | File an already-uploaded document into the appendix at a path. |
projects.update_observation | write | Edit an observation in place; only the fields supplied change. |
projects.consolidate | write | Suggests merges, de-duplications and missing links. Never changes the project by itself. |
projects.apply_consolidation | write | Accept ONE suggestion from a consolidation, by id — this is the step that actually changes the graph. |
projects.reject_consolidation | write | Discard one suggestion; nothing is applied. |
projects.edit_store | write | Rename the project or change its description, icon or visibility. The embedding model stays fixed. |
projects.create_store | create | Make a new project. embedding_model_id is required and permanent. |
projects.propose | create | Author a reviewable package of projects and observations; you click Create. |
projects.delete_observation | destructive | Withheld. Refused for every token — deletion is not possible over the connection. |
projects.merge_entities | destructive | Withheld. Fusing two entities is irreversible, so it is refused for every token. |
Anything a person should see before it lands goes through projects.propose — your assistant writes
the package, you get a review page with the observations laid out as cards and a real Create button.
The direct writes are for the cases where a review adds nothing, like fixing one wrong sentence.
projects.consolidate only proposes a clean-up set; it changes nothing. You (or your assistant, if
you ask it to) then accept the good suggestions one at a time with projects.apply_consolidation and
drop the rest with projects.reject_consolidation. Re-applying an already-applied suggestion is
refused cleanly.
Where you finish this
projects.propose creates nothing. It hands you a link to a page at /external/memories/… inside
Nirvai, where you read the project and the first facts it will hold, and click Create.
- You have to be signed in, and only you can open it. A proposal link is not shareable.
projects.addhas no review page. Writing a new observation into a project that already exists lands directly — the review step is for creating the project itself.- Proposing into a project you already have adds facts to it — pass its id and the package is an add-only one; it never makes a second project.
- It can't be clicked twice. Re-opening afterwards shows Created ✓ and refuses a second project; your assistant picks up the new id from the feed, not by proposing again.
- Want it different? The page gives you a copy-paste block to hand back, and your assistant re-proposes — see the review page.
recall has three modes, and you must name one
mode is required. The connection validates the (mode, query) pair and rejects an inconsistent
one — it will never quietly switch modes on your assistant's behalf.
mode | query | Use it to | You get back |
|---|---|---|---|
recall | must be absent | Browse or enumerate — everything in a category, everything since a date, everything about an entity | Full-text observations plus entities. Complete; no follow-up needed. |
local | required | Ask a natural-language question | Ranked entities, their relationships, and 240-character observation snippets flagged truncated. |
cascade | required | The same question, when local came back thin | The same shape as local. |
mode="recall" with a query is rejected. mode="local" without one is rejected. Filters differ by
mode — nirvai_describe on the project lists which ones that project accepts.
nirvai_execute(
alias = "projects.get_observation",
args = { store: "…", slug: "acme-renewed-msa" },
description = "Read the full note behind the Acme snippet"
)
Reach for get_observation to expand one truncated snippet. Don't loop it to rebuild a project —
that is what the structural mode is for, and it already returns full text.
Worked example: reconciling on first connect
The first time an assistant connects, the durable facts it already carries about you belong in Nirvai, where your agents can see them too. Read first, then write only what is missing.
nirvai_execute(
alias = "projects.recall",
args = { store: "…", mode: "recall", category: "clients", limit: 20 },
description = "See what Nirvai already knows about my clients"
)
nirvai_execute(
alias = "projects.add",
args = {
store: "…",
title: "Acme renewed their MSA",
content: "Acme renewed the master service agreement in March 2025 on a 24-month term.",
category: "contracts",
tags: ["acme", "renewal"],
entities: [{ name: "Acme Corp", type: "company",
description: "long-standing enterprise client; renewed MSA" }],
relationships: [{ source: "Acme Corp", target: "MSA-2025",
relationship_type: "signed" }]
},
description = "Record the Acme renewal I already knew about"
)
This is a one-time reconciliation per project, not a dump of every turn — durable facts about your world only, never transient chat state.
Limits & guarantees
- An observation with no described entity is rejected, up front and cleanly. Without one it would be unfindable, so the connection refuses to write a fact nobody can ever recall.
- Consolidation only proposes.
projects.consolidatereturns suggestions; applying them is a separate, explicitprojects.apply_consolidation. If an assistant says it cleaned up your graph without that step, it did not. - Deletion is impossible.
projects.delete_observationandprojects.merge_entitiesrefuse for every token, always. - Editing a title may re-mint the slug; a content-only edit keeps it, and keeps the entities linked to it.
- Results are bounded. Recall returns a preview plus a link, never the raw graph; large files come back as a download reference rather than inline text.
- Every successful write shows up immediately in your projects view and in the Activity Feed.