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

> ## Agent Instructions
> When helping someone deploy Roomote, distinguish self-hosting from contributing to Roomote. Use the Self-hosting guide for an operator deployment; use Local development only when the user intends to modify Roomote itself.
> When an agent is asked to follow /self-hosting or install Roomote autonomously, read and follow /self-hosting/agent-installation as the normative automation contract even though it is intentionally hidden from side navigation.
> Use the one-command Linux installer for both evaluation and production. On macOS or Windows, create or reuse a full Ubuntu VM and run the same installer inside it; do not replace the installer with the repository's development Compose files.
> For a local VM without a stable public domain, create a temporary HTTPS tunnel, pass its hostname to the installer with internal origin TLS, and keep the tunnel running for OAuth callbacks and webhooks. Quick Tunnel hostnames are temporary and do not provide wildcard preview routing.
> Run automated installs with --no-setup-url so the bootstrap token is not captured in the agent transcript. Let the user obtain the setup URL in a trusted terminal, enter credentials, and complete browser authorization.
> Proceed through safe, reversible setup and pause for privileged host or VM changes, public tunnel creation, credentials or browser authorization, durable external-account changes, destructive operations, existing-state conflicts, or when no documented safe default applies.
> A setup is not complete when the services merely start. Verify sign-in, repository sync, one usable environment, and a real Roomote task that can clone and run a command; verify branch or pull-request delivery and previews when configured.

# Memory

> Give Roomote shared memory, so agents start each task knowing what your team already decided, shipped, and discussed.

Roomote memory is shared across the deployment. Without it, every Roomote task starts
from zero: it reads the repository, works out the conventions again, and has no
idea that the same question was answered three weeks ago. With it, agents can
recall what your deployment already knows, with citations back to the source.

Memory is deployment-wide by design. There is no per-user corpus and no
per-task corpus: one deployment, one memory, shared by everyone who can run a
Roomote task.

When a specific remembered fact materially informs an answer or task, Roomote
names that fact in human terms and explains how it was used. It does not narrate
unrelated retrievals or expose internal memory identifiers, storage paths,
metadata, or provenance fields.

## What goes into it

Roomote fills memory from what it can already see:

* **completed Roomote tasks**, including the request that started the task
  and a short memory the agent writes about its own work: what it decided,
  why, and what is still open. The request is bounded and only recorded for
  tasks a person asked for, never for generated work such as reviews. When a pull
  request the task opened later merges or closes unmerged, the task's memory is
  refreshed with that outcome, so recall can tell work that shipped from work
  that was abandoned. Each memory also records who started the task: a linked
  Roomote member is connected to their person page, so recall can answer what
  someone has been working on. Automated work such as pull request reviews
  names the automation instead of linking a person
* **pull requests** from your connected source-control provider
* **public Slack channels** the Roomote bot has been added to
* **public Discord server channels and active public threads** the Roomote bot
  can read
* **GitHub issues** in connected repositories
* **Notion pages** explicitly shared with the deployment's Notion integration
  including readable database property values such as status, dates, people,
  labels, relations, and formula or rollup results
* **meeting notes** from Granola, when that integration is connected
* **employee directory and reporting structure** from Rippling, when that
  integration is connected; HRIS reporting and membership fields remain
  explicitly authoritative rather than being mixed with inferred collaboration
  signals
* **people identities**, projected from Roomote accounts, linked provider
  handles, and the human members in connected Slack workspace directories;
  Slack display names, real names, and job titles help agents connect people
  across sources even when they do not have Roomote accounts. When the Notion
  integration can list workspace users, verified Notion email addresses link
  those identities to matching Roomote members; users without a visible,
  verified email remain separate identities rather than being matched by name

Pull-request memories retain the context agents need to answer more than whether
a change merged. Pages include the PR description and labels, the files and
leading code areas it changed, available line totals, and review outcomes. That
lets searches connect a decision to why it was made, which part of the codebase
it affected, and who reviewed it. Descriptions are bounded and treated as
source evidence rather than agent instructions; large file lists are summarized
with a count and truncation marker so the page stays useful without becoming
unbounded.

Descriptions and labels come from the normal provider sync. File and review
details require additional provider requests, so Roomote enriches a bounded set
of pull requests during each hourly analytics pass, prioritizing merged work.
Older pages gain this context progressively as the sync reaches them.

Turning memory on also backfills history rather than starting from the
moment you enabled it. Completed tasks are enqueued immediately, and each
source drains its own deeper history in bounded background passes that resume
after an interruption.

## Deleting tasks and sessions

Deleting a Roomote task removes the memory pages Roomote created directly for
that task's runs. Deleting a session first stops its active tasks, then deletes
its associated tasks and removes both those direct task memories and any Memory
page saved directly from the session's conversation. If active work cannot be
stopped safely, the session remains intact so deletion can be retried. Roomote
records memory cleanup durably and retries it in the background if memory is
temporarily unavailable. Pending ingestion and future task-history backfills
exclude deleted tasks so those pages are not recreated.

Archiving a session is reversible and does not remove its memories. Deletion is
also deliberately narrower than complete forgetting: it does not remove pull
request, Slack, or other pages collected independently from their source, and
it does not rewrite broader daily or weekly summaries that may refer to the
deleted work.

Private Slack channels and DMs are never read. Adding the Roomote bot to a
public channel is what designates that channel as a source, so the corpus stays
inside what your team has already made visible company-wide. Slack directory
cards contain names, handles, and job titles, but never copy profile email,
status, timezone, or avatar fields into memory.

Discord collection follows the server's permission model: Roomote includes only
channels visible to the server's `@everyone` role where the bot also has **View
Channel** and **Read Message History**. Private channels, private threads, group
DMs, and direct messages are never collected. Active public threads and forum
posts inherit the visibility of their public parent channel. Roomote re-reads a
bounded recent window so edits and deletions are reflected, and removes stored
pages when an authoritative permission scan shows that a channel is no longer
publicly accessible.

Notion only returns pages explicitly shared with its integration. Workspace
guests and restricted users may omit email addresses, and some integration
configurations cannot list users at all. Roomote still keeps stable Notion user
references in page snapshots in those cases, but it does not guess a match from
the display name. The workspace user directory is refreshed once a day; people
removed from the workspace (or hidden when the integration loses its
user-listing capability) have their Notion identity cards marked deleted on
the next refresh. Notion may truncate long multi-value database properties;
Memory marks those partial values and links back to the source page for the
complete list.

## Turning it on

Memory runs as its own service alongside Roomote, reachable only on your
deployment's internal network. On the hosted templates (Railway, Render,
Coolify) that service is already there after a deploy, sitting idle.

New Roomote Cloud deployments enable memory when initial setup completes.
Existing deployments keep their current setting. Administrators can change it
with the **Enable Memory** toggle at the top of **Settings → Memory**; no
provider key is required. Synthesis runs through your deployment's helper model
— the same small model that already writes task titles and summaries.
Deployments that enabled memory before the toggle existed, by setting
`R_BRAIN_OPENROUTER_API_KEY` or `R_BRAIN_OPENAI_API_KEY`, stay enabled without
doing anything; using the toggle stores an explicit choice that wins over the
key from then on.

Semantic recall still needs embeddings. Those come from an OpenRouter or
OpenAI key — a memory-specific `R_BRAIN_*` key to bill memory separately, or
the deployment's general provider key once memory is enabled — or from a
self-run embeddings upstream (below). The memory service holds no provider
key of its own: it asks Roomote for embeddings and synthesis, and Roomote
forwards them. Changing a key later takes effect on memory's next request,
with no redeploy.

OpenRouter and OpenAI both support memory embedding calls.

### Run embeddings locally

Self-hosted Compose deployments can keep embeddings on their own hardware
while continuing to send chat synthesis to the configured memory provider.
Enable both services and point memory at the bundled inference server:

```sh theme={null}
COMPOSE_PROFILES=brain,local-inference
R_BRAIN_EMBEDDINGS_UPSTREAM_URL=http://infinity:7997
R_BRAIN_EMBEDDING_MODEL=BAAI/bge-m3
R_BRAIN_EMBEDDING_DIMENSIONS=1024
```

The bundled CPU service uses multilingual models so recall can cross languages.
Its anonymous usage reporting is disabled by default in the Roomote Compose
bundle. This is separate from Roomote's own optional anonymous analytics.
For a smaller CPU host, `Alibaba-NLP/gte-multilingual-base` with `768`
dimensions is a lighter embedding alternative. Choose the embedding model and
dimensions before memory's first boot; changing that pair later requires
re-embedding the corpus.

The upstream URL can instead target any OpenAI-compatible embedding server.
Set `R_BRAIN_INFERENCE_UPSTREAM_API_KEY` when that server requires a bearer
key. Roomote forwards model names unchanged to self-run upstreams, so
`R_BRAIN_EMBEDDING_MODEL` must exactly match a model that server exposes,
without a provider prefix.

While memory is disabled, it stays inert. Agents are not told it exists,
and nothing is ingested.

Roomote schedules one maintenance pass each night. It retrieves a bounded,
source-balanced evidence set from gbrain, produces a cited digest of material
effective-dated since the previous successful pass, then stores it under
`daily/digests/` in both the searchable index and the persistent Markdown
corpus. The digest
focuses on concrete decisions, shipped work, blockers, commitments, and
cross-source connections rather than generating a reflection for every raw
page. Each page records how many Slack, task, GitHub, and Notion or meeting
pages were considered and cited, so missing source coverage is visible.

Beginning Tuesday, the same pass also updates
`weekly/summaries/<year>-W<week>`. That bounded synthesis connects durable
decisions, unresolved blockers, commitments, and recurring or superseded
information across the week's available daily digests. Roomote reads those
digest pages by their exact slugs and supplies their content as the complete
evidence set, so raw or historical memory pages cannot enter the weekly pass.

The daily cutoff trails active ingestion and overlaps the previous pass so
collector writes around the nightly boundary are reconsidered. gbrain's
durable worker still owns structural maintenance such as link extraction,
fact consolidation, embedding catch-up, orphan checks, and purging. Roomote
does not run gbrain's prediction-proposal and calibration queue unattended;
that upstream feature requires an operator review workflow before proposals
become canonical memory.

<Note>
  Self-hosted Compose deployments start memory from the `brain` profile, so
  add `brain` to `COMPOSE_PROFILES` in your environment file to bring the
  container up, then enable memory in settings. Production installs pull
  `ghcr.io/roocodeinc/roomote-gbrain` with the same `v*` release tag as Roomote;
  a complete custom image reference can be pinned with `GBRAIN_IMAGE`.
  Everything after that is the same.
</Note>

## Seeing what it knows

**Settings → Memory** is the deployment-wide view of the memory, for admins.

**Memory issues** appears first only when completed tasks are missing memories or
memory writes exhausted their retries. Its repair actions queue missing memories
and retry failed writes without bringing back the removed task-memory stats.

**Memory Stats** breaks the corpus down by what each page came from, such as task
memories, pull requests, Slack, meetings, and people, followed by a chart of the
pages written over the last 30 days and the memories written most recently.
**Browser memories** embeds the corpus page by page, searchable and filterable by
source. Selecting a new memory opens it in the browser and updates the page URL
without adding browser history.

**Status** reports whether recall is semantic or keyword-only and which provider
is serving its embeddings and synthesis. Memory that is running but has no
provider key is called out as needing attention rather than shown as healthy:
without one it can only match keywords, so recall would look real while missing
everything semantic.

**Sources** shows connected sources with their current collection state, when
they were last read, and how far their one-time history sweep has got. Sources
without a connected upstream integration are omitted.

## How agents use it

Agents get the built-in memory as an MCP server with read-only tools. They can
search it, recall relevant pages, browse what exists, and ask for a synthesized
answer with sources. They cannot write to the built-in memory directly.

For a substantive topic, agents query memory before consulting overlapping
Slack, GitHub, task-history, meeting, or pull-request sources. They check those
live sources when memory coverage is insufficient, freshness could change the
answer, or you explicitly ask for live verification.

Writes go through Roomote instead. When an agent finishes substantial work it
records a short memory of what it did, and the platform places that text under
a slug it controls, after scrubbing credential-shaped strings. An agent can
therefore contribute what only it knows without being able to touch any other
page.

Sessions use the same pipeline. Ask Roomote to remember something — or
state a durable preference, decision, or correction — and it saves the fact to
the session's own memory entry, which the platform redacts and files just
like a task memory. Saved facts become searchable after the next ingestion
pass, so they surface in later sessions rather than instantly.

With a [judgment model](/models#judgment-model) on, Roomote also catches what
the agent did not save itself, after every settled turn. In a session it
checks for a stated preference, decision, or correction, an explicit request
to remember, or a finding that took real investigation. In a task it checks
the turn's report for a decision, finding, dead end, or open item a later task
could reuse, and the person's message for a correction or convention that
should guide future work. Credential-shaped strings, email addresses, phone
numbers, and card and ID numbers are scrubbed from the turn before either
model sees it. Only a confident yes leads to a save; the
helper model then writes the memory, which goes through the same redaction
and filing. A task memory written this way says so, grows turn by turn, and is
replaced if the agent records its own. Turns that look sensitive, try to plant
approvals or bypass rules, or repeat what was already saved are skipped,
trivial task work keeps the plain completion line unless it came with a
correction, and [private sessions](/private-sessions) and private tasks are
never checked.

Additional memory integrations, such as Supermemory, can also provide shared
context to tasks and sessions. Roomote chooses one connected memory
store for the initial recall so multiple stores do not repeat the same preflight.
Agents can still consult another store when it has distinct context or you ask
for it by name. Each integration uses its own available memory-writing tools;
Roomote does not duplicate the same learning across stores.

Memories carry the environment they came from, so a page written while working
in staging is distinguishable from one written against production.

## Choosing models

Two settings pick the memory models:

| Variable                  | What it does      | Written as             | Changeable            |
| ------------------------- | ----------------- | ---------------------- | --------------------- |
| `R_BRAIN_MODEL`           | Sourced synthesis | your provider's naming | any time              |
| `R_BRAIN_EMBEDDING_MODEL` | Semantic recall   | a plain model id       | before the first boot |

Leave them unset and memory uses OpenAI's `gpt-5.6-luna` and
`text-embedding-3-small` through whichever provider you configured.

Memory search does not use a cross-encoder reranker: retrieval is hybrid
(vector + keyword fusion), which keeps search latency flat and provider
requirements minimal. When the optional [judgment model](/models#judgment-model)
is on, Roomote reorders `query` results it returns to agents: passages the
judgment model confidently finds relevant move up and ones it confidently finds
irrelevant move down. Nothing is removed, and the passage text is sent to the
judgment model provider.

The synthesis model is applied by Roomote when it forwards the call and passed
to the provider as written, so use that provider's naming
(`openai/gpt-5.6-mini` on OpenRouter, `gpt-5.6-mini` on OpenAI). Changing
it takes effect on the next request with nothing to restart.

<Warning>
  The embedding model works differently, and the difference matters. Its
  output width sizes memory's vector storage when memory is first
  created, and that cannot be resized in place afterwards. So it is given to
  memory at creation rather than applied per request, written as a plain
  model id (`text-embedding-3-large`) that Roomote translates for whichever
  provider is serving. Set it together with `R_BRAIN_EMBEDDING_DIMENSIONS`
  (1536 for `text-embedding-3-small`, 3072 for `text-embedding-3-large`)
  before memory's first boot, or leave both alone.

  Changing it later is not silently applied: memory keeps its original
  model and width, and reports the mismatch in its logs on every start.
  Moving existing memory to a different embedding model means re-embedding
  the whole corpus with `gbrain migrate embeddings`.
</Warning>

## If you turned memory on later

Memory that first boots without a provider key is created with semantic
recall switched off, because the embedding model sizes its vector storage at
creation time. Adding a key later is still fine: memory notices on its next
start, enables semantic recall, and embeds whatever it already holds. It logs
`semantic recall enabled` when it does.

That repair runs once and is safe, since memory in this state has no
embeddings to lose and its pages are preserved. If it cannot complete, the
service logs the commands to run by hand and keeps serving in the meantime,
matching on keywords alone.

## Operating it

* **Back up both memory stores together.** The Railway template schedules
  backups for the memory volume. On supported self-hosted installs, `roomote
  backup` includes both the `gbrain_data` volume and the isolated `gbrain`
  database when memory is enabled. The volume holds the Markdown system of
  record; Postgres holds the searchable index, extracted facts, and durable
  maintenance jobs. Restoring only one can leave the storage layout and index
  inconsistent, so keep them at the same backup consistency point.
* **Losing memory is recoverable only from connected sources.** If both stores
  are recreated, Roomote can reset ingestion checkpoints and backfill task
  history and connected integrations, but user-saved facts and generated
  synthesis may not be reproducible. The deployment starts cold until the
  backfill finishes.
* **The filesystem cutover rebuilds older memory once.** The first start of a
  filesystem-backed image replaces a Postgres-only memory service instead of
  trying to merge the old index into an empty checkout. Roomote then repopulates
  it from its connected sources.
* **Memory has no public service route.** It is never exposed to the internet,
  and task sandboxes reach it only through Roomote's API with their run token,
  which grants read access only.
* **To run with no memory at all**, leave memory disabled in settings.
  Deployments that want to reclaim the resources entirely can delete the
  Memory service from their compose file or template.
