使用 declarative permission rules 控制 agent 可以 read 或 write 哪些 files 和 directories。将 rules list 传给 permissions= 后,agent 的 built-in filesystem tools 会遵守这些规则。
Permissions 需要 deepagents>=0.5.2
Permissions 只适用于 built-in filesystem tools(lsread_fileglobgrepwrite_fileedit_file)。访问 filesystem 的 custom tools 和 MCP tools 不在覆盖范围内。Permissions 也不适用于 sandbox backends,后者通过 execute tool 支持任意 command execution。
当你需要对 built-in filesystem tools 设置 path-based allow/deny rules 时,请使用 permissions。当你需要 custom validation logic(rate limiting、audit logging、content inspection),或需要控制 custom tools 时,请使用 backend policy hooks

Basic usage

FilesystemPermission rules list 传给 create_deep_agent。Rules 按 declaration order 求值。第一条匹配的 rule 生效。如果没有 rule 匹配,则允许 operation。
from deepagents import FilesystemPermission, create_deep_agent


# Read-only agent: deny all writes
agent = create_deep_agent(
    model=model,
    backend=backend,
    permissions=[
        FilesystemPermission(
            operations=["write"],
            paths=["/**"],
            mode="deny",
        ),
    ],
)

Rule structure

每个 FilesystemPermission 都有三个 fields:
FieldTypeDescription
operationslist["read" | "write"]该 rule 适用的 operations。"read" 覆盖 lsread_fileglobgrep"write" 覆盖 write_fileedit_file
pathslist[str]用于匹配 file paths 的 glob patterns(例如 ["/workspace/**"])。支持 ** recursive matching 和 {a,b} alternation。
mode"allow" | "deny" | "interrupt"匹配 operations 时是允许、拒绝,还是暂停等待 human approval。默认值为 "allow"。请参阅 Pause for human approval
Rules 使用 first-match-wins evaluation:第一条 operationspaths 与当前 call 匹配的 rule 会决定结果。如果没有 rule 匹配,则 call 会被 allowed(permissive default)。

Pause for human approval

"interrupt" mode 需要 deepagents>=0.6.8
设置 mode="interrupt",即可在匹配 operation 时暂停等待 human approval,而不是直接允许或拒绝。当 agent 在匹配 interrupt-mode rule 的 path 上调用 built-in write tool(write_fileedit_file)时,create_deep_agent 会发出 human-in-the-loop interrupt,而不是运行 tool,reviewer 可以 approve、edit 或 reject 该 call。
from deepagents import FilesystemPermission, create_deep_agent
from langgraph.checkpoint.memory import InMemorySaver


agent = create_deep_agent(
    model=model,
    permissions=[
        # Pause for approval before writing anything under /secrets.
        FilesystemPermission(
            operations=["write"],
            paths=["/secrets/**"],
            mode="interrupt",
        ),
    ],
    # Interrupt mode requires a checkpointer to pause and resume.
    checkpointer=InMemorySaver(),
)
Interrupt-mode rules 会自动连接到 agent 的 human-in-the-loop middleware,并与你传入的任何 interrupt_on 合并,因此你可以用与 tool-call interrupts 相同的方式处理和 resume。Resume flow 请参阅 Human-in-the-loop
使用 literal leading segment 锚定 interrupt patterns(例如 /secrets/**/projects/*/secrets/**)。Bulk tools(lsglobgrep)会在其 search subtree 可能与 rule 的 anchored prefix 重叠时触发 interrupt,因此像 /**/secrets 这样完全 unanchored 的 pattern 会保守地过度触发。

Examples

Isolate to a workspace directory

只允许在 /workspace/ 下 read 和 write,并拒绝其他所有内容:
agent = create_deep_agent(
    model=model,
    backend=backend,
    permissions=[
        FilesystemPermission(
            operations=["read", "write"],
            paths=["/workspace/**"],
            mode="allow",
        ),
        FilesystemPermission(
            operations=["read", "write"],
            paths=["/**"],
            mode="deny",
        ),
    ],
)

Protect specific files

agent = create_deep_agent(
    model=model,
    backend=backend,
    permissions=[
        FilesystemPermission(
            operations=["read", "write"],
            paths=["/workspace/.env", "/workspace/examples/**"],
            mode="deny",
        ),
        FilesystemPermission(
            operations=["read", "write"],
            paths=["/workspace/**"],
            mode="allow",
        ),
        FilesystemPermission(
            operations=["read", "write"],
            paths=["/**"],
            mode="deny",
        ),
    ],
)

Read-only memory

允许 agent read memory files,但阻止其修改这些 files。这适用于 organization-wide policies 或只应由 application code 更新的 shared knowledge bases。更多 context 请参阅 read-only vs writable memory
from deepagents.backends import CompositeBackend, StateBackend, StoreBackend

agent = create_deep_agent(
    model=model,
    backend=CompositeBackend(
        default=StateBackend(),
        routes={
            "/memories/": StoreBackend(
                namespace=lambda rt: (rt.server_info.user.identity,),
            ),
            "/policies/": StoreBackend(
                namespace=lambda rt: (rt.context.org_id,),
            ),
        },
    ),
    permissions=[
        FilesystemPermission(
            operations=["write"],
            paths=["/memories/**", "/policies/**"],
            mode="deny",
        ),
    ],
)

Deny all access

阻止所有 reads 和 writes。这是一个 restrictive baseline,你可以在其上叠加更具体的 allow rules:
agent = create_deep_agent(
    model=model,
    backend=backend,
    permissions=[
        FilesystemPermission(
            operations=["read", "write"],
            paths=["/**"],
            mode="deny",
        ),
    ],
)

Rule ordering

由于 first-match-wins,rule order 很重要。请将更 specific 的 rules 放在更 broad 的 rules 前:
# Correct: deny .env, allow workspace, deny everything else
correct_permissions = [
    FilesystemPermission(
        operations=["read", "write"],
        paths=["/workspace/.env"],
        mode="deny",
    ),
    FilesystemPermission(
        operations=["read", "write"],
        paths=["/workspace/**"],
        mode="allow",
    ),
    FilesystemPermission(
        operations=["read", "write"],
        paths=["/**"],
        mode="deny",
    ),
]

# Bug: /workspace/** matches .env first, so the deny never triggers
incorrect_permissions = [
    FilesystemPermission(
        operations=["read", "write"],
        paths=["/workspace/**"],
        mode="allow",
    ),
    FilesystemPermission(
        operations=["read", "write"],
        paths=["/workspace/.env"],
        mode="deny",  # never reached
    ),
    FilesystemPermission(
        operations=["read", "write"],
        paths=["/**"],
        mode="deny",
    ),
]

Subagent permissions

Subagents 默认继承 parent agent 的 permissions。若要为 subagent 提供不同 permissions,请在其 spec 中设置 permissions field。这会完全 replace parent 的 rules。
agent = create_deep_agent(
    model=model,
    backend=backend,
    permissions=[
        FilesystemPermission(
            operations=["read", "write"],
            paths=["/workspace/**"],
            mode="allow",
        ),
        FilesystemPermission(
            operations=["read", "write"],
            paths=["/**"],
            mode="deny",
        ),
    ],
    subagents=[
        {
            "name": "auditor",
            "description": "Read-only code reviewer",
            "system_prompt": "Review the code for issues.",
            "permissions": [
                FilesystemPermission(
                    operations=["write"],
                    paths=["/**"],
                    mode="deny",
                ),
                FilesystemPermission(
                    operations=["read"],
                    paths=["/workspace/**"],
                    mode="allow",
                ),
                FilesystemPermission(
                    operations=["read"],
                    paths=["/**"],
                    mode="deny",
                ),
            ],
        }
    ],
)

Composite backends

使用带 sandbox default 的 CompositeBackend 时,每个 permission path 都必须限定在已知 route prefix 下。Sandboxes 支持任意 command execution,因此仅靠 path-based restrictions 无法阻止通过 shell commands 访问 filesystem。将 permissions 限定到 route-specific backends 可以避免这一冲突。
from deepagents.backends import CompositeBackend


composite = CompositeBackend(
    default=sandbox,
    routes={"/memories/": memories_backend},
)

# Works: permissions are scoped to the /memories/ route
agent = create_deep_agent(
    model=model,
    backend=composite,
    permissions=[
        FilesystemPermission(
            operations=["write"],
            paths=["/memories/**"],
            mode="deny",
        ),
    ],
)
包含任何 route 外 paths 的 permissions 会抛出 NotImplementedError
# Raises NotImplementedError: /workspace/** hits the sandbox default
try:
    create_deep_agent(
        model=model,
        backend=composite,
        permissions=[
            FilesystemPermission(
                operations=["write"],
                paths=["/workspace/**"],
                mode="deny",
            ),
        ],
    )
except NotImplementedError:
    pass

# Also raises: /** covers both routes and the default
try:
    create_deep_agent(
        model=model,
        backend=composite,
        permissions=[
            FilesystemPermission(
                operations=["read"],
                paths=["/**"],
                mode="deny",
            ),
        ],
    )
except NotImplementedError:
    pass