代理循环

代理循环将重新调用代理,直到满足完成条件。 使用它进行迭代优化、待办事项完成、等待后台任务,或评估答案是否符合显式条件。

始终为自主循环设定边界。 完成条件可能会失败,模型可能会停止,计算器可以是概率性的。

重要

代理循环是实验性的。

手动设置循环播放

如果您希望在不使用其他 Harness Agent 默认设置的情况下实现循环执行,请使用直接组合 API。

导入循环类型,并用 LoopAgent 包裹任意 AIAgent。 其默认最大值为 10 个代理调用:

using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;

AIAgent baseAgent = chatClient.AsAIAgent();
AIAgent agent = new LoopAgent(
    baseAgent,
    new CompletionMarkerLoopEvaluator("DONE"),
    new LoopAgentOptions { MaxIterations = 5 });

导入 AgentLoopMiddleware 并将其添加到常规 Agent。 默认最大值为 10 个代理运行:

from agent_framework import Agent, AgentLoopMiddleware


def needs_more_work(*, last_result, **kwargs):
    return "DONE" not in last_result.text


agent = Agent(
    client=client,
    middleware=[
        AgentLoopMiddleware(
            needs_more_work,
            max_iterations=5,
        )
    ],
)

谓词可以是同步的,也可以是异步的。 返回 True 继续、 False 停止或 (continue, feedback) 将反馈传递给下一次迭代。

Go 通过 agent/harness/loop 提供受限的重新调用。 在loop.New(loop.Config{...})中注册agent.Config.Middlewares。 中间件运行代理,评估其响应,并选择性地将反馈发送到另一个迭代中。

以下 Foundry 示例使用完成标记。 它需要 FOUNDRY_PROJECT_ENDPOINT、FOUNDRY_MODEL 和 Azure 凭据:

// Copyright (c) Microsoft. All rights reserved.

package main

import (
    "context"

    "github.com/microsoft/agent-framework-go/agent"
    "github.com/microsoft/agent-framework-go/agent/harness/loop"
    "github.com/microsoft/agent-framework-go/examples/internal/demo"
    "github.com/microsoft/agent-framework-go/provider/foundryprovider"
)

var logger = demo.NewLogger(
    "Loop Harness",
    "This sample shows how the loop harness keeps re-invoking an agent until it "+
        "signals completion with a marker, so the agent can work across several turns "+
        "on its own before returning.",
    "Model", demo.FoundryModel,
)

// completionMarker is the token the agent is asked to emit once the task is
// fully done; the loop stops as soon as it appears in a response.
const completionMarker = "TASK COMPLETE"

func main() {
    token := demo.FoundryTokenCredential()

    // Wrap the agent with the loop harness: after each iteration the
    // completion-marker evaluator decides whether to run the agent again.
    a := foundryprovider.NewAgent(
        demo.FoundryProjectEndpoint,
        token,
        foundryprovider.ModelDeployment(demo.FoundryModel),
        foundryprovider.AgentConfig{
            Instructions: "You are a diligent assistant. Work on the request step by step across " +
                "multiple turns. End your final message with the marker '" + completionMarker +
                "' once, and only once, the request is fully complete.",
            Config: agent.Config{
                Name: "Worker",
                Middlewares: []agent.Middleware{
                    // The loop re-invokes the agent (and everything below it,
                    // including the logger) until an evaluator stops the loop.
                    loop.New(loop.Config{
                        Evaluators: []loop.Evaluator{
                            loop.NewCompletionMarkerEvaluator(loop.CompletionMarkerConfig{Marker: completionMarker}),
                        },
                    }),
                    logger, // for logging each agent iteration
                },
            },
        },
    )

    ctx := context.Background()
    resp, err := a.RunText(ctx, "Draft a short checklist for planning a small birthday party, "+
        "then review it once for anything missing, and finish.").Collect()
    demo.Response(resp, err)
}

MaxIterations 是可选的 *int ,默认值为 10。 为任务设定一个明确的界限。 使用多个评估器时,第一个请求另一次迭代的评估器会提供其反馈;仅当所有评估器停止或达到迭代限制时,循环才会停止。

有关无凭据的示例,请参阅 脚本化循环示例。 它演示了标记完成、自定义评估器和迭代安全上限。

选择完成条件

LoopAgent 接受一个求值器或一个有序集合:

评估者 在以下情况下继续
CompletionMarkerLoopEvaluator 最新响应不包含配置的标记。
TodoCompletionLoopEvaluator 已解析的TodoProvider仍包含未完成的项目,并且可以选择仅在指定的代理模式下继续。
BackgroundTaskCompletionLoopEvaluator 已解析的BackgroundAgentsProvider仍包含正在运行的任务。
AIJudgeLoopEvaluator 单独的评判器客户端判定原始请求尚未得到完整回答。
DelegateLoopEvaluator 你的回调函数返回 LoopEvaluation.Continue(...)。

配置了多个评估器时,它们会按顺序运行。 请求另一次迭代的第一个计算器提供其反馈;仅当所有计算器拒绝继续时,循环才会停止。

使用 AI 评估器

法官收到原始请求和最新的代理响应。 如果发现差距,则其分析将成为下一次迭代的反馈:

var evaluator = new AIJudgeLoopEvaluator(
    judgeClient,
    new AIJudgeLoopEvaluatorOptions
    {
        Criteria =
        [
            "Answer every part of the request.",
            "Support conclusions with evidence.",
        ],
    });

AIAgent loopAgent = new LoopAgent(
    agent,
    evaluator,
    new LoopAgentOptions { MaxIterations = 4 });

仅使用你信任其处理原始请求和生成响应的裁判端点。

控制上下文和输出

默认情况下, LoopAgent 重复使用一个会话,并将获胜评估者的最新反馈作为下一个输入发送。 FreshContextPerIteration = true 而是基于原始请求和汇总后的反馈日志重新构建每一轮,并重置或恢复会话。

默认情况下,非流式运行会返回聚合后的转录文本。 设置为 NonStreamingReturnsLastResponseOnly = true 仅返回最终响应。 流式传输始终会发出每次迭代以及任何代表其他对象发送的可见反馈消息。

谓词接收关键字参数,包括 iteration、last_result、messages、original_messages、session、agent、progress 和 feedback。 帮助程序todos_remaining()和background_tasks_running()提供内置的待办事项条件和后台任务条件。 将它们与 todos_remaining_message 或 background_tasks_running_message 搭配,以生成有针对性的下一条输入。

使用 AI 评估器

AgentLoopMiddleware.with_judge 构建了一个由裁判器驱动的循环。 评判循环默认进行五次迭代:

from agent_framework import Agent, AgentLoopMiddleware

loop = AgentLoopMiddleware.with_judge(
    judge_client,
    criteria=[
        "Answer every part of the request.",
        "Support conclusions with evidence.",
    ],
    max_iterations=4,
)

agent = Agent(
    client=client,
    middleware=[loop],
)

当需要更多工作时,法官的推理将反馈给代理。 仅使用你信任其处理原始请求和生成响应的裁判端点。

控制上下文、进度和输出

对于高级循环,请直接构造 AgentLoopMiddleware :

  • record_feedback 在每个工作迭代后创建一个简洁的进度条目。
  • progress向回调公开累积的条目。
  • inject_progress=True 将进度加入到下一轮迭代的输入中。
  • fresh_context=True从原始任务和进度日志重新开始,并将附加的会话恢复到循环前的快照。
  • 对于非流式运行,return_final_only=True 仅返回最后一个响应。

仅当完成谓词保证会终止时,才传递max_iterations=None。

当最新响应中包含已配置的标记时,使用 loop.NewCompletionMarkerEvaluator 停止。 对于应用程序特定的补全,实现loop.Evaluator或使用loop.EvaluatorFunc,返回loop.Stop()、loop.Continue(feedback)或loop.ContinueWithMessages(messages)。

FreshContextPerIteration 基于原始输入和累积的反馈重新开始。 NonStreamingReturnsLastResponseOnly 将非流式处理结果限制为最终迭代。

Go 不包括 C# 示例中所示的内置 AI-judge 评估器。 如果完成需要另一个模型或外部检查,请提供自己的评估器。

在 Harness Agent 中使用循环功能

如果还需要预配置的历史记录、计划、内存、审批和可观测性管道,请使用Harness代理设置。

设置 HarnessAgentOptions.LoopEvaluators。 Harness将LoopAgent应用为最外层的代理修饰器:

using Microsoft.Agents.AI;
using Microsoft.Extensions.AI;

var options = new HarnessAgentOptions
{
    LoopEvaluators =
    [
        new CompletionMarkerLoopEvaluator("DONE"),
    ],
    LoopAgentOptions = new LoopAgentOptions
    {
        MaxIterations = 5,
    },
};

HarnessAgent agent = chatClient.AsHarnessAgent(options);
// Equivalent construction: new HarnessAgent(chatClient, options)
AgentSession session = await agent.CreateSessionAsync();

空集合或nullLoopEvaluators集合会使Harness保持单次运行模式。

审批和会话行为

LoopAgent 在某次迭代返回待处理的工具审批请求时,会在评估其完成条件之前停止。 它向调用方返回请求,而不是将其隐藏在另一个自治迭代后面。 调用方通过正常的 工具审批 流提供审批响应后,代理可以继续。

LoopAgent 本身不添加审批处理功能。 Harness代理在ToolApprovalAgent部应用循环,使待处理的审批请求能够传出循环。

在呼叫之间重复使用相同的 AgentSession 内容以继续对话。 循环迭代默认共享该会话。 FreshContextPerIteration = true 和 LoopAgent 会在受支持的情况下重置或恢复调用方提供的会话状态。 当序列化会话仅包含远程会话标识符时,服务拥有的对话存储可以保留历史记录。

loop_should_continue提供给 create_harness_agent ;loop_max_iterations默认值为 10:

from agent_framework import create_harness_agent


def needs_more_work(*, last_result, **kwargs):
    return "DONE" not in last_result.text


agent = create_harness_agent(
    client=client,
    loop_should_continue=needs_more_work,
    loop_max_iterations=5,
)
session = agent.create_session()

loop_next_message 用于自定义下一次输入。 如果没有 loop_should_continue,工厂就不会添加循环,并且会忽略其他循环参数。

审批和会话行为

如果某次迭代返回待处理的工具审批请求,AgentLoopMiddleware会在评估其继续谓词前停止。 它向调用方返回请求,而不是将其隐藏在另一个自治迭代后面。 调用方通过正常的 工具审批 流提供审批响应后,代理可以继续。

AgentLoopMiddleware 本身不会添加 ToolApprovalMiddleware。 Harness代理将循环置于审批中间件之外,使待处理的审批请求能够传出循环。 启用工具自动审批时,请在每次运行Harness代理时创建并传递一个AgentSession。

在呼叫之间重复使用相同的 AgentSession 内容以继续对话。 循环迭代默认共享该会话。 使用 fresh_context=True 时,该中间件会在每次迭代之间将已附加的会话还原为循环前的快照。 当序列化会话仅包含远程会话标识符时,服务拥有的对话存储可以保留历史记录。

Go harness.AgentConfig 帮助程序默认不会添加循环。 在调用方的 agent.Config.Middlewares 中包含 loop.New(...),以使用有界重新调用来包装已配置的代理。

当迭代生成挂起的工具审批请求时,循环将结束。 它不会自动批准工具。 处理主机中的请求,并在继续之前通过同一会话返回匹配的审批响应。

后续步骤

深入了解