LRU-based intelligent context manager for LLM agents. Keeps hot context, evicts cold.
Project description
๐ฅ hot-context
LRU-based intelligent context manager for LLM agents. Keeps hot context, evicts cold.
Most conversation managers use a naive sliding window โ drop the oldest messages when context fills up. hot-context treats your context window like an intelligent cache: every chunk is scored by relevance, recency, and access frequency, and only the highest-value context survives.
Key Features
- Relevance-aware trimming โ trims tool results to only the lines the LLM actually used, instead of evicting entire entries
- Adaptive token calibration โ learns the real chars-per-token ratio from actual LLM feedback, self-corrects over time
- Entity echo feedback loop โ uses the LLM's own response as a proxy for attention weights, zero extra API calls
- Turn-aware eviction โ never evicts during a turn (LLM needs full context to reason), only trims between turns
- Framework-agnostic core with drop-in adapters for Strands, LangChain, and OpenAI
How It Works
Turn N:
User query โ Tools return data โ LLM sees FULL context โ Answers
โ
Entity echo: what did the LLM use?
Trimmer: keep only relevant lines from tool results
Calibrator: learn real token ratio from Bedrock
โ
Turn N+1:
Context has trimmed tool results (5k instead of 80k) + all assistant answers preserved
Scoring formula (no LLM needed):
score = ฮฑยทsimilarity(chunk, query) + ฮฒยทrecency(chunk) + ฮณยทaccess_frequency(chunk) - ฮดยทsize_penalty(chunk)
- Similarity: Jaccard overlap on extracted entities (BM25-inspired, zero API calls)
- Recency: Exponential decay by turn distance
- Access frequency: Time-decayed count of how often the LLM actually used this chunk
- Size penalty: Large tool results are penalized proportionally to budget
Topic shift detection: When the user changes topics, similarity weight increases and frequency weight decreases โ preventing stale popular chunks from dominating.
Results
Tested against Strands SlidingWindowConversationManager on a real multi-turn agent with MCP tools (SQL queries, knowledge base lookups):
| Metric | SlidingWindow | hot-context |
|---|---|---|
| Q3 (heavy query) | CRASHED โ context overflow | โ Answered (2831 chars) |
| Peak context Q2 | Unbounded (168k+) | 105k (trimmed) |
| Peak context Q3 | Overflow (>200k) | 113k (controlled) |
| Queries completed | 2.5 of 3 | 3 of 3 |
Peak context went DOWN from Q1โQ2 (128kโ105k) โ the trimmer removed irrelevant lines from Q1's tool result.
Quick Start
Strands (drop-in replacement)
from strands import Agent
from strands.models.bedrock import BedrockModel
from hot_context.adapters.strands import StrandsHotContextManager
from hot_context import ScoringWeights
agent = Agent(
model=BedrockModel(model_id="us.anthropic.claude-sonnet-4-5-20250929-v1:0"),
conversation_manager=StrandsHotContextManager(
token_budget=100_000,
weights=ScoringWeights.tool_agent(),
),
)
Framework-agnostic core
from hot_context import HotContextManager, ScoringWeights
manager = HotContextManager(
token_budget=100_000,
weights=ScoringWeights.tool_agent(),
pin_last_n=2,
)
# Before each query
manager.on_query(user_input)
# After LLM responds
manager.on_response(str(result))
Adaptive calibration (Strands)
# Token estimator self-calibrates from actual Bedrock token counts.
# After each LLM call, feed back the reported input_tokens:
cm = agent.conversation_manager
cm.calibrate(agent.messages, actual_input_tokens=87450)
# Future estimates are now more accurate โ no manual tuning needed.
Weight Presets
ScoringWeights.tool_agent() # high similarity โ for agents with many tool calls
ScoringWeights.conversational() # high recency + frequency โ for multi-turn chat
ScoringWeights.research() # high similarity + frequency โ for RAG/research agents
Custom Entity Patterns
import re
from hot_context import HotContextManager
manager = HotContextManager(
extra_patterns=[
("order_id", re.compile(r"\b\d{3}-\d{7}-\d{7}\b")),
("asin", re.compile(r"\bB[A-Z0-9]{9}\b")),
]
)
Architecture
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ HotContextManager โ
โ โ
โ TokenEstimator โโโ EntityExtractor โโโ ContextScorer โ
โ โ โ โ
โ calibrate() score + rank โ
โ (from LLM) โ โ
โ โ โ
โ Trimmer โโโ FeedbackLoop โโโ LLM Response โโโ Evictor โ
โ (line-level (entity echo) (entry-level) โ
โ relevance) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Adapters: Strands | LangChain | OpenAI
Why Not Just Summarize?
| Approach | Token cost | Latency | Quality |
|---|---|---|---|
| Sliding window | Free | None | Poor โ drops relevant old context |
| LLM summarization | High | +500ms/turn | Good โ but expensive at scale |
| hot-context | Free | ~1ms/turn | Good โ keeps what matters, trims what doesn't |
Roadmap
P2 โ Benchmarks & Paper
- Benchmark harness โ synthetic multi-turn conversations with known answers. Measure token savings + answer quality (ROUGE/BERTScore on trimmed vs full context).
- Standard benchmarks โ LongBench, SCROLLS, QuALITY, NarrativeQA for long-context evaluation.
- Ablation studies โ trimmer-only vs scorer-only vs full pipeline vs baselines (MemGPT, LLMLingua, attention sink).
- Token savings curves โ plot peak context vs conversation length across strategies.
Components
| File | Purpose |
|---|---|
manager.py |
Core orchestrator: on_query() โ score + evict, on_response() โ feedback |
scorer.py |
Scoring formula with topic shift detection and pluggable similarity |
token_estimator.py |
Adaptive chars-per-token calibration from real LLM feedback |
trimmer.py |
Line-level relevance trimming of tool results |
chunker.py |
Smart chunking respecting tool-use/tool-result pairing |
entity_extractor.py |
Regex-based entity extraction (dates, IDs, numbers, custom patterns) |
feedback.py |
Entity echo feedback loop โ updates access logs from LLM response |
types.py |
ContextEntry, AccessRecord, ScoringWeights with presets |
adapters/strands.py |
Drop-in ConversationManager for Strands agents |
adapters/langchain.py |
BaseChatMemory adapter for LangChain |
adapters/openai.py |
Message list manager for OpenAI Chat API |
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file hot_context-0.1.0.tar.gz.
File metadata
- Download URL: hot_context-0.1.0.tar.gz
- Upload date:
- Size: 60.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.8.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
60c22c4601d11547bcaa264f91a96ced30375051f0728c767373c9c5c1edcbf1
|
|
| MD5 |
ccee5dbe05c9a930fb3190ff0f65a53c
|
|
| BLAKE2b-256 |
a8437e2b38d6724e81cc1e9444eedd489aaf1990bbab7ebaec605ceca7cd9244
|
File details
Details for the file hot_context-0.1.0-py3-none-any.whl.
File metadata
- Download URL: hot_context-0.1.0-py3-none-any.whl
- Upload date:
- Size: 25.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.8.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9f45d932873f661d9d17171ea504403473f8d27b708c52e67d1f75aa2d2c7bd7
|
|
| MD5 |
217db935b84dde69092ce6d474e54ce4
|
|
| BLAKE2b-256 |
63349e0cc742e2a117be0011d1f4843ebbe8a3b47279ecd4979c94c8af08dd23
|