# How Skill Versioning Works in TencentDB Agent Memory: Expected Version, Patch, Update, and Version History

> Understand TencentDB Agent Memory skill versioning. Learn about expected_version, patch, update, and version history for seamless updates and conflict prevention.

- Repository: [Tencent Cloud/TencentDB-Agent-Memory](https://github.com/TencentCloud/TencentDB-Agent-Memory)
- Tags: deep-dive
- Published: 2026-08-31

---

**Skill versioning uses optimistic locking where clients must supply `expected_version` matching the server's current version; if matched, the server applies the change and returns an incremented version number, otherwise it rejects with a conflict error.**

The **TencentDB Agent Memory** repository implements robust version control for AI skills through a simple but effective integer-based system. Every skill asset carries a monotonic version counter that prevents lost updates and maintains a complete, queryable history. This article examines the exact mechanisms governing `expected_version`, patch operations, full updates, and how version history persists in the metadata layer.

## Skill Versioning Core Concepts

The system treats each **Skill** as an immutable versioned asset. Rather than overwriting data in place, the architecture increments a version counter on every successful modification. This design choice enables audit trails, rollback capabilities, and clean conflict detection between concurrent editors.

For the complete schema definition, see [[`MemoryCore/src/gateway/skill-schemas.ts`](https://github.com/TencentCloud/TencentDB-Agent-Memory/blob/main/MemoryCore/src/gateway/skill-schemas.ts)](https://github.com/TencentCloud/TencentDB-Agent-Memory/blob/feat/server_team/MemoryCore/src/gateway/skill-schemas.ts).

## The Expected Version Mechanism

### What Expected Version Enforces

The **`expected_version`** field implements **optimistic locking**. When a client attempts to modify a skill, it declares which version it believes is current. The server validates this assumption before proceeding.

From [`skill-schemas.ts`](https://github.com/TencentCloud/TencentDB-Agent-Memory/blob/main/skill-schemas.ts):

```typescript
expected_version: z.number().int().min(1)

```

This mandatory field contrasts with the **output** `version` field, which remains optional:

```typescript
version: z.number().int().min(1).optional()

```

Clients receive `version` in read responses but must echo it back as `expected_version` in write requests.

### Validation Flow in Skill Handlers

The optimistic lock check occurs in [[`MemoryCore/src/gateway/skill-handlers.ts`](https://github.com/TencentCloud/TencentDB-Agent-Memory/blob/main/MemoryCore/src/gateway/skill-handlers.ts)](https://github.com/TencentCloud/TencentDB-Agent-Memory/blob/feat/server_team/MemoryCore/src/gateway/skill-handlers.ts). The handler:

1. Retrieves the stored skill record from the metadata store
2. Compares `stored.version` against `request.expected_version`
3. Rejects with a version-conflict error if they differ
4. Proceeds with the update only on exact match

This pattern eliminates race conditions without requiring distributed locks or transaction isolation beyond a single-record compare-and-swap.

## Patch vs. Update Operations

Both **PATCH** (partial modification) and **PUT** (full replacement) endpoints enforce identical version requirements. The distinction lies in payload semantics, not version handling.

### Patch Operation

Partial updates merge changes into the existing skill document while preserving unmodified fields. The client still must supply `expected_version`.

### Update Operation

Full replacements overwrite the entire skill document. The same `expected_version` validation applies, ensuring the client acted on current data before wholesale replacement.

## Version Increment and Response

After successful validation, [[`MemoryCore/src/gateway/v2-router.ts`](https://github.com/TencentCloud/TencentDB-Agent-Memory/blob/main/MemoryCore/src/gateway/v2-router.ts)](https://github.com/TencentCloud/TencentDB-Agent-Memory/blob/feat/server_team/MemoryCore/src/gateway/v2-router.ts) handles the atomic version bump:

```typescript
const updatedVersion = (record.version ?? 0) + 1;

```

The server then returns the new version in a structured envelope:

```typescript
successEnvelope<AtomicUpdateData>({
  id,
  version: `v${updatedVersion}`,
  // ... additional response fields
})

```

Clients receive string-formatted versions like `"v4"` while the database stores raw integers for efficient comparison and indexing.

## Version History in the Metadata Store

### SQLite Adapter Implementation

The [[`MemoryCore/src/metadata/store/sqlite-adapter.ts`](https://github.com/TencentCloud/TencentDB-Agent-Memory/blob/main/MemoryCore/src/metadata/store/sqlite-adapter.ts)](https://github.com/TencentCloud/TencentDB-Agent-Memory/blob/feat/server_team/MemoryCore/src/metadata/store/sqlite-adapter.ts) defines the persistent schema:

```sql
version INTEGER NOT NULL DEFAULT 1

```

Every skill row carries this column from creation. Updates increment the value in-place. While the adapter overwrites rather than appending rows, external audit logging or the MongoDB adapter may capture intermediate states depending on deployment configuration.

### MongoDB Adapter Behavior

The MongoDB implementation mirrors this pattern with equivalent document-level version fields, ensuring consistent behavior across storage backends.

## Practical Implementation Example

```typescript
// 1. Fetch current skill state
const skill = await api.getSkill('skill-123');
// Response: { id: 'skill-123', version: 3, name: 'DataAnalysis', ... }

// 2. Apply partial patch with expected version
await api.patchSkill('skill-123', {
  expected_version: 3,              // Must match server's version
  changes: {
    description: 'Enhanced natural language processing capabilities'
  }
});
// Success response: { id: 'skill-123', version: 'v4', ... }

// 3. Subsequent full update uses latest known version
await api.updateSkill('skill-123', {
  expected_version: 4,              // Now v4 is the expected baseline
  name: 'AdvancedDataAnalysis',
  tools: ['sql_query', 'chart_generation']
});
// Success response: { id: 'skill-123', version: 'v5', ... }

```

## Conflict Resolution Workflow

When `expected_version` mismatches the stored version:

1. Server detects `stored.version !== expected_version`
2. Handler returns version-conflict error (typically HTTP 409 or repository-specific error code)
3. Client must re-fetch the skill to obtain current version and state
4. Client replays logic with updated `expected_version`

This forces explicit merge decisions at the application layer rather than silent overwrites.

## Summary

- **Optimistic locking** via `expected_version` prevents lost updates without distributed coordination
- **Integer versions** start at 1 and increment atomically on every successful write
- **Patch and update** operations share identical version validation semantics
- **Version history** persists in the `version` column of metadata storage (SQLite or MongoDB)
- **Conflict detection** requires clients to re-fetch and retry on version mismatch

## Frequently Asked Questions

### What happens if I omit expected_version in a patch or update request?

The request fails schema validation before reaching business logic. The `expected_version` field is mandatory in [`skill-schemas.ts`](https://github.com/TencentCloud/TencentDB-Agent-Memory/blob/main/skill-schemas.ts) with `.min(1)` constraint, ensuring no write proceeds without explicit version declaration.

### Can two clients update the same skill if they both have the same expected_version?

No—only the first request succeeds. The second client receives a version-conflict error because the first increment changed the stored version. This serializes concurrent modifications and forces the second client to re-fetch.

### How do I query historical versions of a skill?

The core SQLite adapter stores only current version state. Full version history requires either: enabling audit logging at the application layer, using the MongoDB adapter with revision documents, or integrating external change data capture on the `meta_assets` table.

### Does version numbering ever reset?

No. Versions are monotonically increasing integers with no upper bound or reset mechanism. The `v${updatedVersion}` string formatting supports arbitrary integer values without structural limits.