自主性级别
Autonomy is a per-agent setting that lives on a named risk profile — [risk_profiles.<alias>].level. Each agent references one risk profile via agents.<alias>.risk_profile = "<profile-alias>". Three settings; supervised is the default.
[risk_profiles.assistant] # alias = assistant (must match an agents.<alias>.risk_profile)
level = "supervised" # "readonly" | "supervised" | "full"
readonly / supervised / full are the only accepted values; read_only (with an underscore) is rejected at config load. See the canonical Minimal working example for how the profile slots into a complete config.
三个级别
readonly
智能体可以观察,但不能更改任何内容。允许使用的工具是那些没有副作用的工具:
file_read,file_listmemory_searchhttp(仅支持 GET;POST 被阻止)web_searchtime
适用于:面向公众的问答代理、仅分析部署,或在允许其写入任何内容之前,用于验证新工具配置的方式。
supervised(默认)
低风险工具会自动运行。中等风险工具会触发操作员审批提示。高风险工具将被阻止。
风险分类:
| 风险 | 示例 | 行为 |
|---|---|---|
| 低 | file_read、http GET、memory_search、web_search、time | 运行 |
| 中等 | 工作区内的 file_write,具有允许命令的 shell,以及向允许域发送的 http POST | 询问操作员 |
| 高 | shell 中未知/被拒绝的命令、file_write 超出工作区范围、破坏性模式 | 块 |
Approval channel: the approval prompt is delivered through whichever channel initiated the conversation. Telegram uses inline keyboard buttons; Slack Socket Mode uses Block Kit buttons; Discord, Signal, Matrix, and WhatsApp embed a short token in the prompt and wait for a <token> approve|deny|always reply. In the CLI, it’s an inline prompt. In ACP, the agent issues a session/request_permission JSON-RPC request from agent to client (not a session/update notification); the client responds with {"outcome": {"outcome": "selected", "optionId": "allow-once|allow-always|reject-once"}} or {"outcome": {"outcome": "cancelled"}} to approve, always-approve, or deny. See ACP → session/request_permission.
Timeout: unanswered approval requests expire after the channel’s approval_timeout_secs (default 120 for most channels; see each channel’s config block). Timeouts are treated as denials.
full
No approval gates — all tool calls flagged low/medium/high run without asking. workspace_only is implicitly disabled (the agent can access paths outside the workspace); forbidden_paths still blocks; the OS-level sandbox (sandbox_enabled + sandbox_backend) still applies.
这适用于可信的本地开发、CI 或需要端到端运行且无需人工干预的标准操作流程(SOP)。如果你需要 full 模式 + 无工作区限制 + 无沙盒,请参阅 YOLO 模式。
每个工具的覆盖设置
auto_approve, always_ask, and excluded_tools live as fields on the risk profile — they’re flat lists of tool names, not nested tables:
[risk_profiles.assistant]
level = "supervised"
auto_approve = ["browser_open", "http"] # always allow, even at supervised
always_ask = ["file_write", "shell"] # always ask, even at full
excluded_tools = ["browser_automation"] # deny regardless of level
excluded_tools is also available per-channel (channels.<type>.<alias>.excluded_tools) to hide tools from specific surfaces without changing the profile.
Command allow list
对于 shell 工具而言:
[risk_profiles.assistant]
allowed_commands = ["git", "cargo", "grep", "find", "ls", "cat"]
If allowed_commands is non-empty, it’s strict — any command not listed is blocked. The shell-policy validator handles destructive-pattern detection on top of the allowlist.
路径规则
[risk_profiles.assistant]
workspace_only = true
forbidden_paths = ["/etc", "/sys", "/boot", "~/.ssh", "~/.aws"]
workspace_only = true restricts reads and writes to <workspace>/**. forbidden_paths always blocks regardless of workspace setting (covers the cases where workspace_only is off).
沙盒
OS-level sandboxing fields live on the same risk profile:
[risk_profiles.assistant]
sandbox_enabled = true
sandbox_backend = "auto" # "auto" | "landlock" | "firejail" | "bubblewrap" | "docker" | "sandbox-exec" | "none"
firejail_args = [] # extra args when sandbox_backend = "firejail"
See Sandboxing for backend selection per OS.
环境透传
默认情况下,shell 工具在最小化环境中运行。要暴露特定的环境变量:
[risk_profiles.assistant]
shell_env_passthrough = ["PATH", "HOME", "USER", "LANG"]
密钥(API_KEY、_TOKEN、_SECRET、_PASSWORD 模式)绝不会自动传递——请显式列出它们,或在命令内部从密钥存储中获取。
Per-channel stricter autonomy
Autonomy is per-agent, not per-channel. To run a public-facing channel at a stricter level than your main agent, define a second agent bound to a stricter risk profile and route that channel to it:
[agents.public]
model_provider = "anthropic.home"
risk_profile = "public"
channels = ["bluesky.home"]
[risk_profiles.public]
level = "readonly"
Per-channel excluded_tools (channels.<type>.<alias>.excluded_tools) is the cheaper knob when you only need to hide individual tools — no second agent required.
可观测性
审批请求、授权、拒绝和超时均通过 infra crate 发出结构化事件:
INFO autonomy:approval_requested 工具=file_write 路径=/tmp/foo.txt 频道=discord 用户=alice
INFO autonomy:approval_granted 工具=file_write 路径=/tmp/foo.txt 频道=discord 用户=alice
WARN autonomy:approval_timeout 工具=shell 命令="git push" 频道=telegram 用户=bob
WARN autonomy:blocked 工具=shell 命令="rm -rf /tmp" 原因="forbidden pattern"
被阻止的调用的收据会像成功的调用一样写入 tool-receipts 日志 —— 拒绝也是一个值得审计的事件。
为什么不直接使用二进制的“安全模式”?
Because the useful middle ground is big. A user who wants agents to run scripts automatically but not push to master needs something between “everything’s allowed” and “nothing’s allowed”. Three-level autonomy + per-tool overrides + command allowlists gives that knob without fragmenting the config.