Truememory supports graph namespacing through graph_ids — named, isolated knowledge graphs that live alongside user memory in the same Truememory instance. Namespaces hold knowledge that belongs to no user — a product catalog, company policies, a coaching methodology, a support playbook — and can be blended into any user’s memory retrieval.
Graph namespacing is particularly useful for:
- Multi-tenant applications: Isolate curated knowledge between different customers or organizations
- Domain-specific knowledge: Create specialized graphs for different domains or use cases
- Team collaboration: Allow different teams or apps to maintain their own knowledge spaces
- Testing environments: Keep experimental knowledge separate from what production agents see
How Namespacing Works
In Truememory, every node and edge in the knowledge graph is associated with a group id. Each user’s memory already lives in its own automatically managed namespace, keyed by the user’s identity. A graph_id names an additional namespace: nodes and edges written under the same graph_id form a cohesive, isolated graph that can be queried, inspected, and curated independently of every user’s memory and of other namespaces.
Namespaces meet user memory at retrieval time. When a request includes graph_ids, Truememory searches the user’s own graph and each named namespace concurrently, then fuses the rankings into a single result list:
- Each graph is searched independently with the same query
- Rankings are merged — when a user fact and a namespace fact are equally relevant, the user fact wins
- Every result carries its origin:
scope: "user", orscope: "graph"with thegraph_idit came from
A namespace that is empty, nonexistent, or temporarily unreachable contributes no results — the user’s own results always come back. A missing namespace is not an error.
Key Benefits
- Data isolation: A request only touches the namespaces it names — no leakage between namespaces or into user memory
- Simplified management: Related knowledge lives together, inspectable and curatable as one unit
- Curated by design: Namespaces are never written automatically — chat auto-ingest and the agent’s
memory_writetool only touch the user’s own graph - Flexible architecture: Per-tenant graphs, per-domain graphs, and user memory coexist in one Truememory instance
Namespaces store facts and entities in a knowledge graph, retrieved and ranked like memory. To give an agent passages quoted from an uploaded document instead, use Brains (knowledge packs) — the two work well together.
Naming Namespaces
A graph_id is a freeform slug. No registration step is required — a namespace exists once data lands in it. Ids must match:
- Lowercase letters, digits, underscores, or hyphens
- Start with a letter, 3–64 characters long
- Must not begin with a bare UUID — that shape is reserved for user memory namespaces. Ids that need UUID-based uniqueness (an org id, a tenant id) are fully supported — put a short prefix in front:
org_9f8e4b2a-…
Invalid ids are rejected with 400 VALIDATION_ERROR before any operation runs.
| graph_id | Verdict |
|---|---|
acme__product_kb |
✅ Recommended shape |
kb__sales_playbook |
✅ Recommended shape |
org_9f8e4b2a-e89b-12d3-a456-426614174000 |
✅ UUID-based uniqueness, prefixed |
Sales-KB |
❌ Uppercase not allowed |
kb |
❌ Too short (min 3 characters) |
123_team_docs |
❌ Must start with a letter |
9f8e4b2a-e89b-12d3-a456-426614174000 |
❌ Bare UUID — reserved for user memory |
Adding Data to a Namespace
Populate a namespace through Add Data to Memory with a graph_id target instead of agent_id. Writing to a namespace requires a service token — end-user tokens receive 403 AUTH_SERVICE_REQUIRED:
POST https://your-tie-host/memories/graph
Authorization: Bearer $SERVICE_TOKEN
Content-Type: application/json{
"graph_id": "acme__coaching_kb",
"data": "The beginner running program has three phases: base, build, peak.",
"type": "text",
"source_description": "Coaching methodology import"
}Provide exactly one of agent_id (user memory) or graph_id (namespace). Ingestion is asynchronous — the 202 response includes a job_id to poll via GET /memories/graph/status/{job_id}, or pass wait: true for synchronous writes. Writers to one namespace serialize cluster-wide, so concurrent imports never race entity extraction.
Records About People
A namespace often holds one profile record per member of a community. Follow the record-ingestion conventions: stamp each record with the member’s id, put the id in the document, and frame the document as third-party. Each member then becomes one Person node carrying the member’s id as external_id:
MATCH (p:Person {external_id: $memberId}) RETURN pIdentity comes from the id, not the name — two members who share a name keep two separate nodes, and a re-sent record finds its member even after a name change. Records that reference members by id (an event’s host, a group’s owner) get real edges to those members automatically.
Using a Namespace in Chat
For agents running through Truememory’s chat, pass graph_ids directly on the chat completions request — Truememory blends namespace facts into the memory context it injects, with no prompt composition on your side:
POST /v1/chat/completions
{
"model": "chatbot",
"messages": [{"role": "user", "content": "what running program fits a beginner"}],
"graph_ids": ["acme__coaching_kb"]
}The conversation itself still only ingests into the user’s graph — graph_ids affects what the agent reads, never what gets written.
If you run your own LLM, specify graph_ids on Retrieve Memory Context instead — the endpoint that returns exactly what Truememory injects during a chat turn. Namespace facts blend into the per-message retrieval; the cached session context block remains user-only. Everything else about the endpoint is unchanged, and omitting the field gives the existing user-only behavior.
POST https://your-tie-host/memories/retrieve
Authorization: Bearer $TOKEN
Content-Type: application/jsonRequest body:
{
"query": "what running program fits a beginner",
"agent_id": "chatbot",
"graph_ids": ["acme__coaching_kb"]
}| Field | Type | Required | Description |
|---|---|---|---|
graph_ids |
string[] | No | Up to 4 namespaces to blend into the retrieval. Duplicates are deduped. |
Response (trimmed to the retrieval half) — one ranked list; scope and graph_id identify each fact’s origin:
{
"retrieval": {
"results": [
{
"id": "edge-uuid-1",
"name": "TRAINS_FOR",
"content": "User is training for a marathon in October",
"source_name": "User",
"target_name": "Marathon",
"scope": "user",
"graph_id": null
},
{
"id": "edge-uuid-2",
"name": "HAS_PHASE",
"content": "The beginner running program has three phases: base, build, peak",
"source_name": "Beginner running program",
"target_name": "Training phases",
"scope": "graph",
"graph_id": "acme__coaching_kb"
}
],
"prompt": "## Relevant memories for this message\n..."
}
}The rest of the payload — the context block, timings, cache diagnostics — is unchanged; see Retrieve Memory Context.
The same field works on Search Memory when you want raw ranked fact edges without the context block or rendered prompts — results carry the same scope and graph_id tags.
Inspecting a Namespace
Inspection endpoints target exactly one graph per call — the user’s own, or a namespace via graph_id. No blending: pass graph_id to see the namespace, omit it for the user’s graph. graph_id is mutually exclusive with agent_id.
GET https://your-tie-host/memories/graph?graph_id=acme__product_kb
GET https://your-tie-host/memories/timeline?graph_id=acme__product_kb
Authorization: Bearer $TOKEN- Memory Graph renders the namespace’s entities and facts for a graph UI.
- Memory Timeline returns an entity feed, recently active first — useful for reviewing what a namespace contains.
Inspecting a namespace requires a service token — end-user tokens receive 403 AUTH_SERVICE_REQUIRED from both endpoints. A namespace holds cross-user data that is scoped to no caller in particular, so its inspection views are gated exactly like namespace writes. Service tokens with no user attached work fine: curation tooling and org-level dashboards do not need to impersonate a user.
Reading the user’s own graph or timeline (omitting graph_id) is unaffected and still works with an end-user token.
These views are single-scope — one call shows one graph, never a mix. A memories dashboard maps this onto a filter: a “my memories” tab calls the endpoint without graph_id, an “organization” tab calls it with one (through your backend). Same response shape, same cursor pagination, same rendering components. There is no server-side blended feed (the two graphs have independent cursors); if you need an interleaved “all memories” scroll, merge the two cursor streams client-side by timestamp and badge each item by origin.
Managing Namespace Memories
Deleting or merging namespace facts affects every reader, so both operations require a service token. End-user tokens receive 403 AUTH_SERVICE_REQUIRED.
Delete (invalidate) one fact edge — the agent_id path segment is ignored when graph_id is present:
DELETE https://your-tie-host/memories/{agent_id}/{memory_id}?graph_id=acme__product_kb
Authorization: Bearer $SERVICE_TOKENMerge duplicate entities within a namespace — same semantics as a user-scoped merge:
POST /memories/{agent_id}/merge
{
"primary_id": "node-uuid-keep",
"duplicate_id": "node-uuid-fold-in",
"graph_id": "acme__product_kb"
}Empty an entire namespace — a hard delete of every node, edge, and episode in it, from both stores:
POST https://your-tie-host/memories/{agent_id}/clear?graph_id=acme__product_kb
Authorization: Bearer $SERVICE_TOKENThe response’s scope field names what was cleared ("graph" plus the graph_id, vs "user" for a pair clear), so a caller can verify the blast radius. See Clear all memories for details.
Export and import remain user-scoped — the rest of the namespace lifecycle (list, export) ships separately.
Best Practices for Graph Namespacing
- Consistent naming: Use a consistent naming convention for your
graph_idvalues — we recommend{org_or_app}__{topic}, with underscores over hyphens. A namespace is its id (there is no rename), so choose descriptive, permanent names:acme__support_kbages better thankb2. When ids must be globally unique rather than readable, derive them from your own identifiers:org_{org_uuid}. - Documentation: Maintain documentation of your namespace structure and purpose — which namespaces exist, what each contains, and who writes to it. Truememory does not maintain a registry.
- Granularity: Choose an appropriate level of granularity for your namespaces
- Too many namespaces can lead to fragmented data and extra search fan-out per request
- Too few namespaces may not provide sufficient isolation, mixing unrelated domains into every result list
- One namespace per coherent knowledge domain is a good default
- Cross-namespace queries: Retrieval blends the user’s graph with up to 4 namespaces in one call. When you need more than that — or a combined view of inspection feeds — perform multiple queries across namespaces and combine the results in your application logic.
A Multi-Tenant Example
Map each tenant to its own namespace prefix, and pass the tenant’s namespaces on every retrieval for that tenant’s users:
{
"query": "what is the refund policy",
"agent_id": "support-agent",
"graph_ids": ["acme__support_kb", "acme__product_kb"]
}Users of tenant acme get Acme’s policies blended with their personal memory; tenant globex passes globex__support_kb and never sees Acme’s data. Isolation is structural — a request only touches the namespaces it names.