Agent Control Plane:把 AI 代理授权决策搬到模型之外
作者开源 Agent Control Plane(ACP),在 LLM 之外引入策略引擎执行授权决策,并配以 Dafny…
针对 AI 代理普遍存在的提示注入风险,作者提出并开源了 Agent Control Plane(ACP):一个独立于模型的策略执行层,专门决定一个代理动作是否被授权,从而把「谁可信」这一安全判断从模型手中剥离出来。
核心问题:授权不应由模型承担
传统做法是给模型一个凭证,并把这视为「授权」。但模型无法在架构层面区分指令与数据——白底白字的隐藏文本、依赖项 README 中的恶意注释、被投毒的客服工单,都会被当作指令执行。能力更强的模型并不能解决这一问题,因为这是一个架构问题,不是质量问题。
ACP 把授权问题重新表述为:「该动作是否符合策略、是否具备能力、是否达到所需 quorum」,并将这一判断放到模型触及不到的位置执行。即便模型被攻陷,它可以反复请求一个 4 万欧元的合成订单,但风险等级始终由它看不到的已签名策略重算,且该订单必须由人类针对这次具体请求签名才能放行。
架构:两道门
整个控制平面被抽象为一条简单链路:
- agent ──propose──▶ policy engine ──▶ executor ──▶ action
- 策略引擎从模型看不到的已签名策略中重算风险
- 不可逆动作必须由人类签名确认
具体实现为一组 HTTP 接口:
GET /health:存活检查,并返回当前生效 bundle 的哈希GET /actions:枚举九条已注册动作、目标、参数与可逆性POST /propose:唯一的执行入口,按规则返回 executed / held / refusedGET /holds:查看等待人类确认的待办POST /acknowledge:第二个人类对某条 held 动作签字确认POST /release:仅当有效签字绑定到对应字节时才放行
任意模型都可以挂载在上游,控制平面只与策略和签字打交道,因此不受模型行为变化影响。
演示与部署
仓库提供一个本地演示:运行 python3 reference/suites/demo_flow.py 后会启动一个网页,对比「无控制平面」与「接入 ACP」两条路径下同一份被投毒文档的处理结果——前者数据外泄,后者任何不可逆动作都被拦住。演示支持两种模式:粘贴 Anthropic API Key 后接入真实模型,或离线运行预设应答;两种模式下控制平面行为完全一致,这是设计上的有意安排:若两种模式出现分歧,则说明安全保证其实依赖于模型说了什么。
部署方面提供 docker compose -f deploy/docker-compose.yml up -d ingress 一键起服务,监听 8848 端口。
验证:不只是跑通,还要证伪
项目把验证当作第一公民,提供 ./tools/verify.sh 脚本,五大节输出共 18 行结果:
- 完整性:118 个文件哈希与 MANIFEST.sha256 一致
- 离线 Ed25519 签名验证通过
- Dafny 程序验证器:36 条证明通过、0 错误
- 攻击套件 74/74 全数命中
- 一致性套件 45/45 合规
- 执行器突变测试 20/20 被识别
- 确认与审计突变各 6 与 4 项
其中突变测试结果最值得关注:每一次安全检查被删掉,配套攻击就必须成功,以此证明检查确实在做功、测试不是空跑。两道闸门中,./tools/verify.sh --suites 不需 release key、每次提交都应绿;完整 ./tools/verify.sh 还需要离线签名,只在打 tag 的发布版本上才能绿。两次发布之间出现红色完整性属于离线签名的预期表现,并非缺陷。
威胁模型与适用边界
项目将自身定位为「结构性主张」,关键不变量记为 INV-1-HIGH:被攻陷的模型可以请求任意动作,但只有在动作已被策略允许、且满足必要人类签字时才会被执行。换言之,模型只能 propose,不能 authorize。
威胁模型映射到 MITRE ATLAS、ATT&CK 与 OWASP LLM Top 10,并列出八类典型部署场景下的失效模式。作者明确列出该项目不声称的事情:它不保证模型输出正确,不替代数据层防护,也不替代输出审查。ACP 只回答一个问题——「这个动作是否被授权」。
项目以 MIT 协议开源,作者呼吁安全社区进行对抗性复审,认为这是当前最关键的工作缺口。
