# Compaction

Compaction makes room in a long session by replacing older conversation with a
summary, so the session can keep going past the model's context limit.

## How it works

When a session approaches the model's context limit, OpenCode summarizes the
entire current conversation. It also keeps the most recent conversation, about
15,000 tokens by default, beside the summary so exact recent details remain
available.

```text
before   [ system prompt ][ older conversation ............ ][ recent 15k ][ pending work ]
request  [ system prompt ][ older conversation ............ ][ recent 15k ][ summary instructions ]
after    [ system prompt ][ summary of older + recent ][ recent 15k ][ pending work ]
```

Sending the full conversation lets the summary request reuse the normal request's
prompt cache when the provider supports it. Later compactions update the existing
summary using the conversation since that checkpoint.

## Start

Automatic compaction is on by default:

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "compaction": {
    "auto": true,
    "keep": { "tokens": 15000 },
  },
}
```

Compaction is lossy. Increase `keep.tokens` when exact recent details matter,
or request compaction yourself before the automatic one.

## Manual

Request compaction at any time, even for a short history:

```sh
opencode api post /api/session/ses_example/compact --data '{}'
```

The `api` command discovers and authenticates with the background service. Its
response confirms the request was accepted; it does not wait for the summary.
Follow `session.compaction.*` events to learn when it finishes. See the
[API reference](/api) for the full operation.

| Rule | Behavior |
| --- | --- |
| Timing | Runs at the next safe point, before prompts that are still waiting. |
| Repeats | Requests made while one is pending merge into it. |
| Automation | Works when `compaction.auto` is `false`. |

Pass an `id` to make an exact retry idempotent. Reusing that ID for a different
request returns a conflict.

```sh
opencode api post /api/session/ses_example/compact --data '{"id":"msg_compact_once"}'
```

## Settings

Add `compaction` to any [OpenCode configuration file](/config):

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "compaction": {
    "auto": false,
    "keep": { "tokens": 24000 },
    "buffer": "20%",
  },
}
```

| Field | Default | Behavior |
| --- | ---: | --- |
| `auto` | `true` | Compact automatically near the context limit, and recover once when a provider rejects a request as too long. Manual compaction always works. |
| `keep.tokens` | `15000` | Approximate recent conversation kept beside the summary. Larger values preserve more detail but leave less room for new work. |
| `buffer` | `"15%"`, at least 16k | Share of the model's context window kept free. Automatic compaction starts once the conversation reaches the rest. Larger values compact earlier. |

`keep.tokens` accepts a non-negative integer.

### Buffer

`buffer` is a percentage of each model's window, so one setting fits every model:

| Model window | `"buffer": "20%"` compacts at |
| ---: | ---: |
| 128k | ~102k |
| 1M | 800k |

- It is the room kept free, not the point where compaction starts: `"20%"` compacts at 80% full.
- Accepts `"1%"` to `"99%"`, including decimals such as `"12.5%"`.
- A token count such as `20000` also works. The same count is a large share of a small window and a small share of a large one.
- A token count at least as large as the model's window is ignored and the default applies.

## Model

By default OpenCode writes the summary itself, using the session's model. Set
`agents.compaction.model` to use another model for summaries:

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "agents": {
    "compaction": { "model": "anthropic/claude-sonnet-5-5" },
  },
}
```

If that model cannot be resolved, OpenCode falls back to the session's model.

## Background compaction

<Callout type="warning">
  Experimental. This may change, break, or be removed in any release without notice.
</Callout>

Automatic compaction normally pauses the session while the summary is written. With background compaction, OpenCode
writes the summary ahead of time and swaps it in when compaction is due:

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "experimental": {
    "background_compaction": true,
  },
}
```

```text
60k tokens before the threshold   summary of the conversation so far starts in the background
                                  the session keeps going; the summary is held, not applied
threshold                         the held summary is swapped in; everything since it is kept as is
```

On small context windows, the summary starts at most halfway between the first response after the last compaction
and the threshold.

| Rule | Behavior |
| --- | --- |
| Cost | The summary request reuses the prompt cache. A summary that is never used, for example because the session ends before the threshold, still costs tokens. |
| Waits | If the summary is still being written when compaction is due, the session waits for it to finish. |
| Falls back | Compaction summarizes as usual if the conversation since the held summary grew past about 40% of the threshold, or if the model, instructions, or start of the conversation changed. |
| Skipped | Not used for native compaction, right after a model switch, or when a provider rejects a request as too long. After a break longer than the prompt cache lifetime, it starts from the next response instead. |
| Storage | Held summaries live in memory and are lost on restart. |

## Providers

Some providers can compact the conversation on their side instead. Enable it per
provider or model with `settings.compaction`:

```jsonc title="opencode.jsonc"
{
  "$schema": "https://opencode.ai/config.json",
  "providers": {
    "openai": {
      "settings": { "compaction": { "type": "native" } },
      "models": {
        "gpt-6.1-sol": { "settings": { "compaction": { "type": "summary" } } },
      },
    },
  },
}
```

A model setting overrides the provider setting. `native` uses the provider's
compaction; `summary` uses OpenCode's own.

With native compaction, OpenCode sends the conversation to the provider's
compaction endpoint. The provider returns an opaque, encrypted item that stands
in for the older conversation. Your recent messages and attachments, up to
`keep.tokens`, are kept alongside it:

```text
before   [ older conversation ........................ ][ recent user messages ]
after    [ encrypted checkpoint + recent user messages ]
```

| Topic | Behavior |
| --- | --- |
| Support | OpenAI Responses models. Support varies by deployment and model. |
| Threshold | Same `auto` and `buffer` settings as summary compaction. Manual requests work too. |
| Portability | An encrypted checkpoint only works with the same provider and model. If you switch models, the session continues from the original conversation instead. |
| Too long | If the provider rejects a compaction as too long, OpenCode retries it with a smaller request. It does not switch to a summary. |

## Summaries

The summary is structured so another agent could pick the work up from it:

```md
## Objective
Finish the authentication migration.

## Next Move
- Update the callback handler.
- Verify the login flow.
```

It covers the objective and requirements, decisions, completed and active work,
blockers and next moves, and relevant files. In the recent conversation kept
beside it, long tool output is shortened and attachment data is replaced by a
short description.

After compaction, the current versions of your instruction files become the
session's baseline; see [Instructions](/instructions).

## Limits

| Limit | Result |
| --- | --- |
| Model | Summary compaction honors `agents.compaction.model`; otherwise it uses the session's model. Native compaction always uses the session's model. |
| History | Compaction needs older conversation to replace. It cannot create room when a request is mostly fixed instructions and tool schemas. |
| Size | If the conversation to compact is itself too long, OpenCode sends a shortened text version and may leave out the oldest exchanges. |
| Recovery | A request rejected as too long is compacted and retried once. A second rejection is returned as an error. |
| Storage | Earlier messages remain stored even when they are no longer sent to the model. |

For example, compaction cannot help here:

```text
128k context = 120k fixed instructions and tools + 8k conversation
```

## Migration

V1 used tail-turn and pruning behavior. V2 uses summaries and
`compaction.keep.tokens`:

```jsonc
{
  "compaction": {
    "keep": { "tokens": 15000 }
  }
}
```

The settings and behavior on this page apply to V2.