Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

自主性级别

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_list
  • memory_search
  • http(仅支持 GET;POST 被阻止)
  • web_search
  • time

适用于:面向公众的问答代理、仅分析部署,或在允许其写入任何内容之前,用于验证新工具配置的方式。

supervised(默认)

低风险工具会自动运行。中等风险工具会触发操作员审批提示。高风险工具将被阻止。

风险分类:

风险示例行为
file_readhttp GETmemory_searchweb_searchtime运行
中等工作区内的 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.