Skip to content

fix(anthropic): record stream finish_reasons when content is empty - #4446

Open
BetterAndBetterII wants to merge 1 commit into
traceloop:mainfrom
BetterAndBetterII:fix/anthropic-empty-stream-finish-reasons
Open

fix(anthropic): record stream finish_reasons when content is empty#4446
BetterAndBetterII wants to merge 1 commit into
traceloop:mainfrom
BetterAndBetterII:fix/anthropic-empty-stream-finish-reasons

Conversation

@BetterAndBetterII

@BetterAndBetterII BetterAndBetterII commented Aug 30, 2026

Copy link
Copy Markdown

Empty-content Anthropic streaming turns drop gen_ai.response.finish_reasons and gen_ai.output.messages. message_delta only copied stop_reason onto per-event entries, which is a no-op when events is empty, and set_streaming_response_attributes then returned early.

Store the message-level stop_reason on message_delta and use it as the finish_reasons fallback. When content tracing is enabled, emit an empty assistant gen_ai.output.messages entry so empty-content streams still record the turn.

Fixes #4362

Test plan

  • Synthetic message_delta with stop_reason="end_turn" and no content blocks records gen_ai.response.finish_reasons=["stop"] and an empty assistant gen_ai.output.messages entry
  • Same stream with TRACELOOP_TRACE_CONTENT=false still records finish_reasons and omits output.messages
  • cd packages/opentelemetry-instrumentation-anthropic && uv run pytest tests/test_semconv_span_attrs.py -v

Summary by CodeRabbit

  • Bug Fixes

    • Improved streaming response tracking when responses contain no content blocks.
    • Preserved message-level stop reasons and mapped them to finish reasons.
    • Recorded empty assistant output messages when content tracing is enabled.
    • Ensured finish reasons remain available when content tracing is disabled.
  • Tests

    • Added regression coverage for empty-content streaming responses.

Empty-content streams never populate events, so message_delta stop_reason was discarded and both gen_ai.response.finish_reasons and gen_ai.output.messages were dropped.
@CLAassistant

CLAassistant commented Aug 30, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@coderabbitai

coderabbitai Bot commented Aug 30, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 4e33c55e-1189-45bc-94b9-63d2aa4acd01

📥 Commits

Reviewing files that changed from the base of the PR and between 62e24c2 and 768d2ad.

📒 Files selected for processing (3)
  • packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/span_utils.py
  • packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/streaming.py
  • packages/opentelemetry-instrumentation-anthropic/tests/test_semconv_span_attrs.py

Included review availability: Your plan provides up to 8 included reviews per hour; 7 remain after this review.


📝 Walkthrough

Walkthrough

The Anthropic streaming instrumentation now preserves message-level stop_reason values when responses contain no content blocks. Span attributes record the mapped finish reason and, when enabled, an empty assistant output message.

Changes

Anthropic streaming telemetry

Layer / File(s) Summary
Preserve message-level stop reasons
packages/opentelemetry-instrumentation-anthropic/.../streaming.py, packages/opentelemetry-instrumentation-anthropic/.../span_utils.py
Streaming response processing stores stop_reason on the complete response and passes it to span attribute generation.
Record empty-content span attributes
packages/opentelemetry-instrumentation-anthropic/.../span_utils.py, packages/opentelemetry-instrumentation-anthropic/tests/test_semconv_span_attrs.py
The helper maps message-level stop reasons when event finish reasons are absent. It emits an empty assistant output message when content tracing is enabled. Regression tests cover both tracing configurations.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk: ⚪ Minimal · up to 768d2

This localized change preserves finish reasons for empty-content Anthropic streams and records the empty assistant message when content tracing is enabled; no actionable merge-blocking risk remains beyond normal checks and review.

Sequence Diagram(s)

sequenceDiagram
  participant AnthropicStream
  participant complete_response
  participant SpanUtils
  participant Span
  AnthropicStream->>complete_response: store message-level stop_reason
  complete_response->>SpanUtils: pass events and stop_reason
  SpanUtils->>Span: record finish reason
  SpanUtils->>Span: record empty assistant message when enabled
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 62.50% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 8 functions across 3 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the primary fix: recording streaming finish reasons when Anthropic content is empty.
Linked Issues check ✅ Passed The changes satisfy issue #4362. They preserve the message-level stop reason, record fallback finish reasons for empty-content streams, emit an empty assistant output message when content tracing is e…
Out of Scope Changes check ✅ Passed All code and test changes directly support issue #4362 and the stated streaming response attribute objectives. No unrelated changes are evident.
Full details: Linked Issues check

Explanation

The changes satisfy issue #4362. They preserve the message-level stop reason, record fallback finish reasons for empty-content streams, emit an empty assistant output message when content tracing is enabled, and include regression tests for both tracing configurations.

  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@BetterAndBetterII

Copy link
Copy Markdown
Author

I have read the CLA Document and I hereby sign the CLA

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.

🐛 Bug Report: [anthropic] Streaming spans drop gen_ai.response.finish_reasons and gen_ai.output.messages for turns with empty content

2 participants