Summary
The OpenAI ResponseStream instrumentation only wraps the each method, but the upstream OpenAI::Helpers::Streaming::ResponseStream class also exposes a text convenience method that bypasses each and returns text deltas directly. Users who consume the Responses API stream via stream.text.each { |t| ... } get zero tracing.
This is inconsistent within the same SDK: the Chat Completions integration wraps both each and text on ChatCompletionStream, but the Responses integration only wraps each on ResponseStream.
What is missing
ResponseStream#text is not wrapped. The upstream SDK's text method returns a fused chain yielding ResponseTextDeltaEvent content that reads from the underlying HTTP stream directly, bypassing the prepended each method on the ResponseStream object.
How the Chat integration handles this (for reference)
The Chat integration wraps both methods on ChatCompletionStream at lib/braintrust/contrib/openai/instrumentation/chat.rb:152-169:
module ChatCompletionStream
module InstanceMethods
def each(&block) # line 152 — wrapped ✓
...
end
def text # line 159 — wrapped ✓
...
Enumerator.new do |y|
trace_consumption(ctx) do
original_enum.each { |t| y << t }
end
end
end
end
end
The same pattern should be applied to ResponseStream. The ctx[:consumed] guard already prevents double-tracing when both text and each are wrapped on the same object.
Upstream ResponseStream methods
The upstream class (OpenAI::Helpers::Streaming::ResponseStream) exposes:
each — wrapped ✓
text — NOT wrapped ✗ — bypasses each, reads from internal stream directly
until_done — covered (calls each internally)
get_final_response — covered (consumes stream via each)
get_output_text — covered (delegates to get_final_response)
Only text needs a wrapper because it is the only consumption method that bypasses each.
Braintrust docs status
not_found — Braintrust docs do not mention text as a stream consumption method or differentiate between stream consumption patterns.
Upstream sources
Local repo files inspected
lib/braintrust/contrib/openai/instrumentation/responses.rb:118-183 — ResponseStream module only wraps each (line 128)
lib/braintrust/contrib/openai/instrumentation/chat.rb:140-225 — ChatCompletionStream module wraps both each (line 152) and text (line 159)
lib/braintrust/contrib/openai/patcher.rb:113-119 — ResponsesPatcher.patch_response_stream patches ResponseStream class
Summary
The OpenAI
ResponseStreaminstrumentation only wraps theeachmethod, but the upstreamOpenAI::Helpers::Streaming::ResponseStreamclass also exposes atextconvenience method that bypasseseachand returns text deltas directly. Users who consume the Responses API stream viastream.text.each { |t| ... }get zero tracing.This is inconsistent within the same SDK: the Chat Completions integration wraps both
eachandtextonChatCompletionStream, but the Responses integration only wrapseachonResponseStream.What is missing
ResponseStream#textis not wrapped. The upstream SDK'stextmethod returns a fused chain yieldingResponseTextDeltaEventcontent that reads from the underlying HTTP stream directly, bypassing the prependedeachmethod on theResponseStreamobject.How the Chat integration handles this (for reference)
The Chat integration wraps both methods on
ChatCompletionStreamatlib/braintrust/contrib/openai/instrumentation/chat.rb:152-169:The same pattern should be applied to
ResponseStream. Thectx[:consumed]guard already prevents double-tracing when bothtextandeachare wrapped on the same object.Upstream
ResponseStreammethodsThe upstream class (
OpenAI::Helpers::Streaming::ResponseStream) exposes:each— wrapped ✓text— NOT wrapped ✗ — bypasseseach, reads from internal stream directlyuntil_done— covered (callseachinternally)get_final_response— covered (consumes stream viaeach)get_output_text— covered (delegates toget_final_response)Only
textneeds a wrapper because it is the only consumption method that bypasseseach.Braintrust docs status
not_found— Braintrust docs do not mentiontextas a stream consumption method or differentiate between stream consumption patterns.Upstream sources
ResponseStream: https://github.com/openai/openai-ruby/blob/main/lib/openai/helpers/streaming/response_stream.rb — definestext,until_done,get_final_response,get_output_textChatCompletionStream: https://github.com/openai/openai-ruby/blob/main/lib/openai/helpers/streaming/chat_completion_stream.rb — definestext(already wrapped by this SDK)Local repo files inspected
lib/braintrust/contrib/openai/instrumentation/responses.rb:118-183—ResponseStreammodule only wrapseach(line 128)lib/braintrust/contrib/openai/instrumentation/chat.rb:140-225—ChatCompletionStreammodule wraps botheach(line 152) andtext(line 159)lib/braintrust/contrib/openai/patcher.rb:113-119—ResponsesPatcher.patch_response_streampatchesResponseStreamclass