Needle's Bounded Memory Mechanism: How the 256-Token Sliding Window Keeps Inference Memory Constant
Needle caps its runtime memory at approximately 28 MiB regardless of conversation length by pinning tool-related KV entries as permanent "sinks" and restricting the attention KV cache to a configurable sliding window of 256 tokens.
The cactus-compute/needle repository implements a bounded memory mechanism that solves a critical problem in long-context LLM inference: unbounded KV cache growth. By combining a fixed-size sliding window with persistent tool memory, Needle delivers predictable memory usage without sacrificing tool access.
How the Sliding Window Works
KV Window Storage in Model Headers
Needle bakes the sliding-window size directly into the .cact model file format. In needle/model/export.py, the kv_window field stores the window size the model was trained with:
# needle/model/export.py#L27-L30
# The header structure includes:
# kv_window: int # sliding window size in tokens (default: 256)
When you load a Needle model, this value is read from the header and used to configure the inference engine. The default 256-token window provides a balance between context retention and memory efficiency.
Runtime Window Budgeting
At inference time, Needle computes the effective KV window by comparing the model's trained window against hardware memory constraints. The kv_budget_window() and effective_kv_window logic in needle/model/architecture.py handles this:
# needle/model/architecture.py#L998-L1016
# Pseudocode of the budgeting logic:
def kv_budget_window():
# Hardware budget: ~11 MiB reserved for KV cache
max_tokens_by_budget = kv_memory_budget // bytes_per_token
return min(max_tokens_by_budget, config.kv_window)
This ensures the actual window never exceeds either the model's trained capacity or the available GPU/TPU memory.
Attention Masking Implementation
The decoder enforces the sliding window through causal masking. In needle/model/decode.py, attention scores are masked so tokens can only attend to:
- The most recent
kv_windowpositions - Permanent tool KV "sinks" that bypass the window limit
# needle/model/decode.py#L81-L108
# The mask construction ensures:
# 1. Standard causal masking within the window
# 2. Full connectivity to pinned tool KV entries
# 3. Zero attention to tokens outside the sliding window
Why Tools Are Pinned as KV Sinks
Tool-calling capability requires random access to tool definitions throughout any conversation. Rather than re-embedding tools repeatedly (expensive) or letting them scroll out of the sliding window (broken), Needle reserves dedicated KV cache slots for tool embeddings.
These KV sinks are:
- Permanent: Never evicted regardless of window position
- Small: Constant overhead independent of conversation length
- Efficient: Embedded once at model load time
The result: tools remain instantly accessible while the conversation history stays bounded.
Configuring the Sliding Window
Inspect an Existing Model
from needle.model.export import read_header
header = read_header("needle2.cact")
print("KV sliding window:", header.kv_window) # → 256
Export a Custom Window Size
from needle.model.architecture import TransformerConfig
from needle.model.export import export
cfg = TransformerConfig(
d_model=1024,
num_heads=8,
num_layers=12,
kv_window=512, # Larger window: more context, more memory
)
export(params, cfg, tokenizer, out_path="wider_needle.cact")
Inference with Bounded Memory
import needle
agent = needle.Needle(
weights="needle2.cact",
tools=[calculator, search_api] # Tool KV sinks allocated at init
)
# Generate indefinitely—memory stays ~28 MiB
for turn in conversation:
response = agent.run(turn)
Memory Characteristics
| Component | Size | Behavior |
|---|---|---|
| Tool KV sinks | ~2 MiB (fixed) | Never evicted |
| Sliding window KV | ~11 MiB (max) | FIFO replacement |
| Activations/parameters | ~15 MiB | Constant |
| Total runtime | ~28 MiB | Independent of sequence length |
Summary
-
Needle's bounded memory mechanism combines a 256-token sliding window with permanent tool KV sinks to achieve constant memory usage.
-
The
kv_windowparameter inneedle/model/export.pystores the trained window size in model headers. -
kv_budget_window()inneedle/model/architecture.pycomputes the runtime-effective window based on hardware constraints. -
needle/model/decode.pyimplements sliding-window attention masking that preserves tool access while limiting history. -
Total inference memory stays near 28 MiB regardless of conversation length, as documented in the repository's README.
Frequently Asked Questions
What happens if a conversation exceeds 256 tokens?
Earlier tokens beyond the window are attended to via KV cache eviction—their keys and values are overwritten. The model retains access to compressed semantic information through the attention mechanism's recurrent patterns, but specific token-level details from distant history are lost. This mirrors how human conversation works: recent context is vivid, distant context is summarized.
Can I increase the sliding window for longer context?
Yes, by setting a larger kv_window in TransformerConfig during export. However, memory grows linearly with window size: doubling to 512 tokens roughly doubles the KV cache from ~11 MiB to ~22 MiB, pushing total runtime memory toward ~40 MiB. The architecture in needle/model/architecture.py#L998-L1016 enforces the hardware budget ceiling automatically.
Why 256 tokens specifically?
The 256-token default balances three factors according to the cactus-compute/needle source: (1) covering most single-turn tool interactions, (2) fitting comfortably within mobile/edge GPU memory budgets, and (3) matching the pretraining distribution where the model learned to operate. The README explicitly calls this out as the design point for "near 28 MB" memory guarantees.
Do pinned tool sinks reduce the available window for conversation?
No, tool KV sinks are allocated separately from the sliding window budget. The ~11 MiB KV cache is reserved for conversation history; tool embeddings live in their own memory region. This design ensures that activating multiple tools never compresses the available context window—a critical invariant maintained by needle/model/decode.py.
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 →