现场是这样的。运维助手接了 update_ticket 工具,测试时模型把筛选条件写成了全表匹配,一次调用改了 200 行工单状态,事后只能从备份里恢复。
中间走过弯路,把「测试环境和生产共用一个数据库账号」当成主因,改完现象没变。
把日志和配置对完,能解释这个现象的基本就这几处。写操作工具没有强制 WHERE 条件;工具参数里可以直接传表名,没有白名单;调用记录只记了工具名,没有记参数。
上来先确认工具实际执行的完整 SQL
python -c "import json;d=json.load(open('tool_calls.jsonl'));print(len(d))"
给写工具加必填条件与行数上限
python -c "print({'require_where':True,'max_rows':50})"
接着把写工具切到独立只写库并限表
python -c "print('db=write_replica; tables=ticket_status')"
剩下的就是用一条模拟调用验证超限会被拒
python tool_try.py --tool update_ticket --dry-run --rows 200
别只看报错消失,验证要多做一步。不带 WHERE 的调用直接返回参数错误,超过 50 行的更新被拒绝,测试调用的审计日志里能看到完整参数。
这里还有个坑。给 Agent 写权限等于给它一把没有保险的钥匙,行数上限、条件必填、独立账号三件事至少做到两件,再谈自动化。拖得越久,排查成本越高,因为现场状态会被后续操作覆盖。
