Description
Resuming a background response with continuation_token and stream=True re-runs the local tools on every tool-loop iteration.
The non-streaming path fixed this in #5462 (#5394): once the background response completes, OpenAIChatClient pops continuation_token from the caller's options, because FunctionInvocationLayer reuses that dict. The streaming resume branch in _inner_get_response doesn't. After the resumed stream completes with a function call, the tool runs, the loop calls the client again with the same options, and the client takes the retrieve branch again instead of creating a response with the tool results. That repeats until max_iterations, and the run ends with "Function invocation limit reached before a final answer could be produced."
Tools with side effects (sending an email, writing a record) run once per iteration.
Code Sample
options = {"continuation_token": {"response_id": "resp_bg"}, "tools": [send_email]}
stream = client.get_response(messages, stream=True, options=options)
async for _ in stream:
pass
final = await stream.get_final_response()
With responses.with_raw_response.retrieve returning a stream that completes with a send_email function call, and create returning a text answer:
stream=False: retrieve calls=1, create calls=1, tool executions=1, final text='Email sent.'
stream=True: retrieve calls=5, create calls=0, tool executions=4, final text='Function invocation limit reached before a final answer could be produced.'
Agent stream resume (default max_iterations): retrieve calls=41, create calls=0, tool executions=40
Error Messages / Stack Traces
None; the run ends on the invocation-limit fallback text.
Package Versions
agent-framework-core 1.18.0, agent-framework-openai 1.14.3 (main at 1cd06c5)
Python Version
3.12
Additional Context
The streaming resume branch is _chat_client.py:726-758; the non-streaming pop is at :827-834. #7538 is a different, service-side problem with background tool loops. I have a fix with a test and will open a PR.
🤖 Generated with Claude Code
Description
Resuming a background response with
continuation_tokenandstream=Truere-runs the local tools on every tool-loop iteration.The non-streaming path fixed this in #5462 (#5394): once the background response completes,
OpenAIChatClientpopscontinuation_tokenfrom the caller's options, becauseFunctionInvocationLayerreuses that dict. The streaming resume branch in_inner_get_responsedoesn't. After the resumed stream completes with a function call, the tool runs, the loop calls the client again with the same options, and the client takes theretrievebranch again instead of creating a response with the tool results. That repeats untilmax_iterations, and the run ends with "Function invocation limit reached before a final answer could be produced."Tools with side effects (sending an email, writing a record) run once per iteration.
Code Sample
With
responses.with_raw_response.retrievereturning a stream that completes with asend_emailfunction call, andcreatereturning a text answer:Error Messages / Stack Traces
None; the run ends on the invocation-limit fallback text.
Package Versions
agent-framework-core 1.18.0, agent-framework-openai 1.14.3 (main at 1cd06c5)
Python Version
3.12
Additional Context
The streaming resume branch is
_chat_client.py:726-758; the non-streaming pop is at:827-834. #7538 is a different, service-side problem with background tool loops. I have a fix with a test and will open a PR.🤖 Generated with Claude Code