openhands-sdk/openhands/sdk/context/condenser/
Core Responsibilities
The Condenser system has four primary responsibilities:- History Compression - Reduce event lists to fit within context windows
- Threshold Detection - Determine when condensation should trigger
- Summary Generation - Create meaningful summaries via LLM or heuristics
- View Management - Transform event history into LLM-ready views
Architecture
Key Components
| Component | Purpose | Design |
|---|---|---|
CondenserBase | Abstract interface | Defines condense() contract |
RollingCondenser | Rolling window base | Implements threshold-based triggering |
LLMSummarizingCondenser | LLM summarization | Uses LLM to generate summaries |
NoOpCondenser | No-op implementation | Returns view unchanged |
PipelineCondenser | Multi-stage pipeline | Chains multiple condensers |
View | Event view | Represents history for LLM |
Condensation | Condensation event | Metadata about compression |
Condenser Types
NoOpCondenser
Pass-through condenser that performs no compression:LLMSummarizingCondenser
Uses an LLM to generate summaries of conversation history: Process:- Check Threshold: Compare view size to configured limit (e.g., event count >
max_size) - Select Events: Identify events to keep (first N + last M) and events to summarize (middle)
- LLM Call: Generate summary of middle events using dedicated LLM
- Create Event: Wrap summary in
Condensationevent withforgotten_event_ids - Add to History: Agent adds
Condensationto event log and returns early - Next Step:
View.from_events()filters forgotten events and inserts summary
max_size: Event count threshold before condensation triggers (default: 120)keep_first: Number of initial events to preserve verbatim (default: 4)llm: LLM instance for summarization (often cheaper model than reasoning LLM)
PipelineCondenser
Chains multiple condensers in sequence: Use Case: Multi-stage compression (e.g., remove old events, then summarize, then truncate)Condensation Flow
Trigger Mechanisms
Condensers can be triggered in two ways: Automatic Trigger:- When: Threshold exceeded (e.g., event count >
max_size) - Who: Agent calls
condenser.condense()each step - Purpose: Proactively keep context within limits
- When:
CondensationRequestevent added to history (viaview.unhandled_condensation_request) - Who: Agent (on LLM context window error) or application code
- Purpose: Force compression when context limit exceeded
Condensation Workflow
Key Steps:- Threshold Check:
should_condense()determines if condensation needed - Event Selection: Identify events to keep (head + tail) vs forget (middle)
- Summary Generation: LLM creates compressed representation of forgotten events
- Condensation Creation: Create
Condensationevent withforgotten_event_idsand summary - Return to Agent: Condenser returns
Condensation(notView) - History Update: Agent adds
Condensationto event log and exits step - Next Step:
View.from_events()(source) processes Condensation to filter events and insert summary
View and Condensation
View Structure
AView represents the conversation history as it will be sent to the LLM:
View Components:
events: List ofLLMConvertibleEventobjects (filtered by Condensation)unhandled_condensation_request: Flag for pending manual condensationcondensations: List of all Condensation events processed- Methods:
from_events()creates view from raw events, handling Condensation semantics
Condensation Event
When condensation occurs, aCondensation event is created:
Condensation Fields:
forgotten_event_ids: List of event IDs to filter outsummary: Compressed text representation of forgotten eventssummary_offset: Index where summary event should be inserted- Inherits from
Event:id,timestamp,source
Rolling Window Pattern
RollingCondenser implements a common pattern for threshold-based condensation:
Rolling Window Strategy:
- Keep Head: Preserve first
keep_firstevents (default: 4) - usually system prompts - Keep Tail: Preserve last
target_size - keep_first - 1events - recent context - Summarize Middle: Compress events between head and tail into summary
- Target Size: After condensation, view has
max_size // 2events (default: 60)
Component Relationships
How Condenser Integrates
Relationship Characteristics:- Agent → State: Calls
View.from_events()to get current view - Agent → Condenser: Calls
condense(view)each step if condenser registered - Condenser → Agent: Returns
View(proceed) orCondensation(defer) - Agent → Events: Adds
Condensationevent to log when returned
See Also
- Agent Architecture - How agents use condensers during reasoning
- Conversation Architecture - View generation and event management
- Events - Condensation event type and append-only log
- Context Condenser Guide - Configuring and using condensers

