Skip to content

fix(smolagents): suspend stream invocations between reads - #1006

Open
ishan-1010 wants to merge 5 commits into
open-telemetry:mainfrom
ishan-1010:fix-smolagents-stream-invocation-context
Open

ishan-1010 wants to merge 5 commits into
open-telemetry:mainfrom
ishan-1010:fix-smolagents-stream-invocation-context

Conversation

@ishan-1010

Copy link
Copy Markdown

Part of #872 (smolagents).

Both smolagents stream wrappers left their invocation attached after handing the stream back, so whatever the caller did before draining it was parented under the chat or invoke_agent span. The model stream and the agent run stream now suspend the invocation when they are returned, following the OpenAI wrappers. The agent run wrapper does not pass its invocation to the base class, so it overrides _execution_context to reactivate it around each read, which keeps model calls made during the run under the agent span.

Copilot AI balanced review requested due to automatic review settings October 29, 2026 03:27
@ishan-1010
ishan-1010 requested a review from a team as a code owner October 29, 2026 03:27
@linux-foundation-easycla

linux-foundation-easycla Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

CLA Signed
The committers listed above are authorized under a signed CLA.

@opentelemetry-pr-dashboard

opentelemetry-pr-dashboard Bot commented Oct 29, 2026 •

Copy link
Copy Markdown

Pull request dashboard status

Waiting on maintainers · refreshed 2026-11-01 10:17 UTC

Merge when ready.

Status above doesn't look right?
  • Just replied or pushed? Anything around or after the refresh time above may not be picked up yet — give it a few minutes.
  • Anything look wrong? Report it with what you expected; it helps us improve the dashboard.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

The dependency minimum permits util-genai versions lacking required stream-context reactivation, and both stream destructors finalize outside their execution contexts, risking lost context and incorrect span parenting.

2 open issues
What changed in this PR

This PR addresses the smolagents portion of #872 by restoring caller context between stream reads while keeping streamed work under its model or agent span.

Changes:

  • Suspend model and agent invocations before returning streams, with explicit reactivation for agent reads.
  • Add regression tests for caller isolation and nested model-span parenting.
  • Document the context fix in a changelog fragment.
File Description
instrumentation/​opentelemetry-instrumentation-genai-smolagents/​tests/​test_models.py Tests caller context between model-stream reads.
instrumentation/​opentelemetry-instrumentation-genai-smolagents/​tests/​test_agents.py Tests caller isolation and model-work parenting during agent streaming.
instrumentation/​opentelemetry-instrumentation-genai-smolagents/​src/​opentelemetry/​instrumentation/​genai/​smolagents/​patch.py Suspends stream invocations and scopes agent execution context.
instrumentation/​opentelemetry-instrumentation-genai-smolagents/​.changelog/​1006.fixed Records the stream-context correction.

Review effort: Balanced

try:
self._finalize_success()
with self._execution_context():
self._finalize_success()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Could we also close the wrapped stream inside this context? On abandonment, the generator’s finally runs after __del__ returns, so it still executes outside the agent span. The current tests surface this as generator ignored GeneratorExit warnings.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

done in 9512eb2, the GeneratorExit warning is gone as well.
thanks!

for span in span_exporter.get_finished_spans()
if span.name == "caller"
]
assert caller.parent is None

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This covers the caller side, but nothing checks that chat is still current while the model generator runs (the agent test has _SpanningCodeModel for that). Something like this would catch a regression in the per-read activation:

def test_generate_stream_reads_under_the_chat_span(
    instrument_with_content, span_exporter
) -> None:
    model = transformers_model()
    seen = []

    def chunks():
        for text in ["In ", "Paris"]:
            seen.append(get_current_span().get_span_context().span_id)
            yield text

    model.streamer = chunks()
    list(model.generate_stream(messages=MESSAGES))

    (chat,) = spans_by_operation(span_exporter.get_finished_spans(), "chat")
    assert seen == [chat.context.span_id] * 2

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

added it in 2b17c6f, thanks!

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

Development

Successfully merging this pull request may close these issues.

4 participants