Python: Honor a zero handoff autonomous turn limit instead of defaulting to 50 - #8965
Open
Grapette.L (Lesereingrape) wants to merge 1 commit into
Open
Grapette.L (Lesereingrape) wants to merge 1 commit into
Grapette.L (Lesereingrape) wants to merge 1 commit into
Conversation
HandoffAgentExecutor folded autonomous_mode_turn_limit through `or`, so an explicit 0 became the default 50 and the agent kept running on injected prompts instead of returning control to the user.
Grapette.L (Lesereingrape)
requested review from
SergeyMenshykh,
Tao Chen (TaoChenOSU),
Eduard van Valkenburg (eavanvalkenburg),
Giles Odigwe (giles17),
Jose Alvarez (jpalvarezl),
Evan Mattson (moonbox3),
Roger Barreto (rogerbarreto),
sophia-ramsey and
westey (westey-m)
as code owners
October 2, 2026 05:28
Grapette.L (Lesereingrape)
deployed
to
github-app-auth
October 2, 2026 05:28 — with
GitHub Actions
Active
Grapette.L (Lesereingrape)
deployed
to
github-app-auth
October 2, 2026 05:29 — with
GitHub Actions
Active
Member
|
/review |
Contributor
There was a problem hiding this comment.
MAF Automated Review — Iteration 1
Result: No findings
Scope: full PR (1 commit(s)): dcf2f073a31f
Model: gpt-5.6-sol
Overview
The change narrowly distinguishes an explicit zero autonomous-turn limit from the unset None case while preserving the existing default and positive-limit behavior. The builder path preserves zero, handoff and termination checks still take precedence, and the regression test covers the complete public path through the immediate user-input request. No publishable Critical, High, or Medium issue was established.
Reviewed the supplied pull-request change set across correctness, security/reliability, architecture, and failure behavior.
No publishable findings remained after source verification for this scope.
This branch was successfully deployed
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.
Motivation & Context
HandoffAgentExecutor.__init__folded the configured autonomous turn limit through truthiness, so an explicit0became_DEFAULT_AUTONOMOUS_TURN_LIMIT(50). That value reaches the executor unchanged from the public builder path —HandoffBuilder.with_autonomous_mode(turn_limits={agent_id: 0})→self._autonomous_mode_turn_limits.get(id, None)(_handoff.py:1210) — and the consumer compares a counter against it (_handoff.py:480), so a caller who asked an agent never to continue on its own instead got up to 50 injected autonomous prompts and model calls before control returned to the user. The docstrings describe the default as belonging to the unset case, which isNone. Reported and reproducible in #8964.Description & Review Guide
python/packages/orchestrations/agent_framework_orchestrations/_handoff.py:282: theorfallback becomes_DEFAULT_AUTONOMOUS_TURN_LIMIT if autonomous_mode_turn_limit is None else autonomous_mode_turn_limit, plus a docstring line inHandoffAgentExecutor.__init__and inHandoffBuilder.with_autonomous_modestating that0means no autonomous continuation and the default applies only when the limit is left unset. One regression test,test_autonomous_mode_zero_turn_limit_returns_control_immediately, added topython/packages/orchestrations/tests/test_handoff.pynext to the existing turn-limit test.0is now honored: the executor takes therequest_infobranch on the agent's first non-handoff reply instead of running 50 more turns.Nonestill yields 50, and any positive limit behaves exactly as before, so the change is confined to the value that previously read as "unset". Nothing else in the executor changes; the two adjacent autonomous tests (test_autonomous_mode_yields_output_without_user_request,test_autonomous_mode_resumes_user_input_on_turn_limit) still pass untouched.0should be honored as "no autonomous continuation" (this PR) or rejected at build time with aValueError. I chose to honor it because the existing counter comparison already expresses that meaning correctly once0survives, and becausewith_autonomous_modedocuments per-agent limits as caller-chosen. If validation is preferred, the same test can assert the raised error instead.Local run of the package's full gate (
uv run python scripts/workspace_poe_tasks.py check --package orchestrations):fmtandlintpass, all five typing checkers (pyright, mypy, ty, pyrefly, zuban) report 0 errors, and 236 tests pass with 86% coverage on_handoff.py. Before the source change, the new test fails onmain(a91fe668) withassert 51 == 1— 1 required reply plus the 50 autonomous turns the configured0was meant to forbid — and passes after it.Related Issue
Fixes #8964
Contribution Checklist
breaking changelabel needed: only the value that previously fell through to the default changes behavior, andNonekeeps the documented default of 50.Disclosure: this change was produced by an AI coding assistant working from the issue repro, then run through the package's own gate locally as described above. The diff is small and self-contained on purpose so it is quick to audit.