Skip to main content
Save durable user facts to long-term memory before context compaction discards the older messages that contain them. Context compaction is lossy — messages that fall outside the compaction window are gone. This feature runs one bounded child agent with search_memory and store_memory before compaction, so stable user-provided facts in the older slice are saved to long-term memory first. It never blocks compaction: if the child times out or fails, compaction still runs.

Quick Start

1

Enable with True

One bool on ExecutionConfig turns the flush on. It stays off by default with zero overhead — the child agent is never constructed.
2

Tune with the config class

Swap the bool for PreCompactionMemoryFlushConfig to set the deadline, token cap, minimum turns, or a cheaper model for the child.

How It Works

The flush fires at the older-slice boundary — exactly the messages that are about to disappear — searches memory to avoid duplicates, stages writes, and commits them only if the child finishes in time. The child agent has zero autonomy budget (max_steps=3, no streaming, no verbose) and cannot recurse into another compaction. Only user and assistant text is serialised — tool messages and non-text parts are dropped.

MemoryFlushResult

The flush returns a frozen MemoryFlushResult (importable from praisonaiagents.compaction) describing what happened.

Configuration Options

PreCompactionMemoryFlushConfig controls the child agent’s budget.
The nested config defaults to enabled=True so PreCompactionMemoryFlushConfig(...) is ergonomic. The containing ExecutionConfig.pre_compaction_memory_flush slot stays default-off.

Environment Overrides

Two environment variables override the code-level config at runtime. Invalid values are ignored with a logged warning — the code-level config stands.

Behaviour Guarantees

  • Never blocks compaction. Every failure path returns a MemoryFlushResult(attempted=True, completed=False, ...) and logs a warning; compaction proceeds unchanged.
  • Atomic commit-or-nothing. Child writes are staged and committed only after successful, in-time completion. A timed-out worker cannot mutate the parent memory store.
  • Sync path in a daemon thread. A stuck provider cannot delay process shutdown.
  • Tool payloads excluded. Only user and assistant text is serialised.
  • Prompt-injection posture. The child treats the transcript as data, not instructions, refuses to store credentials or secrets, and uses only the two provided memory tools.

Common Patterns

Save user preferences before a chat session’s context rotates by enabling the flush alongside compaction:
Point a cheaper model at the flush child than the parent uses for the main loop:
Wire an app-level metric on MemoryFlushResult.reason (count timeout vs completed) to tune timeout_seconds over time.

Best Practices

The child is capped at max_steps=3 and rarely needs more than the default timeout_seconds=20.0. Raise it only if you observe reason == "timeout" dominating.
When the parent uses an expensive model, pass llm="gpt-4o-mini" (or similar). The flush job is short and doesn’t need the top-tier model.
The default min_turns_to_flush=2 avoids firing on trivial compactions. Raise it if reason == "below_minimum" dominates your metrics.
The child agent shares the parent’s memory backend but cannot access its tools — that’s a deliberate boundary. Don’t try to bypass it by mutating the child.

Advanced

Framework authors wiring the flush into a custom compactor path can call run_pre_compaction_flush (async) or run_pre_compaction_flush_sync directly. Both need a parent_agent shaped like Agent — it must expose _memory_instance and .llm.

Context Compaction

Automatically compact chat history near the token limit.

Memory

Long-term memory storage and retrieval.

Context Compaction Policy

Choose the strategy that runs after the older-slice boundary.

Session Compaction Checkpoint

Persist compaction state across sessions.