Hacktoberfest 2026:维护者为十月标记出来的 issue,仍然开放、适合新手。 浏览 Hacktoberfest issue

Python: [Bug]: A handoff autonomous turn limit of 0 silently becomes the default 50 turns

已关闭
#8,964 1 条评论 0 个 reaction 已指派 1 人 在 GitHub 查看

维护者通常 1 天内回复

@eavanvalkenburg 已经在做这个了。

开始于 2026年10月2日。

  • #8965 来自 @Lesereingrape —— 已合并

评估

这个 Issue 还没有评估数据。

描述

orchestration python reproduced
Description

HandoffAgentExecutor.__init__ folds the configured autonomous turn limit through truthiness (python/packages/orchestrations/agent_framework_orchestrations/_handoff.py:282):

self._autonomous_mode_turn_limit = autonomous_mode_turn_limit or _DEFAULT_AUTONOMOUS_TURN_LIMIT

with _DEFAULT_AUTONOMOUS_TURN_LIMIT = 50 (:229), so an explicitly configured 0 is silently replaced by 50. 0 is the natural way for a caller to say "this agent must not continue on its own", and the public builder path makes it reachable without constructing the executor directly: HandoffBuilder.with_autonomous_mode(turn_limits={agent_id: 0}) stores the mapping and build() hands it to the executor unchanged through self._autonomous_mode_turn_limits.get(id, None) (:1210), where the or above then swallows it.

The consumer treats the value as a plain counter bound (:480):

if self._autonomous_mode and self._autonomous_mode_turns < self._autonomous_mode_turn_limit:

With the intended limit of 0 that branch is never taken, so the executor emits request_info as soon as the agent answers without requesting a handoff. With the swallowed 50, the executor instead injects the autonomous prompt and re-runs the agent up to 50 more times first. The docstring describes the default as belonging to the unset case — "Maximum number of autonomous turns before returning control to the user. If not provided, a default turn limit will be used." (:934) — and "not provided" is None, not 0.

The cost is not cosmetic: a caller who asks one agent to stop autonomously gets up to 50 unwanted model calls and 50 unwanted replies before control returns.

Code Sample

Reproduces with the module's existing mock harness, no API keys needed. Added to python/packages/orchestrations/tests/test_handoff.py, right after test_autonomous_mode_resumes_user_input_on_turn_limit:

async def test_autonomous_mode_zero_turn_limit_returns_control_immediately():
    """A turn limit of 0 means no autonomous continuation, not the default turn limit."""
    triage_client = MockChatClient(name="triage", handoff_to="worker")
    worker_client = MockChatClient(name="worker")
    triage: Agent[Any] = Agent(id="triage", name="triage", client=triage_client,
                               require_per_service_call_history_persistence=True)
    worker: Agent[Any] = Agent(id="worker", name="worker", client=worker_client,
                               require_per_service_call_history_persistence=True)

    workflow = (
        HandoffBuilder(participants=_as_handoff_agents(triage, worker), termination_condition=lambda _: False)
        .with_start_agent(_as_handoff_agent(triage))
        .with_autonomous_mode(agents=[worker], turn_limits={resolve_agent_id(worker): 0})
        .build()
    )

    events = await _drain(workflow.run("Start", stream=True))
    assert len(worker_client.received_messages) == 1, "A zero turn limit must not grant autonomous turns"
Error Messages / Stack Traces

No exception is raised — the agent just keeps going. The assertion above fails on main:

>       assert len(worker_client.received_messages) == 1, "A zero turn limit must not grant autonomous turns"
E       AssertionError: A zero turn limit must not grant autonomous turns
E       assert 51 == 1
packages\orchestrations\tests\test_handoff.py:1358

51 = the one reply the worker owes the handoff plus the 50 autonomous turns the configured 0 was supposed to forbid.

Package Versions

agent-framework-core: 1.19.0, agent-framework-orchestrations: 1.2.0 (source main @ a91fe668)

Additional Context

HandoffAgentExecutor is the only consumer of turn_limits, and the same truthiness pattern is not used for the other autonomous settings (prompts maps to prompts or {}, which is correct for a container), so replacing the or with an is None check is the whole fix.

#6328 lists "Turn limit = 0 (default limit of 50 applied)" as one of its observations while investigating a separate 49-vs-50 boundary question with live models. This issue isolates only the 0-becomes-default part, which is deterministic and unit-testable; the boundary question in #6328 is unaffected by this and stays open.

主要语言
Python
星标
14.2k
派生
2.5k
平均合并
2 天 9 小时
30 天内合并 PR
384

环境准备

在 Codespaces 中打开

在浏览器里用你自己的 GitHub 账号启动这个项目的开发容器。

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

microsoft/agent-framework 的其他 Issue

查看 microsoft/agent-framework 的全部 Issue

相似的 Issue

更多 Python Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。