智能体不是一次性的“检索 + 生成”。面对一个问题,它会先查一路资料,看结果不够再换个方式查,必要时读原文、调用外部工具,甚至把一部分工作交给另一个更专门的智能体。每一步做什么,由模型根据当前掌握的证据决定。
让模型自己决定,难点在于让它可控:不能调用不存在的工具,不能越权读数据,不能无限循环下去,失败了也不能留下半截回答。这篇讲 ApeMind 如何做到这些。
一轮的完整轨迹
下面是一轮问答的真实结构(内容为示意)。点右侧步骤或用方向键逐步查看,留意上方的状态和预算如何变化。
- 创建并抢占
同一个幂等键只会产生一轮。轮次先进入排队,抢到执行租约的进程才开始运行,多个进程不会重复执行同一轮。
- 装配这一轮
确定模型、提示词、资料范围和工具清单。历史太长时先摘要再裁剪,保证第一次请求就不会超出模型上下文。
- 第一次决策:多路检索
模型选择
search_knowledge,一次请求同时走向量、全文和图谱三路。 - 失败即信息
某次调用漏了必填参数。服务端返回可自纠的
invalid_param,而不是误导性的“查无结果”,模型下一步补齐参数重试。 - 交给子智能体
需要专门研究的部分,以结构化交接单委派给子智能体。它在独立会话里运行,结果作为一次工具返回回到这一轮。
- 回读原文
检索结果只是摘录。回答前按证据引用读回原文,确认条款号和措辞。
- 回答并附上依据
边生成边推送。本轮回读过的原文作为编号依据附在回答下方,和回答一起写入持久消息,轮次完成。
模型能看见哪些工具
模型只能调用这一轮真实注册的工具。工具清单由每个智能体的工具配置决定:管理员可以按服务器、按工具开关,不在清单里的工具,模型看不见,也调不到。
- 提示词不是白名单。系统提示词里可以介绍工作方法,但模型是否能调用某个工具,只以本轮注册的工具定义为准。
- 不确定时收窄,而不是放开。工具配置暂时读不到时,只暴露 4 个高频知识库工具:列出知识库、列出文档、统一检索、读取证据,不会退回到全量工具。
- 外部工具可插拔。除了内置的知识库、图谱、网页工具,还可以接入第三方 MCP 服务器;某个外部服务器连不上时被跳过并记录降级,不拖垮整轮。
资料范围不等于权限
用户在输入框里 @ 某个知识库,或者用 # 指定某篇文档,是在告诉智能体“这一轮先看这里”。范围按优先级确定:本条消息里明确提到的最优先,其次是请求里带的,最后是智能体的默认知识库。
但这只是选材提示。每一次真实读取,都会重新校验智能体托管密钥的授权范围、工具范围,以及当前用户对这份资料的实时权限。@ 一个无权访问的知识库不会让它变得可读;被撤销权限的资料,下一次读取就会被拒绝。
一次工具调用要穿过的几层
模型发出的调用不会原样直达工具。中间有一组包装层,各自处理一类常见问题:有的直接修好,有的把问题整理成模型能看懂的提示交回去。选一个场景,看调用在哪一层被处理。
层的排列为示意,表达的是职责而不是精确的调用顺序。
这些机制的共同点是:修复要么精确,要么不做。裸名恢复只在唯一、无歧义时生效,不做模糊匹配;参数修复记录每一次修改。修不了的问题不会被掩盖,而是变成结构化的错误交还给模型,整轮不会因为一次调用失败而重来。
预算:给每一轮划定边界
模型自己决定下一步,就必须有人决定“到此为止”。每个智能体有一个响应预算档位,同时约束三件事:总时限、工具调用次数、包含工具调用的模型轮数。显式设置的数字优先于档位。
轮数在每批工具执行之前检查:一旦超限,这一整批工具都不会执行,智能体转入回退回答,只基于已经收集到的证据作答,并说明证据边界。预算耗尽不会留下一个没有结尾的回答。
把子任务交给子智能体
一个智能体可以挂载其他智能体作为子智能体。在父智能体眼里,每个子智能体就是一个工具,名字形如 subagent__policy_researcher。调用它时必须提交一张结构化的交接单。
- goal
- 整理华东区差旅超标的完整审批链
- context_refs
- ref_12、ref_31(已读过的证据引用)
- acceptance
- 每个审批节点都要附上原文出处
- constraints
- 只看 2024 年以后生效的制度
上下文为什么不会爆
长对话和大段工具返回是上下文溢出的两大来源。运行时在每次请求模型前做三层处理:
- 工具返回按类型截断。历史里超长的工具结果按工具类型设上限,并插入截断标记,模型知道这里被省略了。
- 历史先摘要再裁剪。有会话摘要时只保留最近几轮原文,其余由摘要代替。
- 最终守护。发送前再按模型的上下文窗口检查一次,仍会溢出就直接给出友好提示并正常结束本轮,而不是发出一个注定失败的请求。
写进数据库的工具输出只保存 8 KiB 以内的预览,单个长文档不会把消息记录撑大,刷新页面后也仍能看到摘要。
依据从哪里来
搜索结果只是候选。智能体按证据句柄回读原文后,读取工具的返回会被转换成结构化的来源材料:引用的文字、知识库与文档定位、产生它的工具调用。这些材料按顺序编号,作为回答的依据,和回答一起持久化。
引用回答的是“这句话依据的是哪段原文”,帮你核对,但不等于自动证明答案完全正确。完整机制见 引用如何回到原文。
断线和刷新
执行过程通过 SSE 实时推送,每 5 秒一次心跳防止代理断开空闲连接。网络闪断后,前端带着上次收到的序号重连,从断点继续,重复的片段会被去重。隔了很久再刷新,实时事件可能已过期,这时从持久化的消息里恢复最终答案、工具摘要和引用。
运行这一轮的进程如果意外退出,后台协调器会发现失去租约的轮次,把它标记为失败,界面不会永远停在“运行中”。
边界
- 工具怎么选、先查什么后查什么由模型决定,不同模型的策略会有差异;预算和权限是硬边界,策略不是。
- 运行时保证“只用真实工具、不越权、有终点”,不保证每一次都选到最优路径。
- 公开到网站的智能体,推理过程可能对访客可见,发布前应确认它适合公开。
出问题时查哪一环
回答提到“证据不足”或比预期短
可能是预算先到了:工具调用次数或轮数达到上限,转入了基于已有证据的回退回答。在执行过程里看调用次数;问题确实复杂时,把智能体切到更大的预算档位。
智能体从不调用某个工具
先确认这个工具在该智能体的工具配置里是开启的。提示词里写了也没用,模型只能看见本轮注册的工具。
@ 了知识库,回答里却没有它的内容
@ 只是选材提示。确认智能体的托管密钥授权范围包含这个知识库,以及当前用户对它有读权限;也检查一下执行过程里检索是否返回了结果。
给想深入的读者:哪些状态是权威的
轮次的生命周期以数据库里的轮次记录为准,Redis 只保存低延迟的状态影子、执行租约、短期事件和取消标记。可刷新恢复的答案、工具摘要和引用以持久化的消息片段为准。历史事件不做长期逐条回放,长期审计依赖持久消息和调用明细账本。