1. 为什么我要拆 Deep Research Agent 的双系统骨架Deep Research Agent 是谷歌开源的一套研究型智能体参考实现它最值得关注的点不是“能搜网页”而是把 System 1 快思考与 System 2 慢推理做成了可配置、可切换的两条执行路径。System 1 负责意图识别、查询改写、工具选择这类毫秒级决策System 2 负责多步规划、交叉验证、长链综合这类需要几十秒甚至几分钟的慢推理。适合谁适合已经写过基础 ReAct Agent、想进一步复现“快慢双系统”调度逻辑的开发者也适合想把现有单模型 Agent 改造成分层架构的工程同学。我试过用单模型硬扛研究类任务结果就是要么快但浅要么深但贵中间没有过渡带。Deep Research Agent 的架构性突破在于它不要求一个模型同时具备两种能力而是用配置把两条路径解耦。你可以只开 System 1 做轻量问答也可以让 System 1 判断“这题需要慢推理”后再升级到 System 2。下面我会给出可复制的config.toml骨架、TaoToken 统一 Key/API 通道的接入配置以及逐步验证快慢切换是否生效的动作。整套流程不需要你改模型权重只改配置和调用链。2. TaoToken 前置统一 Key 与 API 通道准备在写配置之前先把调用通道固定下来。Deep Research Agent 的双系统会频繁切换模型和工具如果每个子系统各自维护一套 Key排障时会非常痛苦。我的做法是用 TaoToken 作为统一入口官网地址是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 基址用 https://taotoken.net/api 不加 UTM。这样 System 1 和 System 2 共用同一个 Key只是模型名和参数不同。你需要先拿到 API Key入口在 https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite 。拿到后不要硬编码进代码用环境变量注入。我习惯这样写export TAOTOKEN_API_KEYsk-你的key export TAOTOKEN_BASE_URLhttps://taotoken.net/api注意System 1 和 System 2 建议用同一个 Key 但不同模型。System 1 用轻量快速模型System 2 用推理能力更强的模型。TaoToken 的通道对两者都兼容切换时只改model字段即可。如果你还没决定 System 2 用哪个模型可以先去模型对话页面手动试一轮确认慢推理模型在你的任务上表现符合预期入口是 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite 。确认后再写进配置避免配置写完才发现模型选错。3. 可复制的 config.toml 骨架下面这份config.toml是我实测能跑通双系统切换的最小骨架。核心思路是[system1]和[system2]各自独立配置模型、温度、最大步数[router]决定什么时候从快切到慢。# config.toml - Deep Research Agent 双系统骨架 [api] base_url https://taotoken.net/api api_key_env TAOTOKEN_API_KEY timeout_seconds 120 [system1] # 快思考意图识别、查询改写、工具选择 model gemini-2.0-flash temperature 0.2 max_tokens 1024 max_steps 3 tools [web_search, url_fetch] [system2] # 慢推理多步规划、交叉验证、长链综合 model gemini-3-pro-preview temperature 0.4 max_tokens 8192 max_steps 12 tools [web_search, url_fetch, code_exec, note_take] enable_self_check true [router] # 快慢切换策略 mode adaptive # adaptive | always_fast | always_slow complexity_threshold 0.65 max_fast_retries 2 escalate_on [low_confidence, multi_hop, conflict_detected] [memory] # 双系统共享的中间状态 store sqlite path ./agent_state.db reasoning_window 3 # System 2 只看最近3步推理 tool_summary true # 工具状态压缩成摘要再传入几个关键参数解释。router.mode设成adaptive时System 1 先跑跑完输出一个置信度低于complexity_threshold就升级到 System 2。escalate_on是升级触发条件列表multi_hop表示问题需要多跳检索conflict_detected表示检索结果互相矛盾。memory.reasoning_window控制 System 2 每次推理只看最近几步避免上下文无限膨胀这也是成本能压下来的原因之一。如果你要做长期编码类 Agent建议把 System 2 的max_steps调大并考虑用 Coding Plan 通道入口是 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite 。研究型任务和编码型任务对慢推理的步数需求差别很大不要共用一套参数。4. 逐步验证确认快慢切换与调用链路生效配置写完不代表生效必须逐步验证。我分成四步每步都有明确的成功信号。第一步验证 System 1 单独可跑。用一个简单问题触发快路径import os, httpx, tomllib with open(config.toml, rb) as f: cfg tomllib.load(f) headers { Authorization: fBearer {os.environ[cfg[api][api_key_env]]}, Content-Type: application/json, } payload { model: cfg[system1][model], messages: [{role: user, content: 今天北京天气怎么样}], temperature: cfg[system1][temperature], max_tokens: cfg[system1][max_tokens], } r httpx.post(f{cfg[api][base_url]}/v1/chat/completions, headersheaders, jsonpayload, timeout60) print(r.status_code, r.json()[choices][0][message][content][:80])成功信号返回 200内容里包含天气相关回答且响应时间在 2 秒内。如果超时先检查base_url是否漏了/v1路径TaoToken 的兼容接口需要完整路径。第二步验证 System 2 慢推理可跑。把model换成system2.model问题换成需要多步的比如“对比三篇近期关于 Agent 记忆机制的论文列出共同点和分歧”。成功信号响应时间明显变长10 秒以上返回内容有结构化对比且引用了多个来源。第三步验证 router 切换。构造一个 System 1 置信度低的问题观察日志里是否出现escalate事件。你可以在代码里加一行打印if result[confidence] cfg[router][complexity_threshold]: print(f[router] escalate to system2, confidence{result[confidence]:.2f})成功信号日志出现 escalate且后续请求确实用了system2.model。如果一直不升级检查complexity_threshold是不是设得太低或者 System 1 的置信度计算逻辑没接上。第四步验证调用链路完整性。用一次完整研究任务跑通检查agent_state.db里是否同时有 System 1 和 System 2 的记录且tool_state被压缩成摘要。成功信号数据库里能看到两条不同system字段的记录reasoning_window生效历史推理没有被全量传入。5. 本篇常见错排查第一个高频错误是base_url写成https://taotoken.net/api后直接拼/chat/completions漏了/v1。TaoToken 的兼容接口路径是/api/v1/chat/completions少一段就 404。排查方法用 curl 直接打一次看返回体里的 error message。第二个错误是 System 1 和 System 2 共用同一个max_tokens。System 1 设太大浪费成本System 2 设太小会导致慢推理被截断表现为“回答到一半停了”。排查方法看返回的finish_reason如果是length就说明被截断调大system2.max_tokens。第三个错误是 router 的escalate_on条件写了但没触发。常见原因是 System 1 的输出结构里没有对应的字段比如你写了multi_hop但 System 1 根本没输出这个标记。排查方法先把 System 1 的原始输出打印出来确认字段名和值再回填到escalate_on。第四个错误是memory.reasoning_window设成 0 或负数导致 System 2 拿不到任何历史推理表现为“每次慢推理都像从零开始”。排查方法检查配置值建议至少设 2 到 3。第五个错误是工具调用状态没有压缩tool_summary设成 false导致 System 2 的上下文被工具原始输出撑爆。排查方法看单次请求的 token 数如果超过max_tokens的 80%就该开摘要了。注意排障时优先用最小请求验证单点不要一上来就跑完整研究任务。双系统链路长单点验证能快速定位是 API 层、模型层还是 router 层的问题。6. 接入文档与后续动作如果你在接入过程中遇到鉴权或路径问题直接查接入文档最省时间入口是 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 。文档里有完整的请求示例和错误码说明比在代码里反复试要快。验证模型阶段建议先用模型对话页面手动跑几轮快慢对比确认 System 2 的慢推理在你的任务上确实有增益再写进config.toml。入口是 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite 。长期编码或 Agent 类任务用 Coding Plan 通道更划算入口是 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite 。最后说一个我踩过的坑双系统的memory不要用内存字典进程一重启状态就没了慢推理的中间结果全丢。用 sqlite 或文件持久化调试时还能回放。配置骨架先跑通再逐步调complexity_threshold和reasoning_window这两个参数直接决定成本和效果的平衡点。