过去半年,我们团队把钉群里那些散落的“技术提问、需求流转、数据查询”消息,逐步改造成了一条由Agent 基础设施支撑的全链路任务流水线:在钉群@机器人发起请求,平台完成路由、拆解、执行、交付,最终把产物回传群里。这篇文章想记录的,不是某个 Agent 玩出了多惊艳的效果,而是我们搭建团队级 Agent 基础设施时踩过的坑、验证过的方案,以及那些只有到了多人协作场景才真正暴露出来的问题。
先说结论:很多人以为“团队级 Agent”就是把一个单机 Agent 接上钉群机器人,大家一起用。实际做下来你会发现,从“能用”到“团队可用”之间隔着一整套基础设施——请求建模、路由分发、执行编排、记忆恢复、产物回传、权限审计、评估回归。这每一环都有大量工程细节,光靠提示词优化解决不了。
这篇文章会比较长,适合已经在做 Agent 应用、想往团队级规模推进的开发者。我会按我们实际落地的链路顺序来写,尽量把关键决策背后的原因说清楚。
1. 团队协作里的真实场景:为什么非得把钉群提问做成任务
先还原一下我们当初的痛点。团队几十号人,日常有大量重复性诉求散落在各个钉群里:后端问某个服务的调用方式、运营要一份数据报表、测试要生成一批测试数据、前端想知道一个接口的返回结构。以前这些事要么找人私聊,要么在群里轮番 @,要么等人有空了再去处理。效率低不说,很多信息在聊天记录里淹没,过两周想找当时的结论,翻半天翻不到。
我们最初的想法是“搞个智能问答机器人”,把团队的文档喂进去,让它在群里回答问题。试了一段时间发现,问答只能解决“知道”,解决不了“办事”。同事问“帮我查一下 order 表里 24 小时内失败订单有多少”,他真正想要的不是一段 SQL 讲解,而是那份查询结果;运营说“给我出一份本周各渠道的转化日报”,她要的是一个可以直接打开的表格文件,不是生成步骤的说明。
这就是我们把定位从“问答机器人”调成“任务交付平台”的根本原因。Agent 不应该只是话痨,它要把对话变成动作,把动作变成产物,再把产物送回到对话里。钉群的价值在于它是入口和出口:入口是老板、运营、技术都习惯的地方,出口是产物可以自然回传和留存的地方。
在这个阶段,我们确立了三个核心使用场景:
- 技术助手:查日志、查表结构、排查报错原因、解释某段代码逻辑。
- 数据助手:写 SQL、查数据、生成报表文件,回传表格附件。
- 流程助手:发起审批、创建需求单、把信息整理成结构化工单。
三个场景看起来不复杂,但它们对基础设施的诉求是一致的:要能理解意图、要有工具能力、要能跑长任务、要能交付文件、要有人能审计到底发生了什么。
提示:如果你是刚开始做这件事,建议不要一上来就追求“全场景通吃”。先挑一个高频、结果可验证的场景跑通全链路,比如“查数据并回传表格”。这个场景能覆盖消息接入、意图识别、工具执行、产物回传、失败重试五个核心环节,非常适合用来做基础设施的第一版验证。
2. 整条链路的骨架:从一个 @ 到交付产物的六个环节
团队级 Agent 全链路的核心不是某个模型多聪明,而是整条链路的工程化程度。我们最终沉淀下来的架构,可以概括成六个环节:
| 环节 | 职责 | 核心难点 |
|---|---|---|
| 消息接入 | 接收钉群消息、解析触发指令 | 消息噪声过滤、用户身份映射、幂等 |
| 请求建模 | 把非结构化提问转为结构化任务 | 上下文补齐、意图判定、参数抽取 |
| 路由分发 | 决定任务交给哪个 Agent | 意图分类、路由测试、兜底策略 |
| 执行编排 | 拆解任务、调度工具、循环迭代 | 状态管理、超时重试、并发控制 |
| 交付回传 | 把结果和产物送回钉群 | 文件上传、富文本卡片、失败说明 |
| 治理审计 | 记录全过程、评估质量、权限管控 | 埋点规范、评估集、审计日志 |
这个骨架看起来简单,但每一环在实际落地时都有很多细节。我后面几节会逐层拆开讲,先说说整体设计的两个原则。
第一个原则是**“对话有状态,任务有身份”**。钉群里的每个请求,我们都会生成一个全局唯一的 task_id。不管后续是调大模型、跑工具、多轮迭代还是失败重试,全程都带着这个 task_id。这样做的直接好处是:用户可以在群里问“刚才那个任务怎么样了”,我们能把状态捞出来追踪。更深层的好处是,它为日志关联、性能分析、成本归因、审计追溯提供了统一的主键。没有这一层,整个基础设施就是一盘散沙。
第二个原则是**“工具是能力边界,模型是决策边界”**。我们明确了一点:Agent 能做什么由工具列表决定,Agent 怎么做由模型推理决定。因此所有外部系统操作(查库、调接口、读文档、发消息)都必须封装成工具,由平台统一管理权限和审计。这样既保证了能力可扩展,也保证了权限边界安全可控。
3. 钉群消息接入与请求建模:第一道闸门怎么做才稳
消息接入是整个链路里看起来最简单、实际最容易翻车的地方。先泼一盆冷水:钉群的机器人回调接口,收上来的消息比你想象的要脏得多,不加清洗直接喂给大模型,轻则任务跑偏,重则上下文被撑爆、直接报错。
3.1 消息噪声过滤:别把闲聊当成任务
我们接的第一个版本,只要群里@机器人就触发任务,结果群里聊天时的@、讨论时的@、甚至别人发个表情包@了一下,全都进到任务链路里,推理费用哗哗涨,群里同事也被频繁的“收到”刷屏烦得要死。
后来我们加了严格的触发条件:只处理以“@机器人”开头且包含明确动作指令的消息;纯寒暄消息、非任务消息,机器人直接不响应。同时维护一个“消息意图预判”层:用一个轻量模型或者规则,先判断这条消息到底是不是任务请求。是的再去触发完整链路。这套预判机制把无效任务请求降低了约七成,成本控制效果立竿见影。
3.2 用户身份映射:钉号与平台账号的桥接
钉群的用户 ID 是钉钉体系里的 ID,我们的平台有自己的用户体系,两者要做映射。不做这层映射会出大问题。比如某个同事通过群机器人发起一个查询数据表的任务,如果平台不知道这个钉钉 ID 对应谁,就无法做权限校验,也无法确定该给这个任务挂哪个数据源权限、哪个审批流程。
我们实现了一个简单的映射服务:第一次使用机器人时,要求用户在群里发一条认证消息,机器人回传一个链接,让用户点击完成钉钉ID和平台账号的绑定。绑定之后,每次任务自动带上用户身份。这套机制虽然多了一步操作,但在权限审计时价值非常大——出了问题我们能知道是哪个人在什么时间发起过什么任务,这是团队级基础设施的合规底线。
3.3 消息清洗与上下文补齐:模型表现的天花板
钉群消息天然碎片化:同事可能先发一句“那个查询能帮我做一下吗”,然后又补一句“就是 order 表那个”。如果模型只看到第二条,根本不知道“那个”指什么。我们在消息进入 Agent 之前,会先做一个“会话合并”处理:以自然时间窗口或用户会话 ID 为单位,把前后多条消息组装成一个完整请求。
具体的做法是:为每个钉群会话维护一个滑动窗口,把近 5 条消息按时间倒序拼接,加上“用户最新意图大概率在最后一条消息”的提示词约束。这样模型在理解任务时会同时看到前面的语境,回答准确性明显改善。
另一个经验是请求建模时,一定要把环境信息说清楚。所谓环境信息,包括当前时间、用户身份、所在群名称、群标签。例如“查一下今天的失败订单”,如果模型不知道“今天”是哪天,很容易拿训练数据里的时间瞎猜。这个细节我们第一版没做,后来发现模型经常把“今天”理解成上下文无关的日期,才补上了系统级的时间注入。
4. 路由识别节点:怎么判断这话该谁干、该用哪个 Agent
路由是团队级 Agent 基础设施里最容易“被低估”的模块。很多人以为路由就是让大模型做个意图分类,但实际运行之后你会发现,路由的准确率直接决定整个系统的口碑。路由错了,后面一切能力都白搭——而且用户不会认为是“路由出了问题”,只会觉得“这个机器人不行”。
4.1 路由方案演进:从规则到分类器再到模型
我们早期的路由实现非常朴素:用关键词规则,消息里出现“查”“统计”“报表”就丢给数据 Agent,出现“日志”“报错”“异常”就丢给技术 Agent。这套规则在最初几十条消息里表现还行,但很快暴露问题:团队内口语表达太丰富了,“看看最近接口稳不稳”这种话,既没有“查”也没有“日志”,规则直接懵掉。
后来我们换成了基于少量样本的意图分类模型:预先标注几百条典型请求,训练一个多分类模型,把消息分到“数据查询、技术排查、流程发起、闲聊、其他”五类。效果比规则好很多,但维护成本高:团队业务变化快,新场景出现时又得重新标注和训练。
最终我们采用的是“模型为主、规则为辅”的混合路由:
- 先用系统级规则做快速拦截(例如黑名单话题、非任务话题直接返回)。
- 再用大模型做意图分类和参数抽取,输出结果为结构化 JSON。
- 最后用轻量规则校验 JSON 格式和取值范围,不合规则进入“澄清追问”流程。
这套方案兼顾了准确率和可维护性:规则处理高频场景、模型处理长尾场景、最后的校验兜底避免模型乱输出。
4.2 路由测试:把“拍脑袋”变成“可回归”
路由模块一定要有独立的测试集,这是我们从惨痛教训里总结出来的。有一段时间我们频繁调整 Agent 的提示词,每次都觉得“这次肯定更准了”,结果上线后总有某个场景被改坏,用户反馈 “以前能识别的问题现在不认识了”。后来我们建立了一个包含几百条消息的回归测试集,每改一次路由逻辑,就全量跑一遍测试集,算准确率和分类混淆矩阵,低于基线就回滚。
这个测试集的做法很简单:把历史消息里被验证过的请求整理成 JSON 文件,每条包含“原始消息、上下文、期望路由的目标 Agent、期望抽取的参数”。测试时逐条调用路由模块,和期望结果比对。虽然朴素,但它让路由优化从“玄学”变成了“可量化”。
4.3 兜底策略:宁可追问,不要猜错
路由模块一定要有完善的兜底。我们发现一种很典型的情况:模型对一个请求的意图不够确定时,会随机挑一个概率最高的分类先干活。结果就是“帮我写个周报”这种请求,被路由去查了数据库,折腾半天给出一堆毫不相关的数据。
我们的对策是:给路由模型加一个“信心阈值”机制,当最高分类的概率低于设定阈值时,不直接路由,而是进入澄清流程——机器人回复“我理解您可能想让我做 A 或 B,请确认一下”。这虽然多了一轮对话,但避免了错误执行带来的更大返工成本。对团队级基础设施来说,可控性比“看起来很智能”重要得多。
5. 多 Agent 协作与工具调用的执行编排
路由解决“谁来干”,执行编排解决“怎么干”。这一节是工程复杂度最高的地方。我们经历了从“单 Agent 直连工具”到“多 Agent 协作 + 任务编排”的演进过程,其中有几个关键抉择值得展开说说。
5.1 单 Agent 的局限:不能把对话历史当状态
第一版执行器是“单 Agent + ReAct 循环”:拿到用户请求后,大模型反复思考“我需要调用哪个工具、得到什么结果、下一步怎么做”,直到任务完成。这个模式在有明确工具链的场景下能用,但它有两个团队级场景无法容忍的问题。
第一个问题是上下文无限膨胀。Agent 每轮推理都把全部对话历史和全部工具输出塞进上下文,任务一长,Token 费用飙升,而且模型会在大段上下文中“迷失”关键信息,导致后面几轮决策质量明显下降。第二个问题是无法并行和编排。一个请求可能需要“先查数据库 A 拿到用户列表,再逐个调接口 B 查状态”,再并行做“生成汇总表”,单 Agent 的顺序推理做不了 DAG 型任务编排,效率极低。
5.2 多 Agent 协作:分工明确,避免“什么都干”
我们最终把执行器拆成了“编排者 + 多个专业 Worker Agent”的架构。编排者负责理解任务目标、拆解子任务、监控子任务完成状态、汇总结果。专业 Worker 只负责某一类能力:数据库查询、代码解释、文档生成、报表生成、外部 API 调用等。
这个架构的收益很直接:
- 每个 Worker 的提示词可以写得很专、工具列表很小,模型决策精度大幅提升。
- 编排者可以并行调度多个 Worker,子任务之间互不阻塞。
- 某个 Worker 失败时,编排者可以单独重试这个子任务,而不是整个任务从头再来。
这里有个常被问到的概念区分:harness 和 Agent 的区别。简单说,harness 是“承载 Agent 运行的平台外壳”,负责工具注册、上下文管理、模型调用、安全控制这些通用机制;Agent 是“基于模型 + 提示词 + 工具的具体智能体实例”。我们在实践中是把 harness 当成“运行时”,把各种 Worker 当成“运行时上加载的配置”。搞清这个关系,团队分工才不会乱:工程团队维护 harness,业务团队维护 Agent 配置,两者通过接口协作。
5.3 工具调用规范:一切能力皆工具,一切工具皆入档
团队级 Agent 里,工具是核心资产。我们规定所有外部操作一律封装为工具,并给每个工具定义统一的 JSON Schema:工具名称、入参、出参、错误码、权限要求、调用示例。这个规范的好处是,所有 Agent 都能通过同一种方式调用任意工具,新增能力时不需要改 Agent 代码,只要向工具仓库注册一个新工具。
工具出错处理我们也做了标准化。以前 Worker 调工具出错时,模型会把原始报错贴给用户,满是技术黑话,同事根本看不懂。后来我们要求工具对输出做“用户可读化处理”——工具层捕获异常并转化成“失败原因 + 建议动作”,例如“查询超时,请稍后重试”或“没有该数据源的权限,请联系管理员开通”。这个“把报错翻译成人话”的工作看似低技术含量,却大幅改善了使用体验。
5.4 超时与重试:长任务一定要异步化
钉群机器人响应是有超时限制的,但我们很多任务——查全量数据、生成复杂报表、批量处理——执行时间远超限制。如果同步等待结果,唯一的结局就是“请求超时,任务失败”,用户看到机器人没有任何反应,体验极差。
我们把执行链路改成了异步任务模式:收到请求后,立即回用户一条“收到,任务正在处理中,预计需要 N 分钟,完成后我会在这里通知您”。然后任务进入后台队列,由 Worker 执行;完成后再通过消息卡片把结果和产物推回钉群。
异步化带来两个额外收益:一是可以对任务做优先级排队,高优请求插队处理;二是任务执行过程中,用户可以随时追问状态,平台能通过 task_id 查询进度。这套异步模式,是钉群机器人从“玩具”变成“团队基础设施”的关键一步。
6. 记忆、上下文与状态恢复:长任务不断线的三个关键
团队级 Agent 和单机 Demo 的最大差别,在于它的任务常常不是“一次对话就能结束”的。用户可能上午发起一个查询,下午追问“那个结果里异常的那几条再帮我看看”,甚至第二天继续“基于昨天的结果再出一份周报”。这个场景考验的是 Agent 的记忆和状态恢复能力,而不是模型能力。
6.1 短期会话上下文:钉群会话维度的状态管理
我们为每个钉群会话维护了一个短期上下文存储,记录最近若干轮的任务请求和结果摘要。用户新的追问进来时,系统自动携带该会话的最近一轮任务结果摘要,作为上下文补充。
这里有个经验:不要直接把上一轮的完整结果塞给模型。上一轮的结果可能是一张很大的表格,全量塞进上下文既浪费 Token 又干扰判断。我们的做法是让模型在完成任务时同时产出一份“任务摘要”:做了什么、得出什么结论、关键数字是什么、产物文件 ID 是什么。这份摘要几百字左右,存入会话上下文。下一轮追问时把摘要拿出来用,效率高很多。
6.2 长期记忆:把高频知识沉淀到向量库
团队级 Agent 要面对的另一个问题是:同样的问题会被不同人反复问。“XX 服务的鉴权方式是什么”“XX 表的字段含义是什么”,每次都要 Agent 现查文档或现读代码太浪费,而且回答质量不稳定。
我们做了一层知识沉淀机制:当 Agent 完成一个任务后,如果判定其结论具备复用价值,就把“问题 + 回答摘要”写入向量知识库。后续相同或相似提问,路由会走“记忆检索”路径,先检索知识库,命中高相似度就直接复用历史结论,不再重新执行任务链路。
这个机制要控制好两个边界:一是知识过期问题,我们会给知识条目标注来源时间和失效时间,涉及动态数据(例如线上配置、当前状态)的知识不做长期记忆;二是权限边界,从知识库读到的历史回答,必须是发起查询的人有权限看的内容,否则会造成信息越权泄露。
6.3 任务断点恢复:跑挂了不能从头再来
长任务跑了一半挂了,是最影响团队信任的事。我们做任务编排时,把每个任务拆成可独立执行的最小步骤单元,每一步执行完成后,把当前状态写入持久化存储。
这样当某一步失败时,编排者有两种处理方式:如果错误可重试(例如超时、服务暂时不可用),单独重试该步骤;如果错误不可恢复(例如缺权限、数据不存在),则记录失败原因,向钉群汇报失败信息,同时把任务状态标记为“失败”。
对用户来说,这避免了“第 3 步永久失败却要从第 1 步重新再来”的糟糕体验。对系统来说,步骤级状态持久化也为后续做 human-in-the-loop(人工介入)留了口子——某些关键步骤可以设计为“需要用户确认后继续”,这在团队级场景里非常有用。
7. 交付回传、沉淀与审计:任务真正闭合的标志
任务执行完不等于结束,把结果顺利送回用户手里、并让过程可追溯,才算一个完整的闭环。这一节说说我们在交付和审计上的实践。
7.1 产物类型与回传策略:不只是发一段文字
钉群里的交付物形态,决定了用户觉得这个 Agent “好不好用”。我们总结了几类回传方式:
- 短结论型:直接回复一段文字摘要,适合“接口是否正常”“报错原因是什么”这类简单问题。
- 文件型:生成 CSV、Excel、PDF 等文件,通过钉群机器人接口上传为附件,适合数据报表、导出清单。
- 卡片型:用钉钉消息卡片展示结构化的关键信息,例如任务进度、关键指标、审批状态。
- 链接型:当产物是平台内可访问的资源时,生成一个链接,用户点击进入平台查看详情报表。
我们的经验是:默认优先用文件型交付数据类任务。原因是群里看文字摘要,人们还是很难直接使用数据;如果生成文件,用户可以直接下载、转发、继续加工,价值感完全不同。
7.2 失败交付也要体面:给出可理解的原因和补救路径
任务失败时,回传消息的设计同样重要。我们规定失败回传必须包含三个信息:失败原因(用户可读)、建议补救动作、工单编号或者 task_id。例如:
“很抱歉,订单数据表查询失败。原因是数据源连接超时(task_id: xxx)。建议稍后重试,或联系数据平台团队检查数据源状态。”
这样同事收到失败消息后,知道是怎么回事、下一步该怎么办,而不是盯着一个技术报错日志发呆。同时,带 task_id 意味着他可以随时把这条消息转给负责人,后者能顺着 ID 查日志、定位问题。
7.3 任务归档与知识沉淀:让每一次交付都有长期价值
每次任务执行的全过程,包括原始请求、路由结果、工具调用记录、中间产物、最终结果,我们都会存入任务归档库。这个库至少有三个用途:
- 用于审计回溯:任何一次异常操作都能查到对应的人和请求。
- 用于构建评估集:从归档库里抽取历史请求,构造回归测试集。
- 用于知识沉淀:挖掘高频问题,补充到长期记忆库和帮助文档。
实践了几个月后,任务归档库成了我们团队最有价值的数据资产之一。很多“这个机器人在群里做过什么”的问题,都可以直接从归档库里找到答案,不需要再去问同事。
8. 评估、权限与治理:团队级基础设施和“跑通的 Demo”之间的分水岭
最后一节,讲那些让 Agent 从个人玩具变成团队服务的关键工程项。这些东西不性感,甚至很琐碎,但没有它们,系统根本无法在几十人、上百人的团队里稳定运行。
8.1 评估体系:没有量化,就没有优化
我们团队的 Agent 评估体系分三层:
- 单任务正确性评估:对每个任务,判断最终结果是否满足用户要求。数据类任务可以自动化比对结果集,非数据类任务采用人工打分。
- 链路质量评估:统计任务完成率、平均完成时长、首次尝试成功率、工具调用失败率、Token 成本等指标。
- 用户反馈评估:在钉群交付卡片上内置“有用/没用”按钮,用户点选后反馈会回流到评估系统。
这套评估体系的最大价值,不是给团队一个“分数”,而是让每一次改动都有据可依。比如我们的路由模块做了优化,上线前后对比任务完成率和用户负面反馈率,数据一出来,就知道改动是正向还是负向,不用靠感觉拍板。
注意:Agent 评估一定要警惕“幸存者偏差”。如果只评估成功执行的任务,你会漏掉那些“路由错了但用户将就着用了”的坏案例。所以我们的评估集里专门保留了大量“边界、歧义、缺参数”的请求,确保系统在模糊场景下的表现也处于监控中。
8.2 权限与数据安全:Agent 能访问什么,必须清晰可控
团队级 Agent 能接触的数据范围,比个人 Agent 大得多,权限设计是硬底线。我们按照“最小权限”原则做了三层设计:
- 用户维度:每个用户在平台上有自己的角色和权限组,Agent 发起数据访问时必须校验用户权限。
- 数据源维度:每个数据源配置独立的白名单,一个 Agent 只能访问它职责范围内的数据源。
- 工具维度:每个工具标注可调用用户范围和频控策略,敏感操作(如发消息给外部、执行写操作)需要二次审批。
执行写操作时的“人工确认闸门”特别重要。早期我们让 Agent 直接执行数据更新类操作,结果有一次它把参数理解错了,更新错了数据,虽然影响不大但吓出一身冷汗。后来所有写操作都必须先输出“即将执行的操作内容”,用户确认后才实际执行。
8.3 灰度发布与回滚:别让一次改动影响全团队
团队级基础设施的每一次 Agent 配置调整,都相当于一次线上变更。我们建立了简单的灰度发布流程:先在内部测试群里发布新配置,用模拟请求跑一轮回归;再选择一个小团队作为灰度群,观察实际任务表现;确认没问题后,再全量发布。
这套流程虽然多花了一两个小时,但避免了很多次“上线后同事来吐槽”的尴尬场面。尤其是模型的提示词改动,经常是这边感觉优化了、那边某个场景却坏掉了,灰度群是发现这类问题的最早警报。
8.4 成本与降本实践:模型推理费用必须盯住
团队级 Agent 运行起来后,最大的成本项就是大模型推理。我们踩过的成本坑主要有三个:
- 上下文无限膨胀:如上文提到的,长任务对话历史不断累积,费用成倍上涨。解决办法是任务摘要替换 + 定期裁剪上下文。
- 无效重试:工具调用失败后,模型反复用相同方式重试,白白消耗 Token。解决办法是限制单步最大重试次数,超过则触发“更换策略”指令。
- 过度工具调用:有些简单任务模型会拆成很多步,每一步都调一次大模型。解决办法是给模型提供“直接回答”选项,不需要工具时可以不调工具。
我们做了简单的 Token 成本看板,把每个任务的平均成本和按用户、按功能的成本分布都展示出来。有了数据之后,优化目标就清楚了:哪个场景最烧钱,就针对性优化那个场景的提示词和工具设计。
回到开头说的那句话:团队级 Agent 基础设施,难点从来不在“让模型生成一段合理的回复”,而在于把钉群杂乱的请求变成可追踪、可控制、可交付、可审计的任务。这条链路没有多少高深的理论,全是工程细节的堆积。但也正是这些细节,决定了同事是觉得“这个机器人真好用”,还是觉得“这玩意儿也就玩玩”。
如果你也正在从单机 Agent 往团队级推进,我的建议是先找一条高频、结果可验证的业务线,把消息接入、路由、执行、交付、审计这五块骨架搭起来。不要一上来就追求“所有问题都能解决”,先把“一类问题能稳定解决”跑通,再逐步扩展工具和场景。这条路看起来慢,实际上是最稳的。