Coverage for agentos/tools/risk.py: 57%

42 statements  

« prev     ^ index     » next       coverage.py v7.14.3, created at 2026-07-09 09:19 +0800

1""" 

2AgentOS v1.1.4 Tool Risk Rating — 工具风险分级。 

3 

4给每个工具标注低/中/高风险,触发对应级别的 guard 检查。 

5灵感来自 OpenAI Agents SDK 的 Tool Risk Rating 设计。 

6""" 

7 

8from __future__ import annotations 

9 

10from dataclasses import dataclass 

11from enum import StrEnum 

12 

13 

14class ToolRiskLevel(StrEnum): 

15 """工具操作风险等级。 

16 

17 LOW: 只读查询、信息检索,无副作用 

18 MEDIUM: 写入/修改操作,可逆或有审计 

19 HIGH: 删除、支付、发消息等不可逆操作 

20 CRITICAL: 系统级操作(格式化、重置、权限变更) 

21 """ 

22 

23 LOW = "low" 

24 MEDIUM = "medium" 

25 HIGH = "high" 

26 CRITICAL = "critical" 

27 

28 

29@dataclass 

30class ToolRiskRating: 

31 """工具风险评定元数据。""" 

32 

33 level: ToolRiskLevel = ToolRiskLevel.MEDIUM 

34 """风险等级。""" 

35 

36 reversible: bool = True 

37 """操作是否可逆。""" 

38 

39 requires_approval: bool = False 

40 """是否需要人工审批。""" 

41 

42 financial_impact: bool = False 

43 """是否有财务影响。""" 

44 

45 description: str = "" 

46 """风险说明。""" 

47 

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 ) 

55 

56 

57# ── 常见操作的风险预设 ────────────────────────────────────────────────────── 

58 

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} 

145 

146 

147def get_risk_preset(tool_name: str) -> ToolRiskRating | None: 

148 """根据工具名称获取预设风险等级。""" 

149 return RISK_PRESETS.get(tool_name.lower()) 

150 

151 

152def infer_risk_level( 

153 tool_name: str, 

154 tool_description: str = "", 

155 arguments: dict | None = None, 

156) -> ToolRiskRating: 

157 """根据工具名和描述推断风险等级。 

158 

159 优先使用预设,否则通过关键词推断。 

160 """ 

161 preset = get_risk_preset(tool_name) 

162 if preset: 

163 return preset 

164 

165 name_lower = tool_name.lower() 

166 desc_lower = tool_description.lower() 

167 

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"] 

172 

173 all_text = f"{name_lower} {desc_lower}" 

174 

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 )