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

> Discover how TencentDB Agent Memory ensures robust multi-tenant data isolation using a four-field tuple validated at the API and embedded in storage keys for secure access.

- Repository: [Tencent Cloud/TencentDB-Agent-Memory](https://github.com/TencentCloud/TencentDB-Agent-Memory)
- Tags: architecture
- Published: 2026-09-02

---

**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`](https://github.com/TencentCloud/TencentDB-Agent-Memory/blob/main/MemoryCore/src/gateway/v2-schemas.ts) defines these mandatory fields:

```typescript
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`](https://github.com/TencentCloud/TencentDB-Agent-Memory/blob/feat/server_team/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:

```typescript
// /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`](https://github.com/TencentCloud/TencentDB-Agent-Memory/blob/feat/server_team/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`](https://github.com/TencentCloud/TencentDB-Agent-Memory/blob/feat/server_team/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:

```typescript
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;
}

```

```typescript
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:
- Type definition: [`sdk/memory-core/typescript/src/v3/types.ts#L1-L11`](https://github.com/TencentCloud/TencentDB-Agent-Memory/blob/feat/server_team/sdk/memory-core/typescript/src/v3/types.ts#L1-L11)
- Constructor enforcement: [`sdk/memory-core/typescript/src/v3/client.ts#L140-L149`](https://github.com/TencentCloud/TencentDB-Agent-Memory/blob/feat/server_team/sdk/memory-core/typescript/src/v3/client.ts#L140-L149)

### Python SDK

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

```python
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`](https://github.com/TencentCloud/TencentDB-Agent-Memory/blob/feat/server_team/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`](https://github.com/TencentCloud/TencentDB-Agent-Memory/blob/feat/server_team/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`](https://github.com/TencentCloud/TencentDB-Agent-Memory/blob/feat/server_team/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`](https://github.com/TencentCloud/TencentDB-Agent-Memory/blob/feat/server_team/MemoryCore/src/utils/env-config.ts#L153-L155)

## Practical Usage Examples

### TypeScript Client with Strict Isolation

```typescript
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

```http
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`](https://github.com/TencentCloud/TencentDB-Agent-Memory/blob/main/v2-router.ts) for all `/v3/*` paths |
| **SDK Constructor** | Mandatory `V3IsolationContext` parameter | [`client.ts`](https://github.com/TencentCloud/TencentDB-Agent-Memory/blob/main/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`](https://github.com/TencentCloud/TencentDB-Agent-Memory/blob/main/redis-session-store.ts) |
| **SQLite Persistence** | Per-service database scoping | [`sqlite-store.ts`](https://github.com/TencentCloud/TencentDB-Agent-Memory/blob/main/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`](https://github.com/TencentCloud/TencentDB-Agent-Memory/blob/main/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`](https://github.com/TencentCloud/TencentDB-Agent-Memory/blob/main/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.