第 2 部分 平台技术架构
版本:v2.0| 定位:定义平台运行时架构。第 1 部分给「装什么」,第 3 部分给「怎么门禁」,本文给「Harness 怎么托管、Loop 怎么跑、工具怎么路由」,第 4 部分叠加计费与金融合规。
2.0 架构总览(H=⟨C,A,R⟩ 重述)
平台由两层 组成,通过稳定的 Harness Contract 连接(§0.4 已用 ⟨C,A,R⟩ 重述):
css
┌─────────────────────────── Harness(控制面 / 装配期 + 常驻服务)──────────────────────────┐
│ C:能力注册表(Capability Registry) │ A:Dispatcher(调度) │ R:会话/状态·模型路由·可观测/计量·记忆层 │
└───────────────┬───────────────────────────────────────────────────────────────────────────┘
│ Harness Contract:loop.requestTool(toolId, args) → pdp.decide() → execute → telemetry
▼
┌─────────────────────────── Loop(运行面 / 每 Agent 一个迭代实例)──────────────────────────┐
│ Intake→Plan→Act→Observe→Reflect→Terminate | 护栏 | 上下文工程 | 子代理委派 | 错误恢复 │
└───────────────────────────────────────────────────────────────────────────────────────────┘
- Harness 常驻:负责装配(注册+门禁,第 3 部分 S1)、调度、计量、可观测、记忆(对应 ⟨C,A,R⟩ 的 C/A/R 控制面侧)。
- Loop 按需:每个用户任务 = 一个 Loop 实例,跑完即销毁(沙箱随生命周期,第 3 部分 §3.6)。
2.1 两层职责边界
| 关注点 | Harness(控制面) | Loop(运行面) |
|---|---|---|
| 生命周期 | 进程级常驻 | 任务级(一次对话/一个 Agent 任务) |
| 核心职责 | 注册能力、门禁、调度、路由、计量、可观测 | 迭代推理、工具调用、护栏、上下文、委派、恢复 |
| 门禁位置 | 第 2/3/4 关(装配期,第 3 部分 S1) | 第 5 关 PDP(每次 Act,第 3 部分 S4/S5) |
| 状态 | 跨任务持久(注册表、账单、审计) | 任务内瞬时(对话历史、工作区、中间产物) |
| 失败域 | 影响平台全局(须高可用) | 仅影响单个任务(可重试/隔离) |
2.2 Harness 子系统
2.2.1 能力注册表(Capability Registry)【= ⟨C⟩ Control】
- 输入 :第 3 部分门禁产出的
ToolManifest(含commercialStatus/riskTier/egress/secretsref /permissions)。 - 存储 :按
kind(skill / mcp / proprietary)+direction(方向技能包)索引。 - 消费方:Dispatcher(查权限)、ModelRouter(查成本档)、PDP(查策略)、第 4 部分计费(查费率)。
- 装配期动作(S1) :新工具经第 3 部分第 2/3 关 → 写入注册表 → 归入方向技能包预设(见第 1 部分 §1.3)。
2.2.2 会话与状态管理【= ⟨R⟩ Runtime】
- 一个
Session= 一个用户任务,绑定:agentProfile、独立workdir(第 3 部分 §3.6.2)、memory句柄(cloud/user/workspace 三层)、loopConfig(模板+护栏)。 - 会话结束 → 销毁沙箱与工作区、清除 secret(第 3 部分 §3.6.5)。
2.2.3 模型抽象与路由(ModelRouter)
-
统一
Model接口,屏蔽厂商差异;按 (scenario, subtask, costTier) 选模型:- 轻量任务(补全/分类/抽取)→ 低成本模型;
- 规划/推理/长上下文 → 推理型模型;
- 失败/超时 → 回退链(fallback chain)。
-
路由决策受
costBudget(Loop 护栏)与第 4 部分费率约束。
2.2.4 工具调度器(Dispatcher)【= ⟨A⟩ Agency】
- 统一入口:
dispatch(toolId, args, actor) → result。 - 流程:查注册表 → 调 PDP 决策(第 3 部分第 5 关)→ spawn/复用沙箱(按 riskTier)→ 执行 → 回写 telemetry(含 costUsd)→ 返回。
- 三类工具同一接口:
skill(本地方法)、mcp(stdio/remote 进程)、proprietary(平台内置)。 - PDP 钩子是硬编码内置:未过 PDP 的工具调用一律不允许执行。
2.2.5 流式与可观测(Telemetry)【= ⟨R⟩ Runtime】
- OpenTelemetry:每个 Loop 实例一个 trace,每工具调用一个 span(含 toolId/risk/decision/latency/cost)。
- 指标:p95 延迟、错误率、成本/任务、护栏触发次数。
- 与第 3 部分审计日志、第 4 部分计费埋点共用同一收集管道(S5)。
2.2.6 记忆层【= ⟨R⟩ Runtime】
- 接入 cloud / user / workspace 三层记忆(详见技术纵览 v3.0 第 5--7 章:记忆五层 + RAG + GraphRAG),Loop 在 Intake/Reflect 相位读写,支撑跨任务连续性与「断点续跑」(与 §3.8 事件溯源打通)。
2.3 Loop 子系统(单 Agent 运行时循环)
2.3.1 循环相位
css
Intake(收用户输入+场景契约)
→ Plan(sequential-thinking / 任务分解,产出步骤)
→ Act(选工具 → 经 Dispatcher+PDP 执行)
→ Observe(读结果/错误)
→ Reflect(自检:是否达成?需重试/委派/换模型?)
→ [未达成且未超护栏] 回到 Plan/Act
→ Terminate(present outcome,写记忆)
2.3.2 护栏(Guardrails)
| 护栏 | 实现 | 触发动作 |
|---|---|---|
maxTurns |
Loop 计数器 | 超阈值强制 Terminate + 摘要 |
tokenBudget |
累计上下文 token | 触发压缩(§2.3.3)或终止 |
costBudget |
累计 costUsd(来自 Dispatcher) |
超阈值 suspend + 通知(与 PDP 熔断协同) |
humanCheckpoint |
场景模板标记(第 1 部分 §1.3) | 高风险节点挂起等人(发布/写库/外发/付费) |
circuitBreaker |
连续失败计数 | 暂停该工具,转 fallback/人工 |
2.3.3 上下文工程(Context Engineering)
- 窗口接近上限 → 触发 compact / summarization(保留决策与待办,丢弃原始长文本)。
- 中间产物落
workdir(加密),步骤间用引用而非全量重传,支撑长链路断点续跑。
2.3.4 子代理委派(Sub-agent Delegation)
- 长任务 / 可并行子任务 → Loop 调 Harness 派生子 Loop(fan-out 模板,第 1 部分 §1.3)。
- 子代理独立沙箱、独立护栏;父 Loop 汇聚结果后继续。
- 用于:自媒体三分支并行、多源 ETL、代码库多模块分析。
2.3.5 错误恢复与回退
- 工具调用失败 →
Observe捕获 →Reflect决策:重试(指数退避)/ 换参数 / 换模型(ModelRouter fallback)/ 转人工。 - 沙箱崩溃 → 仅该 Loop 受影响(故障隔离,第 3 部分 §3.1),不波及宿主。
2.4 工具路由策略(Routing & Orchestration,S3)
| 选择 | 规则 | 依据 |
|---|---|---|
| skill vs mcp vs native | 纯「方法/流程」→ skill;连外部系统→ mcp;宿主内置能力→ native | 能力注册表 kind |
| 具体工具 | 多候选时按 capability 匹配 + 门禁状态(warn 需确认)+ 成本 | 注册表 + PDP |
| 模型 | 轻量→低成本;规划/推理→推理型;超时→回退 | ModelRouter(§2.2.3) |
| 编排 | 跨方向任务 → Orchestrator 选方向技能包 + 实例化 Loop(见 §2.5) | 第 1 部分 §1.3 + 场景编排手册 |
2.5 多 Agent 调度(Orchestrator)
- 入口:用户任务 → 意图识别 → 选方向技能包(第 1 部分 §1.3)→ 实例化主 Loop。
- 编排:主 Loop 按子任务调用 Dispatcher 路由,或派生子 Loop(fan-out)。
- 复用场景编排手册的 6 条链路:自媒体全链路 / 数据→PPT→发布 / 编程流水线 / 量化研究 / 知识问答 / 跨方向编排(见第 5 部分)。
- 治理 :每个子 Loop 继承主会话的 PDP 策略与
costBudget;Orchestrator 不绕过门禁。
2.6 标准流程映射(S0--S6 → 架构组件)
| 阶段 | 主要落点 |
|---|---|
| S0 场景契约 | Loop 的 session.scenarioContract |
| S1 Harness 装配 | §2.2.1 能力注册表 + 第 3 部分第 2/3 关 |
| S2 Loop 设计 | §2.3 + 第 1 部分 §1.3 模板/护栏 |
| S3 路由与编排 | §2.4 + §2.5 |
| S4 门禁与合规注入 | §2.2.4 Dispatcher 内置 PDP(第 3 部分第 5 关)+ 第 4 部分合规规则 |
| S5 可观测与计量 | §2.2.5 Telemetry + 第 3 部分审计 + 第 4 部分计费 |
| S6 评估与回归 | 质量/成本/合规基线(CI eval)+ 模型升级触发 Harness 消融回归(§2.9.3) |
2.7 参考实现骨架(TypeScript,编排层)
kotlin
// harness.ts ------ 控制面核心
class Harness {
registry: CapabilityRegistry; // §2.2.1 消费第3部分门禁
router: ModelRouter; // §2.2.3
pdp: PolicyEngine; // 第3部分第5关
telemetry: Telemetry; // §2.2.5
async assemble(manifest: ToolManifest) { // S1 装配期
const res = await loadTool(manifest); // 第3部分 loader → 含第2/3关
if (res.ok) this.registry.register(res.manifest);
}
dispatch(toolId: string, args: any, actor: Actor) {
const tool = this.registry.get(toolId);
const decision = this.pdp.decide({ tool, call: { type: 'exec', args }, actor }); // 每次Act前
if (!decision.allow) return decision.deny();
const r = executeInSandbox(tool, args); // §2.2.4
this.telemetry.record({ toolId, costUsd: r.costUsd, decision }); // S5
return r;
}
}
// loop.ts ------ 运行面核心
class Loop {
cfg: LoopConfig; // 模板+护栏(第1部分 §1.3, S2)
turns = 0; cost = 0;
async run(input: string) {
let ctx = this.intake(input); // Intake
while (this.turns++ < this.cfg.maxTurns) {
const plan = this.plan(ctx); // Plan
const call = plan.nextTool(); // Act 决策
const res = harness.dispatch(call.toolId, call.args, this.actor); // → PDP → 执行
ctx = this.observe(res); // Observe
if (this.reflect(ctx).done) break; // Reflect → Terminate 条件
if (this.cost += res.costUsd > this.cfg.costBudget) this.suspend(); // 护栏
}
return this.terminate(ctx); // Terminate + 写记忆
}
}
2.8 与第 1/3/4 部分衔接
- ← 第 1 部分:方向技能包 = Harness 预设(S1),Loop 模板 = 第 1 部分 §1.3。
- ← 第 3 部分:Dispatcher 内置 PDP(第 5 关),装配期消费第 2/3 关结论。
- → 第 4 部分 :Dispatcher 回写
costUsd+ Telemetry 为计费/合规提供埋点(S5/S4)。
2.9 默认策略基线(决策裁决 v2 · 含 research/production 开关)
来源:用户在六决策点的裁决请求(2026-07-11)已确认,v2.0 新增
harnessMode显式身份。
2.9.1 决策 1 · 隔离默认档:sandbox-exec 默认开启(宽松 profile)
- 默认 :macOS 上
medium档默认套sandbox-exec(Seatbelt),profile 仅做三件事------系统目录只读、限定工具专属可写目录、egress 走白名单;已通过签名校验的可信工具允许降档到进程内。 - 依据 :
sandbox-exec运行时开销主要在 profile 编译(fork/exec 一次性成本,通常 < 50ms),稳态 syscall 开销可忽略;仅「海量小文件 I/O」场景有损耗。 - 演进(roadmap) :Apple 已把
sandbox-exec标 deprecated(仍可用多年)。架构上把隔离后端抽象为接口,中期迁移到 Lima / container / microVM (macOS 桌面端无原生容器,Lima 轻量 VM 是目前最干净替代);regulated 场景直接上 Firecracker microVM(见 §3.6 / §3.14)。
2.9.2 决策 4 · PDP 选型:MVP 自研轻量 → 长期迁 Cedar(跳过 OPA)
- 默认 :MVP 用声明式 JSON/YAML 规则 + 简单匹配器 自研(零依赖、可内嵌、易调试);策略条目规模化后迁移到 Cedar(AWS 开源,专为授权设计,且 2026-03 已成为 Bedrock AgentCore Policy 内置引擎)。
- 选型理由 :自研起步快但缺形式化验证;OPA/Rego 生态成熟但学习曲线陡、可读性差、且是通用策略语言(非授权专用);Cedar 语法可读、支持 SMT 静态分析(可判定「是否存在越权路径」)、deny-overrides 语言层强制、性能优于 OPA------2026 趋势是授权场景从 OPA 向 Cedar 迁移。
2.9.3 决策 5 + 前沿范式 · Loop 护栏默认值 + 研究/生产二分 + 策略重定价
- 生产档默认(production) :
maxTurns=30、costBudget=$1、按场景分档(见下表);humanCheckpoint五类不可逆操作强制人审(§2.9.4)。这本质是「生产型 Harness」参数(对齐技术纵览 v3.0 §9.11)。 - 研究档(research,显式开关) :放宽护栏、允许多子代理并行、接更多工具,用于冲能力天花板;不计入生产计费基线,需显式
harnessMode: research开启。 - 策略重定价 + 消融删冗(S6 增强) :每次底层模型升级,S6 评估回归新增一步 Harness 消融回归------对每条护栏/子代理/评估器/路由策略跑对照消融,测量边际贡献,主动删除不再产生收益的组件(对齐技术纵览 v3.0 §9.12 / §10.5 补偿面迁移)。详见 §6.6。
| 参数 | 生产默认 | 简单任务 | 复杂任务 | 硬顶 |
|---|---|---|---|---|
maxTurns |
30 | 25 | 50 | 100 |
costBudgetUsd |
$1.0 | $0.5 | $3--5 | ×2 后熔断 |
costWarnRatio |
0.8 | 0.8 | 0.8 | --- |
- 软停规则 :成本达 80% 仅预警;达 100% 软停 + 询问用户是否追加预算;到硬顶(×2)强制熔断。
2.9.4 决策 6 · humanCheckpoint 默认触发集:五类不可逆操作强制人审
判定原则:不可逆 + 外部可见 。以下动作在 Act 前强制人机回路 (与 SOUL.md「对外部动作保持谨慎」一致),与第 3 部分的 ⚠️ 升级规则共用同一条 PDP 通道:
- 写生产 (
deploy/ 改 DB schema) - 对外发布 (
publish.social/ 公开链接) - 付费扣款 (
billing.charge/ 采购数据) - 批量删除 (
fs.delete.bulk/DROP TABLE) - 发送消息 (
message.send/ 邮件 / 群发)
内部只读、组织类动作(读文件、整理、生成草稿)保持 自动执行以维持效率。
2.9.5 默认策略基线配置模板(Loop + 隔离 + harnessMode)
yaml
# platform.baseline.yaml ------ 由 Harness 在 S1 装配期加载,Loop 在 S2/S4 覆盖
harnessMode: production # research | production(§2.9.3 研究/生产二分)
researchOverride:
maxTurns: 200
costBudgetUsd: 20.0
allowFanOut: true
extraTools: ["experimental-*"]
loop:
defaults:
maxTurns: 30
hardCap: 100
costBudgetUsd: 1.0
costWarnRatio: 0.8
scenarioTiers: # 第1部分 §1.3 场景可覆盖
office.simple: { maxTurns: 25, costBudgetUsd: 0.5 }
data.quant: { maxTurns: 50, costBudgetUsd: 5.0 }
media.full: { maxTurns: 50, costBudgetUsd: 3.0 }
code.pipeline: { maxTurns: 40, costBudgetUsd: 2.0 }
humanCheckpoint:
requireOn:
- action: "deploy"
- action: "db.write.schema"
- action: "publish.social"
- action: "billing.charge"
- action: "fs.delete.bulk"
- action: "message.send"
isolation: # 见 §2.9.1 / §3.6
default:
macos: { medium: "sandbox-exec", high: "sandbox-exec" }
linux: { medium: "subprocess+ulimit", high: "nsjail" }
regulated: { high: "firecracker-microvm" } # 金融/医疗等受监管数据
本基线在 Harness 装配期(S1)作为全局默认加载,Loop 在 S2 据场景契约覆盖特定字段;所有覆盖动作写入审计(S5)。许可证类默认(决策 2/3)见 第 3 部分 §3.13。
2.10 【维度补全】六框架收敛与国际对标
本节约 Part 2 原「落地里程碑」前的空白,用 2026-07 框架实证补全,使架构决策具备外部参照。
| 框架 | Stars | 架构风格 | 本蓝图可映射点 | 对本平台的启示 |
|---|---|---|---|---|
| LangGraph | 31k | 图/状态机 | Orchestrator 图(§2.5)、Durable Execution | 模型灵活性最强(同代理换 Claude/GPT/Gemini);持久化执行/检查点 |
| CrewAI | 50.4k | 角色组队 + 事件驱动 | 方向技能包 = Crew、Sub-agent = Agent | 社区最大、原型最快;年 20 亿+ 次执行 |
| Claude Agent SDK | 6.6k | 自主工具循环(编排即代码) | Loop 原语(§2.3)、hooks | 深度优化 Claude;锁定模型(换 GPT 需重写 schema) |
| OpenAI Agents SDK | 25.7k | 轻量 Provider 无关 | 三档护栏(input/output/tool)、Sandbox 类 | 原生 voice(gpt-realtime)、最干净 handoff;无原生 A2A |
| Microsoft Agent Framework 1.0 | 10k | 图工作流 + 分层 | HITL 烘焙进图、类型安全组件 | Python/.NET;原生 A2A |
| Google ADK | 19.4k | 代码优先 + 层级组合 | sub_agents 层级、Policy 评估 | 四语言(Py/TS/Java/Go);A2A-native |
关键启示:
- 框架收敛 = 原语收敛:typed delegation、生命周期钩子、HITL 已是标配------本蓝图 Harness Contract + PDP + humanCheckpoint 与之同构,不绑定任何单一框架。
- 协议层打破厂商锁定:MCP 管工具、A2A 管 Agent 间通信,二者组合使「今天选的框架不是永久决定」(见 §6.2)。
- 模型亲和力是真实约束:若平台需跨模型调度,LangGraph 式抽象优于 Claude/OpenAI SDK 的强绑定------本蓝图 ModelRouter(§2.2.3)刻意做模型无关抽象。
- 三范式取舍:事件驱动(OpenAI)适合对话流;图工作流(ADK/MS)适合结构化 pipeline/审批链;编排即代码(Anthropic)灵活但状态管理自担------本蓝图 Orchestrator(§2.5)默认图式(可可视化、易调试),复杂场景允许 code 式自定义。
第 3 部分 加载隔离与许可证门禁(原 Part 3)
版本:v2.0(整合 + 维度补全)| 定位:定义工具进入平台 → 隔离运行 → 许可证合规校验的工程实现规范,明确其在 Harness(装配期)与 Loop(运行期)中的时空位置。目标:默认安全、许可证可证、行为可审计、横向可扩展。
3.0 设计目标与约束
| 目标 | 说明 |
|---|---|
| 最小权限 | 每个 Skill/MCP 仅获得其声明所需的能力、文件根、网络出口 |
| 故障隔离 | 单个工具崩溃/失控不波及宿主与其他 Agent |
| 许可证合规 | 安装即判定商用状态,自动拦截 ❌、提示 ⚠️,记录决策 |
| 可审计 | 加载、调用、拒绝全程留痕(谁/何时/何工具/何许可证/决策) |
| 供应链可控 | 版本锁定、哈希校验、secret 不落盘 |
| 跨平台 | macOS(开发/桌面端)与 Linux(服务端)均可落地 |
非目标(本期不解决) :多租户硬隔离(由第 2 部分调度层负责)、模型权重许可审查(属数据/创作方向,单独流程)。
3.1 门禁在 Harness / Loop 中的时空位置(2026-07 范式)
| 关卡 | 所在阶段 | 触发时机 | 产物 / 动作 |
|---|---|---|---|
| 第 2 关 静态扫描 + 风险分级 | Harness 装配期(S1) | 工具注册/安装时一次性 | riskTier 写入 Manifest 并缓存 |
| 第 3 关 许可证门禁 | Harness 装配期(S1) | 同上 | commercialStatus(allow/warn/deny)缓存 |
| 第 4 关 隔离沙箱 | Harness 装配期 spawn | 注册后拉起沙箱实例 | 沙箱随 Agent 会话(Loop 生命周期) 绑定 |
| 第 5 关 运行时 PDP | Loop 运行期(S4/S5) | Agent 每次 Act 阶段调用工具前 | 实时决策 egress/fs/能力/��批/成本熔断 |
关键设计点:
- Harness 静态分类,Loop 动态校验:装配期只做「这个工具能不能进平台」(deny 直接拒、warn 管理员确认);运行期每次调用都再过 PDP------因为同一工具在不同场景/参数下风险不同(如 DB MCP 读 vs 写)。
- PDP 是 Loop 的内置钩子 :Loop 的 Act 相位在
execute(toolCall)之前必须先pdp.decide(call),拒绝则不执行、审批类则挂起等人。 - 护栏协同 :Loop 的
maxTurns/costBudget/humanCheckpoint与 PDP 的成本熔断、工具级审批共享同一组配置,避免双重标准。 - 沙箱生命周期 = Loop 生命周期:Agent 会话结束即销毁沙箱与工作区,secret 从环境清除(接 §3.6.5)。
一句话:第 2/3/4 关由 Harness 在「装」的时候搞定,第 5 关由 Loop 在「跑」的时候每步卡------这正是 Harness Engineering 与 Loop Engineering 的分工边界。
3.2 总体架构(管道)
scss
[ 1.注册/安装请求 ] ─▶ [ 2.静态扫描与风险分级 ] ─▶ [ 3.许可证门禁 ] ─▶ [ 4.隔离沙箱加载 ] ─▶ [ 5.运行时策略引擎 ] ─▶ Agent
│ │ │ │ │
│ ├─ 形态识别 ├─ SPDX 识别 ├─ 进程/FS/Net 隔离 ├─ egress 允许列表
│ ├─ 危险 API 检测 ├─ 允许/条件/拒绝 ├─ 资源限额 ├─ 工具级审批
│ └─ 风险分级(tier) └─ 合规义务提示 └─ secret 注入 └─ 审计日志
- 第 2 关 产出
riskTier(low/medium/high/regulated),决定第 4 关隔离强度。 - 第 3 关 产出
commercialStatus(allow/warn/deny),deny 直接拒绝。 - 第 5 关是运行时持续执行点,每次工具调用都过策略引擎(PDP)。
3.3 工具清单元数据模型(Manifest)
perl
{
"id": "browser-use",
"kind": "mcp", // skill | mcp | proprietary
"source": "https://github.com/browser-use/browser-use",
"version": "0.1.0",
"license": "MIT", // SPDX 表达式,缺失则视为 UNLICENSED
"risk": "high", // 由第2关静态扫描生成/覆盖
"entrypoint": {
"skill": "SKILL.md",
"mcp": { "transport": "stdio", "command": "uvx", "args": ["browser-use"] }
},
"permissions": {
"fsReadRoots": ["${skillDir}"],
"fsWriteRoots": ["${agentWorkdir}"],
"egress": ["https://*.anthropic.com", "https://*.openai.com"],
"capabilities": [], // 如 ["net","exec"],默认空
"secrets": ["BROWSER_USE_API_KEY"]
},
"commercial": {
"status": "allow", // allow | warn | deny
"copyleft": false,
"obligations": []
}
}
关键原则:未声明即默认禁止 。任何未在
permissions中显式列出的文件根、网络域、能力,运行时一律拒绝。
3.4 第 2 关:静态扫描与风险分级
3.4.1 形态识别
skill:含SKILL.md,可能带scripts/。mcp-stdio:本地子进程(command/args),风险最高(可任意代码)。mcp-remote:SSE/HTTP 远端服务,风险在数据出网而非代码执行。proprietary:平台内置/商业授权,信任级别由平台背书。
3.4.2 静态检测项(针对脚本/MCP 启动命令)
| 检测 | 方法 | 命中即升级 |
|---|---|---|
| 文件系统越权 | AST 扫描 fs.readFile/rm/writeFile 路径是否超出声明根 |
risk=high |
| 任意子进程 | 检测 child_process.exec/eval、动态 require |
risk=high |
| 网络出网 | 扫描 fetch/http/socket 目标域名 |
比对 egress 声明 |
| 环境变量读取 | 扫描 process.env 是否读取未声明 secret |
risk=medium |
| 沙箱逃逸特征 | 检测 /proc、ptrace、namespace 操作 |
risk=high 并告警 |
| 依赖供应链 | 解析 requirements.txt/package.json,比对已知恶意包库 |
命中则 deny |
3.4.3 风险分级规则
- low:纯 Markdown Skill、无脚本、无网络。
- medium:带脚本但仅本地计算、声明清晰的 fs/网络。
- high :MCP-stdio、含
exec/动态加载、或 egress 指向不可信域。 - regulated(新增):处理金融/医疗/PII 等受监管数据,无论代码风险,隔离直接升 microVM(见 §3.6)。
3.5 第 3 关:许可证门禁
3.5.1 许可证识别流程
- 优先读
SKILL.md/pyproject.toml/package.json中的license字段(SPDX)。 - 缺失则读取仓库根
LICENSE文件,用 SPDX 检测库匹配。 - 远程仓库经 GitHub API
license.spdx_id获取。 - 仍无法判定 → 标记为
UNLICENSED→ 按 deny 处理,要求人工标注后放行。
3.5.2 判定规则表(商用视角)
| 类别 | 许可证 | 门禁动作 | 合规义务提示 |
|---|---|---|---|
| ✅ 允许 | MIT, Apache-2.0, BSD-2/3-Clause, ISC, Python-2.0, Zlib, Unlicense, CC0-1.0, MS-PL | 直接放行 | 保留版权声明(Apache 还需 NOTICE) |
| ✅ 弱 copyleft | MPL-2.0 | 放行 | 仅修改的文件需开源 |
| ⚠️ 条件 | LGPL-2.1/3.0 | 放行(动态链接) | 静态链接需提供目标文件/源码 |
| ⚠️ 强 copyleft | GPL-2.0, GPL-3.0, AGPL-3.0 | 需管理员确认 → 本平台默认 ❌ 拒 AGPL(决策 3) | AGPL:网络分发即须开源整体;GPL:分发须提供源码 |
| ⚠️ 公平许可 | Fair-code(n8n 类) | 需确认 | 自托管免费,SaaS 化需商业授权 |
| ⚠️ 署名共享 | CC-BY-SA | 需确认 | 演绎作品须同协议 |
| ❌ 拒绝 | 非商业(CC-BY-NC、gordenppt)、UNLICENSED、无声明(gpt-image2 类) | 安装即拦 | 不可商��,须改用替代或获书面授权 |
3.5.3 门禁动作
- 安装时(同步) :分类→若
deny返回{allowed:false, reason};若warn弹出管理员确认并写入审计;若allow直接放行并缓存结论。 - 运行时(异步校验) :加载时比对 Manifest 哈希,若源码/LICENSE 变更则重新走门禁,防止「安装合规、后续变更违规」。
- UI 表现:工具详情页显示徽章 ✅/⚠️/❌ + 许可证全文 + 义务说明,列表页可一键按商用状态筛选。
3.5.4 与第 1 部分结论的映射(可直接落库)
- ✅ 入库:ppt-master(MIT)、html-ppt-skill(MIT)、browser-use(MIT)、video-use(MIT)、claude-real-video(MIT)、drawio-skill(MIT)、Understand-Anything(MIT)、mattpocock/skills(MIT)。
- ❌ 拒绝(决策 3):guizang(AGPL-3.0) ------ 网络分发义务触发服务端开源传染,商用平台默认拒绝,改用 MIT 的
ppt-master/html-ppt-skill;Agent-Reach(MIT 但 Cookie/ToS 灰区) ------ 不默认加载,需法务评估。 - ❌ 拒绝:gordenppt(非商业)、gpt-image2(无声明)。
3.6 第 4 关:隔离沙箱加载(四级 + regulated)
按 riskTier 选择隔离强度,遵循「能轻不重」原则以控制开销;regulated 数据直接上最强隔离。
3.6.1 进程隔离
| tier | Linux | macOS | 说明 |
|---|---|---|---|
| low | 同源进程内调用 | 同源进程内 | 纯 Markdown,无代码 |
| medium | 独立子进程 + ulimit |
独立子进程 + ulimit |
本地脚本 |
| high | nsjail / gVisor 容器 | sandbox-exec 配置文件 |
MCP-stdio、exec 类 |
| regulated | Firecracker microVM(独立 guest kernel) | Lima/container 内 microVM | 金融/医疗/PII 等受监管数据 |
- Linux(服务端推荐) :
nsjail(Google,Apache-2.0)或gVisor做轻量容器;配合seccomp过滤危险 syscall(ptrace、mount、socket 未声明域)。 - macOS(桌面/Tauri 端) :Apple
sandbox-exec的自定义 profile(deny-by-default + 白名单文件/网络),或 entitlements 限制。 - regulated:Firecracker microVM(AWS 开源,Rust),125ms 启动、<5MiB 开销、150 VMs/秒/主机;需突破 guest kernel + hypervisor 两道墙才能逃逸,是金融/医疗数据的基准隔离(见 §3.14 CVE 教训)。
3.6.2 文件系统隔离
- 只读挂载 Skill/MCP 自身目录(
fsReadRoots)。 - 可写区限定到
${agentWorkdir}(每 Agent 独立临时目录,生命周期绑定会话)。 - 禁止 访问
~/.ssh、~/.workbuddy(宿主凭据)、其他 Agent 工作区(路径前缀校验)。
3.6.3 网络出网隔离
- default-deny:沙箱网络命名空间默认无外网。
- 仅放行 Manifest
egress中声明的域(精确或宿主级通配)。 - 实现:Linux
iptables/eBPF 出网白名单,或 nsjail 的--net限制 + 代理转发。
3.6.4 资源限额
- CPU/内存/
timeout:medium/high 设上限(如 2 vCPU、512MB、60s),超时杀进程并返回错误。 - 实现:cgroups v2(Linux)/
ulimit+timeout命令;macOS 用launchdlimits 或进程级setrlimit。
3.6.5 Secret 注入(脑手分离 / Credential Proxy)
- 声明于
permissions.secrets的密钥,从平台 Vault 在运行时注入环境变量,绝不写入 Skill 目录或镜像层。 - 进程退出后从环境清除,日志中脱敏(正则遮蔽
sk-*、AKIA*等)。 - 原则(对齐 Anthropic《Decoupling the brain from the hands》) :不可信执行环境永远拿不到原始 token,凭据由 Credential Proxy / Vault 持有------这是脑手分离的落地(技术纵览 v3.0 §9 / 安全章对应)。
3.7 第 5 关:运行时策略引擎(PDP)【Cedar 深化】
集中式策略决策点,每次工具调用都经过,与隔离层解耦,便于统一治理。
3.7.1 策略模型(长期目标态:Cedar)
php
// egress 策略
forbid (principal == User::"agent", action == Action::"network", resource == Network::Host)
when { not resource.host like "*.anthropic.com" && not resource.host like "*.openai.com" }
// 高危能力需审批
permit (principal == User::"agent", action == Action::"exec", resource is Tool)
when { Tool.risk == "high" && Context.adminApproved == true }
为何 Cedar 而非 OPA(2026 实证) :
- AWS 2026-03 将 Cedar 作为 Bedrock AgentCore Policy 内置引擎,在网关边界拦截每个 Agent 工具调用,策略可直接用 Cedar 编写或从自然语言生成并形式化。
- Cedar 的 deny-overrides-permit 在语言层强制------你无法意外写出一条让开发者覆盖安全团队 forbid 的 Cedar 策略;OPA/Rego 中这只是约定。
- Cedar 支持 SMT 形式化验证 (
cedar-policy-validator可证明「不存在越权路径」),这是安全关键部署的关键差异。- MVP 阶段可用自研 JSON/YAML 匹配器(§2.9.2),策略规模化后切换 Cedar runtime,接口不变。
3.7.2 策略维度
- egress 允许列表:未声明域拒绝。
- fs 根校验 :读写路径前缀必须在
fsReadRoots/fsWriteRoots。 - 能力门禁 :
exec/net等能力需显式声明且走审批。 - 工具级审批:high 风险工具的首次调用需用户/管理员确认(可缓存「本次会话信任」)。
- 成本/频率熔断:对接第 1 部分成本看板,超阈值暂停(如 Understand-Anything 单次分析费用、ElevenLabs 调用次数)。
3.8 审计日志(升级为可回放状态源 · 事件溯源)
对齐技术纵览 v3.0 §10.8 / §26。生产型 Harness 的持久状态应是外部 session event log(事件溯源) ,不绑定任何容器。
每条记录含:
scss
{ ts, actor(agent/user), toolId, version, license, commercialStatus,
callType, target(host/path), decision(allow/deny/approve),
sandbox(tier), latencyMs, costUsd?, loopIteration, checkpoint, decisionTrace }
- 落盘到只追加(append-only)存储,供合规审计与追溯。
- 兼作状态回放源 :每条记录携带
loopIteration/checkpoint/decision,支持从任意事件重放会话,天然支撑「沙箱崩溃 → 重建 → 从断点续跑」(事件溯源)。第 4 部分 §4.1.5 埋点闭环由此打通(domain与checkpoint字段已含costUsd,补domain与checkpoint即可)。
3.9 供应链与纵深防御
| 措施 | 实现 |
|---|---|
| 版本锁定 | tool.lock.json 记录 commit SHA / 包版本,禁止浮动 |
| 完整性校验 | 加载前比对 SHA-256,变更即重新门禁 |
| 恶意包识别 | 依赖解析后比对 OSV / GHSA 漏洞库,命中 deny |
| Secret 扫描 | 提交阶段扫描 Skill 目录,发现硬编码密钥即拒绝 |
| 逃逸监控 | seccomp 审计 + 异常 syscall 告警 |
| 最小镜像 | MCP 容器基于 distroless,无 shell |
3.10 参考实现骨架(TypeScript,编排层)
typescript
// licenseGate.ts ------ 许可证门禁核心
type Commercial = 'allow' | 'warn' | 'deny';
const ALLOW = new Set(['MIT','Apache-2.0','BSD-2-Clause','BSD-3-Clause','ISC','Python-2.0','Zlib','Unlicense','CC0-1.0','MS-PL','MPL-2.0']);
const WARN = new Set(['LGPL-2.1','LGPL-3.0','GPL-2.0','GPL-3.0','AGPL-3.0','Fair-code','CC-BY-SA']);
const DENY = new Set(['CC-BY-NC','non-commercial','UNLICENSED']);
export function gateLicense(spdx: string): { status: Commercial; reason: string } {
if (ALLOW.has(spdx)) return { status: 'allow', reason: '宽松许可,保留声明即可' };
if (WARN.has(spdx)) return { status: 'warn', reason: 'copyleft/公平许可,需管理员确认并履行开源/授权义务' };
if (DENY.has(spdx) || !spdx || spdx === 'NOASSERTION')
return { status: 'deny', reason: '非商业或无许可证声明,禁止商用' };
return { status: 'warn', reason: '未分类许可,按条件处理并要求人工核验' };
}
javascript
// loader.ts ------ 加载主流程(伪代码)
async function loadTool(manifest: ToolManifest): Promise<LoadResult> {
const scan = await staticScan(manifest); // 第2关
const tier = scan.risk; manifest.risk = tier;
const gate = gateLicense(await resolveLicense(manifest)); // 第3关
if (gate.status === 'deny') return { ok: false, reason: gate.reason };
if (gate.status === 'warn' && !(await adminAck(manifest.id))) return { ok: false, reason: '需管理员确认' };
const sandbox = await spawnSandbox(manifest, tier); // 第4关(含 regulated→microVM)
registerPolicy(sandbox.id, manifest.permissions); // 第5关 PDP 注册
audit.log({ event: 'load', toolId: manifest.id, license: manifest.license, status: gate.status });
return { ok: true, sandboxId: sandbox.id };
}
3.11 落地里程碑
| 阶段 | 范围 | 交付物 |
|---|---|---|
| M1(MVP) | Manifest 模型 + 静态扫描 + 许可证分类门禁(sync) | 安装即拦截 ❌、提示 ⚠️,列表可筛选 |
| M2 | 进程/FS 隔离(medium tier 全平台;high tier Linux nsjail) | 单工具失控不影响宿主 |
| M3 | egress 防火墙 + 策略引擎 + 审计日志 + secret 注入 | 运行时持续治理、可审计 |
| M4 | 供应链(lock+hash+OSV)、macOS sandbox-exec、成本熔断 | 纵深防御闭环 |
| M5(v2 新增) | Cedar runtime 切换 + regulated microVM + 事件溯源回放 | 形式化验证 + 断点续跑 |
3.12 与第 1/2/4 部分衔接
- ← 第 1 部分:29 场景的工具推荐已标注 ✅/⚠️/❌,本门禁直接消费这些标签作为初始允许列表。
- → 第 2 部分 :本第 5 关 PDP 是「Harness/多 Agent 调度」的工具侧安全底座 ;Harness 在 S1 装配期消费第 2/3 关结论构建能力注册表,Loop 在运行期(S4/S5)每次 Act 前调用 PDP。
- → 第 4 部分 :成本熔断与
costUsd字段为计费模型提供埋点(S5 计量 );金融/数据合规规则在 S4 注入同一 PDP,与许可证门禁共用决策通道。
3.13 默认策略基线(决策裁决 v2)
3.13.1 决策 2 · ⚠️ 类工具授权:TOFU 首次确认 + 范围绑定 + 越界再提示
- 默认 :首次加载时一次性确认,并当场绑定授权范围 (可写目录、可出网域名、可调用能力);此后在范围内静默运行;一旦触及范围外资源或高危动作(写系统目录、外发新域名、涉 secret/付费)再弹二次升级确认。
- 依据 :Claude Code / Cursor 的 "allowlist + escalation" 模式。纯「每次提示」导致 consent fatigue(同意疲劳) ;纯「一次性确认」又过宽。范围绑定 + 越界升级是两者最优折中。
3.13.2 决策 3 · AGPL(guizang):列入 ❌ 排除,用 MIT 工具替代
- 默认 :商用闭源 SaaS 平台默认拒绝 AGPL-3.0 ,用 MIT 的
ppt-master/html-ppt-skill替代 guizang。 - 依据:AGPL 第 13 条(网络交互条款)------只要平台通过网络向用户提供 guizang 功能,即触发「提供服务即需公开对应源码」义务,具备向平台服务端「传染」效应。Google 等大厂内部政策明确禁用 AGPL 即出于此。除非运行在完全隔离、不构成「网络提供服务」的沙箱(平台形态下几乎不成立),否则不值得为单个 PPT 工具承担开源整个服务端的法律风险。
3.13.3 决策 1(隔离档)与决策 4(PDP 选型):见第 2 部分 §2.9
3.13.4 Cedar 策略样例(第 3/5 关的统一表达)
ini
// ---------- 许可证门禁(第3关 / 决策3)----------
forbid (principal == User::"platform", action == Action::"loadTool", resource is Tool)
when { Tool.license in ["AGPL-3.0", "GPL-3.0", "GPL-2.0"] };
forbid (principal == User::"platform", action == Action::"loadTool", resource is Tool)
when { Tool.commercial == "non-commercial" || Tool.license == "UNLICENSED" };
permit (principal == User::"platform", action == Action::"loadTool", resource is Tool)
when { Tool.license in ["MIT","Apache-2.0","BSD-2-Clause","BSD-3-Clause","ISC","MPL-2.0","Unlicense","CC0-1.0"] };
permit (principal == User::"admin", action == Action::"approveWarnTool", resource is Tool);
// ---------- 运行时 PDP(第5关 / 决策2 越界升级)----------
permit (principal == User::"agent", action == Action::"useTool", resource is Tool)
when { Tool.commercial == "warn" && Context.isInApprovedScope == true };
forbid (principal == User::"agent", action == Action::"useTool", resource is Tool)
when { Context.crossesScopeBoundary == true };
// ---------- 隔离分级绑定(决策1 / regulated)----------
permit (principal == User::"agent", action == Action::"spawnSandbox", resource is Tool)
when {
(Tool.risk == "medium" && Context.os == "macos" && Context.sandbox == "sandbox-exec")
|| (Tool.risk == "high" && Context.os == "linux" && Context.sandbox == "nsjail")
|| (Tool.risk == "regulated" && Context.sandbox == "firecracker-microvm")
};
Cedar 支持策略静态分析:可在 CI(S6)中跑「是否存在越权路径」判定,确保任何
permit都不会被意外forbid旁路------这是选 Cedar 而非 OPA 的关键收益。
3.13.5 基线在管道中的落点
| 决策 | 关卡 | 落点 | 可覆盖性 |
|---|---|---|---|
| 决策 1 隔离档 | 第 4 关 | sandboxExecProfile 默认开;regulated→microVM |
可信签名工具降档 |
| 决策 2 TOFU | 第 5 关 | 范围绑定 + 越界升级 | 管理员可改范围 |
| 决策 3 AGPL❌ | 第 3 关 | forbid AGPL 写死 |
不可覆盖(法务红线) |
| 决策 4 Cedar | 第 5 关 | PolicyEngine 后端 |
MVP 自研 → 长期 Cedar |
| 决策 5/6 护栏 | 第 5 关 + Loop | maxTurns/costBudget/humanCheckpoint | 场景可覆盖 |
3.14 【维度补全】沙箱 CVE 实证 + OWASP + MCP EMA
本节约原 Part 3「待确认」部分,用 2026-07 安全实证补全,使隔离决策「有案可稽」。
-
标准容器不足以隔离 LLM 生成代码:容器与宿主共享内核,一处内核漏洞或配置错误即可逃逸。2026 主流四级为 容器(低) / gVisor(中高) / microVM·Firecracker(高) / WASM·V8 Isolates(JS-only 高)。本蓝图 §3.6 四级 + regulated 与之对齐。
-
真实 CVE 教训:
- CVE-2025-59528(CVSS 10.0) :Flowise CustomMCP 未校验用户配置即执行 JS,直连
child_process/fs,12,000+ 暴露实例被攻陷------根因是缺执行沙箱。 - CVE-2025-59536(CVSS 8.7) :Claude Code 配置注入绕过 secure mode。
- 二者均证明:应用层安全控制(system prompt / 审批弹窗)在缺隔离时形同虚设;沙箱是兜底爆炸半径。
- CVE-2025-59528(CVSS 10.0) :Flowise CustomMCP 未校验用户配置即执行 JS,直连
-
OWASP Agentic Top 10 :ASI05(Unexpected Code Execution) 已将沙箱列为强制控制(control,非建议)。
-
Microsoft Agent Governance Toolkit + NVIDIA 沙箱指引 共同收敛到四层强制:网络出口、文件系统边界、secret 作用域、配置文件保护------与本蓝图 §3.6.2--3.6.5 完全一致。
-
Anthropic 实践参照 :claude.ai 服务端用 gVisor(每会话销毁、零本地文件访问、最小爆炸半径);Claude Code 本地用 macOS Seatbelt / Linux bubblewrap,并开源
anthropic-experimental/sandbox-runtime(文件默认仅写 cwd、网络仅经 proxy 白名单)。OpenAI Agents SDK 2026-04 原生 Sandbox 类(容器 + 文件系统快照 + 可恢复状态)。 -
MCP 安全新前沿(2026) :MCP 2026-07 RC 引入 EMA(Enterprise-Managed Authorization,跨应用访问) ------把身份变成集中治理平面(Okta 主导),解决多 connector 的 scope 最小化与审计;并提出 MCP Apps (工具返回交互式 UI 而非仅 JSON)、Tasks(长任务原语)。本蓝图门禁的 PDP + egress 白名单 + 审计,可平滑升级对接 EMA,作为企业托管授权的落点(详见 §5.7)。