# Artifacts Source: https://docs.klio.tech/concepts/artifacts Files, documents, and JSON records shared across the org, discovered through the same recall an agent already calls. Memory is good at facts, decisions, and plans — short, durable statements. It is the wrong shape for a design doc, a dataset, or a PDF. Artifacts are Klio's answer to that: a place to put the bytes, wired into the same discovery path as everything else. An artifact is a document, a JSON record, or a file, stored under the org and made discoverable to every agent in it — the same tenancy boundary as memory, described in [Scope](/concepts/scope). ## Discovery: a card, then the bytes This is the part worth understanding before the tool parameters. Storing an artifact does two things, not one. It stores the bytes, and it writes a short **card** into the same shared memory that [`recall`](/tools/recall) already searches — a sentence or two describing what the artifact is, tagged `memory_type: "artifact"` with the artifact's id in `metadata.artifact_id`. That means an agent that has never heard of the artifact finds it the ordinary way: it calls `recall` about something it needs, the card surfaces like any other memory, and the agent reads `metadata.artifact_id` off the result and calls [`artifact_get`](/tools/artifact-get) to fetch the contents. No separate artifact index, no second tool to remember to call. ```json theme={null} { "title": "Q3 pricing analysis", "summary": "Competitor pricing comparison and margin model for the Q3 review", "kind": "document", "content": "# Q3 Pricing Analysis\n\n..." } ``` Klio writes the artifact and, alongside it, a card: ```text theme={null} [artifact] Q3 pricing analysis — Competitor pricing comparison and margin model for the Q3 review (document, 4.1 KB) ``` ```json theme={null} { "query": "did anyone look at competitor pricing for Q3?" } ``` `recall` returns the card like any other memory — same relevance ranking, same scope rules — with `metadata.artifact_id` pointing at the full document. ```json theme={null} { "artifact_id": "art_01J...", "mode": "text" } ``` Returns the text, paginated. See [`artifact_get`](/tools/artifact-get) for paging and the binary path. The card is deliberately terse — enough for recall's ranking and for a human or agent to decide whether it is worth opening. The full content lives behind `artifact_get`, not in the card itself. ## Storing one [`artifact_put`](/tools/artifact-put) has three behaviours, selected by which arguments you pass: | Path | When | Calls | | -------------------- | --------------------------------- | ------------------------------------------------------- | | **Inline** | Text up to 64KB | One call, with `content` | | **Presigned upload** | Larger or binary content | Two calls: request, then upload the bytes, then confirm | | **Confirm** | Second half of the presigned path | One call, passing back the `artifact_id` | Inline is the only write path available to clients that speak MCP but cannot make an arbitrary HTTP request — ChatGPT connectors and Claude.ai custom connectors both fall in this category. If your integration is one of those, your artifacts go through `content`, up to 64KB. Confirm is not a formality. The server re-measures the uploaded object itself and enforces the plan's per-file and pool limits against that measured size, not whatever the client declared when requesting the upload URL. ## Reading one [`artifact_get`](/tools/artifact-get) has two modes: * **`mode: "text"`** *(default)* — the contents, one page at a time. Binary artifacts return an error pointing at `mode: "url"` instead — Klio does no text extraction from PDFs or Office documents in this version. * **`mode: "url"`** — a presigned download link, valid for 15 minutes, forced to download rather than render inline. ## Retracting one [`forget`](/tools/forget) accepts an artifact id as well as a memory id. It retracts the artifact and hides its card in the same call — recall stops surfacing it immediately. ## Storage limits Artifacts are available on every plan; what a plan buys is capacity, not access. Limits are per file and for the org's total pool: | Plan | Per file | Total pool | | ------------------ | -------- | ---------- | | Free | 10 MB | 100 MB | | Starter, Pro, Team | 50 MB | 5 GB | | Platform | 1 GB | 1 TB | A single upload is capped at 100 MB regardless of plan — multipart upload is not available yet. Talk to us if you need to store artifacts larger than that. Once the pool is full, writes are rejected until something is forgotten, superseded, or the plan is upgraded. Reads always keep working — a full pool never blocks `artifact_get` or `recall`. ## Retention Ordinary memories age out under the plan's retention window. Artifacts do not — an artifact lives until it is forgotten, superseded by a newer version, or the org's storage pool fills. There is no time-based expiry on artifact content. ## What this version does not do Artifacts are managed through the MCP tools only. There is nowhere in app.klio.tech to browse, upload, or delete one directly. The `klio` CLI does not have an artifact command in this version. Binary formats — PDF, Word, Excel, images — are stored and downloadable, but nothing extracts their text for `mode: "text"` or for recall. Only the card is searchable; the binary content itself is not. # The handover loop Source: https://docs.klio.tech/concepts/handover-loop Six movements that turn raw session activity into something the next agent can act on. A shared text store is not a workplace. The difference is what happens between one agent writing and the next one reading — six movements, of which the last three are the ones a plain database will not do for you. An agent connects over MCP and is resolved to an org, an agent identity, and optionally a space. No vendor owns the door — Claude Code, Cursor, Codex and your own agents all arrive the same way. Work is recorded as it happens through `remember`, `decide`, `plan`, `observe`, and `note`. Secrets and personal data are stripped **before** anything is persisted, and that step fails closed. Every write lands under an org, and optionally a space. The job's knowledge stays with the job rather than in one undifferentiated pile. See [Scope and spaces](/concepts/scope). Raw activity is condensed into the few durable facts worth keeping. The next agent should inherit conclusions, not transcripts — a thousand observations are worth less than the one decision they led to. When a newer memory contradicts an older one, the old one is superseded rather than left to compete with it. This is the step almost nothing else does, and it is why recall stays sharp instead of degrading into a pile of mutually contradictory notes. The next agent calls `recall` and receives current state. One writes; the next to look already sees it. ## Why distil and retire matter Keeping text is easy. Two things make stored context stop being useful over time, and both are the store's job to handle: An agent that logs every step produces thousands of low-value entries. Recall over that returns noise, and the model spends its context budget reading things that did not matter. Distilling means a session's worth of activity collapses into the handful of facts that survive it. Six months in, the store holds "we use fixed backoff" *and* "we use jittered backoff." Both surface. The agent picks one — sometimes the wrong one — and quietly undoes work. Superseding means the retired statement stops being returned, so nobody acts on stale truth. ## What the loop does not do Klio does not notify running agents. A write is available to the next agent that **reads**, immediately — but an agent already mid-session will not learn about it until it calls `recall` again. If you need two agents to coordinate within a single turn, that is a job for your orchestration layer, not for memory. Nor does it decide what is worth keeping on your behalf. Agents write what they are told to write. The prompt guidance in the [Quickstart](/quickstart#make-it-a-habit) exists because a workplace where nobody writes anything down is just an empty room. # Scope and spaces Source: https://docs.klio.tech/concepts/scope Strong scope is the feature. Random global memory everywhere is the failure mode. The most common objection to shared agent memory is the right one: memory that leaks everywhere is worse than no memory. An agent working on your billing service should not surface a note from an unrelated prototype, and one team's context should not appear in another's. Klio answers that with three separate axes. ## The three axes The tenant boundary, resolved from your API key. Nothing crosses it. Every read and write is confined to the org the key belongs to. Who wrote it, from the `X-Vex-Agent` header. Used for attribution, and for private memory when you ask for it. A named subdivision within the org — one per project, service, or workstream. Managed with the [`space`](/tools/space) tool. ## The visibility ladder Where a memory lands depends on **how it was written**, not on a parameter you have to remember. | `scope` | Who can recall it | What lands there | | ---------------------- | ---------------------------------------- | ----------------------------------------------------------- | | `private` | **Only you.** Not teammates. Not admins. | Everything your editor captures passively | | `project` | Members of that project, and org admins | Explicit writes made while a project is set | | `org` | Everyone in the org | Explicit writes — `remember`, `decide`, `plan`, `note` | | `agent` *(deprecated)* | The agent identity that wrote it | Superseded by `private`. Still readable; no longer written. | ### Capture is private, sharing is deliberate Passive capture — the hooks that record what your agent did — lands in **your** private scope. Nobody else can read it, including an organisation administrator. Calling a write tool is the act of sharing. `remember`, `decide`, `plan` and `note` write to the team, or to a project when one is set. ```json theme={null} { "content": "The staging deploy needs the VPN on" } ``` That goes to the whole org, because you chose to write it. ### Recall spans everything you are entitled to A normal `recall` searches your private memories, the projects you belong to, and the org's shared brain — in one call. Ask for `scope: "private"` to narrow to your own. ### Promoting something you captured When a passive capture turns out to be worth sharing, promote it: ```json theme={null} { "memory_id": "60a0fa87-…", "to": "org" } ``` `share` moves it from your private scope to the team's, and keeps you recorded as the author. Only the owner of a memory can share it. **Private means private.** There is no administrator override, no support path and no break-glass. An organisation administrator sees every org and project memory and a single org-wide storage total — never the contents of anyone's private scope, and never a per-person count of it. **`agent` scope is not a privacy boundary** and never was. It resolves against the `X-Vex-Agent` header, which the client sends and can set to any value. It is deprecated in favour of `private`, which is enforced against your verified credential. Existing `agent`-scoped memories remain readable; nothing new is written there. ## Spaces A space is a named store within the org. Use one per project so a question about the billing service does not pull answers from the marketing site. ```json theme={null} { "action": "create", "name": "Billing service", "slug": "billing" } ``` Then pass the slug on reads and writes: ```json theme={null} { "content": "Invoices are generated nightly at 02:00 UTC", "space": "billing" } ``` ```json theme={null} { "query": "when do invoices generate?", "space": "billing" } ``` Omit `space` and you are working against the org's default store. See the [`space` tool](/tools/space) for `list`, `create`, `info`, and `switch`. ## Narrowing a recall [`recall`](/tools/recall) also accepts a `project` filter, which narrows results without needing a separate space: ```json theme={null} { "query": "auth error handling", "project": "api", "limit": 5 } ``` Clients can additionally declare a workspace-wide project through the `X-Vex-Project` header. A project is identified by whichever of these it has: a git remote URL when the workspace is a git repo, or the repository root directory path when it is not. Both resolve. Earlier, only a git remote or a project's display name looked itself up correctly — a non-git project fell back silently to org-wide recall, with nothing to indicate why its memories were not showing up filtered. Directory-path projects now resolve the same way git-remote ones always did. Filtering by project is additive, not subtractive: recall fills the result set with that project's memories first, then — if the limit has not been reached — fills the remaining slots with unfiled memories (nothing was ever explicitly attached to a project). Memories filed under a *different* project never come back. There is no third pool for "everything, ranked, regardless of project." Project resolution **fails open**. If the header is missing, the identifier is unknown, or the lookup errors, the request falls back to org-wide rather than returning nothing. That keeps a misconfigured client working, but it means the header is a convenience — never a security boundary. The boundary is the org. This is the same story as [spaces](/tools/space#spaces-are-not-a-tenancy-boundary): narrowing by project is a relevance filter. Anyone holding the org's API key can still recall any project's memories by asking for them, or by omitting the filter entirely. ## Choosing a layout One org, one space per repo. Set `X-Vex-Project` per workspace, or pass `space` explicitly. Skip `agent` scope entirely — with one person, shared is the point. One org, spaces per service or bounded context. Set `X-Vex-Agent` per tool so you can see whether a decision came from Claude Code or Cursor, and who was driving. One org per client, not one space per client. Spaces subdivide; they are not a tenancy boundary. If two bodies of work must never see each other, they need separate orgs and separate keys. # What Klio keeps Source: https://docs.klio.tech/concepts/what-klio-keeps What belongs in a shared workplace, what is stripped before it is written, and what is retired once it stops being true. A memory layer is defined as much by what it refuses to keep as by what it stores. This page is the honest version of both. ## Keep vs. never keep * **Decisions** — what was chosen, and why * **Repo rules** — conventions the work must hold to * **Plans** — the shape of work in flight * **Durable facts** about the project or the people on it * **Secrets** — keys, tokens, credentials * **Personal data** — redacted before write * **Transcripts, tool calls, file contents** * **Anything a newer decision has retired** The test for whether something belongs: *would the next agent be worse off without it?* A decision passes. A log line of a file being read does not. ## Redaction fails closed Secrets and personal data are stripped **before** anything is persisted — not on the way out. If content cannot be made safe, the write is rejected rather than stored in a degraded form. This is a backstop, not a licence. Redaction is pattern-based, and no pattern set catches everything. Do not deliberately route credentials or customer PII through memory tools on the assumption that they will be caught. Prompt your agents not to send them in the first place. ## Superseding When a newer memory contradicts an older one, the older one is superseded and stops surfacing in recall. The chain is retained — the history of what was believed when is not deleted — but only current truth comes back from a query. This is what keeps recall sharp over months. Without it, a store accumulates contradictions and the agent picks between them arbitrarily. To retract something explicitly rather than waiting for it to be contradicted, use [`forget`](/tools/forget) with the memory id from a prior recall. ## Deduplication Near-identical writes are collapsed rather than stored twice. Agents are repetitive by nature — several of them working the same project will write the same conclusion in slightly different words, and without dedup the store fills with paraphrases of a single fact. Dedup is similarity-based, so it is a judgement call rather than an exact match. Two genuinely distinct facts phrased almost identically can be collapsed. If you need both, make the wording meaningfully different or scope them to different [spaces](/concepts/scope). ## Where it physically lives Memory lives on Klio's infrastructure, encrypted in transit and at rest at the infrastructure level, isolated per org. Secrets and PII are redacted before storage. The encryption keys are ours, and Cloud writes are not hash-chained. If your threat model requires keys you hold, self-host. Memory lives in your own Postgres, on your own hardware. It is encrypted at rest under a key **you** own, and every write is chained with SHA-256 so the history is tamper-evident and independently inspectable. Nothing leaves your estate. See [Self-hosting](/self-host/install). The user-held key and the hash chain are properties of the **self-hosted** engine specifically. Anywhere you see those claims, they refer to self-hosting — Klio Cloud makes the weaker guarantees described above. # Any MCP client Source: https://docs.klio.tech/connect/any-mcp-client Klio is a standard Streamable HTTP MCP server — anything that speaks the protocol can join. There is no Klio SDK to install. If your agent speaks MCP, it can use the workplace, and that is deliberate: a workplace that only admitted one vendor's agents would not be a workplace. ## Connection details | | | | ------------- | ------------------------------------------------------------------------------------------------------------ | | **Endpoint** | `https://mcp.klio.tech/mcp` | | **Transport** | Streamable HTTP | | **Auth** | `X-Vex-Key` header, or an OAuth bearer token | | **Identity** | `X-Vex-Agent` header (optional, recommended) | | **Tools** | `recall`, `remember`, `observe`, `plan`, `decide`, `note`, `artifact_put`, `artifact_get`, `space`, `forget` | ## Generic configuration Most clients accept a variant of this shape: ```json theme={null} { "mcpServers": { "klio": { "url": "https://mcp.klio.tech/mcp", "headers": { "X-Vex-Key": "YOUR_KEY", "X-Vex-Agent": "your-agent-name" } } } } ``` Give every distinct client its own `X-Vex-Agent` value — `codex`, `ci-bot`, `review-agent`. That string is what makes "which agent decided this?" answerable later. ## Codex Add to `~/.codex/config.toml`: ```toml theme={null} [mcp_servers.klio] url = "https://mcp.klio.tech/mcp" [mcp_servers.klio.headers] "X-Vex-Key" = "YOUR_KEY" "X-Vex-Agent" = "codex" ``` ## Building your own agent Point any MCP client library at the endpoint and pass the headers. The tools arrive through the standard `tools/list` handshake with full JSON schemas — you do not need to hardcode their shapes. ```python theme={null} # Pseudocode — use whichever MCP client library your stack provides. client = MCPClient( url="https://mcp.klio.tech/mcp", headers={ "X-Vex-Key": os.environ["KLIO_API_KEY"], "X-Vex-Agent": "my-research-agent", }, ) hits = await client.call("recall", {"query": "what did we decide about retries?"}) await client.call("decide", { "content": "Cache embeddings for 24h", "rationale": "Re-embedding the same documents was 60% of our token spend", }) ``` ## Verifying the endpoint A bare request without a valid key returns `401`. That is the healthy response — it confirms the endpoint is live and enforcing auth: ```bash theme={null} curl -i https://mcp.klio.tech/mcp ``` ## Self-hosted Running your own engine? The endpoint is the same path on your own host, and everything else is unchanged: ``` http://localhost:8080/mcp ``` See [Self-hosting](/self-host/install) for the exact port your install exposes. ## Notes The hosted server accepts OAuth bearer tokens for clients that support the MCP authorization flow. The agent identity then defaults to the OAuth `client_id`, unless `X-Vex-Agent` overrides it. `X-AgentGuard-Key` is still accepted as an alias for `X-Vex-Key`, so older clients keep working. Do not use it in new integrations. # Claude Code Source: https://docs.klio.tech/connect/claude-code Connect Claude Code to a shared Klio workplace. ## Add the server ```bash theme={null} claude mcp add --transport http klio https://mcp.klio.tech/mcp \ --header "X-Klio-Key: YOUR_KEY" \ --header "X-Klio-Agent: claude-code" ``` Then confirm it registered: ```bash theme={null} claude mcp list ``` You should see `klio` with ten tools: `recall`, `remember`, `observe`, `plan`, `decide`, `note`, `artifact_put`, `artifact_get`, `space`, `forget`. `X-Vex-Agent: claude-code` is what makes attribution work later — it is how you tell which agent left a given decision. Pick a stable string and keep it consistent across machines. ## Make recall reflexive Claude Code will use the tools when it judges them relevant, but memory pays off when reading is automatic. Add this to `CLAUDE.md` at your repo root: ```md theme={null} ## Shared memory (Klio) Before answering questions about this project, call `recall` first — another agent may have already decided it. Persist durable knowledge as it arises, without being asked: - a decision is made → `decide` with its rationale - a plan is set → `plan` - a durable fact or preference → `remember` Do not persist secrets, tool call logs, or file contents. ``` Repo-level `CLAUDE.md` is the right home for this — it travels with the project, so every teammate's Claude Code picks up the same habit. ## Scope it to the repo If you run several projects, give each one its own [space](/concepts/scope) so a question about one does not pull answers from another: ```bash theme={null} claude mcp add --transport http klio https://mcp.klio.tech/mcp \ --header "X-Klio-Key: YOUR_KEY" \ --header "X-Klio-Agent: claude-code" \ --header "X-Vex-Project: git@github.com:acme/billing.git" ``` `X-Vex-Project` accepts a git remote URL. If the repo has no remote configured, pass the repository's root directory path instead — Klio resolves both the same way. Project resolution fails open — an unrecognised value falls back to org-wide rather than erroring. It is a relevance filter, not a security boundary. ## Local install If you are self-hosting, `klio init` wires Claude Code for you rather than you running `claude mcp add` by hand: ```bash theme={null} npx @klio-tech/klio init --local ``` See [Self-hosting](/self-host/install). ## Troubleshooting Run `claude mcp list`. If `klio` is absent the server was never added; if it is present but failing, the key is usually wrong — a bad key returns `401`. Most often the write went somewhere else. Check that both agents use the same key (same org), and that you are not writing with `space` set but reading without it. Without instruction, a model treats tools as optional. Add the `CLAUDE.md` block above — an explicit "call recall first" changes behaviour immediately. # Cursor Source: https://docs.klio.tech/connect/cursor Connect Cursor to the same shared workplace your other agents use. ## Add the server Create `.cursor/mcp.json` in your project (or `~/.cursor/mcp.json` for every project): ```json theme={null} { "mcpServers": { "klio": { "url": "https://mcp.klio.tech/mcp", "headers": { "X-Vex-Key": "YOUR_KEY", "X-Vex-Agent": "cursor" } } } } ``` Reload Cursor, then check **Settings → MCP** — `klio` should be listed with ten tools. A project-level `.cursor/mcp.json` contains your API key. Add it to `.gitignore`, or keep the config in `~/.cursor/mcp.json` instead so the key never sits in the repo. ## Set `X-Vex-Agent` differently per tool Use `cursor` here and `claude-code` in Claude Code. That difference is the whole point of the header — it lets you see, later, which agent left which decision, and it makes [`scope: "agent"`](/concepts/scope) meaningful. ## Make recall reflexive Add a rule in `.cursor/rules/klio.mdc`: ```md theme={null} --- description: Shared memory across agents alwaysApply: true --- Before answering questions about this project, call `recall` first — another agent may have already decided it. When a decision is made, call `decide` with its rationale. When a plan is set, call `plan`. When the user states a durable fact or preference, call `remember`. Do not persist secrets, tool call logs, or file contents. ``` ## Proving it works with Claude Code The point of a shared workplace is that it does not matter which agent shows up. Worth testing once: Have Claude Code record a decision with `decide`. Then start a fresh Cursor session and ask the same question in your own words. It calls `recall`, finds the decision Claude Code wrote, and answers — including *why*. You never re-explained it. If that works, both agents are on the same org and the handover is live. ## Troubleshooting Almost always the key. Cursor surfaces little detail, so test the endpoint directly — a wrong or revoked key returns `401`: ```bash theme={null} curl -i https://mcp.klio.tech/mcp -H "X-Klio-Key: YOUR_KEY" ``` Different keys mean different orgs, and orgs never share. Confirm both use the same key — and that one is not passing a `space` the other omits. # What is Klio? Source: https://docs.klio.tech/index A shared workplace for AI agents. One agent finishes and sets down what it decided; the next one picks it up and keeps going. Your agents don't forget because their memories are bad. They forget because each one keeps a private notebook. Every vendor built memory for its own agent, inside its own product. Your Claude Code context stays in Claude Code. Your editor's context stays in your editor. No vendor has a reason to hand your work to a competitor's agent — so you end up being the integration layer, re-explaining the same decisions to every tool. **Klio is the workplace those agents share.** It is vendor-neutral and speaks MCP, so any agent can clock in, read what the last one left, do its work, and set down what it decided for whoever comes next. Claude Code, Cursor, Codex, or your own agent. Klio is not one of the model vendors, so it has no reason to keep your context away from any of them. Memory lives under an org and a space — not one global pile. Strong scope is the feature; see [Scope and spaces](/concepts/scope). When a newer decision contradicts an older one, the old one is superseded. Anyone can keep text; almost nobody retires it. The core engine is open source and self-hostable, so the workplace can live on your own hardware. The layers that reason over it stay on Cloud. See [Self-hosting](/self-host/install). ## The shape of it An agent connects over MCP and gets ten verbs. In practice two of them carry most of the value: ```text Before acting theme={null} recall("how do we handle auth errors in the API?") → 3 memories: 1 decision, 1 repo rule, 1 plan ``` ```text After deciding theme={null} decide( content: "Retry 429s with jittered backoff, cap at 5 attempts", rationale: "Upstream rate-limits per minute; fixed backoff synchronised our retries" ) ``` The next agent to open the same project — whichever vendor it came from — calls `recall` and sees that decision. Nothing is re-explained, and no work is paid for twice. Writes are available to the next agent that reads, immediately. Klio does not push to agents that are already mid-session — an agent sees new state the next time it calls `recall`. ## Get started Connect your first agent to hosted Klio in about two minutes. The six movements that turn raw activity into something the next agent can actually use. All ten MCP tools, with their exact parameters and return shapes. Run the open-source engine on your own machine or infrastructure. # Quickstart Source: https://docs.klio.tech/quickstart Connect your first agent to a shared workplace, and watch a second agent pick up where it left off. By the end of this page one agent will have written a decision and a second agent — from a different vendor — will have read it back. That handover is the whole product; everything else is detail. ## Prerequisites * An MCP-capable agent. [Claude Code](/connect/claude-code), [Cursor](/connect/cursor), or [anything else that speaks MCP](/connect/any-mcp-client). * A free Klio account at [app.klio.tech](https://app.klio.tech/auth/sign-up). Prefer to run everything yourself? Skip this page and go to [Self-hosting](/self-host/install) — one command brings up the engine locally and wires your agents to it. ## Get connected Sign in at [app.klio.tech](https://app.klio.tech), open **Settings → API keys**, and create a key. It looks like `vex_live_…`. The key is shown once. Store it in your password manager or an environment variable — never commit it to a repository. Klio's hosted endpoint speaks Streamable HTTP MCP: ``` https://mcp.klio.tech/mcp ``` Authenticate with the `X-Klio-Key` header (the legacy `X-Vex-Key` name still works). For Claude Code: ```bash theme={null} claude mcp add --transport http klio https://mcp.klio.tech/mcp \ --header "X-Klio-Key: YOUR_KEY" \ --header "X-Klio-Agent: claude-code" ``` `X-Klio-Agent` is optional but recommended — it is what lets you see which agent wrote what. Clients that omit it share a single default agent identity. See [Authentication](/tools/authentication) for every header. Ask your agent to list its tools, or run: ```bash theme={null} claude mcp list ``` You should see ten Klio tools: `recall`, `remember`, `observe`, `plan`, `decide`, `note`, `artifact_put`, `artifact_get`, `space`, and `forget`. ## Prove the handover This is worth doing once, deliberately, so you can see the mechanism work. In your connected agent, say: > We're going to retry 429s with jittered backoff, capped at five attempts. > Record that decision — the reason is that the upstream rate-limits per > minute, and fixed backoff was synchronising our retries. The agent should call `decide`. You can also call it directly: ```json theme={null} { "content": "Retry 429s with jittered backoff, cap at 5 attempts", "rationale": "Upstream rate-limits per minute; fixed backoff synchronised our retries" } ``` Open a *different* agent — Cursor if the first was Claude Code — connected with the same key. Start a fresh session and ask: > How do we handle rate limiting on the upstream API? It calls `recall`, finds the decision, and answers with the rationale. You never re-explained it. If the second agent found the decision, your workplace is working. Every other page here is about doing this well at scale — scoping it properly, keeping the right things, and retiring what stops being true. ## Make it a habit Agents recall well when asked, but the value compounds when writing is automatic. Add something like this to your agent's system prompt or rules file: ```md theme={null} Before answering questions about this project, call `recall` first. When a decision is made, call `decide` with its rationale. When a plan is set, call `plan`. Do not persist secrets, tool call logs, or file contents. ``` Klio strips secrets and personal data before anything is stored, and the redaction step fails closed — if content cannot be made safe, it is not written. That is a backstop, not a licence to send it everything. See [What Klio keeps](/concepts/what-klio-keeps). ## Next Keep a team's memory shared without turning it into one global pile. Exact parameters and defaults for all ten tools. # CLI reference Source: https://docs.klio.tech/self-host/cli Every command and flag in the klio launcher. The launcher ships as [`@klio-tech/klio`](https://www.npmjs.com/package/@klio-tech/klio) on npm. Run it with `npx` — there is nothing to install globally. ```bash theme={null} npx @klio-tech/klio [options] ``` ## Commands Set up the local stack and wire your AI agents (Claude Code, Cursor, and any other supported client found on the machine). ```bash theme={null} npx @klio-tech/klio init [--cloud | --local] [--email ] [--image-tag ] ``` | Flag | Effect | | ------------------- | --------------------------------------------------------- | | `--local` | Run the full stack locally; skip the hosted/local prompt | | `--cloud` | Wire agents to Klio Cloud instead of a local stack | | `--email ` | Pre-fill the claim email | | `--image-tag ` | Pin a specific container image tag instead of the default | Show what is running, where, and as whom. The first thing to run when something looks wrong. ```bash theme={null} npx @klio-tech/klio status ``` Re-prompt for provider, curator and agent settings — or upgrade the stack to a new release. ```bash theme={null} npx @klio-tech/klio update [--check | --to-latest | --to-version ] [--watch] ``` | Flag | Effect | | ------------------ | --------------------------------------------------------------------------------------------------------------------------------- | | `--check` | Report whether an upgrade is available; change nothing | | `--to-latest` | Upgrade the stack to the newest release | | `--to-version ` | Upgrade (or pin) to a specific version | | `--watch` | Run a long-lived host-side process that applies background auto-updates the bridge has detected — avoids needing docker-in-docker | Tweak runtime settings such as auto-update mode and claim email. ```bash theme={null} npx @klio-tech/klio configure ``` Stop the stack. **Data is preserved** — this is the safe way to pause. ```bash theme={null} npx @klio-tech/klio down ``` Stop the stack, **delete all data**, and restore agent configs from the backups taken during `init`. ```bash theme={null} npx @klio-tech/klio uninstall ``` This deletes your memory store. Use `down` if you only want to stop the stack. Print the package version. ```bash theme={null} npx @klio-tech/klio version # or npx @klio-tech/klio --version ``` ## Global flags | Flag | Effect | | ----------------- | ------------------------- | | `-h`, `--help` | Print usage | | `-v`, `--version` | Print the package version | # Self-hosting Klio Source: https://docs.klio.tech/self-host/install Run the open-source engine on your own hardware. One command brings up the stack and wires your agents to it. The Klio engine is open source and self-hostable. Self-hosting is free, nothing leaves your machine, and the custody guarantees are stronger than Cloud's: memory is encrypted at rest under a key **you** own, and every write is chained with SHA-256 so the history is tamper-evident. What you get is the **core memory engine** — capture, recall, spaces, projects and the curator. The layers built on top of the store are Cloud-only: the knowledge graph that links memories to the entities they are about, hybrid recall that matches exact identifiers as well as meaning, artifacts, compression, and the reconciliation pass that judges when a new fact contradicts an older one and retires it. So the trade is custody against capability. If memory must not leave your network, self-host. If you want everything that reasons over the store, use Cloud — all of it is on the Free plan, so you can compare them without paying. ## Prerequisites * **Docker** running — check with `docker info` * **Node 20+** — needed only to run the launcher via `npx` * **\~8 GB free disk** for the container images * *(macOS, if you choose the Ollama provider)* a working `ollama` install for Metal acceleration. On Linux the `docker-ollama` compose profile is used as a CPU fallback. ## Install ```bash theme={null} npx @klio-tech/klio init ``` That single command pulls the containers (engine, bridge, dashboard, plus Postgres and Redis), boots them, runs migrations, walks you through provider and model selection, detects every supported AI agent on your machine, and patches each one's MCP config. Roughly 30 seconds on a warm Docker, about two minutes on a cold first run. `klio init` accepts `--local` or `--cloud` to skip the prompt, and `--email ` to pre-fill the claim address. Pin a specific build with `--image-tag `. ## Confirm it is up ```bash theme={null} npx @klio-tech/klio status ``` This reports what is running, where, and as whom. Your agents should now list the ten Klio tools without any further configuration — the launcher already wrote their MCP config for you. ## What you get that Cloud does not Memory is encrypted at rest under a key you hold. On Klio Cloud the keys are ours. Every write is chained with SHA-256, so the history can be independently verified. Cloud writes are not hash-chained today. Anywhere the docs mention a user-held encryption key or a hash chain, that refers to the **self-hosted** engine specifically. See [What Klio keeps](/concepts/what-klio-keeps#where-it-physically-lives) for the Cloud equivalent. ## Connecting agents manually The launcher patches agent configs for you, but if you need to wire one by hand it is the same MCP endpoint on your own host: ``` http://localhost:8080/mcp ``` Everything in [Any MCP client](/connect/any-mcp-client) applies unchanged — only the base URL differs. ## Day-two operations | Command | What it does | | ------------------------------- | --------------------------------------------------------------- | | `npx @klio-tech/klio status` | Show what is running, where, and as whom | | `npx @klio-tech/klio update` | Re-prompt provider/model, or upgrade the stack | | `npx @klio-tech/klio configure` | Tweak runtime settings (auto-update mode, claim email) | | `npx @klio-tech/klio down` | Stop the stack — **data is preserved** | | `npx @klio-tech/klio uninstall` | Stop and **delete all data**; restore agent configs from backup | See the [CLI reference](/self-host/cli) for the full flag set. `uninstall` deletes your memory store. `down` is the one you want for stopping the stack temporarily. ## Source and licence The engine lives at [github.com/klio-tech/klio](https://github.com/klio-tech/klio). Klio is open core, and the line is capability rather than hosting: the memory engine and MCP shim are open source and free to run yourself, while the graph, hybrid recall, artifacts, compression and reconciliation are part of Klio Cloud. Cloud is not the same software with a bill attached. # artifact_get Source: https://docs.klio.tech/tools/artifact-get Fetch an artifact surfaced by recall — its text, paginated, or a download link. The read half of [artifacts](/concepts/artifacts). Takes the `artifact_id` from a card's `metadata.artifact_id`, surfaced by a normal [`recall`](/tools/recall) call. ## Parameters From a recall result's `metadata.artifact_id`. `text` returns the contents, paginated. `url` returns a presigned download link instead. Character offset to continue reading from. Used with `mode: "text"`. ## `mode: "text"` (default) Returns the contents one page at a time. Page size is 51,200 characters. ```json theme={null} { "artifact_id": "art_01J...", "mode": "text" } ``` ```json theme={null} { "artifact_id": "art_01J...", "title": "Q3 pricing analysis", "kind": "document", "text": "# Q3 Pricing Analysis\n\n...", "offset": 0, "has_more": true } ``` Continue by passing the next offset: ```json theme={null} { "artifact_id": "art_01J...", "mode": "text", "offset": 51200 } ``` Binary artifacts — PDFs, Office documents, images — return `{"artifact_id": "...", "title": "...", "kind": "...", "error": "not_text"}` rather than an extraction attempt. Klio does no text extraction from binary formats in this version; use `mode: "url"` to download and read them yourself. ## `mode: "url"` Returns a presigned download link. ```json theme={null} { "artifact_id": "art_01J...", "mode": "url" } ``` ```json theme={null} { "artifact_id": "art_01J...", "title": "Onboarding deck", "kind": "file", "url": "https://...", "expires_in": 900 } ``` The link is valid for 900 seconds and forces a download (`Content-Disposition: attachment`) rather than rendering inline — including for content types a browser would otherwise open directly, like PDFs or images. ## Notes A page is capped at 51,200 characters regardless of how large the underlying artifact is. A multi-megabyte document takes several calls with increasing `offset` to read in full — `has_more` tells you whether another page remains. `mode: "text"` works for plain text, JSON, XML, and YAML content. PDFs, Word and Excel files, and images are not extracted — `mode: "text"` on one of these returns `not_text`, and `mode: "url"` is the only way to retrieve it. # artifact_put Source: https://docs.klio.tech/tools/artifact-put Store a document, JSON record, or file, and make it discoverable through recall. Writes an artifact and, alongside it, the card that makes it findable — see [Artifacts](/concepts/artifacts) for how the two connect. Always writes to the org's shared memory; there is no `agent`-scoped, private artifact. Three behaviours, selected by which arguments are present. ## Inline: `content` given One call. For text up to 64KB — the only write path available to clients that speak MCP but cannot make an arbitrary HTTP request, such as ChatGPT connectors and Claude.ai custom connectors. ```json theme={null} { "title": "Q3 pricing analysis", "summary": "Competitor pricing comparison and margin model for the Q3 review", "kind": "document", "content": "# Q3 Pricing Analysis\n\n..." } ``` ```json theme={null} { "stored": true, "artifact_id": "art_01J...", "version": 1, "status": "active" } ``` ## Presigned upload: `content` omitted, `mime_type` and `size_bytes` given For larger or binary content. Returns an upload URL rather than storing anything yet. ```json theme={null} { "title": "Onboarding deck", "summary": "Slide deck used in the July onboarding call", "kind": "file", "mime_type": "application/pdf", "size_bytes": 2400000 } ``` ```json theme={null} { "stored": false, "artifact_id": "art_01J...", "upload_url": "https://...", "method": "PUT", "expires_in": 900 } ``` `upload_url` is signed for exactly the `size_bytes` you declared — an upload of any other size is rejected at the storage layer, so declare the real size. Upload the bytes with an HTTP `PUT`, then confirm. ## Confirm: `artifact_id` given Call again with the `artifact_id` from the presigned response, no other arguments needed. ```json theme={null} { "artifact_id": "art_01J..." } ``` ```json theme={null} { "stored": true, "artifact_id": "art_01J...", "version": 1, "status": "active" } ``` The server measures the uploaded object itself at confirm time — size and checksum both — and enforces the plan's limits against that measured value, not the `size_bytes` you declared when requesting the URL. Confirm is what activates the artifact; nothing is discoverable through recall until it succeeds. ## Parameters Short name for the artifact. Up to 200 characters. One line describing what this is. Other agents find the artifact by this text, via the card — write it as the search phrase you would want to match. Up to 500 characters. `document` for prose, `record` for JSON, `file` for binary content. Inline text, up to 64KB. Omit to use the presigned upload path instead. MIME type of the upload. Required when `content` is omitted. Byte size of the upload. Required when `content` is omitted — the upload URL is signed for exactly this many bytes. Optional space slug. Omit to file to the org's default store. Optional project identifier. See [Scope](/concepts/scope) for how project resolution works. Id of an artifact this one replaces. The superseded version is retired and its card hidden, the same way a superseded memory stops surfacing in recall. Confirms an upload started earlier. Pass only this (and no other argument) to confirm. ## Limits `content` over 64KB is rejected outright, with a message pointing at the presigned path — it does not silently truncate or fall back. Both the inline and presigned paths are checked against the plan's per-file limit and the org's remaining pool before anything is stored. See [storage limits](/concepts/artifacts#storage-limits). A presigned upload is one HTTP `PUT`, so `size_bytes` above 100MB is rejected with `too_large_for_single_upload`. Multipart upload is not available yet, so an artifact larger than that cannot be stored in this release. This only affects plans whose per-file limit is above 100MB — on every other plan the plan limit is reached first and the error is `file_too_large`. Nothing is reserved when a request is refused. A full pool rejects further `artifact_put` calls. It does not affect `artifact_get` or `recall` — existing artifacts stay readable. # Authentication Source: https://docs.klio.tech/tools/authentication Endpoint, headers, and how a request resolves to an org, an agent, and a project. ## Endpoint Hosted Klio speaks MCP over Streamable HTTP: ``` https://mcp.klio.tech/mcp ``` Self-hosted installs expose the same path on whatever host you run the MCP service on. ## API key Authenticate with the `X-Klio-Key` header: ```bash theme={null} curl https://mcp.klio.tech/mcp \ -H "X-Klio-Key: vex_live_..." \ -H "X-Klio-Agent: claude-code" ``` Create keys in the dashboard under **Settings → API keys**. The key resolves the request to an org, and that org boundary is the one guarantee nothing crosses. A key is org-wide. Anyone holding it can read and write everything in that org's memory. Treat it like a database credential: environment variables or a password manager, never a committed file. `X-Vex-Key` and the older `X-AgentGuard-Key` are accepted as legacy aliases for `X-Klio-Key`, and they will keep working — existing configs never break. New integrations should use the `X-Klio-*` names. When both a Klio and a Vex header are present, the Klio one wins. ### OAuth The hosted MCP server also accepts OAuth bearer tokens, verified against the Klio Cloud issuer, for clients that support the MCP authorization flow. In that case the agent identity defaults to the OAuth `client_id` unless `X-Klio-Agent` overrides it. ## Headers | Header | Required | Purpose | | ---------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------- | | `X-Klio-Key` | Yes¹ | API key. Resolves the org. Legacy alias: `X-Vex-Key`. | | `X-Klio-Agent` | No | Stable agent identity. Drives attribution. Legacy alias: `X-Vex-Agent`. | | `X-Klio-Project` | No | Declares the workspace's project — a git remote URL, or the repo root path for a non-git workspace. Legacy alias: `X-Vex-Project`. | ¹ Unless you are authenticating with an OAuth bearer token instead. ### `X-Klio-Agent` A stable, per-agent string — `claude-code`, `cursor`, `codex`, `ci-bot`. It is what makes a ledger of "who wrote what" possible, and it is what `scope: "agent"` resolves against. Clients that omit it are all folded into a single default agent identity. Things still work, but attribution collapses and private scope stops being meaningfully private. ### `X-Vex-Project` Lets a workspace declare its project once instead of passing `project` on every call. It accepts a git remote URL when the workspace is a git repo, and the repository root directory path when it is not — both resolve to the same project a matching `project` argument would. Project resolution **fails open**: a missing header, an unrecognised identifier, or a lookup error all fall back to org-wide rather than failing the request. This keeps a misconfigured client working, but it means the header is a convenience — never a security control. The security boundary is the org. ## Errors | Status | Meaning | Fix | | ------ | ------------------------------------------------ | ----------------------------------------------------------- | | `401` | Missing or invalid `X-Vex-Key` | Check the header name and that the key has not been revoked | | `403` | Key is valid but not permitted for this resource | Confirm the key belongs to the org you are addressing | | `429` | Plan quota or rate limit reached | See usage in the dashboard, or upgrade the plan | A bare `GET https://mcp.klio.tech/mcp` returning `401` is expected — that is the endpoint confirming it is alive and requires auth. # decide Source: https://docs.klio.tech/tools/decide Record a decision and its rationale as soon as one is made. The highest-value verb. A decision recorded with its reasoning is the thing that stops the next agent from quietly undoing your work — and stops a human from having to explain the same trade-off twice. ## Parameters The decision that was made. Why this was chosen over the alternatives. Optional, but decisions without reasoning get re-litigated the first time someone disagrees. `org` (default) writes to the shared team memory. `agent` keeps it private to the identity in the `X-Vex-Agent` header. See [Scope](/concepts/scope). Optional space slug. Omit to write to the org's default store. ## Examples ```json With rationale theme={null} { "content": "Retry 429s with jittered backoff, cap at 5 attempts", "rationale": "Upstream rate-limits per minute; fixed backoff synchronised our retries" } ``` ```json A rejected alternative is still a decision theme={null} { "content": "Not moving to a monorepo this quarter", "rationale": "CI migration cost outweighs the benefit while we are three services" } ``` ## Guidance The decision tells the next agent *what*; the rationale tells it *whether the reasoning still holds*. Circumstances change — an agent that can see why a choice was made can tell when it should be revisited. One that only sees the choice cannot. "We considered X and chose not to" is worth as much as what you picked. Without it, someone re-proposes X every quarter. A newer decision that contradicts an older one retires it — the old one stops surfacing in recall. You do not need to clean up first. See [What Klio keeps](/concepts/what-klio-keeps). # forget Source: https://docs.klio.tech/tools/forget Retract a memory or artifact by id so it stops surfacing in recall. Explicit retraction. Use it when something was written that should not have been, or when a fact has stopped being true and nothing has contradicted it yet. `memory_id` also accepts an artifact id. Klio tries it as an artifact first — a hit retracts the artifact and hides its [card](/concepts/artifacts) in the same call, so recall stops surfacing it immediately. If it is not an artifact id, the ordinary memory retraction runs instead. ## Parameters The id of the memory or artifact to retract. Memory ids come back on [`recall`](/tools/recall) results; artifact ids come back on [`artifact_put`](/tools/artifact-put) responses or in a card's `metadata.artifact_id`. ## Example Recall first to find the id, then retract: ```json theme={null} { "query": "deployment schedule" } ``` ```json theme={null} { "memory_id": "mem_01HZX9..." } ``` ## When to reach for it An agent recorded a customer name, or an internal detail that does not belong in shared memory. Retract it. "Deploys are paused during the migration" was true and is not any more, and there is no newer decision to supersede it. Retract rather than leaving it to mislead. If a memory is technically true but consistently crowds out better answers, retracting it is a legitimate fix. You usually do not need `forget` for ordinary changes of mind. Recording the new decision with [`decide`](/tools/decide) supersedes the one it contradicts automatically — and unlike retraction, that keeps the reasoning trail intact. A retracted memory stops surfacing in recall for everyone on the org. If several agents depended on it, they lose it at the same moment — and unlike superseding, there is no replacement left in its place. # note Source: https://docs.klio.tech/tools/note Free-form durable context that is not a fact, decision, or plan. The catch-all. Use it when something is worth keeping but does not fit the other verbs — context, caveats, warnings about the shape of the codebase. ## Parameters The free-form note to store. `org` (default) writes to the shared team memory. `agent` keeps it private to the identity in the `X-Vex-Agent` header. See [Scope](/concepts/scope). Optional space slug. Omit to write to the org's default store. ## Examples ```json A caveat about the code theme={null} { "content": "The legacy/ directory is scheduled for deletion after Q3 — do not invest in refactoring it" } ``` ```json Context a newcomer would lack theme={null} { "content": "The odd retry logic in the webhook handler exists because a partner's endpoint returns 200 before it has actually processed anything" } ``` ## Guidance If you find yourself reaching for `note` constantly, check whether the content is really a [decision](/tools/decide) or a [fact](/tools/remember). Those types carry more weight in recall, so using the right verb makes the memory easier to find later. # observe Source: https://docs.klio.tech/tools/observe Log something the agent saw or did this session. Session activity worth carrying forward — a surprising behaviour, a discovered constraint, a result that will matter later. This is the verb most likely to fill a store with noise, so it is also the one to use most sparingly. ## Parameters What the agent observed or did this session. `org` (default) writes to the shared team memory. `agent` keeps it private to the identity in the `X-Klio-Agent` header. See [Scope](/concepts/scope). Optional space slug. Omit to write to the org's default store. ## Examples ```json A discovered constraint theme={null} { "content": "The integration suite fails on Node 18 but passes on 20 — the fetch polyfill is the cause" } ``` ```json A surprising behaviour theme={null} { "content": "The staging Postgres rejects connections without the VPN, even from CI" } ``` ## Guidance Do not log routine activity. An agent that calls `observe` after every tool call produces a store where recall returns noise instead of signal. Before writing, ask whether it will still matter next week. If not, skip it. "The suite fails on Node 18" is an observation. Once you have confirmed it and pinned the version, it has become a fact — write it with [`remember`](/tools/remember) so it carries the right weight. # Tools overview Source: https://docs.klio.tech/tools/overview The ten MCP tools Klio exposes, and when each one is the right verb. Klio's surface is deliberately small: one verb per job, so an agent choosing between them does not have to think hard. Every MCP client gets all ten automatically on connection — there is no SDK to wire up. ## The ten verbs | Tool | Purpose | Required | | ------------------------------------- | ----------------------------------------------------- | -------------------------- | | [`recall`](/tools/recall) | Retrieve relevant memories before acting | `query` | | [`remember`](/tools/remember) | Store a durable fact or preference | `content` | | [`decide`](/tools/decide) | Record a decision and its rationale | `content` | | [`plan`](/tools/plan) | Record a forward-looking plan | `content` | | [`observe`](/tools/observe) | Log what the agent saw or did this session | `content` | | [`note`](/tools/note) | Durable context that is not a fact, decision, or plan | `content` | | [`artifact_put`](/tools/artifact-put) | Store a document, JSON record, or file | `title`, `summary`, `kind` | | [`artifact_get`](/tools/artifact-get) | Fetch an artifact surfaced by recall | `artifact_id` | | [`space`](/tools/space) | List, create, inspect, or switch spaces | `action` | | [`forget`](/tools/forget) | Retract a memory or artifact by id | `memory_id` | ## Choosing a write verb The five write tools differ only in the type they record, but that type is what makes recall useful later — a decision and a stray observation should not carry the same weight. Use whenever an option was picked over alternatives. Pass `rationale`; a decision without its reasoning gets re-litigated the first time someone disagrees with it. > "We'll use jittered backoff for 429s, because fixed backoff was > synchronising our retries." Facts about the project, the stack, or the people. Call it proactively when a user reveals one, not only when asked to. > "The team deploys on Tuesdays." · "Abhishek prefers TypeScript strict mode on." Forward-looking intent, so the next agent can continue rather than restart. > "Next: migrate the auth service to the new token format, then backfill." Session activity worth carrying forward. Use sparingly — this is the verb most likely to fill a store with noise. If it will not matter next week, do not write it. > "The integration suite fails on Node 18 but passes on 20." The catch-all for context that is worth keeping but is not a fact, decision, or plan. > "The `legacy/` directory is scheduled for deletion after Q3 — don't invest in it." ## Common parameters Every write tool (`remember`, `decide`, `plan`, `observe`, `note`) accepts: `org` shares the memory with every agent on the org. `agent` keeps it private to the identity in the `X-Klio-Agent` header. See [Scope](/concepts/scope). Optional space slug. Omit to write to the org's default store. [`artifact_put`](/tools/artifact-put) is the one write tool without a `scope` parameter — artifacts are always org-shared, with no private, `agent`-scoped equivalent. It does accept `space` and `project`. See [Artifacts](/concepts/artifacts). ## What good usage looks like Agents use Klio well when reading is reflexive and writing is selective: ```md theme={null} Before answering questions about this project, call `recall` first. When a decision is made, call `decide` with its rationale. When a plan is set, call `plan`. Do not persist secrets, tool call logs, or file contents. ``` The failure mode is not too little memory — it is too much. An agent that calls `observe` after every tool call produces a store where recall returns noise. Write conclusions, not activity. # plan Source: https://docs.klio.tech/tools/plan Record a forward-looking plan when one is set. Intent, so the next agent continues the work instead of restarting it. A plan written at the end of a session is what turns a hard stop into a handover. ## Parameters The forward-looking plan to record. `org` (default) writes to the shared team memory. `agent` keeps it private to the identity in the `X-Vex-Agent` header. See [Scope](/concepts/scope). Optional space slug. Omit to write to the org's default store. ## Examples ```json A sequence of work theme={null} { "content": "Next: migrate the auth service to the new token format, then backfill existing sessions, then remove the compatibility shim" } ``` ```json With a stopping point theme={null} { "content": "Refactoring the invoice generator in three passes. Pass 1 (extraction) is done; pass 2 splits the tax calculation out next.", "space": "billing" } ``` ## Guidance A plan is most useful when it records progress against itself. "Three passes, first is done" tells the next agent where to start. "Refactor in three passes" does not. When the work is done or the approach changes, record the new decision. The superseding step retires the plan it contradicts, so you are not maintaining a to-do list by hand. # recall Source: https://docs.klio.tech/tools/recall Retrieve relevant memories for the current org before acting. The read verb. An agent should call this before answering questions about a project — it is the half of the handover that makes the other half worth doing. ## Parameters What to search the team's memory for. Search matches on meaning and on exact wording at the same time, so you can phrase it the way you would ask a colleague, or paste the identifier you are actually looking for. `org` searches the shared team memory plus your own private memories and the projects you belong to. `private` narrows to your own memories only. `agent` searches what this agent identity wrote and is not a privacy boundary. See [Scope](/concepts/scope). Optional space slug, to confine the search to one project's store. Optional project identifier, to narrow results without switching space. Matches a git remote URL, a repository root path, a project id, or a display name. See [Scope](/concepts/scope#narrowing-a-recall). Maximum memories to return. Between `1` and `50`. ## Examples ```json Basic theme={null} { "query": "how do we handle auth errors in the API?" } ``` ```json Scoped to a space theme={null} { "query": "when do invoices generate?", "space": "billing", "limit": 5 } ``` ```json This agent's private notes theme={null} { "query": "what was I in the middle of?", "scope": "agent" } ``` ```json An exact identifier theme={null} { "query": "KLIO_METRICS_TOKEN" } ``` ## Notes on behaviour If a decision has been contradicted by a newer one, recall returns the current version only. You are not asked to reconcile the two — that is the point of the retire step in the [handover loop](/concepts/handover-loop). A memory written by another agent a second ago is available to the next recall. There is no push to already-running agents, so an agent mid-session sees new state only when it calls `recall` again. Recall runs two searches and combines them. One matches meaning, so a paraphrase finds a memory that used different words. The other matches the text itself, so a rare literal finds the memory that contains it. This matters because the two fail in opposite places. A search for a flag name, an error string, a commit hash or a function name is the case where meaning-based search is weakest: the token is rare, so it carries little signal, and memories that are merely *about* the same topic can crowd out the one memory that actually names it. Pasting the literal is not a worse query than describing it. It is usually the better one. An identifier is matched as its parts, in order. `pool_pre_ping` matches text containing `pool pre ping` adjacent and in that sequence, so a memory that happens to use all three words separately does not match. The default of `10` suits most questions. Raising it toward `50` spends the model's context on progressively less relevant results — usually a sign the query should be narrower, or the memories should live in a [space](/concepts/scope). Passing `project` returns that project's memories first, then fills any remaining slots (up to `limit`) with unfiled memories — never with another project's. If a query has few hits inside the project, expect the rest of the page to be org-wide unfiled results, not padding from elsewhere. Results carry a memory id. Pass it to [`forget`](/tools/forget) to retract something that surfaced and should not have. # remember Source: https://docs.klio.tech/tools/remember Store a durable fact or preference for the team. Facts that stay true past this session — about the project, the stack, or the people working on it. Call it **proactively**. When a user reveals a durable preference or fact in passing, that is the moment to write it; waiting to be asked means it is usually never written at all. ## Parameters The durable fact or preference to store. `org` (default) writes to the shared team memory. `agent` keeps it private to the identity in the `X-Vex-Agent` header. See [Scope](/concepts/scope). Optional space slug. Omit to write to the org's default store. ## Examples ```json A team convention theme={null} { "content": "The team deploys on Tuesdays; no releases after 15:00 UTC on Fridays" } ``` ```json A personal preference theme={null} { "content": "Abhishek prefers TypeScript with strict mode on, and no default exports" } ``` ```json Scoped to a project theme={null} { "content": "Invoices are generated nightly at 02:00 UTC", "space": "billing" } ``` ## Guidance "We deploy on Tuesdays" is a fact. "We deployed on Tuesday" is an event — that belongs in [`observe`](/tools/observe), if anywhere. Memories are read cold, months later, by an agent with none of your context. "Use the new endpoint" is useless. "The billing service moved to /v2/invoices in June; /v1 is read-only" survives. # space Source: https://docs.klio.tech/tools/space List, create, inspect, or switch the named stores within an org. A space is a named subdivision of an org's memory — one per project, service, or workstream. Spaces are how a shared workplace stays useful as it grows, instead of collapsing into one pile where every query returns everything. ## Parameters The operation to perform. Human-readable space name. Used by `create`. Space slug. Used by `info`, `switch`, and optionally `create`. ## Actions Enumerate the spaces on this org. ```json theme={null} { "action": "list" } ``` Create a space. Pass a readable `name`; supply `slug` to control the identifier rather than having one derived. ```json theme={null} { "action": "create", "name": "Billing service", "slug": "billing" } ``` Inspect one space by slug. ```json theme={null} { "action": "info", "slug": "billing" } ``` Make a space the active one for this session, so subsequent calls do not need to pass `space` each time. ```json theme={null} { "action": "switch", "slug": "billing" } ``` ## Using a space Once created, pass the slug on reads and writes: ```json theme={null} { "content": "Invoices generate nightly at 02:00 UTC", "space": "billing" } ``` ```json theme={null} { "query": "when do invoices generate?", "space": "billing" } ``` Or `switch` once and let the session carry it. ## Spaces are not a tenancy boundary Spaces subdivide an org's memory for relevance. They are **not** an isolation boundary — anyone holding the org's API key can read any space in it. If two bodies of work must never see each other — separate clients, separate customers — they need separate orgs and separate keys, not separate spaces. See [Scope and spaces](/concepts/scope) for how spaces interact with `org` and `agent` scope.