How TencentDB Agent Memory Handles Fact Retrieval: A Two-Step RAG Architecture
TencentDB Agent Memory retrieves specific facts through a two-phase RAG pipeline that separates knowledge discovery from consumption, dynamically injecting knowledge tool blocks into LLM prompts for on-demand fact extraction.
The TencentCloud/TencentDB-Agent-Memory repository implements a sophisticated retrieval system that resolves fact-level queries without bloating the context window. Instead of embedding entire knowledge bases into prompts, the system uses a lightweight discovery-and-injection pattern that lets the LLM decide which specific facts to fetch. This approach keeps memory overhead minimal while enabling precise access to team wikis, code graphs, and agent-specific knowledge assets.
Discovery Phase: Mapping Available Knowledge Assets
Before any facts are retrieved, the KnowledgeToolsInjector must identify which knowledge assets are accessible to the current session. This discovery logic branches based on whether the request originates from a specific user agent or a general team context.
Agent-Bound Asset Resolution
When a user-key is present in the session, the injector queries the kernel knowledge service through listAgentKnowledgeIds followed by listKnowledgeByIds to fetch assets bound to that specific agent. This logic resides in MemoryProxy/src/knowledge/core-client.ts (lines 71-80), ensuring agents only receive knowledge relevant to their configured scope.
Team-Wide Fallback
If no user-key is provided, the system falls back to listKnowledge, retrieving the complete catalog of team-wide knowledge assets such as wiki pages and code-graph indexes. This team-level discovery ensures collaborative agents can access shared organizational knowledge without individual configuration.
Injection Phase: Rendering the Knowledge Tools Block
Once assets are identified, the renderKnowledgeToolsBlock function in MemoryProxy/src/injection/injectors/knowledge-tools-injector.ts (lines 39-49) constructs a <knowledge_tools> XML block. Each <knowledge/> tag within this block contains:
- knowledge_id: Unique identifier for the asset
- service_url: Endpoint where the knowledge service resides
- repo_slug: Repository identifier (derived from
repo_urlwhen missing) - summary: Concise description of wiki assets
This block is injected directly into the LLM prompt, presenting the available tools without exposing their underlying data.
Fact Retrieval via Tool Invocation
The LLM consumes the injected block and orchestrates the actual fact extraction through a two-step HTTP workflow against the knowledge service endpoints.
Tool Catalog Discovery
To understand available operations, the LLM first calls the tools/list endpoint at <service_url>/tools/list, passing mandatory headers including x-tdai-service-id (the tenant identifier) and optional telemetry headers like x-conversation-id. This returns the catalog of available tools such as search or read_page (see header construction in knowledge-tools-injector.ts, lines 54-60).
Fact Extraction
Using the desired tool_name and parameters, the LLM issues a tools/call request to retrieve specific facts—whether a wiki excerpt or code-graph node. The response follows a unified envelope format {code, message, data} where code === 0 indicates successful retrieval. This separation of discovery from consumption ensures the LLM only fetches facts when explicitly needed.
Graceful Degradation and Error Handling
If any HTTP call to the knowledge service fails—whether during discovery or tool invocation—the client returns an empty list and the injector suppresses the <knowledge_tools> block entirely. This architecture allows the LLM to fall back to pure memory search or local code inspection without failing the request, maintaining system resilience even when knowledge services are unavailable.
Implementation Code Examples
The following examples demonstrate the core client initialization and block rendering pattern used in production:
// MemoryProxy/src/knowledge/core-client.ts
import { getCoreKnowledgeClient } from "./knowledge/core-client.js";
const client = getCoreKnowledgeClient({
endpoint: "http://kernel:8420",
serviceToken: "YOUR_SERVICE_TOKEN",
serviceId: "default",
timeoutMs: 5000,
});
// Team-wide asset discovery
const assets = await client.listKnowledge("team-123");
console.log(assets); // [{knowledge_id, type, service_url, name, …}, …]
// MemoryProxy/src/injection/injectors/knowledge-tools-injector.ts
import { renderKnowledgeToolsBlock } from "./injection/injectors/knowledge-tools-injector.js";
const block = renderKnowledgeToolsBlock(assets, "default", {
sessionKey: "conv-abc",
userId: "user-xyz",
teamId: "team-123",
});
// Injected into LLM prompt as <knowledge_tools>...</knowledge_tools>
console.log(block);
# Direct tool call for fact retrieval
curl -sSk -X POST http://knowledge-service/v3/tools/call \
-H 'content-type: application/json' \
-H 'x-tdai-service-id: default' \
-H 'x-conversation-id: conv-abc' \
-d '{
"knowledge_id": "wiki-789",
"tool_name": "read_page",
"params": {"page_id": "introduction"}
}'
Summary
- Two-phase architecture: TencentDB Agent Memory separates asset discovery (
listKnowledge) from fact consumption (tools/call) to minimize prompt size. - Dynamic injection: The
KnowledgeToolsInjectorrenders XML tool blocks only when assets are available, avoiding empty context pollution. - LLM-driven selection: The LLM decides which specific facts to retrieve by calling discovered tools, rather than receiving pre-fetched documents.
- Resilient design: Failed knowledge service calls result in empty block injection, allowing graceful fallback to memory-based reasoning.
- Configuration: Core client settings and injection hooks are defined in
core-client.tsandknowledge-tools-injector.tson thefeat/server_teambranch.
Frequently Asked Questions
How does TencentDB Agent Memory handle fact retrieval when specific facts are needed?
The system implements a RAG-driven approach where the KnowledgeToolsInjector first discovers available knowledge assets (team-wide or agent-bound), injects them as tool definitions into the prompt, and allows the LLM to call specific endpoints like tools/call to retrieve exact facts on demand.
What is the difference between listKnowledge and listAgentKnowledgeIds?
listKnowledge retrieves the complete catalog of team-wide knowledge assets when no specific user context exists, while listAgentKnowledgeIds followed by listKnowledgeByIds fetches assets bound to a specific agent when a user-key is present, enabling personalized knowledge scopes.
What happens if the knowledge service is unavailable?
If HTTP calls to the kernel knowledge service fail during discovery or tool invocation, the client returns an empty list and the injector omits the <knowledge_tools> block entirely. The LLM then falls back to pure memory search or local code inspection without throwing errors.
Where is the knowledge tool block rendering logic located?
The XML block generation logic resides in MemoryProxy/src/injection/injectors/knowledge-tools-injector.ts within the renderKnowledgeToolsBlock function (lines 39-49), while the HTTP client for knowledge discovery is implemented in MemoryProxy/src/knowledge/core-client.ts.
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 →