首页 / 文章

七种智能体循环模式及其失效场景:ReAct、Maker-Checker及其他模式。

一份关于智能体循环设计的实用指南,涵盖了从计划-执行-验证到人工介入的各种模式,同时提供了关于何时适用、何时避免以及如何选择的指导。

发布者:REACTAPP.TOP阅读约 9 分钟1958 词

来源: Agentic Loops & Design Patterns

不应仅凭智能体的话术来判断其能力。真正重要的是在流量高峰、系统出故障以及审计人员来访时的表现。正是在这些情况下,循环设计模式的优势才会超越任何单一的提示策略。将循环视为架构基础元素时效果最佳:每个循环都针对特定类型的问题,存在已知的权衡因素,应当经过深思熟虑后选用。以下这些模式都配有 Claude 风格的示例,以及应避免使用它们的场景。

1. 规划、执行、验证

这是最基础的模式。智能体先规划一个小步骤,执行相应操作,然后检查该操作是否使其更接近明确设定的目标。它在灵活性与可控性之间取得平衡。

// Pseudo-code: Node/TypeScript orchestrating Claude as an agent

async function planActVerifyLoop(ticket) {
  let iteration = 0;
  const maxIterations = 5;

  while (iteration < maxIterations) {
    iteration++;

    // 1. PLAN: ask Claude for the next step
    const plan = await claude.chat({
      model: "claude-3-opus",
      messages: [
        {
          role: "user",
          content: `You are a coding agent working on ticket ${ticket.id}.
Goal: Make tests pass for this ticket without changing public APIs.

Current context:
${ticket.description}
${ticket.latestFailureLog}

What is the single most useful next action?`
        }
      ]
    });

    // 2. ACT: execute the suggested action if it's in the allowed action space
    const action = parseAction(plan);
    const result = await executeAction(action); // run tests, edit file, etc.

    // 3. VERIFY: use tests as verification
    const verification = await runTests(ticket.testSuite);

    if (verification.allPassing) {
      return { status: "done", iterations: iteration };
    }

    // Attach the failure output back into ticket context
    ticket.latestFailureLog = verification.failureOutput;
  }

  return { status: "budget_exhausted" };
}

在该架构中,Claude负责下一动作的微观规划,而循环机制则负责通过测试进行验证并设定迭代次数上限。这样的分工能够避免系统仅因模型自信就宣布任务成功。

适合该架构的场景包括具有可衡量进展的多步骤工程任务、需要达到经过验证的稳定工作状态的发布脚本与配置更改,以及能够内置测试或模式验证等严格检查机制的内部工具。

不适合该架构的场景则包括营销文案或长篇写作等纯创意工作、依赖主观判断且验证仅能体现个人喜好的情况,以及无法在关键路径上进行多次迭代的实时处理流程。

2. ReAct(先推理,再行动)

ReAct将短暂的思考与单一动作交替进行。它不会事先规划完整的路径,而是先分析当前状态,选择一种工具并使用它,然后再进行思考。正因如此,它非常适合用于探索性或诊断性任务,在这类任务中,每一次新的观察都可能合理地改变计划。

# Pseudo-code: Python coordinator orchestrating Claude tool calls

def react_loop(incident):
    iteration = 0
    max_iterations = 6

    while iteration < max_iterations:
        iteration += 1

        # REASON: Claude decides what to inspect next
        reasoning = claude.chat(
            model="claude-3-opus",
            messages=[
                {
                    "role": "user",
                    "content": f"""
You are an SRE assistant triaging a payment incident.

Incident summary:
{incident.summary}

Recent metrics:
{incident.latest_metrics}

Logs snippet:
{incident.logs_snippet}

Decide one next diagnostic action from:
- CHECK_METRICS
- CHECK_LOGS
- CHECK_DB_HEALTH
- SUMMARIZE_FINDINGS_AND_RECOMMEND_ACTION

Explain your reasoning briefly and output JSON with 'action' and 'target'.
"""
                }
            ]
        )

        action = parse_json(reasoning)
        if action["action"] == "SUMMARIZE_FINDINGS_AND_RECOMMEND_ACTION":
            return claude.chat(... )  # final summary + recommended steps

        # ACT: run the selected diagnostic
        observation = run_diagnostic(action, incident)

        # Update incident state for the next reasoning step
        incident.update_with_observation(observation)

每一个诊断步骤都有明确的目标,Claude在每次操作后都能获取最新的上下文信息。

可将其用于事件诊断与根本原因分析,适用于那些每个答案都会决定下一步检查内容的复杂支持工作流程,以及证据零散且不完整的安全调查场景。

当处理方案已经明确、流程清晰时,比如在ETL风格的文档处理中,或者当处理效率过高导致逐步骤推理成本过高,又或是行动空间过于狭窄以至于额外思考毫无意义时,可跳过此步骤。

3. 反思与修正

这里分为两个阶段:生成与评估,之后再进行修改步骤。对于任何需要在交付给客户、监管机构或生产系统之前经过审核的内容,这一流程都能提供合理的默认处理方式。关键在于分离:评估者可以是另一个提示词、成本更低的模型,甚至是规则引擎。

async function reflectReviseLoop(draftInput: string) {
  // 1. GENERATE
  const draft = await claude.chat({
    model: "claude-3-opus",
    messages: [
      {
        role: "user",
        content: `
Write a customer-facing email explaining a declined payment due to suspected fraud.
Constraints:
- empathetic but clear
- no admission of fault
- no promises about future approvals

Context:
${draftInput}
`
      }
    ]
  });

  // 2. CRITIQUE (using a cheaper model as checker)
  const critique = await claude.chat({
    model: "claude-3-haiku",
    messages: [
      {
        role: "user",
        content: `
You are a compliance checker.

Review the following email for:
- policy violations
- misleading statements
- over-commitments

Output a JSON with:
- issues: list of strings
- safe: boolean

Email:
${draft.content}
`
      }
    ]
  });

  const review = JSON.parse(critique.content);

  if (review.safe) {
    return draft.content;
  }

  // 3. REVISE
  const revised = await claude.chat({
    model: "claude-3-opus",
    messages: [
      {
        role: "user",
        content: `
You wrote this email:
${draft.content}

Compliance issues:
${review.issues.join("\n")}

Rewrite the email to resolve all issues while preserving intent.
`
      }
    ]
  });

  return revised.content;
}

这种模式适用于处理涉及欺诈、拒付或监管变更等敏感主题的客户消息,也适合可能需接受审计的内部复盘,以及那些政策合规性比表达风格更为重要的内容。

它不适用于低风险的内部头脑风暴(因为批评会增加阻力且无法真正保障安全)、那些只需简单回复的极短对话,以及像交易过程中的即时消息这类对延迟要求极高的场景,在这些情况下只需一次性回复即可。

4. 起草、测试、修正

工程团队通常偏爱这种循环流程,因为其结果具有客观性且独立于模型本身:测试套件要么通过,要么失败。在每一轮中,智能体会提出修改建议,运行测试并查看哪些测试失败,随后修复这些问题并重复该流程,直到系统处于已知正常状态或达到迭代上限为止。

async function draftTestFixLoop(issue: Issue) {
  const maxIterations = 4;
  let iteration = 0;

  while (iteration < maxIterations) {
    iteration++;

    // DRAFT: Claude proposes code changes
    const patch = await claude.chat({
      model: "claude-3-opus",
      messages: [
        {
          role: "user",
          content: `
You are an autonomous coding agent.

Ticket:
${issue.title}
${issue.body}

Current failing tests:
${issue.failingTests}

Propose a minimal patch as a diff that makes tests pass
without changing public APIs.`
        }
      ]
    });

    applyPatchToGitRepo(patch.content);

    // TEST: run CI locally or via API
    const testResult = await runCi(issue.branchName);

    if (testResult.success) {
      // FIX_DONE: open a PR with the diff
      await openPullRequest(issue, patch.content);
      return { status: "done" };
    }

    // FEEDBACK: update failingTests for next iteration
    issue.failingTests = testResult.failureSummary;
  }

  return { status: "needs_human_review" };
}

它适用于那些风险较低、范围有限且已被标记为可交由客服处理的工单,也适合在回滚操作十分简单的内部工具中,以及那些能够承受延迟和成本的非关键流程。

对于任何会直接改变核心交易路径的资金流动、模式变更、迁移操作以及跨领域重构,还有那些自动化编辑可能违反监管政策的逻辑部分,都应避免使用此方法。

5. 审核者与执行者

一名客服负责执行操作,另一名则负责检查。在支付系统中,这类似于已用于高风险操作的制作者-审核者控制机制,因此很容易向风险管控与合规团队进行说明。

这种模式适用于任何需要第二双眼睛监督的场景,比如自动化系统涉及配置、路由或通知等接近生产环境的系统,以及领导层会查看的高重要性报告或仪表板。

它不适用于那些额外审核成本高于其带来的收益的简单任务、必须一步完成响应的延迟敏感型流程,或是那些因规则过于宽松而会导致审核者对看似合格的内容直接放行的处理流程。

6. 带记忆的重试

大多数简单的循环只是重复尝试。而带记忆的重试循环则会记录失败状态,并利用这些信息避免再次犯同样的错误。

def retry_with_memory_loop(task, max_attempts=3):
    failures = []

    for attempt in range(1, max_attempts + 1):
        # Ask Claude to consider past failures before deciding the next move
        decision = claude.chat(
            model="claude-3-opus",
            messages=[
                {
                    "role": "user",
                    "content": f"""
You are handling a task with a flaky external API.

Task:
{task.description}

Past failures:
{failures}

Decide whether to:
- RETRY_API
- FALLBACK_TO_CACHE
- ESCALATE_TO_HUMAN

Explain briefly and output JSON: {{ "choice": "...", "reason": "..." }}
"""
                }
            ]
        )

        choice = parse_json(decision)

        if choice["choice"] == "RETRY_API":
            result = call_api(task)
        elif choice["choice"] == "FALLBACK_TO_CACHE":
            result = use_cache(task)
        else:
            return {"status": "escalated", "failures": failures}

        if result.success:
            return {"status": "success", "attempts": attempt}

        failures.append(result.error_summary)

    return {"status": "max_attempts_exhausted", "failures": failures}

适合的应用场景包括结构不稳定的集成、存在速率限制的API以及您无法控制的外部系统、格式不一致的文档解析,还有那些允许重试的非关键工作流。

不适合的应用场景则是核心交易流程(因为重试可能导致相同结果重复出现)、那些不具备幂等性的操作(无法确保重试的安全性),以及要求故障必须立即显现且不能默默进行重试的场景。

7. 人工介入

对于任何涉及真实资金、真实客户或可能面临监管风险的场景,这都是必要的防护机制。该流程会自动运行到一定程度,一旦信心不足或风险上升,就会及时将任务移交给人处理。

async function triageLoop(ticket: Ticket) {
  const autoActions = ["LABEL", "ROUTE_TO_QUEUE", "REQUEST_MORE_INFO"];

  const decision = await claude.chat({
    model: "claude-3-opus",
    messages: [
      {
        role: "user",
        content: `
You are a support triage agent in a payments company.

Ticket:
${ticket.body}

Decide one of:
- LABEL (low risk)
- ROUTE_TO_QUEUE (medium risk)
- ESCALATE_TO_HUMAN (high risk / unclear)

Return JSON with:
- choice
- risk_level
- rationale
`
      }
    ]
  });

  const choice = JSON.parse(decision.content);

  if (choice.choice === "ESCALATE_TO_HUMAN") {
    await createHumanTask(ticket, choice.rationale);
    return { status: "escalated" };
  }

  // LABEL or ROUTE_TO_QUEUE are automated but bounded
  await applyAutomatedTriage(ticket, choice);
  return { status: "auto_treated" };
}

可将其用于任何能够提升客户体验或公平感的自动化场景,适用于部分自动化有帮助但完全自主操作存在风险的流程,以及需要在控制措施放宽前进行学习的早期部署。

不应将其用于完全内部且风险较低的任务(因为人类操作只会增加干扰),也不适用于后台批量处理工作(因为人类的审核能力无法扩展),以及升级处理只会让人员不堪重负而无法改善结果的情境。

实际选择方法

当出现新的智能体应用机会时,“我该如何引导它?”并非正确的第一个问题。四个更好的问题是:

  1. 什么信号可以验证结果:测试、架构、规则、指标还是人类判断?
  2. 该任务实际需要多少步骤才能完成?
  3. 系统出现故障时会发生什么?
  4. 如果出错,谁会受到影响?

这些答案揭示了一种规律:

  • 强二元验证方式表明应采用草拟、测试、修复的流程。
  • 探索性路径则适合使用ReAct方法。
  • 若涉及政策或语气方面的问题,应考虑反思修改,或是采用批评与建设相结合的方式。
  • 在不稳定环境中需要带着记忆重新尝试。
  • 高风险情况意味着从一开始就应设置人工介入机制。

实际上,循环工程与其说关乎巧妙的协调,不如说是对系统进行有条理的思考。