Skip to content

Graph Namespacing

Updated View as Markdown

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:

  1. Each graph is searched independently with the same query
  2. Rankings are merged — when a user fact and a namespace fact are equally relevant, the user fact wins
  3. Every result carries its origin: scope: "user", or scope: "graph" with the graph_id it 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_write tool 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 p

Identity 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/json

Request 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_TOKEN

Merge 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_TOKEN

The 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_id values — 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_kb ages better than kb2. 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.

Navigation

Type to search…

↑↓ navigate↵ selectEsc close