How Skill Versioning Works in TencentDB Agent Memory: Expected Version, Patch, Update, and Version History
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/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:
expected_version: z.number().int().min(1)
This mandatory field contrasts with the output version field, which remains optional:
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/feat/server_team/MemoryCore/src/gateway/skill-handlers.ts). The handler:
- Retrieves the stored skill record from the metadata store
- Compares
stored.versionagainstrequest.expected_version - Rejects with a version-conflict error if they differ
- 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/feat/server_team/MemoryCore/src/gateway/v2-router.ts) handles the atomic version bump:
const updatedVersion = (record.version ?? 0) + 1;
The server then returns the new version in a structured envelope:
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/feat/server_team/MemoryCore/src/metadata/store/sqlite-adapter.ts) defines the persistent schema:
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
// 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:
- Server detects
stored.version !== expected_version - Handler returns version-conflict error (typically HTTP 409 or repository-specific error code)
- Client must re-fetch the skill to obtain current version and state
- 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_versionprevents 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
versioncolumn 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 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.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →