Skip to content

Conversation

@irvingpop
Copy link

@irvingpop irvingpop commented Jan 1, 2026

Summary

PR #3220 fixed AsyncMessages.stream() for the non-beta API by moving it from WRAPPED_AMETHODS to WRAPPED_METHODS. However, the beta API equivalents were not included in that fix.

This PR applies the same fix to:

  • anthropic.resources.beta.messages.messages.AsyncMessages.stream
  • anthropic.lib.bedrock._beta_messages.AsyncMessages.stream

Problem

When using async with client.beta.messages.stream(...), the instrumentation fails with:

RuntimeWarning: coroutine '_awrap' was never awaited
  async with self._client.beta.messages.stream(**stream_kwargs) as stream:
RuntimeWarning: Enable tracemalloc to get the object allocation traceback

Traceback (most recent call last):
  File "app/services/llm.py", line 491, in stream_plan_with_honeycomb_tools
    async with self._client.beta.messages.stream(**stream_kwargs) as stream:
                ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^
TypeError: 'coroutine' object does not support the asynchronous context manager protocol

Reproduction Environment

  • Python: 3.13
  • anthropic: 0.75.0
  • traceloop-sdk: 0.50.1
  • opentelemetry-api: 1.39.1
  • opentelemetry-sdk: 1.39.1

Root Cause

stream() returns an AsyncMessageStreamManager (async context manager), not a coroutine. The async wrapper incorrectly awaits it, breaking the context manager protocol.

Solution

Move the beta AsyncMessages.stream entries from WRAPPED_AMETHODS to WRAPPED_METHODS, matching the pattern established in PR #3220 for the non-beta version.

Testing

  • All existing tests pass
  • Added new tests for beta streaming (sync and async)
  • Added manual verification script

Related

  • I have added tests that cover my changes.
  • If adding a new instrumentation or changing an existing one, I've added screenshots from some observability platform showing the change.
  • PR name follows conventional commits format: feat(instrumentation): ... or fix(instrumentation): ....
  • (If applicable) I have updated the documentation accordingly.

Important

Fixes beta API AsyncMessages.stream by moving it to sync wrapper, ensuring correct context manager usage.

This description was created by Ellipsis for c26aee3. You can customize this summary. It will automatically update as commits are pushed.

Summary by CodeRabbit

  • Bug Fixes

    • Adjusted streaming instrumentation so beta streaming paths are handled consistently with non-beta flows, improving observability for streaming interactions.
  • Tests

    • Added end-to-end tests covering legacy sync and async beta streaming, validating span attributes, token accounting, and logging behavior across configurations.

✏️ Tip: You can customize this high-level summary in your review settings.

The beta streaming API methods (beta.messages.AsyncMessages.stream)
were incorrectly placed in WRAPPED_AMETHODS, causing them to be
wrapped with an async wrapper that awaits the result. However,
stream() returns an async context manager, not a coroutine, so it
should use the sync wrapper like the non-beta version.

This fixes the error:
  RuntimeWarning: coroutine '_awrap' was never awaited
  TypeError: 'coroutine' object does not support the asynchronous
              context manager protocol

Applies the same fix from PR traceloop#3220 to the beta API endpoints that
were missed.

Fixes traceloop#3178

Signed-off-by: Irving Popovetsky <irving@honeycomb.io>
@CLAassistant
Copy link

CLAassistant commented Jan 1, 2026

CLA assistant check
All committers have signed the CLA.

@coderabbitai
Copy link

coderabbitai bot commented Jan 1, 2026

📝 Walkthrough

Walkthrough

Moves streaming handling for AsyncMessages.stream from async wrapping to the synchronous wrapping path for both Anthropic beta and Bedrock beta SDKs; adds tests exercising legacy sync and async streaming, event logging, and span/token attribute assertions.

Changes

Cohort / File(s) Summary
Instrumentation wrapping updates
packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/__init__.py
Added AsyncMessages.stream entries to WRAPPED_METHODS for anthropic.resources.beta.messages.messages.AsyncMessages.stream and anthropic.lib.bedrock._beta_messages.AsyncMessages.stream; removed the same entries from WRAPPED_AMETHODS, shifting stream handling to the synchronous wrapping path.
Beta streaming tests
packages/opentelemetry-instrumentation-anthropic/tests/test_beta_streaming.py
New test module with four tests validating legacy sync streaming and various async streaming scenarios (with/without event content logging), asserting spans, GenAI/span attributes, token accounting, and log emission.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I hopped through streams both async and neat,
Wrapped them where sync and context managers meet.
No more unawaited coroutines to fear,
Tests hum like carrots—everything clear! 🥕

Pre-merge checks and finishing touches

✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed Title accurately describes the main change: moving beta AsyncMessages.stream from async to sync wrapper, directly addressing the bug fix.
Linked Issues check ✅ Passed Changes directly resolve issue #3178 by moving AsyncMessages.stream to sync wrapper path, preventing incorrect await of async context manager and fixing RuntimeWarning/TypeError.
Out of Scope Changes check ✅ Passed All changes are scoped to addressing the beta streaming bug: updates to WRAPPED_METHODS/WRAPPED_AMETHODS and new tests validating sync/async beta streaming paths.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings

📜 Recent review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between c26aee3 and d95bb46.

📒 Files selected for processing (1)
  • packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/__init__.py
🧰 Additional context used
📓 Path-based instructions (1)
**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.py: Store API keys only in environment variables/secure vaults; never hardcode secrets in code
Use Flake8 for code linting and adhere to its rules

Files:

  • packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/__init__.py
🔇 Additional comments (4)
packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/__init__.py (4)

88-89: Excellent documentation of the async context manager pattern.

This comment clearly explains why AsyncMessages.stream belongs in WRAPPED_METHODS despite being on an async class. The clarification that it returns an async context manager (not a coroutine) helps prevent future mistakes.


102-107: Correct fix for beta AsyncMessages.stream.

Moving this entry from WRAPPED_AMETHODS to WRAPPED_METHODS correctly fixes the bug. The _wrap function (line 551) doesn't await the result, allowing it to properly handle the AsyncMessageStreamManager returned by stream(). This matches the established pattern for the non-beta AsyncMessages.stream entry above.


109-110: Clear documentation for Bedrock beta variant.

The comment repeats the same explanation as lines 88-89, which aids clarity when reviewing the Bedrock entries independently. While slightly redundant, this improves maintainability for a complex wrapping configuration.


123-128: Comprehensive fix includes Bedrock beta variant.

This entry correctly applies the same fix to the Bedrock SDK's beta streaming API, ensuring consistent behavior across both the regular Anthropic SDK and Bedrock SDK variants. The change completes the fix for issue #3178.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

Copy link
Contributor

@ellipsis-dev ellipsis-dev bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Important

Looks good to me! 👍

Reviewed everything up to c26aee3 in 36 seconds. Click for details.
  • Reviewed 270 lines of code in 2 files
  • Skipped 0 files when reviewing.
  • Skipped posting 4 draft comments. View those below.
  • Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/__init__.py:97
  • Draft comment:
    Good: The beta AsyncMessages.stream entry has been added to WRAPPED_METHODS. This change ensures that the method is wrapped using the sync wrapper, which is the correct behavior for an async context manager. This aligns with the non-beta API fix and resolves #3178.
  • Reason this comment was not posted:
    Comment did not seem useful. Confidence is useful = 0% <= threshold 50% This comment is purely informative, explaining what the change does and why it was made. It doesn't ask for any specific action or suggest any improvements. According to the rules, purely informative comments should be removed.
2. packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/__init__.py:110
  • Draft comment:
    Nice: The beta AsyncMessages.stream entry for the Bedrock SDK ('anthropic.lib.bedrock._beta_messages') has been added to WRAPPED_METHODS. This consistently applies the fix for both beta APIs.
  • Reason this comment was not posted:
    Comment was not on a location in the diff, so it can't be submitted as a review comment.
3. packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/__init__.py:132
  • Draft comment:
    Removal: Taking the beta AsyncMessages.stream entries out of WRAPPED_AMETHODS avoids the erroneous async wrapping (which would await a context manager). This change prevents the TypeError and RuntimeWarning observed earlier.
  • Reason this comment was not posted:
    Comment was not on a location in the diff, so it can't be submitted as a review comment.
4. packages/opentelemetry-instrumentation-anthropic/tests/test_beta_streaming.py:22
  • Draft comment:
    The new tests for the beta streaming API are comprehensive. They cover both sync and async usage, verify span attributes and log outputs for legacy and event-enabled scenarios, which is excellent for guarding against regressions.
  • Reason this comment was not posted:
    Comment did not seem useful. Confidence is useful = 0% <= threshold 50% This comment is purely informative, praising the comprehensiveness of the tests without suggesting any changes or improvements. It doesn't align with the rules as it doesn't provide actionable feedback or suggestions.

Workflow ID: wflow_ft1EVXQYqGof3BHM

You can customize Ellipsis by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/__init__.py (1)

87-99: Consider adding an explanatory comment for the beta methods.

Similar to the comment on lines 78-80 that explains why non-beta AsyncMessages.stream uses the sync wrapper, consider adding a comment before the beta method entries (lines 100-105 and 119-124) to clarify that these async resources also return async context managers and therefore use the sync wrapper.

🔎 Proposed addition
     },
+    # Beta API methods use the same pattern: AsyncMessages.stream returns
+    # an async context manager, so we use the sync wrapper (not async wrapper)
     {
         "package": "anthropic.resources.beta.messages.messages",
         "object": "AsyncMessages",
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between a6d3fa9 and c26aee3.

📒 Files selected for processing (2)
  • packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/__init__.py
  • packages/opentelemetry-instrumentation-anthropic/tests/test_beta_streaming.py
🧰 Additional context used
📓 Path-based instructions (1)
**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.py: Store API keys only in environment variables/secure vaults; never hardcode secrets in code
Use Flake8 for code linting and adhere to its rules

Files:

  • packages/opentelemetry-instrumentation-anthropic/tests/test_beta_streaming.py
  • packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/__init__.py
🧬 Code graph analysis (1)
packages/opentelemetry-instrumentation-anthropic/tests/test_beta_streaming.py (1)
packages/opentelemetry-semantic-conventions-ai/opentelemetry/semconv_ai/__init__.py (1)
  • SpanAttributes (64-245)
🪛 Ruff (0.14.10)
packages/opentelemetry-instrumentation-anthropic/tests/test_beta_streaming.py

24-24: Unused function argument: instrument_legacy

(ARG001)


24-24: Unused function argument: reader

(ARG001)


76-76: Unused function argument: instrument_legacy

(ARG001)


76-76: Unused function argument: reader

(ARG001)


136-136: Unused function argument: instrument_with_content

(ARG001)


136-136: Unused function argument: reader

(ARG001)


173-173: Unused function argument: instrument_with_no_content

(ARG001)


177-177: Unused function argument: reader

(ARG001)

🔇 Additional comments (6)
packages/opentelemetry-instrumentation-anthropic/opentelemetry/instrumentation/anthropic/__init__.py (2)

100-105: LGTM! Beta AsyncMessages.stream correctly uses sync wrapper.

This change correctly moves the beta AsyncMessages.stream method to WRAPPED_METHODS, matching the pattern established for the non-beta version (lines 81-86). Since stream() returns an async context manager rather than a coroutine, it must not be awaited by the async wrapper.


119-124: LGTM! Bedrock beta AsyncMessages.stream correctly uses sync wrapper.

This change correctly applies the same fix to the Bedrock beta variant, ensuring consistency across all beta streaming APIs.

packages/opentelemetry-instrumentation-anthropic/tests/test_beta_streaming.py (4)

22-71: LGTM! Comprehensive test for sync beta streaming.

The test correctly validates sync beta streaming behavior with legacy attributes, including prompt/completion content, token usage, and log emission. The test structure and assertions are appropriate.

Note: The Ruff warnings about unused instrument_legacy and reader arguments are false positives—these are pytest fixtures used for their side effects (instrumentation setup and metrics collection).


73-131: LGTM! Critical test case validates the fix.

This is the main test that validates the fix for issue #3178. Before the fix, this would fail with "TypeError: 'coroutine' object does not support the asynchronous context manager protocol." The test now passes because AsyncMessages.stream uses the sync wrapper instead of the async wrapper.

The docstring clearly explains the problem and solution, making this an excellent regression test.

Note: The Ruff warnings about unused arguments are false positives for pytest fixtures.


133-168: LGTM! Test validates event-based logging with content.

The test correctly validates beta streaming with events and content logging enabled, verifying that 2 logs are emitted and token usage is tracked properly. The focus on token usage rather than span attributes is appropriate for event-based instrumentation.

Note: The Ruff warnings about unused arguments are false positives for pytest fixtures.


170-208: LGTM! Test validates event-based logging without content.

The test correctly validates that beta streaming with events still emits logs (for structure) even when content logging is disabled. This complements the previous test by covering a different instrumentation configuration.

Note: The Ruff warnings about unused arguments are false positives for pytest fixtures.

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 stream() fails with a TypeError when instrumented

2 participants