ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Deepseek Harness 四大执行模式对比:架构师视角下的 subagent 与 workflow 配置骨架

Deepseek Harness 四大执行模式对比:架构师视角下的 subagent 与 workflow 配置骨架 1. 为什么四种执行模式总被用混Deepseek Harness下文简称 DSH里能派活给子代理的入口有四个subagent、subagent_fork、workflow、ralph。名字看着像同一族函数实际是四种完全不同的架构组件——上下文契约、生命周期、阻塞行为、成本模型都不一样。我见过最常见的翻车方式是把subagent当同步函数用、把workflow当单任务调度器用、把ralph当自动重试用结果要么主会话被上下文撑爆要么循环空转烧 token。这篇面向需要在真实项目里落地多模式编排的架构师交付三样东西一张五维对照表、一份可直接复制的config.tomlsettings.json配置骨架、以及逐模式切换与验证的具体动作。所有请求统一走 TaoToken 的 Key/API 通道这样你在本地联调时不用为每个模式单独配一套凭证切换模式只改配置不改接入层。先给结论这四种模式的关系类比成分布式系统里的组件更准确——subagent像 RPC 调用自包含、无状态subagent_fork像带上下文快照的 RPCworkflow像消息队列 流水线扇出、barrier、结构化收口ralph像定时任务 事件循环每轮全新、靠外部状态续命。把它们当四个名字一样的函数来用是绝大多数配置事故的根源。2. TaoToken 前置统一 Key 与接入通道在动手写配置之前先把接入层固定下来。DSH 的四种模式最终都要发模型请求如果每个模式各配一套 endpoint 和 key排障时你根本分不清是模式配置错了还是凭证错了。我的做法是所有模式共用同一个 TaoToken API Keybase_url 统一指向https://taotoken.net/api。你需要准备的东西只有两样第一一个可用的 API Key。登录 TaoToken 控制台在 API Keys 页面创建一个复制出来。这个 Key 会被写进settings.json的环境变量段四个模式共享。第二确认 base_url。DSH 的模型请求走 OpenAI 兼容协议时base_url 填https://taotoken.net/api注意不要带多余的路径后缀也不要手动拼/v1——客户端库通常会自己补。如果你用的是 Anthropic 协议通道比如 Claude Code 那套走的是另一条 deep link配置方式不同本文聚焦 OpenAI 兼容这条主线。注意Key 不要硬编码进config.toml提交到仓库。放在settings.json引用的环境变量里或者用本地.env文件.gitignore里加一行。控制台入口在这里创建 Key 和查看用量都在同一个地方https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi_keysutm_campaignrewrite接入文档协议细节、错误码、限流说明在这里https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite3. 五维对照表与配置骨架3.1 四种模式的架构差异先把 excerpt 里那张表用架构师能直接决策的形式重排一遍补上我实测后加的成本模型一列维度subagentsubagent_forkworkflowralph上下文继承完全隔离继承本会话已完成轮次脚本编排与会话隔离全新空白无任何上下文执行模型单次/多轮委派单次/多轮委派流水线脚本循环迭代每轮全新子代理生命周期持久 subagent_id可续聊持久 subagent_id可续聊一次性脚本跑完即散多轮循环worker 报告完成/阻塞默认阻塞后台 fire-and-forget后台 fire-and-forget前台脚本跑完才返回前台每轮跑完才返回长期记忆无靠产物无靠产物无靠产物共享 workspace 作为唯一记忆成本模型单次 prompt 成本重读父会话历史token 偏高编排脚本便宜N 个子代理并发轮数 × 单轮成本关键差异不在能不能派活而在上下文契约和生命周期。subagent和subagent_fork返回的subagent_id是持久的你可以用send_message在同一子会话里继续派活workflow和ralph没有持久子代理脚本/循环结束就散了别指望回头再问某一步。3.2 config.toml 骨架下面这份config.toml是我在项目里用的骨架四个模式的开关、默认参数、并发上限都收在这里。你可以直接复制把model和max_concurrent按你的部署能力调。# config.toml — DSH 多模式编排骨架 [provider] base_url https://taotoken.net/api api_key_env TAOTOKEN_API_KEY # 从环境变量读不硬编码 default_model deepseek-chat timeout_seconds 120 [subagent] enabled true run_in_background true # 默认后台下一步依赖结果时再改 false max_concurrent 4 [subagent_fork] enabled true run_in_background true max_concurrent 2 # fork 重读历史并发压低省 token [workflow] enabled true blocking true # 前台脚本跑完才返回 max_concurrent 8 # 扇出场景可调高注意部署 cap default_meta_name unnamed-workflow [ralph] enabled true max_rounds 20 # 硬上限防止空转烧 token workspace_dir ./.dsh/workspace # 唯一长期记忆落盘位置 objective_immutable true几个参数值得单独说。subagent_fork.max_concurrent我压到 2因为每个 fork 子代理都会重读父会话全部历史并发一高 token 成本是线性涨的。workflow.max_concurrent可以到 8但你要先确认部署侧的并发 cap撞上限会直接报错。ralph.max_rounds是硬保险没有它一个判断不了完成的 objective 会让循环跑到天荒地老。3.3 settings.json 骨架settings.json负责把环境变量和模式默认值串起来。注意env段里的 Key 引用方式{ env: { TAOTOKEN_API_KEY: ${TAOTOKEN_API_KEY}, DSH_PROVIDER_BASE_URL: https://taotoken.net/api }, harness: { configPath: ./config.toml, defaultMode: subagent_fork, logLevel: info, workspace: ./.dsh/workspace }, modes: { subagent: { syncWhenDependent: true }, subagent_fork: { inheritCompletedTurnsOnly: true }, workflow: { schemaValidation: true }, ralph: { reportOnEachRound: true } } }inheritCompletedTurnsOnly这个开关对应subagent_fork的契约它继承的是已完成轮次不包括当前正在生成的那一轮。schemaValidation打开后workflow里用agent()带opts.schema的调用会做强类型校验拿到的不是自然语言而是结构化 JSON。4. 逐模式切换与验证请求配置写完不算完得逐个模式跑通验证。下面每个模式给一段最小可复制的调用和预期结果。4.1 subagent自包含 prompt 验证subagent的核心契约是子代理看不到本会话任何历史所以 prompt 必须自包含。验证方法是故意在 prompt 里省略背景看它是否报缺少上下文。// 验证 subagent 的隔离性 const id await subagent({ description: 独立调研, prompt: 请调研 Deepseek Harness 中 workflow 模式的 parallel() 与 pipeline() 的区别给出对比表格。背景这是一个多模式编排项目需要选型。产出格式Markdown 表格。, run_in_background: true }); console.log(subagent_id:, id);预期结果立刻返回一个subagent_id主线程不阻塞。等几秒后用send_message(id, 补充一下 barrier 的语义)续聊能拿到连贯回复——这验证了subagent_id的持久性。4.2 subagent_fork上下文继承验证subagent_fork要验证的是它能看到本会话已完成轮次。先在主会话里说一句我们决定用 pipeline 而不是 parallel然后 fork 出去问它我们刚才决定了什么。// 先在主会话完成一轮讨论再 fork const forkId await subagent_fork({ description: 基于刚才的讨论继续, prompt: 在刚才讨论的基础上给出 pipeline 的落地步骤。, run_in_background: true });预期结果子代理能复述出用 pipeline 而不是 parallel这个决定。如果它说我不知道你讨论过什么说明inheritCompletedTurnsOnly没生效回去检查settings.json的modes.subagent_fork段。4.3 workflow流水线扇出验证workflow是前台阻塞的脚本跑完才返回。验证重点是parallel()的 barrier 语义和pipeline()的无 barrier 语义。const result await workflow({ script: const files args.files; // pipeline每个文件独立跑完所有阶段阶段间不互相阻塞 const reports await pipeline( files, (f) agent(lint 文件 f), (f) agent(为文件 f 生成测试建议) ); return reports.filter(Boolean); , meta: { name: codebase-audit, description: 代码库审计 } }); console.log(JSON.stringify(result, null, 2));预期结果返回一个 JSON 序列化的数组每个元素对应一个文件的处理结果。注意pipeline里每个agent()调用都是独立上下文跨阶段不共享——这是反模式里最容易踩的坑。4.4 ralph循环迭代验证ralph每轮启动全新子代理唯一记忆是 workspace 文件。验证方法是看它能否靠 workspace 续命。const report await ralph({ objective: 把 src/legacy/ 下的文件逐个迁移到新架构每完成一个就在 .dsh/workspace/progress.md 里划掉一行。全部完成后报告 completion。, maxRounds: 20 }); console.log(report);预期结果每轮结束后拿到子代理报告循环直到 objective 里的完成条件满足或撞到maxRounds。如果循环卡住不动八成是 objective 里没写清如何判断完成或者任务没有可写产物——子代理下一轮会失忆。5. 本篇常见错排查5.1 报错subagent 返回结果为空或答非所问最常见原因是 prompt 不自包含。subagent看不到父会话历史如果你在 prompt 里写就像我们刚才讨论的那样它只会一脸茫然。排查动作把 prompt 单独拎出来读一遍假设你是一个刚进项目的陌生人能不能只靠这段文字完成任务。不能就补背景。5.2 报错subagent_fork 子代理说没有上下文先确认settings.json里inheritCompletedTurnsOnly为true。再确认你 fork 的时机——它继承的是已完成轮次如果你在同一个生成轮里 fork当前轮还没完成自然继承不到。排查动作在主会话完成一轮完整问答后再 fork。5.3 报错workflow 并发撞上限workflow的parallel()会同时启动 N 个子代理N 超过部署 cap 时直接报错。排查动作把config.toml里workflow.max_concurrent调低或者把parallel()换成pipeline()——后者每个 item 独立跑完所有阶段阶段间不互相阻塞峰值并发更低。5.4 报错ralph 循环空转循环跑了十几轮还在原地通常是两个原因objective 里没写可验证的完成条件或者任务没有可写产物。排查动作检查.dsh/workspace/下有没有进度文件在更新。没有更新说明子代理每轮都在失忆重来把如何判断完成和产物写到哪里明确写进 objective。5.5 报错401 / 403 鉴权失败四个模式共用同一个 Key如果某个模式报鉴权失败先确认TAOTOKEN_API_KEY环境变量在当前 shell 里可见echo $TAOTOKEN_API_KEY再确认base_url是https://taotoken.net/api且没有多余后缀。排查动作用 curl 直接打一次接口排除是 DSH 配置问题还是凭证问题。curl -s https://taotoken.net/api/chat/completions \ -H Authorization: Bearer $TAOTOKEN_API_KEY \ -H Content-Type: application/json \ -d {model:deepseek-chat,messages:[{role:user,content:ping}]}返回正常 JSON 说明接入层没问题问题在 DSH 的模式配置里。6. 选型决策与统一通道收口把决策树压缩成一句话一次性独立任务用subagent需要本会话上下文用subagent_fork可预期的批量扇出用workflow长跑且有可写产物用ralph。90% 的日常派活场景subagent_fork后台 必要时send_message续聊就够了。批量任务的三步走12 个子任务直接subagent310 个结构相似的用workflowpipeline()长跑迭代且有明确终止条件的用ralph并且一定要设maxRounds。成本意识这块再强调一次subagent_fork的子代理会重读父会话全部历史上下文真的需要才用它workflow的编排脚本本身便宜但 N 个子代理并发可能撞部署上限ralph的总成本 轮数 × 单轮成本maxRounds是你的刹车。所有模式的请求最终都走同一个 TaoToken 通道切换模式只改config.toml不改接入层。如果你还在逐个模式配凭证建议先把 Key 统一到settings.json的环境变量段再按上面的骨架逐个验证。长期跑编码和 Agent 类任务的话Coding Plan 那条通道更适合挂后台常驻https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding_planutm_campaignrewrite想先在对话里验证模型行为再写配置用模型对话页最快https://taotoken.net/chat?utm_sourcetaotoken_aicg_blog_endutm_contentmodel_chatutm_campaignrewrite配置骨架和验证动作都跑通之后你会发现这四种模式真正的价值不在能派活而在它们各自独立的生命周期和上下文契约——把它们当四种架构组件来组合而不是四个名字一样的函数来调用。
返回列表