Coverage for agentos/tools/risk.py: 58%
43 statements
« prev ^ index » next coverage.py v7.14.3, created at 2026-07-02 09:59 +0800
« prev ^ index » next coverage.py v7.14.3, created at 2026-07-02 09:59 +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, field
11from enum import Enum
12from typing import Optional
15class ToolRiskLevel(str, Enum):
16 """工具操作风险等级。
18 LOW: 只读查询、信息检索,无副作用
19 MEDIUM: 写入/修改操作,可逆或有审计
20 HIGH: 删除、支付、发消息等不可逆操作
21 CRITICAL: 系统级操作(格式化、重置、权限变更)
22 """
24 LOW = "low"
25 MEDIUM = "medium"
26 HIGH = "high"
27 CRITICAL = "critical"
30@dataclass
31class ToolRiskRating:
32 """工具风险评定元数据。"""
34 level: ToolRiskLevel = ToolRiskLevel.MEDIUM
35 """风险等级。"""
37 reversible: bool = True
38 """操作是否可逆。"""
40 requires_approval: bool = False
41 """是否需要人工审批。"""
43 financial_impact: bool = False
44 """是否有财务影响。"""
46 description: str = ""
47 """风险说明。"""
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 )
58# ── 常见操作的风险预设 ──────────────────────────────────────────────────────
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="天气查询"),
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="安装软件包"),
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 ),
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}
115def get_risk_preset(tool_name: str) -> Optional[ToolRiskRating]:
116 """根据工具名称获取预设风险等级。"""
117 return RISK_PRESETS.get(tool_name.lower())
120def infer_risk_level(
121 tool_name: str,
122 tool_description: str = "",
123 arguments: Optional[dict] = None,
124) -> ToolRiskRating:
125 """根据工具名和描述推断风险等级。
127 优先使用预设,否则通过关键词推断。
128 """
129 preset = get_risk_preset(tool_name)
130 if preset:
131 return preset
133 name_lower = tool_name.lower()
134 desc_lower = tool_description.lower()
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"]
141 all_text = f"{name_lower} {desc_lower}"
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 )