How the Injection Pipeline Is Organized in TencentDB Agent Memory: Architecture and Flow

The injection pipeline in TencentDB Agent Memory is a deterministic request-processing orchestrator that parses raw LLM requests through ProtocolAdapters, detects agent profiles, executes registered InjectionHooks at predefined InjectionPoints, and serializes enriched prompts downstream.

The injection pipeline serves as the central processing engine in the TencentDB Agent Memory system. It intercepts incoming requests from LLM proxies, enriches prompts with contextual memories, skills, and knowledge tools, and forwards modified requests to downstream providers. The architecture is implemented in TypeScript within the MemoryProxy/src/injection/ directory and follows a strict execution order to ensure deterministic prompt modification.

High-Level Architecture

The pipeline processes every request through a standardized flow implemented in the InjectionPipeline class within [pipeline.ts](https://github.com/TencentCloud/TencentDB-Agent-Memory/blob/feat/server_team/MemoryProxy/src/injection/pipeline.ts).


raw body → Adapter.parse() → AgentContext
          │
          └─► Detect AgentProfile (URL-path lookup → legacy content scan)
          │
          └─► Execute registered InjectionHooks at each InjectionPoint
          │
          └─► Adapter.serialize() → modified body

This design decouples protocol-specific parsing from injection logic, allowing the system to handle multiple LLM providers (OpenAI, Anthropic) through a unified internal representation called AgentContext.

Core Pipeline Components

ProtocolAdapter

The ProtocolAdapter interface (defined in [adapters/interface.ts](https://github.com/TencentCloud/TencentDB-Agent-Memory/blob/feat/server_team/MemoryProxy/src/injection/adapters/interface.ts)) handles translation between vendor-specific request formats and the generic AgentContext. Each adapter implements parse() to deserialize incoming requests and serialize() to produce the final enriched payload.

AgentProfile

AgentProfile (see [agents/interface.ts](https://github.com/TencentCloud/TencentDB-Agent-Memory/blob/feat/server_team/MemoryProxy/src/injection/agents/interface.ts)) describes agent configurations (e.g., codebuddy, workbuddy) and provides slot resolution for anchor-based injection. Profiles enable precise placement of injected content within specific regions of the system prompt without disturbing surrounding text.

HookRegistry and InjectionHook

The HookRegistry (in [registry.ts](https://github.com/TencentCloud/TencentDB-Agent-Memory/blob/feat/server_team/MemoryProxy/src/injection/registry.ts)) maintains a collection of InjectionHook instances organized by InjectionPoint. Each hook (such as the SkillInjector in [skill-injector.ts](https://github.com/TencentCloud/TencentDB-Agent-Memory/blob/feat/server_team/MemoryProxy/src/injection/injectors/skill-injector.ts)) declares an anchor, a cacheStrategy, and an execute method that returns content blocks to inject.

Optional Infrastructure Components

Step-by-Step Execution Flow

The process() method in pipeline.ts orchestrates the injection pipeline through nine distinct phases:

  1. Adapter Selection (lines 90-96): The pipeline looks up the appropriate ProtocolAdapter from options.adapters using metadata.protocol.

  2. Parsing (line 99): adapter.parse(body, metadata) creates an AgentContext containing the system message, user messages, tool definitions, and metadata.

  3. Agent Detection (lines 101-128): If options.agentProfiles is supplied, the pipeline performs a fast lookup via metadata.agentSource. If not found, the deprecated detectAgent function scans the system prompt text. The detected profile is stored in ctx.metadata.custom.agentProfile.

  4. Hook Execution (lines 150-176, 190-252): executeHooks(ctx) iterates over the fixed executionOrder of InjectionPoints and runs every hook registered for each point.

  5. Cache Handling (lines 54-78, 84-122, 124-149): Hooks declaring a cacheStrategy (none, session_init, or hybrid) interact with the cache repository. The pipeline reads pre-warmed blocks on cache hits, self-heals missing caches on first-turn misses, and merges cached with fresh blocks for hybrid strategies.

  6. Injection Application (lines 331-379): applyInjection(ctx, hook, point, blocks) attempts anchor-based insertion using the AgentProfile. If the anchor matches a defined slot, content is inserted exactly at that location; otherwise, the pipeline falls back to point-based injection.

  7. Point-Based Injection (lines 382-500): Handles coarse-grained insertion at specific points (system.prefix, user.first_turn, etc.) by prepending, appending, or replacing text blocks and tool definitions.

  8. Serialization (lines 134-135): After all hooks execute, the adapter's serialize method produces the final request body for the downstream LLM.

  9. Observer Notifications (lines 86-88, 136-138, 190-194, 217-221, 228-232, 242-245): Throughout the process, the observer receives notifications for start/end events, hook success/failure, and timing metrics.

Injection Points and Execution Order

The pipeline processes hooks in a strict deterministic sequence defined in executionOrder within pipeline.ts:

  1. system.prefix
  2. system.before_tools
  3. system.after_tools
  4. system.suffix
  5. tools.prepend
  6. tools.append
  7. user.first_turn
  8. user.before
  9. user.after

This ordering guarantees that system-level memories and instructions appear before tool definitions, while user-turn injections respect first-turn semantics for multi-turn conversations.

Anchor-Based vs Point-Based Injection

The injection pipeline supports two placement strategies:

Anchor-Based Injection: When a hook provides an anchor (via hook.anchor.rawKey or hook.anchor.slot), the pipeline attempts to locate the exact slot in the agent's system prompt using the AgentProfile. If found, profile.applyAnchor inserts content at the precise location—enabling surgical modifications like inserting memories within specific XML blocks.

Point-Based Injection: If anchor resolution fails or no anchor is provided, the pipeline logs a warning and falls back to coarse-grained injection at the predefined InjectionPoint (e.g., prepending to the system message).

Caching Strategies for Performance

Hooks declare their caching behavior via the cacheStrategy property:

  • none: Executes the hook's execute method on every request (legacy behavior).
  • session_init: On the first turn, attempts to fetch pre-warmed blocks from HookCacheRepo. On a cache miss, executes the hook once and self-heals the cache (unless the request is read-only). Subsequent turns hit the cache directly.
  • hybrid: Combines cached blocks with freshly executed results, de-duplicating by metadata.cacheKey or (type, content) tuples.

These strategies reduce latency for static assets like skill listings while maintaining freshness for dynamic content such as session-specific memories.

Implementation Example

The following TypeScript example demonstrates how to construct and utilize the injection pipeline in a proxy server:

// 1️⃣ Create protocol adapters (OpenAI, Anthropic, etc.)
import { OpenAIAdapter } from './injection/adapters/openai.js';
import { AnthropicAdapter } from './injection/adapters/anthropic.js';

const adapters = new Map<string, ProtocolAdapter>([
  ['openai', new OpenAIAdapter()],
  ['anthropic', new AnthropicAdapter()],
]);

// 2️⃣ Register injection hooks (skill search, knowledge tools, etc.)
import { registry } from './injection/registry.js';
import { SkillInjector } from './injection/injectors/skill-injector.js';
import { KnowledgeToolsInjector } from './injection/injectors/knowledge-tools-injector.js';

// Register hooks for specific injection points
registry.register('system.prefix', new SkillInjector({ /* config */ }));
registry.register('system.after_tools', new KnowledgeToolsInjector({ /* config */ }));

// 3️⃣ Optional: provide a cache repo (e.g., Redis-backed)
import { RedisHookCacheRepo } from '../db/redisHookCacheRepo.js';
const hookCacheRepo = new RedisHookCacheRepo(redisClient);

// 4️⃣ Optional: load per-agent profiles (fast lookup by URL path)
import { WorkbuddyProfile } from './injection/agents/workbuddy/profile.js';
import { CodeBuddyProfile } from './injection/agents/codebuddy/profile.js';
const agentProfiles = new Map<string, AgentProfile>([
  ['workbuddy', new WorkbuddyProfile()],
  ['codebuddy', new CodeBuddyProfile()],
]);

// 5️⃣ Build the pipeline
import { InjectionPipeline } from './injection/pipeline.js';
const pipeline = new InjectionPipeline(
  registry,
  adapters,
  { agentProfiles, hookCacheRepo },
  /* observer can be omitted → NoopInjectionObserver */
);

// 6️⃣ Process a request (example: OpenAI chat completion)
async function handleOpenAI(body: Record<string, unknown>) {
  const metadata = {
    protocol: 'openai',
    agentSource: 'codebuddy',      // derived from URL path
    userId: 'alice',
    spaceId: '',
    // …other fields required by AgentContextMetadata
  };
  const enrichedBody = await pipeline.process(body, metadata);
  // `enrichedBody` now contains injected memories, skill listings, etc.
  return enrichedBody;
}

Summary

  • The injection pipeline in pipeline.ts serves as the core orchestrator for prompt enrichment in TencentDB Agent Memory.
  • ProtocolAdapters decouple vendor-specific formats (OpenAI, Anthropic) from internal processing logic.
  • InjectionHooks execute at nine ordered InjectionPoints (system, tools, user phases) to modify prompts deterministically.
  • AgentProfiles enable anchor-based injection for precise content placement within specific prompt slots.
  • Caching strategies (session_init, hybrid) minimize latency by storing pre-computed blocks while supporting dynamic content.
  • The architecture supports optional telemetry through InjectionObserver and persistent caching through HookCacheRepo.

Frequently Asked Questions

What is the primary function of the InjectionPipeline class?

The InjectionPipeline class serves as the central request processor in TencentDB Agent Memory. It ingests raw LLM requests, converts them to a generic AgentContext via ProtocolAdapters, executes registered injection hooks at specific points in the prompt, and serializes the enriched context back into a vendor-specific format. According to the source code in pipeline.ts, this class handles the entire lifecycle from parsing to serialization, including agent detection and caching logic.

How does the pipeline determine where to inject content?

The pipeline uses a two-tier strategy defined in lines 331-379 and 382-500 of pipeline.ts. First, it attempts anchor-based injection: if a hook declares an anchor, the pipeline queries the AgentProfile to locate a specific slot in the system prompt (e.g., an <Agent> XML block). If the anchor resolves successfully, content is inserted at that exact location. If anchor resolution fails or the hook provides no anchor, the pipeline falls back to point-based injection, which prepends or appends content at one of the nine predefined InjectionPoints (system.prefix, user.first_turn, etc.).

What are the available caching strategies for injection hooks?

Hooks declare caching behavior via the cacheStrategy property with three possible values. none bypasses caching entirely, executing the hook on every request. session_init checks the HookCacheRepo for pre-warmed blocks on the first turn; on a miss, it executes the hook and populates the cache (unless read-only), serving subsequent turns from cache. hybrid merges cached blocks with freshly executed results, de-duplicating by cache keys to balance freshness with performance.

How does the pipeline handle different LLM protocols like OpenAI and Anthropic?

The pipeline abstracts protocol differences through the ProtocolAdapter interface defined in adapters/interface.ts. During initialization, consumers provide a Map of adapters keyed by protocol name (e.g., "openai", "anthropic"). When processing a request, the pipeline selects the appropriate adapter using metadata.protocol (lines 90-96 of pipeline.ts), calls adapter.parse() to normalize the request into an AgentContext, and uses adapter.serialize() after injection to produce the final protocol-specific payload. This architecture allows the same injection logic to work across multiple LLM providers without modification.

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 →