返回案例和资讯
技术分享2026/07/1311 分钟阅读华胥星辰团队

Agent 运行时:一次请求经历了五层

从请求进入网关到返回最终答案,经过了 Profile 路由、检索、构造上下文、模型推理与质量门控五层。每一层都有可观测的记录,每一个环节都可以独立迭代。

Agent运行时架构设计质量保证
Agent 运行时:一次请求经历了五层

写在前面 辣椒AI 最早是一个单体 Agent:提示词很长、工具很多、自主规划。跑了一段时间之后我们重构了它,做成了五层结构。这篇把每一层的职责和设计决策摊开来写。


一、从单体到分层

最初的架构很简单:

用户输入 → 一个全能 Agent(长提示词 + 多工具 + 自主规划) → 回复

在生产环境跑了真实流量后,几个问题越来越突出:

  • 同一个输入两次运行路径可能不同,用户反馈不稳定
  • 工具多了以后乱调、漏调、重复调用
  • 出错时无法定位是哪一步崩的
  • 优化一个能力(比如检索),可能影响其他能力

这些问题的根因都一样:职责太集中。 一个环节承载了太多不同的决策,改了 A 就会影响 B,测不全也防不住。

分层不是一个"好"设计,是一种"不得已"

每次有人问"你们的 Agent 架构设计为什么是分层的",我们的回答都一样:不是设计出来的,是撞出来的。

第一版上线后,连续三次线上故障(一次幻觉、一次工具超时、一次检索结果为空)的排查都极其痛苦——因为单体 Agent 的每一步都没有明确的输入输出边界,排查就是大海捞针。第三次故障处理完后,我们决定在下一版重构中把链路拆开。

这不是教科书上那种"你应该这样做架构"的设计,是"不拆开就管不住"的生存需求。


Agent 运行时的五层架构
Agent 运行时的五层架构


二、分层

代码
请求
  ↓
层① Profile 路由     ←── 这个请求属于哪一类任务?
  ↓
层② 检索             ←── 从知识库里召回相关内容
  ↓
层③ 上下文构造        ←── 把检索结果、历史对话等拼成完整提示词
  ↓
层④ 模型推理          ←── 调用模型生成回复
  ↓
层⑤ 质量门控          ←── 回答合格吗?引用存在吗?
  ↓
回复(或拦截/降级)

每一层只管一件事,输入输出结构化。下面逐层展开。


三、层①:Profile 路由

这一层的职责是把用户输入归类,决定后续走哪条处理路径。

归类依据包括:用户角色、所选的模式、历史交互特征、输入本身的内容特征。不靠模型自由规划。

目前的做法是为每一类请求定义好处理路径——用什么检索策略、用什么提示词模板、用什么模型、怎么校验输出。代价是灵活性下降,收益是行为可预测、成本可估算。

为什么不用模型做路由

用模型判断"这个请求应该怎么处理"看起来更灵活——模型可以处理你没见过的请求类型。

但问题是:

  • 路由判断本身需要一次模型调用,增加了延迟
  • 同一个请求两次可能被路由到不同的 Profile,结果不一致
  • 新上线的 Profile 需要模型"学会"识别,过渡期不精准

我们选择规则 + 特征匹配的路由方式。规则能覆盖当前已知的任务类型,未知类型有兜底 Profile。新 Profile 上线时,路由规则同步更新——这是一个显式的、可测试的变更。

路由决策的三个层次

  1. 用户角色:管理员和企业用户的默认处理路径不同
  2. 选择的模式:用户选了"知识问答"模式还是"内容创作"模式
  3. 内容特征:输入本身的内容决定了走哪条路径

分层的好处是:下层不需要知道上层为什么把它归类到这里,它只需要知道"我是属于这个 Profile 的请求,我的处理规则如下"。


四、层②:检索

不是所有请求都需要检索。这一层判断是否需要、需要什么类型的检索、以及检索策略。

不同类型的请求,检索策略不同:

  • 知识问答:语义检索(向量) + 关键词检索(BM25),两种结果融合排序
  • 表格数据查询:需不需要查关系数据?
  • 多材料综述:需要跨文档检索,对去重的要求更高

检索结果是一份结构化列表,每条包含:片段 ID、内容摘要、来源、权重、权限标记。

混合检索的融合排序

语义检索和关键词检索各有优势场景。融合之后需要对两边的结果合并去重并重新排序。

我们的做法是 Reciprocal Rank Fusion(RRF)——它不关心具体分数的量级,只需要知道每个结果的排名位置。语义结果排第 1 和关键词结果排第 3 的在 RRF 里得到类似的融合分,避免了"语义检索的分数是 0.92、关键词检索的分数是 12.5"这种不可比的问题。


五、层③:上下文构造

把检索结果、用户历史交互、当前问题、用户偏好设置拼成一个完整的提示词。

这里的核心约束:

  • 控制长度——留给回答的空间要够。总长度等于拼接的上下文加上模型最大输出长度,必须保证回答不会被截断。
  • 保持结构——而不是把所有内容揉成一段长文本。检索结果按来源分组、历史对话按时间排列、偏好设置放在末尾。
  • 权限信息在检索层已经过滤——这一层只负责组装,不负责筛选。

上下文预算管理

对于不同 Profile,上下文的分配策略不同:

  • 知识问答:检索结果占 60%,历史对话占 20%,偏好占 10%,余量 10%
  • 多材料综述:检索结果占 80%,其他占 20%
  • 简单对话:检索结果占 30%,历史对话占 50%,余量 20%

这个预算分配不是死的,会根据实际的 token 计数动态调整。


六、层④:模型推理

调用模型生成回复。这一层的复杂度不在调用本身(换模型厂商只是个配置切换),而在于:

  • 流式输出控制——逐 token 推给前端,前端做打字机效果
  • 超时与降级——超时后不是返回报错,而是返回"正在处理中,稍后查看"的提示
  • 模型级错误处理——配额耗尽、内容安全拦截、输出截断,每种有各自的处理方式

不同 Profile 可以使用不同规格的模型——简单任务用小模型,复杂推理用大模型。这是分层架构最直接的收益之一。


七、层⑤:质量门控

这是最后一道防线。从多个维度检查回复质量:

  • 引用校验——引用的片段 ID 是否存在?内容是否真实?是否越界?
  • 事实一致性——回答和检索到的证据是否矛盾?
  • 格式完整性——结构化输出是否符合预期格式?
  • 敏感内容——有没有泄露不该说的信息?

不通过校验的回答会被标记,根据 Profile 配置决定是重新生成还是直接拦截。

质量门控的"先记录、后拦截"策略

新的校验规则上线时,先只在观测模式下记录,不拦截。跑一段真实流量后分析误伤率,再决定是否正式上线为拦截模式。这个策略让我们避免了很多次"一条规则上线后大量正常回答被拦截"的事故。

关于这套可观测能力的实现,详见《Agent 可观测性:用三张表回答"它当时到底做了什么"》。


八、每层独立可观测

每一层都产生结构化日志,记录输入、输出、耗时和状态。串联请求标识可以看出整个链路。

这带来的实际收益:

  • 排障时能精确定位是哪一层的问题——不需要在大段文本日志里 grep
  • 优化时能看出瓶颈在哪——是检索慢还是模型慢,数据不会骗人
  • 成本分析时能按层、按 Profile 统计消耗——哪些请求最贵、哪些步骤最耗 token

九、分层的代价

没有免费午餐。分层带来了:

  • 延迟增加。五层意味着五次内部串行处理,即使每层都很快,串在一起也增加了整体耗时。
  • 更多组件要维护和监控。每一层都是一个独立的代码模块,有自己的配置、日志和错误处理。
  • 错误会传递。上一层的小偏差到下层可能被放大。这是为什么我们在每层之间要求结构化的输入输出——便于做中间态的校验和告警。

延迟控制

五层的端到端延迟目标在 2 秒以内(不含模型推理时间)。主要通过:

  • 每一层内部做超时控制,不无限等待
  • 检索层做并行查询(语义 + 关键词同时跑)
  • 上下文构造是纯 CPU 操作,耗时控制在 50ms 以内

实测下来,检索层是最大的延迟来源(因为要等网络返回),其他三层都在几十毫秒级别。


十、这套结构适合谁

如果你在做一个需要稳定运行、需要排障、需要持续优化的 Agent 系统,分层结构值得参考。

如果只是一个原型或内部工具,单体 Agent 完全够用。不要为了分层而分层——我们分是因为被实际问题逼到了这一步。


想聊 Agent 架构设计,欢迎联系我们。

想在你的业务里试试同样的做法?

告诉我们业务问题与数据现状,我们会给出方案建议与落地路径。