# How to Configure Context Compaction Strategies in Forge

> Learn how to configure context compaction strategies in Forge using the pluggable ContextManager and strategy objects like NoCompact, SlidingWindowCompact, or TieredCompact. Optimize your token budget enforcement.

- Repository: [Antoine/forge](https://github.com/antoinezambelli/forge)
- Tags: how-to-guide
- Published: 2026-05-22

---

**Forge provides a pluggable compaction system via the `ContextManager` class in [`src/forge/context/manager.py`](https://github.com/antoinezambelli/forge/blob/main/src/forge/context/manager.py), which delegates token-budget enforcement to strategy objects like `NoCompact`, `SlidingWindowCompact`, or `TieredCompact` defined in [`src/forge/context/strategies.py`](https://github.com/antoinezambelli/forge/blob/main/src/forge/context/strategies.py).**

The `antoinezambelli/forge` repository implements a sophisticated context management system to prevent LLM prompts from exceeding token limits. Understanding how to configure context compaction strategies in Forge allows you to optimize memory usage while preserving critical conversation history across long-running workflows.

## Understanding Forge's Context Management Architecture

Forge separates budgeting logic from compaction algorithms. The **ContextManager** maintains the token budget and monitors usage, while a **CompactStrategy** implementation handles the actual message reduction when thresholds are breached.

### The ContextManager Core

The `ContextManager` class in [`src/forge/context/manager.py`](https://github.com/antoinezambelli/forge/blob/main/src/forge/context/manager.py) orchestrates the compaction lifecycle. It tracks the `budget_tokens` limit and uses `estimate_tokens`—which relies on either a cached token count from the LLM backend or a character-count heuristic—to monitor prompt size. When `maybe_compact` is triggered, the manager delegates to the configured strategy. If compaction occurs (phase index > 0), the manager instantiates a `CompactEvent` (defined in lines 12-22 of [`manager.py`](https://github.com/antoinezambelli/forge/blob/main/manager.py)) and fires the optional `on_compact` callback for logging or UI feedback.

### The CompactStrategy Interface

All strategies inherit from the base class in [`src/forge/context/strategies.py`](https://github.com/antoinezambelli/forge/blob/main/src/forge/context/strategies.py) and implement the `compact(messages, budget, ...)` method. This method returns a tuple containing the compacted message list and a phase index where **0** indicates no compaction occurred and **1-3** represent increasingly aggressive compaction phases. This design allows you to swap or extend strategies without modifying the manager's token-budgeting logic.

## Built-in Context Compaction Strategies

Forge ships with three production-ready strategies in [`src/forge/context/strategies.py`](https://github.com/antoinezambelli/forge/blob/main/src/forge/context/strategies.py), each optimized for different memory constraints and workflow patterns.

### NoCompact for Unrestricted Workflows

Use **NoCompact** for very small or short-lived workflows, or when running on hardware with abundant VRAM (≥ 32 GB). This strategy accepts no parameters and returns the message history unchanged, effectively disabling compaction.

```python
from forge.context.manager import ContextManager
from forge.context.strategies import NoCompact

ctx = ContextManager(
    strategy=NoCompact(),
    budget_tokens=12_000,          # typical 8 K-token LLM budget

)

```

### SlidingWindowCompact for Predictable Truncation

**SlidingWindowCompact** provides simple, predictable truncation that preserves the system prompt, the original user request, and the last *N* iterations of conversation. It accepts two core parameters:

- `keep_recent` (int): Specifies how many recent loop iterations to retain untouched.
- `compact_threshold` (float): The fraction of the token budget that triggers compaction (default **0.75**).

```python
from forge.context.strategies import SlidingWindowCompact

# Keep the last 3 iterations fully intact; start compacting at 75 % of the budget

strategy = SlidingWindowCompact(keep_recent=3, compact_threshold=0.75)

ctx = ContextManager(strategy=strategy, budget_tokens=12_000)

```

### TieredCompact for Aggressive Memory Management

**TieredCompact** implements a three-phase compaction algorithm designed for aggressive memory conservation. The strategy progressively discards information: first removing nudges and truncating tool results, then dropping tool results entirely, and finally keeping only tool-call skeletons. Configuration parameters include:

- `keep_recent` (int, default **2**): Recent iterations to preserve.
- `compact_threshold` (float): Fallback threshold if `phase_thresholds` is omitted.
- `phase_thresholds` (tuple[float, float, float]): Per-phase trigger fractions (e.g., `(0.60, 0.75, 0.90)`).

```python
from forge.context.strategies import TieredCompact

# Keep 2 recent iterations; shrink aggressively as the budget fills:

#   Phase 1 @ 60 %  → drop nudges / truncate tool results (≈200 chars)

#   Phase 2 @ 75 %  → drop tool results entirely

#   Phase 3 @ 90 %  → keep only tool-call skeletons

strategy = TieredCompact(
    keep_recent=2,
    phase_thresholds=(0.60, 0.75, 0.90)
)

ctx = ContextManager(strategy=strategy, budget_tokens=12_000)

```

## Configuring Compaction Callbacks and Monitoring

The `ContextManager` accepts optional callback hooks for observability. The `on_compact` parameter receives a `CompactEvent` object containing `phase_reached`, `tokens_before`, `tokens_after`, `messages_before`, and `messages_after`. You can also supply `on_context_threshold` to inject warning strings before inference calls when `check_thresholds` is enabled.

```python
def log_compaction(event):
    print(
        f"Compaction (phase {event.phase_reached}) "
        f"reduced tokens {event.tokens_before}->{event.tokens_after} "
        f"and messages {event.messages_before}->{event.messages_after}"
    )

ctx = ContextManager(
    strategy=TieredCompact(),
    budget_tokens=12_000,
    on_compact=log_compaction,
)

```

## Integrating with Workflow Runners

In production deployments, you typically inject the configured `ContextManager` into a `WorkflowRunner`. The `WorkflowRunner` class in [`src/forge/core/runner.py`](https://github.com/antoinezambelli/forge/blob/main/src/forge/core/runner.py) automatically invokes `ctx_manager.maybe_compact(...)` during the execution loop, ensuring context limits are enforced without manual intervention.

```python
from forge.core.runner import WorkflowRunner
from forge.context.strategies import TieredCompact

strategy = TieredCompact(keep_recent=4)
ctx_manager = ContextManager(strategy=strategy, budget_tokens=16_000)

runner = WorkflowRunner(context_manager=ctx_manager)
runner.run(workflow)          # the runner will call ctx_manager.maybe_compact(...)

```

Server-side implementations in [`src/forge/server.py`](https://github.com/antoinezambelli/forge/blob/main/src/forge/server.py) and proxy scenarios in [`src/forge/proxy/proxy.py`](https://github.com/antoinezambelli/forge/blob/main/src/forge/proxy/proxy.py) demonstrate additional patterns for instantiating a fresh `ContextManager` per request or session.

## Summary

- **Three strategies** control how Forge manages token budgets: `NoCompact`, `SlidingWindowCompact`, and `TieredCompact`.
- **Configuration** occurs through the `ContextManager` constructor, passing the strategy instance and a `budget_tokens` integer.
- **TieredCompact** offers granular control via `phase_thresholds`, triggering three distinct compaction phases at specified budget percentages.
- **Monitoring** is implemented via the `on_compact` callback, which receives a `CompactEvent` detailing the compaction impact.
- **Integration** requires passing the configured manager to `WorkflowRunner` or using it directly in custom inference loops.

## Frequently Asked Questions

### What is the default compaction threshold in Forge?

The default `compact_threshold` is **0.75** (75% of the token budget) for both `SlidingWindowCompact` and `TieredCompact`. However, `TieredCompact` can override this with per-phase thresholds via the `phase_thresholds` parameter, allowing Phase 1 to trigger at 60%, Phase 2 at 75%, and Phase 3 at 90%.

### When should I use TieredCompact versus SlidingWindowCompact?

Use **SlidingWindowCompact** for simple, predictable workflows where you only need to truncate older iterations while keeping the system prompt and recent history intact. Choose **TieredCompact** for complex, long-running agents that generate tool results and reasoning chains, as its three-phase approach aggressively preserves the most critical information while shedding auxiliary data like nudges and detailed tool outputs.

### How do I implement a custom compaction strategy?

Subclass the `CompactStrategy` base class from [`src/forge/context/strategies.py`](https://github.com/antoinezambelli/forge/blob/main/src/forge/context/strategies.py) and implement the `compact(messages, budget, **kwargs)` method. Your implementation must return a tuple of `(compacted_messages, phase_index)`, where `phase_index` is 0 for no compaction or 1-3 indicating the severity of reduction performed. Pass your custom instance to `ContextManager(strategy=YourStrategy())`.

### Where is the token estimation logic implemented?

The `ContextManager.estimate_tokens` method in [`src/forge/context/manager.py`](https://github.com/antoinezambelli/forge/blob/main/src/forge/context/manager.py) handles token counting. It uses either a cached token count updated from the LLM backend or falls back to a simple character-count divided by four heuristic when cached counts are unavailable.