# How the Cache-Stable System Prompt Is Composed in DeepSeek-Reasonix: Base, Tools, and Memory Layers

> Discover how DeepSeek-Reasonix builds its cache-stable system prompt by combining base, tools, and memory layers for consistent AI responses. Learn more about its composition.

- Repository: [YHH/DeepSeek-Reasonix](https://github.com/esengine/DeepSeek-Reasonix)
- Tags: internals
- Published: 2026-06-22

---

**The cache-stable system prompt in DeepSeek-Reasonix is assembled by concatenating the static base prompt, a markdown tool block rendered from registered schemas, and a deterministic memory block, ensuring immutable prefixes across conversation turns unless explicitly modified.**

In the DeepSeek-Reasonix repository, the system prompt serves as the immutable prefix sent to the LLM on every request. Maintaining a cache-stable system prompt is critical for performance and consistency, as it prevents unnecessary cache invalidation across conversation turns. The composition process combines three distinct layers—base prompt, tool schemas, and session memory—into a deterministic string that remains unchanged unless the user explicitly modifies one of its components.

## The Three-Layer Architecture of the Cache-Stable System Prompt

### Base Prompt Layer

Located in [`internal/config/system_prompt.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/config/system_prompt.go), the base prompt represents the static text loaded from files such as [`REASONIX.md`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/REASONIX.md). This layer forms the first line of the final prompt and never moves position. It provides the core instructions and personality definition for the LLM interaction, remaining constant throughout the session unless manually edited.

### Tool Block Layer

The tool block is generated by walking registered tools in [`internal/tool/registry.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/tool/registry.go) during the boot process. Each tool's schema—including `name`, `description`, `input`, and `output` parameters—is rendered into markdown under a `# Tools` header. Because the tool set is fixed for a given session, this block remains cache-stable and is appended directly after the base prompt.

### Memory Block Layer

Session-specific context comes from the memory block, generated by the `(*memory.Set).Block()` method in [`internal/memory/memory.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/memory/memory.go). This deterministic markdown rendering includes project-level documents, user-level documents, and the auto-memory index. The block appears last in the prompt sequence, providing contextual data without destabilizing the cache prefix.

## How the Compose Function Ensures Cache Stability

The `memory.Compose` function (lines 56-68 in [`internal/memory/memory.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/memory/memory.go)) handles the concatenation logic with strict safeguards to preserve cache stability:

```go
// internal/memory/memory.go
func Compose(base string, s *Set) string {
    block := s.Block()
    if block == "" {
        return base               // no memory → keep base unchanged
    }
    if strings.TrimSpace(base) == "" {
        return block               // rare case: no base prompt
    }
    return strings.TrimRight(base, "\n") + "\n\n" + block
}

```

This implementation guarantees that if the memory block is empty, the function returns the base prompt unchanged, maintaining the exact byte-for-byte cache key. The function also handles edge cases where the base prompt might be empty, ensuring robust composition regardless of input state.

## Boot-Time Orchestration

The final assembly occurs during system initialization in [`internal/boot/boot.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/boot/boot.go). The boot process loads the base prompt, appends the rendered tool block, and invokes `memory.Compose` to fold in the memory layer. This produces the final structure:

```

<base prompt>
<optional output-style modifications>

# Tools

…tool-1 schema…
…tool-2 schema…

# Memory

…project & user docs…
…saved index…

```

## Practical Implementation Examples

### Building the Prompt from Custom Base and Memory

```go
import (
    "github.com/esengine/DeepSeek-Reasonix/internal/config"
    "github.com/esengine/DeepSeek-Reasonix/internal/memory"
)

func BuildPrompt() (string, error) {
    // Load the static base prompt (e.g. from REASONIX.md)
    base, err := config.LoadBasePrompt()
    if err != nil {
        return "", err
    }

    // Discover the memory for the current session
    mem := memory.Load(memory.Options{
        CWD:     ".",           // project directory
        UserDir: config.MemoryUserDir(),
    })

    // Compose the stable prompt
    return memory.Compose(base, mem), nil
}

```

### Adding a New Tool to the Cache-Stable Prefix

```go
// Register a new tool (this happens at boot time)
tool.Register(tool.Tool{
    Name:        "search_web",
    Description: "Search the web and return the top‑3 URLs",
    Input:       []tool.Param{{Name: "query", Type: "string"}},
    Output:      []tool.Param{{Name: "results", Type: "[]string"}},
})

// The boot process now renders the tool block.
// When the system prompt is later composed, the new tool schema will
// automatically become part of the cache‑stable prefix.

```

### Verifying Cache Stability Across Turns

```go
prompt1, _ := BuildPrompt()
prompt2, _ := BuildPrompt()
if prompt1 != prompt2 {
    // This should never happen unless the user edited the base prompt,
    // added/removed a tool, or changed a memory document.
    log.Fatalf("system prompt changed between turns")
}

```

## Summary

- The cache-stable system prompt in DeepSeek-Reasonix consists of three immutable layers: base prompt, tool block, and memory block.
- The `memory.Compose` function in [`internal/memory/memory.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/memory/memory.go) handles concatenation while preserving byte-for-byte stability when memory is empty.
- Tool schemas are rendered from [`internal/tool/registry.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/tool/registry.go) and remain fixed per session, ensuring the prefix does not shift unexpectedly.
- The boot process in [`internal/boot/boot.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/boot/boot.go) orchestrates the final assembly, maintaining strict ordering: base first, tools second, memory last.

## Frequently Asked Questions

### What happens if the memory block is empty?

When the memory block contains no documents, the `Compose` function returns the base prompt unchanged, preserving the exact cache key. This optimization prevents unnecessary cache invalidation when no session context has been accumulated.

### Why is the tool block placed before the memory block?

The tool block precedes the memory block to ensure the LLM understands available actions before receiving project-specific context. This ordering prevents the model from hallucinating tool usage before seeing valid tool schemas, while both blocks remain deterministic and cache-stable for the session duration.

### How does the system maintain cache stability across conversation turns?

Cache stability is maintained by treating the base prompt and tool set as immutable after initialization. Only explicit user edits to [`REASONIX.md`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/REASONIX.md), tool registration changes, or memory document updates modify the prefix. The `Compose` function's empty-block check ensures that transient memory states do not alter the cache key.

### Where is the base prompt loaded from in the DeepSeek-Reasonix source code?

The base prompt is loaded in [`internal/config/system_prompt.go`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/internal/config/system_prompt.go), typically reading from a file named [`REASONIX.md`](https://github.com/esengine/DeepSeek-Reasonix/blob/main/REASONIX.md). This file provides the static instructions that form the first line of every LLM request.