How the v3 `/v3/scenario/*` Endpoints Manage L2 Scenarios in TencentDB Agent Memory

The v3 /v3/scenario/* endpoints provide five CRUD operations for managing L2 scenarios: ls to list files, read to retrieve markdown content, write to create or update with versioning, rm to delete, and count to tally files—all enforcing team-agent-user isolation and path-traversal protection.

The L2 scenario layer in TencentDB Agent Memory stores complete markdown files representing structured scenarios or "scenes." These files power contextual memory for AI agents, with the v3 data-plane API exposing granular control over this content. All five scenario endpoints share a unified architecture for isolation, validation, and storage abstraction, implemented centrally in MemoryCore/src/gateway/v2-router.ts.


The Five v3 /v3/scenario/* Endpoints

Each endpoint follows a consistent POST-over-HTTP pattern with JSON bodies, returning standardized envelopes containing code, message, request_id, and data.

POST /v3/scenario/ls — List Scenario Files

handleScenarioLs retrieves the scene index: an array of scenario file paths with their metadata.

The handler accepts an optional path_prefix to scope the listing, then calls storage.listObjects filtered by L2 isolation fields (team_id, agent_id, user_id). Each returned entry contains path, summary, updated_at, and related fields.

Router registration appears at line 424 of v2-router.ts:

// Request shape validated by scenarioLsRequestSchema
{
  path_prefix?: string  // "" or omitted for root listing
}

// Response data
{
  scenes: [
    { path: "scenarios/onboarding.md", summary: "User onboarding flow", updated_at: "2024-01-15T09:23:00Z", version: 3 },
    ...
  ]
}

POST /v3/scenario/read — Retrieve Full Content

handleScenarioRead fetches the complete markdown of a single scenario, internal meta block intact.

The path parameter undergoes safePath validation via Zod schema to prevent directory traversal. The handler injects isolation fields into the request context before reading from storage. The raw response includes the -----META-START----- … -----META-END----- wrapper that front-end code later strips.

See line 425 for implementation.

// Request
{ path: "scenarios/known_issue_resolution.md" }

// Response data includes raw markdown:
{
  content: "-----META-START-----\nversion: 2\nupdated_at: ...\n-----META-END-----\n# Known Issue Resolution\n\nWhen users report..."

}

POST /v3/scenario/write — Create or Update with Versioning

handleScenarioWrite implements upsert semantics with automatic version incrementing.

The request body validates against scenarioWriteRequestSchema (defined in v2-schemas.ts around line 269). New files start at v1; each subsequent write increments the version. The handler persists content, updates metadata (summary, timestamps), and returns the new version.

See line 426 for handler registration.

// Request
{
  path: "scenarios/escalation_playbook.md",
  content: "# Escalation Playbook\n\n1. Verify customer tier...",

  summary: "Tiered escalation procedures"
}

// Response data
{
  version: 4,
  updated_at: "2024-01-16T14:32:00Z"
}

POST /v3/scenario/rm — Delete Scenario Files

handleScenarioRm performs atomic deletion of a scenario by path.

Validated by scenarioRmRequestSchema using the same safePath protection, the handler invokes storage.deleteObject and returns a simple success indicator. The file and its index entry disappear together.

See line 427 for implementation.

// Request
{ path: "scenarios/deprecated_workflow.md" }

// Response
{ success: true }

POST /v3/scenario/count — Count Matching Scenarios

handleScenarioCount returns the total number of scenario files matching an optional prefix.

This endpoint reuses the listing logic but returns only the aggregate count—useful for pagination UIs or quota enforcement. Validation uses scenarioCountRequestSchema (line 141 in v2-schemas.ts).

See line 428 for handler registration.

// Request
{ path_prefix: "scenarios/2024-q1/" }

// Response data
{ count: 47 }

Core Architecture Mechanisms

Isolation Enforcement via resolveIsolation

All five endpoints require four identifiers: team_id, agent_id, user_id, and task_id. These may appear in request bodies or x-tdai-* headers. The resolveIsolation function (lines 990–1000 in v2-router.ts) normalizes and validates these fields, rejecting incomplete requests with HTTP 422.

This ensures strict data separation between organizational boundaries—no scenario file is accessible without complete isolation context.

Path-Traversal Protection

Every endpoint accepting a path parameter uses the safePath Zod validator. This strips ../ components and anchors paths within the service's storage namespace, preventing escape to parent directories or system files.

Storage Abstraction

Handlers call resolveStoreForRequest and resolveStorageForRequest to obtain storage instances. The generic Storage interface allows the same endpoint code to operate over ClickHouse, local filesystem, or cloud object stores without modification.

Versioning and Meta Block Handling

Scenario files maintain internal versioning front-end components consume. The write endpoint auto-increments versions; read returns raw content including meta wrappers. Client-side code in MemoryPanel/web/src/pages/ChatMemoryPage/utils/memory-utils.ts handles meta block stripping for display purposes.


Complete API Usage Examples

Listing Scenarios

const response = await fetch("http://localhost:8420/v3/scenario/ls", {
  method: "POST",
  headers: {
    "Authorization": "Bearer <KERNEL_AUTH_TOKEN>",
    "Content-Type": "application/json",
    "x-tdai-team-id": "team_prod",
    "x-tdai-agent-id": "agent_support_bot",
    "x-tdai-user-id": "user_ops_001"
  },
  body: JSON.stringify({ path_prefix: "playbooks/" })
});
const { scenes } = (await response.json()).data;

Reading Scenario Content

const response = await fetch("http://localhost:8420/v3/scenario/read", {
  method: "POST",
  headers: { /* auth and isolation headers */ },
  body: JSON.stringify({ path: "playbooks/security_incident.md" })
});
const { content } = (await response.json()).data;
// content includes -----META-START----- block

Writing a New Scenario

const response = await fetch("http://localhost:8420/v3/scenario/write", {
  method: "POST",
  headers: { /* auth and isolation headers */ },
  body: JSON.stringify({
    path: "playbooks/new_feature_announcement.md",
    content: "# New Feature: Vector Search\n\nOur latest release adds...",

    summary: "Customer-facing announcement for vector search capability"
  })
});
const { version, updated_at } = (await response.json()).data;

Deleting a Scenario

await fetch("http://localhost:8420/v3/scenario/rm", {
  method: "POST",
  headers: { /* auth and isolation headers */ },
  body: JSON.stringify({ path: "playbooks/superseded_policy.md" })
});

Counting Scenarios

const response = await fetch("http://localhost:8420/v3/scenario/count", {
  method: "POST",
  headers: { /* auth and isolation headers */ },
  body: JSON.stringify({ path_prefix: "archived/" })
});
const { count } = (await response.json()).data;

Key Source Files

File Purpose Location
MemoryCore/src/gateway/v2-router.ts Handler registration and core logic for all /v3/scenario/* endpoints MemoryCore/src/gateway/v2-router.ts
MemoryCore/src/gateway/v2-schemas.ts Zod schemas: scenarioWriteRequestSchema, scenarioReadRequestSchema, safePath validator MemoryCore/src/gateway/v2-schemas.ts
MemoryPanel/web/src/pages/ChatMemoryPage/utils/memory-utils.ts Client-side meta block stripping from read responses MemoryPanel/web/src/pages/ChatMemoryPage/utils/memory-utils.ts
MemoryCore/v3-api-memorycore-doc.md Official API documentation for v3 endpoints MemoryCore/v3-api-memorycore-doc.md

Summary

  • Five endpoints provide complete L2 scenario lifecycle management: ls, read, write, rm, and count.

  • Mandatory isolation via team_id, agent_id, user_id, and task_id prevents cross-tenant data access, enforced by resolveIsolation in v2-router.ts.

  • Automatic versioning on write operations tracks scenario evolution without manual version management.

  • Path-traversal protection through safePath Zod schemas ensures storage security.

  • Storage-agnostic design via the Storage interface abstraction supports multiple backends from identical endpoint code.


Frequently Asked Questions

What is an L2 scenario in TencentDB Agent Memory?

An L2 scenario is a complete markdown file representing a structured scene or procedural context for AI agent memory. Unlike L1 (key-value pairs) or L3 (semantic vectors), L2 stores human-readable, versioned documents that agents can reference during conversations.

How does scenario versioning work?

Each write operation automatically increments an internal version counter starting from v1. The version and timestamps are stored in the meta block (between -----META-START----- and -----META-END-----) and returned in the API response. No manual version specification is required.

Why do all scenario endpoints use POST instead of RESTful HTTP methods?

The v3 API design prioritizes consistent request envelopes and complex filtering parameters (like path_prefix) that exceed URL length limits for GET requests. POST with JSON bodies also simplifies header-based isolation and batch operations across the entire v3 surface.

How do I strip the meta block from scenario content for display?

The reference implementation in MemoryPanel/web/src/pages/ChatMemoryPage/utils/memory-utils.ts parses the raw markdown and removes everything between -----META-START----- and -----META-END-----. Your client code should implement similar logic, or you can use a regex like /-----META-START-----[\s\S]*?-----META-END-----/ to isolate the content portion.

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 →