Bug: server-side compaction is not emitted on Responses tool-call-only turns
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 31.6k
- Forks
- 5.7k
- Avg merge
- 1d 6h
- Merged PRs (30d)
- 96
Description
Confirm this is an issue with the Python library and not an underlying OpenAI API
- This is an issue with the Python library
Describe the bug
Describe the bug
I am using the Responses API through openai-python with:
context_management=[{"type": "compaction", "compact_threshold": 1000}]store=Falsegpt-5.4
I see different behavior depending on the output type of the turn:
-
For a long plain request,
response.outputcontains:messagecompaction
-
For a long request that returns only
function_call,response.outputcontains only:function_call
-
If I continue the tool loop and the next turn is again only
function_call, there is still nocompaction. -
Only when the model finally returns an assistant
messagedoesresponse.outputinclude:messagecompaction
This means that in tool-heavy agent loops with several consecutive tool-call turns, context can continue growing without any emitted compaction item, and the loop can eventually hit
context_length_exceeded before compaction appears.
I reproduced this through openai-python using both client.responses.create(...) and client.responses.parse(...).
If this is expected backend/API behavior rather than a Python SDK issue, please let me know and I can move the report.
To Reproduce
- Create a long input that is clearly above the compaction threshold.
- Enable server-side compaction with a very low threshold, for example:
context_management=[{"type": "compaction", "compact_threshold": 1000}] - Force the first turn to produce a
function_call. - Send the corresponding
function_call_output. - If the model produces another
function_call, observe that there is still nocompactionitem inresponse.output. - Observe that
compactiononly appears once the model finally emits an assistantmessage.
Observed output from my repro:
R1 input_tokens 5084
R1 output_types ['function_call']
R2 input_tokens 5119
R2 output_types ['function_call']
R3 input_tokens 5154
R3 output_types ['message', 'compaction']
For comparison, a plain long request with the same threshold produces compaction immediately:
CREATE input_tokens 5007
CREATE output_types ['message', 'compaction']
To Reproduce
import asyncio
from openai import AsyncOpenAI
from azure.identity.aio import DefaultAzureCredential, get_bearer_token_provider
AZURE_ENDPOINT = "https://<your-resource>.openai.azure.com/openai/v1/"
MODEL = "gpt-5.4"
async def main():
cred = DefaultAzureCredential()
token_provider = get_bearer_token_provider(
cred,
"https://cognitiveservices.azure.com/.default"
)
client = AsyncOpenAI(
base_url=AZURE_ENDPOINT,
api_key=token_provider,
)
long_text = "context " * 5000
tools = [{
"type": "function",
"name": "echo_tool",
"description": "Echo a short string",
"parameters": {
"type": "object",
"properties": {
"text": {"type": "string"}
},
"required": ["text"],
"additionalProperties": False
}
}]
cm = [{"type": "compaction", "compact_threshold": 1000}]
conversation = [{
"role": "user",
"content": (
long_text +
"\n\nCall echo_tool twice in sequence. "
"First with text=first. After I return the tool result, "
"call echo_tool again with text=second. "
"Only after the second tool result, answer DONE."
)
}]
for step in range(1, 5):
response = await client.responses.create(
model=MODEL,
input=conversation,
tools=tools,
store=False,
context_management=cm,
)
print(f"R{step} input_tokens:", response.usage.input_tokens)
print(f"R{step} output_types:", [getattr(i, 'type', None) for i in response.output])
conversation.extend(response.output)
function_calls = [i for i in response.output if getattr(i, "type", None) == "function_call"]
if function_calls:
for idx, fc in enumerate(function_calls, start=1):
conversation.append({
"type": "function_call_output",
"call_id": fc.call_id,
"output": f"tool-result-{step}-{idx}",
})
else:
break
await client.close()
await cred.close()
asyncio.run(main())
Code snippets
OS
Windows
Python version
3.11.5
Library version
openai 2.21.0
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reproducing the reported sequence with responses.create and responses.parse, using the supplied tool-call loop and context_management settings. Compare the SDK's returned output items with the underlying Responses API behavior. Done means determining whether the Python library drops compaction items on tool-call-only turns and, if so, defining a regression test for the corrected behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- api
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Needs clarification
- Newbie friendliness
- 38/100