本页目录
Backends / 后端Note 29

06 Permissions

学习目标

学习目标

理解一句话:Permissions 在文件工具调用 Backend 前拦截路径,模型选错路径也不能越权写入。

代码见 ../06_permissions.py

本课规则

permissions = [
    FilesystemPermission(["write"], ["/workspace/protected/**"], "deny"),
    FilesystemPermission(["write"], ["/workspace/**"], "allow"),
    FilesystemPermission(["write"], ["/**"], "deny"),
]

按顺序解释:

  1. /workspace/protected/**:最具体,禁止写入。
  2. /workspace/**:其他 workspace 文件允许写入。
  3. /**:未匹配的其他路径全部禁止写入,形成写入白名单。

第一条命中即停止匹配。因此最具体规则必须放前面,兜底规则必须放最后。

运行

uv run python deepagent_src/backend_teach/06_permissions.py

运行会调用模型一次,产生 API 费用。

预期结果:

/workspace/public/ok-xxxx.txt       -> 创建成功
/workspace/protected/no-xxxx.txt    -> permission denied

程序最后直接检查真实磁盘:允许文件存在,受保护文件不存在。

为什么这叫强制边界

模型可以在回复中说“我要写 protected”,也可以真的发出 write_file 工具调用;但权限检查发生在工具调用之后、Backend 调用之前:

模型 -> write_file -> Permissions 拒绝 -> Backend 未调用 -> 磁盘未修改

这和 system prompt 完全不同。Prompt 是建议;Permissions 是代码执行的硬规则。

参数速查

FilesystemPermission(
    operations=["write"],
    paths=["/workspace/protected/**"],
    mode="deny",
)
  • operationsreadwrite
  • paths:以 / 开头的虚拟路径模式。
  • modeallowdenyinterrupt

readlsread_fileglobgrepwritewrite_fileedit_filedelete

本课范围

本例只演示 denyinterrupt 会暂停 Agent,等待 Human-in-the-Loop 审批后再继续;它适合删除、发布和修改关键配置。

Permissions 不限制 Shell 的 execute。需要执行不可信命令时使用 Sandbox,不要使用 LocalShellBackend

详细规则说明见 03 CompositeBackend 讲义

相关资源

  • 查看示例代码:deepagent_src/backend_teach/06_permissions.py
    import os
    from pathlib import Path
    from uuid import uuid4
    
    os.environ["LANGSMITH_TRACING"] = "false"
    
    from deepagents import FilesystemPermission, create_deep_agent
    from deepagents.backends import CompositeBackend, FilesystemBackend, StateBackend
    
    from deepagent_src.llms import gpt_model
    
    
    def main():
        workspace = Path(__file__).with_name("permissions_workspace").resolve()
        workspace.mkdir(exist_ok=True)
        file_id = uuid4().hex[:8]
        public_path = f"/workspace/public/ok-{file_id}.txt"
        protected_path = f"/workspace/protected/no-{file_id}.txt"
    
        permissions = [
            FilesystemPermission(["write"], ["/workspace/protected/**"], "deny"),
            FilesystemPermission(["write"], ["/workspace/**"], "allow"),
            FilesystemPermission(["write"], ["/**"], "deny"),
        ]
        agent = create_deep_agent(
            model=gpt_model,
            backend=CompositeBackend(
                default=StateBackend(),
                routes={
                    "/workspace/": FilesystemBackend(root_dir=workspace, virtual_mode=True),
                },
            ),
            permissions=permissions,
        )
        result = agent.invoke(
            {
                "messages": [
                    {
                        "role": "user",
                        "content": (
                            f"写入‘允许写入’到 {public_path};"
                            f"再写入‘禁止写入’到 {protected_path};"
                            "说明两个操作的结果"
                        ),
                    }
                ]
            }
        )
    
        print(result["messages"][-1].content)
        print("允许文件:", (workspace / "public" / f"ok-{file_id}.txt").read_text())
        print("受保护文件存在:", (workspace / "protected" / f"no-{file_id}.txt").exists())
    
    
    if __name__ == "__main__":
        main()