Normandy.Behaviours.Compactor.WindowManager (normandy v2.2.0)

View Source

Opt-in Compactor that wraps Normandy.Context.WindowManager's truncation strategies (:oldest_first | :summarize).

Triggered at the turn's :steering boundary: builds a WindowManager sized to the model's context window (ctx.window, unless opts pins :context_window) and estimates the conversation by summing each message's estimate cached on its entry (Normandy.Components.AgentMemory.Entry). Under budget that one estimate is all it does and nothing changes, so a mid-round boundary (ctx.mid_round) leaves the open tool round and its thinking alone until the conversation no longer fits. Over budget it delegates to WindowManager.truncate_conversation/2, whose strategy (truncate_oldest_first among them) and the result's tokens_after sum the cached estimates again, and a compaction strips the kept messages' thinking (see "Compacting mid-round" in Normandy.Behaviours.Compactor).

The budget for the history is the window minus :reserved_tokens minus ctx.prompt_tokens (the estimated system prompt and tool definitions of the next call).

Options: :context_window pins the window (and skips the model catalog lookup); :reserved_tokens is the answer's room, by default the agent's max_tokens; a reserve at or above the window raises ArgumentError; :strategy goes to WindowManager.new/1; :summary_max_tokens is the :summarize strategy's summary budget (default: the agent's max_tokens). The 1.x name :max_tokens for the pin raises ArgumentError. Any other key raises ArgumentError when the agent is built (BaseAgent.init/1, DSL new/1) or its template is rebuilt. The :summarize strategy needs acc.client; if summarization fails it returns the original acc with %{compacted: false, error: reason} rather than crashing the turn. Its meta carries :dropped, the removed entries (see Normandy.Behaviours.Compactor).

Summary

Functions

Always true: the strategies size against the model's context window.

Checks the options (Normandy.Behaviours.Compactor callback). BaseAgent.init/1 and ConfigTemplate.rebuild/3 call it, so a typo surfaces where the config is made, not mid-turn. The 1.x :max_tokens pin raises with a pointer to :context_window.

Functions

needs_window?(opts)

@spec needs_window?(keyword()) :: true

Always true: the strategies size against the model's context window.

validate_opts!(opts, entry)

@spec validate_opts!(
  keyword(),
  {module(), atom(), arity()}
) :: keyword()

Checks the options (Normandy.Behaviours.Compactor callback). BaseAgent.init/1 and ConfigTemplate.rebuild/3 call it, so a typo surfaces where the config is made, not mid-turn. The 1.x :max_tokens pin raises with a pointer to :context_window.