Skip to content

symfonic.agent.conversation

conversation

Conversation-manager strategy objects.

Named, swappable strategies that decide how a conversation's history is kept within the model's context window. They are thin, legible wrappers over machinery symfonic-core already has -- the summarizing compaction node (:class:~symfonic.core.config.CompactionConfig) and the pure message-count window (AgentConfig.max_conversation_messages) -- packaged as first-class objects a caller can drop into :class:~symfonic.agent.engine.SymfonicAgent::

from symfonic.agent.conversation import SlidingWindowConversationManager

agent = SymfonicAgent(
    model_provider=provider,
    conversation_manager=SlidingWindowConversationManager(window_size=20),
)

Each strategy resolves into an :class:~symfonic.core.config.AgentConfig override via :meth:ConversationManager.apply; there is no new engine behavior. When a strategy is passed, it takes precedence over any compaction / max_conversation_messages already set on the config.

The three built-ins:

  • :class:SummarizingConversationManager -- summarize overflow into a running summary (the framework's default behavior, parameterized). Best when older turns still carry information the model needs.
  • :class:SlidingWindowConversationManager -- keep only the most recent window_size messages; older ones are dropped, not summarized. Cheapest; best when only recent context matters.
  • :class:NullConversationManager -- no management; history grows unbounded (up to the model's own limit). For short sessions or when the caller manages history externally.

.. note:: These strategies govern the LangGraph conversation window only. They are orthogonal to the 5-layer HMS memory: hydration, consolidation, and procedural learning continue independently. A sliding window drops raw turns from the prompt; it does not erase what HMS has already persisted.

ConversationManager

Base strategy: resolve into an :class:AgentConfig override.

Subclasses implement :meth:apply, returning a new AgentConfig with the compaction and/or max_conversation_messages fields set to realize the strategy. The engine consumes the resulting config unchanged.

NullConversationManager dataclass

NullConversationManager()

Bases: ConversationManager

No management: history grows unbounded (up to the model's own limit).

Both the summarizer and the count-drop are disabled. Suitable for short sessions or when the caller manages conversation length externally.

SlidingWindowConversationManager dataclass

SlidingWindowConversationManager(window_size: int = 40)

Bases: ConversationManager

Keep only the most recent window_size messages; drop older ones.

A pure message-count window -- no LLM summary. The summarizer is disabled (both token thresholds raised out of reach) so the only limiter is the count-drop of the oldest turns when history exceeds window_size.

SummarizingConversationManager dataclass

SummarizingConversationManager(
    context_window_tokens: int | None = None,
    keep_recent_messages: int = 10,
    soft_threshold_tokens: int = 4000,
    summary_model: str = "claude-haiku-4-5",
)

Bases: ConversationManager

Summarize overflow into a running summary (framework default behavior).

When the estimated token count crosses soft_threshold_tokens (or the hard context_window_tokens budget), the oldest messages beyond keep_recent_messages are summarized via summary_model and removed from the live history. This is symfonic-core's default; this manager just names and parameterizes it.