How Session Compaction Works in Pi Web: Events, Triggers, and Implementation

Session compaction in Pi Web archives older chat turns into a single summary entry and emits compaction_start and compaction_end events to keep the UI synchronized.

The pi-web repository manages long-running conversations by storing every turn in a Pi Agent JSON-L session file. When histories grow large, the system performs session compaction to summarize older messages into a lightweight entry, ensuring the interface remains responsive. Understanding the compaction trigger mechanisms and the specific events emitted allows developers to build UIs that gracefully handle these archival transitions.

What Is Session Compaction?

Session compaction is the process of replacing a segment of historical chat messages with a single compaction entry containing a summarized version of that context. According to the source code in lib/types.ts, the system defines a specific entry type "compaction" that stores the summary body alongside optional metadata about files read or modified during the conversation. This reduces the session file size while preserving essential context for the agent.

How to Trigger a Compaction

The Pi Agent supports both manual and automatic initiation of compaction, with both paths emitting identical event signatures (differentiated only by an auto_ prefix).

Manual Trigger via API

To compact a session on demand, the UI sends a command through the RPC layer. In lib/rpc-manager.ts, the AgentSessionWrapper.send() method receives the command and forwards it to the inner Agent via inner.compact(...).

await sendAgentCommand(sessionId, {
  type: "compact",
  // optional: give the model extra instructions on how to summarise
  customInstructions: "Summarise the conversation in 2‑3 sentences."
});

Automatic Compaction

The Pi SDK may automatically initiate compaction based on internal heuristics regarding session size or message count. These automatic runs emit events prefixed with auto_, such as auto_compaction_start and auto_compaction_end, but otherwise follow the identical lifecycle as manual compactions.

The Compaction Lifecycle and Events Emitted

The compaction process follows a strict three-phase lifecycle defined in lib/rpc-manager.ts, emitting specific events that allow the UI to track progress.

compaction_start Event

Immediately before the SDK begins summarizing history, it emits a compaction_start event (or auto_compaction_start for automatic runs). The AgentSessionWrapper subscribes to the inner Agent via inner.subscribe and re-emits this event to the client, signaling that a long-running operation has begun.

Compaction Processing

During processing, the SDK reads the old entries, generates a summary string, and writes a new JSON-L entry of type "compaction". This entry contains the human-readable summary plus read-files and modified-files sections. The helper parseCompactionSummary in lib/compaction-summary.ts extracts these structured fields from the raw content:

import { parseCompactionSummary } from "@/lib/compaction-summary";

const entry = /* a SessionMessageEntry of type "compaction" */;
const summary = parseCompactionSummary(entry.message.content as string);
console.log(summary.body);           // human‑readable summary text
console.log(summary.readFiles);      // files that were read during the run
console.log(summary.modifiedFiles);  // files that were written/changed

compaction_end Event

Once the summary entry is successfully written to the session file, the SDK emits a compaction_end event (or auto_compaction_end). The wrapper forwards this to the client, clears the “Stop compaction” UI button, and updates its internal isCompacting flag to false.

Handling Compaction Events in the UI

The React hook hooks/useAgentSession.ts listens for these events to manage loading states and prevent user actions during archival.

const handleAgentEvent = useCallback((event: AgentEvent) => {
  switch (event.type) {
    case "compaction_start":
    case "auto_compaction_start":
      setIsCompacting(true);          // show “Compacting…” UI
      break;

    case "compaction_end":
    case "auto_compaction_end":
      setIsCompacting(false);         // hide the UI spinner
      break;

    // …other event cases…
  }
}, []);

The hook also contains reconciliation logic to handle missed end events, ensuring the isCompacting state remains accurate even if network issues occur during the compaction process.

Summary

  • Session compaction consolidates historical chat messages into a single JSON-L entry with type "compaction", reducing storage overhead and maintaining UI performance.
  • The system emits compaction_start and compaction_end events (prefixed with auto_ for automatic triggers) via the AgentSessionWrapper subscription mechanism in lib/rpc-manager.ts.
  • Manual compaction is triggered by sending a {type: "compact"} command with optional customInstructions to the agent session.
  • Use parseCompactionSummary from lib/compaction-summary.ts to extract summary bodies, read files, and modified files from compaction entries.
  • UI components consume these events in hooks/useAgentSession.ts to toggle loading indicators and disable controls during active compaction.

Frequently Asked Questions

What events does Pi Web emit during session compaction?

Pi Web emits compaction_start immediately before summarization begins and compaction_end after the summary entry is permanently written. For automatic compactions initiated by the SDK's internal heuristics, these events are prefixed with auto_ (e.g., auto_compaction_start and auto_compaction_end), allowing the UI to distinguish between user-initiated and background processes.

How do I manually trigger a session compaction in Pi Web?

Send a command object with type: "compact" to the agent session via the API endpoint POST /api/agent/[id]. The client-side helper sendAgentCommand wraps this request, and the AgentSessionWrapper.send() method in lib/rpc-manager.ts forwards the instruction to the inner Agent's compact() method. You may optionally include a customInstructions string to guide the summarization model.

What data is stored in a compaction entry?

A compaction entry contains a summary body describing the archived conversation, plus optional metadata listing files that were read or modified during the session. The parseCompactionSummary function in lib/compaction-summary.ts extracts these fields—specifically body, readFiles, and modifiedFiles—from the entry's content string, providing structured access to the archived context.

How does the UI know when compaction starts and ends?

The hooks/useAgentSession.ts hook subscribes to the agent's event stream and listens for compaction_start and compaction_end events (including their auto_ variants). When these events arrive, the hook updates a React state variable isCompacting, which controls the visibility of loading spinners and the enabled state of the "Stop compaction" button, ensuring the interface remains synchronized with the underlying Agent state.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →