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

43 statements  

« prev     ^ index     » next       coverage.py v7.14.3, created at 2026-07-03 17:38 +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, field 

11from enum import Enum 

12from typing import Optional 

13 

14 

15class ToolRiskLevel(str, Enum): 

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

17 

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

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

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

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

22 """ 

23 

24 LOW = "low" 

25 MEDIUM = "medium" 

26 HIGH = "high" 

27 CRITICAL = "critical" 

28 

29 

30@dataclass 

31class ToolRiskRating: 

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

33 

34 level: ToolRiskLevel = ToolRiskLevel.MEDIUM 

35 """风险等级。""" 

36 

37 reversible: bool = True 

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

39 

40 requires_approval: bool = False 

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

42 

43 financial_impact: bool = False 

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

45 

46 description: str = "" 

47 """风险说明。""" 

48 

49 def requires_user_confirm(self) -> bool: 

50 """是否需要二次确认。""" 

51 return ( 

52 self.level in (ToolRiskLevel.HIGH, ToolRiskLevel.CRITICAL) 

53 or self.requires_approval 

54 or self.financial_impact 

55 ) 

56 

57 

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

59 

60RISK_PRESETS: dict[str, ToolRiskRating] = { 

61 # 只读操作 → LOW 

62 "list_files": ToolRiskRating(level=ToolRiskLevel.LOW, reversible=True, description="只读文件列表"), 

63 "read_file": ToolRiskRating(level=ToolRiskLevel.LOW, reversible=True, description="只读文件内容"), 

64 "search": ToolRiskRating(level=ToolRiskLevel.LOW, reversible=True, description="搜索查询"), 

65 "get_current_time": ToolRiskRating(level=ToolRiskLevel.LOW, reversible=True, description="读取系统时间"), 

66 "weather_query": ToolRiskRating(level=ToolRiskLevel.LOW, reversible=True, description="天气查询"), 

67 

68 # 写入操作 → MEDIUM 

69 "write_file": ToolRiskRating(level=ToolRiskLevel.MEDIUM, reversible=True, description="创建或写入文件"), 

70 "create_directory": ToolRiskRating(level=ToolRiskLevel.MEDIUM, reversible=True, description="创建目录"), 

71 "rename_file": ToolRiskRating(level=ToolRiskLevel.MEDIUM, reversible=True, description="重命名文件"), 

72 "update_config": ToolRiskRating(level=ToolRiskLevel.MEDIUM, reversible=True, description="修改配置"), 

73 "send_http_request": ToolRiskRating(level=ToolRiskLevel.MEDIUM, reversible=True, description="发送HTTP请求"), 

74 "install_package": ToolRiskRating(level=ToolRiskLevel.MEDIUM, reversible=False, description="安装软件包"), 

75 

76 # 删除/破坏 → HIGH 

77 "delete_file": ToolRiskRating( 

78 level=ToolRiskLevel.HIGH, reversible=False, requires_approval=True, 

79 description="删除文件(移入回收站)", 

80 ), 

81 "delete_directory": ToolRiskRating( 

82 level=ToolRiskLevel.HIGH, reversible=False, requires_approval=True, 

83 description="删除目录", 

84 ), 

85 "truncate_table": ToolRiskRating( 

86 level=ToolRiskLevel.HIGH, reversible=False, requires_approval=True, 

87 description="清空数据库表", 

88 ), 

89 "send_message": ToolRiskRating( 

90 level=ToolRiskLevel.HIGH, reversible=False, requires_approval=True, 

91 description="发送消息/通知", 

92 ), 

93 

94 # 高风险/财务/系统 → CRITICAL 

95 "execute_payment": ToolRiskRating( 

96 level=ToolRiskLevel.CRITICAL, reversible=False, 

97 requires_approval=True, financial_impact=True, 

98 description="执行支付操作", 

99 ), 

100 "format_disk": ToolRiskRating( 

101 level=ToolRiskLevel.CRITICAL, reversible=False, 

102 requires_approval=True, description="格式化磁盘", 

103 ), 

104 "reset_system": ToolRiskRating( 

105 level=ToolRiskLevel.CRITICAL, reversible=False, 

106 requires_approval=True, description="重置系统", 

107 ), 

108 "modify_permissions": ToolRiskRating( 

109 level=ToolRiskLevel.CRITICAL, reversible=True, 

110 requires_approval=True, description="修改系统权限", 

111 ), 

112} 

113 

114 

115def get_risk_preset(tool_name: str) -> Optional[ToolRiskRating]: 

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

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

118 

119 

120def infer_risk_level( 

121 tool_name: str, 

122 tool_description: str = "", 

123 arguments: Optional[dict] = None, 

124) -> ToolRiskRating: 

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

126 

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

128 """ 

129 preset = get_risk_preset(tool_name) 

130 if preset: 

131 return preset 

132 

133 name_lower = tool_name.lower() 

134 desc_lower = tool_description.lower() 

135 

136 # Critical keywords 

137 critical_kw = ["format", "reset", "payment", "root", "sudo", "admin privilege"] 

138 high_kw = ["delete", "remove", "drop", "purge", "truncate", "send", "publish", "notify"] 

139 medium_kw = ["write", "create", "update", "modify", "install", "deploy", "execute", "run"] 

140 

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

142 

143 if any(kw in all_text for kw in critical_kw): 

144 return ToolRiskRating( 

145 level=ToolRiskLevel.CRITICAL, reversible=False, 

146 requires_approval=True, description=f"推断为 CRITICAL: {tool_name}", 

147 ) 

148 if any(kw in all_text for kw in high_kw): 

149 return ToolRiskRating( 

150 level=ToolRiskLevel.HIGH, reversible=False, 

151 requires_approval=True, description=f"推断为 HIGH: {tool_name}", 

152 ) 

153 if any(kw in all_text for kw in medium_kw): 

154 return ToolRiskRating( 

155 level=ToolRiskLevel.MEDIUM, reversible=True, 

156 description=f"推断为 MEDIUM: {tool_name}", 

157 ) 

158 return ToolRiskRating( 

159 level=ToolRiskLevel.LOW, reversible=True, 

160 description=f"推断为 LOW: {tool_name}", 

161 )