SPB Git

Repository Public

compaction.md 13.9 KB 492 lines markdown

1# Compaction23> For the complete documentation index, see [llms.txt](/llms.txt). Markdown versions of documentation pages are available by appending `.md` to the page URL.45## Overview67To support long-running interactions, you can use compaction to reduce context8size while preserving state needed for subsequent turns.910Compaction helps you balance quality, cost, and latency as conversations grow.1112## Server-side compaction1314You can enable server-side compaction in a Responses create request15(`POST /responses` or `client.responses.create`) by setting16`context_management` with `compact_threshold`.1718- When the rendered token count crosses the configured threshold, the server19  runs server-side compaction.20- No separate `/responses/compact` call is required in this mode.21- The response stream includes the encrypted compaction item.22- ZDR note: server-side compaction is ZDR-friendly when you set `store=false`23  on your Responses create requests.2425The returned compaction item carries forward key prior state and reasoning into26the next run using fewer tokens. It is opaque and not intended to be27human-interpretable.2829For stateless input-array chaining, append output items as usual. If you are30using `previous_response_id`, pass only the new user message each turn. In both31cases, the compaction item carries context needed for the next window.3233Latency tip: After appending output items to the previous input items, you can34drop items that came before the most recent compaction item to keep requests35smaller and reduce long-tail latency. The latest compaction item carries the36necessary context to continue the conversation. If you use37`previous_response_id` chaining, do not manually prune.3839## User journey40411. Call `/responses` as usual, but include `context_management` with42   `compact_threshold` to enable server-side compaction.432. As the response streams, if the context size crosses the threshold, the server44   triggers a compaction pass, emits a compaction output item in the same stream,45   and prunes context before continuing inference.463. Continue your loop with one pattern: stateless input-array chaining (append47   output, including compaction items, to your next input array) or48   `previous_response_id` chaining (pass only the new user message each turn and49   carry that ID forward).5051<a id="server-side-compaction-user-flow"></a>5253## Example user flow5455```javascript56import OpenAI from "openai";57import { toResponseInputItems } from "openai/lib/responses/ResponseInputItems";5859const client = new OpenAI();6061const conversation = [62  {63    type: "message",64    role: "user",65    content: "Let's begin a long coding task.",66  },67];6869const response = await client.responses.create({70  model: "gpt-5.3-codex",71  input: conversation,72  store: false,73  context_management: [{ type: "compaction", compact_threshold: 200_000 }],74});7576conversation.push(...toResponseInputItems(response.output));77console.log(response.output_text);78```7980```python81conversation = [82    {83        "type": "message",84        "role": "user",85        "content": "Let's begin a long coding task.",86    }87]8889while keep_going:90    response = client.responses.create(91        model="gpt-5.3-codex",92        input=conversation,93        store=False,94        context_management=[{"type": "compaction", "compact_threshold": 200000}],95    )9697    conversation.extend(response.output)9899    conversation.append(100        {101            "type": "message",102            "role": "user",103            "content": get_next_user_input(),104        }105    )106```107108```go109package main110111import (112	"bufio"113	"context"114	"encoding/json"115	"fmt"116	"os"117118	"github.com/openai/openai-go/v3"119	"github.com/openai/openai-go/v3/responses"120)121122func main() {123	client := openai.NewClient()124	conversation := []responses.ResponseInputItemUnionParam{125		responses.ResponseInputItemParamOfMessage("Let's begin a long coding task.", responses.EasyInputMessageRoleUser),126	}127	scanner := bufio.NewScanner(os.Stdin)128	for {129		response, err := client.Responses.New(context.Background(), responses.ResponseNewParams{130			Model: "gpt-5.3-codex",131			Store: openai.Bool(false),132			Input: responses.ResponseNewParamsInputUnion{OfInputItemList: conversation},133			ContextManagement: []responses.ResponseNewParamsContextManagement{{134				Type: "compaction", CompactThreshold: openai.Int(200000),135			}},136		})137		if err != nil {138			panic(err)139		}140		conversation = append(conversation, outputAsInput(response.Output)...)141		fmt.Println(response.OutputText())142		if !scanner.Scan() {143			break144		}145		conversation = append(conversation,146			responses.ResponseInputItemParamOfMessage(scanner.Text(), responses.EasyInputMessageRoleUser),147		)148	}149	if err := scanner.Err(); err != nil {150		panic(err)151	}152}153154func outputAsInput(output []responses.ResponseOutputItemUnion) []responses.ResponseInputItemUnionParam {155	input := make([]responses.ResponseInputItemUnionParam, 0, len(output))156	for _, item := range output {157		var converted responses.ResponseInputItemUnion158		if err := json.Unmarshal([]byte(item.RawJSON()), &converted); err != nil {159			panic(err)160		}161		input = append(input, converted.ToParam())162	}163	return input164}165```166167```java168import com.openai.client.OpenAIClient;169import com.openai.client.okhttp.OpenAIOkHttpClient;170import com.openai.core.JsonValue;171import com.openai.models.responses.EasyInputMessage;172import com.openai.models.responses.ResponseCreateParams;173import com.openai.models.responses.ResponseInputItem;174import java.util.ArrayList;175import java.util.List;176import java.util.Map;177178var conversation = new ArrayList<ResponseInputItem>();179conversation.add(180    ResponseInputItem.ofEasyInputMessage(181        EasyInputMessage.builder()182            .role(EasyInputMessage.Role.USER)183            .content("Let's begin a long coding task.")184            .build()));185186ResponseCreateParams params =187    ResponseCreateParams.builder()188        .model("gpt-5.3-codex")189        .inputOfResponse(conversation)190        .store(false)191        .putAdditionalBodyProperty(192            "context_management",193            JsonValue.from(List.of(Map.of("type", "compaction", "compact_threshold", 200000))))194        .build();195196var response = client.responses().create(params);197response.output().stream()198    .map(item -> JsonValue.from(item).convert(ResponseInputItem.class))199    .forEach(conversation::add);200conversation.add(201    ResponseInputItem.ofEasyInputMessage(202        EasyInputMessage.builder()203            .role(EasyInputMessage.Role.USER)204            .content("Now implement the next step.")205            .build()));206207client208    .responses()209    .create(params.toBuilder().inputOfResponse(conversation).build())210    .output()211    .stream()212    .flatMap(item -> item.message().stream())213    .flatMap(message -> message.content().stream())214    .flatMap(content -> content.outputText().stream())215    .forEach(text -> System.out.println(text.text()));216```217218```ruby219require "openai"220221client = OpenAI::Client.new222conversation = [223  {224    type: :message,225    role: :user,226    content: "Let's begin a long coding task."227  }228]229230response = client.responses.create(231  model: "gpt-5.3-codex",232  input: conversation,233  store: false,234  context_management: [235    {236      type: :compaction,237      compact_threshold: 200_000238    }239  ]240)241conversation.concat(response.output)242conversation << {243  type: :message,244  role: :user,245  content: "Now implement the next step."246}247next_response = client.responses.create(248  model: "gpt-5.3-codex",249  input: conversation,250  store: false,251  context_management: [252    {253      type: :compaction,254      compact_threshold: 200_000255    }256  ]257)258puts(next_response.output_text)259```260261262## Standalone compact endpoint263264For explicit control, use the265[standalone compact endpoint](https://developers.openai.com/api/reference/resources/responses/methods/compact) for266stateless compaction in long-running workflows.267268This endpoint is fully stateless and ZDR-friendly.269270You send a full context window (messages, tools, and other items), and the271endpoint returns a new compacted context window you can pass to your next272`/responses` call.273274The returned compacted window includes an encrypted compaction item that carries275forward key prior state and reasoning using fewer tokens. It is opaque and not276intended to be human-interpretable.277278Note: the compacted window generally contains more than just the compaction279item. It can also include retained items from the previous window.280281Output handling: do not prune `/responses/compact` output. The returned window282is the canonical next context window, so pass it into your next `/responses`283call as-is.284285### User journey for standalone compaction2862871. Use `/responses` normally, sending input items that include user messages,288   assistant outputs, and tool interactions.2892. When your context window grows large, call `/responses/compact` to generate a290   new compacted context window. The window you send to `/responses/compact`291   must still fit within your model's context window.2923. For subsequent `/responses` calls, pass the returned compacted window293   (including the compaction item) as input instead of the full transcript.294295<a id="standalone-compact-endpoint-user-flow"></a>296297### Example user flow298299```javascript300import OpenAI from "openai";301302const client = new OpenAI();303304const conversation = [{ role: "user", content: "Plan a trip to Kyoto." }];305306const compacted = await client.responses.compact({307  model: "gpt-6-astra",308  input: conversation,309});310311const nextInput = [312  ...compacted.output.map((item) => item),313  { role: "user", content: "Add two more days to the itinerary." },314];315316const response = await client.responses.create({317  model: "gpt-6-astra",318  input: nextInput,319  store: false,320});321322console.log(response.output_text);323```324325```python326# Full window collected from prior turns327long_input_items_array = [{"role": "user", "content": "Plan a trip to Kyoto."}]328329# 1) Compact the current window330compacted = client.responses.compact(331    model="gpt-6-astra",332    input=long_input_items_array,333)334335# 2) Start the next turn by appending a new user message336next_input = [337    *compacted.output,  # Use compact output as-is338    {339        "type": "message",340        "role": "user",341        "content": user_input_message(),342    },343]344345next_response = client.responses.create(346    model="gpt-6-astra",347    input=next_input,348    store=False,  # Keep the flow ZDR-friendly349)350```351352```go353package main354355import (356	"bufio"357	"context"358	"encoding/json"359	"fmt"360	"os"361362	"github.com/openai/openai-go/v3"363	"github.com/openai/openai-go/v3/responses"364)365366func main() {367	client := openai.NewClient()368	longInputItems := []responses.ResponseInputItemUnionParam{369		responses.ResponseInputItemParamOfMessage("Plan a trip to Kyoto.", responses.EasyInputMessageRoleUser),370	}371	compacted, err := client.Responses.Compact(context.Background(), responses.ResponseCompactParams{372		Model: "gpt-6-astra",373		Input: responses.ResponseCompactParamsInputUnion{OfResponseInputItemArray: longInputItems},374	})375	if err != nil {376		panic(err)377	}378	scanner := bufio.NewScanner(os.Stdin)379	if !scanner.Scan() {380		return381	}382	nextInput := append(outputAsInput(compacted.Output),383		responses.ResponseInputItemParamOfMessage(scanner.Text(), responses.EasyInputMessageRoleUser),384	)385	nextResponse, err := client.Responses.New(context.Background(), responses.ResponseNewParams{386		Model: "gpt-6-astra",387		Store: openai.Bool(false),388		Input: responses.ResponseNewParamsInputUnion{OfInputItemList: nextInput},389	})390	if err != nil {391		panic(err)392	}393	fmt.Println(nextResponse.OutputText())394}395396func outputAsInput(output []responses.ResponseOutputItemUnion) []responses.ResponseInputItemUnionParam {397	input := make([]responses.ResponseInputItemUnionParam, 0, len(output))398	for _, item := range output {399		var converted responses.ResponseInputItemUnion400		if err := json.Unmarshal([]byte(item.RawJSON()), &converted); err != nil {401			panic(err)402		}403		input = append(input, converted.ToParam())404	}405	return input406}407```408409```java410import com.openai.client.OpenAIClient;411import com.openai.client.okhttp.OpenAIOkHttpClient;412import com.openai.models.responses.EasyInputMessage;413import com.openai.models.responses.ResponseCompactParams;414import com.openai.models.responses.ResponseCompactionItemParam;415import com.openai.models.responses.ResponseCreateParams;416import com.openai.models.responses.ResponseInputItem;417import java.util.ArrayList;418419var compacted =420    client421        .responses()422        .compact(423            ResponseCompactParams.builder()424                .model("gpt-6-astra")425                .input("Plan a trip to Kyoto.")426                .build());427var input = new ArrayList<ResponseInputItem>();428for (var item : compacted.output()) {429  item.message().map(ResponseInputItem::ofResponseOutputMessage).ifPresent(input::add);430  item.reasoning().map(ResponseInputItem::ofReasoning).ifPresent(input::add);431  item.compaction()432      .map(433          value ->434              ResponseInputItem.ofCompaction(435                  ResponseCompactionItemParam.builder()436                      .id(value.id())437                      .encryptedContent(value.encryptedContent())438                      .build()))439      .ifPresent(input::add);440}441input.add(442    ResponseInputItem.ofEasyInputMessage(443        EasyInputMessage.builder()444            .role(EasyInputMessage.Role.USER)445            .content("Add restaurant recommendations.")446            .build()));447448client449    .responses()450    .create(451        ResponseCreateParams.builder()452            .model("gpt-6-astra")453            .inputOfResponse(input)454            .store(false)455            .build())456    .output()457    .stream()458    .flatMap(item -> item.message().stream())459    .flatMap(message -> message.content().stream())460    .flatMap(content -> content.outputText().stream())461    .forEach(text -> System.out.println(text.text()));462```463464```ruby465require "openai"466467client = OpenAI::Client.new468long_input = [469  {470    role: :user,471    content: "Plan a trip to Kyoto."472  }473]474compaction = client.responses.compact(475  model: "gpt-6-astra",476  input: long_input477)478next_input = [479  *compaction.output,480  {481    type: :message,482    role: :user,483    content: "Add restaurant recommendations."484  }485]486response = client.responses.create(487  model: "gpt-6-astra",488  input: next_input,489  store: false490)491puts(response.output_text)492```
Files main
Menu

Theme