pub struct LlmCompaction { /* private fields */ }Expand description
Background LLM summarization behind the synchronous
CompactionStrategy trait. See the module docs for the design,
the cost trade-off, and the known limitation.
The state machine is per-session. Do not share one instance across
concurrently running loops — Agent never does, but a hand-built
AgentLoopConfig could.
Implementations§
Source§impl LlmCompaction
impl LlmCompaction
Sourcepub fn from_config(config: ModelConfig) -> Self
pub fn from_config(config: ModelConfig) -> Self
A compaction strategy that summarizes with the model in config,
selecting the built-in provider for the config’s protocol and resolving
the API key from the provider-conventional environment variable.
This mirrors Agent::from_config, and for
the same reason: a bare (provider, model, key) triple lets the three
drift apart, and drops the base_url, headers, and compat flags that
every non-Anthropic provider needs.
The request is standalone, so this can (and usually should) name a cheaper model than the main loop’s.
Sourcepub fn from_config_with(
registry: &ProviderRegistry,
config: ModelConfig,
) -> Result<Self, AgentBuildError>
pub fn from_config_with( registry: &ProviderRegistry, config: ModelConfig, ) -> Result<Self, AgentBuildError>
Like from_config but resolves the provider from a
caller-supplied registry, returning an error if the config’s protocol
isn’t registered.
Sourcepub fn from_provider(
provider: Arc<dyn StreamProvider>,
config: ModelConfig,
) -> Self
pub fn from_provider( provider: Arc<dyn StreamProvider>, config: ModelConfig, ) -> Self
A compaction strategy that summarizes with an explicit provider.
The escape hatch for custom StreamProvider implementations and test
doubles — pair with ModelConfig::mock.
The config is still required so the model id, context window, and pricing
stay defined together, matching
Agent::from_provider.
Sourcepub fn with_api_key(self, key: impl Into<String>) -> Self
pub fn with_api_key(self, key: impl Into<String>) -> Self
Use an explicit API key instead of the environment-resolved one.
Sourcepub fn with_trigger_ratio(self, ratio: f32) -> Self
pub fn with_trigger_ratio(self, ratio: f32) -> Self
Fraction of the budget at which background summarization starts.
Clamped to [0.1, 0.95]. Default: DEFAULT_TRIGGER_RATIO.
Sourcepub fn with_retain_tail_tokens(self, tokens: usize) -> Self
pub fn with_retain_tail_tokens(self, tokens: usize) -> Self
Token budget for the retained tail of recent messages.
Setting this too high relative to the context budget disables the
strategy outright: summarization is first attempted at
trigger_ratio · budget, and if the tail alone would consume all the
history that exists at that point, there is nothing left to summarize.
The default therefore derives from the budget —
min(DEFAULT_RETAIN_TAIL_TOKENS, budget / 4), recomputed per call
so it tracks the loop’s calibrated budget — rather than being a fixed
number that silently no-ops on smaller context windows.
An explicit value here is used as given. If it turns out to be too
large, a one-time warn! says so instead of failing quietly.
Sourcepub fn with_system_prompt(self, prompt: impl Into<String>) -> Self
pub fn with_system_prompt(self, prompt: impl Into<String>) -> Self
Replace the summarization system prompt.
Sourcepub fn with_instruction(self, instruction: impl Into<String>) -> Self
pub fn with_instruction(self, instruction: impl Into<String>) -> Self
Replace the summarization instruction (the “handoff briefing” prompt).
Sourcepub fn with_max_summary_tokens(self, tokens: u32) -> Self
pub fn with_max_summary_tokens(self, tokens: u32) -> Self
Cap on briefing length in output tokens. Default: 2000, floor: 256.
A briefing that hits this cap comes back with StopReason::Length and is
rejected rather than spliced — a truncated handoff loses the “Open items”
section the instruction puts last.
Sourcepub fn with_timeout(self, timeout: Duration) -> Self
pub fn with_timeout(self, timeout: Duration) -> Self
How long one summarization attempt may run.
Default: DEFAULT_REQUEST_TIMEOUT.
Sourcepub fn with_retry_config(self, retry: RetryConfig) -> Self
pub fn with_retry_config(self, retry: RetryConfig) -> Self
Retry policy for the summarization request. Default:
RetryConfig::default; pass RetryConfig::none to disable.
Sourcepub fn with_event_sender(self, events: UnboundedSender<AgentEvent>) -> Self
pub fn with_event_sender(self, events: UnboundedSender<AgentEvent>) -> Self
Emit AgentEvent::ContextCompacted on this channel when compaction
runs, by either path.
CompactionStrategy::compact has no access to the loop’s event
channel, so the sender has to come in from the side. Pair it with
Agent::prompt_with_sender, where
the caller owns the channel. Without it the per-compaction cost is still
logged at info!, but nothing structured is emitted.
let (tx, rx) = tokio::sync::mpsc::unbounded_channel();
let agent = Agent::from_config(ModelConfig::anthropic("claude-sonnet-5", "Sonnet 5"))
.with_compaction_strategy(
LlmCompaction::from_config(ModelConfig::anthropic(
"claude-haiku-4-5",
"Haiku 4.5",
))
.with_event_sender(tx.clone()),
);Trait Implementations§
Source§impl CompactionStrategy for LlmCompaction
impl CompactionStrategy for LlmCompaction
Source§fn compact(
&self,
messages: Vec<AgentMessage>,
config: &ContextConfig,
) -> Vec<AgentMessage>
fn compact( &self, messages: Vec<AgentMessage>, config: &ContextConfig, ) -> Vec<AgentMessage>
config. Read moreSource§impl Debug for LlmCompaction
Redacts api_key; ModelConfig’s own Debug redacts header values.
impl Debug for LlmCompaction
Redacts api_key; ModelConfig’s own Debug redacts header values.