How Anchor-Based Landing Ensures Precise Injection into System Prompts
Anchor-based landing resolves semantic slots against an AgentProfile to rebuild system messages at exact structural locations, falling back to point-based injection when anchors cannot be resolved.
The Memory Proxy component in TencentCloud/TencentDB-Agent-Memory manages the dynamic assembly of LLM system prompts by injecting skills, Wiki pages, and custom tools. Through anchor-based landing, the system achieves surgical precision in content placement, ensuring that injected blocks land exactly where the agent’s prompt structure expects them—such as inside a specific "Memory" or "Skills" section.
The Architecture of Anchor-Based Injection
The injection pipeline in MemoryProxy/src/injection/pipeline.ts implements a two-step resolution process that bridges portable semantic tags with concrete prompt structures.
Defining Anchor Targets
Each InjectionHook may declare an optional anchor property that specifies exactly where content should land. The AnchorTarget interface, defined in MemoryProxy/src/injection/types.ts, supports both portable semantic slots and concrete structural keys:
export interface AnchorTarget {
slot?: SemanticSlot; // portable tag such as "memory", "skills", …
rawKey?: string; // concrete heading/key used as an escape hatch
relation: AnchorRelation; // before / after / inside_prepend / inside_append
}
This dual-key design allows developers to reference abstract content categories (like "skills") that resolve differently per agent, or pin injections to literal headings (like "## Memory") when portability is not required.
The Resolution Pipeline
When applyInjection processes a hook, it first attempts to resolve the anchor against the current request’s AgentProfile. According to the source code at lines 56–58 in MemoryProxy/src/injection/pipeline.ts:
const key = hook.anchor.rawKey
?? (hook.anchor.slot ? profile.resolveSlot(hook.anchor.slot) : null);
The profile.resolveSlot method translates portable semantic tags into agent-specific headings. For example, the slot "skills" might resolve to "## Skills" for one agent profile but "### Tooling" for another, enabling the same injector to work across diverse agent configurations.
Segment Validation and Prompt Reconstruction
Once the target key is resolved, the pipeline validates existence within the current system message and performs surgical insertion.
Parsing and Matching Segments
The current system text is parsed into discrete segments using profile.parse(currentText). The pipeline checks whether any segment’s key matches the resolved anchor key. If found, the injection proceeds using the specified AnchorRelation (before, after, inside_prepend, or inside_append).
As implemented in applyInjection at lines 60–68:
const newSegments = profile.applyAnchor(
segments,
{ key, relation: hook.anchor.relation },
text,
);
sysMsg.blocks = [{ type: "text", content: profile.rebuild(newSegments) }];
The profile.applyAnchor method inserts the new content at the specified relation, and profile.rebuild reconstructs the system prompt with the injected block preserving all surrounding context and formatting.
Fallback Strategy for Missing Anchors
When anchor resolution fails—due to missing profiles, undefined slots, or absent raw keys—the system degrades gracefully to maintain functionality.
Point-Based Fallback
If the anchor cannot be resolved, the pipeline emits a diagnostic warning and delegates to applyByPoint, which inserts the block at coarse-grained locations such as system.prefix, system.suffix, or system.before_tools. From lines 71–76 in MemoryProxy/src/injection/pipeline.ts:
console.warn(`[injection] anchor slot "${hook.anchor.slot ?? hook.anchor.rawKey}" unresolved …`);
this.applyByPoint(ctx, point, blocks);
This fallback mechanism ensures that injectors remain functional across agents that may not implement the expected profile structure, preserving backward compatibility while encouraging migration to structured profiles.
Practical Implementation Examples
Example 1: Semantic Slot Injection
The following hook uses a portable slot to inject skill documentation before the skills section:
export const skillInjector: InjectionHook = {
id: "skill-injector",
point: "system.suffix", // fallback point
anchor: { slot: "skills", relation: "before" },
priority: HOOK_PRIORITY.SKILL,
description: "Inject custom skill blocks",
async execute(ctx) {
return [{ type: "text", content: "## CustomSkill\nUse this whenever …" }];
},
};
hookRegistry.register(skillInjector);
When the request matches an agent profile containing a "## Skills" heading (or whatever the profile maps the "skills" slot to), the injection appears immediately before that section. If the profile lacks the heading, the block appends to the system prompt suffix.
Example 2: Raw Key Targeting
For non-portable, exact placement requirements, use rawKey to bypass slot resolution:
const rawKeyInjector: InjectionHook = {
id: "rawkey-injector",
point: "system.suffix",
anchor: { rawKey: "## Memory", relation: "inside_append" },
priority: HOOK_PRIORITY.MEMORY,
description: "Append extra memory description",
async execute() {
return [{ type: "text", content: "Additional context for the Memory section." }];
},
};
Here rawKey pins the injection to the literal heading "## Memory", appending content inside that section regardless of the agent’s profile slot mappings.
Summary
- Anchor-based landing uses
AnchorTargetdeclarations to specify exact insertion points within system prompts via semantic slots or raw keys. - The resolution pipeline in
applyInjectiontranslates portable slots to concrete headings usingprofile.resolveSlot, then validates and inserts content usingprofile.applyAnchor. - The system rebuilds the complete prompt with
profile.rebuildafter injection, preserving surrounding context and formatting integrity. - When anchors cannot be resolved, the pipeline falls back to point-based injection at
system.prefix,system.suffix, orsystem.before_toolsto maintain compatibility. - Concrete implementations can be found in
MemoryProxy/src/injection/injectors/skill-injector.tsandtdai-profile-memory-injector.tson thefeat/server_teambranch.
Frequently Asked Questions
What is the difference between anchor-based and point-based injection in TencentDB-Agent-Memory?
Anchor-based injection targets specific structural locations within the system prompt (like sections or headings) using semantic slots or raw keys, while point-based injection operates at coarse-grained positions such as system.prefix or system.suffix without knowledge of the prompt’s internal structure. Anchor-based landing provides precise control but requires an AgentProfile to resolve slot mappings.
How does the system handle missing anchors or unresolved slots?
When an anchor cannot be resolved—either because the profile is missing, the slot is undefined, or the rawKey is absent—the pipeline logs a warning and automatically falls back to point-based injection using the hook’s declared point property. This ensures that content is still injected into the system prompt even when precise placement is impossible.
What anchor relations are supported for positioning injected content?
The AnchorRelation type supports four positioning strategies: before (insert immediately before the target segment), after (insert immediately after), inside_prepend (insert at the beginning of the target section), and inside_append (insert at the end of the target section). These relations are defined in MemoryProxy/src/injection/types.ts.
Where is the core injection logic implemented in the repository?
The core injection orchestration resides in MemoryProxy/src/injection/pipeline.ts, specifically within the applyInjection method (lines 56–76 on the feat/server_team branch). Type definitions including AnchorTarget, AnchorRelation, and InjectionHook are located in MemoryProxy/src/injection/types.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 →