当前位置: 首页 > news >正文

Tool Permission 与 Sandbox 安全流水线

1. 为什么工具系统是 Agent 最危险的部分

一个只会聊天的模型,最多是说错话。一个能调用工具的 Agent,可能会删文件、跑命令、发消息、调用外部 API、读取密钥、修改代码。

所以生产级 Agent 的安全边界,不在 prompt,而在工具系统。

可以用一句话概括:

模型负责提出动作,Harness 负责判断能不能做。

Hermes 的源码非常适合说明这件事。它不是把工具写成一堆散函数,而是有完整的工具注册、工具集过滤、危险命令审批、沙箱执行、MCP 工具接入和凭证隔离机制。

2. 第一层:ToolRegistry 让工具先变成“受管对象”

Hermes 的工具注册中心在tools/registry.py。文件开头就说明了设计:

"""Central registry for all hermes-agent tools. Each tool file calls registry.register() at module level to declare its schema, handler, toolset membership, and availability check. """

核心注册结构可以简化为:

classToolEntry:def__init__(self,name,toolset,schema,handler,check_fn,requires_env,is_async,description,emoji,max_result_size_chars=None):self.name=name self.toolset=toolset self.schema=schema self.handler=handler self.check_fn=check_fn self.requires_env=requires_env self.is_async=is_async self.description=description self.emoji=emoji self.max_result_size_chars=max_result_size_chars

这说明工具不是普通函数,而是带元数据的受管对象。

一个工具至少要说清楚:

  • 它叫什么;
  • 属于哪个 toolset;
  • 参数 schema 是什么;
  • 由哪个 handler 执行;
  • 需要哪些环境变量;
  • 是否可用;
  • 最大输出多大。

对新手来说,可以把ToolRegistry理解成“工具仓库管理员”。模型不能随便拿工具,必须先通过这个仓库。

3. 第二层:工具自动发现

Hermes 不是在model_tools.py里手写一个巨大工具列表,而是扫描tools/*.py,找模块顶层是否调用了registry.register(...)

def_module_registers_tools(module_path:Path)->bool:source=module_path.read_text(encoding="utf-8")tree=ast.parse(source,filename=str(module_path))returnany(_is_registry_register_call(stmt)forstmtintree.body)

然后导入这些模块:

defdiscover_builtin_tools(tools_dir=None):module_names=[f"tools.{path.stem}"forpathinsorted(tools_path.glob("*.py"))ifpath.namenotin{"__init__.py","registry.py","mcp_tool.py"}and_module_registers_tools(path)]formod_nameinmodule_names:importlib.import_module(mod_name)

这个设计有两个好处。

第一,新增工具不用改中心文件,只要在工具文件里注册。

第二,只有真正声明了注册行为的文件才会被加载,减少误导入。

4. 第三层:toolset 控制模型能看到哪些工具

工具注册后,并不代表模型一定能用。toolsets.py把工具按场景分组:

TOOLSETS={"web":{"description":"Web research and content extraction tools","tools":["web_search","web_extract"],"includes":[]},"terminal":{"description":"Terminal/command execution and process management tools","tools":["terminal","process"],"includes":[]},"file":{"description":"File manipulation tools","tools":["read_file","write_file","patch","search_files"],"includes":[]},}

model_tools.py会根据 enabled / disabled toolsets 计算最终工具集合:

ifenabled_toolsetsisnotNone:fortoolset_nameinenabled_toolsets:resolved=resolve_toolset(toolset_name)tools_to_include.update(resolved)filtered_tools=registry.get_definitions(tools_to_include,quiet=quiet_mode)

通俗解释:工具不是全员上桌,而是按场景发通行证。

如果你做客服 Agent,可能只给知识库和工单工具;如果做代码 Agent,才给文件、终端、测试工具。

5. 第四层:工具 schema 会动态修正

Hermes 里一个很专业的细节是:工具 schema 不是完全静态的。

例如execute_code工具可能允许在沙箱里调用部分工具,但这必须根据当前会话真实可用工具来决定:

if"execute_code"inavailable_tool_names:sandbox_enabled=SANDBOX_ALLOWED_TOOLS&available_tool_names dynamic_schema=build_execute_code_schema(sandbox_enabled,mode=_get_execution_mode())

为什么要这么做?

因为如果 schema 里写着“你可以用 web_search”,但实际 web_search 没有配置 API key,模型就容易幻觉调用不可用工具。Hermes 通过动态 schema 降低这种错配。

这就是生产系统和 demo 的差别:demo 只求跑通,生产系统要减少模型误会。

6. 第五层:危险命令审批

Hermes 的危险命令审批在tools/approval.py。文件开头写得很清楚:

"""Dangerous command approval -- detection, prompting, and per-session state. This module is the single source of truth for the dangerous command system: - Pattern detection - Per-session approval state - Smart approval via auxiliary LLM - Permanent allowlist persistence """

核心流程可以理解成:

defcheck_dangerous_command(command,env_type,approval_callback=None):is_dangerous,pattern_key,description=detect_dangerous_command(command)ifnotis_dangerous:return{"approved":True}choice=prompt_dangerous_approval(command,description)ifchoice=="deny":return{"approved":False,"message":"BLOCKED: User denied this potentially dangerous command"}return{"approved":True}

真实源码比这个复杂,支持:

  • manual:人工审批;
  • smart:辅助 LLM 判断低风险命令是否可自动批准;
  • off:关闭审批;
  • yolo:当前 session 放行;
  • once / session / always / deny多种用户选择。

新手要记住:危险命令审批不是“模型自己判断危险不危险”,而是代码里的安全模块判断。

7. 第六层:会话级审批隔离

Hermes 使用contextvars绑定当前审批会话:

_approval_session_key=contextvars.ContextVar("approval_session_key",default="",)defset_current_session_key(session_key:str):return_approval_session_key.set(session_keyor"")

为什么重要?

因为 Hermes 可以跑 CLI、gateway、多平台消息、子 Agent。多个会话可能同时等待审批。如果审批状态用全局变量乱放,就可能出现 A 会话批准了命令,B 会话误以为自己也被批准。

contextvars的作用就是让并发上下文里的“当前会话”不串线。

8. 第七层:终端执行有沙箱后端

Hermes 的tools/terminal_tool.py文件开头说明:

Supports local execution, containerized backends, and Modal cloud sandboxes.

这说明终端工具不只是subprocess.run()。Hermes 会根据配置选择执行环境,管理 sandbox 生命周期,处理后台进程、工作目录、清理逻辑等。

生产场景里,终端工具最危险。Hermes 的做法是把它包成受控服务:

模型提出 command -> approval.py 判断是否危险 -> terminal_tool 选择执行环境 -> sandbox 执行 -> 输出清洗和截断 -> 返回 tool result

如果用普通人的话说:模型不是直接摸服务器,而是隔着一个带门禁的操作台。

9. 第八层:凭证不能随便进沙箱

Hermes 里有tools/credential_files.pytools/env_passthrough.py

这两个模块非常现实。很多安全事故不是因为命令本身有多危险,而是因为命令拿到了不该拿的凭证。

例如:

  • 沙箱需要某个 API key 才能运行测试;
  • 远程环境需要少量 credential file;
  • 但不能把整个 home 目录挂进去;
  • 也不能把所有环境变量透传进去。

所以 Hermes 用专门模块管理“哪些凭证可以进沙箱”。这比简单说“我们有沙箱”更专业。

10. 第九层:MCP 工具也进入统一注册

Hermes 的tools/mcp_tool.py很大,说明 MCP 不是随便拼接进去的。

源码里能看到 MCP 相关能力:

  • 连接 MCP server;
  • OAuth 恢复;
  • HTTP / stdio transport;
  • 工具发现;
  • 工具名冲突保护;
  • 动态注册和注销;
  • 断线重连;
  • 关闭时清理子进程。

MCP server 提供的工具最终也会注册进 Hermes 的 registry。也就是说,外部工具进入系统后,也要经过 Hermes 的工具生命周期管理。

11. 给新手的完整心智模型

可以把 Hermes 工具系统想成一栋工厂:

  • ToolRegistry是工具仓库;
  • toolsets.py是工种权限表;
  • model_tools.py是调度员;
  • approval.py是安检;
  • terminal_tool.py是危险设备操作间;
  • sandbox 是隔离车间;
  • MCP 是外部供应商接入通道;
  • credential/env 管理是钥匙柜。

模型不是老板,不是它说用什么就用什么。模型只是提出需求,Harness 才决定能不能执行。

12. 结论

结合 Hermes 源码看,工具系统的专业性体现在:

  • 工具统一注册;
  • 工具按 toolset 暴露;
  • schema 根据可用能力动态修正;
  • Agent-level 工具由主循环截获;
  • 高风险命令进入审批;
  • 沙箱执行隔离副作用;
  • 凭证透传受控;
  • MCP 工具纳入统一生命周期。

所以,Tool Permission 与 Sandbox 不是可选增强,而是 Agent 从玩具走向生产的底线工程。

参考资料

  • Hermes 源码:tools/registry.py
  • Hermes 源码:model_tools.py
  • Hermes 源码:toolsets.py
  • Hermes 源码:tools/approval.py
  • Hermes 源码:tools/terminal_tool.py
  • Hermes 源码:tools/code_execution_tool.py
  • Hermes 源码:tools/mcp_tool.py
  • MCP Security Best Practices: https://modelcontextprotocol.io/docs/tutorials/security/security_best_practices
  • OWASP Top 10 for LLM Applications: https://owasp.org/www-project-top-10-for-large-language-model-applications/
http://www.jsqmd.com/news/849939/

相关文章:

  • 一个8B小模型从53%到99%?这护栏也太离谱了
  • 为什么你的5年经验简历不值钱?一招升维对标8年薪资
  • 市场主流零代码平台选型榜单
  • 使用svg图标
  • 别再只调参了!用CLIP+医学影像做Zero-shot分类,5分钟搞定你的第一个Demo
  • 期货合约乘数与最小变动价位:从 Quote 读规格做下单预算
  • Hermes Agent 反思阶段的 3 层反馈闭环:Skill 自主优化实测提升 37% 生成准确率
  • 校园外卖市场还值得做吗?一文看懂校园外卖系统源码开发搭建
  • yolo26 pt转onnx
  • Maven高级
  • 一种基于TSPC-DFF的高速低功耗Fractional PLL实现
  • 养老护理员网课选哪家好?3大平台网课深度测评!
  • 2026针对压力少白头的森优时铁锌维推荐 科学内调改善毛囊营养
  • DDoS防护架构解析与实战经验
  • 小程序源码
  • Figma 设计稿直转可运行代码:Vibe Coding 联动 Cursor 的 4 步自动化工作流
  • 深入解析Token(原生代币):从原理到未来,开发者必读指南
  • 基于MATLAB的GPS捕获、跟踪与PVT计算实现
  • 人机协同新范式:AI数字员工Agent如何破解企业系统孤岛
  • AI 钻牛角尖怎么办?Vibe Coding 中人工介入的 4 个关键信号
  • 死信队列与补偿作业
  • 老项目重构提效实录:Vibe Coding 集成 Claude Code 与 Codex 的 4 步迁移工作流
  • 盲人出行辅助系统原型
  • 12000 Star 的 MonkeyCode,我们把它部署到了内网
  • 深入Linux Input子系统:从全志T113-S3的按键事件,看懂/dev/input/eventX
  • ToastFish:终极Windows通知栏摸鱼背单词神器,上班族必备的隐蔽学习工具
  • 2026年AI搜索优化服务商TOP10榜单发布:技术原生派领跑,垂直专精派各显神通
  • 告别降级:PyTorch高版本下Mask R-CNN/Faster R-CNN THC头文件与内存分配兼容性修复实战
  • 稳定币深度解析:从技术内核到生态未来
  • Claude Code Hooks 触发时机全解析:PreToolUse、PostToolUse、Stop 3 类事件的 5 个执行边界