Coverage for agentos/tools/risk.py: 57%
42 statements
« prev ^ index » next coverage.py v7.14.3, created at 2026-07-06 20:49 +0800
« prev ^ index » next coverage.py v7.14.3, created at 2026-07-06 20:49 +0800
1"""
2AgentOS v1.1.4 Tool Risk Rating — 工具风险分级。
4给每个工具标注低/中/高风险,触发对应级别的 guard 检查。
5灵感来自 OpenAI Agents SDK 的 Tool Risk Rating 设计。
6"""
8from __future__ import annotations
10from dataclasses import dataclass
11from enum import StrEnum
14class ToolRiskLevel(StrEnum):
15 """工具操作风险等级。
17 LOW: 只读查询、信息检索,无副作用
18 MEDIUM: 写入/修改操作,可逆或有审计
19 HIGH: 删除、支付、发消息等不可逆操作
20 CRITICAL: 系统级操作(格式化、重置、权限变更)
21 """
23 LOW = "low"
24 MEDIUM = "medium"
25 HIGH = "high"
26 CRITICAL = "critical"
29@dataclass
30class ToolRiskRating:
31 """工具风险评定元数据。"""
33 level: ToolRiskLevel = ToolRiskLevel.MEDIUM
34 """风险等级。"""
36 reversible: bool = True
37 """操作是否可逆。"""
39 requires_approval: bool = False
40 """是否需要人工审批。"""
42 financial_impact: bool = False
43 """是否有财务影响。"""
45 description: str = ""
46 """风险说明。"""
48 def requires_user_confirm(self) -> bool:
49 """是否需要二次确认。"""
50 return (
51 self.level in (ToolRiskLevel.HIGH, ToolRiskLevel.CRITICAL)
52 or self.requires_approval
53 or self.financial_impact
54 )
57# ── 常见操作的风险预设 ──────────────────────────────────────────────────────
59RISK_PRESETS: dict[str, ToolRiskRating] = {
60 # 只读操作 → LOW
61 "list_files": ToolRiskRating(
62 level=ToolRiskLevel.LOW, reversible=True, description="只读文件列表"
63 ),
64 "read_file": ToolRiskRating(
65 level=ToolRiskLevel.LOW, reversible=True, description="只读文件内容"
66 ),
67 "search": ToolRiskRating(level=ToolRiskLevel.LOW, reversible=True, description="搜索查询"),
68 "get_current_time": ToolRiskRating(
69 level=ToolRiskLevel.LOW, reversible=True, description="读取系统时间"
70 ),
71 "weather_query": ToolRiskRating(
72 level=ToolRiskLevel.LOW, reversible=True, description="天气查询"
73 ),
74 # 写入操作 → MEDIUM
75 "write_file": ToolRiskRating(
76 level=ToolRiskLevel.MEDIUM, reversible=True, description="创建或写入文件"
77 ),
78 "create_directory": ToolRiskRating(
79 level=ToolRiskLevel.MEDIUM, reversible=True, description="创建目录"
80 ),
81 "rename_file": ToolRiskRating(
82 level=ToolRiskLevel.MEDIUM, reversible=True, description="重命名文件"
83 ),
84 "update_config": ToolRiskRating(
85 level=ToolRiskLevel.MEDIUM, reversible=True, description="修改配置"
86 ),
87 "send_http_request": ToolRiskRating(
88 level=ToolRiskLevel.MEDIUM, reversible=True, description="发送HTTP请求"
89 ),
90 "install_package": ToolRiskRating(
91 level=ToolRiskLevel.MEDIUM, reversible=False, description="安装软件包"
92 ),
93 # 删除/破坏 → HIGH
94 "delete_file": ToolRiskRating(
95 level=ToolRiskLevel.HIGH,
96 reversible=False,
97 requires_approval=True,
98 description="删除文件(移入回收站)",
99 ),
100 "delete_directory": ToolRiskRating(
101 level=ToolRiskLevel.HIGH,
102 reversible=False,
103 requires_approval=True,
104 description="删除目录",
105 ),
106 "truncate_table": ToolRiskRating(
107 level=ToolRiskLevel.HIGH,
108 reversible=False,
109 requires_approval=True,
110 description="清空数据库表",
111 ),
112 "send_message": ToolRiskRating(
113 level=ToolRiskLevel.HIGH,
114 reversible=False,
115 requires_approval=True,
116 description="发送消息/通知",
117 ),
118 # 高风险/财务/系统 → CRITICAL
119 "execute_payment": ToolRiskRating(
120 level=ToolRiskLevel.CRITICAL,
121 reversible=False,
122 requires_approval=True,
123 financial_impact=True,
124 description="执行支付操作",
125 ),
126 "format_disk": ToolRiskRating(
127 level=ToolRiskLevel.CRITICAL,
128 reversible=False,
129 requires_approval=True,
130 description="格式化磁盘",
131 ),
132 "reset_system": ToolRiskRating(
133 level=ToolRiskLevel.CRITICAL,
134 reversible=False,
135 requires_approval=True,
136 description="重置系统",
137 ),
138 "modify_permissions": ToolRiskRating(
139 level=ToolRiskLevel.CRITICAL,
140 reversible=True,
141 requires_approval=True,
142 description="修改系统权限",
143 ),
144}
147def get_risk_preset(tool_name: str) -> ToolRiskRating | None:
148 """根据工具名称获取预设风险等级。"""
149 return RISK_PRESETS.get(tool_name.lower())
152def infer_risk_level(
153 tool_name: str,
154 tool_description: str = "",
155 arguments: dict | None = None,
156) -> ToolRiskRating:
157 """根据工具名和描述推断风险等级。
159 优先使用预设,否则通过关键词推断。
160 """
161 preset = get_risk_preset(tool_name)
162 if preset:
163 return preset
165 name_lower = tool_name.lower()
166 desc_lower = tool_description.lower()
168 # Critical keywords
169 critical_kw = ["format", "reset", "payment", "root", "sudo", "admin privilege"]
170 high_kw = ["delete", "remove", "drop", "purge", "truncate", "send", "publish", "notify"]
171 medium_kw = ["write", "create", "update", "modify", "install", "deploy", "execute", "run"]
173 all_text = f"{name_lower} {desc_lower}"
175 if any(kw in all_text for kw in critical_kw):
176 return ToolRiskRating(
177 level=ToolRiskLevel.CRITICAL,
178 reversible=False,
179 requires_approval=True,
180 description=f"推断为 CRITICAL: {tool_name}",
181 )
182 if any(kw in all_text for kw in high_kw):
183 return ToolRiskRating(
184 level=ToolRiskLevel.HIGH,
185 reversible=False,
186 requires_approval=True,
187 description=f"推断为 HIGH: {tool_name}",
188 )
189 if any(kw in all_text for kw in medium_kw):
190 return ToolRiskRating(
191 level=ToolRiskLevel.MEDIUM,
192 reversible=True,
193 description=f"推断为 MEDIUM: {tool_name}",
194 )
195 return ToolRiskRating(
196 level=ToolRiskLevel.LOW,
197 reversible=True,
198 description=f"推断为 LOW: {tool_name}",
199 )