Before you follow along

This video is a snapshot in time. Some APIs and examples have changed since recording. Follow the code on this page, and look for “Changed since recording” notices below.

*[Watch on YouTube](https://www.youtube.com/watch?v=6zbbYm902MQ&list=PLDzwjhH-4yhU&index=8)*

*Code for this lesson: [`samples/08-context-management`](https://github.com/aws-samples/sample-building-with-strands-course/tree/main/samples/08-context-management)*

## What context engineering is

Context engineering is the discipline of deciding **what information enters the model’s context window, when, and in what form**. Unlike prompt engineering (which focuses on instructions), context engineering ensures the model has the right data at the right time without overflowing the window or wasting tokens.

It breaks down into four categories:

| Category | What It Does | Strands Primitive |
| --- | --- | --- |
| **Select** | Choose what enters context, inject relevant info, filter out noise | `ContextInjector` plugin |
| **Compress** | Shrink what’s already in context, summarize history, truncate results | `ContextManager` strategies (truncate, summarize, drop) |
| **Isolate** | Separate concerns, give sub-agents their own context windows | Multi-agent patterns with separate agent contexts |
| **Externalize** | Move large data out of context, store externally, keep a compact reference | `ContextManager` stash + retrieval tool |

## The one-line default: `context_manager="auto"`

Changed since recording

The video uses `SummarizingConversationManager` and `ContextOffloader`. The updated starting point is `context_manager="auto"`. For custom behavior, use `ContextManager` and `Offload` from `strands.experimental.context_manager`, as shown below. Truncation keeps previews; it does not simply drop whole messages.

For most use cases, start here:

```python
from strands import Agent

agent = Agent(context_manager="auto")
```

This single parameter enables:

-   **Offloading** large tool results to a stash, replaced with truncated previews
-   **Summarization** of old messages into structured summaries (not dropped)
-   **Proactive compression** firing at 85% context usage to stay ahead of overflow

The effect on cost and answer quality depends on the workload. Measure both with your own evaluation cases.

For agents that need to protect specific context across long conversations, use `context_manager="agentic"`. The model gets tools to summarize, truncate, or pin messages itself, trading some tokens for judgment.

## Context injector

The `ContextInjector` plugin folds ephemeral text into the model input before each call. The text is never written to conversation history; it augments one call only. Use it for context the agent should always have but that doesn’t belong in stored history: current time, environment facts, retrieval lookups.

```python
from datetime import datetime, timezone
from strands import Agent
from strands.vended_plugins.context_injector import ContextInjector

agent = Agent(
    plugins=[
        ContextInjector(
            lambda context: f"<now>{datetime.now(timezone.utc).isoformat()}</now>"
        ),
    ],
)
```

Control when injection fires:

-   `trigger="userTurn"` (default): only on fresh user messages
-   `trigger="everyTurn"`: before every model call, including mid-task tool-result turns
-   Custom predicate: `trigger=lambda context: context.state.get("recall_enabled") is True`

## ContextManager and Offload strategies

The `ContextManager` is the engine behind `context_manager="auto"`. When you need custom control over how context is managed, build your own strategy pipeline using `Offload` strategies.

Experimental

`ContextManager` and `Offload` are currently exported from `strands.experimental.context_manager`. They are fully functional and will move to the main namespace in an upcoming release.

There are three types of Offload strategies:

| Strategy | What stays in context |
| --- | --- |
| `Offload.truncate(...)` | A head/tail preview of the original |
| `Offload.summarize(...)` | An LLM-generated summary of the original |
| `Offload.drop(...)` | Nothing (original goes to stash only) |

Each strategy takes a **target** that controls what content it operates on:

```python
from strands.experimental.context_manager import Offload

Offload.summarize("*")                   # everything: all message types
Offload.truncate("tool_results")         # only successful tool results
Offload.drop("tool_result_errors")       # only errored tool results
Offload.summarize("assistant_text")      # only assistant text blocks
Offload.truncate(["bash", "read_file"])  # only results from specific tools
Offload.truncate(["!read_file"])         # everything except read_file
```

And `.when(...)` sets the conditions:

-   `threshold=N`: fire on individual blocks exceeding N tokens (per-block mode)
-   `utilization=0.85`: fire when the context window is 85% full (per-message mode)
-   `preserve_recent=N`: skip the N most recent matching messages

### Truncate strategy (keep previews)

Truncate matching content to head/tail previews when context gets full:

```python
from strands import Agent
from strands.experimental.context_manager import ContextManager, Offload

agent = Agent(
    context_manager=ContextManager(
        strategies=[
            Offload.truncate("tool_results").when(threshold=2500),
            Offload.truncate("*").when(utilization=0.9, preserve_recent=10),
        ],
    ),
)
```

📂 [sliding\_window.py](https://github.com/aws-samples/sample-building-with-strands-course/tree/main/samples/08-context-management/sliding_window.py)

### Summarize strategy

Instead of dropping old messages, compress them into summaries. Preserves more information, but summaries are lossy:

```python
from strands import Agent
from strands.experimental.context_manager import ContextManager, Offload

agent = Agent(
    context_manager=ContextManager(
        strategies=[
            Offload.truncate("tool_results").when(threshold=2500),
            Offload.summarize("*").when(utilization=0.85, preserve_recent=10),
        ],
    ),
)
```

📂 [summarizing.py](https://github.com/aws-samples/sample-building-with-strands-course/tree/main/samples/08-context-management/summarizing.py)

### Custom summarizer (cheaper model)

Summarizing history doesn’t require your most capable model. Pass a cheaper one, and a domain-specific prompt, via the config dict:

```python
from strands import Agent
from strands.models import BedrockModel
from strands.experimental.context_manager import ContextManager, Offload

summarizer_model = BedrockModel(model_id="us.anthropic.claude-haiku-4-5-20251001-v1:0")

agent = Agent(
    context_manager=ContextManager(
        strategies=[
            Offload.truncate("tool_results").when(threshold=2500),
            Offload.summarize(
                "*",
                {
                    "model": summarizer_model,
                    "system_prompt": "Summarize the customer service conversation...",
                },
            ).when(utilization=0.85, preserve_recent=8),
        ],
        stash=False,
    ),
)
```

`stash=False` turns off the stash entirely: offloaded content isn’t kept anywhere and the agent gets no retrieval tool. That’s fine for pure summarization where you don’t need to pull anything back. Leave it on (the default) when you want the agent to be able to recover offloaded tool results.

📂 [custom\_summarizer.py](https://github.com/aws-samples/sample-building-with-strands-course/tree/main/samples/08-context-management/custom_summarizer.py)

## Strategy comparison

| Strategy | Tradeoff |
| --- | --- |
| `context_manager="auto"` | Best default. Offloading + summarization + proactive compression |
| `context_manager="agentic"` | Model self-manages context. Trades tokens for judgment |
| `Offload.truncate(...)` | Keeps a preview; originals remain recoverable when stash is enabled |
| `Offload.summarize(...)` | Preserves more info. Lossy compression, costs an LLM call |
| `Offload.drop(...)` | Most aggressive. Content goes to stash only |
| Context injection | Ephemeral per-call data. Never persisted to history |

## Resources

-   📖 [Context Management](/pr-cms-5317/docs/user-guide/sdk/context-management/index.md)
-   📖 [Context Injector](/pr-cms-5317/docs/user-guide/sdk/plugins/context-injector/index.md)
-   📖 [Blog: Reduced cost, better isolation, and more resilience](https://strandsagents.com/blog/reduced-cost-better-isolation-more-resilience/)