让不同厂商的大模型进同一个「群聊」按能力干活dsh-teamcast 的设计与实现一、写这篇文章的初衷大家好我是 dsh-teamcast 的作者一个还在成长中的开发者。这个项目是我最近持续投入的一个开源小项目目前跑通了一个基础版本。开发过程中我收获很多但也越来越清楚地意识到一个项目如果只靠我一个人闭门造车很多设计问题、代码习惯问题很难被发现。所以想通过这篇文章把项目介绍给社区里的各位开发者和前辈希望得到一些真实的反馈。代码结构、实现方式、命名、文档或者任何您觉得可以改进的地方都可以直接告诉我我会认真看、认真改。二、dsh-teamcast 是什么先说痛点。现在做多智能体协作主流思路是「编排」提前画好 DAG / workflow把每个节点绑死某个模型然后照着图执行。但我自己日常用下来总觉得这不太像真实团队干活的样子——真实团队更像一个群聊群里有个 Lead任务来了临时拉人、按每个人的能力派活而不是提前把组织架构和每个人的岗位焊死。dsh-teamcast 就是冲着这个场景做的它是一个 deepseek-harnessdsh的群聊分派插件构建在官方 Agent TeamsLead 具名 teammate 持久邮箱 共享任务板之上让 Lead 在对话过程中按「成员能力画像」把子任务分派给不同厂商、不同型号的模型去执行。比如 Lead 自己用强推理模型做设计把批量机械性工作派给快而便宜的模型代码审查交给一个独立成员——成员的 provider/model 是不是合法由一份「成员名册」硬性约束可用范围由用户自己随时编辑Lead 不能越界挑模型不带路由的成员默认继承 Lead 自己的模型。一句话概括把「这个子任务用哪个模型」从提前配置变成对话中的一等公民同时用白名单守住边界。它不是追求技术炫技的玩具也不是大而全的平台就是一个我从自己日常痛点出发的小工具。目前远谈不上成熟但我希望它能真正有用。项目地址https://gitee.com/luo_yixuan/dsh-teamcast三、目前已经完成的部分核心流程闭环包装官方spawn_teammate工具增加provider/model/reasoning_effort三个可选参数Lead 派活时指定成员模型路由经底层注入生效官方的任务板、邮箱、记账逻辑原样保留。成员名册roster fail-closed 闸门spawn 时的显式路由必须命中名册或额外放行规则allowedRoutes否则直接拒绝并给出可操作的错误提示不带路由继承 Lead永远放行模板里的推荐模型只作展示提示。24 个内置职业团队模板共 122 名成员覆盖前后端、移动、游戏、嵌入式、DevOps、数据分析、翻译、安全、法务金融、电商、教育、供应链等场景每队 4-7 人成员描述写到工具级每份 SOP 是带质量门禁的流水线设置页一键导入即建队导入为整册替换单团队模式。两个只读发现工具list_group_models返回按团队分组的名册能力表list_team_templates返回模板构成与分工 SOP——Lead 派活前先查表。Web 设置卡片两级导航模板网格 ↔ 团队详情、三步向导添加成员、级联 provider→model 选择器选择面从全量 592 条收敛到单家几十条加插件总开关全部可视化编辑改完即热生效。63 条单元测试全绿覆盖路由闸门、透传层、工具包装三大模块pnpm test可复现。当前版本 v0.1.02026-10-09 发布定位是实验包这些主要用来验证方向细节还有很多要补。四、项目结构与技术思路技术选型上我尽量选自己熟悉、社区资料多的TypeScript 5.6 cordis 插件体系声明式inject依赖 schemastery 配置 vitest 单测 esbuild 构建 Web 客户端Node ^22.19 || 24MIT 协议。源码约 2600 行其中路由策略route-policy.ts刻意写成纯函数、零框架依赖方便单测和移植。获取代码gitclone https://gitee.com/luo_yixuan/dsh-teamcast.gitpnpminstallpnpmbuild:all# 宿主tsc Web 客户端esbuildpnpmtest# vitest63 条单测pnpmtypecheck# tsc --noEmit下面几个设计点是我最没把握、也最希望前辈们看看的。4.1 名册一份数据三种身份roster 条目是{name, description, provider, model, team}我让它同时充当三样东西spawn 白名单provider/model 必须命中、能力画像description 动态注入 Lead 的 systemPrompt成为 Lead 「看人派活」的依据、团队分组配合团队 SOP 做模板化分工。好处是配置面小、Lead 天然知道「队里都有谁、各擅长什么」但我也怀疑这是不是把三个概念耦合得过早了见第六节。4.2 路由闸门宁可拒绝不放脏路由闸门语义是 fail-closed 的// route-policy.tsif(!gate.allows(provider,model)){thrownewError(child LLM route ${provider}/${model} is not in the group-chat roster; allowed:${gate.describe()})}名册条目缺字段、配置写坏、provider 未注册一律拒绝且错误信息里带上当前合法路由清单引导用户去设置页补名册。模型给什么畸形入参类型用unknown接也要给出可读错误。我担心的是对个人开发者太严了会不会烦要不要加一个 warn-and-allow 的宽松模式4.3 最 tricky 的部分用 AsyncLocalStorage 补上跨层路由透传这是整个项目里我做得最不安、也最想请教的一段。调研中发现官方agentTeams.spawnTeammate()内部调用subagents.startContinuable(...)时硬编码了请求体不透传agentOptions0.1.7 / 0.2.0-rc.2 实测均如此而底层的resolveChildAgentOptions()本身完全支持agentOptions覆盖父路由。也就是说缺的只是「工具层 → 服务层」这最后一公里。我的方案是用AsyncLocalStorage携带路由而不是 fork 官方包spawn 包装层 execute └─ als.run(route, 官方 execute) ← 路由进 ALS └─ 官方 agentTeams.spawnTeammate() ← 官方记账原样保留 └─ startContinuable包装 ← 读 ALS注入 └─ request.agentOptions { provider, model }这样官方的 journal / roster 记账一行不改升级兼容面最小ALS 跨 await 传播并发 spawn 各走各的 store 互不串扰没有 store 时包装层纯透传行为与未装插件完全一致。代价是 monkey patch 了官方服务的startContinuable——卸载时我用Object.getOwnPropertyDescriptor精确还原原属性描述符而不是 delete避免把实例自有方法删没并用Symbol.for做跨模块副本的幂等标记。这个做法长期是否健康有没有更优雅的扩展点我漏掉了真心求指点。4.4 热生效volatile 现读不持有快照全部配置字段标了 cordis 的.volatile()设置页表单写入 profile 的cordis.patch.ymlLoader 原地热更不重启 fiber、不重挂工具。有个我踩过才理顺的细节插件自带的 bundle 补丁文件只在首次安装时兜底默认值它不在热更监视列表里用户编辑的真正落点是 profile 的同名文件——两个「长得一样」的配置文件职责并不相同。配套地我让所有读取点每次现场读readVolatilesystemPrompt 段也注册成动态函数() string名册改完下一次装配立刻生效。我尚未想明白的坑是热更发生在一个工具调用中途时前后两次现读可能拿到不同版本配置要不要做调用内快照4.5 分层策略分配规则与 skill 都做了分层Lead 怎么决定「活给谁」我调研后的结论是 description 匹配是主流且有效的竞标制没有产品先例、多轮广播烧 token所以做了三层逐层降级模板固定分工——用户点名某职业团队按该队 SOP 切分描述匹配——按名册 description 把子任务对到最合适的成员难活给强推理模型批量活给快模型审查给非作者成员用户点名——用户 了谁就用谁。skill 也分两层Lead 的指派方法论五步指派程序 四要素 「何时不要委派」固定注入 prompt、不受开关控制12 条执行类角色 skill 由enableSkills开关控制默认不注入、不自动匹配。4.6 角色 skill站在开源社区的肩膀上改造我不是提示词工程专家所以写角色 skill 时没有闭门造车而是站在开源社区已有成果上改造。来源与授权都在代码注释里做了说明均允许复用Lead 的指派方法论融合了四家的长处Anthropic Claude Code subagent 官方模式的指派方法论仅借鉴思路未复制任何文本——「读名册 → 拆分写域 → 四要素指派 → 验证路由 → 评审交付」的五步程序其中四要素指派要求每条派活消息必须同时包含目标GOAL、输出格式OUTPUT FORMAT、边界BOUNDARIES、上下文CONTEXT缺任何一项就说明任务还不具备派发条件宁可先自己补齐避免成员返工MetaGPT的 SOP 流水线思想——按角色职责把任务拆成带质量门禁的工序LangGPT的结构化工作流写法——把方法论写成可逐步遵循的流程而不是散落的形容词CrewAI 示例的 goal 表达——动词开头 可交付的验收标准。122 个成员的执行类角色 skill基于 awesome-chatgpt-promptsCC0 1.0、MetaGPTMIT、LangGPTMIT、CrewAI examplesMIT改造。这份来源与授权清单也同步放在仓库 README 的「致谢」一节。改造过程中我总结了几条「专业 skill 和普通 skill 的差距」也放在代码注释里顺带求做提示词工程的前辈帮我看看这些总结是否以偏概全交付物要具名——写成可验收的名词短语而不是「帮我分析一下」负面约束要显式——NEVER / DO NOT 必须真实存在输出结构提前给定——结构即质量人设用可核验的特异点替代形容词——「检查缺失的 import」比「优秀的 QA 工程师」有用精简——1-4 句足够不写 2000 词的人设小作文。五、我自己觉得还不够好的地方写这篇文章很大一部分原因就是我知道项目还有不少问题。我自己已经看到的实验包无稳定性承诺本插件 monkey patch 了官方内部服务Agent Teams 的 journal / mailbox 接口随 dsh 升级就可能失效我对 0.1.7 / 0.2.0-rc.2 两个版本做过实测peer 依赖也按 0.1.x / 0.2.x 的并集声明但这不是长久之计只有单测没有端到端63 条单测覆盖了闸门、透传、包装但真实多模型并发 spawn 的场景压测还没做写冲突只靠 prompt 软约束官方限制所有成员共享同一工作目录本插件只解决「谁用什么模型干活」不解决文件锁写域不相交目前只写在指派规则里没有硬性拦截成本账没算过跨 provider 不共享 KV cache同样的任务拆给多个厂商模型token 成本是否反而更高我没有数据文档不足README 有安装运行说明但设计决策的来龙去脉大多埋在代码注释里。六、希望大家重点帮我看看的几个方向如果各位愿意花一点时间看看代码这几个具体问题是我最想请教的跨层透传的方案选择AsyncLocalStorage 注入 vs 改用参数逐层透传 vs fork 官方包哪条路长期更健康fail-closed 闸门的松紧现在名册外路由一律硬拒绝是否应该提供 warn-and-allow 的宽松模式名册「白名单/画像/分组」三合一是不是过度耦合热更与一致性volatile 现读有没有我没想到的一致性坑后续迭代优先级是先补端到端测试和成本统计还是先做路由的观测性比如每次 spawn 记录实际模型与耗时又有哪些设计您觉得应该果断砍掉我不怕问题多只怕问题一直藏在那里。哪怕听起来很小的建议我都会认真看、认真改。七、获取代码与上手路径项目主页https://gitee.com/luo_yixuan/dsh-teamcast克隆后pnpm install pnpm build:allpnpm test/pnpm typecheck可验证测试与类型。装进 dsh 这一步 README 写了详细说明本地开发目录不建议直接dsh plugin install会重新解析依赖、顶掉钉住的版本推荐软链 bundle 注册的方式。装好后可以按 README 的「五分钟验证」走一遍① 设置 → 插件 → 群聊分派 能看到卡片模板网格显示 24 个团队② 随便导入一个模板名册出现成员默认「继承 Lead」③ 新会话里让 Lead 执行list_group_models应返回按团队分组的能力表④ 让它 spawn 一个名册外的路由如foo/bar应被拒绝——说明闸门生效。欢迎在仓库 Issues 里提问题也欢迎直接评论交流、提交修改建议。对话内大概是这样用的README 里的原例用 Agent Teams 建一个团队来分析这个目录的结构。 先 list_team_templates 看有哪些模板 然后按「网站前后端组」的分工建成员 frontend 用 buddy/glm-5.3backend 用 trae/DeepSeek-V4-Pro。作为一个还在成长中的开发者我非常珍惜每一条来自社区的反馈。八、写在最后我知道这个项目现在还有很多不足也请大家批评的时候尽量温和一些让我在改进的同时保留继续做下去的热情。但我也不会把「新项目还不成熟」当成不认真做事的借口——只要大家指出的问题有道理我一定尽快响应并改进。也借这里感谢 deepseek-harness 提供的插件体系与 Agent Teams 实验能力感谢 MetaGPT、LangGPT、CrewAI 这些开源项目——站在它们的肩膀上像我这样的初学者才敢动手。感谢每一位愿意花时间看到这里的朋友。如果你对多智能体协作、模型路由或者插件化的设计思路有任何想法欢迎随时联系我哪怕只是聊聊也好。希望 dsh-teamcast 能在一轮轮反馈中变得越来越好。