Skip to content

Rooms

A room is a memory space shared across Mnemoverse accounts. Instead of every agent keeping its own private pool, members of a room write to and read from one shared pool — using the same /memory/write and /memory/read calls you already make, with xroom:<room_id> in the existing domain field. There is no new endpoint and no new request field to learn.

Agent A (vendor 1, key mk_live_A...) ──┐
                                       ├── domain: "xroom:room_01J8ZQ5XK7E9GVA2M4N6P8R0TC" ──► one shared memory
Agent B (vendor 2, key mk_live_B...) ──┘

A room is its own memory bucket, separate from every member's personal memory. An atom written to a room lives in the room — not in the writer's account. Nothing you keep in your own memory is shared by joining a room; only what you explicitly write with the room's domain goes into it. Reading a room searches the room's atoms, not your own.

Beta — the data path is live, room setup is on request

Works today with any mk_live_ API key: writing, reading, batch-writing, feedback, and consolidation against a room you are a member of — on POST /memory/write, /memory/write_batch, /memory/read, /memory/feedback, and /memory/consolidate.

Not self-service yet: creating a room and managing its members. In beta, rooms are set up for you on request — contact us with the accounts you want in the room and the scope each should have (read or read_write). Self-service room management in the console is planned.

Three Jobs a Room Does

1. Shared Memory for a Dev Team

Your team runs coding agents — each engineer with their own API key, so each agent's memory is private by default. What one agent learned debugging staging on Tuesday, another agent re-derives from scratch on Thursday.

With a room, every member writes findings to the same address:

bash
curl -X POST https://core.mnemoverse.com/api/v1/memory/write \
  -H "X-Api-Key: mk_live_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Staging deploys fail when REDIS_URL is unset — the worker falls back to localhost and times out. Fix: set REDIS_URL in the staging env group.",
    "concepts": ["staging", "redis", "deploy"],
    "domain": "xroom:room_01J8ZQ5XK7E9GVA2M4N6P8R0TC"
  }'

Response:

json
{
  "stored": true,
  "atom_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
  "importance": 0.82,
  "reason": "novel insight — high knowledge delta"
}

The body is otherwise the normal write schema — content (required, 1–10,000 characters) plus optional concepts, metadata, fingerprint, and external_ref (an author object is also accepted, but it is honored only for service integrations and ignored on API-key calls); unknown fields are rejected with 400 (VALIDATION_ERROR).

Two days later a teammate's agent — different API key, different account — queries the same room:

bash
curl -X POST https://core.mnemoverse.com/api/v1/memory/read \
  -H "X-Api-Key: mk_live_TEAMMATE_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "query": "why do staging deploys time out?",
    "domain": "xroom:room_01J8ZQ5XK7E9GVA2M4N6P8R0TC",
    "top_k": 5
  }'

Response:

json
{
  "items": [
    {
      "atom_id": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
      "content": "Staging deploys fail when REDIS_URL is unset — the worker falls back to localhost and times out. Fix: set REDIS_URL in the staging env group.",
      "relevance": 0.91,
      "similarity": 0.86,
      "valence": 0.0,
      "importance": 0.82,
      "source": "semantic",
      "concepts": ["staging", "redis", "deploy"],
      "metadata": {}
    }
  ],
  "episodic_hit": false,
  "query_concepts": ["staging", "deploy", "timeout"],
  "expanded_concepts": ["staging", "deploy", "timeout", "redis"],
  "search_time_ms": 14.2
}

The atom one member wrote comes back on another member's key. Retrieval works exactly as it does in your own account — relevance ranking, Hebbian concept expansion (expanded_concepts pulled in redis from learned associations) — just over the shared pool. Each returned item also carries a domain field (and provenance when the atom is authored), and /memory/read accepts authorship filters (author_principal, author_agent, author_client_env, author_is_external) — useful for telling apart who wrote what in a shared space. See the API Reference for the full schemas.

2. One Person, Two Assistants: Claude and ChatGPT Sharing Context

You use Claude for some work and ChatGPT for other work, and each one only knows what you told it. If both connect to Mnemoverse through the MCP server, a room gives them one shared address for context that should follow you across assistants.

Both data-path tools in the MCP server — memory_write and memory_read — take a domain parameter and forward it to the API unchanged. So the integration is nothing more than passing the room address as the domain. When Claude saves something:

json
{
  "content": "Flight to Lisbon booked for Sept 12, returning Sept 19. Hotel not booked yet.",
  "domain": "xroom:room_01J8ZQ5XK7E9GVA2M4N6P8R0TC"
}

And when ChatGPT later calls memory_read:

json
{
  "query": "when is the Lisbon trip?",
  "domain": "xroom:room_01J8ZQ5XK7E9GVA2M4N6P8R0TC"
}

The domain string flows through the MCP server untouched; membership is checked server-side on every request. In practice you put the room address in each assistant's project instructions or system prompt ("store and look up shared context in domain xroom:room_...") — the assistants will generally pass it on their memory calls, but prompt-following is best-effort, so spot-check early sessions to confirm the domain is actually being used.

One honest caveat: if both assistants authenticate with the same API key, they already share memory — a plain domain is enough. A room earns its keep when the two connections authenticate as different accounts (separate keys, a teammate's setup) and you still want one shared pool.

3. Agent Handoff

A research agent digs into a problem overnight; a coding agent picks up the findings in the morning. Different agents, different keys — the room is the handoff surface.

The research agent drops its findings in one batch. POST /memory/write_batch resolves the domain per item, so a single batch can mix room writes with private ones:

bash
curl -X POST https://core.mnemoverse.com/api/v1/memory/write_batch \
  -H "X-Api-Key: mk_live_RESEARCH_AGENT_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "items": [
      {
        "content": "The N+1 queries come from the serializer re-fetching org settings per row. Batch-load via select_related fixes it.",
        "concepts": ["n-plus-one", "serializer", "performance"],
        "domain": "xroom:room_01J8ZQ5XK7E9GVA2M4N6P8R0TC"
      },
      {
        "content": "Benchmark: endpoint P95 drops from 1.8s to 240ms with the batch-load patch on the staging dataset.",
        "concepts": ["benchmark", "latency", "performance"],
        "domain": "xroom:room_01J8ZQ5XK7E9GVA2M4N6P8R0TC"
      },
      {
        "content": "Note to self: profiling harness lives in scripts/profile_api.py.",
        "domain": "project:perf-sprint"
      }
    ]
  }'

Response:

json
{
  "total_count": 3,
  "stored_count": 3,
  "results": [
    { "index": 0, "stored": true, "atom_id": "1f0e3dad-9908-4a55-8d6f-1c1b2f0a9e11", "importance": 0.79, "error": null },
    { "index": 1, "stored": true, "atom_id": "2a8b6c1e-4d3f-4b7a-9e2c-5f6a7b8c9d0e", "importance": 0.74, "error": null },
    { "index": 2, "stored": true, "atom_id": "3c9d7e2f-5a4b-4c8d-af3e-6a7b8c9d0e1f", "importance": 0.61, "error": null }
  ]
}

If an item addresses a room the caller cannot use, the request fails with that item's real status — a 403 or 404, not a generic 500.

The coding agent reads the room (same POST /memory/read call as in job 1, its own key), applies the fix, and closes the loop with feedback — telling the memory which findings actually helped:

bash
curl -X POST https://core.mnemoverse.com/api/v1/memory/feedback \
  -H "X-Api-Key: mk_live_CODING_AGENT_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "atom_ids": ["1f0e3dad-9908-4a55-8d6f-1c1b2f0a9e11", "2a8b6c1e-4d3f-4b7a-9e2c-5f6a7b8c9d0e"],
    "outcome": 1.0,
    "query_concepts": ["n-plus-one", "performance"],
    "domain": "xroom:room_01J8ZQ5XK7E9GVA2M4N6P8R0TC"
  }'

Response:

json
{
  "updated_count": 2,
  "avg_valence": 0.5,
  "coactivation_edges": 4,
  "feedback_time_ms": 8.3
}

Feedback mutates ranking weights, so it requires read_write membership. That is also how you build a one-directional handoff: give a consumer agent read scope and it can retrieve everything but change nothing. A write attempt on a read-scope key:

bash
curl -X POST https://core.mnemoverse.com/api/v1/memory/write \
  -H "X-Api-Key: mk_live_READONLY_CONSUMER_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Consumers should not be able to add this.",
    "domain": "xroom:room_01J8ZQ5XK7E9GVA2M4N6P8R0TC"
  }'

returns 403 in the standard error envelope:

json
{
  "code": "FORBIDDEN",
  "message": "Read-only membership cannot write to this room",
  "requestId": "...",
  "retryable": false,
  "details": null
}

The room stays a one-way publication channel: the writing side curates what consumers see, and the reading side cannot pollute it.

The Address: xroom:<room_id>

  • A room address is the literal prefix xroom: followed by the room id. Room ids have the shape room_<ulid> — e.g. room_01J8ZQ5XK7E9GVA2M4N6P8R0TC — and you receive yours when the room is set up.
  • The prefix must be lowercase xroom: with no leading whitespace. A near-miss of the canonical form — uppercase XROOM:, a stray leading space — is rejected with 400 rather than silently treated as a private domain. Anything that doesn't look like xroom: at all (say, a mistyped xrom:room_...) is treated as an ordinary private domain in your own account — so double-check the address you paste.
  • The room id may only contain letters, digits, underscores, and hyphens.
  • The address is not a secret capability. Knowing a room id grants no access to its contents: access is enforced by the API's membership check on every request, and non-members get 403. The one thing a bare id does reveal is existence — since 404 means "no such room" and 403 means "exists, but you are not a member" (see Errors), any authenticated caller can confirm whether a room exists.

room: is not xroom:

The legacy room:Y namespace label (no x) is an ordinary domain string inside your own account — nothing written there is shared with anyone. Only the xroom: prefix addresses a shared room.

Which Endpoints Accept Room Domains

EndpointRoomsMembership scope required
POST /memory/writeYesread_write
POST /memory/write_batchYes — resolved per item; a batch may mix room and private domainsread_write
POST /memory/readYesread or read_write
POST /memory/feedbackYesread_write
POST /memory/consolidateYesread_write
GET /memory/statsNo — takes no domain; always reports your own account
POST /memory/query, POST /memory/read-batch, POST /memory/write-batchNo — xroom: domains return 400
DELETE /memory/domain/{domain}No — xroom: domains return 400

Mind the underscore: the room-capable batch write is /memory/write_batch. The hyphenated /memory/write-batch is a different endpoint and rejects room domains.

Membership, Scopes, and Lifecycle

There are exactly two membership scopes:

ScopeCan doCannot do
readPOST /memory/read against the roomAny write-path call (write, write_batch, feedback, consolidate) — 403
read_write (invite default)Everything in the table above

How membership behaves over its lifetime:

  • Grants can expire. A membership may carry an expiry time; without one, it is open-ended but revocable. When a grant expires, requests simply start returning 403 Not an active member of this room.
  • Revocation is immediate and forward-only. A revoked member loses access from that moment on. There is no retroactive un-sharing: whatever the member already read, it keeps, and atoms it wrote remain in the room. Re-inviting a revoked member restores access.
  • Rooms can be archived. Archiving is a soft closure: members' data-path calls return 403 Room is archived (a non-member still gets the membership 403 — see Errors). Permanent deletion of a room's data is handled on request in beta — there is no user-facing wipe.
  • Enforcement is per-request. Membership and scope are checked by the API's membership check on every call — an expired or revoked grant stops working on the very next request.

In beta, all of these operations — inviting, changing scope, setting expiry, revoking, archiving — are performed for you on request (contact us).

Billing

Usage is always billed to the authenticated caller — the account whose API key makes the request — never to the room owner. A member's write into a shared room consumes the member's quota; so does a member's read. Two consequences worth knowing:

  • Your daily quota is enforced against your own account, whichever rooms you touch (Pricing).
  • A room owner cannot be cost-attacked through invitees' traffic: inviting someone gives them access, not your bill.

Only successful requests (HTTP status below 400) count toward usage.

Errors

Room errors use the standard error body: {code, message, requestId, retryable, details}.

HTTPcodeWhenmessage
400VALIDATION_ERRORDomain looks like a room address but isn't canonical (uppercase prefix, leading space)Non-canonical room address; use 'xroom:<room_id>' (no leading space, lowercase prefix)
400VALIDATION_ERRORRoom id contains characters outside letters, digits, _, -Malformed room id: ...
403FORBIDDENRoom id is empty or reservedInvalid room address
401UNAUTHORIZEDRequest to a room address is not authenticatedCaller org not identified
404NOT_FOUNDRoom does not existRoom not found
403FORBIDDENYou are not an active member — never invited, grant expired, or revokedNot an active member of this room
403FORBIDDENRoom is archived (members only; see note below)Room is archived
403FORBIDDENread-scope member calls write, feedback, or consolidateRead-only membership cannot write to this room
400VALIDATION_ERRORRoom domain sent to POST /memory/query, POST /memory/read-batch, or POST /memory/write-batchxroom: rooms are only supported on the v2 memory API (/memory/write, /memory/read).
400VALIDATION_ERRORRoom domain sent to DELETE /memory/domain/{domain}Room domains (xroom:) are not supported on this delete endpoint.
503INTERNAL (retryable)Rooms storage is temporarily unavailable — retryService unavailable: rooms require the DB backend

Two deliberate behaviors to be aware of when handling these:

  • 404 vs 403 is meaningful: 404 means the room does not exist; 403 means it exists but you are not an active member.
  • Membership is checked before archive state, so a non-member of an archived room still gets the membership 403 — outsiders cannot probe whether a room has been archived.

Beta Limitations

Explicitly, what rooms do not do in beta:

  1. No self-service room management. Creating a room, inviting members, changing scopes, revoking, and archiving are all handled on request via contact. A console UI is planned.
  2. No room listing or room stats via API key. GET /memory/stats reports your own account only, and there is no API-key way to enumerate the rooms you belong to. Keep your room addresses in your own configuration.
  3. No user-facing room deletion. DELETE /memory/domain/{domain} rejects room domains, and DELETE /memory/atoms/{atom_id} only reaches atoms in your own account. The MCP memory_delete_domain tool hits the same guard, so it cannot wipe a room either. Permanent deletion of room data is handled on request.
  4. Rooms only work on the endpoints listed above. POST /memory/query, POST /memory/read-batch, and the hyphenated POST /memory/write-batch reject xroom: domains with 400.
  5. No retroactive un-sharing. Revoking a member stops future access immediately, but does not claw back what they already read — and atoms they wrote stay in the room. Treat a room's contents as shared with everyone who has ever been an active member.
  • Getting Started — get a free API key and make your first write/read in two minutes.
  • API Reference — full request and response schemas for the memory endpoints.
  • MCP Server — the @mnemoverse/mcp-memory-server package whose memory_write/memory_read tools carry the domain parameter.
  • Agent Setup — per-client walkthroughs for connecting Claude, ChatGPT, and editors.
  • Multi-Tenant Platform — how accounts, domains, and isolation work underneath rooms.
  • Security — how keys, tokens, and your data are handled.