Repository navigation
Conversation
0xABCD01
force-pushed
the
fix/527-pause-turn-continuation
branch
from
November 7, 2026 09:39
6d64c61 to
86bbd97
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Fixes #527.
In the
agentsexample,Agent._agent_loop()treated any response without a clienttool_useblock as complete. A server-tool response (web search / code execution) withstop_reason="pause_turn"contains onlyserver_tool_useblocks, sorun()returned the unfinished turn instead of continuing it.The loop now continues a paused turn: the assistant message is already in history, so the next iteration issues the follow-up request. Consecutive continuations are bounded by
MAX_PAUSE_TURN_CONTINUATIONS = 10; past the cap,run()returns the last response. The counter resets whenever a response carries client tool calls.One judgment call to flag: the issue asks for a bound on repeated continuations but does not name a value or an exhaustion behavior. I picked 10 (an order of magnitude above a realistic chained server-tool turn, while capping a pathological always-pause loop at 10 extra API calls) and returning the last response rather than raising, since
run()callers do not handle exceptions from it and the returned response'sstop_reasonshows what happened. Happy to adjust either.Continuing the turn also required a fix in
agents/utils/history_util.py. With prompt caching enabled (the default),MessageHistory.format_for_api()addscache_controlby spreading the last message's content blocks as dicts — but assistant responses are stored as raw SDK block models, and a continuedpause_turnis the first path where an assistant message is the last one at request time, so the continuation raisedTypeError: 'ServerToolUseBlock' object is not a mapping. The caching branch now dumps non-dict blocks to dicts first (model_dump(exclude_unset=True), which matches the SDK's own wire form for the same blocks); dict blocks pass through unchanged, and no other formatting path is touched.Quickstart
(The quickstart checklist predates the
agentsexample and has no entry for it; this change is inagents/, named here and in the description, so N/A is the closest available option.)Type of Change
Testing
Added
agents/test_pause_turn.py(offline; mocked client, real SDKMessageobjects, no API calls):run()returns the second response,messages.createcalled twice. (Prompt caching disabled here to isolate stop-reason handling.)createcalls and no exception; the test also asserts the follow-up request's last message is the paused assistant message, as dict blocks withcache_controlapplied.The tests fail without this change, and the default-configuration test also fails with the
TypeErrorabove when only the loop change is applied without thehistory_utilfix; the issue's repro script flips fromAssertionError: run() returned an unfinished server-tool turnto a continued, completed turn.pytest agents/: 3 passed.pyrightreports 0 errors onagents/agent.pyandagents/utils/history_util.py(same as HEAD);ruff checkon the touched files reports only a pre-existingBLE001inhistory_util.py, unchanged from HEAD.Screenshots
N/A — no UI change.
Additional Notes
Scope is the
agentsexample only. I checked the other examples for the same shape:computer-use-demoandbrowser-use-demoloop the same way but configure client tools only, sopause_turncannot occur there today;computer-use-best-practicesdoes seeserver_tool_useblocks (advisor) and breaks onend_turn/no-tool-use, so it may deserve the same look separately.