[python] AST语法树来加速大量库文件和注册的加载以及审查

Hermes Agent 这套工程中,利用 Python 的 ast(Abstract Syntax Tree,抽象语法树)模块,最根本的目的有三个:动态插件/工具注册、静态代码安全审计、以及毫秒级轻量语法自检

在以下三种核心业务场景中,工程会调用 ast 进行处理:


1. 动态工具自动注册 ------ ast.parse(用于启动加速)

tools/registry.py 文件中,工程通过 ast 来静态扫描并定位各个插件模块中的工具注册(registry.register(...))调用。

  • 为什么要用 ast 如果直接用 Python 的 import 去加载所有 Python 工具文件(目前有约 70 多个工具文件),会因为导入大量第三方重型依赖(比如 playwrightspotifyfeishu 等库)而导致程序启动变得非常缓慢。
  • 如何使用: 系统通过 ast.parse() 生成语法树,利用 ast.NodeVisitor 寻找特定的 registry.register 节点。通过这种不实际执行(Import)代码的代码分析,仅仅提取工具的 Schema 元数据。
python:45:51:/home/limx/Projects/hermes-agent/tools/registry.py 复制代码
        # 1. 使用 ast.parse 在不 import 运行的情况下,静态解析出所有的工具注册调用
        tree = ast.parse(source, filename=str(module_path))
  • 什么时候用: 系统初始化/ CLI 启动时。 这样做在启动时跳过了沉重的 import 链,实现了极速启动。

2. 技能库安全深度审计(Deep Audit) ------ ast_scan_path

因为该系统支持用户通过 Skills Hub(如 agentskills.io 或第三方 URL)安装社区提交的技能,甚至智能体自己也能编写 scripts/ 辅助脚本,所以存在恶意代码注入的风险。

tools/skills_ast_audit.py 中,工程内置了对技能 Python 代码的静态 AST 扫描。

  • 目的: 作为轻量级静态分析(SAST)工具,检测是否存在危险的动态代码执行、黑客绕过、以及未声明加载行为
  • 如何使用:
    • 通过 ast 检查是否有 importlib.import_module(...) 或非字面量的 __import__ 节点(防止动态加载后门)。
    • 检查是否有动态变量作为属性获取的 getattr(obj, <variable>),防止动态提取私有凭据。
    • 检查是否有对 __dict__ 的非字面量下标访问,阻断混淆代码的运行。
python:33:50:/home/limx/Projects/hermes-agent/tools/skills_ast_audit.py 复制代码
    class V(ast.NodeVisitor):
        def visit_Call(self, node):
            f = node.func
            # 1. 发现 importlib.import_module(...)
            if isinstance(f, ast.Attribute) and f.attr == "import_module":
                findings.append((rel_path, node.lineno, "dynamic_import",
                                 "importlib.import_module() --- loads arbitrary modules at runtime"))
            # 2. 发现 __import__(非字面量字符串)
            elif isinstance(f, ast.Name) and f.id == "__import__":
                if node.args and not isinstance(node.args[0], ast.Constant):
                    findings.append((rel_path, node.lineno, "dynamic_import_computed",
                                     "__import__ with non-literal module name"))
            # 3. 发现 getattr(obj, 非字面量字符串)
            elif isinstance(f, ast.Name) and f.id == "getattr":
                if len(node.args) >= 2 and not isinstance(node.args[1], ast.Constant):
                    findings.append((rel_path, node.lineno, "dynamic_getattr",
                                     "getattr with non-literal attribute name"))
            self.generic_visit(node)
  • 什么时候用: 当运行 hermes skills audit --deep 手动审计,或者智能体自创技能/安装第三方 Hub 技能时。 用于向用户提示"哪些脚本使用了黑魔法,需要人工复核"。

3. 在线编写代码的微秒级语法自检 ------ ast.parse

当智能体在当前会话中写完一段 Python 代码(通过 write_file 写入或 patch 修改)时,它可能无意中留下了缺括号、冒号或者拼写等导致语法不通的问题。

为了保证代码运行安全并快速发现问题,系统在 tools/file_operations.py 中内置了轻量级、无副作用的 Linter。

  • 目的: 在不产生真实子进程、不产生外部执行依赖、不运行可能有风险的脚本的情况下,超高速确认 Python 语法是否合规
  • 如何使用:
    直接对要检测的代码内容运行 ast.parse()
python:466:474:/home/limx/Projects/hermes-agent/tools/file_operations.py 复制代码
    """In-process Python syntax check via ast.parse."""
    import ast as _ast
    try:
        # 如果解析失败,说明有基础语法错误(例如 SyntaxError 等)
        _ast.parse(content)
  • 什么时候用: 智能体每次修改/写入 Python 代码之后、或者准备保存一个技能之前。
    如果捕获了 SyntaxError,系统就能在不运行代码、不生成 linter 进程的前提下,在一毫秒内快速向智能体返回具体的报错行号和错误提示,让智能体当场进行自我修正。

总结

在 Hermes Agent 这种高频、高可信度 AI 执行环境中,ast 是一把**"在不实际运行代码的前提下,精准看穿代码意图、检测代码漏洞与语法缺陷"**的瑞士军刀。其最核心的优势就是:极速、安全、无副作用

相关推荐
我材不敲代码17 小时前
Python 正则表达式实战总结
数据库·python·正则表达式
勇哥的编程江湖17 小时前
25 Elasticsearch Terms Aggregation 实战
java·服务器·前端
半亩码田17 小时前
为什么 AI 框架几乎全选 Python,而不选 C#?从历史、语言设计和生态三个维度拆解
python·ai编程
cui_ruicheng17 小时前
Linux网络编程(八):基于TCP实现CommandServer
linux·服务器·网络·tcp/ip
不吃土豆的马铃薯17 小时前
网络 IO 核心(同步/异步)概念笔记
服务器·c语言·开发语言·网络·c++·笔记
张小凡vip17 小时前
python的__init__.py说明
开发语言·前端·python
小黑随笔17 小时前
Python asyncio 模块学习总结:从“等着”到“切出去干点别的”
开发语言·python·学习
IT策士17 小时前
Django 从 0 到 1 打造完整电商平台:购物车页面增删改查商品数量
后端·python·django
还是鼠鼠17 小时前
AI掘金头条新闻系统 (Toutiao News)-封装通用成功响应格式
数据库·后端·python·fastapi·web