MemoryAsset ACL Strategy: How Fixed Binding + ACL Controls Agent Loadouts in TencentDB Agent Memory

The MemoryAsset ACL Strategy combines Fixed Binding and ACL layers to restrict which memory assets an Agent can access, first limiting Agents to pre-selected loadouts then enforcing fine-grained Team → User → Agent → Visibility permissions.

This two-stage permission system is central to the TencentDB Agent Memory architecture. It allows teams to share institutional knowledge through shared memory assets while maintaining strict data isolation. According to the repository's README, "assets are uniformly registered as Memory Assets" and the hub "uses Fixed Binding + ACL to determine which assets a given Agent can use"【README.md#L57-L60】.

How Fixed Binding Creates Agent Loadouts

Fixed Binding is the first filtering layer. When an Agent is created or edited, administrators explicitly bind specific memory assets to that Agent's configuration. This creates an immutable loadout that defines exactly which Chat Memory, Skills, Wiki, and CodeGraph assets the Agent may attempt to access.

Assets outside this bound set are invisible to the Agent regardless of ACL permissions. This architectural decision prevents accidental data exposure and simplifies runtime permission evaluation.

Creating an Agent with a Fixed Loadout

import { MemoryCoreClient } from '@tencentdb/memory-core';

const client = new MemoryCoreClient({ endpoint, apiKey });

await client.createAgent({
  name: 'Research Scout',
  team_id: 'team-123',
  loadout: {
    chat_memory_ids: ['cm-987'],
    wiki_ids:        ['wiki-321'],
    skill_ids:       ['skill-654'],
  },
});

The loadout object in the createAgent call establishes the fixed binding. The Agent cannot access assets beyond these IDs, even if permissions would otherwise allow it【README.md#L11-L13】.

ACL Layer: Team → User → Agent → Visibility Enforcement

After Fixed Binding narrows the asset pool, the ACL (Access Control List) subsystem applies granular permissions. The ACL system stores meta_asset_acl records in the metadata database that grant or deny specific actions to identified subjects.

Core ACL Data Model

In MemoryCore/src/metadata/store/sqlite-adapter.ts, the ACL table schema defines the permission structure:

// From sqlite-adapter.ts#L263-L289
CREATE TABLE meta_asset_acl (
  id TEXT PRIMARY KEY,
  asset_id TEXT NOT NULL,
  subject_type TEXT NOT NULL,  -- 'user', 'team_role', 'agent'
  subject_id TEXT NOT NULL,
  permission TEXT NOT NULL,    -- 'read', 'write', 'admin'
  effect TEXT NOT NULL,        -- 'allow' or 'deny'
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

This schema supports three subject types with hierarchical evaluation:

  • user — individual user accounts
  • team_role — role-based group permissions
  • agent — Agent-specific overrides

Permission Checker Implementation

The runtime ACL evaluation occurs in MemoryCore/src/metadata/service/permission-checker.ts. The core logic iterates matching ACL records and applies precedence rules:

// From permission-checker.ts#L27-L33 and #L86-L94
export async function checkPermission(request: AclCheckRequest): Promise<boolean> {
  const aclRecords = await fetchAclRecords({
    asset_id: request.asset_id,
    subject_types: ['agent', 'user', 'team_role'], // Evaluation order
  });

  for (const record of aclRecords) {
    if (matchesSubject(record, request) && record.permission === request.action) {
      return record.effect === 'allow';
    }
  }
  return false; // Default deny
}

The iteration order prioritizes agent-specific rules, then user, then team_role, allowing fine-grained overrides of broader permissions【permission-checker.ts#L27-L33】【permission-checker.ts#L86-L94】.

Granting ACL Permissions

Administrators grant access through the API defined in MemoryCore/src/metadata/router/v3-meta-router.ts:

// Grant read access to a specific user
await client.grantAcl({
  asset_id:     'wiki-321',
  subject_type: 'user',
  subject_id:   'user-42',
  permission:   'read',
  effect:       'allow',
});

The aclGrantSchema validates requests with these exact fields【v3-meta-router.ts#L319-L325】.

Runtime ACL Check Flow

When an Agent attempts asset access, MemoryProxy/src/tdai/client.ts performs the verification:

// From client.ts#L329-L361
const aclResponse = await fetch(`${base}/v3/meta/acl/check`, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    user_id:   context.userId,
    asset_id:  requestedAssetId,
    action:    'read',
    agent_id:  context.agentId,  // Enables agent-specific ACL evaluation
  }),
});

const { allowed } = await aclResponse.json();
if (!allowed) {
  throw new PermissionDeniedError(`ACL denied for ${requestedAssetId}`);
}

The agent_id parameter enables the permission checker to apply Agent-specific overrides to inherited User or Team Role permissions【client.ts#L329-L361】.

Asset Visibility Levels

Assets carry a visibility field that interacts with ACL evaluation:

Visibility Behavior
private Only explicit ACL grants permit access
team Team members gain read access by default; ACL can restrict
restricted Requires explicit ACL grant regardless of team membership

The visibility field is defined in MemoryCore/src/metadata/types.ts and evaluated during the ACL check alongside explicit permission records.

Debugging ACL Configuration

List all ACL entries for an asset to diagnose permission issues:

// List ACL entries via /v3/meta/acl/list
const aclList = await client.listAcl({ asset_id: 'wiki-321' });

// Returns array of: { asset_id, subject_type, subject_id, permission, effect }
console.table(aclList);

The list endpoint is defined at v3-meta-router.ts#L444-L447【v3-meta-router.ts#L444-L447】.

Key Implementation Files

File Path Responsibility
README.md Conceptual documentation of Fixed Binding + ACL strategy【README.md】
MemoryCore/src/metadata/types.ts Asset metadata and ACL type definitions【types.ts】
MemoryCore/src/metadata/store/sqlite-adapter.ts ACL persistence layer with meta_asset_acl table【sqlite-adapter.ts#L263-L289】
MemoryCore/src/metadata/service/permission-checker.ts Core ACL evaluation logic【permission-checker.ts】
MemoryCore/src/metadata/router/v3-meta-router.ts REST API for aclGrant, aclRevoke, aclList, aclCheck【v3-meta-router.ts】
MemoryProxy/src/tdai/client.ts Proxy-side ACL enforcement before asset retrieval【client.ts#L329-L361】
MemoryPanel/web/src/services/asset-scope-store.ts UI state management for fixed binding configuration【asset-scope-store.ts】

Summary

  • Fixed Binding creates immutable Agent loadouts that limit which memory assets an Agent can discover.
  • ACL applies fine-grained permissions within the bound set, evaluating agent, user, and team_role subject types in that precedence order.
  • The two-layer model enables teams to share experience assets while maintaining strict data isolation through private, team, and restricted visibility levels.
  • Default deny applies when no ACL records match, ensuring no accidental access grants.
  • Runtime enforcement occurs in MemoryProxy before asset retrieval, with the permission checker in MemoryCore serving as the authoritative decision engine.

Frequently Asked Questions

How does Fixed Binding differ from ACL in the MemoryAsset security model?

Fixed Binding operates at configuration time, permanently attaching specific asset IDs to an Agent's loadout. ACL operates at request time, evaluating whether the requesting context (Team → User → Agent) has permission to perform the requested action on an asset within that loadout. Fixed Binding is a coarse gate; ACL provides fine-grained control.

Can an Agent access assets not in its Fixed Binding if ACL permissions exist?

No. Fixed Binding is evaluated before ACL checks. Assets outside the bound loadout are completely invisible to the Agent regardless of ACL configuration. This prevents information leakage through enumeration attacks and simplifies security auditing.

What happens when multiple ACL records conflict for the same subject?

The permission checker evaluates records in agent, user, team_role order and returns on the first match. More specific subject types override broader ones. An agent record takes precedence over a user record, which takes precedence over a team_role record【permission-checker.ts#L27-L33】.

How do I troubleshoot "ACL denied" errors in production?

Use the /v3/meta/acl/list endpoint to retrieve all ACL records for the target asset. Verify that: (1) the asset ID exists in the Agent's loadout, (2) at least one record matches the requesting user_id or agent_id with effect: 'allow', and (3) no more specific record with effect: 'deny' exists higher in the evaluation order【v3-meta-router.ts#L444-L447】.

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 →