Quickstart¶
Add ContextSage to an agent¶
IntelligentSummarizationMiddleware is agent middleware. Add it to
create_agent wherever you would use LangChain's SummarizationMiddleware:
from langchain.agents import create_agent
from langchain_core.tools import tool
from contextsage import IntelligentSummarizationMiddleware
@tool
def order_status(order_id: str) -> str:
"""Return the status of an order."""
return f"{order_id}: shipped"
agent = create_agent(
model="openai:gpt-5",
tools=[order_status],
middleware=[
IntelligentSummarizationMiddleware(
model="openai:gpt-5-mini",
trigger=("tokens", 100_000),
keep=("messages", 20),
)
],
)
modelwrites the summaries. It can differ from the agent's model.triggerdecides when to summarize: here, once the history reaches 100,000 tokens. Leave it out to summarize only when the history no longer fits the model's context window.keepis how much recent history stays verbatim: here, the last 20 messages. Older messages are replaced by the summary.
Everything else has production defaults; see Configuration.
Watch it work¶
The quickstart example runs an agent on a history whose large incident report pushes it past the trigger. It uses scripted models, so it runs offline and always prints the same output:
"""Add ContextSage to a LangChain agent and watch it summarize a long history.
Run: python examples/quickstart.py
The agent starts from a history whose large tool result pushes it past the
trigger. Before the next model call, ContextSage compacts the repetitive log
and JSON in that result, LangChain writes the summary, and ContextSage checks
that the incident and transaction IDs survived.
"""
import json
from langchain.agents import create_agent
from langchain_core.messages import AIMessage, HumanMessage, ToolMessage
from _models import first_line, scripted_model
from contextsage import IntelligentSummarizationMiddleware, SummarizationEvent
events: list[SummarizationEvent] = []
middleware = IntelligentSummarizationMiddleware(
model=scripted_model(
"The payments outage INC-9931 was traced to transaction TX-991 and a "
"saturated connection pool."
),
trigger=("tokens", 2_000),
keep=("messages", 2),
observability_hook=events.append,
)
agent = create_agent(
model=scripted_model("INC-9931 only affects the payments service."),
tools=[],
middleware=[middleware],
)
log = "".join(
f"2026-10-04T03:{index // 60:02d}:{index % 60:02d}Z INFO payments-worker "
"processing queue\n"
for index in range(200)
)
report = (
"Incident INC-9931: elevated latency on the payments service.\n"
+ json.dumps({"orders": [{"status": "queued"}] * 40, "region": "eu-west-1"})
+ "\n"
+ log
+ "2026-10-04T04:00:00Z ERROR connection pool exhausted for TX-991\n"
)
history = [
HumanMessage("Investigate the payments outage."),
AIMessage("", tool_calls=[{"id": "call-1", "name": "incident_report", "args": {}}]),
ToolMessage(report, tool_call_id="call-1"),
AIMessage("INC-9931 is caused by connection pool exhaustion."),
HumanMessage("Is any other service affected?"),
]
result = agent.invoke({"messages": history})
print("History after the agent turn:")
for message in result["messages"]:
print(f" {message.type:<5} {first_line(message.text)}")
event = events[0]
print()
print(f"tokens before: {event.input_tokens}")
print(f"after compaction: {event.prepared_tokens}")
print(f"after summary: {event.output_tokens}")
print(f"compression ratio: {event.compression_ratio:.3f}")
print(f"validation: {event.validation_status}")
print(f"must-keep facts: {event.must_preserve_facts}")
Output:
History after the agent turn:
human Here is a summary of the conversation to date:
ai INC-9931 is caused by connection pool exhaustion.
human Is any other service affected?
ai INC-9931 only affects the payments service.
tokens before: 3283
after compaction: 166
after summary: 70
compression ratio: 0.021
validation: passed
must-keep facts: 2
Before the agent's model call, ContextSage:
- Checked the trigger. The history held 3,283 tokens, over the 2,000-token trigger.
- Analyzed the history. It parsed each message into content units and
found two facts that must survive: the incident
INC-9931and the transactionTX-991. - Compacted the report. 200 routine log lines collapsed into a marker naming the omitted lines, and 40 identical JSON records into one counted entry, bringing the history down to 166 tokens.
- Had LangChain summarize the messages older than the last two.
- Validated the result. Both facts are in the summary, so validation passed and nothing had to be restated.
The SummarizationEvent passed to observability_hook records each of these
numbers, without any message content.
Next steps¶
- How it works explains each step in detail.
- Examples shows compaction, preservation, recovery, provenance and observability, offline and with a live model.
- Agent Skills teach coding agents to integrate ContextSage correctly.