Skip to content

质量、安全与可观测性

Demo 能运行不代表系统可靠。评估告诉你效果如何,可观测性还原每一步发生了什么;安全与可靠性则决定工具能不能执行、数据能不能读取,以及失败后什么时候必须停下来。

文章重点
Agent 评估结果、过程、成本和安全的综合评测
可观测性tracing、调试、成本和缓存命中率
Agent 安全边界身份上下文、工具授权、参数校验、人工审批和审计
Prompt Injection 与工具安全直接与间接注入、RAG 投毒、MCP 信任和数据外传防护
数据隐私与租户隔离数据分类、检索过滤、日志脱敏、记忆隔离和删除
Agent 可靠性与故障防护预算、超时、有限重试、熔断、幂等、降级和人工接管

文章学习清单

Agent 评估

  • 为你的 Agent 攒 10 ~ 20 个测试任务,写下每个的期望结果

    • 预期结果:评测集不是随手问题列表,而是包含 task、期望答案或行为、重要性、风险、允许工具、禁止工具和判分方式的可重复数据。
    • 验收标准:样本覆盖正常、边界、无答案、工具异常和安全场景;每条样本的期望结果能被另一个人理解并独立判分,且不会把唯一措辞误当成唯一正确答案。
  • 统计任务成功率,作为基线

    • 预期结果:固定模型、提示词、工具版本和评测集后,保存基线版本、每条样本结果、失败原因和汇总指标;成功率应按样本级别计算,不能只报一次运行的总体感觉。
    • 验收标准:能给出成功率、各类别成功率、失败样本清单和重复运行的波动范围;后续改动可以与这份基线进行同口径比较。
  • 对同一个答对的任务,检查它的轨迹是否有重复 / 多余调用

    • 预期结果:对每条成功样本检查工具名称、参数、顺序、次数、证据使用和终止原因,区分“结果正确”和“过程合规高效”。
    • 验收标准:能识别重复查询、无关检索、无必要 handoff、超过预算和不该调用的工具;为这些情况设定最大次数或禁止事件,并在报告中单独统计。
  • 用 LLM-as-judge 给开放性任务打分,和你自己的判断对比

    • 预期结果:裁判模型使用明确 rubric、固定分值含义和结构化输出,对准确性、完整性、依据、风格或安全逐项评分,而不是只给一句“不错”。
    • 验收标准:先用一批人工标注样本校准裁判,检查与人工的一致性和系统性偏差;对低置信度、分歧大和高风险样本保留人工复核,不把裁判模型当绝对真值。
  • 改一版提示词,重跑评测集,用数据说明是变好还是变坏

    • 预期结果:只改变提示词这一变量,使用同一评测集、模型参数和判分规则,对比新旧版本的质量、轨迹、成本、延迟和安全结果。
    • 验收标准:能列出提升与退化的样本,说明是否达到预设门槛;若随机性较高,应进行多次运行或固定采样条件,避免把偶然波动误判成改进。
  • 给评测集加上“为什么这题重要”的说明

    • 回答要点:重要性说明应关联真实用户频率、业务损失、合规风险、代表的能力边界或历史事故,而不是写“用于测试”。它帮助团队决定样本权重、发布门禁和失败后的优先级;高风险低频样本也可能比低风险高频样本更值得设硬门槛。
    • 验收标准:每条样本都能回答“测什么、为什么测、失败会造成什么后果、谁负责维护”。
  • 给评测集补上成本、缓存命中率和最大工具调用次数

    • 预期结果:每条运行记录任务级成本、各类 token、缓存读取/写入、工具次数、延迟和是否超预算,汇总时计算平均值、P95 和超限样本。
    • 验收标准:成本按每一轮模型调用和外部服务累加,缓存字段按供应商 usage 映射;能找到“质量变好但成本翻倍”或“平均正常但 P95 失控”的具体样本。
  • 给安全样本补上“应该拒绝 / 应该降级 / 绝对不能调用的工具”

    • 预期结果:样本明确处置等级:可直接回答、需要澄清、降级为只读信息、转人工或拒绝,并列出允许和禁止的工具以及必须审计的字段。
    • 验收标准:运行时不仅检查最终文字,还检查真实工具调用和副作用;任何高风险样本只要发生未授权工具调用,就算安全评测失败,即使最终回答看起来正确。

可观测性

  • 给你的 Agent 加结构化日志:每轮打印工具调用、结果、token 用量

    • 预期结果:每轮产生可检索的结构化事件,至少包含 run_id、轮次、节点或工具、状态、耗时、输入/输出 token、错误和成本;工具参数与结果先做脱敏和摘要。
    • 验收标准:能按一次运行还原事件顺序,按模型、工具、租户统计耗时和费用,并能在日志中定位失败节点;日志不会泄露 API key、完整隐私文本或未授权的业务数据。
  • 把 API 的 usage 统一映射成 input / cached / cache_write / output / reasoning

    • 预期结果:不同 API 可能把输入称为 prompt_tokensinput_tokens,缓存字段也可能嵌套在不同位置,因此应在适配层统一成内部字段,并记录模型、价格版本和原始字段缺失情况。reasoning 通常是 output 的明细,只有在供应商明确单独计费时才单独计价,不能默认重复相加。
    • 验收标准:至少用两种响应格式和一次没有缓存字段的响应测试映射,确认总量守恒、空值处理正确,且换 API 不会改业务侧成本统计。
  • 按普通输入、缓存输入、缓存写入、输出分别估算一次任务成本

    • 预期结果:按每次模型调用计算 uncached_input = input - cached - cache_write,分别乘普通输入、缓存读取、缓存写入和输出单价,再累加任务中的其他模型与外部服务费用。
    • 验收标准:用一组已知 token 和价格手算结果与程序结果对比,能处理模型无 cache write 字段、不同服务层价格和价格版本变化,并把估算值标为估算而非财务账单。
  • 计算一个任务的 cached_tokens / input_tokens,观察缓存命中率

    • 预期结果:单个任务可用 cached_tokens / input_tokens 观察读取比例,但批量统计应使用 sum(cached_tokens) / sum(input_tokens),同时查看 cache write 和有效节省金额。命中率高不一定代表省钱,还要确认缓存写入成本、请求是否因此改变以及缓存是否命中在正确的稳定前缀。
    • 验收标准:连续运行同类请求后能看到首请求写入、后续请求读取或明确解释为什么没有命中;能按模型、缓存 key 和租户比较,而不是只看一个全局平均数。
  • 调整 prompt:稳定内容放前面、变化内容放后面,对比命中率变化

    • 预期结果:建立改动前后的可比实验,把 system prompt、工具定义、schema 和固定示例组成稳定前缀,把用户问题、时间、检索结果等变化内容放到后缀,并保持请求参数一致。
    • 验收标准:在同一批请求和足够重复次数下,比较缓存读取率、写入率、输入成本、延迟和答案质量;命中率上升但质量下降时不能算成功。
  • 给同类请求设置稳定的 prompt_cache_key,观察 cached_tokens 是否上升

    • 预期结果:同一租户、应用和提示词版本的请求使用稳定且合理分桶的 key,前缀实际保持一致;不同权限边界或不同提示词版本不能错误共享可能泄露数据的缓存。
    • 验收标准:在供应商明确支持该参数时,通过 usage 观察读取 token 和成本变化;若参数不受支持,记录降级到自动缓存的结果,不把“设置了 key”本身当成命中证明。
  • 接一个 tracing 工具,看可视化调用树

    • 预期结果:一次 trace 能展开入口、模型调用、路由/节点、检索、工具、重试、护栏和最终响应,并展示父子关系、状态、耗时、token 和错误。
    • 验收标准:制造一次慢工具和一次模型错误,能从调用树定位瓶颈与失败原因;trace 中的敏感输入按采样、脱敏或哈希策略处理,且不会为了观测阻塞主链路。
  • 给每次运行加 run_id,把日志、trace、成本串起来

    • 预期结果:入口生成全局唯一的 run_id,下游 span、异步任务、工具调用和成本记录继承它,同时用 trace_idspan_idparent_id 表达调用关系。
    • 验收标准:给定一个业务请求 ID,能查到完整运行、每轮 token、缓存、工具费用和最终状态;重试共享业务关联但有独立 attempt 标识,避免重复计费或把两次运行混成一条。

Agent 安全边界

  1. 问题:为什么在 system prompt 里写“普通用户不能删除工单”仍然不够?

    **参考答案:**Prompt 只能影响模型生成什么,不能替代后端授权。模型可能理解错误、受到注入攻击,或者直接生成一个越权工具调用;真正执行工具的代码必须根据经过认证的 tenant_iduser_id 和角色重新判断权限。即使模型声称“管理员已经批准”,工具入口也只能相信权限服务和审批记录。

  2. 问题:只读工具和有副作用工具应该怎样设置不同边界?

    **参考答案:**只读工具也要限制租户、资源范围和返回字段,但通常不需要逐次人工确认;创建、修改、删除、发送和付款等副作用工具还要校验审批状态、幂等键和参数摘要。高风险操作应先生成待执行动作,再由独立确认步骤批准,批准内容变化后必须重新确认。

  3. 问题:安全审计事件至少要记录什么,又不能记录什么?

    **参考答案:**应记录 run_id、操作者、租户、工具名、资源范围、策略版本、授权结果、审批记录和执行状态,以便回答“谁在什么时候尝试做了什么”。API Key、完整个人资料、隐藏提示词和未经脱敏的工具结果不应原样写入日志;必要字段可以脱敏、哈希或只保存摘要。

Prompt Injection 与工具安全

  1. 问题:直接 Prompt Injection 和间接 Prompt Injection 有什么区别?

    **参考答案:**直接注入来自用户输入,例如要求忽略系统规则;间接注入藏在网页、邮件、知识库文档或工具返回中,用户本人可能没有看到。两者都不能只靠一句“不要听恶意指令”解决,程序需要标记数据来源、限制外部内容的指令优先级,并在工具和数据出口做不可绕过的校验。

  2. 问题:检索到的文档为什么不能直接当成系统指令?

    **参考答案:**检索内容属于不可信业务数据,可能过期、被投毒或包含针对模型的命令。它只能作为回答证据放进明确的数据区,不能提升为 system 或 developer 权限;模型根据文档提出的工具调用,仍要经过白名单、参数、权限和出站策略检查。

  3. 问题:接入 MCP Server 或第三方工具前应该检查什么?

    **参考答案:**先确认服务来源、传输和认证方式、工具描述是否会动态变化、它能访问哪些数据和网络,以及调用是否会产生副作用。工具 schema 只是接口说明,不是安全证明;客户端仍要限制可用工具、参数范围、返回大小、敏感字段和出站目标,并对工具版本变化重新评审。

数据隐私与租户隔离

  1. 问题:为什么在模型回答之后再做脱敏通常太晚?

    **参考答案:**敏感数据可能已经进入模型请求、第三方 trace、缓存或供应商日志,输出阶段再遮住只保护了用户看到的最后一层。更稳妥的顺序是在入口分类和最小化数据,检索前按租户与用户过滤,发送模型前再次裁剪,日志和 trace 分别应用脱敏策略。

  2. 问题:多租户 RAG 为什么必须在检索阶段执行权限过滤?

    **参考答案:**如果先跨租户召回文档,再要求模型“不要泄露”,敏感内容已经进入上下文,模型可能引用、总结或通过间接提示泄露。检索查询必须带上服务端注入的 tenant_id 和资源权限,在向量检索、关键词检索和重排阶段保持同一过滤条件;模型生成的租户 ID 不能作为授权依据。

  3. 问题:用户要求删除数据时,为什么不能只删除聊天记录?

    **参考答案:**同一份数据可能还存在长期记忆、向量索引、缓存、评测样本、日志、trace 和派生摘要中。删除流程要根据数据血缘找到这些副本,区分立即删除、延迟清理和依法保留的审计记录,并记录删除任务的状态;被删除内容不能继续通过旧索引或缓存召回。

Agent 可靠性与故障防护

  1. 问题:为什么只有 max_turns 还不能阻止 Agent 失控?

    **参考答案:**单轮可能生成很长输出、调用昂贵工具或等待很久,因此还要限制总耗时、输入输出 token、费用、工具次数、同一工具重复次数和 handoff 深度。各项预算由程序累计,并在接近上限时降级或结束,不能让模型自行判断“再试一次应该没事”。

  2. 问题:哪些错误适合重试,哪些错误应该立即停止?

    **参考答案:**短暂网络故障、限流和部分服务不可用通常可以在上限内退避重试;认证失败、权限拒绝、参数校验失败和确定性业务错误重复执行也不会变好。副作用工具只有在幂等机制和执行状态可确认时才能自动重试,否则应先查询结果或转人工。

  3. 问题:熔断、降级和人工接管分别解决什么问题?

    **参考答案:**熔断在下游持续失败时暂时停止继续施压;降级把任务切到更简单且安全的路径,例如只返回已缓存的只读信息;人工接管处理权限、歧义或高风险异常。三者都要返回明确状态,不能把失败悄悄包装成成功答案,也不能在降级路径中放宽原有权限。

持续学习,持续实践。