1"""

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

3

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

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

6"""

7

8 from __future__ import annotations

9

10 from dataclasses import dataclass, field

11 from enum import Enum

12 from typing import Optional

13

14

15 class 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

31 class 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

60 RISK_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

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

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

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

118

119

120 def 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 )