# OpenAI compaction vs a memory layer: what each keeps

> How Responses API compaction works: compact_threshold, the /responses/compact endpoint, what the encrypted item keeps, what it costs, and when memory fits.

OpenAI's Responses API can compact a conversation for you. It is OpenAI's own answer to "my conversation is too long", and for some agents it is enough. This guide covers how to turn it on, what the compacted output contains, what it costs, its limits, and where it differs from a memory layer. OpenAI facts are from its docs as of 12 November 2026.

## What is compaction?

Compaction shrinks a long conversation into a smaller context window that the model can continue from. From OpenAI's [compaction guide](https://developers.openai.com/api/docs/guides/compaction):

- **Server-side:** add `context_management` with a `compact_threshold` to a `/responses` request. "When the rendered token count crosses the configured threshold, the server runs server-side compaction", and the response includes the encrypted compaction item.
- **Standalone:** call `/responses/compact` with a full context window and get back a smaller window to send next. "The returned window is the canonical next context window, so pass it into your next `/responses` call as-is."
- **The compaction item is encrypted.** "It is opaque and not intended to be human-interpretable." It "carries forward key prior state and reasoning into the next run using fewer tokens."
- **Earlier items can go.** You can drop items that came before the most recent compaction item. If you chain with `previous_response_id`, do not prune by hand.

It is a Responses API feature. The Chat Completions [create reference](https://developers.openai.com/api/reference/resources/chat/subresources/completions/methods/create) has no `context_management` parameter.

## How do you turn compaction on?

Server-side, in a stateless loop that appends each response's output to the input. In Python, following OpenAI's example:

```python
from openai import OpenAI

client = OpenAI()
conversation = [{"type": "message", "role": "user", "content": "Let's begin a long coding task."}]

while True:
    response = client.responses.create(
        model="gpt-5.3-codex",
        input=conversation,
        store=False,
        context_management=[{"type": "compaction", "compact_threshold": 200000}],
    )
    conversation.extend(response.output)  # includes the compaction item when one is made
    conversation.append({"type": "message", "role": "user", "content": next_user_message()})
```

In TypeScript:

```ts
import OpenAI from 'openai';
import { toResponseInputItems } from 'openai/lib/responses/ResponseInputItems';

const client = new OpenAI();
const conversation: OpenAI.Responses.ResponseInputItem[] = [
  { type: 'message', role: 'user', content: "Let's begin a long coding task." },
];

const response = await client.responses.create({
  model: 'gpt-5.3-codex',
  input: conversation,
  store: false,
  context_management: [{ type: 'compaction', compact_threshold: 200_000 }],
});
conversation.push(...toResponseInputItems(response.output));
```

With `previous_response_id`, turn on the same `context_management` and keep sending only the newest user message; OpenAI's [deployment checklist](https://developers.openai.com/api/docs/guides/deployment-checklist) says the server compacts the conversation when it gets too large.

Standalone, when you want to choose the moment yourself, for example after a milestone:

```ts
const compacted = await client.responses.compact({ model: 'gpt-5', input: conversation });

const next = await client.responses.create({
  model: 'gpt-5',
  input: [...compacted.output, { role: 'user', content: 'Add two more days to the itinerary.' }],
  store: false,
});
```

```python
compacted = client.responses.compact(model="gpt-5", input=conversation)

next_response = client.responses.create(
    model="gpt-5",
    input=[*compacted.output, {"type": "message", "role": "user", "content": next_user_message()}],
    store=False,
)
```

## What does the compacted output contain?

- **One opaque compaction item.** You cannot read it, edit it, or ask what it kept.
- **Possibly some retained items.** OpenAI says the compacted window "generally contains more than just the compaction item. It can also include retained items from the previous window." It does not say which.
- **Your user messages.** Vercel's AI Gateway docs, which proxy the endpoint, describe the output as "your user messages, followed by one opaque `compaction` item that stands in for everything else" ([Vercel](https://vercel.com/docs/ai-gateway/sdks-and-apis/responses/compaction)).
- **Stacked items over time.** Compact again later and, per the same Vercel page, "a new `compaction` item stacks on top of the previous one."

Assistant turns, tool calls, tool output and reasoning are folded into the item. If a detail did not make it in, there is no way to get it back from the item.

## What does compaction cost?

OpenAI's compaction guide does not publish a separate price. Vercel's gateway docs say a compaction request "runs the model over your conversation, and you pay for it like any other Responses API request: input, cached input, reasoning, and output tokens from the response's `usage` block" ([Vercel](https://vercel.com/docs/ai-gateway/sdks-and-apis/responses/compaction)).

So each compaction is a full model pass over the history at the moment it runs, and the requests after it are smaller until the next threshold. Read the `usage` on the response that compacts to see the cost for your model.

## Is compaction ZDR-friendly?

Yes, when you keep storage off. OpenAI says server-side compaction "is ZDR-friendly when you set `store=false`", and the standalone endpoint "is fully stateless and ZDR-friendly" ([compaction guide](https://developers.openai.com/api/docs/guides/compaction)). Everything needed to continue lives in the item you carry in `input`.

## Limits

- **OpenAI models only.** The compaction item is OpenAI server-side state. Vercel's gateway returns a `400` for compaction requests to other providers' models and does not fail over ([Vercel](https://vercel.com/docs/ai-gateway/sdks-and-apis/responses/compaction)).
- **Opaque.** You cannot show a user what the agent remembers, audit it, or delete one fact from it.
- **No recall on demand.** What was folded away does not come back when the conversation returns to it.
- **Responses only.** No Chat Completions equivalent.
- **It acts on size.** A token threshold decides when it runs, not what the conversation still needs.

## Compaction with the Agents SDK

The OpenAI Agents SDK for Python has `OpenAIResponsesCompactionSession`, which wraps another session (such as `SQLiteSession`) and compacts stored history with the Responses API, checking after each turn whether to compact. Its docs say not to wrap `OpenAIConversationsSession` with it, because the two manage history in different ways ([Sessions](https://openai.github.io/openai-agents-python/sessions/)).

## Side by side

| | Compaction | Threadless AI |
|---|---|---|
| When it acts | When tokens cross your threshold, or when you call `/responses/compact` | Every call: the request is sized for a 200k-token context window |
| What the model gets | An encrypted item, plus recent items | The latest messages word for word, the facts from older messages, and older messages that matter to what was just asked |
| What is kept | An encrypted item, plus some retained items | Facts your model wrote, readable, plus the full stored history |
| Can you read what was kept | No | Yes: facts in every request, and `export` returns everything |
| Do details come back later | Only what the item carried | Yes: older messages that matter come back, with their dates, when the conversation turns to them |
| Sense of time | Turn order | Recalled messages and facts carry their dates |
| Changed facts | Inside the item | Newer facts replace older ones |
| Works with Chat Completions | No, Responses only | Yes, and Responses |
| Models | OpenAI only | Any model the OpenAI API you call accepts |
| ZDR / `store: false` | Yes | Yes: we drop `store`; conversation content is processed on our servers ([Security](https://threadlessai.com/security)) |
| Cost per compaction | A model pass over the history, at normal token rates | No pass over the history: your model notes the key facts with one note tool call before older messages stop being sent word for word |
| Ongoing cost | Smaller requests until the next threshold | The memory's meters, and smaller requests |

## When compaction is enough

- Conversations that run long once, then end: a long coding task, a long document session.
- When you do not need to know or show what the agent remembers.
- When everything must stay inside OpenAI's platform.

## When a memory layer fits better

- **Conversations that run for weeks.** An agent that works with the same person over time needs what is current in view and the rest recallable, not one compressed past.
- **Details that matter later.** An order number from three weeks ago needs to come back exactly when the user asks about it.
- **Auditability.** Facts are sentences you can read, export and delete.
- **Chat Completions.** Compaction is a Responses feature; memory works with both formats.

## Using them together

Not needed: Threadless AI keeps every request sized for a 200k-token context window, so the threshold you would set for compaction is not reached. If you pass `previous_response_id` or `store`, they are dropped from the request, because we hold the history.

## Questions people ask

### Is compaction the same as summarisation?

Close, but not readable. A summary is text you can inspect; compaction produces an encrypted item meant only for the model. Both replace detail with something shorter, and neither brings the detail back later.

### Can I see what compaction kept?

No. OpenAI describes the compaction item as opaque and not intended to be human-interpretable. You can see any retained items around it, but not what the item itself carries.

### Does compaction lose information?

It is designed to keep what the next turns need in fewer tokens, so some detail goes by design. Which detail is not something you choose or can inspect.

### Does compaction work with previous_response_id?

Yes. Set `context_management` with a `compact_threshold` and keep sending only the newest message; the server compacts when the chain gets too large. Do not prune items by hand when chaining.

### Is compaction ZDR compatible?

Yes. Server-side compaction is ZDR-friendly with `store=false`, and the standalone `/responses/compact` endpoint is stateless.

### Does compaction work with other providers?

No. The item is OpenAI server-side state, so only OpenAI models can use it.

## Related

- [previous_response_id and the Conversations API](https://threadlessai.com/guides/previous-response-id-and-conversations-api)
- [LLM context window management: the four approaches](https://threadlessai.com/guides/context-window-management)
- [OpenAI Responses API memory](https://threadlessai.com/guides/responses-api-memory)
- [Fix OpenAI context_length_exceeded errors](https://threadlessai.com/guides/openai-context-length-exceeded)
