Skip to content

fix(openai_agents): tolerate a ResponseSpanData with no response - #3326

Open
BlueX888 wants to merge 1 commit into
confident-ai:mainfrom
BlueX888:fix/openai-agents-none-response-in-trace-properties
Open

BlueX888 wants to merge 1 commit into
confident-ai:mainfrom
BlueX888:fix/openai-agents-none-response-in-trace-properties

Conversation

@BlueX888

Copy link
Copy Markdown

Summary

update_trace_properties_from_span_data() in deepeval/openai_agents/extractors.py dereferences span_data.response unconditionally. The OpenAI Agents SDK only populates that attribute when sensitive data is included in the trace, so with RunConfig(trace_include_sensitive_data=False) every ResponseSpanData reaches the trace processor with response=None and the call raises AttributeError.

Why

Root cause, deepeval/openai_agents/extractors.py:431-440 (before this change):

def update_trace_properties_from_span_data(
    trace: Trace,
    span_data: Union["ResponseSpanData", "GenerationSpanData"],
):
    if isinstance(span_data, ResponseSpanData):
        if not trace.input:
            trace.input = parse_response_input(
                span_data.input, span_data.response.instructions   # <-- line 436
            )
        raw_output = parse_response_output(span_data.response.output)

The sibling extractor for the same span data already handles this case — update_span_properties_from_response_span_data() returns early when response is None (deepeval/openai_agents/extractors.py:95-98) — but the trace-level one does not.

The SDK side (agents/models/openai_responses.py:613-619, openai-agents 0.22.3) assigns the span data only behind if tracing.include_data()::

if tracing.include_data():
    span_response.span_data.response = response
    span_response.span_data.input = input
elif redacted_response_id_endpoint_is_trusted and self._uses_official_openai_endpoint():
    span_response.span_data._response_id = response.id

So with trace_include_sensitive_data=False (ModelTracing.ENABLED_WITHOUT_DATA) the span carries only _response_id; response and input stay None.

Impact: DeepEvalTracingProcessor.on_span_end() (deepeval/openai_agents/callback_handler.py:121) raises inside the SDK's processor loop, which logs and swallows it (agents/tracing/provider.py:162-173). Execution never reaches observer.__exit__ (callback_handler.py:136-138), so the LlmSpan stays open in current_span_context / trace_manager.active_spans, its Observer stays in span_observers, and the trace loses the span silently. Verified locally against openai-agents 0.22.3: before the fix the SDK logs Error in trace processor during on_span_end and current_span_context.get() is still non-None after the run; after the fix span_observers is empty and the current span is cleared.

Changes

  • deepeval/openai_agents/extractors.py — return early from update_trace_properties_from_span_data() when a ResponseSpanData has response=None, mirroring the existing guard in update_span_properties_from_response_span_data().
  • tests/test_integrations/test_openai_agents/test_extractors.py — regression test: build a ResponseSpanData(response=None, input=None) and call the extractor; it must not raise and must leave trace.input / trace.output unset.

No other files are touched; the GenerationSpanData branch is unchanged.

Testing

Regression test on the unpatched tree (test file present, extractors.py at HEAD~1):

$ PYTHONPATH=$PWD .../deepeval_lc_venv/bin/python -m pytest tests/test_integrations/test_openai_agents/test_extractors.py -p no:cacheprovider -q
                trace.input = parse_response_input(
>                   span_data.input, span_data.response.instructions
                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                )
E               AttributeError: 'NoneType' object has no attribute 'instructions'
deepeval/openai_agents/extractors.py:436: AttributeError
FAILED tests/test_integrations/test_openai_agents/test_extractors.py::test_update_trace_properties_without_response
1 failed in 0.13s

Same command on the patched tree:

1 passed in 0.02s

Whole openai_agents module, patched: 15 failed, 1 passed, 1 skipped; same tree with extractors.py reverted: 16 failed, 1 skipped. The failure sets are identical apart from the new test (red → green); the 15 remaining failures are pre-existing and environmental — openai.OpenAIError: Missing credentials ... set the OPENAI_API_KEY environment variable — since this sandbox has no OPENAI_API_KEY, and the CI job is gated on if: ${{ env.OPENAI_API_KEY != '' }}.

Format and lint:

$ .../bin/python -m black --check deepeval/openai_agents/extractors.py tests/test_integrations/test_openai_agents/test_extractors.py
2 files would be left unchanged.
$ .../bin/python -m ruff check deepeval/openai_agents/extractors.py tests/test_integrations/test_openai_agents/test_extractors.py
All checks passed!

(mypy is scoped to ^deepeval/telemetry/ by the repo's pre-commit config, so it does not cover this diff.)

Notes

Related, separate report: #3314 covers the same failure mode for GenerationSpanData with usage=None in update_span_properties_from_generation_span_data (a different function and a different span type); that is not addressed here. This change is limited to the ResponseSpanData branch of update_trace_properties_from_span_data.

update_trace_properties_from_span_data dereferenced span_data.response
unconditionally, but the OpenAI Agents SDK only populates response when
sensitive data is included in the trace. With
RunConfig(trace_include_sensitive_data=False) every ResponseSpanData
arrives with response=None and the AttributeError escaped
DeepEvalTracingProcessor.on_span_end, leaving the LlmSpan unexited.

Guard the None response the same way
update_span_properties_from_response_span_data already does.
@vercel

vercel Bot commented Sep 20, 2026

Copy link
Copy Markdown

@BlueX888 is attempting to deploy a commit to the Confident AI Team on Vercel.

A member of the Team first needs to authorize it.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant