Description
ResponseStream accepts an Awaitable[AsyncIterable], and ResponseStream.from_awaitable() accepts an Awaitable[ResponseStream]. Passing an asyncio.Task or asyncio.Future to either entry point currently fails when resolving the stream. Passing the underlying coroutine directly works.
This comes up when stream initialization has already been scheduled with asyncio.create_task(). The task should be awaited before the resulting stream is consumed, just as it is for a coroutine source.
Code Sample
import asyncio
from collections.abc import AsyncIterable
from agent_framework import ChatResponse, ChatResponseUpdate, Content, ResponseStream
async def updates() -> AsyncIterable[ChatResponseUpdate]:
yield ChatResponseUpdate(role="assistant", contents=[Content.from_text("hello")])
async def get_stream() -> ResponseStream[ChatResponseUpdate, ChatResponse]:
return ResponseStream(updates(), finalizer=ChatResponse.from_updates)
async def main() -> None:
source = asyncio.create_task(get_stream())
stream = ResponseStream.from_awaitable(source)
try:
print((await stream.get_final_response()).text)
finally:
await source
asyncio.run(main())
Expected output: hello.
Error Messages / Stack Traces
The example raises RuntimeError: Inner stream not available. Iterating the same wrapper instead raises AttributeError: '_asyncio.Task' object has no attribute '__aiter__'. A Future source fails for the same reason.
Package Versions
agent-framework-core 1.18.0, reproduced from source at 3c670707766a8455da6491a9049cc9d575e019f0.
Python Version
Python 3.12.14 on macOS arm64.
Additional Context
The reproduction runs locally without a model or network request. _get_stream() currently checks asyncio.iscoroutine(), which excludes Tasks and Futures. The module already uses inspect.isawaitable() for other awaitable inputs.
I have a small fix and regression coverage for both entry points, keeping the existing coroutine cases as controls.
Description
ResponseStreamaccepts anAwaitable[AsyncIterable], andResponseStream.from_awaitable()accepts anAwaitable[ResponseStream]. Passing anasyncio.Taskorasyncio.Futureto either entry point currently fails when resolving the stream. Passing the underlying coroutine directly works.This comes up when stream initialization has already been scheduled with
asyncio.create_task(). The task should be awaited before the resulting stream is consumed, just as it is for a coroutine source.Code Sample
Expected output:
hello.Error Messages / Stack Traces
The example raises
RuntimeError: Inner stream not available. Iterating the same wrapper instead raisesAttributeError: '_asyncio.Task' object has no attribute '__aiter__'. A Future source fails for the same reason.Package Versions
agent-framework-core1.18.0, reproduced from source at3c670707766a8455da6491a9049cc9d575e019f0.Python Version
Python 3.12.14 on macOS arm64.
Additional Context
The reproduction runs locally without a model or network request.
_get_stream()currently checksasyncio.iscoroutine(), which excludes Tasks and Futures. The module already usesinspect.isawaitable()for other awaitable inputs.I have a small fix and regression coverage for both entry points, keeping the existing coroutine cases as controls.