# How to Implement Agent State Compaction and Resume in AI Suite

> Implement agent state compaction and resume in AI Suite using PostgresStateStore.compact_state() and Engine.resume() for efficient conversation management and full context recovery.

- Repository: [Andrew Ng/aisuite](https://github.com/andrewyng/aisuite)
- Tags: how-to-guide
- Published: 2026-07-30

---

**AI Suite provides built-in state compaction via `PostgresStateStore.compact_state()` to summarize historic messages into compacted records, and session resumption via `Engine.resume()` to restore agent conversations from persistent PostgreSQL storage with full context recovery.**

The `andrewyng/aisuite` framework stores every agent turn in a persistent PostgreSQL state store, allowing long-running sessions to accumulate thousands of messages. To prevent performance degradation from loading massive conversation histories, AI Suite implements agent state compaction and resume capabilities that summarize old messages while maintaining seamless conversation continuity.

## How State Compaction Works in AI Suite

State compaction reduces memory and I/O overhead by replacing contiguous blocks of historic messages with a single summary record.

### The Compaction Process

According to the source code in [`aisuite/mcp/state_store.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/mcp/state_store.py), the `compact_state()` method executes a four-step transactional workflow:

1. **Collect the target slice** – Fetch the specific `message_id` values that need compaction, typically the oldest messages already included in the model context.

2. **Generate a summary** – Invoke the configured LLM provider with a summarize prompt to create `summary_text`.

3. **Create a CompactionRecord** – Store the compaction metadata including a unique `compaction_id` (formatted as `cmp_<uuid>`), source message IDs, summary text, and a new revision number.

4. **Replace original messages** – Remove the original message slice from the thread and insert a virtual placeholder message flagged as `compacted`.

If any step fails, the transaction rolls back leaving the thread unchanged. The method returns the new revision number for optimistic locking.

### CompactionRecord Structure

The `CompactionRecord` captures:

- `compaction_id`: Unique identifier (`cmp_<uuid>`)
- `source_message_ids`: Original message identifiers
- `summary_text`: LLM-generated summary content
- `revision`: Thread revision number after compaction

### Key Implementation

The core logic resides in [`aisuite/mcp/state_store.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/mcp/state_store.py):

```python
from aisuite.mcp.state_store import PostgresStateStore
from uuid import uuid4

def compact_state(self, thread_id: str, source_message_ids: List[str], reason: str) -> CompactionRecord:
    # Gather messages

    messages = self._fetch_messages(thread_id, source_message_ids)
    
    # Summarise via LLM provider

    summary = self.provider.summarise(messages)
    
    # Build record

    record = CompactionRecord(
        compaction_id=f"cmp_{uuid4().hex}",
        source_message_ids=source_message_ids,
        summary_text=summary,
        reason=reason,
        revision=self._next_revision(thread_id),
    )
    
    # Store & replace

    self._save_compaction(record)
    self._replace_with_placeholder(thread_id, record)
    return record

```

## How Session Resumption Works

The `Engine.resume()` method in [`aisuite/framework/engine.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/framework/engine.py) restores agent state from persistent storage, handling both regular messages and compacted placeholders.

### Loading Thread State

When resuming, the engine calls `store.get_thread_head(thread_id)` to retrieve the latest revision, model context message IDs, and compaction metadata. It then loads the actual message content via `load_messages()`.

### Expanding Compacted Messages

Compacted messages remain collapsed until the LLM requests the full context. The engine lazily invokes `self._expand_compacted(messages)` to retrieve summaries from `CompactionRecord` entries on-demand, rather than expanding all historic compactions at once.

### Durable Resume for Pending Tools

If the previous session ended while waiting for user approval or tool execution, the **durable resume** mechanism automatically replays pending `ToolResult` objects. This allows the conversation to continue without requiring the user to re-approve already authorized actions.

### Resume Implementation

The resumption logic in [`aisuite/framework/engine.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/framework/engine.py) follows this pattern:

```python
async def resume(self, thread_id: str) -> None:
    head = await self.state_store.get_thread_head(thread_id)
    messages = await self.state_store.load_messages(head.model_context_message_ids)
    
    # Expand compacted placeholders if the LLM requests them

    self._expand_compacted(messages)
    
    # Replay any pending tool results (durable resume)

    await self._replay_pending_tool_results(thread_id)
    
    self.current_thread = Thread(messages=messages, revision=head.revision)

```

## Complete Implementation Workflow

Combine compaction and resume to manage long-running agent sessions efficiently.

### 1. Compact State

Manually trigger compaction when sessions exceed configurable thresholds (e.g., >200 messages):

```python
from aisuite.mcp.state_store import PostgresStateStore

store = PostgresStateStore(dsn="postgresql://user:pass@localhost/aisuite")
thread_id = "t_12345"

# Compact the first 50 messages

message_ids = store.head(thread_id).model_context_message_ids[:50]
compacted = store.compact_state(
    thread_id=thread_id,
    source_message_ids=message_ids,
    reason="Session optimization - reduce memory footprint"
)

print(f"Created compaction {compacted.compaction_id}, revision {compacted.revision}")

```

### 2. Resume Session

Restore the conversation and continue processing:

```python
from aisuite.framework import Engine

engine = Engine(state_store=store, provider=your_llm_provider)

# Re-hydrate engine, expand compacted placeholders as needed,

# and re-execute any pending tool calls

await engine.resume(thread_id)

# Continue conversation seamlessly

await engine.send_user_message("Summarize our previous discussion")

```

## Key Implementation Files

- [`aisuite/mcp/state_store.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/mcp/state_store.py): Implements `PostgresStateStore.compact_state()` and `CompactionRecord` storage.
- [`aisuite/framework/engine.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/framework/engine.py): Contains `Engine.resume()` and durable resume logic.
- [`tests/agents/test_postgres_state_store.py`](https://github.com/andrewyng/aisuite/blob/main/tests/agents/test_postgres_state_store.py): Verifies compaction serialization and resume behavior.
- [`platform/docs/IMPLEMENTATION-LEDGER.md`](https://github.com/andrewyng/aisuite/blob/main/platform/docs/IMPLEMENTATION-LEDGER.md): Documents the resume pipeline and "RESUME HERE" markers.
- [`platform/docs/MESSAGING-AND-SESSIONS.md`](https://github.com/andrewyng/aisuite/blob/main/platform/docs/MESSAGING-AND-SESSIONS.md): Describes message flow and session lifecycle.

## Summary

- **State compaction** in `andrewyng/aisuite` uses `PostgresStateStore.compact_state()` to summarize message blocks into `CompactionRecord` entries, replacing original messages with virtual placeholders.
- **Session resumption** relies on `Engine.resume()` in [`aisuite/framework/engine.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/framework/engine.py) to restore thread state, lazily expand compacted messages, and replay pending tool results.
- Compaction triggers automatically based on message count thresholds or manual invocation, with full transactional safety ensuring data integrity.
- The **durable resume** feature automatically handles interrupted tool executions, eliminating the need for users to re-approve actions after reconnection.

## Frequently Asked Questions

### What triggers state compaction in AI Suite?

Compaction triggers either manually through direct `compact_state()` invocation or automatically when session message counts exceed configurable limits (typically 200 messages). The system targets the oldest messages already incorporated into the model context to minimize impact on recent conversation history.

### How does AI Suite handle compacted messages during resume?

During `Engine.resume()`, compacted messages remain as virtual placeholders in the initial message list. The engine expands them on-demand via `_expand_compacted(messages)` only when the LLM requires access to the summarized historical context, optimizing memory usage during session restoration.

### What is durable resume and when does it occur?

**Durable resume** automatically replays pending `ToolResult` objects when restoring sessions that were interrupted during tool execution or user approval workflows. This occurs in `Engine.resume()` through `_replay_pending_tool_results()`, allowing conversations to continue without requiring users to re-approve actions after application restarts or network reconnections.

### Where is agent state stored in AI Suite?

Agent state persists in **PostgreSQL** by default through the `PostgresStateStore` class in [`aisuite/mcp/state_store.py`](https://github.com/andrewyng/aisuite/blob/main/aisuite/mcp/state_store.py). This includes raw messages, `CompactionRecord` entries, thread revision numbers, and pending tool results, enabling durable resumption across application restarts.