Azure / Azure/azure-sdk-for-python

azure-ai-agentserver-core: OpenTelemetry context detach failure during streaming responses

Open
#44,884 3 comments 1 reaction 0 assignees View on GitHub
customer-reported Hosted Agents needs-team-attention question Service Attention
Dominant language
Python
Stars
5.6k
Forks
3.4k
Avg merge
1d 21h
Merged PRs (30d)
193

Description

- **Package Name**: azure-ai-agentserver-core
- **Package Version**: 1.0.0b1 (or check your installed version with `pip show azure-ai-agentserver-core`)
- **Operating System**: macOS (also reproducible on other platforms)
- **Python Version**: 3.13

**Describe the bug**

When using streaming responses with `azure-ai-agentserver-core`, OpenTelemetry raises `ValueError: was created in a different Context` errors during context detach. This is a known issue with OpenTelemetry when async generators aren't properly closed using `contextlib.aclosing()`.

The error occurs in `azure/ai/agentserver/core/server/base.py` in the `gen_async()` function where the streaming response iterates over an async generator without wrapping it with `aclosing()`.

**To Reproduce**

1. Create an agent using `agent_framework` with streaming enabled
```python
import asyncio
from dotenv import load_dotenv

load_dotenv(override=True)

from agent_framework.azure import AzureAIAgentClient
from azure.ai.agentserver.agentframework import from_agent_framework
from azure.identity.aio import DefaultAzureCredential

async def main():
async with (
DefaultAzureCredential() as credential,
AzureAIAgentClient(credential=credential) as client,
):
agent = client.create_agent(
name="SimpleAgent",
instructions="You are a helpful assistant. Just respond briefly to any message.",
)

print("Server running on http://localhost:8088")
server = from_agent_framework(agent, credential)
await server.run_async()

if __name__ == "__main__":
asyncio.run(main())
```
2. Host it using `azure.ai.agentserver.agentframework.from_agent_framework()`
3. Send requests that trigger streaming responses. curl -X POST http://localhost:8088/responses -H "Content-Type: application/json" -d '{"stream": true, "input": "Hello"}'
4. Observe the error in logs:```
ValueError: at 0x...> was created in a different Context
Failed to detach context
```

**Expected behavior**

No OpenTelemetry context detach errors during streaming responses.

**Screenshots**

N/A

**Additional context**

This is a known issue with OpenTelemetry and async generators, fixed in other projects:
- **Root cause**: https://github.com/open-telemetry/opentelemetry-python/issues/2606
- **Fix pattern**: https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3938
- **Documentation**: https://logfire.pydantic.dev/docs/reference/advanced/generators/

**Suggested fix** in `azure/ai/agentserver/core/server/base.py`:

The async generator `resp` should be wrapped with `contextlib.aclosing()`:

```python
from contextlib import aclosing

async def gen_async():
ctx = TraceContextTextMapPropagator().extract(carrier=context_carrier)
token = otel_context.attach(ctx)
error_sent = False
try:
yield _event_to_sse_chunk(first_event)
async with aclosing(resp) as stream: # <-- ADD THIS
async for event in stream:
yield _event_to_sse_chunk(event)
except Exception as e:
# ... error handling
finally:
otel_context.detach(token)
# ...
```

Similarly for the sync generator case using `contextlib.closing()`.

Contributor guide

Open the contributing guide

Research direction

Start in azure/ai/agentserver/core/server/base.py at the gen_async() function and inspect the corresponding sync generator path. Reproduce a streaming response to confirm the context-detach error, then verify both async and sync streaming paths close their generators before detaching context and no longer emit the error.

Written by the indexing model from the issue text.

Assessment

Tech stack
azure, python
Domain
backend-api-design, observability
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.