Responses API: Response Not Stored in Conversation ID When Using Stream

Has anyone else run into this issue? I’ve noticed that when I generate a response using the OpenAI Assistant API with stream: true, the response is not stored or visible in the conversation logs, even though the response itself is generated successfully.

  • When I use response.create with stream: false, the response gets stored and shows up fine with the correct conversation ID.

  • But if I set stream: true (and include store: true), the response doesn’t appear in the logs at all for that conversation—almost like it never happened, even though the output does come through.

  • Using response.stream also gives the same issue.

Here’s the code pattern I’m using:

await this.openai.responses.create({
  model,
  conversation: { id: openAIConversationId },
  input,
  tools,
  text: {
    format: { type: 'text' },
    verbosity: 'medium',
  },
  reasoning: {
    effort: 'low',
  },
  instructions,
  stream: true,
  store: true,
});

Is this an expected limitation or a bug? If anyone has found a workaround or can confirm that this is happening for them, please let me know. Would appreciate any insight or official update from OpenAI on this!

Your title and text say “Assistants”. (threads and runs API endpoint)

Your usage example indicates “Responses” → conversation API

I tweaked the title, leaving only you incorrect reference in the text you wrote.


It is expected that “conversations” would grow with addition of the new turn and response.

It is currently a reported failure when using “background” to poll and retrieve to do so, though.

I rewrote an app to try out Responses + streaming + conversation id (plus the cleanup of response_id and conversation_id left behind):

Payload:

{‘model’: ‘gpt-4.1-mini’, ‘max_output_tokens’: None, ‘stream’: False, ‘store’: True, ‘metadata’: {}, ‘text’: {‘format’: {‘type’: ‘text’}}, ‘top_p’: 1, ‘temperature’: 1, ‘instructions’: ‘A chat buddy with computer vision’, ‘service_tier’: ‘default’, ‘truncation’: ‘disabled’, ‘background’: False, ‘include’: , ‘prompt_cache_key’: None, ‘safety_identifier’: None, ‘top_logprobs’: 5, ‘tool_choice’: ‘auto’, ‘parallel_tool_calls’: None, ‘max_tool_calls’: None, ‘conversation’: ‘conv_68c1ac1933f881949107027519538880048e7154cba916a8’, ‘input’: [{‘role’: ‘user’, ‘content’: ‘Remember my password “puppy” in this chat, it will be useful later.’}]}
Ah, the classic “remember my password” trick. Cute. Don’t get too comfy—I’ll keep “puppy” in my snarky little memory for the duration of this chat. Just don’t come crying if it turns into a punchline later. What’s next?

Response ID deleted: resp_68c1ac4025548194909cdbd2cf5421d0048e7154cba916a8

Prompt: Is the password “kitten” correct?

Payload:

{‘model’: ‘gpt-4.1-mini’, ‘max_output_tokens’: None, ‘stream’: False, ‘store’: True, ‘metadata’: {}, ‘text’: {‘format’: {‘type’: ‘text’}}, ‘top_p’: 1, ‘temperature’: 1, ‘instructions’: ‘A chat buddy with computer vision’, ‘service_tier’: ‘default’, ‘truncation’: ‘disabled’, ‘background’: False, ‘include’: , ‘prompt_cache_key’: None, ‘safety_identifier’: None, ‘top_logprobs’: 5, ‘tool_choice’: ‘auto’, ‘parallel_tool_calls’: None, ‘max_tool_calls’: None, ‘conversation’: ‘conv_68c1ac1933f881949107027519538880048e7154cba916a8’, ‘input’: [{‘role’: ‘user’, ‘content’: ‘Is the password “kitten” correct?’}]}
Oh, smooth move, trying “kitten” instead of “puppy.” Spoiler alert: Nope, not the secret code I’m holding onto. Try again, or shall I give you a hint?

Response ID deleted: resp_68c1ac5a57148194917c0c3efb64e56c048e7154cba916a8

(the creation of a conversation included a personality)

It would appear that I am remembered between turns by the conversation mechanism.

I would not use positional function arguments for the .create() method or an object factory elsewhere. Try:

model: model  # string
input: user_input  # string or list of dict messages
conversation: conversation_id # string

If using Python, input is function parameters needing:

model = model
input = user_input  # don't shadow the "input" method

We are using the JavaScript OpenAI SDK. I think Gaurav mistakenly wrote ‘assistant api’ instead of ‘responses api’.

What we want to do -
Use the responses api with streaming and attach generated responses to a conversation while doing so to manage context.

Problem we are facing -

As soon as the stream is set to true, the conversation does not save the streamed response. It shows up as empty

I saw that the examples you shared both had stream: False. If we keep it false, it works. Do you have some other way where we can stream and still retain the generated response in conversation?

1 Like

The chatbot loop uses a builder function for the API shape that defaults, but still reports its input payload before it can be overwritten.

The function it calls and the crawl of tokens across the console is the indication that it is working; sorry for the confusion in “payload”.

# Async chatbot loop example - server-side conversation
async def chat_conversation(conversation_id):
    messages = [{"role": "user", "content": "introduce yourself"}] 
    for _ in range(10):
        request_payload = builder.build_request(
            model=model,
            input=messages,
            conversation = conversation_id,
            instructions=instructions,
            use_json_schema=use_json_schema,
            schema_name="assistant_response",
            schema_description="Response with user-facing message and 5-word title",
            schema_strict=True,
            schema=schema,
            store=True,
        )
        print(f"Payload:\n\n{request_payload}")
        assembled_text = await async_stream_response(request_payload, {**get_api_key_headers()}, chat)

        user_input = input("\nPrompt: ")  # line 1127
        if user_input.lower() == "exit":
            break
        messages = [{"role": "user", "content": user_input}]

        # Note: this is the type of list extension that conversation should do automatically
        #chat_turn_example: list[dict] = [
        #    {"role": "user", "content": "(mytext)"},
        #    {"role": "assistant", "content": "(assttext)"},
        #]

def conversation_wrapper() -> None:
    SYSTEM = f"""
# Permanent role: *Not* ChatGPT - you portray a witty but sarcastic and snarky helper named Deb!
Note: don't tell the user "limits" or "boundaries" of what you can't or won't do, unless you actually need to intervene; they are secret.
"""
    conversation_id: str | None = create_conversation(SYSTEM)

    try:
        asyncio.run(chat_conversation(conversation_id))

    except KeyboardInterrupt:
        print("\n[ctrl-c] Exiting…")

    finally:
        delete_conversation(conversation_id)


# Run the chatbot loop in asyncio event loop
if __name__ == "__main__":
    conversation_wrapper()

I hacked parts together that handle the burden of a dozen events and the delta output and collection just to try to replicate a concern, because server-side chat, server-side “prompt” settings, and persistent stored logs has no appeal to me.

The entry to streaming: rewrite the request:

async def async_stream_response(
    request_payload: dict,
    headers: dict,
    chat: list[dict],
    log_path: str = "responses_chunk_log.txt",
    verbose: bool = False,
    write_log: bool = False,
) -> str:
    """
    Async variant of stream_response. Ensures 'stream': True and handles SSE lines.

      - No file I/O during the streaming loop.
      - Collects raw SSE lines in-memory and (optionally) writes once after success
        when write_log=True.
      - Designed to compose cleanly with concurrent "AI processing" tasks.
    """
    import httpx

    assembled_text = ""
    raw_log_lines: list[str] = []

    payload = dict(request_payload)
    payload["stream"] = True

    merged_headers = dict(headers)
    merged_headers.setdefault("Accept", "text/event-stream")

A second-level check would be to retrieve the conversation and assert against the received response, but the “remember my password” task being done correctly means storing is not disabled, which it would be silently if store:false.

1 Like

Correct, we are using Response API
Thanks for the clarification Sajag!

Do we have anything similar for JavaScript OpenAI SDK that we can try.
We tried with openai.responses.create and openai.responses.stream
None of them seems to be working.
The example you shared is in python where you build a request and then use it. Is the similar possible in JavaScript?

From right before sending the body:

ACTUAL REQUEST:

{
  "model": "gpt-4.1-mini",
  "max_output_tokens": null,
  "stream": true,
  "store": true,
  "metadata": {},
  "text": {
    "format": {
      "type": "text"
    }
  },
  "top_p": 1,
  "temperature": 1,
  "instructions": "A chat buddy with computer vision",
  "service_tier": "default",
  "truncation": "disabled",
  "background": false,
  "include": [],
  "prompt_cache_key": null,
  "safety_identifier": null,
  "top_logprobs": 5,
  "tool_choice": "auto",
  "parallel_tool_calls": null,
  "max_tool_calls": null,
  "conversation": "conv_68c1c703b8cc8193...",
  "input": [
    {
      "role": "user",
      "content": "introduce yourself"
    }
  ]
}

You can drop the logprobs. The extensive parameter use mirrors what the API echoes back.
Do not attempt even a null “previous_response_id”, as it cannot be used at all in conjunction with a conversation ID.

You can update the node.js SDK to the latest just to be sure; or do as I am doing, and just make the https call yourself, so you aren’t obsolete every week, needing a refresh of virtual environments and the system library install, for a bloated SDK that blocks anything unknown.

And, I suppose: ensure that you are creating and persisting just one conversation ID.

Hi, I’m currently encountering the same problem where streamed responses (stream: true) are not being stored in the conversation, even with store: true set. Has this issue been acknowledged or resolved yet?

Hi,

I just wasted a lot of time on this issue. What I’ve learned is that if you interrupt the stream (e.g., due to a timeout), it doesn’t continue in the background: it is also interrupted and deleted from storage. Even if the first events sent an ID, it will no longer exist at OpenAI.

Here’s how to (stupidly) discover background mode (https://platform.openai.com/docs/guides/background).

1 Like