Skip to content

Python: Support Responses API server-side compaction with store=false - #8891

Open
Dineshsuriya D (droideronline) wants to merge 8 commits into
microsoft:mainfrom
droideronline:feature/responses-compaction-store-false
Open

Dineshsuriya D (droideronline) wants to merge 8 commits into
microsoft:mainfrom
droideronline:feature/responses-compaction-store-false

Conversation

@droideronline

Copy link
Copy Markdown
Contributor

Motivation & Context

The Responses API supports server-side compaction via context_management, including with store=false. When the context crosses compact_threshold, the service emits an encrypted compaction output item. In stateless (input-array) mode the caller replays that item on the next request and can drop the items before it.

OpenAIChatClient and FoundryChatClient already forwarded context_management to the service, but dropped the compaction item as unparsed output. With store=false every later turn resent the full uncompacted history, so compaction saved no tokens.

Description & Review Guide

  • What are the major changes?
    • Core: new "compaction" content type and Content.from_compaction(protected_data=..., id=...). The encrypted payload lives in protected_data (like encrypted reasoning), so it round-trips through history serialization.
    • OpenAI Responses client (inherited by FoundryChatClient):
      • Compaction output items are parsed into compaction content in both non-streaming responses and response.output_item.done stream events.
      • For stateless requests, the latest compaction item is replayed as a {"type": "compaction", "encrypted_content", "id"} input item, and messages before the message that contains it are dropped, except system/developer messages. Pruning is per message so tool calls stay paired with their results, and it runs before the stateless reasoning-group validation.
      • With previous_response_id / conversation continuation, the compaction item is not re-sent and nothing is pruned, as the docs require.
      • context_management is declared on OpenAIChatOptions (and therefore FoundryChatOptions).
  • What is the impact of these changes?
    • store=false conversations using context_management now carry the compacted state forward and send much smaller requests after compaction. Behavior without compaction items is unchanged. Other providers skip the new content type like any unsupported content.
  • What do you want reviewers to focus on?
    • Whether a core content type is the right home for the compaction item versus a provider-specific representation.
    • The pruning rule (message granularity, keeping system/developer messages).

Not included: a wrapper for the standalone responses.compact endpoint, and surfacing the streaming response.compaction.compacting progress event.

Related Issue

Fixes #8890

Contribution Checklist

  • The code builds clean without any errors or warnings
  • All unit tests pass, and I have added new tests where possible
  • The PR follows the Contribution Guidelines
  • This PR is linked to an issue and there is no other open PR for this issue (see Related Issue above).
  • This is not a breaking change. If it is a breaking change, add the breaking change label (or add "[BREAKING]" to the title prefix, before or after any language prefix) — a workflow keeps the label and title prefix in sync automatically.

Add a core compaction content type and teach the OpenAI Responses client
(inherited by FoundryChatClient) to preserve compaction output items in
streaming and non-streaming responses. For stateless requests the latest
compaction item is replayed as an input item and the history before it,
other than system/developer messages, is no longer sent. With service-side
storage the item is not re-sent and nothing is pruned. context_management
is now a typed option.

Fixes microsoft#8890

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@agent-framework-automation agent-framework-automation Bot added the python Usage: [Issues, PRs], Target: Python label Sep 30, 2026
@droideronline

Copy link
Copy Markdown
Contributor Author

Fixed the failing "Test Typing Checks" job in 97decb4: the compaction agent test now declares its options as OpenAIChatOptions so mypy and pyrefly accept the context_management entry. No library code changed.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dineshsuriya D (@droideronline) I don't think we should merge this as a separate OpenAI-specific compaction path yet. Core already exposes provider-neutral compaction through CompactionStrategy, the chat client's compaction_strategy, and CompactionProvider, while this adds a second "compaction" concept: a public Content type/factory whose actual contract is an OpenAI Responses encrypted item, with pruning and replay implemented only in the OpenAI client. That leaves callers and future providers with two compaction models that do not compose, and makes the core contract difficult to evolve beyond OpenAI's current wire shape. Could we step back and propose how server-side compaction dovetails with the existing compaction abstraction—particularly how client-side strategies, provider-owned opaque continuation state, and non-OpenAI providers compose—before fixing the public Content contract? At minimum, the new Content.from_compaction surface and content type need to be staged as experimental under the core feature-lifecycle rules until that design is settled.

Add ExperimentalFeature.SERVER_COMPACTION and mark Content.from_compaction
and ContextManagementOptions with it, and document the staged surface in
core AGENTS.md and PACKAGE_STATUS.md, until the design for composing
server-side compaction with CompactionStrategy is settled.
@droideronline

Copy link
Copy Markdown
Contributor Author

Eduard van Valkenburg (@eavanvalkenburg) thanks, agreed that this shouldn't add a second compaction model. I've staged the new surface as experimental in 572feb2: new ExperimentalFeature.SERVER_COMPACTION on Content.from_compaction and ContextManagementOptions, documented in core AGENTS.md and PACKAGE_STATUS.md, following the COMPUTER_USE precedent. Moving this PR to draft while we settle the design. Here is a proposal for how server-side compaction could dovetail with the existing abstraction:

1. Server compaction is expressed with the existing exclusion/summary annotations

When a provider returns a compaction item, the client records it the same way a SummarizationStrategy records a summary:

  • The message holding the compaction content becomes a summary group, with _summary_of_message_ids / _summary_of_group_ids pointing at the groups it covers (everything before it except system groups).
  • Those covered groups get _excluded=True with a new _exclude_reason="server_compaction", and _summarized_by_summary_id back to it.
  • Grouping stays atomic, so reasoning/tool-call groups are never split, and _validate_reasoning_groups_for_stateless_replay keeps working unchanged.

Pruning then comes from the generic project_included_messages path instead of OpenAI-specific code, and CompactionProvider / history skip_excluded persist and load it like any other compaction.

2. The opaque payload stays provider-owned continuation state

The compaction content is just the carrier for the provider's opaque state (protected_data plus a provider marker in additional_properties), similar to encrypted reasoning. The core contract would be "opaque, provider-scoped compacted state for the groups it summarizes", not OpenAI's wire shape. Each provider decides whether it can replay it; providers that can't simply skip it.

3. Composition with client-side strategies

  • Client-side strategies see the server summary as an ordinary summary group, so TruncationStrategy, SlidingWindowStrategy, etc. keep working on top. Excluding the server summary group with a local strategy is allowed; the provider then falls back to sending the remaining included messages.
  • A small capability flag on the chat client (for example SUPPORTS_SERVER_COMPACTION, alongside STORES_BY_DEFAULT) would let token-budget strategies avoid compacting history the service is about to compact itself. That is optional and could be a follow-up.
  • With previous_response_id / conversation continuation nothing changes: the service owns the state and nothing is replayed or pruned.

4. Non-OpenAI providers and switching providers

Anthropic's context management returns comparable compaction blocks, so the same annotations would fit there. The open trade-off is switching providers mid-conversation: a provider that can't read the opaque state gets neither it nor the excluded history. Options are (a) accept that, as with encrypted reasoning today, or (b) have the projection re-include server_compaction-excluded groups when the active client can't replay the compaction content. I lean towards (b) since the original messages are still in history.

Questions

  1. Does mapping server compaction onto the summary/exclusion annotations match how you'd like this to evolve, or would you prefer a dedicated group kind?
  2. Should the provider-switching fallback in (4b) be part of the first version?
  3. Is a separate ADR wanted before I rework the PR, or is agreeing here enough?

If this direction works, I'll rework the PR to drop the OpenAI-specific pruning and implement (1) and (2), keeping everything under SERVER_COMPACTION.

@droideronline
Dineshsuriya D (droideronline) marked this pull request as draft October 1, 2026 11:10
@agent-framework-automation agent-framework-automation Bot added the documentation Usage: [Issues, PRs], Target: documentation in the code base and learn docs label Oct 1, 2026
@droideronline
Dineshsuriya D (droideronline) marked this pull request as ready for review October 1, 2026 11:11
@droideronline

Copy link
Copy Markdown
Contributor Author

Merged latest main (a5173fd). The previous markdown-link-check failure was transient 504 responses from github.com on links outside this PR. The workflow runs for the new commit are waiting for maintainer approval; could someone approve them when convenient? Thanks!

…paction-store-false

# Conflicts:
#	python/packages/openai/agent_framework_openai/_chat_client.py
@eavanvalkenburg

Copy link
Copy Markdown
Member

/review

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

MAF Automated Review — Iteration 1

Result: Findings reported
Scope: full PR (7 commit(s)): ef81873c944a, 97decb470796, 8f4148e75d20, 572feb2b8cb1, a5173fd3c2d9, c0a3518c76ff, 975c0874cb1b
Model: gpt-5.6-sol

Overview

The change consistently parses and serializes compaction items across streaming, non-streaming, OpenAI, and Foundry paths, with tests covering continuation mode, stateless replay, instruction preservation, and reasoning-group validation. The residual correctness risk is that pruning recognizes a compaction marker more broadly than serialization does, so malformed persisted or caller-created content can silently remove usable history without supplying replacement state.

Reviewed the supplied pull-request change set across correctness, security/reliability, architecture, and failure behavior.
1 verified finding remained after source verification (1 medium) across 1 file. Details are attached to the affected lines below.

Affected areas: python/packages/openai/agent_framework_openai/_chat_client.py

Comment thread python/packages/openai/agent_framework_openai/_chat_client.py Outdated
…g it

Ignore compaction content without a replayable payload when choosing the boundary.
@eavanvalkenburg

Copy link
Copy Markdown
Member

Dineshsuriya D (@droideronline) Thanks for the work here. Before merging, we want to spec this out further: server-side Responses compaction is currently an OpenAI service-specific capability, and we need to be careful about the Agent Framework abstraction and portability contract. Please hold further implementation changes while we work through the design on #8890.

This branch was successfully deployed

1 active deployment
github-app-auth — 6f5fa9ea Deployed Oct 14, 2026 by droideronline via add_label #25372
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Usage: [Issues, PRs], Target: documentation in the code base and learn docs python Usage: [Issues, PRs], Target: Python

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Python: [Feature]: Support Responses API server-side compaction (context_management) with store=false

3 participants