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

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, the base prompt represents the static text loaded from files such as 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 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. 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) handles the concatenation logic with strict safeguards to preserve cache stability:

// 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. 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

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

// 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

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 handles concatenation while preserving byte-for-byte stability when memory is empty.
  • Tool schemas are rendered from internal/tool/registry.go and remain fixed per session, ensuring the prefix does not shift unexpectedly.
  • The boot process in 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, 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, typically reading from a file named REASONIX.md. This file provides the static instructions that form the first line of every LLM request.

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 →