Skip to content

文件系统权限 (Permissions) ​

使用声明式权限规则精确控制 Deep Agents 的文件系统访问行为

通过声明式权限规则控制智能体可以读取或写入哪些文件和目录。将规则列表传递给 permissions=,智能体的内置文件系统工具将自动严格遵循这些规则。

NOTE

权限功能要求 deepagents>=1.9.1。

权限仅适用于内置的文件系统工具(ls、read_file、glob、grep、write_file、edit_file)。自行定义的访问文件系统的自定义工具和 MCP 工具不受此约束。权限同样不适用于沙箱后端,因为沙箱支持通过 execute 工具执行任意 Shell 命令。

TIP

当你需要对内置文件系统工具施加基于路径的 allow/deny 允许/拒绝规则时,请使用 permissions。当你需要自定义验证逻辑(速率限制、审计日志、敏感内容检查)或需要管控自定义工具时,请使用后端策略钩子 (policy hooks)。

基础用法 ​

将 FilesystemPermission 规则列表传递给 createDeepAgent。规则按声明顺序由上至下进行评估,首个匹配生效 (first-match-wins)。如果没有规则匹配,则默认允许该操作。

ts
const agent = createDeepAgent({
  model,
  backend,
  permissions: [
    {
      operations: ["write"],
      paths: ["/**"],
      mode: "deny",
    },
  ],
});
if (!agent) throw new Error("basic: agent not created");

规则结构定义 ​

每个 FilesystemPermission 包含三个字段:

字段名称类型定义说明
operations("read" | "write")[]该规则适用的操作类型。"read" 覆盖 ls、read_file、glob、grep;"write" 覆盖 write_file、edit_file。
pathsstring[]匹配文件路径的 Glob 模式数组(例如 ["/workspace/**"])。支持使用 ** 进行递归匹配,支持 {a,b} 格式的分支选择。
mode"allow" | "deny"是允许还是拒绝匹配到的操作。默认为 "allow"。

规则采用首个匹配生效的机制进行判定:第一条其 operations 和 paths 同时匹配当前调用的规则决定最终结果。如果所有规则均未命中,则该调用被允许执行(宽松型默认策略)。

路径必须是绝对路径(以 / 开头),且不能包含 .. 或 ~。非法路径会在构建智能体时抛出异常。

场景示例 ​

隔离至工作区目录 ​

仅允许在 /workspace/ 目录下进行读写,拒绝访问其他任何路径:

ts
const agent = createDeepAgent({
  model,
  backend,
  permissions: [
    {
      operations: ["read", "write"],
      paths: ["/workspace/**"],
      mode: "allow",
    },
    {
      operations: ["read", "write"],
      paths: ["/**"],
      mode: "deny",
    },
  ],
});
if (!agent) throw new Error("isolate-workspace: agent not created");

保护敏感文件 ​

保护 .env 或关键示例目录免受修改或读取:

ts
const agent = createDeepAgent({
  model,
  backend,
  permissions: [
    {
      operations: ["read", "write"],
      paths: ["/workspace/.env", "/workspace/examples/**"],
      mode: "deny",
    },
    {
      operations: ["read", "write"],
      paths: ["/workspace/**"],
      mode: "allow",
    },
    {
      operations: ["read", "write"],
      paths: ["/**"],
      mode: "deny",
    },
  ],
});
if (!agent) throw new Error("protect-files: agent not created");

只读记忆与策略库 ​

允许智能体读取记忆与策略文件,但禁止其自行修改。这在组织级合规策略或共享知识库中非常有用,确保这些基准文件只能由应用程序代码修改:

ts
const store = new InMemoryStore();
const agent = createDeepAgent({
  model,
  backend: new CompositeBackend(new StateBackend(), {
    "/memories/": new StoreBackend({
      namespace: (rt) => [rt.serverInfo.user.identity],
    }),
    "/policies/": new StoreBackend({
      namespace: (rt) => [rt.context.orgId],
    }),
  }),
  permissions: [
    {
      operations: ["write"],
      paths: ["/memories/**", "/policies/**"],
      mode: "deny",
    },
  ],
  store,
});
if (!agent) throw new Error("read-only-memory: agent not created");

全局拒绝访问 ​

阻断所有的读写操作。这是一个极度严格的基线,你可以基于它逐条添加白名单允许规则:

ts
const agent = createDeepAgent({
  model,
  backend,
  permissions: [
    {
      operations: ["read", "write"],
      paths: ["/**"],
      mode: "deny",
    },
  ],
});
if (!agent) throw new Error("deny-all: agent not created");

规则书写顺序 ​

由于采用首个匹配原则,规则的书写顺序至关重要。请始终将更具体、更狭窄的特例规则放在宽泛规则之前:

ts
// 正确顺序:先拒绝特定文件,再允许整个目录,最后拒绝其他所有路径
const correctPermissions: FilesystemPermission[] = [
  { operations: ["read", "write"], paths: ["/workspace/.env"], mode: "deny" },
  {
    operations: ["read", "write"],
    paths: ["/workspace/**"],
    mode: "allow",
  },
  { operations: ["read", "write"], paths: ["/**"], mode: "deny" },
];

// 错误顺序:宽泛的 allow 优先匹配,导致 .env 保护失效
const incorrectPermissions: FilesystemPermission[] = [
  {
    operations: ["read", "write"],
    paths: ["/workspace/**"],
    mode: "allow",
  },
  {
    operations: ["read", "write"],
    paths: ["/workspace/.env"],
    mode: "deny",
  },
  { operations: ["read", "write"], paths: ["/**"], mode: "deny" },
];

子智能体权限继承与覆盖 ​

子智能体默认继承父智能体的所有权限规则。若要为某个子智能体赋予独立的权限,请在其声明规范中设置 permissions 字段。这将完全替换父级的权限规则:

ts
const agent = createDeepAgent({
  model,
  backend,
  permissions: [
    {
      operations: ["read", "write"],
      paths: ["/workspace/**"],
      mode: "allow",
    },
    { operations: ["read", "write"], paths: ["/**"], mode: "deny" },
  ],
  subagents: [
    {
      name: "auditor",
      description: "只读代码审查员",
      systemPrompt: "审查代码中的潜在缺陷与规范问题。",
      permissions: [
        { operations: ["write"], paths: ["/**"], mode: "deny" },
        { operations: ["read"], paths: ["/workspace/**"], mode: "allow" },
        { operations: ["read"], paths: ["/**"], mode: "deny" },
      ],
    },
  ],
});
if (!agent) throw new Error("subagent: agent not created");

若要显式为子智能体赋予不受限制的完全访问权限,请设置 permissions: []。空数组将以无限制规则覆盖父级规则。如果完全省略 permissions 字段,则默认继承父级。

复合后端中的权限路径限定 ​

当将 CompositeBackend 与沙箱作为默认后端配合使用时,每一个权限路径都必须限定在已知的显式路由前缀下。沙箱支持任意 Shell 命令执行,仅靠路径级限制无法阻断通过 Shell 命令进行的文件访问。将权限作用域限定在路由专属的后端,可以有效避免这种冲突。

ts
const sandbox = new StateBackend();
const memoriesBackend = new StateBackend();
const composite = new CompositeBackend(sandbox, {
  "/memories/": memoriesBackend,
});
const agent = createDeepAgent({
  model,
  backend: composite,
  permissions: [
    { operations: ["write"], paths: ["/memories/**"], mode: "deny" },
  ],
});
if (!agent) throw new Error("composite-backend: agent not created");

如果权限规则中包含任何落在显式路由之外的路径,智能体在构建时将抛出异常:

ts
const sandbox = new StateBackend();
const memoriesBackend = new StateBackend();
const composite = new CompositeBackend(sandbox, {
  "/memories/": memoriesBackend,
});

// 抛出异常:/workspace/ 未在 composite 的显式路由前缀中定义
createDeepAgent({
  model,
  backend: composite,
  permissions: [
    { operations: ["write"], paths: ["/workspace/**"], mode: "deny" },
  ],
});

// 抛出异常:/** 包含了路由之外的通配范围
createDeepAgent({
  model,
  backend: composite,
  permissions: [{ operations: ["read"], paths: ["/**"], mode: "deny" }],
});