Best practice for combining OpenAI streaming and structured outputs?

I already have normal OpenAI streaming working in my Bubble app using the Responses API.

Right now, I stream the assistant’s plain text response to the user in real time.

Now I’m trying to move from plain text responses to JSON structured outputs, so that the AI can return both:

  1. a message to display in the chat
  2. structured data to drive UI actions

For example:

{
“assistant_message”: “I created a section based on your reference material.”,
“proposal_type”: “section”
}

The issue is that when I use Structured Outputs with json_schema and stream: true, the streamed response.output_text.deltacontains the JSON text itself, like:

{“assistant_message”:“I created…

instead of streaming only the assistant_message value.

I also noticed that I can create a response field from:

response.output_text.done -> text

which seems to provide the final JSON string after completion.

My question is:

What is the best practice in Bubble for combining OpenAI streaming with JSON structured outputs?

Should I:

  • keep using the text stream for real-time display
  • capture the final JSON from response.output_text.done
  • parse it after completion for UI actions

Or is there a better way to stream only the chat message while still receiving the structured JSON at the end?

Any examples or recommended patterns would be very helpful.

I would not make the streaming text and the structured output do the same job.

The pattern I would use is:

  1. stream text only for the user-facing “typing” experience
  2. keep a final non-streamed structured response for the workflow/database step
  3. map only the fields the app actually needs
  4. fail clearly if a required path is missing or the model returns the wrong shape

That keeps the UI fast without making your database depend on whatever partial chunks arrive during streaming.

I built SchemaField Mapper for the final handoff piece: raw JSON/text in, explicit paths out, missing-field errors when the response shape changes. It is not a replacement for Bubble’s native JSON parsing; it is a deterministic guardrail for the values your workflow depends on. I can also set this up as a small fixed-fee Bubble workflow cleanup if that is the easier route.

Thanks, that makes sense.

So the safer pattern is to separate the user-facing stream from the final structured response, instead of trying to make one streamed JSON response handle both.

I’m currently leaning toward using streaming only for the chat display, then using the completed response / final JSON for the actual workflow and database updates.

Appreciate the explanation!