1. 先把 DeepResearch 工作流拆开看:Dify 节点编排到底在做什么
Dify 里的 DeepResearch 工作流,本质上是一个“用 LLM 决定搜什么、用搜索工具拿资料、再让 LLM 汇总成报告”的循环结构。它不是什么黑魔法,拆开之后你会发现核心就三件事:控制迭代次数、动态生成搜索主题、把中间结果汇总成最终报告。适合谁?适合想复刻深度研究流程、又不想从零写调度代码的开发者。你只要理解节点之间的数据流,就能自己改出一个更符合业务场景的版本。
我先把工作流从推荐页复制到自己的工作区,然后导出 DSL。DSL 是一个 YAML 文件,里面记录了所有节点、连线、变量和提示词。拿到 DSL 之后,你可以直接读,也可以丢给任意一个支持长文本的模型帮你梳理节点关系。我当时的提示词是:“这是一个 Dify 工作流的配置文件,请先详细描述各个节点,然后描述整个流程,最后用 mermaid 画出流程图。”注意,这里只是让模型帮你理解,不是让模型替你跑工作流。
拆解下来,节点大致分四层。第一层是输入与控制:Start 节点接收用户输入,Code 节点根据 depth 生成一个数组,用来控制迭代次数。第二层是迭代主体:Iteration 节点遍历数组,里面包含 LLM 节点分析当前主题、Tavily Search 节点执行搜索、JSON Parse 节点提取 nextSearchTopic 和 shouldContinue、Assign Variables 节点更新搜索主题列表和控制变量、If-Else 节点判断是否继续。第三层是结果汇总:Template Transform 节点格式化中间搜索结果,Variable Aggregator 节点汇总所有中间结果。第四层是最终输出:Final LLM 节点分析汇总结果生成报告,Answer 节点输出。
这里最关键的是 LLM 节点的提示词设计。system prompt 大意是:你正在调查以下主题,你发现了什么,还有哪些问题未解决,接下来需要调查哪些具体方面;不要输出与已搜索主题完全相同的内容;如果需要进一步搜索,设置 nextSearchTopic;如果信息足够,把 shouldContinue 设为 false;以 JSON 格式输出。user prompt 里注入 Topic、Findings、Searched Topics。这个设计决定了整个工作流是“动态搜索”而不是“固定轮次搜索”。
如果你只是想把工作流跑起来,需要准备两样东西:一个 Tavily 的 key,以及两个 LLM 节点的模型配置。Tavily 每月有免费搜索额度,简单玩一下够用。模型配置这里就是后面要说的重点——两个 LLM 节点如果分别配不同厂商的 key,管理起来很麻烦,用统一 Key 会省事很多。
还有一个容易漏掉的细节:Intermediate Output Format 节点里要加一行检索结果输出,类似{{ index + 1 }}/{{ depth }}th search executed. {{ text }},否则中间结果的可读性会很差。做完这些再发布工作流,预览时只需要填 depth 和研究题目,就能启动 DeepResearch。
实测下来,这个内置工作流跑出来的结果只能算中规中矩。迭代节点可能只迭代 3 次就被 LLM 判停,每次 Tavily 检索 5 篇文章,3 次共 15 篇,而且基本都是英文文章。最终报告的质量,个人感觉并不比一些成熟的对话产品更好。原因也很直接:这个工作流太简单了。LLM 主题分析和终止搜索节点的设置、信源组成、报告生成节点的提示词,都还有大量优化空间。但它最大的价值是帮你揭开了 DeepResearch 的面纱——你可以在它基础上继续改,而不是从零猜。
2. TaoToken 统一 Key 前置:为什么两个 LLM 节点要共用一个入口
Dify 工作流里只要出现多个 LLM 节点,就会遇到一个很现实的问题:每个节点都要选模型供应商、填 API Key、填 Base URL。如果两个节点用不同厂商,你就要维护两套 key;如果同一个厂商但不同模型,切换时又要改配置。更麻烦的是,当你想对比不同模型对 DeepResearch 最终报告质量的影响时,每换一次模型就要重新填一遍 key,工作流日志里还容易看混。
TaoToken 在这里的角色,是提供一个统一的模型调用入口。你可以在 TaoToken 里拿到一个 API Key,然后把 Dify 里所有 LLM 节点的模型供应商都指向同一个 Base URL,用同一个 Key,只改 Model ID 来切换模型。这样做的直接好处是:工作流里两个 LLM 节点可以共用一套凭证,验证多模型切换时只需要改模型名,不用动 Key 和地址。
具体来说,TaoToken 的 API 地址是https://taotoken.net/api,官网是https://taotoken.net/?utm_source=taotoken_aicg_blog_end&utm_medium=csdn&utm_campaign=rewrite&utm_content=。你需要在 TaoToken 的控制台里创建一个 API Key,然后回到 Dify 的模型供应商配置里,选择 OpenAI-API-compatible 这类兼容入口,把 Base URL 填成 TaoToken 的 API 地址,把 Key 填进去,再填你要用的 Model ID。
这里要强调一点:TaoToken 不是让你绕过什么限制,它就是一个正常的模型调用聚合入口,方便你在一个地方管理 Key 和切换模型。你完全可以在 Dify 里直接配各家官方 Key,只是节点多了之后维护成本高。用统一 Key 的核心动机是“少改配置、方便对比”。
如果你还没有 Key,可以先去 TaoToken 控制台创建。创建之后,建议先不要急着填进 Dify,而是用一条 curl 命令验证 Key 是否可用。验证通过再进 Dify 配置,能省掉很多“到底是 Key 错了还是 Dify 配错了”的排查时间。
另外,Dify 里配置模型供应商时,Base URL 的写法要注意:有些版本要求填到/v1,有些版本只填到域名。TaoToken 的 API 地址是https://taotoken.net/api,如果 Dify 提示 404,可以尝试在末尾加上/v1,也就是https://taotoken.net/api/v1。这个细节后面排错部分会再展开。
对于长期做编码或 Agent 类工作流的开发者,如果你不只是想跑 DeepResearch,还想把同一套 Key 用在更多模型调用场景里,可以了解一下 Coding Plan。它适合需要长期、稳定调用模型的场景,入口在 TaoToken 的 coding-plan 页面。但就本篇的 DeepResearch 工作流而言,你只需要一个普通 API Key 就够了。
3. 可复制配置:Dify 模型供应商 + DSL 片段 + 环境变量
这一节给你可以直接复制粘贴的配置。先说你需要在 Dify 里改什么,再说 DSL 里哪些字段要跟着改。
第一步,在 Dify 的“设置 - 模型供应商”里添加一个 OpenAI-API-compatible 供应商。配置项如下:
{ "provider": "openai_api_compatible", "base_url": "https://taotoken.net/api/v1", "api_key": "sk-你的TaoTokenKey", "model_id": "你的模型ID", "model_type": "llm" }注意,Dify 不同版本对 Base URL 的校验不一样。如果保存时提示连接失败,先把https://taotoken.net/api/v1改成https://taotoken.net/api再试。两个都试一遍,哪个能通过就用哪个。Key 填你在 TaoToken 控制台创建的那一串。
第二步,打开 DeepResearch 工作流的 DSL 文件,找到两个 LLM 节点。DSL 里 LLM 节点的模型配置通常长这样:
model: provider: openai_api_compatible name: 你的模型ID mode: chat completion_params: temperature: 0.3你需要把provider改成你刚添加的兼容供应商名称,把name改成你要用的 Model ID。两个 LLM 节点可以填同一个模型,也可以填不同模型——这正是后面做多模型对比的关键。如果你想让“主题分析节点”用推理型模型、“最终报告节点”用长文本型模型,就在这里分别改name。
第三步,如果你是用 Docker 部署 Dify,建议把 Key 放到环境变量里,而不是硬编码在 DSL 中。在docker/.env里加一行:
TAOTOKEN_API_KEY=sk-你的TaoTokenKey然后在docker-compose.yaml里给 api 和 worker 服务加上环境变量引用:
services: api: environment: - TAOTOKEN_API_KEY=${TAOTOKEN_API_KEY} worker: environment: - TAOTOKEN_API_KEY=${TAOTOKEN_API_KEY}改完之后执行:
cd docker docker compose down docker compose up -d这样做的目的是:DSL 可以分享给别人,Key 不会跟着泄露。如果你只是本地测试,直接填在 Dify 界面里也可以,但正式用建议走环境变量。
第四步,检查 Intermediate Output Format 节点。这个节点负责把每次检索结果格式化,方便后面汇总。内容参考:
{{ index + 1 }}/{{ depth }}th search executed. {{ text }}如果你想让报告里保留来源链接,可以改成:
[{{ index + 1 }}] {{ text }}第五步,确认 Iteration 节点的输入数组来自 Code 节点。Code 节点的逻辑是根据 depth 生成一个长度为 depth 的数组。如果你把 depth 设成 5,迭代最多跑 5 次,但 LLM 可能提前把 shouldContinue 设为 false,实际迭代次数会少于 5。这个设计是合理的,避免无意义搜索。
配置完成后,先不要急着发布。点预览,填一个 depth 比如 3,再填一个研究题目,比如“2025 年边缘计算在工业质检中的落地案例”,看工作流能不能跑通。跑通之后再发布到探索页。
4. 验证请求与成功结果:从 curl 到工作流日志
在把 Key 填进 Dify 之前,先用 curl 验证一次,能排除掉大部分低级错误。命令如下:
curl -X POST "https://taotoken.net/api/v1/chat/completions" \ -H "Authorization: Bearer sk-你的TaoTokenKey" \ -H "Content-Type: application/json" \ -d '{ "model": "你的模型ID", "messages": [ {"role": "user", "content": "用一句话说明什么是深度研究工作流"} ], "temperature": 0.3 }'如果返回里能看到choices字段和正常内容,说明 Key、Base URL、Model ID 三者至少是通的。如果返回 401,说明 Key 有问题;如果返回 404,说明 Base URL 路径不对;如果返回 model not found,说明 Model ID 写错了。这三种错误后面排错部分会细说。
curl 通过之后,回到 Dify 工作流预览。填 depth=3,研究题目填一个你熟悉的话题,启动。然后打开工作流日志,逐个节点看执行情况。重点看三个地方:Iteration 节点实际迭代了几次、Tavily Search 每次返回了几篇文章、Final LLM 节点的输入 token 数是多少。
一个正常的成功结果应该长这样:Iteration 节点显示迭代 3 次,每次 Tavily 返回 5 条结果,中间结果被 Template Transform 格式化后进入 Variable Aggregator,Final LLM 拿到汇总后的 findings,输出一份带小标题的报告。报告里应该能看到对多个来源的引用,而不是只有一段泛泛而谈。
如果你在日志里看到 Iteration 只跑了 1 次就停了,不要慌,这通常是 LLM 在第一次迭代后就把 shouldContinue 设成了 false。你可以检查 LLM 节点的提示词,看是不是“信息足够”的判断过于宽松。可以把 system prompt 里的终止条件写得更严格一点,比如要求至少覆盖三个不同子问题才允许停止。
验证多模型切换时,你只需要改 LLM 节点的 Model ID,然后重新跑同一个研究题目。对比两次报告的结构、引用数量和结论深度。这一步用统一 Key 的优势就体现出来了:你不用改 Base URL,也不用换 Key,只改一个模型名,就能在同一工作流里做 A/B 对比。
如果你验证模型时想更直观地对比输出,可以打开 TaoToken 的模型对话页面,把同一段提示词分别发给不同模型,看原始输出差异。模型对话入口在 TaoToken 的模型对话页面。但注意,工作流里的表现和单轮对话不完全一样,最终还是要以工作流日志为准。
5. 本篇常见错排查:401、local proxy failed、reading choices、OAuth
这一节按真实报错来。你在 Dify 里接 TaoToken 统一 Key,最可能遇到下面几类错误。
第一类:401 Unauthorized。报错原文通常是{"error":{"message":"Invalid API key","type":"invalid_request_error"}}。原因一般是 Key 复制时带了空格,或者 Key 已经被删除。解决方法是重新在 TaoToken 控制台创建一个 Key,复制时注意不要带首尾空格。如果你把 Key 放在.env里,检查有没有引号包裹导致 Key 被当成字符串带上了引号。
第二类:local proxy failed。这个报错在 Dify 的模型供应商测试连接时比较常见,原文类似local proxy failed: connection refused。原因通常是 Dify 容器访问不到你填的 Base URL,或者 Base URL 路径写错。先确认https://taotoken.net/api/v1和https://taotoken.net/api哪个能通。如果你是在 Docker 里跑 Dify,还要确认容器有外网访问能力。这个报错和“代理”无关,就是网络连通性和路径问题。
第三类:reading choices 相关报错。原文可能是error reading choices: unexpected end of JSON input或者cannot read property 'choices' of undefined。这通常说明返回体不是标准 OpenAI 格式,或者返回了空内容。先检查 Model ID 是否写对,再检查请求参数里有没有 Dify 自动加上的、TaoToken 不支持的字段。可以先用第 4 节的 curl 命令确认接口本身返回正常,再回 Dify 看请求体差异。
第四类:OAuth 相关报错。如果你在 Dify 里选错了供应商类型,比如选成了需要 OAuth 授权的官方供应商,而不是 OpenAI-API-compatible,就会看到 OAuth 授权失败或回调地址错误的提示。解决方法是删掉错误的供应商配置,重新添加 OpenAI-API-compatible 类型,只填 Base URL、Key、Model ID 三件套。
这里把三件套再强调一次:Base URL 填https://taotoken.net/api/v1(或/api),Key 填 TaoToken 控制台创建的 Key,Model ID 填你要用的模型名。这三个任何一个错,都会导致上面的报错。如果你用的是 CC Switch、Cline MCP 或 Codex 的 auth.json,配置逻辑是一样的:Base URL、Key、Model ID 三件套必须完整且一致。比如 Codex 的auth.json里,base_url和api_key要对应同一个入口,Model ID 单独在配置里指定。
还有一个容易忽略的错:工作流日志里 Final LLM 节点报context length exceeded。这是因为 Variable Aggregator 汇总了太多中间结果,超出了模型上下文。解决办法是减小 depth,或者在 Template Transform 节点里对每条结果做截断,比如只保留前 500 字。
6. 从 Agent 节点到 Manus:Dify 工作流还能怎么升级
Dify 在 v1.0.0 之后新增了 Agent 节点,这个节点的执行流程分三个阶段:初始化、迭代循环、回答。初始化阶段设置参数、工具和上下文;迭代循环阶段准备包含当前上下文的提示,调用 LLM,解析响应决定是调用工具还是得到最终答案,如果需要调用工具就执行工具并用输出更新上下文,循环直到任务完成或达到最大迭代次数;最后返回最终答案。这个流程和 OpenManus 这类多智能体框架的“规划—执行—反馈”结构非常像。
但要说最新版 Dify 能不能直接搭出一个完整的 Manus,我的判断是暂时还不能。缺的不是 Agent 节点,而是记忆模块、browser-use 这类辅助模块,以及更细粒度的任务调度。不过核心的 Agent 节点已经出来了,你完全可以照着 OpenManus 的流程图,用工作流拼出一个简易版:一个 Agent 节点负责理解需求,一个 Agent 节点负责调用搜索工具,一个 Agent 节点负责汇总,中间用 If-Else 和 Variable Aggregator 做反馈控制。
如果你想继续完善内置 DeepResearch 工作流,可以从三个方向入手。第一,扩充信源:把 Tavily 换成或加上 Firecrawl、本地文献库、其他搜索接口,让检索结果更多样。第二,优化提示词:主题分析节点要求 LLM 输出更具体的子问题,终止条件要求覆盖至少 N 个不同角度。第三,报告生成节点单独配一个长文本模型,和主题分析节点用的模型分开,通过 TaoToken 统一 Key 切换 Model ID 即可。
对于想长期做 Agent 类工作流的开发者,统一 Key 的价值会随着节点数量增加而放大。你不需要在每个节点里重复填 Key,只需要在供应商配置里维护一份。如果你后续要接入更多模型调用场景,可以看看 TaoToken 的 Coding Plan,它适合需要长期稳定调用模型的编码和 Agent 场景。而如果你只是想先验证模型输出,模型对话页面更轻量。接入文档在 TaoToken 的 doc 页面,API Key 管理在 console 的 api-keys 页面。
最后给一个实用建议:每次改完 DSL,先导出备份,再发布。Dify 的工作流版本管理不算强,改坏了回滚比较麻烦。你可以用cp命令给 DSL 文件加时间戳备份,和升级 Dify 时备份 docker-compose 是同一个习惯。这样你就能放心大胆地试各种 Agent 化改造,而不怕把能跑的工作流改崩。