ExAgent.Compaction.Summary (ExAgent v2.2.0)

View Source

A compactor that summarizes older messages and keeps a recent window verbatim.

When the history exceeds :threshold_tokens (estimated via ExAgent.Compaction.estimate_tokens/1 by default), everything older than the last :keep_recent messages is eligible for the caller's :summarize function. Complete tool exchanges, original instructions, and the latest user request are preserved. The recent window expands to avoid splitting calls from results or retries. Older completed exchanges within the current run are also eligible.

The summary is ordinary user-level context inserted before the active user request, never a new System instruction. Pinned messages may exceed the target window, and a summary is not guaranteed to reduce the model-specific token count. Context without an identifiable user request is left unchanged.

Options

  • :threshold_tokens — non-negative threshold (default 4000); compact once the estimate exceeds it.
  • :keep_recent — non-negative minimum trailing messages kept verbatim (default 6); zero still retains instructions and the active user request.
  • :summarize — (old_messages -> summary_text). Required to compact; if absent, the projection is left untouched. May also return {:no_change} or {:error, reason}; other non-string results are rejected.
  • :token_counter — (messages -> non_neg_integer()), default ExAgent.Compaction.estimate_tokens/1.

:summarize may perform external IO. The callback's model requests, tokens and costs are not automatically observable or charged to this run by this API. Repeated model requests can invoke it repeatedly; applications must not treat compaction as an exactly-once side effect.

Wiring

Supply a trusted, explicitly configured model and summarizer_agent; ReqLLM credentials and tool/stream qualification belong to those instances.

compaction = %ExAgent.Compaction.Capability{
  compactor: ExAgent.Compaction.Summary,
  opts: [
    threshold_tokens: 6000,
    keep_recent: 8,
    summarize: fn old ->
      {:ok, %{output: text}} = ExAgent.run(summarizer_agent, summarize_prompt(old))
      text
    end
  ]
}

ExAgent.new(model: model, capabilities: [compaction])