Skip to content

课 2 · ReAct 循环与多步任务

本课目标

实现 ReAct 模式的 Agent 循环,处理多步任务的拆解与执行。课后你会拿到一个能自主完成多步任务的 Agent。

上一课实现了工具调用。但那些都是"一问一答"——用户问天气,模型调一次 API 就结束了。

真实任务往往需要多步执行:查资料 → 分析 → 调用接口 → 验证结果 → 汇总。Agent 需要一个循环机制来自主推进。

ReAct 模式

ReAct(Reasoning + Acting)是最主流的 Agent 工作模式,循环三步:

  • Thought:模型分析当前情况,决定下一步做什么
  • Action:调用工具执行动作
  • Observation:拿到工具返回的结果

然后模型基于 Observation 再次 Thought,决定是否需要继续执行,还是可以给出最终答案。

具体例子

用户:帮我分析一下知识库里关于 React 性能优化的内容,然后创建一个学习计划

Thought: 用户想了解 React 性能优化并制定学习计划。
         我先搜索知识库找到相关内容。
Action:  searchDocs({ query: "React 性能优化" })
Observation: 找到 3 篇文档:React.memo、useCallback/useMemo、虚拟列表...

Thought: 搜到了性能优化的核心技术点。现在创建学习计划。
Action:  createTodo({ title: "学习 React.memo", priority: "high" })
Observation: 待办已创建

Thought: 继续创建其他学习项。
Action:  createTodo({ title: "学习 useCallback/useMemo", priority: "medium" })
Observation: 待办已创建

Thought: 学习计划创建完成,可以汇总回复用户了。
Final:   "我在知识库中找到了 React 性能优化的内容,核心包括...
          已为你创建了以下学习计划:..."

Vercel AI SDK 中的 ReAct

好消息:Vercel AI SDK 的 generateText 配合 stopWhen: stepCountIs(n) 后,天然支持 ReAct 循环

typescript
const result = await generateText({
  model,
  tools: { /* 工具定义 */ },
  stopWhen: stepCountIs(10),  // 允许最多 10 步循环
  system: `你是一个任务助手。对于复杂任务,请一步步执行:
1. 先分析任务需要哪些步骤
2. 逐步调用工具完成每个步骤
3. 最终汇总结果`,
  prompt: userInput,
})

模型会自动在"思考 → 调用工具 → 拿结果 → 再思考"之间循环,直到它认为任务完成或达到 stepCountIs(...) 设定的上限。

多步任务拆解

一个好的 Agent 能把复杂任务自动拆解成可执行的步骤

关键在 System Prompt 中引导:

typescript
const systemPrompt = `
<role>
你是一个任务执行 Agent,能调用工具完成用户交给你的任务。
</role>

<workflow>
1. 理解用户意图,拆解为具体的执行步骤
2. 按顺序逐步执行,每步调用适当的工具
3. 如果某步失败,分析原因后重试或跳过
4. 所有步骤完成后,用自然语言汇总执行结果
</workflow>

<rules>
- 每次只执行一个步骤,不要跳步
- 执行前简要说明当前步骤的目的
- 遇到错误时最多重试 2 次,仍失败则告知用户
</rules>
`

错误处理

工具执行可能失败——网络超时、参数错误、权限不足。Agent 需要处理这些异常。

在工具内处理错误

typescript
const searchTool = tool({
  description: '搜索知识库',
  inputSchema: z.object({
    query: z.string().describe('搜索关键词'),
  }),
  execute: async ({ query }) => {
    try {
      const results = await search(query)
      return { success: true, results }
    } catch (error) {
      return {
        success: false,
        error: error instanceof Error ? error.message : '搜索失败',
      }
    }
  },
})

返回结构化的错误信息,模型可以据此决定是重试还是换个方式。

onStepFinish 回调

Vercel AI SDK 提供 onStepFinish 回调,可以追踪每一步的执行:

typescript
const result = await generateText({
  model,
  tools: { /* ... */ },
  stopWhen: stepCountIs(10),
  prompt: userInput,
  onStepFinish: ({ text, toolCalls, toolResults, usage }) => {
    console.log(`步骤完成:`)
    if (toolCalls?.length) {
      for (const tc of toolCalls) {
        console.log(`  工具: ${tc.toolName}(${JSON.stringify(tc.args)})`)
      }
    }
    if (text) {
      console.log(`  输出: ${text.slice(0, 100)}`)
    }
    console.log(`  Token: ${usage.totalTokens}`)
  },
})

终止条件

Agent 循环必须有终止条件,否则可能无限执行。

自然终止

模型判断任务完成,不再调用工具,直接返回文本——这是最理想的情况。

步数上限强制终止

typescript
stopWhen: stepCountIs(10)  // 超过 10 步强制停止

自定义终止逻辑

typescript
let stepCount = 0
const MAX_COST = 0.1  // 最多花 $0.1
let totalCost = 0

const result = await generateText({
  model,
  tools: { /* ... */ },
  stopWhen: stepCountIs(20),
  prompt: userInput,
  onStepFinish: ({ usage }) => {
    stepCount++
    // 粗算 Token 成本
    totalCost += (usage.promptTokens * 3 + usage.completionTokens * 15) / 1_000_000
    if (totalCost > MAX_COST) {
      throw new Error('超出成本预算,终止执行')
    }
  },
})

实际场景:研究型 Agent

一个完整的研究型 Agent 示例:

typescript
const researchAgent = async (question: string) => {
  return generateText({
    model,
    system: `你是一个研究助手。用户会给你一个技术问题,你的任务是:
1. 先搜索知识库
2. 分析搜索结果是否充分
3. 如果不够,尝试不同的搜索词再搜一次
4. 整理信息后给出结构化的回答`,
    tools: {
      searchKnowledgeBase: tool({
        description: '在知识库中搜索文档',
        inputSchema: z.object({
          query: z.string(),
        }),
        execute: async ({ query }) => { /* 实际搜索逻辑 */ },
      }),
      saveNote: tool({
        description: '保存研究笔记',
        inputSchema: z.object({
          title: z.string(),
          content: z.string(),
        }),
        execute: async ({ title, content }) => { /* 保存逻辑 */ },
      }),
    },
    stopWhen: stepCountIs(8),
    prompt: question,
  })
}

本课产物

  • ✅ ReAct 循环(Thought → Action → Observation)
  • ✅ 多步任务自动拆解与执行
  • ✅ 工具错误处理与重试机制
  • ✅ 终止条件设计(自然终止、步数上限、成本预算)
  • ✅ 研究型 Agent 的完整实现

完整代码在 basic/examples/05-agent/02-react/index.ts

试试看

bash
cd daqi-ai-agent
pnpm exec tsx basic/examples/05-agent/02-react/index.ts
  1. 给一个需要多步推理的任务(如「先查 A,再根据结果决定是否查 B」),观察 Thought → Action → Observation 的循环次数
  2. 给一个超出 Agent 能力范围的任务,看它在哪一步停下或如何降级
  3. 修改步数上限(stepCountIs(...)),对比 5 步和 20 步对复杂任务完成度的影响

面试追问

Q:ReAct 模式怎么工作?

三步循环:Thought(分析当前情况、决定下一步)→ Action(调用工具执行)→ Observation(获取结果)。模型基于 Observation 再次 Thought,决定继续执行还是返回最终答案。Vercel AI SDK 中可用 stopWhen: stepCountIs(n) 开启多步循环并限制最大步数。

Q:Agent 不稳定的原因是什么?

几个常见原因:模型对工具描述理解不准确导致选错工具、参数格式错误导致工具执行失败、上下文过长导致模型"忘记"任务目标、没有终止条件导致无限循环。缓解方式:完善工具描述、做参数校验、控制 stopWhen: stepCountIs(...)、加 onStepFinish 监控。

Q:工具调用失败怎么处理?

工具内捕获异常返回结构化错误信息,模型可以据此重试或换方案。设置最大重试次数防止无限重试。对于关键操作,可以加 human-in-the-loop——失败后暂停询问用户是否继续。

面向前端工程师和独立开发者的 AI 应用工程课程