一个回答需要10分钟:飞书问答机器人踩坑实录——纯Agent自由检索,差点让我们的机器人“难产”
一次关于“为什么生产级Agent必须学会做减法”的实战复盘
01. 缘起:给内部开发者配一个“懂代码”的飞书助手
我们团队内部维护着大量的自研工具和软件。其中核心的XXX项目涉及多个私有代码仓库,总代码量数万行,文档采用渐进式披露的方式嵌在代码仓库里。日常工作中,内部开发人员在使用这些工具时遇到报错,高频地截图丢到群里问。
“这个报错什么意思?”
“这个工具怎么又挂了?”
重复性问题消耗了大量人工答疑时间。我们决定做一个飞书机器人——一个能看懂报错截图、能翻源码、能查文档的AI Agent。用多模态模型识别截图内容,用Qwen开源的几十B多模态模型做基座模型,配上Pi Agent做底层的任务理解,任务拆解,调度,代码分析等——让它像一个高级工程师一样在代码库里“自由翱翔”找答案。
听起来很完美,对吧?
现实给了我们一记响亮的耳光。
02. 大坑:当“自由Agent”陷入“10分钟魔咒”
理想中秒回的机器人,在实际内测中变成了“加载中”的噩梦。
我们原本的方案很纯粹:纯靠Agent自主决策。用户丢来报错截图,多模态模型识别文字,Agent开始在代码仓库里“掘地三尺”。我们提供的就是自带文档的多个代码仓库(当然,文档的内容质量我们是可以保障的)——就是让Agent自己决定翻哪里、怎么翻。
通过Langfuse链路追踪,我们看到了触目惊心的一幕:解决一个稍微复杂的问题,Agent竟然需要发起50到100次的工具调用。
它在干什么?不断地用Grep试探关键词,用Bash查目录结构,用Read读疑似文件。因为上下文不够,还要启动Sub-Agent去子目录里继续翻
更让我们崩溃的是对比实验。我们使用了完全相同的Prompt,让业界公认的Coding Agent标杆——Claude Code——来执行同样的任务。结果呢?也需要10到15分钟。
15分钟!在飞书这种即时通讯场景下,等一个机器人回复要一刻钟,这根本不可用。
不仅如此,由于有时遇到未知的问题,Agent偶尔还会脱离代码实际情况,仅凭问题表面的通用知识胡诌答案。更糟糕的是,因为耗时过长,直接触发了我们设定的超时限制——用户连结果都等不到,只看到一句“请求超时”。
我们意识到:飞书问答机器人和我们平时用coding agent寻找bug不一样,用户不会等待那么长时间获得回答,因此在这种场景下,完全的“自由意志”是致命的。仅凭AGENTS.md以及一些文档,然后靠agent调用多次工具来查找答案,纯粹是在浪费Token和时间。Agent再聪明,没有方向感也是白搭。
03. 破局:不要纯RAG,也不要纯Agent,要“粗搜+精搜”分层
针对这种问题,我们下一步探索的解法是:摒弃非黑即白的方案,采用“粗搜(混合检索)定位区域” + “精搜(Coding Agent)校验事实”的两阶段策略。
第一步:粗搜(混合检索)——解决“去哪看”
这里的核心洞察是:文档和代码分开处理。
纯RAG(向量检索)搜代码一些致命伤:它是语义搜索不是关键词精准搜索,且会破坏代码之间的结构性和关联性。在源码阅读中,我们更依赖精确的符号和关键词——函数名、类名、错误码,这些东西差一个字就完全不一样。且RAG的分块很有可能把代码的层级关系和关联关系破坏掉,所以我们对代码的搜索不用RAG。
所以我们粗搜层采用BM25(关键词精确匹配) + RAG(语义向量)的混合检索,而且主要针对文档部分(而非源码)。文档采用递归分块512 token,保证检索颗粒度精准,既有语义理解又有精确匹配。
当用户发来报错截图时,多模态模型先提取关键报错码和核心名词。粗搜层迅速在文档库中定位出“可能涉及的模块、配置项或变更记录”。
这个阶段的目标很明确:不求甚解,但求缩小包围圈。告诉精搜层:“这个问题大概率跟‘权限配置模块’和‘最新提交的Feature-X’有关,重点去这几个文件里看。”
第二步:精搜(Coding Agent)——解决“是什么”
有了粗搜提供的“嫌疑人名单”——具体的文件路径、函数名、相关文档片段——我们才把这个结论作为先验知识注入给Coding Agent。
此时,Coding Agent不再是蒙眼狂奔。它带着地图进场,知道该读哪个文件、该查哪个函数。工具调用不再需要那么多的试探,直接瞄准目标定向验证。
粗搜负责广度和效率,精搜负责深度和准确——各司其职,互不干扰。
当然,这只是我们提出的一个可能的解决方案,我们会在下周实施,且在下一篇中说一下效果。
如果你也在做类似的企业级AI Agent项目,欢迎交流。踩过的坑,值得让更多人绕过去。
