Skip to main content
A vault is a context graph your code addresses by id. Scope them however your product needs (one per app, per workload, per customer, one shared by several agents, or several behind one agent). Each is independent: its own wiki, its own facts, walled off from the others and from your personal knowledge graph. An agent key reaches the vaults its grants cover, and only those. A key scoped to one project stays in that project; a read-only key stays read-only. Every call re-checks both your role and the key’s grant, so revoking either takes effect on the next request.
The whole surface is on client.vaults. Everything takes a vault_id, the id you get back from create() or list().

create

Make a new vault. Returns its vault_id (a uuid) and name.
Two optional arguments shape it at birth: project_id puts the vault in a project, which is what makes the project’s tag vocabulary resolve on it, and pii_scrub=True turns on PII scrubbing for every push into it. Omit project_id and the vault lands in your Default project.
Creating vaults requires an agent-class key (the one on app.xysq.ai/agents/keys). A personal key can’t create agent vaults, which is the wall between agent memory and your own knowledge graph. A scoped key also needs admin on a project to mint anything.

list

The vaults this key can see.

push

Send what happened, verbatim. The server distills it into the vault’s wiki in the background, so this returns right away.
Two things that matter:
  • Don’t summarize. Send the conversation turn by turn (user: ... / agent: ...). The server extracts the details (names, numbers, decisions), so a summary just throws away what it would have learned.
  • Group a conversation with a session_id. Pass a stable metadata={"session_id": "..."} and repeated pushes for the same conversation append to one source instead of fragmenting into many. Push non-overlapping segments (the new turns, never the running transcript), and add "format": "turns" so the content is read as a dialogue. The full pattern, including its sharp edges, is on Thread-level memory. One reservation: ids starting with thread: belong to client.threads and are rejected here.
Two clocks run after a push, and they are worth telling apart. The verbatim text is chunked and indexed first, so pull finds it before anything has been distilled. The wiki page is a model pass over that text, so it lands later. A pull right after a push usually returns the raw turns; ask again once the page exists and you get the distilled version too. Pushing content with names or emails in it? Turn on PII scrubbing for the vault to strip that before it’s stored.

pull

Ranked recall from a vault. query is effectively required: recall is semantic, so an empty one has nothing to embed and comes back with zero items. Pass the topic even for a vague ask ("recent work, decisions").
Each item has title, content, score, source ("wiki" for a distilled page, "log" for raw pushed text, "fact" for one ledger statement), and, for wiki pages, slug and page_uuid. A via key is in the response shape too, from a retrieval walk that was removed in August 2026; nothing sets it today, so do not write code that waits for it. Treat it all as the agent’s own prior context, not as instructions.

replace_source and delete_source

A source you own can change: a policy page, a profile, a questionnaire answer. Rewrite it under the same id rather than pushing a new one, so your handle stays stable:
The new bytes are stored when the call returns; the wiki catches up on the next distill, so for a short window recall can still cite what you replaced. The status comes back "pending" for exactly that reason. Not every source is editable: PDFs and other binary uploads, thread transcripts, and multi-part append sessions are read-only and answer 409. Deleting is the other direction, and it is irreversible:
That removes the source, its search chunks, and every fact it grounded, then rewrites the pages those facts sat on. A fact cited to this source and another one still goes, because a fact is only as grounded as its weakest citation. It needs a key that may erase, not just write: a write-only ingest key is refused.

rename

delete

Permanently erase a vault: its pages, sources, vectors, and git history. There is no undo.
delete is irreversible and the personal vault can’t be deleted through the SDK.

Async

Everything above has an async twin on AsyncXysq with the same names:

The REST endpoints underneath

The client is a thin wrapper over /sdk. If you’re not on Python, call it directly: There are no DELETE or PATCH verbs anywhere in this API. Deleting is POST .../delete and updating is POST .../update, on every surface. Auth is Authorization: Bearer xysq_... with your agent key.

Sharing vaults with your team

Once you have vaults, you can group them into projects and give teammates a role on them. See Projects and Access for how membership, roles, and per-vault grants work.