> ## Documentation Index
> Fetch the complete documentation index at: https://renor.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Several agents, one memory

> How several agents sharing one Renor workspace are identified, what happens when two of them write the same fact, what a read shows about where a memory came from, and what is not built yet.

A Renor workspace belongs to one owner account. Every agent that account signs in reads and writes the same memory: tell Claude Code something once and Codex can recall it. This page says what the engine does when more than one of those agents is active, and what it does not do yet.

## How an agent is identified

Two different things identify a caller, and they are not the same thing.

* **The connection token identifies the workspace.** An agent connects to `https://mcp.renor.cloud/mcp` with a connect token, minted when you sign in (OAuth) or as a key from the dashboard. The gateway resolves that token to one workspace on every request and routes there; a missing or revoked token is refused. Tokens are stored only as a hash, can be revoked, and a revocation takes effect on the next request. The token says *which workspace*, not *which agent*.
* **The `source` field names the agent.** Every write records a `source`. For a named connection, the gateway supplies its authenticated connection name and refuses an attempt to name another author. Only an unnamed fallback label, taken from the write or the product named in its User-Agent (`claude-code/2.1.288` becomes `claude-code`), is self-reported. It is shown beside the memory and stored with it. A name that is a path or a URL is reduced to the name it ends in, and the stored name is capped, so a long path is never kept whole.

The dashboard's connection list is the same idea from the control-plane side: it records one row per client, keyed by the product in the User-Agent, keeps each client's latest label, and bounds how many it keeps. It tells you which agents have connected, not which one wrote a given memory.

<Note>
  A named connection's author is authenticated; only an unnamed fallback label is self-reported. The author is not an access control: there are no per-agent permissions, and every agent in the workspace can read and write everything the workspace holds.
</Note>

## When two agents write the same fact

A fact is a subject, a predicate and a value in a scope (`Fjord`, `database`, `SQLite`). For any one subject, predicate and scope there is **exactly one current value**. A new value does not sit beside the old one; it replaces it, and the old value stays in history.

What happens when two agents save the same fact:

* **They do not race.** Each workspace runs one engine process, and every lifecycle write (the decision, the ledger append and the index update) runs one at a time inside it. Two calls are handled in the order they arrive; one lands, then the other sees the result.
* **If the second writes the same value, the same way, nothing changes.** The receipt says `nochange` and no new event is written.
* **If the second writes a different value, it becomes current and the first is kept as history.** The engine closes the old value (stamps it with when it stopped being current) and opens the new one, in a single transaction. The ledger — the durable record the index is rebuilt from — holds both events, and the event that appears later in the ledger is the current one.
* **If the second event is older than the value it would replace, it is refused and nothing is written.** The check runs before the ledger is touched, so a clock that jumped backward cannot leave a self-rejected event behind. The write returns an error; the memory is unchanged.

The same rule applies to a value saved under the same subject and predicate with different words: it is recorded as a new event that replaces the old one, and the old one stays in history.

```text theme={null}
agent A  remember  Fjord · database · PostgreSQL   → action "store"
agent B  remember  Fjord · database · SQLite       → action "supersede"
                                                     (closes PostgreSQL, opens SQLite)

retrieve_memory { subject: "Fjord", predicate: "database", include_history: true }
  → SQLite      current: true
    PostgreSQL  current: false, validTo: <when it was replaced>
```

`retrieve_memory` with `as_of` and an ISO date returns what was current at that time, so the value an earlier agent wrote is still answerable.

## When agents name the same thing differently

Correction is narrow on purpose. A new value closes the current one only under the **same subject, predicate and scope, spelled the same way** (case and Unicode form are folded). When several agents write, the same thing often arrives under another name (`Atlas project` from one agent, `Atlas` from another) or in another scope (a correction saved without the project's scope goes to global). Those do **not** replace each other; both values stay current.

Renor names the possible collision instead of guessing:

* a fact save's receipt can carry `possibleDuplicates`: the other current facts related to the one just written;
* a read can carry `conflicts`: groups of related current facts whose values disagree.

Two facts are related when they share a predicate and their subjects are one identity, or one name is the other with one more word before or after it. Values are compared after case and accent folding, so `Sao Paulo` and `São Paulo` are not a conflict. Nothing is merged or superseded by this; it is a signal for you or the agent to correct.

## What a read shows about where a memory came from

Where a memory came from is shown in some places and not in others, and the difference matters when several agents write.

* **Notes and daily-log entries carry their `source`.** `memory_map` lists it with each memory, and `read_memory` returns it in the memory's metadata. It is the name the writer recorded.
* **`get_context` names another agent that saved a fact; `retrieve_memory` does not.** `get_context` adds the `source` when it differs from the reading agent, and omits it when the reader saved the fact or nobody is named. `retrieve_memory` returns the fact's event id instead. To inspect the complete authorship record, read the ledger: `export_memory` returns every fact event with its `source`, its sentence, its scope and its event id.
* **A flag-gated lane can add provenance to `get_context`.** A deployment can turn on a read-honesty lane that adds a `provenance` field to each item — the note path or the ledger, and the last date the system recorded it as current. It is **off by default**, so a default deployment does not show it.

`memory_map` also lists recent write events, but those carry no `source`, and `retrieve_memory` with `include_history` returns the old value with its dates and its event id, not the agent. A fact's complete authorship history remains in the ledger; `export_memory` returns it.

## What is not built yet

* **Fact-read authorship differs by tool.** `get_context` names another agent that saved a fact; `retrieve_memory` does not.
* **Only an unnamed fallback author is self-reported.** A named connection's author is authenticated, but there are no per-agent permissions.
* **Writes are serialized inside one engine process, not across processes.** Running two writers against the same workspace at the same time is not protected; the durable cross-process guard (an OS-level writer lock with fsync barriers) is not built. The ledger is durable and the index is rebuilt from it, so a crash is recoverable, but two live processes are not coordinated.
* **A `scope` is a folder, not a permission.** It separates projects inside one workspace; a read that names no scope sees every scope, and any agent can read or write any scope.
* **A workspace is not separated per person.** It has one owner account, but the control plane also supports an invited member joining it, and every member reaches the same memory. Nothing partitions a workspace by person or by agent.
* **The connection list is bounded and self-reported.** It keeps a limited number of clients per workspace and each client's latest label; a client names itself, so the list is a convenience, not an audit log.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.