FDE W5 Day 2 学习手册 · 工具运行时与可靠性
W5 Day2 · A 级(必须掌握,面试核心)· 4h · 学完能讲透"工具鉴权怎么落地(不是靠 Annotation)、执行预算怎么设、超预算如何优雅结束"
本日定位:W5D1 讲了 Tool Runtime 的抽象层。Day2 深入它最要命的两块可靠能力:工具鉴权(谁能调什么)和执行预算(调用次数/Token/时间上限)。这是 Agent 上生产的"安全闸"和"熔断丝"。
学完能回答:① 工具鉴权在企业里怎么落地,为什么不能靠 MCP Tool Annotation;② 执行预算(次数/Token/时间)怎么设、超预算时 Agent 怎么优雅结束。
使用方法:通读原理 → 重点看「工程含义」「面试话术」「易错点」→ 做自测清单 → 配合《FDE-W5D2-评测题.md》。选中不熟的词可标注(左下★重要 / 右下📌待查)。候选人背景:36岁,Java+大数据+医疗保险行业,示例围绕特药理赔/保险知识库。
一、工具鉴权的本质:谁能在什么角色下调什么工具
工具鉴权回答一个问题:这次 Agent 调用,是否有权执行它想执行的工具?维度有三个——主体(谁)、角色(什么身份)、工具(干什么)。
| 维度 | 含义 | 保险例子 |
| 主体(Subject) | 发起调用的用户/会话身份 | 保单持有人本人 vs 客服坐席 vs 理赔员 |
| 角色(Role) | 主体在流程中的身份 | 普通查询角色 / 审批角色 / 管理员 |
| 工具(Tool) | 要执行的操作 | query_policy(只读)/ submit_claim(写)/ adjust_limit(高敏) |
allowed = policy(subject, role, tool, context) → true / false(拒绝并触发 fallback)
规则示例:普通查询角色只能调 query_policy;只有"审批角色"才能调 submit_claim;adjust_limit(调整报销上限)需管理员 + 二次确认。
鉴权本质是"授权决策点(PDP)"。企业里它不该散落在每个工具内部 if 判断,而应集中:Agent 调工具前,Runtime 统一向授权服务校验。这样策略改一处即可,且可审计(谁在何时被允许/拒绝调了什么)。
工具鉴权 = 判断"主体在什么角色下能不能调这个工具"。它是集中式授权决策,不该每个工具自己写 if,而由 Runtime 在调用前统一校验,拒绝则走 fallback。
① 鉴权是运行时动作,不是"注册时写死"。同一工具对不同用户结果不同,要靠运行时携带的 subject/role 判断。② 鉴权失败要"显式拒绝 + 留痕 + 安全降级",绝不能静默放行或静默跳过(跳过后 Agent 可能用别的方式绕过)。③ "模型说它有权"不等于真有权——模型输出不可信,必须服务端校验。
二、工具鉴权 vs MCP Tool Annotation(Annotation 只是提示)
MCP(Model Context Protocol)里每个 Tool 可带 Tool Annotation,如 readOnlyHint、destructiveHint、openWorldHint、idempotentHint。它们是给模型/客户端的"提示",不是安全边界。
| 维度 | Tool Annotation | 真正的鉴权 |
| 位置 | 工具描述(元数据) | 服务端授权(PDP/PAP) |
| 可信度 | 提示,模型可忽略/可被诱导 | 强制,服务端执行 |
| 作用 | 帮模型决策"该不该调" | 决定"能不能调" |
| 被绕过后果 | 模型乱调,但应有服务端兜底 | 越权操作,安全事故 |
MCP 规范原文也强调:Annotation 是 hint,服务器 MUST 仍执行自己的授权检查,不能因为工具标了 readOnly 就跳过鉴权。Annotation 只是优化模型行为的提示。
对 Java 背景很直观:Annotation 像接口上的 @Readonly 注释——给人/框架看的,不提供任何强制安全。真安全是 Spring Security 的 @PreAuthorize 那种服务端拦截。两者必须同时存在,且以后者为准。
Tool Annotation(readOnly/destructive 等)只是给模型的"提示",可被忽略、不可当安全边界。真鉴权是服务端授权检查(MCP 规范也要求服务器 MUST 自行校验)。Annotation ≠ 鉴权。
① 最常见的错:以为"工具标了 readOnlyHint 就不用鉴权",结果任何会话都能调,越权读患者病历——这是合规事故。② Annotation 由工具提供方写,不可信,攻击者可能故意标错(把一个写操作标成只读)诱导模型。③ 即使有 Annotation,每次调用仍要在服务端按 subject/role/tool 校验,Annotation 最多用来"提前拒绝"优化体验。
三、鉴权落地:角色 / 权限 / 策略实现
3.1 权限模型
推荐 RBAC(基于角色)+ 可选 ABAC(基于属性)。每个工具在注册时绑定所需权限标签,如 permissions:["tool:claim:submit"]。Runtime 调工具前,用"会话角色拥有的权限集合"∩"工具所需权限"判断是否放行。
// 伪代码:Runtime 调用前的授权拦截
function authorize(session, toolSpec):
required = toolSpec.permissions // 如 ["tool:claim:submit"]
granted = session.role.permissions // 角色已授权集合
if required not subset of granted:
audit.deny(session, tool, required) // 留痕
return ToolResult(error="FORBIDDEN", safe=true) // 受控拒绝
if toolSpec.requiresStepUp and not session.stepUpDone:
return ToolResult(error="NEED_STEPUP") // 二次确认
return invoke(toolSpec, session)
3.2 实现位置
- Runtime 层统一拦截:所有工具调用必经此关,业务工具零侵入。
- 对接企业 IAM:复用现有单点登录/权限中心,不另起炉灶。
- 保险场景:理赔员角色可调 submit_claim,但 adjust_limit 需"管理员 + 二次确认(step-up)"。
落地要点:权限策略集中定义、Runtime 统一拦截、对接企业 IAM、每次授权结果留痕。这样"谁能调什么"可改、可审、可回溯,满足保险行业合规要求。
落地用 RBAC:工具注册时绑权限标签,Runtime 调前用"角色权限∩工具所需"判断;高敏工具加 step-up 二次确认;对接企业 IAM;每次授权留痕。业务工具零侵入。
① 别把权限写死在 prompt 里让模型"自觉"——模型可被提示注入绕过,必须服务端强制。② 拒绝后要返回"受控错误"而非抛异常崩主流程,让 Agent 能降级(如转人工)。③ 权限粒度别太细(每字段一个权限,难维护)也别太粗(一个"理赔权限"包揽读写,违反最小权限),按业务域 + 操作类型划分。
四、执行预算①:工具调用次数上限
Agent 可能陷入"调工具 A→发现缺 B→调 B→又缺 A"的死循环,无限烧 token。必须设定单次 Agent 调用的工具调用总次数上限(如 20 次)。
if (tool_call_count >= MAX_TOOL_CALLS) → 停止调用,进入"预算耗尽"收尾分支
- 设多少:取决于任务复杂度。简单理赔查询 5–8 次;复杂多工具编排 15–20 次。太低会"没查完就被掐断",太高仍可能失控。
- 按工具分级:高成本/高风险工具(submit_claim)单独再设更紧的子预算。
次数预算是"防失控"的第一道闸。它和 W5D3 的"重试"配合:重试也计入次数预算,避免"重试把次数耗光"。超次数不是报错,而是进入可控收尾。
工具调用次数上限防死循环烧 token。按任务复杂度设(简单 5–8、复杂 15–20),高敏工具单独更紧。超次数不报错,进入可控收尾分支。
① 次数上限要"全局计数",包括重试触发的工具调用,否则重试会悄悄突破。② 上限太低会导致复杂任务"半途被掐",需配合"收尾时说明哪些没查完"而非直接失败。③ 计数要在 Runtime 层统一做,不能在各工具里各自记,否则并发/重试会漏记。
五、执行预算②:Token 预算
除了工具次数,还要限制单次 Agent 调用的总 token 消耗(输入+输出+工具结果回填)。防止长上下文 + 多轮工具结果把成本/延迟拖爆。
| 预算类型 | 控制什么 | 超限动作 |
| 输入 token 预算 | 进模型的上下文大小 | 触发裁剪(W5D1)或拒绝新增工具结果 |
| 输出 token 预算 | 模型生成长度 | 收紧 max_tokens,强制收尾 |
| 总成本预算 | 整次调用花费 | 进入收尾,报告"预算耗尽" |
Token 预算和 Context 裁剪是"一体两面":裁剪保证不超窗口,预算保证不超成本。建议在 Runtime 维护一个 running cost,每次 LLM/工具调用后累加,接近阈值就预警并准备收尾。
Token 预算限制单次调用的总 token 消耗(输入/输出/工具结果)。和裁剪一体两面:裁剪防超窗、预算防超成本。Runtime 维护 running cost,接近阈值就预警收尾。
① Token 预算和次数预算要联动:有时次数没满但 token 已爆(如一个超长工具结果),两种预算任一触发都应收尾。② 预算预警阈值要留余量(如 90% 就准备收尾),因为最后一次 LLM 调用可能还不少 token。③ 不要把溢出直接当成"失败"返回给用户,应优雅收尾并说明"已查到部分结果"。
六、执行预算③:时间预算
整体 Agent 超时:单次 Agent 调用设总时长上限(如 60s/120s)。超时就中断循环,返回目前为止的最佳答案或转人工。
deadline = now + TIME_BUDGET; 每轮循环检查 now > deadline → 中断,收尾
- 时间预算 vs 工具超时:工具超时(W5D3)是单工具调用的超时;时间预算是"整个 Agent 调用"的超时,更上层。
- 用户感知:长任务可流式返回中间进度,避免用户以为卡死。
时间预算保护"整体可用性"——一个卡死的 Agent 调用不能占着连接/线程不放。它和工具超时配合:工具超时先兜底单个慢工具,时间预算兜底整体循环。
时间预算 = 整个 Agent 调用的总时长上限(如 120s),超时中断循环收尾。它比单工具超时更上层:工具超时管单个调用,时间预算管整个 Loop。
① 时间预算要用"绝对 deadline"而非"每轮计时累加"——后者因调度抖动/并发会不准。② 超时中断要"安全":已做的部分状态要能恢复(结合 W5D1 Checkpointer),不能中断即丢失。③ 前端要有超时反馈("处理超时,已转人工/请重试"),不能静默挂起。
七、工具隔离:工具异常不影响主流程
工具可能在运行时抛异常(NPE、下游 500、超时)。隔离保证:单个工具失败,Agent 主循环不崩,而是拿到一个"受控错误"自行决策(重试 or 换工具 or 转人工)。
try { result = invoke(tool) } catch(e) { return ToolResult(error=classify(e), safe=true) }
- 异常分类:网络/超时(可重试)→ 业务校验失败(不可重试,直接告诉模型"参数不对")→ 系统错误(转人工)。
- 隔离粒度:按业务域分组线程池/协程,避免"查保单慢"拖住"算报销"。
隔离是可靠性的底线。没有隔离,一个下游抖动就让整个理赔 Agent 崩溃、用户白等。隔离 + 受控错误让 Agent "有韧性"——局部失败可吸收。
工具隔离 = 单工具失败不崩主流程,而是返回受控错误让 Agent 决策(重试/换工具/转人工)。按业务域分组执行单元,异常分类后分别处理。
① 隔离不是"catch Throwable 吞掉"——吞掉会让错误消失、问题无解,要分类返回明确错误类型。② 隔离要防"资源泄漏":工具里的线程/连接/文件句柄要在 finally 释放,否则慢工具堆积拖垮进程。③ 受控错误要带足够信息(错误类、是否可重试),否则 Agent 拿到"ERROR"无法决策。
八、资源限制:CPU / 内存 / 网络隔离
部分工具可能"吃资源"(如本地 PDF 解析、大模型本地推理、批量计算)。需要限制其资源,避免拖垮宿主。
| 资源 | 风险 | 手段 |
| CPU | 重计算占满核,别的工具饿死 | 独立进程/容器、cgroup、线程池上限 |
| 内存 | 大文件解析 OOM 杀进程 | 独立服务、内存上限、流式处理 |
| 网络 | 打爆下游/外网泄漏 | 出口白名单、QPS 限流、超时 |
对 Java 背景:这正是"把重工具拆成独立微服务 / 用线程池隔离 + 信号量限流"的思路。Runtime 层统一做资源配额,工具本身不必关心。
资源限制 = 给工具设 CPU/内存/网络配额,防重工具拖垮宿主。手段:独立进程/容器、cgroup、线程池上限、出口白名单、限流。Runtime 统一做,工具零感知。
① 不要在同一 JVM 里跑"可能 OOM 的本地解析"——一个工具 OOM 整个 Agent 进程全完。重工具应独立服务化。② 网络隔离要防"数据外泄":Agent 工具只能访问白名单内网/知识库,不能任意访问外网(合规+安全)。③ 资源配额设太紧会让正常工具被限流饿死,要压测定阈值。
九、预算超支时 Agent 如何优雅结束
"优雅结束"指:预算(次数/Token/时间任一)触发后,Agent 不抛异常、不卡死,而是产出当前最优结果 + 明确状态说明。
if budget_exhausted:
answer = synthesize(current_facts) # 用已收集信息尽量答
return AgentResult(
answer = answer,
status = "PARTIAL", # 部分完成
missing = unmet_requirements, # 还差什么没查
suggestion = "建议转人工 / 补充材料后重试"
)
- 区分"失败"与"部分完成":已查到保单就返回已知结论 + 说明缺失,比"对不起我超时了"有用得多。
- 可恢复:已收集字段保留(Checkpointer),用户补材料后从断点续,不重来。
- 转人工兜底:高敏/高风险任务超预算直接转人工,不硬编答案。
优雅结束的核心是把"预算耗尽"当一等状态处理:返回 PARTIAL + 缺失项 + 建议,而不是异常。这决定了用户体验和系统韧性。
预算超支 → 用已收集信息合成答案,返回 PARTIAL 状态 + 缺失项 + 建议(转人工/补材料重试),已收集字段保留可续。区分"部分完成"与"失败"。
① 别把"超预算"当成"成功"返回——故意给个看似完整但缺关键的答案更危险(如没查到拒赔条款就说"可全额报销")。必须显式标 PARTIAL。② 优雅结束也要"及时",不能在临界值附近还硬跑最后一次超贵调用。③ 转人工兜底要带"上下文摘要",让人一眼看懂 Agent 查到哪了,否则人工接手成本更高。
十、资源与监控:预算/鉴权全留痕
| 记录项 | 用途 |
| 每次鉴权结果(allow/deny + 原因) | 审计越权尝试、合规 |
| 工具调用次数 / token / 耗时 | 预算使用可视化、成本预警 |
| 预算耗尽事件 | 定位"任务太复杂"或"预算设太低" |
| 隔离触发的受控错误 | 定位不稳定工具 |
鉴权结果、预算用量、隔离错误全要记 Trace——尤其"拒绝"和"预算耗尽"最该记全,用于审计与调参。
① 鉴权拒绝记录要含 subject/role/tool/deny 原因,否则合规审计时说不清"为什么拒了这次理赔查询"。② 预算监控要设告警:某工具突然次数暴涨,可能是循环 bug 或被攻击。
十一、面试达标线①:工具鉴权在企业里怎么落地(不是靠 Annotation)
| 要点 | 说明 |
| Annotation 只是提示 | readOnly/destructive 等是给模型的 hint,可被忽略,不可当安全边界(MCP 规范也要求服务端自校验) |
| 集中式授权 | Runtime 调工具前统一向 PDP 校验 subject/role/tool,业务工具零侵入 |
| 权限模型 | RBAC(角色权限)+ 高敏 step-up 二次确认;对接企业 IAM |
| 拒绝处理 | 受控拒绝 + 留痕 + 安全降级(转人工),绝不静默放行/跳过 |
鉴权落地 = 集中式服务端授权(Runtime 统一拦截)+ RBAC + 高敏 step-up + 对接 IAM + 拒绝留痕降级。Annotation 只是提示,真安全靠服务端强制校验。
十二、面试达标线②:执行预算怎么设、超预算时如何优雅结束
三类预算:次数(防死循环)/ Token(防超成本)/ 时间(防整体卡死) │ 联动:任一触发即收尾 │ 优雅结束:PARTIAL + 缺失项 + 建议,不抛异常不硬编
- 次数预算:按任务复杂度设(简单 5–8、复杂 15–20),高敏工具单独更紧,含重试计数。
- Token 预算:限制输入/输出/总成本,Runtime 维护 running cost,近阈值预警。
- 时间预算:整体调用 deadline,比单工具超时更上层,安全中断可恢复。
- 优雅结束:超支后用已收集信息合成答案,返回 PARTIAL 状态 + 缺失项 + 建议(转人工/补材料),已收集字段保留可续;高敏任务直接转人工,绝不硬编完整答案。
十三、W5D2 自测清单
- 能说清工具鉴权的三维度(主体/角色/工具)和"集中式授权决策点"的设计。
- 能区分 Tool Annotation 和真正鉴权:Annotation 是提示不可当安全边界,MCP 规范也要求服务端自校验。
- 能画出鉴权落地的实现:Runtime 统一拦截、RBAC + step-up、对接 IAM、拒绝留痕降级。
- 能解释为什么"模型说有权"不可信,必须服务端强制校验。
- 能说出执行预算的三类(次数/Token/时间)各自控制什么、怎么设。
- 能讲清次数预算如何防死循环,以及高敏工具单独子预算。
- 能区分"整体时间预算"和"单工具超时"的层次关系。
- 能解释工具隔离:异常分类(可重试/不可重试/系统)与受控错误返回。
- 能说出资源限制(CPU/内存/网络)的手段与"重工具独立服务化"的原因。
- 能讲清预算超支时如何优雅结束(PARTIAL + 缺失项 + 建议),并解释为什么不能当成功返回。
十四、高频面试题速记卡
Q:MCP 的 Tool Annotation 能当鉴权依据吗?
不能。readOnly/destructive 等只是给模型的"提示",可被忽略、不可信。真鉴权是服务端授权检查,MCP 规范也要求服务器 MUST 自行校验。
Q:工具鉴权在企业怎么落地?
Runtime 调工具前统一向授权服务校验 subject/role/tool(RBAC + 高敏 step-up),对接企业 IAM,拒绝留痕并安全降级(转人工),业务工具零侵入。
Q:为什么"模型说它有权"不能信?
模型输出可被提示注入诱导,不可作为安全边界。必须服务端强制校验,否则越权读患者病历是合规事故。
Q:执行预算有哪三类?
次数(防死循环烧 token)、Token(防超成本/超窗)、时间(防整体卡死)。任一触发即收尾,且含重试计数要联动。
Q:整体时间预算和单工具超时什么关系?
工具超时管单个调用;时间预算管整个 Agent 循环,更上层。两者配合:工具超时兜底慢工具,时间预算兜底整体。
Q:工具隔离是什么意思?
单工具失败不崩主流程,捕获异常返回"受控错误"(带错误类/是否可重试),让 Agent 决策重试/换工具/转人工。异常要分类不能吞掉。
Q:预算超支时 Agent 该怎么结束?
优雅结束:用已收集信息合成答案,返回 PARTIAL + 缺失项 + 建议(转人工/补材料),已收集字段保留可续;高敏任务直接转人工,绝不硬编完整答案。
Q:为什么超预算不能当"成功"返回?
硬给看似完整但缺关键的答案更危险(如没查拒赔条款就说全额报销)。必须显式标 PARTIAL 并说明缺失。
Q:资源限制为什么要把重工具独立服务化?
同 JVM 跑可能 OOM 的本地解析会拖垮整个 Agent 进程;独立进程/容器 + cgroup 限配额,故障和资源不互相传染。
Q:权限粒度怎么定才合理?
别太细(每字段一权限难维护)也别太粗(读写一锅端违反最小权限)。按业务域 + 操作类型划分(如 tool:claim:submit)。
FDE W5D2 学习手册 · 工具运行时与可靠性(面试级)· 配合《FDE-W5D2-评测题.md》自测 · 资源:LangGraph BV1zKx4zWEZP、MCP 授权规范 modelcontextprotocol.io/specification/2025-11-25/schema
📌 待查★ 重要