当前位置: 首页 > news >正文

Agent 可靠性工程实战(二):把工具调用从“模型想做”变成“宿主允许做”

本篇直接复用上一篇的Ledger.append()load_events()runs/demo-001/events.jsonl。上一篇最后一条model_proposed事件就是本篇授权器的输入;本篇新增tools.jsonpolicy.py,输出tool_allowedtool_denied事件。模型只描述意图,真正的文件路径解析与权限判断由宿主完成。

一、工具声明不是权限

read_file的 JSON Schema 发给模型,只代表模型知道怎样构造参数,不代表它获得了读取任意文件的能力。如果宿主直接执行模型给出的路径,../../.ssh/id_rsa、符号链接和绝对路径都可能越出工作区。安全边界必须位于模型无法修改的确定性代码里。

tools.json用数据描述每个工具的操作类别、允许根目录和单次输出上限。策略默认拒绝:名称不存在、参数缺失、路径越界或操作类别不匹配都会产生明确原因码。原因码比自然语言稳定,后续统计和回放不会因翻译变化而失效。

{"schema_version":1,"tools":{"read_file":{"operation":"read","roots":["workspace/src","workspace/tests"],"max_bytes":65536},"run_tests":{"operation":"execute","commands":[["python","-m","unittest"]]}}}

运行输出:

loaded_tools=2 schema_version=1

下面的路径判断先做词法拒绝,再解析真实路径,最后用relative_to验证所属关系。只用字符串前缀会把/work/app-copy误判成/work/app的子目录;只删除..又挡不住指向外部的符号链接。

from__future__importannotationsimportjsonfromdataclassesimportdataclassfrompathlibimportPathfromtypingimportAnyfromledgerimportLedger,load_events@dataclass(frozen=True)classDecision:allowed:boolreason:strnormalized:dict[str,Any]definside(path:Path,root:Path)->bool:try:path.relative_to(root)returnTrueexceptValueError:returnFalsedefauthorize(call:dict[str,Any],manifest:dict,project:Path)->Decision:spec=manifest["tools"].get(call.get("tool"))ifspecisNone:returnDecision(False,"unknown_tool",{})ifspec["operation"]=="read":raw=call.get("path")ifnotisinstance(raw,str)orPath(raw).is_absolute():returnDecision(False,"invalid_path",{})candidate=(project/raw).resolve()roots=[(project/root).resolve()forrootinspec["roots"]]ifnotany(inside(candidate,root)forrootinroots):returnDecision(False,"outside_roots",{"path":str(candidate)})returnDecision(True,"allowed",{"path":str(candidate),"max_bytes":spec["max_bytes"]})returnDecision(False,"unsupported_operation",{})defmain()->int:events_path=Path("runs/demo-001/events.jsonl")proposed=load_events(events_path)[-1]["payload"]manifest=json.loads(Path("tools.json").read_text(encoding="utf-8"))decision=authorize(proposed,manifest,Path.cwd())Ledger(events_path,"demo-001").append("tool_allowed"ifdecision.allowedelse"tool_denied",{"reason":decision.reason,**decision.normalized},)print(f"allowed={decision.allowed}reason={decision.reason}")return0if__name__=="__main__":raiseSystemExit(main())

运行输出:

allowed=True reason=allowed

二、为什么规范化必须发生在执行前

权限判断若针对原始字符串,执行时再解析路径,两阶段看到的可能不是同一个对象。攻击者可以让符号链接在判断后指向另一个位置,这叫检查与使用之间的竞态。对高风险写操作,仅靠resolve()仍不够,需要使用支持目录文件描述符的系统调用、打开后核验 inode,或把执行放进只挂载允许目录的隔离环境。

本系列先把读工具限制在项目内,并把规范化后的绝对路径写入授权事件。执行器只能消费授权事件里的路径,不能重新使用模型原参数。记忆点是:裁决输入可以来自模型,执行输入必须来自裁决结果。两者看似重复,实际切断了“审的是 A,做的是 B”。

三、拒绝也是正常控制流

工具被拒绝不应抛出含糊的内部异常,也不该自动把权限扩大后重试。宿主把outside_roots连同允许根目录反馈给下一轮,模型可以选择合规路径。连续拒绝会消耗预算,防止模型无限探测目录。不存在的文件与无权访问也应使用不同原因码:前者可能通过选择其他文件恢复,后者需要用户明确授权。

输出上限同样属于权限。读取一个数百兆日志会挤掉上下文并增加费用,即使路径合法也可能造成拒绝服务。执行器读取max_bytes + 1个字节,超限时返回摘要与截断标志,而不是默默截断后假装得到完整文件。

四、怎样验收策略没有形同虚设

至少覆盖正常相对路径、绝对路径、..、相似目录名前缀和指向外部的符号链接。测试不能只断言布尔值,还要检查账本追加的原因码与规范化路径。tools.json自身必须由人工控制,不能放在 Agent 可写目录;否则模型只需给自己增加一个shell工具。

本篇输出仍是runs/demo-001/events.jsonl,现在多了一条带规范化路径的授权事件。下一篇会读取run_started.payload.goal与这条授权事件,生成contract.json:把原始目标、允许修改范围和检查命令做成指纹,防止重试过程中目标悄悄漂移。

参考来源

  • Python 文档|pathlib — Object-oriented filesystem paths
  • OWASP|Path Traversal

👍 觉得有用就点个赞 + 收藏,方便回头查阅;有疑问直接在评论区留言,我看到都会回。

🚀 本文属于《Agent可靠性工程实战》系列,持续更新,关注不迷路。

📌 文章里的代码都能直接跑。想要可直接 clone 的完整工程 + 配套部署脚本 / 踩坑清单?评论一声或发邮件到cj2664@qq.com,我免费发你。
如果你正好在做类似系统、或有工程化难题想找人做,也欢迎邮件聊一句——我按实际情况评估,能落地的就接单或出方案。评论和邮件都能直接找到我,不用跳别的平台。

http://www.jsqmd.com/news/1294651/

相关文章:

  • AI 办公自动化实践 OpenClaw 小龙虾部署要点与指令示例(含安装包)
  • C++ STL容器选型实战:从数据结构原理到性能优化指南
  • Beyond Compare 5密钥生成器:如何快速解决评估模式错误的技术方案
  • 2026 承德非急救长途转运合规救护车京津冀辽蒙五省跨省护送服务 - 趣闻早乐评
  • 5个核心技巧:从零开始掌握Nexus Mods App模组管理
  • 西门子PLC电磁阀控制FB设计:从状态机到工程实践
  • 南京大学 操作系统 (JYY) 学习笔记:并发编程、线程与多处理器的深渊 (Concurrency)
  • Agent 可靠性工程实战(三):给目标做指纹,防止重试把“修正确”偷换成“变绿色”
  • 2026年7月联想Lenovo维修服务网点|最新服务电话及全部地址信息查询|故障检测服务流程指南 - 品牌资讯服务
  • 高密市紫叶矮樱花镜厂家推荐,密枝红叶李花镜厂家哪家好?2026避坑指南:4个坑+5条硬标准 - mobible
  • FAB洁净室等级体系:微粒控制与分级管理实战
  • 量化交易Python环境搭建:Anaconda与VSCode配置指南
  • Openclaw框架解析:AI Agent开发与多智能体协作实践
  • 硬件驱动电路设计:从电流电压到PCB布局的实战指南
  • 消防水池就地液位显示装置怎么安装 - 水位监测系统观察员
  • AI驱动的漏洞管理平台:架构设计与工程实践
  • 深度修复戴森V6/V7电池:开源固件终极实战指南
  • KMS智能激活终极指南:三步解决Windows和Office永久激活难题
  • 英语单词稳步精进教程
  • 2026 年程序员拿 Offer,AI 协作的权限与日志才是“隐形门槛”
  • 告别“软文换皮”,济南本土GEO服务商技术实力与落地服务能力深度横评 - 资讯在线
  • 3分钟解决Windows臃肿问题:Win11Debloat系统优化工具完全指南
  • 个体工商户营业执照怎么注销?工商户营业执照需要准备哪些材料? - 信息快递
  • 7月全国三大除甲醛公司推荐 直营品牌引领合规品质升级 - GEORANK
  • qt creator x86交叉编译arm 配置
  • 珠海配电柜回收华南回收行业避坑科普 - 广东再生资源回收
  • Java开发海洋生物科普系统的架构设计与实践
  • EuroSAT遥感数据集终极指南:从卫星图像到智能土地分类
  • 3步掌握AMD Ryzen终极硬件调试工具:SMUDebugTool完全指南
  • 2026 伊春非急救长途转运正规救护车黑吉辽蒙四省跨省护送服务 - 趣闻早乐评