-
Notifications
You must be signed in to change notification settings - Fork 522
Description
OpenAI Stream Wrapper Missing Attribute Delegation Causes AttributeError
Problem Description
Users integrating AgentOps with ChainLit and other frameworks encounter the following error when accessing attributes on OpenAI streaming responses:
'OpenAIAsyncStreamWrapper' object has no attribute 'choices'
Environment Details
- AgentOps version: 0.4.16
- OpenAI version: 1.90.0
- ChainLit version: 2.5.5
- Integration: ChainLit-based chat (xpander)
Root Cause
The OpenAIAsyncStreamWrapper and OpenaiStreamWrapper classes in agentops/instrumentation/providers/openai/stream_wrapper.py act as proxies around OpenAI stream objects but don't implement __getattr__ to delegate attribute access to the underlying stream.
When code tries to access stream.choices or other stream attributes, Python looks for the attribute on the wrapper class, can't find it, and raises an AttributeError.
Code Example
def run_completion(messages: List[Any]):
client = AsyncOpenAI(api_key=getenv("HOSTED_ASSISTANTS_WEBUI_OPENAI_API_KEY", ""))
return client.chat.completions.create(
messages=messages_with_current_date,
tool_choice="required" if is_sub_agent else "auto",
tools=xpander.agent.get_tools(),
**settings,
)
# This fails when AgentOps wraps the stream:
# stream.choices # AttributeError: 'OpenAIAsyncStreamWrapper' object has no attribute 'choices'Expected Behavior
The stream wrapper should transparently proxy all attributes to the underlying OpenAI stream object, allowing users to access choices, model, id, usage, and other stream attributes without errors.
Impact
- Breaks integration with ChainLit and other frameworks that access stream attributes
- Prevents users from accessing standard OpenAI stream response properties
- Affects both sync and async OpenAI streaming workflows
Solution
Implement __getattr__ method in both wrapper classes to delegate attribute access to the underlying stream object.
Fix
The fix adds __getattr__ methods to both OpenAIAsyncStreamWrapper and OpenaiStreamWrapper classes that delegate attribute access to self._stream, making the wrappers transparent to users while maintaining all instrumentation functionality.