Skip to content

Not yet published

This plugin package is not published yet. Stay tuned.

@apeira/plugin-compact ​

Automatic context compaction for long-running Apeira agents.

The plugin appends a durable summary after a successful over-threshold turn. Storage remains an append-only fact log; model context is derived from the latest summary without storage-specific compaction support.

Install ​

sh
pnpm add @apeira/plugin-compact

Usage ​

ts
import { createAgent } from '@apeira/core'
import { responses } from '@apeira/core/responses'
import { compact } from '@apeira/plugin-compact'

const agent = createAgent({
  initialState: {
    contextLength: 128_000,
  },
  instructions: 'You are a helpful assistant.',
  plugins: [
    compact({
      compactAgent: {
        runner: responses({
          apiKey: process.env.OPENAI_API_KEY,
          baseURL: 'https://api.openai.com/v1/',
          model: 'gpt-5.5-mini',
        }),
      },
      threshold: 0.9,
    }),
  ],
  runner: responses({
    apiKey: process.env.OPENAI_API_KEY,
    baseURL: 'https://api.openai.com/v1/',
    model: 'gpt-5.5',
  }),
})

compactAgent.runner may use a smaller or cheaper model than the main agent. When omitted, the plugin reuses the parent agent runner.

The same configuration works with @apeira/session; no session adapter or compaction predicate is required:

ts
const session = createSession({
  defaultRef: 'main',
  sessionStorage: mem(),
})

const agent = createAgent({
  // ...
  plugins: [compact({ compactAgent: { runner: summaryRunner } })],
  storage: session.storage,
})

How it works ​

  • onTurnFinish checks the completed turn's final usage.totalTokens.
  • Above the threshold, it reads raw storage, applies its own previous summary projection, asks the compact agent to summarize that input, and appends one compact entry containing { summary }.
  • On later turns, transformEntries replaces the latest compact entry with a temporary developer <context_summary> input and hides entries covered by that summary.
  • Core appends current-turn live input after this historical projection, so the transform cannot inspect or modify it.

Original input, output, state, and lifecycle entries are never rewritten or deleted.

API ​

compact(options) ​

ts
interface CompactPluginOptions {
  compactAgent: {
    instructions?: CreateAgentOptions['instructions']
    runner?: Runner
  }
  threshold?: number
}
OptionTypeDefaultDescription
compactAgent{ instructions?, runner? }—Temporary agent configuration used to generate summaries.
thresholdnumber0.9Compaction threshold as a fraction of state.contextLength.

Set the context window through agent state:

ts
createAgent({
  // ...
  initialState: { contextLength: 128_000 },
})

If state.contextLength is absent, the plugin uses 128000.

Failure behavior ​

If summary generation fails, returns empty output, or is refused, the plugin appends nothing and retries on later over-threshold turns. After three consecutive failures, it appends this fallback as a compact summary:

json
{
  "summary": "(Earlier conversation omitted due to length)"
}

Notes ​

  • The temporary summary agent has no plugins, so compaction cannot recursively compact itself.
  • turn.done is emitted before summary generation, but the queue awaits onTurnFinish before starting the next turn.
  • Summary generation reads raw storage plus compact's own previous-summary projection. Other plugins' transformEntries hooks are not applied.