Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Context Condensation

The Condenser trait compresses conversation history before it reaches the model, keeping context windows manageable in long-running agents.

Condenser Trait

use synaptic::condenser::Condenser;

#[async_trait]
pub trait Condenser: Send + Sync {
    async fn condense(&self, messages: Vec<Message>) -> Result<Vec<Message>, SynapticError>;
}

Built-in Condensers

NoOpCondenser

Returns messages unchanged. Useful as a default or placeholder.

use synaptic::condenser::NoOpCondenser;

let condenser = NoOpCondenser;
let output = condenser.condense(messages).await?;
// output == messages (unchanged)

RollingCondenser

Keeps the most recent N messages. The system message is preserved by default.

use synaptic::condenser::RollingCondenser;

let condenser = RollingCondenser::new(20)
    .with_preserve_system(true);  // default: true

LlmSummarizingCondenser

Summarizes older messages using an LLM while keeping recent messages intact.

use synaptic::condenser::LlmSummarizingCondenser;

let condenser = LlmSummarizingCondenser::new(
    model.clone(),   // Arc<dyn ChatModel>
    4096,            // max_tokens threshold
    5,               // keep_recent: number of recent messages to preserve
);

When the estimated token count exceeds max_tokens, older messages are summarized into a single system message and prepended to the recent messages.

TokenBudgetCondenser

Trims messages to fit within a token budget using a TokenCounter.

use synaptic::condenser::TokenBudgetCondenser;
use synaptic::core::HeuristicTokenCounter;

let counter = Arc::new(HeuristicTokenCounter);
let condenser = TokenBudgetCondenser::new(4096, counter)
    .with_include_system(true);  // preserve system message (default)

PipelineCondenser

Chains multiple condensers in sequence. Each condenser's output feeds into the next.

use synaptic::condenser::{PipelineCondenser, RollingCondenser, TokenBudgetCondenser};

let pipeline = PipelineCondenser::new(vec![
    Arc::new(RollingCondenser::new(50)),
    Arc::new(TokenBudgetCondenser::new(4096, counter)),
]);

CondenserMiddleware

Wraps any condenser as an Interceptor, automatically condensing messages before each model call.

use synaptic::condenser::CondenserMiddleware;
use synaptic::condenser::RollingCondenser;

let middleware = CondenserMiddleware::new(
    Arc::new(RollingCondenser::new(20)),
);

// Use with agent options
let options = AgentOptions {
    middleware: vec![Arc::new(middleware)],
    ..Default::default()
};