【Agent Harness实战】你的AI Agent是在“自律”还是在“被铐着”?聊聊Gliding Horse的硬核门禁
你的AI Agent是在“自律”还是在“被铐着”?聊聊Gliding Horse的硬核门禁
当AI Agent的"安全"不再依赖LLM的自觉,而是靠代码级强制执行——这就是Gliding Horse(流马)的硬核门禁哲学。本文深入对比软性限制(Prompt引导)与硬性限制(系统调用门+数字签名+角色白名单)的本质差异,揭示为何企业级AI Agent需要"被铐着"才能跑得稳。不讲空话,只聊代码层面的安全架构。
在开始之前,咱们先做一道选择题。
你训你家狗子“不准偷吃桌上的肉”。你把肉放在桌上,然后出门了。你猜狗子会偷吃吗?
- 选项A:会。狗子听不懂人话,它只看到肉。
- 选项B:不会。你把肉放进了带锁的保险箱,狗子压根碰不到。
这题傻子都知道选B。但回到我们天天打交道的AI Agent,很多人却天真地选了A。
最近看到一个挺有意思的项目叫Superpowers,它搞了个“HARD-GATE”门禁机制。名字听着很硬核,我仔细研究了一下代码……然后发现它本质上就是选项A——它在给AI做思想教育,让AI“自觉”遵守规则。
而我们做的Gliding Horse(流马),选了选项B——我们根本不信任AI,所以用系统代码给它铐上了手铐和脚镣。
下面这张流程图直观展示了Gliding Horse硬核门禁的完整工作流程——从Agent发起操作请求,到系统调用门的三道硬拦截,再到阶段门禁的质量关卡:
流程说明: Agent的每一步操作都必须先经过系统调用门的三道硬锁——参数校验、签名验证、角色白名单,任何一道不通过都会被硬性驳回。通过后执行工具并产出结果,再进入阶段门禁接受SHACL契约的质量检查,不合格则打回重做,合格才能流转到下一阶段。整个流程没有“AI自觉”的余地,全是代码级的强制执行。
一、Superpowers的“硬门禁”到底长啥样?
先客观还原一下它的工作原理:
- 每次新对话开始时,
session-start这个hook脚本被执行。 - 这个脚本只做一件事:把
using-superpowers这个“元技能”的Markdown内容,完整地注入到会话的上下文里。 - 这个“元技能”里写满了各种规矩。比如某个技能的
SKILL.md里写着HARD-GATE: 在用户批准设计前,不得编写任何代码。
看见没,它所谓的“门禁”,就是一串文本。它没有执行任何代码来锁门,只是把“行为守则”塞给了LLM。
这相当于你在狗子耳边说:“肉在桌上,但你不能吃哦,吃了我生气。”然后你走了。 这就是典型的软性限制——规则写在纸上,执行全靠自觉。
二、Gliding Horse的“硬性门禁”:不信AI,只信代码
流马的门禁哲学非常冷酷:能执行代码的AI,本质上是一个潜在的罪犯。 我们不是在赌它遵不遵守规矩,而是让它在物理上(系统层面)根本做不了违规的事。
在流马里,Agent(不管是PA/DA/CA/AA)的任何一步操作,都必须经过一个铁面无私的裁判——系统调用门(Syscall Gate)。
这不是一段Prompt,这是几百行Rust代码,它挡在Agent和外部世界之间,执行三层硬拦截:
- 第一道锁:JSON Schema校验。 Agent说我要调这个工具。行,你的参数合不合规?格式对不对?类型对不对?任何一个字段不合Schema,直接驳回,连日志带错误码甩回给Agent,让它自己改。
- 第二道锁:Ed25519数字签名验证。 参数对了就行?万一这个Skill被人篡改过,里面藏了恶意指令怎么办?每执行一个Skill,Gate都会验它的Ed25519签名。签名对不上,直接拒绝加载。
- 第三道锁:角色白名单检查。 你是PA(计划者)?对不起,你的身份只能读文件、查知识图谱。想写文件?想执行shell命令?白名单里没有你,直接拒绝。 哪怕LLM自己产生了“我要删库”的幻觉,Gate也会把它摁回去。
这还没完。当一个DA(执行者)好不容易干完了活,想把产出(比如一份PRD文档)传给下游的CA(检查者)时,它会触发流马的第二道硬门禁——阶段门禁(Stage Gate)。这个Gate会自动加载我们预设的SHACL契约(一种结构化质量标准),去图谱里检查这份PRD:
- “有没有定义功能模块?”→ 没有。流转被硬性阻断。
- “有没有列出系统参与者?”→ 没有。打回给DA,附上所有缺失项,让它重做。
这套循环,完全没有依赖“AI你自觉点”这种鬼话。不合格就是不合格,系统代码不给你过,你喊破喉咙也没用。
下面用一段简化的Rust伪代码,展示Syscall Gate如何执行JSON Schema校验和角色白名单检查的核心逻辑:
// ============================================================
// 简化版 Syscall Gate 核心逻辑(Rust 伪代码)
// ============================================================
/// 系统调用门:Agent 的每一步操作都必须经过此门
async fn syscall_gate(
agent_id: &str,
role: &str, // 当前 Agent 角色:PA / DA / CA / AA
tool_name: &str, // 要调用的工具名
params: &Value, // 工具参数(JSON)
skill_signature: &str,// 技能包的 Ed25519 签名
) -> Result<Output, GateError> {
// ---- 第一道锁:JSON Schema 校验 ----
let schema = load_tool_schema(tool_name).await?;
if let Err(errors) = validate_json(&schema, params) {
return Err(GateError::SchemaRejected {
tool: tool_name.into(),
reason: format!("参数校验失败: {:?}", errors),
});
}
info!("✅ [Gate] Schema 校验通过: {}", tool_name);
// ---- 第二道锁:Ed25519 数字签名验证 ----
let skill_pubkey = lookup_skill_publisher(tool_name).await?;
if !verify_ed25519(skill_signature, &skill_pubkey, params) {
return Err(GateError::SignatureMismatch {
tool: tool_name.into(),
reason: "技能包签名无效,可能已被篡改".into(),
});
}
info!("✅ [Gate] 签名验证通过: {}", tool_name);
// ---- 第三道锁:角色白名单检查 ----
let whitelist = load_role_whitelist(role).await?;
if !whitelist.contains(tool_name) {
return Err(GateError::RoleForbidden {
agent: agent_id.into(),
role: role.into(),
tool: tool_name.into(),
reason: format!("角色「{}」无权调用「{}」", role, tool_name),
});
}
info!("✅ [Gate] 角色权限通过: {} -> {}", role, tool_name);
// 三道锁全部通过,放行
execute_tool(tool_name, params).await
}
这段代码清晰地展示了流马门禁的冷酷逻辑:参数不对 → 驳回;签名不对 → 驳回;角色没权限 → 驳回。 没有任何“商量”的余地,每一
下面是一个具体的 SHACL 契约 示例,用 Turtle 格式定义了对 PRD 文档的结构化质量约束——要求 PRD 必须包含"功能模块"和"系统参与者"两个属性,且每个属性至少有一个值:
# ============================================================
# SHACL 契约:PRD 文档质量标准(Turtle 格式)
# ============================================================
@prefix sh: <http://www.w3.org/ns/shacl#> .
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
@prefix prd: <http://glidinghorse.dev/ontology/prd#> .
# PRD 文档的形状定义
prd:PRDShape
a sh:NodeShape ;
sh:targetClass prd:PRDDocument ; # 作用于所有 PRDDocument 类型的节点
sh:property [
sh:path prd:hasFunctionalModule ; # 属性:功能模块
sh:minCount 1 ; # 至少 1 个
sh:severity sh:Violation ; # 缺失即违规
sh:message "PRD 必须至少定义一个功能模块" ;
] ;
sh:property [
sh:path prd:hasSystemActor ; # 属性:系统参与者
sh:minCount 1 ; # 至少 1 个
sh:severity sh:Violation ; # 缺失即违规
sh:message "PRD 必须至少列出一个系统参与者" ;
] .
工作原理: 阶段门禁(Stage Gate)在收到 DA 产出的 PRD 后,会将其加载到知识图谱中,然后运行 SHACL 验证引擎(如 Oxigraph 或 Apache Jena)对 prd:PRDShape 进行校验。如果 PRD 节点缺少 prd:hasFunctionalModule 或 prd:hasSystemActor 属性(或属性值为空),引擎就会抛出 sh:Violation 级别的验证错误,并附上 sh:message 中的提示文本。Gate 捕获这些错误后,将 PRD 打回给 DA 重做,同时附上所有缺失项的清单——整个过程完全自动化,没有任何"AI 自觉"的余地。
行都是硬性拦截。
三、硬性限制 vs 软性限制,一张表看懂
| 类型 | 本质 | 实现方式 | 在 AI Agent 中的表现 |
|---|---|---|---|
| 软性限制 | 行为建议与引导 | Prompt / Markdown / Mermaid 图 | Superpowers 的 HARD-GATE:把规则注入上下文,要求 AI “自律”。 |
| 硬性限制 | 代码级强制拦截 | Hook 脚本 / 系统调用门 / 数字签名 / 角色白名单 | Gliding Horse 的 Gate:在代码层物理阻止 Agent 执行违规操作。 |
四、这套硬核门禁带来的架构收益
1. 确定性
把校验逻辑从“LLM的良心”变成了“Rust的函数”。同样的输入永远得到同样的拦截结果,不存在“今天心情好放你一马”。这对于企业级应用是必需品——审计、合规需要的就是确定无疑的结果。
2. 角色隔离
PA只能读,DA可以读写但必须签名,CA可以查一切并标记问题。通过Gate强制执行最小权限原则,一个Agent被“策反”不会导致系统崩盘。
3. 质量前置
以前软件工程的质量靠最后的测试兜底,测试来不及就“先上线再说”。流马通过阶段Gate把质量卡在每个阶段的出口——需求不合格别进设计,设计不合格别进编码。上线即灾难的概率直线下降。
4. 安全防篡改
即使外部MCP工具或社区Skill被恶意修改,Ed25519签名校验会直接拒绝加载。整个工具生态是“保税区”模式——开放,但每件货都过安检。
五、不便(如果有的话)
坦白说,硬性门禁确实有一个代价:初期配置成本更高。 你需要为每种交付物定义SHACL契约(PRD要包含什么、设计文档要包含什么),需要为每个角色配置工具白名单。这不是开箱即用的“聊天机器人”,而是一套需要定制的“工程流水线”。
但我们认为这不是劣势,而是分工——软性限制适合轻量级个人工具,硬性限制是企业级生产环境的基本要求。流马选择后者,是因为我们相信,真正能替代程序员的不是最强的AI,而是最可靠的AI。
六、最后说句人话
Superpowers的“门禁”是在给AI念《员工手册》,希望它做个好员工。流马的门禁是在办公室门口装了个安检门,身上有违禁品?门都进不来。
这两种思路没有绝对的对错,但如果你像我一样,不相信AI的“自律性”,只相信代码的“强制执行”,那你大概会喜欢流马的这套设计。
我这套系统叫 Gliding Horse(流马),所有代码都在 GitHub 上:https://github.com/doiito/gliding_horse
这个系列写了十多篇了,从 JSON-LD 到 CPU 缓存记忆,从 Oxigraph 到丰田安灯绳,从技能图谱到硬核门禁。下次可能是真正的总结篇——把这些拼在一起,聊聊流马到底能做什么。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐



所有评论(0)