# How MemoryProxy Injects Team Memory and Skills into LLM Requests

> Learn how MemoryProxy injects team memory and skills into LLM requests. Discover how it uses injectors and HTTP headers to enable LLM access to team resources securely.

- Repository: [Tencent Cloud/TencentDB-Agent-Memory](https://github.com/TencentCloud/TencentDB-Agent-Memory)
- Tags: deep-dive
- Published: 2026-08-22

---

**TLDR: MemoryProxy injects team memory and skills into LLM requests by rendering static curl-based tool specification blocks into the system prompt via two dedicated injectors — `TdaiMemoryToolsInjector` and `SkillToolsInjector` — which embed session identity as HTTP headers so the LLM can call team-wide resources without ever seeing or forging secrets.**

In the TencentCloud/TencentDB-Agent-Memory repository, MemoryProxy acts as a secure gateway between an LLM and shared team assets. Every LLM turn is enriched with tool definitions that let the model search memory and manage skills, while identity is handled automatically through HTTP headers. This article breaks down the exact injection mechanism, the source files that implement it, and how the whole pipeline protects your data.

## The Two Injection Hooks

MemoryProxy uses two dedicated injection hooks to enrich every LLM turn with static, session-stable tool specifications. Both operate at the system prompt level, keeping the model's visible context clean and free of any sensitive identity information.

| Hook | What it injects | Where it is inserted | How identity is added |
|------|----------------|----------------------|-----------------------|
| **`TdaiMemoryToolsInjector`** | A `<tdai_memory_tools>` block describing read-only TDAI memory endpoints (search, query, conversation-search) | `system.suffix` (the very end of the system prompt) | Calls `getTdaiIdentity(ctx.metadata.custom)` to obtain the current **team_id**, **user_id**, **agent_id**, and **session_id**, then adds `x-tdai-service-id` and `x-conversation-id` headers to every curl recipe |
| **`SkillToolsInjector`** | A `<skill_tools>` block describing cloud-skill CRUD and read-only operations (search, view, files-read, extract) | `system.before_tools` (just before the `<available_skills>` block) | Uses the same session metadata to build the `x-tdai-service-id` and `x-conversation-id` headers, guaranteeing the LLM's curl calls are signed with the correct team/user/agent context |

Both injectors are **static** — the block content depends only on the proxy base URL and the session's identity. They are rendered once at `session_init` (via `cacheStrategy: "session_init"`), then cached for the whole session, which makes them cheap and cache-friendly.

## How the Injection Works Internally

The injection pipeline flows through five steps, each orchestrated by the memory proxy core:

1. **Session metadata is attached to every request** by the core gateway. The metadata contains a `custom` object holding the current session's `team_id`, `user_id`, `agent_id`, `session_id`, and the tenant's `space_id`.

2. **Pre-warm step**: When a new session is created, the proxy runs the `prewarm(input)` method of each injector. The `TdaiMemoryToolsInjector.prewarm` receives `sessionInfo.session_id` and `sessionInfo.space_id` and calls `renderTdaiMemoryToolsBlock` to produce the full text block. The `SkillToolsInjector.prewarm` does the same for the skill block, optionally toggling write capabilities via `allowLlmWrite`.

3. **Caching**: The rendered block is wrapped in a `ContextBlock` with a stable `cacheKey` — either `tdai-memory-tools-injector:tools` or `skill-tools-injector:catalog:ro/rw`.

4. **Attachment**: The injection engine (registered in [`src/injection/index.ts`](https://github.com/TencentCloud/TencentDB-Agent-Memory/blob/main/src/injection/index.ts)) attaches the block to the appropriate point in the system prompt. Because the block lives inside the *system* prompt, the LLM never sees the raw identity headers — it only sees the curl recipes.

5. **Request interception**: When the LLM issues a curl command that hits a memory or skill endpoint, MemoryProxy intercepts the request, reads the `x-tdai-service-id` and `x-conversation-id` headers that are baked into the curl recipe, and injects the real **team-wide IdFields** (`team_id`, `user_id`, `agent_id`) into the upstream core request. This guarantees that the LLM cannot forge identities and that the token never appears in the prompt.

## Configuring the Proxy Base URL

The first step is configuring where MemoryProxy points when forwarding requests to the core gateway. The configuration is done in [`memory-proxy/config.example.yaml`](https://github.com/TencentCloud/TencentDB-Agent-Memory/blob/main/memory-proxy/config.example.yaml):

```yaml
proxyBaseUrl: "http://127.0.0.1:8096"
allowLlmWrite: false   # optional, controls skill write tools

```

The `allowLlmWrite` flag determines whether the `SkillToolsInjector` renders write-capable curl recipes (like `skill_create`) or only read-only ones (like `skill_search`).

## Rendering the Memory Tools Block

The `TdaiMemoryToolsInjector` calls `renderTdaiMemoryToolsBlock` to generate the memory specification. In TypeScript, you can see the full process:

```ts
import { renderTdaiMemoryToolsBlock } from "./injection/injectors/tdai-tools-injector";

const block = renderTdaiMemoryToolsBlock(
  "http://127.0.0.1:8096",   // proxyBaseUrl
  "conv-12345",              // sessionId (x-conversation-id)
  "space-abc"                // spaceId (x-tdai-service-id)
);
console.log(block);

```

The resulting block looks something like this:

```text
<tdai_memory_tools>
**这些是你可以主动调用的记忆能力**（不是文档），通过 Bash + curl 使用。
...
<tool name="tdai_memory_search">
    curl: http://127.0.0.1:8096/memory-bridge/v3/atomic/search
    body: {"query": "<text>", "limit": 5}
    use:  搜索 L1 原子记忆…
</tool>
…
</tdai_memory_tools>

```

Because each tool recipe includes the `curl` command and expected body format, the LLM can immediately execute searches against the team memory without knowing anything about the underlying authentication mechanism.

## Rendering the Skill Tools Block

The `SkillToolsInjector` uses `renderSkillToolsBlock` to build the skill catalog. This block is more complex because it conditionally includes write operations based on the `allowLlmWrite` flag:

```ts
import { renderSkillToolsBlock } from "./injection/injectors/skill-tools-injector";

const block = renderSkillToolsBlock(
  "http://127.0.0.1:8096",
  true,                     // allowLlmWrite – inject write tools
  "conv-12345",
  "space-abc"
);
console.log(block);

```

When write mode is enabled, the output includes CRUD recipes like:

```text
<skill_tools>
...
<tool name="skill_search">
    path: http://127.0.0.1:8096/skill-bridge/v3/skill/search
    body: {"query": "…"}
...
<tool name="skill_create">
    path: http://127.0.0.1:8096/skill-bridge/v3/skill/create
    body: {"name":"…","content":"…"}
...
</skill_tools>

```

The search tool is always present. The create/update/delete tools only appear when `allowLlmWrite: true`.

## Example: LLM Calling a Memory Endpoint

Once the system prompt contains the injected blocks, the workflow looks like this. Inside its reasoning, the LLM emits a curl command to call the memory bridge:

```bash
curl -sfk -X POST http://127.0.0.1:8096/memory-bridge/v3/atomic/search \
  -H 'Content-Type: application/json' \
  -H 'x-tdai-service-id: space-abc' \
  -H 'x-conversation-id: conv-12345' \
  -d '{"query":"用户偏好的编程语言","limit":5}'

```

MemoryProxy receives this request, validates the injected headers, and forwards it to the core gateway. The upstream service automatically inserts the **team_id**, **user_id**, and **agent_id** that belong to the conversation. The LLM never sees those values — it only sees the curl command with the two headers that act as opaque identifiers. This design ensures authentication and authorization happen at coordinates where the protocol does not force the LLM to handle secrets.

## Key Source Files

| File (GitHub link) | Role |
|--------------------|------|
| [`MemoryProxy/src/injection/injectors/tdai-tools-injector.ts`](https://github.com/TencentCloud/TencentDB-Agent-Memory/blob/main/MemoryProxy/src/injection/injectors/tdai-tools-injector.ts) | Implements the `<tdai_memory_tools>` injector that adds team-wide memory curl recipes |
| [`MemoryProxy/src/injection/injectors/skill-tools-injector.ts`](https://github.com/TencentCloud/TencentDB-Agent-Memory/blob/main/MemoryProxy/src/injection/injectors/skill-tools-injector.ts) | Implements the `<skill_tools>` injector that adds skill-related curl recipes |
| [`MemoryProxy/src/injection/index.ts`](https://github.com/TencentCloud/TencentDB-Agent-Memory/blob/main/MemoryProxy/src/injection/index.ts) | Registers the injectors and wires them to the correct system-prompt insertion points (`system.suffix` and `system.before_tools`) |
| [`MemoryProxy/src/types.ts`](https://github.com/TencentCloud/TencentDB-Agent-Memory/blob/main/MemoryProxy/src/types.ts) | Defines `AgentContext`, `CacheStrategy`, `HookPriority` and the `getTdaiIdentity` helper used by the injectors |
| [`MemoryProxy/src/tdai/identity.ts`](https://github.com/TencentCloud/TencentDB-Agent-Memory/blob/main/MemoryProxy/src/tdai/identity.ts) | Extracts `team_id`, `user_id`, `agent_id`, and `session_id` from the session metadata |
| [`MemoryProxy/src/workbuddyHandler.ts`](https://github.com/TencentCloud/TencentDB-Agent-Memory/blob/main/MemoryProxy/src/workbuddyHandler.ts) | The main request handler that receives the LLM's curl calls, validates the injected headers, and forwards the request to core services |

## Summary

- **MemoryProxy uses a static injection model**: both the memory and skill tool blocks are rendered once per session and cached, so the per-query overhead is close to zero.

- **Identity is transmitted via headers, not the prompt**: curl recipes contain `x-tdai-service-id` and `x-conversation-id`, and a dedicated code path back-fills the real `team_id`, `user_id`, and `agent_id` upstream.

- **Write access is optional**: the `allowLlmWrite` config flag controls whether the skill catalog exposes mutating operations, giving you granular control over what the LLM may change.

- **All wiring is centralized in [`src/injection/index.ts`](https://github.com/TencentCloud/TencentDB-Agent-Memory/blob/main/src/injection/index.ts)**, respecting the `AgentContext` types that define the interface between the gateway and the injection engine.

## Frequently Asked Questions

### What exactly does the `TdaiMemoryToolsInjector` inject?

The `TdaiMemoryToolsInjector` injects a `<tdai_memory_tools>` block at the end of the system prompt (`system.suffix`). The block contains curl recipes for read-only memory endpoints like `tdai_memory_search`, letting the LLM query team-wide atomistic memory during conversation. Each recipe includes the required HTTP headers for identity, so the model simply executes the curl command.

### Does the LLM ever see the real team or user credentials?

No. The system prompt only contains curl recipes with the session identifier headers (`x-tdai-service-id` and `x-conversation-id`). Actual authentication tokens and the full `team_id`/`user_id`/`agent_id` triple are injected downstream by MemoryProxy in [`workbuddyHandler.ts`](https://github.com/TencentCloud/TencentDB-Agent-Memory/blob/main/workbuddyHandler.ts), only after the LLM emits a curl call.

### How does the `SkillToolsInjector` decide whether to include write operations?

The `renderSkillToolsBlock` function receives an `allowLlmWrite` boolean. When `true`, it injects CRUD operations like `skill_create`, `skill_update`, and `skill_delete`. When `false`, it only emits read-only tools such as `skill_search` and `skill_files_read`. This flag is controlled via the `allowLlmWrite` setting in the config file.

### Why are the injected blocks cached at `session_init`?

Because the block content depends only on the proxy base URL and session identity — which are stable for the entire session. Rendering once and caching with a stable `cacheKey` avoids repeated string-building overhead on every LLM call, keeping the proxy efficient even under heavy load.