ContextSage
ContextSage is an intelligent, production-grade replacement for
LangGraph's built-in SummarizationMiddleware. It adds an information-aware
planning layer on top of LangGraph/LangChain's existing summarization
mechanism, so that when an agent's context grows too large, ContextSage
decides what should be preserved, compressed, or left untouched — instead
of blindly summarizing "the oldest messages first".
from langchain.agents import create_agent
from contextsage import IntelligentSummarizationMiddleware
middleware = IntelligentSummarizationMiddleware(
model=model,
trigger=("tokens", 100_000),
keep=("messages", 20),
)
agent = create_agent(
model=model,
tools=tools,
middleware=[middleware],
)
That's it. Everything else — context decomposition, importance scoring, preservation requirements, provenance tracking, validation, and recovery — happens automatically inside the middleware.
Why ContextSage?
Modern agents accumulate heterogeneous context: natural language, JSON,
logs, stack traces, tool metadata, tables, and code, often mixed together in
a single large tool result. LangGraph's SummarizationMiddleware is a solid,
general-purpose building block, but it does not:
- distinguish between critical and disposable information,
- protect user corrections and active constraints from being lost,
- deterministically compress structured/log content instead of paying for an LLM call on data an LLM doesn't need to read,
- validate that a summary didn't silently drop something important,
- recover gracefully if summarization fails or a summary is invalid.
ContextSage adds exactly this intelligence layer, while reusing — not reimplementing or forking — LangGraph's own semantic summarization for the parts only an LLM can do well.
Principle
Information preservation > raw token reduction.
A smaller summary that loses a customer ID, a user correction, or a root cause is a failure, even if it saves tokens. ContextSage's planner is budget-aware and information-aware.
Installation
pip install contextsage
langgraph-xai is installed automatically as a direct dependency and used
internally for provenance/evidence tracking — no separate setup required.
Authoritative OpenAI-compatible token counting via tiktoken, and real
code-structure detection via tree-sitter, are also core dependencies —
no optional extras to install for ContextSage's default behavior.
How it works
Complete context
|
v
Heterogeneous context decomposition -> Context units
|
v
Structural signals -> Importance -> Relationships / Provenance
|
v
Preservation requirements -> Summarization plan
|
v
Selective deterministic transformation
|
v
LangGraph semantic summarization (reused, not forked)
|
v
Validation -> Recovery (if needed) -> Reconstruction
See docs/architecture.md for the full design and docs/ for component-level documentation.
Examples
Runnable examples live in examples/ and call a real,
network-backed chat model (via examples/_llm.py) so
their output reflects genuine model behavior rather than a scripted fake.
Install the examples extra, then copy .env.example to .env and set
EXPLABS_API_KEY:
pip install -e ".[examples]"
cp .env.example .env # then fill in EXPLABS_API_KEY
python examples/basic.py
| Example | Demonstrates |
|---|---|
| basic | The minimal end-to-end quickstart. |
| large_tool_output | A single large mixed JSON+log ToolMessage with a preserved transaction ID and root cause. |
| mixed_mcp_output | Heterogeneous MCP-style tool output (text + JSON + logs) in one message. |
| logs | Log-heavy content with trace ID and root-cause preservation. |
| rag | Contradiction-preserving behavior across conflicting retrieval sources. |
| structured_data | JSON/structured-data preservation across multiple tool results. |
| recovery | Graceful fallback when the summarization LLM call itself fails (uses an intentionally-failing model, not the real one). |
| policy | How policy="maximum_preservation" | "balanced" | "maximum_compression" changes preservation outcomes (no model call). |
| all_parameters | Every IntelligentSummarizationMiddleware constructor parameter set to an explicit non-default value, each one's effect independently verified (budget math, parsers, token_counter, observability_hook, provenance/lineage, summary_prompt/trim_tokens_to_summarize, ...). |
| sql_parser | A custom SQLContentParser (parsers=[...]) built on the production-grade sqlglot package — demonstrates the parsers extension point classifying, isolating, and preserving SQL content, plus overriding its own keyword_pattern/dialect rules, without any SQL dependency forced into core. |
| agent_create_agent | langchain.agents.create_agent running a real compiled LangGraph agent, with the middleware triggering mid-run inside the agent's own loop. |
| deep_agent | deepagents.create_deep_agent — the middleware plugs into a deep agent's own (larger) graph the same way. |
| swarm | langgraph_swarm.create_swarm — a two-agent swarm with a real handoff tool; the middleware is attached to only one specialist agent and runs across checkpointed multi-turn state. Requires the deepagents/langgraph-swarm extras (installed with examples). |
What ContextSage is not
- Not an agent framework, memory framework, or a replacement for LangGraph/LangChain.
- Not a general-purpose parser/document-processing framework.
- Not a new plugin platform — there is no public plugin registry.
ContextSage stays narrowly focused on one job: intelligent context summarization for LangGraph/LangChain agents.
Contributing
See CONTRIBUTING.md for development setup and pull request guidelines. This project follows the Code of Conduct. For security issues, see SECURITY.md instead of opening a public issue.
License
Apache License 2.0. See LICENSE.
Release files for contextsage 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| contextsage-0.1.0.tar.gz | 305.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| contextsage-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 379.2 kB
Release files / contextsage-0.1.0.tar.gz
| Download URL | contextsage-0.1.0.tar.gz |
|---|---|
| Size | 305.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
43355b80755351c0aa6b9d946e6f3f03aaff62fe8f36882e159d359d1460b90c
|
|
BLAKE2b-256 checksum How to use checksums |
1a1aa7e9bc44f8373cf8f08f7c716399986532f83433b584c61eae973fac846c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.15 {"installer":{"name":"uv","version":"0.12.15","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / contextsage-0.1.0-py3-none-any.whl
| Download URL | contextsage-0.1.0-py3-none-any.whl |
|---|---|
| Size | 74.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
52e9ba214b5e0c657ae43505a2b00107f8602bd52d708cda4ef21a2bda972645
|
|
BLAKE2b-256 checksum How to use checksums |
da68fba375221a422d9942afe79f1a6aed53ee4e0688ad17e8772bb5e89fd8dc
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.12.15 {"installer":{"name":"uv","version":"0.12.15","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|