登录
推荐 文章 Go 技术 课程 下载 专题 AI
首页 >  科技周边 >  人工智能

AI 代理执行循环怎样设置工具调用最大轮数

来源:17golang原创

时间:2026-11-14 04:39:35 253浏览 收藏

我在给工具型代理加预算时,最容易混淆的是“调用了几次工具”和“模型循环了几轮”。更稳妥的做法是把 max_turns 当作代理运行的硬上限,再单独记录工具错误率、延迟和成本。OpenAI Agents SDK 的 Runner 会在最终输出、handoff 或工具结果之间继续循环;达到上限时抛出 MaxTurnsExceeded,也可以用错误处理器转成受控结果。

官方地址:https://openai.github.io/openai-agents-python/

如果任务通常 2~3 轮就能完成,可以先设 5 轮作为保护线;不要用“取消上限”解决未收敛问题,而要让上限触发后留下可观测、可解释的退出结果。

先把工具调用循环拆成可计数的回合

一个 turn 是一次模型调用,它可能在同一回合里产生一个或多个函数工具调用。工具执行完成后,结果会回到下一次模型调用;因此工具调用次数不一定等于 turn 数。把这几个量拆开,后面才知道上限到底保护了什么。

Runner、模型回合、函数工具和最终输出的静态关系说明图
图1:代理执行循环的结构说明图,区分模型回合、工具调用和最终输出;这不是运行截图。
from agents import Agent, Runner

agent = Agent(
    name="资料整理员",
    instructions="先调用工具收集资料,再给出简短结论。",
    tools=[search_docs],
)

result = await Runner.run(
    agent,
    "整理这份接口变更的影响范围。",
    max_turns=5,  # 限制模型回合数,不是把工具调用数直接设为 5
)

print(result.final_output)  # 只在代理正常产生最终输出时读取结果

上面的 5 是循环保护线,不是质量分数。一次回合内如果模型并行请求多个工具,工具执行并发还受 max_function_tool_concurrency 等设置影响,这个并发限制与 max_turns 是两件事。

在上限触发时给出受控退出

只设置上限而不处理异常,用户看到的通常是一次失败。生产代码更适合把“没在预算内完成”转成明确状态,让调用方决定是否缩小问题、转人工或异步重试。

from agents import Agent, Runner, RunErrorHandlerInput, RunErrorHandlerResult

def on_max_turns(_data: RunErrorHandlerInput[None]) -> RunErrorHandlerResult:
    # 明确告诉调用方:预算耗尽,不把同一任务偷偷重跑
    return RunErrorHandlerResult(
        final_output="本次任务超过工具调用预算,请缩小范围后再试。",
        include_in_history=False,  # 避免把兜底文案当成正常答案历史
    )

result = await Runner.run(
    agent,
    "检查一组变更记录并归纳风险。",
    max_turns=5,  # 先给一个可观测的硬边界
    error_handlers={"max_turns": on_max_turns},  # 将异常变成受控输出
)

print(result.final_output)  # 调用方可以据此转入人工或缩小任务

这里的退出文案不应伪装成完整答案。它只说明代理没有在预算内完成,调用方还需要保存本次轮数、最后一个工具错误和任务标识。

用指标选择 max_turns,而不是凭感觉

我通常先在固定任务集上观察四个数字:成功任务的平均轮数、P95 轮数、工具错误率和达到上限的比例。若大多数成功样本在 3 轮内结束,直接把上限设成 20 往往只是延迟和成本的隐形放大器;若很多任务在 5 轮时刚好被截断,则应先检查工具返回是否过长、参数是否不完整,而不是盲目把上限加倍。

max_turns、MaxTurnsExceeded 与延迟成本预算的静态关系说明图
图2:轮数上限与指标边界的关系说明图,展示预算和失败退出的对应关系;这不是性能截图。
观察信号更合理的动作
平均轮数低、上限触发少保留小幅余量,例如从 3 调到 5
工具错误率随轮数上升先修工具契约、参数校验和错误提示
上限触发集中在长任务拆分任务或改成异步,不只提高上限
轮数稳定但成本波动大另算输入输出 token、工具延迟和并发,不把 max_turns 当总预算

并发工具和嵌套代理要单独设预算

max_turns 约束的是某次代理运行的模型回合。它不等于单回合可以同时执行多少个本地工具,也不自动替子代理设定同样的上限。父代理调用一个 agent-as-tool 时,应给嵌套运行单独的 max_turns,并在业务层再加总延迟和成本预算。

from agents import Agent, ModelSettings, RunConfig, ToolExecutionConfig

agent = Agent(
    name="资料整理员",
    instructions="只调用必要工具,遇到不完整数据就说明缺口。",
    model_settings=ModelSettings(
        parallel_tool_calls=False,  # 需要严格单工具节奏时关闭模型并行请求
    ),
)

run_config = RunConfig(
    tool_execution=ToolExecutionConfig(
        max_function_tool_concurrency=2,  # 限制本地工具同时执行的数量
    ),
)

result = await Runner.run(
    agent,
    "只整理已提供的资料。",
    max_turns=5,  # 仍然只代表模型回合上限
    run_config=run_config,
)

最后记住三个边界:max_turns 防止循环失控,工具并发限制保护本地执行资源,业务预算则负责限制总延迟和花费。三者分开记录,代理才会既能完成任务,也能在失败时及时停下来。

相关问题

max_turns 设为 None 可以吗?

可以表示不启用 SDK 的轮数上限,但仍建议在业务层保留超时、取消和成本预算。无限轮数不等于代理会自动收敛。

工具调用次数能直接用 max_turns 代替吗?

不能。一次模型回合可能产生多个工具调用,多个回合也可能重复调用同一个工具;需要单独统计工具调用事件。

声明:本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>