How Data Isolation Works in TencentDB Agent Memory: Architecture and Implementation

TencentDB Agent Memory enforces strict multi‑tenant data isolation through a mandatory four‑field tuple (team_id, agent_id, user_id, session_id) validated at the API layer and embedded into storage keys.

The TencentDB-Agent-Memory repository implements a layered isolation strategy that spans from incoming HTTP requests down to the underlying Redis and SQLite storage backends. This design ensures that teams, agents, and users can never access data outside their authorized scope, even when multiple tenants share the same infrastructure.

The Isolation Tuple: Core Identity Fields

All v3 API endpoints—representing the "strict isolation version" of the data plane—require four identity fields that together form a composite isolation key. The Zod schema isolationFieldsSchema in MemoryCore/src/gateway/v2-schemas.ts defines these mandatory fields:

export const isolationFieldsSchema = z.object({
  team_id: z.string().nonempty(),
  agent_id: z.string().nonempty(),
  user_id: z.string().nonempty(),
  session_id: z.string().nonempty(),
});

Source: MemoryCore/src/gateway/v2-schemas.ts#L300-L305

An optional fifth field, task_id, can be appended for finer-grained task-level scoping but is not enforced by the base isolation schema.

API Layer Enforcement

v3 Router Validation

The gateway router explicitly designates /v3 as the strict isolation path that shares handlers with /v2 but applies separate validation:

// /v3 is L0–L3 data-plane strict isolation version
//   - shares handler with /v2 but uses separate isolation validation
// /v3 paths require team_id, agent_id, user_id, session_id

Source: MemoryCore/src/gateway/v2-router.ts#L102-L105

When a request hits any /v3 endpoint, the router parses incoming headers or body fields against isolationFieldsSchema. Missing values trigger an immediate 422 error before any data layer access occurs.

Header and Body Extraction

Isolation fields can be supplied via x-tdai-* headers or JSON payload fields. The parsing utilities in the gateway normalize these sources into a consistent internal structure used by downstream handlers.

Source: MemoryCore/src/gateway/v2-router.ts#L80-L150

SDK-Level Contract Enforcement

TypeScript SDK

The MemoryClient constructor for v3 demands a V3IsolationContext object. Omitting this parameter throws a ParamError at instantiation:

export interface V3IsolationContext {
  /** Team ID. Required by v3 strict isolation. */
  team_id: string;
  /** Agent ID. Required by v3 strict isolation. */
  agent_id: string;
  /** User ID. Required by v3 strict isolation. */
  user_id: string;
  /** Session ID. Required by v3 strict isolation. */
  session_id: string;
  /** Optional task ID carried in isolation fields. */
  task_id?: string;
}
constructor(transport: Transport, isolation: V3IsolationContext) {
  if (!isolation) throw new ParamError("v3 MemoryClient transport constructor requires isolation context");
  this.isolation = {
    team_id: isolation.team_id,
    agent_id: isolation.agent_id,
    user_id: isolation.user_id,
    session_id: isolation.session_id,
    task_id: isolation.task_id,
  };
}

Sources:

Python SDK

The Python v3 client mirrors this behavior, rejecting any construction attempt without the isolation dictionary:

client = MemoryClient(
    transport,
    isolation={
        "team_id": "team-123",
        "agent_id": "agent-beta",
        "user_id": "user-99",
        "session_id": "sess-20230902-002",
    },
)

Source: sdk/memory-core/python/tencentdb_agent_memory/v3/client.py#L155-L162

Storage Layer Isolation

Redis Key Prefixing

The memory proxy service embeds isolation fields directly into Redis key names, ensuring physical separation at the caching layer:


${serviceId}:session:${sessionKey}:${teamId}:${agentId}

This pattern guarantees that even with shared Redis infrastructure, keys from different teams or agents remain namespace-separated and cannot collide or be accessed through key enumeration.

Source: MemoryProxy/src/redis-session-store.ts#L1-L3

SQLite Scoped Stores

For persistent knowledge storage, SQLite-backed stores are initialized per serviceId with isolation enforced through table-level separation or database file organization, preventing cross-tenant data leakage at the filesystem and query levels.

Source: MemoryKnowledge/src/store/sqlite-store.ts#L6-L7

Environment Configuration

The gateway's environment configuration documents that v3 endpoints reject requests lacking isolation fields, serving as a runtime contract enforcement mechanism:

Source: MemoryCore/src/utils/env-config.ts#L153-L155

Practical Usage Examples

TypeScript Client with Strict Isolation

import { MemoryClient } from '@tencentdb-agent-memory/memory-sdk-ts/v3';

const transport = new HttpTransport({ baseUrl: 'https://memory.api.tencentcloud.com' });

const isolation = {
  team_id: 'team-123',
  agent_id: 'agent-alpha',
  user_id: 'user-42',
  session_id: 'sess-20230902-001',
};

// Constructor throws ParamError if any isolation field is missing
const client = new MemoryClient(transport, isolation);

// All operations automatically scoped to the isolation tuple
await client.conversationAdd({
  messages: [{ role: 'user', content: 'Hello' }],
});

Direct REST API Call

POST /v3/conversation/add HTTP/1.1
Host: memory.api.tencentcloud.com
Content-Type: application/json
x-tdai-team-id: team-456
x-tdai-agent-id: agent-gamma
x-tdai-user-id: user-77
x-tdai-session-id: sess-20230902-003

{
  "messages": [{"role": "user", "content": "How does isolation work?"}]
}

Missing any header results in a 422 response from the gateway validator.

Isolation Level Matrix

Layer Mechanism Enforcement Point
API Gateway Schema validation (isolationFieldsSchema) v2-router.ts for all /v3/* paths
SDK Constructor Mandatory V3IsolationContext parameter client.ts in TypeScript and Python SDKs
HTTP Transport Header injection from context SDK request interceptors
Redis Cache Key prefix with serviceId:teamId:agentId redis-session-store.ts
SQLite Persistence Per-service database scoping sqlite-store.ts in Knowledge service

Summary

  • TencentDB Agent Memory data isolation relies on a mandatory four-field tuple: team_id, agent_id, user_id, session_id
  • API layer validates this tuple via isolationFieldsSchema in v2-schemas.ts at the /v3 router level
  • SDK constructors require V3IsolationContext and throw ParamError if fields are absent, preventing accidental unscoped calls
  • Storage backends embed isolation fields into Redis key prefixes and SQLite database scoping for physical separation
  • Multi-layer defense: Gateway validation, SDK enforcement, and storage naming conventions work together to guarantee tenant isolation

Frequently Asked Questions

What happens if I omit an isolation field in a v3 API request?

The gateway returns a 422 Unprocessable Entity error. The isolationFieldsSchema in v2-schemas.ts requires all four fields (team_id, agent_id, user_id, session_id) to be non-empty strings, and the v3 router applies this validation before any handler execution.

Can I use the same MemoryClient for multiple users or sessions?

No—the V3IsolationContext is immutable after client construction. Each distinct (team, agent, user, session) combination requires a separate MemoryClient instance. The SDK design intentionally prevents sharing clients across isolation boundaries to eliminate accidental data leakage.

How does the storage layer prevent key collisions between teams?

Redis keys follow a structured prefix pattern: ${serviceId}:session:${sessionKey}:${teamId}:${agentId}. This ensures that identical session keys from different teams occupy distinct Redis namespaces. SQLite stores similarly scope tables or databases by serviceId first, then apply query-level filtering by isolation fields.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →