主题
权限
使用声明式权限规则为 Deep Agents 控制文件系统访问
使用声明式权限规则控制智能体可以读取或写入哪些文件和目录。将规则列表传给 permissions=,智能体内置的文件系统工具就会遵守这些规则。
NOTE
权限需要 deepagents>=0.5.2。
权限仅适用于内置文件系统工具(ls、read_file、glob、grep、write_file、edit_file、delete)。访问文件系统的自定义工具和 MCP 工具不在覆盖范围内。权限也不适用于 沙箱后端,后者支持通过 execute 工具执行任意命令。
TIP
当你需要针对内置文件系统工具的 基于路径的允许/拒绝规则 时,请使用 permissions。当你需要自定义验证逻辑(速率限制、审计日志记录、内容检查)或需要控制自定义工具时,请使用 后端策略钩子。
基本用法
将 FilesystemPermission 规则列表传给 create_deep_agent。规则按声明顺序进行评估。第一个匹配的规则获胜。如果没有规则匹配,则允许该操作。
python
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",
),
],
)1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
规则结构
每个 FilesystemPermission 有三个字段:
| 字段 | 类型 | 描述 |
|---|---|---|
operations | list["read" | "write"] | 此规则适用的操作。"read" 涵盖 ls、read_file、glob、grep。"write" 涵盖 write_file、edit_file、delete。 |
paths | list[str] | 用于匹配文件路径的 Glob 模式(例如 ["/workspace/**"])。支持 ** 递归匹配和 {a,b} 备选。 |
mode | "allow" | "deny" | "interrupt" | 是否允许、拒绝或在匹配的操作上暂停以等待人工批准。默认为 "allow"。参见 暂停以等待人工批准。 |
规则采用「首个匹配者获胜」的评估方式:其 operations 和 paths 与当前调用匹配的第一条规则决定结果。如果没有规则匹配,则调用被 允许(宽松默认)。
暂停以等待人工批准
NOTE
"interrupt" 模式需要 deepagents>=0.6.8。
设置 mode="interrupt" 可暂停以等待人工批准,而不是直接允许或拒绝匹配的操作。当智能体对匹配中断模式规则的路径调用内置写入工具(write_file、edit_file、delete)时,create_deep_agent 会引发人在回路中断,而不是运行该工具,审阅者可以批准、编辑或拒绝该调用。
python
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(),
)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
中断模式规则会自动接入智能体的人在回路中间件,并与你传入的任何 interrupt_on 合并,因此你可以像处理工具调用中断一样处理和恢复它们。有关恢复流程,请参阅 人在回路。
NOTE
删除目录是全有或全无的:delete 会检查目标以及每个后代路径上的 write 权限,只要其中任何一个被拒绝,就会拒绝整个操作,而不是移除树的一部分。delete 对已存在的空目录也会应用同样保守的检查,因为它仍然是一个目录,而不是已确认的叶子目标。
删除普通文件则是精确匹配的情况:delete 会像 write_file 和 edit_file 那样解析目标,采用「首个匹配者获胜」的评估方式,因此较早的、更窄的 allow 规则会胜过较晚的兜底 deny。此精确匹配行为需要 deepagents>=0.7.3。
TIP
请用字面量的前导段来锚定中断模式(例如 /secrets/** 或 /projects/*/secrets/**)。批量工具(ls、glob、grep,以及对目录执行 delete)在其搜索子树可能与规则锚定的前缀重叠时会触发中断,因此像 /**/secrets 这样完全未锚定的模式会保守地过度触发。
示例
隔离到工作区目录
仅允许在 /workspace/ 下读写,并拒绝其他一切:
python
agent = create_deep_agent(
model=model,
backend=backend,
permissions=[
FilesystemPermission(
operations=["read", "write"],
paths=["/workspace/**"],
mode="allow",
),
FilesystemPermission(
operations=["read", "write"],
paths=["/**"],
mode="deny",
),
],
)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
保护特定文件
python
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",
),
],
)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
只读记忆
允许智能体读取记忆文件,但阻止其修改它们。这对于应仅由应用程序代码更新的组织范围策略或共享知识库很有用。有关更多背景信息,请参阅 只读与可写记忆。
python
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",
),
],
)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
拒绝所有访问
阻止所有读写。这是一个限制性的基线,你可以在其之上叠加更具体的 allow 规则:
python
agent = create_deep_agent(
model=model,
backend=backend,
permissions=[
FilesystemPermission(
operations=["read", "write"],
paths=["/**"],
mode="deny",
),
],
)1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
规则排序
由于「首个匹配者获胜」,规则的顺序很重要。请将更具体的规则放在更宽泛的规则之前:
python
# 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",
),
]1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
子智能体权限
子智能体 默认继承父智能体的权限。要给子智能体不同的权限,请在其 spec 中设置 permissions 字段。这会完全 替换 父级的规则。
python
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",
),
],
}
],
)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
组合后端
当使用带有沙箱默认值的 CompositeBackend 时,每个权限路径都必须限定在已知的路由前缀之下。沙箱支持执行任意命令,因此仅靠基于路径的限制无法阻止通过 shell 命令访问文件系统。将权限限定到特定路由的 后端 可以避免这种冲突。
python
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",
),
],
)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
包含任何路由之外路径的权限会引发 NotImplementedError:
python
# 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:
pass1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31