
1. ReWOO 三段式推理到底解决什么问题ReWOO 是一种把 Agent 推理链路拆成 Planner、Worker、Solver 三个独立阶段的模式。它要解决的核心痛点很具体ReAct 那种“边想边调工具边等结果”的循环每一步都要把历史上下文重新塞回模型步骤一多 token 消耗就成倍上涨。ReWOO 的做法是先把完整计划一次性生成出来再批量执行工具调用最后统一整合证据出答案。适合谁适合任务逻辑相对清晰、工具集合稳定的场景比如多步问答、固定流程的数据分析、需要控制成本的 Agent 推理链路验证。如果你正在用统一 Key/API 通道跑 Agent想快速验证 Planner→Worker→Solver 是否跑通这篇可以直接跟着操作。我先把三段式的职责用一句话说清楚Planner 负责“要做什么”输出带#E1、#E2占位符的计划Worker 负责“找证据”按计划逐个调用工具并把结果填回占位符Solver 负责“出答案”拿着计划加证据直接生成最终结果不再调工具。三者串起来就是先规划、再干活、最后整合。和 ReAct 对比ReWOO 省 token 的关键在于把推理过程和外部观察分离。ReAct 每轮都要重放历史ReWOO 只在 Planner 阶段做一次完整推理Worker 阶段是纯执行Solver 阶段只读一次证据。步骤越多这个差距越明显。但要注意ReWOO 并不是不需要 Observation它只是把 Observation 集中到 Worker 阶段批量获取Planner 阶段完全不依赖工具反馈。下面这张表可以帮你快速判断该用哪种模式维度ReActReWOO推理与执行交替进行先规划后执行token 消耗随步骤线性增长集中在 Planner 一次动态调整强可随时改策略弱计划固定适合场景环境未知、工具多变逻辑清晰、工具稳定典型失败循环过多、成本高规划偏差、连锁失效理解了这张表你就知道为什么 Kiro 的 Planner 模式、Cursor 的 TODO LIST 都能看到 ReWOO 的影子——它们本质上都是“先出计划再逐项执行”。但实际用下来任务逻辑越清晰这种模式越顺手任务越动态越容易卡在初始规划上。2. 用 TaoToken 统一通道接入 ReWOO要让 Planner、Worker、Solver 三段都跑起来你需要一个能同时承载多次模型调用的通道。TaoToken 在这里的角色是提供统一的 API 入口你不需要为 Planner 和 Solver 分别配置不同的 Key一个 Key 就能覆盖整条链路。官网地址是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 基址是 https://taotoken.net/api 。接入前先确认两件事第一你已经在控制台创建了 API Key第二你清楚 ReWOO 链路里至少会有两次模型调用Planner 一次、Solver 一次Worker 阶段如果用到 LLM 工具还会再多一次。所以 Key 的额度要留够别跑到一半断掉。关于 Key 的获取和模型选择可以直接走这两个入口获取 API Keyhttps://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 接入文档https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite如果你只是想先验证模型能不能正常对话可以用模型对话页面快速试一次https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite 。但 ReWOO 的验证重点不在单轮对话而在于三段式链路是否按预期流转所以下面我会直接给可复制的配置骨架。有一点要提前说清楚TaoToken 是 API 通道不是编辑器替代品。你的 Planner 提示词、Worker 工具函数、Solver 整合逻辑仍然要写在你自己的项目里。TaoToken 负责的是让这些调用走同一条稳定通道。3. 可复制的 config.toml 与 settings.json 配置先给config.toml骨架。这个文件负责定义 ReWOO 三段各自的模型参数和工具注册。注意base_url统一指向 TaoToken 的 API 地址api_key从环境变量读取不要硬编码。# config.toml - ReWOO 三段式推理配置骨架 [llm] base_url https://taotoken.net/api api_key ${TAOTOKEN_API_KEY} timeout 60 max_retries 2 [planner] model claude-3-5-sonnet temperature 0.2 max_tokens 1024 system_prompt 针对以下任务请制定可逐步解决问题的计划。 每个计划需要指明将使用的外部工具以及对应的输入。 你可以将证据存储在变量 #E 中供后续工具调用。 格式Plan, #E1, Plan, #E2, Plan, ... 每个 Plan 后只能跟一个 #E。 [worker] model claude-3-5-sonnet temperature 0.0 max_tokens 512 tools [google_search, llm_query, calculator] [solver] model claude-3-5-sonnet temperature 0.0 max_tokens 1024 system_prompt 请解决以下任务。我们已经制定了逐步的 Plan并为每个 Plan 检索了对应的证据。 使用这些证据时请谨慎较长的证据可能包含无关信息。 回答时只输出最终结果不要添加额外文字。 [tools.google_search] type http endpoint https://taotoken.net/api/v1/search top_k 5 [tools.llm_query] type llm model claude-3-5-sonnet [tools.calculator] type local module math再给settings.json片段。这个文件负责运行时行为比如是否打印中间计划、是否缓存 Worker 结果、Solver 是否强制只输出答案。{ rewoo: { enable_planner: true, enable_worker: true, enable_solver: true, print_plan: true, print_evidence: true, cache_worker_results: false, solver_output_only: true, max_plan_steps: 5, evidence_truncate_length: 2000 }, logging: { level: INFO, log_planner_output: true, log_worker_calls: true, log_solver_input: false } }两个文件的分工要记清楚config.toml管“用什么模型、调什么工具”settings.json管“跑的时候打不打印、缓不缓存、截不截断”。max_plan_steps建议先设 5ReWOO 的规划偏差在步骤过多时会被放大限制步数能帮你更快定位问题。evidence_truncate_length设 2000 是为了防止 Worker 返回的超长网页内容把 Solver 的上下文撑爆。注意api_key用${TAOTOKEN_API_KEY}这种环境变量占位不要直接写明文。如果你在本地调试可以先export TAOTOKEN_API_KEY你的Key再运行。4. 跑通一次 Planner→Worker→Solver 调用配置就绪后用一段 Python 脚本把三段串起来。下面这个例子用“2024 中国首富的家乡是哪里”作为任务你可以直接替换成自己的问题。import os import re import json import requests BASE_URL https://taotoken.net/api API_KEY os.environ[TAOTOKEN_API_KEY] HEADERS { Authorization: fBearer {API_KEY}, Content-Type: application/json } def call_llm(system_prompt, user_content, temperature0.0): payload { model: claude-3-5-sonnet, temperature: temperature, messages: [ {role: system, content: system_prompt}, {role: user, content: user_content} ] } resp requests.post( f{BASE_URL}/v1/chat/completions, headersHEADERS, jsonpayload, timeout60 ) resp.raise_for_status() return resp.json()[choices][0][message][content] # ---------- Planner ---------- planner_system open(config.toml).read() # 实际项目里从配置加载 task 2024中国首富的家乡是哪里 plan_text call_llm(planner_system, fTask: {task}, temperature0.2) print( Planner 输出 ) print(plan_text) # ---------- Worker ---------- def parse_plan(plan_text): steps [] for line in plan_text.splitlines(): match re.search(r#E(\d)\s*\s*(\w)\[(.?)\], line) if match: steps.append({ id: f#E{match.group(1)}, tool: match.group(2), input: match.group(3) }) return steps def run_tool(tool_name, tool_input): if tool_name Google: resp requests.post( f{BASE_URL}/v1/search, headersHEADERS, json{query: tool_input, top_k: 5}, timeout30 ) return resp.json().get(results, []) if tool_name LLM: return call_llm(你是一个知识助手。, tool_input) return f未注册工具: {tool_name} steps parse_plan(plan_text) evidence {} for step in steps: result run_tool(step[tool], step[input]) evidence[step[id]] result print(f Worker {step[id]} ({step[tool]}) ) print(json.dumps(result, ensure_asciiFalse)[:300]) # ---------- Solver ---------- solver_input fPlan:\n{plan_text}\n\nEvidence:\n{json.dumps(evidence, ensure_asciiFalse)}\n\nTask: {task} solver_system 请根据上述证据回答问题只输出最终结果。 final_answer call_llm(solver_system, solver_input, temperature0.0) print( Solver 最终答案 ) print(final_answer)跑完之后你会看到三段输出。Planner 阶段应该给出类似这样的计划Plan: 使用 Google 搜索 2024 年中国首富的姓名。#E1 Google[2024 中国首富] Plan: 根据 #E1 的结果搜索首富的家乡信息。#E2 Google[张一鸣 家乡] Plan: 若 #E2 不够明确用 LLM 辅助推断。#E3 LLM[张一鸣的家乡是哪里]Worker 阶段会依次打印#E1、#E2、#E3的工具返回。Solver 阶段则输出最终答案比如“根据 2024 年胡润百富榜首富张一鸣的家乡是福建省龙岩市。”验证链路是否跑通看三个信号第一Planner 输出里每个 Plan 后面都跟了且只跟了一个#E第二Worker 阶段每个#E都有对应的工具返回没有出现“未注册工具”第三Solver 输出是干净的结果没有把证据原文大段复述出来。三个都满足说明 Planner→Worker→Solver 链路正常。5. 本篇常见错排查5.1 Planner 输出格式不合法导致 Worker 解析为空最常见的报错是steps列表为空Worker 一个工具都没调。原因通常是 Planner 没有严格按#E1 Tool[input]的格式输出比如写成了#E1: Google[...]或者把两个#E写在同一行。排查方法是先把print_plan打开肉眼确认 Planner 原始输出。修复手段是在 Planner 的 system prompt 里加一句“每个 Plan 后只能跟一个 #E格式必须是 #E数字 工具名[输入]”并把temperature压到 0.2 以下。5.2 Worker 阶段工具名大小写不匹配run_tool里判断的是Google、LLM但 Planner 可能输出google、llm。这种大小写不一致会让工具调用直接落到“未注册工具”分支。修复很简单在run_tool入口统一做tool_name.lower()或者把工具注册表改成大小写不敏感。我试过在解析阶段就把工具名标准化比在调用阶段补救更省事。5.3 Solver 把证据原文当答案输出如果 Solver 返回的是大段网页内容而不是一句话结论说明solver_output_only没生效或者 system prompt 不够强硬。把 Solver 的 system prompt 改成“回答时只输出最终结果不要添加额外文字不要引用证据原文”同时把temperature设为 0.0。另外检查evidence_truncate_length如果证据太长Solver 容易被无关信息带偏。5.4 请求超时或 401超时通常是timeout设太短Worker 阶段搜索工具返回慢。把config.toml里的timeout调到 60 秒max_retries设 2。401 则是 Key 没读到检查环境变量TAOTOKEN_API_KEY是否真的 export 成功可以用echo $TAOTOKEN_API_KEY确认。如果 Key 没问题还是 401去控制台确认这个 Key 是否被禁用或额度耗尽。5.5 规划偏差导致连锁失效这是 ReWOO 的固有局限不是配置错误。表现是 Planner 第一步就查错了方向后面 Worker 拿到的证据全是偏的Solver 自然给不出正确答案。缓解办法有两个一是限制max_plan_steps步数越少偏差影响越小二是对任务逻辑清晰度做预判如果任务本身需要动态调整策略ReWOO 就不是最优选择这时候应该考虑 ReAct 或混合模式。排障时优先看 Planner 原始输出80% 的问题出在计划格式或计划内容上而不是 Worker 或 Solver。6. 继续验证与长期编码的入口链路跑通之后下一步通常是把它接到真实项目里。如果你要长期跑编码类 Agent建议用 Coding Plan 来管理调用配额和模型切换https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite 。如果你更习惯在 Claude Code 这类工具里验证 ReWOO 的 Planner 行为可以看 ClaudeCodeAnthropic 的接入方式https://taotoken.net/claude-code-anthropic?utm_sourcetaotoken_aicg_blog_endutm_contentclaude_codeutm_campaignrewrite 。回到 ReWOO 本身它的三段式结构在任务逻辑清晰时确实省 token但 Planner 的静态规划能力是天花板。我的经验是先把max_plan_steps控制在 3 到 5 步把 Planner 的 temperature 压到 0.2把 Solver 的 temperature 压到 0.0这三个参数调好链路稳定性会明显提升。至于 Planner 提示词里的工具描述写得越具体规划偏差越小——别只写“搜索工具”要写清楚“输入是搜索查询返回标题、URL 和摘要”。