Skip to content

Conversation Management

A conversation manager keeps your agent’s context window within the model’s token limit as the conversation grows, trimming or summarizing older messages while preserving the ones that still matter. It runs inside the agent loop, so context management happens automatically as messages accumulate.

This page covers the built-in conversation managers and how to write your own. If you want sensible defaults wired up for you rather than configuring a manager by hand, start with Manage the context window; the managers documented here are the mechanism underneath it.

Pick a conversation manager based on how you want history trimmed. Each one implements the ConversationManager interface with a different strategy. Use one of the three built in:

Or build your own manager that matches your requirements.

The NullConversationManager is a simple implementation that does not modify the conversation history. Pass it explicitly to turn off the default SlidingWindowConversationManager and keep the full conversation history. It’s useful for:

  • Short conversations that won’t exceed context limits
  • Debugging purposes
  • Cases where you want to manage context manually
from strands import Agent
from strands.agent.conversation_manager import NullConversationManager
agent = Agent(
conversation_manager=NullConversationManager()
)

The SlidingWindowConversationManager implements a sliding window strategy that maintains a fixed number of recent messages. This is the default conversation manager used by the Agent class when no conversation_managerconversationManager is specified. To turn it off and keep the full history, pass a NullConversationManager.

from strands import Agent
from strands.agent.conversation_manager import SlidingWindowConversationManager
# Create a conversation manager with custom window size
conversation_manager = SlidingWindowConversationManager(
window_size=20, # Maximum number of messages to keep
should_truncate_results=True, # Enable truncating the tool result when a message is too large for the model's context window
)
agent = Agent(
conversation_manager=conversation_manager
)

Key features of the SlidingWindowConversationManager:

  • Maintains Window Size: Automatically removes messages from the window if the number of messages exceeds the limit.

  • Dangling Message Cleanup: Removes incomplete message sequences to maintain valid conversation state.

  • Overflow Trimming: In the case of a context window overflow, it will trim the oldest messages from history until the request fits in the models context window.

  • Configurable Tool Result Truncation: Enable or disable truncation of tool results when the message exceeds context window limits. When enabled (the default; should_truncate_results=TrueshouldTruncateResults: true), the oldest message with tool results is truncated first so recent context is preserved as long as possible. Truncation depends on content type:

    • Text payloads keep their head and tail, separated by a <truncated chars="N"/> marker.
    • Images, videos, binary documents, and oversized JSON are replaced by a typed placeholder, for example [image: png, source: bytes, 12345 bytes].
    • The tool result’s original status and error fields are preserved.

    When disabled, full results are preserved but more historical messages may be removed. For a proactive alternative that preserves full content externally, see the Context Offloader plugin.

  • Per-Turn Management: Optionally apply context management proactively during the agent loop execution, not just at the end.

  • Message Pinning: Protect specific messages from trimming during context reduction. See Message Pinning.

  • Proactive Compression: Pass proactiveCompression: true or proactiveCompression: { compressionThreshold: 0.7 } to trigger context reduction before the model call when projected input tokens exceed a configurable threshold. See Proactive Context Compression.

Per-Turn Management:

By default, the SlidingWindowConversationManager applies context management only after the agent loop completes. The per_turn parameter allows you to proactively manage context during execution, which is useful for long-running agent loops with many tool calls.

from strands import Agent
from strands.agent.conversation_manager import SlidingWindowConversationManager
# Apply management before every model call
conversation_manager = SlidingWindowConversationManager(
per_turn=True, # Apply management before each model call
)
# Or apply management every N model calls
conversation_manager = SlidingWindowConversationManager(
per_turn=3, # Apply management every 3 model calls
)
agent = Agent(
conversation_manager=conversation_manager
)

The per_turn parameter accepts:

  • False (default): Only apply management after the agent loop completes
  • True: Apply management before every model call
  • An integer N (must be > 0): Apply management every N model calls

The SummarizingConversationManager (Python) / SummarizingConversationManager (TypeScript) summarizes older messages instead of discarding them. It keeps the substance of earlier turns in the context while staying within token limits.

Configuration parameters:

  • summary_ratio (float, default: 0.3): Ratio of the oldest messages to summarize and replace when reducing context (clamped between 0.1 and 0.8)
  • preserve_recent_messages (int, default: 10): Minimum number of recent messages to always keep
  • summarization_agent (Agent, optional): Custom agent for generating summaries. If not provided, uses the main agent instance. Cannot be used together with summarization_system_prompt.
  • summarization_system_prompt (str, optional): Custom system prompt for summarization. If not provided, uses a default prompt that creates structured bullet-point summaries focusing on key topics, tools used, and technical information in third-person format. Cannot be used together with summarization_agent.

Basic Usage:

By default, the SummarizingConversationManager uses the same model and configuration as your main agent for summarization.

from strands import Agent
from strands.agent.conversation_manager import SummarizingConversationManager
agent = Agent(
conversation_manager=SummarizingConversationManager()
)

You can also customize the behavior by adjusting parameters like summary ratio and number of preserved messages:

from strands import Agent
from strands.agent.conversation_manager import SummarizingConversationManager
# Create the summarizing conversation manager with default settings
conversation_manager = SummarizingConversationManager(
summary_ratio=0.3, # Summarize and replace the oldest 30% of messages when context reduction is needed
preserve_recent_messages=10, # Always keep 10 most recent messages
)
agent = Agent(
conversation_manager=conversation_manager
)

Custom System Prompt for Domain-Specific Summarization:

You can customize the summarization behavior by providing a custom system prompt that tailors the summarization to your domain or use case.

from strands import Agent
from strands.agent.conversation_manager import SummarizingConversationManager
# Custom system prompt for technical conversations
custom_system_prompt = """
You are summarizing a technical conversation. Create a concise bullet-point summary that:
- Focuses on code changes, architectural decisions, and technical solutions
- Preserves specific function names, file paths, and configuration details
- Omits conversational elements and focuses on actionable information
- Uses technical terminology appropriate for software development
Format as bullet points without conversational language.
"""
conversation_manager = SummarizingConversationManager(
summarization_system_prompt=custom_system_prompt
)
agent = Agent(
conversation_manager=conversation_manager
)

Advanced Configuration with Custom Summarization Agent:

For advanced use cases, provide a custom summarization_agent to handle summarization. A custom agent lets you use a different model (such as a faster or cheaper one), run tools during summarization, or apply summarization logic specific to your domain. It brings its own system prompt, tools, and model configuration to produce summaries that preserve the context your use case depends on.

from strands import Agent
from strands.agent.conversation_manager import SummarizingConversationManager
from strands.models import AnthropicModel
# Create a cheaper, faster model for summarization tasks
summarization_model = AnthropicModel(
model_id="claude-haiku-4-5-20251001", # More cost-effective for summarization
max_tokens=1000,
params={"temperature": 0.1} # Low temperature for consistent summaries
)
custom_summarization_agent = Agent(model=summarization_model)
conversation_manager = SummarizingConversationManager(
summary_ratio=0.4,
preserve_recent_messages=8,
summarization_agent=custom_summarization_agent
)
agent = Agent(
conversation_manager=conversation_manager
)
  • Context Window Management: reduces context automatically when token limits are exceeded
  • Structured Summaries: uses bullet-point summaries to capture key information from older turns
  • Tool Pair Preservation: keeps tool use and result message pairs together during summarization
  • Message Pinning: protect specific messages from summarization during context reduction. See Message Pinning.
  • Configurable Behavior: tune summarization through the parameters above
  • Fallback Safety: handles summarization failures gracefully

Message pinning protects specific messages from eviction during context reduction. Pinned messages survive both sliding-window trimming and summarization, which makes pinning useful for preserving system prompts, critical instructions, or key decisions that must remain in the conversation regardless of length.

Messages are pinned by setting metadata.custom.pinned = true on the message object. The SDK provides both a declarative configuration (pin_first / pinFirst) and runtime utility functions for programmatic control.

Protecting Initial Messages with pin_first

Section titled “Protecting Initial Messages with pin_first”

Both SlidingWindowConversationManager and SummarizingConversationManager accept a pin_first (Python) / pinFirst (TypeScript) parameter that permanently protects the first N messages from eviction. This is the simplest way to preserve system prompts or initial instructions across all context reductions.

from strands import Agent
from strands.agent.conversation_manager import SlidingWindowConversationManager
agent = Agent(
conversation_manager=SlidingWindowConversationManager(
window_size=40,
pin_first=1,
)
)

The same parameter works with SummarizingConversationManager:

from strands.agent.conversation_manager import SummarizingConversationManager
agent = Agent(
conversation_manager=SummarizingConversationManager(
pin_first=2,
)
)

The pin metadata is written during the first context reduction and remains set permanently, protecting those messages through all subsequent reductions.

By default, conversation managers are reactive. They only reduce context after the model rejects a request with a context window overflow error. Proactive compression avoids wasting round-trips and output token starvation by triggering context reduction before the model call when the projected input token count exceeds a configurable threshold of the model’s context window.

Pass proactive_compression to any built-in conversation manager. Use True for the default 0.7 threshold, or pass a dict with a custom compression_threshold ratio between 0 and 1. For example, 0.7 will trigger compression when 70% of the model’s context window is used:

With SlidingWindowConversationManager:

from strands import Agent
from strands.agent.conversation_manager import SlidingWindowConversationManager
agent = Agent(
conversation_manager=SlidingWindowConversationManager(
window_size=50,
proactive_compression={"compression_threshold": 0.7},
),
)

With SummarizingConversationManager:

from strands import Agent
from strands.agent.conversation_manager import SummarizingConversationManager
agent = Agent(
conversation_manager=SummarizingConversationManager(
proactive_compression=True,
),
)

Without proactive_compression, only reactive overflow recovery is used.

Before each model call, the agent estimates the projected input token count and attaches it to the BeforeModelCallEvent. When proactive compression is configured, the conversation manager compares this estimate against the model’s contextWindowLimit:

if projectedInputTokens / contextWindowLimit >= compressionThreshold:
reduce() // proactively compress context

Each conversation manager uses the same reduction logic for proactive compression as reactive overflow recovery. Proactive compression is best-effort only, so if reduce() throws or returns false, the error is swallowed and the model call proceeds normally.

Because BeforeModelCallEvent triggers before every model call including calls within a tool-use cycle, this provides automatic in-loop compression. If an agent makes five tool calls in a single invocation and context grows past the threshold between calls three and four, compression triggers before call four.

For details on how the SDK estimates tokens, resolves context window limits, and computes utilization, see Context Estimation.

To create a custom conversation manager, implement the ConversationManager interface, which is composed of three key elements:

  1. apply_management: This method is called after each event loop cycle completes to manage the conversation history. It’s responsible for applying your management strategy to the messages array, which may have been modified with tool results and assistant responses. The agent runs this method automatically after processing each user input and generating a response.

  2. reduce_context: This method is called when the model’s context window is exceeded (typically due to token limits). It implements the specific strategy for reducing the window size when necessary. The agent calls this method when it encounters a context window overflow exception, giving your implementation a chance to trim the conversation history before retrying.

  3. removed_message_count: Conversation managers track this attribute, and Session Management uses it to load messages from session storage efficiently. The count represents messages from the user or model that the manager removed from the agent’s messages, not messages the manager added through something like summarization.

  4. register_hooks (optional): Override this method to integrate with hooks. This enables proactive context management patterns, such as trimming context before model calls. Always call super().register_hooks when overriding.

See the SlidingWindowConversationManager implementation as a reference example.