How to Extract Skills from Conversation Sessions in TencentDB Agent Memory
To extract skills from conversation sessions, send messages via POST /v3/skill/conversation/add and let automatic thresholds trigger background LLM-based extraction.
TencentDB Agent Memory mines Skills—reusable knowledge fragments—directly from turn-by-turn conversation streams. The extraction process is fully automated: you stream session data through a single API, and the system archives and processes it when predefined thresholds are met. This article walks through the complete pipeline, from message ingestion to querying extracted skills, based on the source implementation in TencentCloud/TencentDB-Agent-Memory.
The Skill Extraction Pipeline
The core flow spans six stages, from request validation to background processing:
| Stage | Action | Source File |
|---|---|---|
| 1. Request building | Construct JSON payload with identifiers and five-role messages | add-handler.ts |
| 2. Validation & counting | Check roles, tool_call_id presence, and count tool calls |
add-handler.ts |
| 3. Threshold evaluation | Compare against byte count, tool call count, and compression thresholds | add-handler.ts |
| 4. Archive & task creation | Write archive file and enqueue extraction task atomically | trigger-service.ts |
| 5. Background extraction | LLM-based worker processes archived session | extract-worker.ts |
| 6. Skill retrieval | Query results via Skill APIs | skill-types.ts |
Message Structure and Five-Role Schema
Each conversation turn uses a strict five-role schema defined in the validation layer. The VALID_ROLES constant permits: user, assistant, tool_call, tool_result, and system.
For tool_call and tool_result roles, the tool_call_id field is mandatory. The handler counts occurrences of tool-invocation roles separately to track against the toolCallThreshold.
Example message array structure:
[
{ "role": "user", "content": "How do I optimize a slow query?" },
{ "role": "assistant", "content": "Check the execution plan first." },
{ "role": "tool_call", "content": "", "tool_call_id": "tc-001", "tool_name": "explain" },
{ "role": "tool_result", "content": "Full table scan detected on users table", "tool_call_id": "tc-001" }
]
Threshold Configuration and Trigger Logic
The DEFAULT_HANDLER_THRESHOLDS object in add-handler.ts defines three independent triggers:
- Tool call threshold:
10tool invocations - Byte threshold: approximately
40 KBuncompressed - Compression threshold:
40 KB(triggers archival for compression evaluation)
Archive and extraction launch when any threshold satisfies:
rawBytes ≥ requestCompressThresholdBytes
OR toolCallCount ≥ toolCallThreshold
OR byteCount ≥ bytesThreshold
The SkillTriggerService.archive method implements atomic task enqueueing under a mutex. This prevents race conditions where duplicate "ghost tasks" could spawn multiple extractors for the same session.
SDK Implementation with SkillClient
The TypeScript SDK provides SkillClient as a thin wrapper around all 17 skill endpoints. Initialize with default identifiers to reduce per-call repetition:
import { SkillClient } from 'memory-core';
const skills = new SkillClient({
endpoint: 'https://memory.tencentyun.com',
apiKey: 'sk-******',
serviceId: 'mem-xyz',
teamId: 'team-01',
agentId: 'agent-coder',
userId: 'u-alice',
});
Submit conversation turns using conversationAdd (defined around L380 in skill-client.ts). This forwards to POST /v3/skill/conversation/add without client-side threshold logic—validation and triggering remain server-side:
await skills.conversationAdd({
instance_id: 'default',
session_id: 'sess-12345',
space_id: '',
user_id: 'u-alice',
team_id: 'team-01',
agent_id: 'agent-coder',
messages: [
{ role: 'user', content: 'How can I sort an array in Python?' },
{ role: 'assistant', content: 'You can use `sorted()` or `list.sort()`.' },
{
role: 'tool_call',
content: '',
tool_call_id: 'tc-001',
tool_name: 'python-docs',
},
{
role: 'tool_result',
content: 'sorted() returns a new list, list.sort() sorts in-place.',
tool_call_id: 'tc-001',
},
],
});
Retrieving Extracted Skills
After background processing completes (typically seconds), query skills through two primary patterns:
Semantic search using natural language:
const result = await skills.search({
query: 'array sorting Python',
top_k: 5,
team_id: 'team-01',
agent_id: 'agent-coder',
});
console.log(result.items.map(s => s.name));
// ['Python List Sorting Patterns', 'In-place vs Copy Sort Decisions']
Enumerative listing with filters:
const list = await skills.list({
filters: {
owner_agent_id: 'agent-coder',
status: ['active']
},
});
Both return SkillSummary objects (defined skill-types.ts containing skill_id, name, description, and optional content when include_content is true.
Key Source Files
| File | Purpose | Location |
|---|---|---|
add-handler.ts |
HTTP handler, validation, threshold evaluation, archive triggering | MemoryCore/src/core/skill/conversation-add/ |
trigger-service.ts |
Atomic archive writing and task enqueueing with mutex protection | MemoryCore/src/core/skill/conversation-add/ |
skill-client.ts |
SDK client exposing conversationAdd, search, list endpoints |
sdk/memory-core/typescript/src/v3/ |
skill-types.ts |
TypeScript interfaces for all skill request/response shapes | sdk/memory-core/typescript/src/v3/ |
skill-handlers.ts |
Server-side router mapping /v3/skill/* to core handlers |
MemoryCore/src/gateway/ |
core-client.ts |
Proxy layer client forwarding calls to core service | MemoryProxy/src/skill/ |
Summary
- Skill extraction in TencentDB Agent Memory is triggered automatically when conversation sessions hit byte, tool-call, or compression thresholds.
- Five-role messages (
user,assistant,tool_call,tool_result,system) feed the pipeline viaPOST /v3/skill/conversation/add. - Atomic archival through
SkillTriggerService.archiveprevents duplicate extraction jobs. SkillClient.conversationAddprovides SDK access; thresholds remain server-side for consistency.- Retrieval endpoints
searchandlistreturn structuredSkillSummaryobjects with full metadata.
Frequently Asked Questions
What triggers skill extraction?
Extraction triggers when any of three thresholds is exceeded: tool-call count (default 10), uncompressed bytes (~40 KB), or compression evaluation threshold (40 KB). These are evaluated in add-handler.ts after each conversation/add request.
Can I force immediate extraction without waiting for thresholds?
The source implementation does not expose a synchronous force-extract option. The archive method in trigger-service.ts only fires when threshold conditions satisfy. For custom behavior, you would need to modify DEFAULT_HANDLER_THRESHOLDS or implement direct task enqueueing.
How are tool roles validated in the request?
The handler checks VALID_ROLES membership for every message. For tool_call and tool_result, it additionally verifies tool_call_id presence and non-empty content requirements. See validation logic in add-handler.ts.
What happens if two requests hit thresholds simultaneously?
SkillTriggerService.archive uses a mutex-protected critical section when enqueuing tasks. This guarantees atomicity: only one task entry is created even under concurrent threshold breaches, eliminating duplicate extraction jobs.
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 →