Skip to content

01 · 系统总体方案 ​

文档定位:本文件是全套开发文档的总纲,给出系统的分层架构、组件职责、数据流、安全边界与关键设计取舍。其余文档均从本文件展开。

关联文档:CONTEXT.md(领域词汇)、docs/02-安全管控插件层设计.md、docs/03-Agent层设计-OpenClaw二次开发.md、docs/04-MCP安全网关设计.md、docs/05-数据库设计.md、docs/06-Web前端设计.md、docs/07-STM32边缘终端设计.md、docs/08-部署与运维.md、docs/09-原型验证方案.md、docs/10-答辩问答手册.md、docs/adr/


1. 课题定位与研究问题 ​

1.1 业务背景 ​

工业设备的非计划停机代价高昂。预测性运维(Predictive Maintenance)通过持续采集设备温度、振动等状态量,结合故障知识库与专家经验,在故障发生前给出预警与检修建议。

大模型驱动的 AI Agent 具备"读手册 + 看数据 + 写结论"的完整能力,天然适合这一场景。但把它放进工业现场,会遇到一个绕不开的问题:

Agent 越权。 一旦 Agent 通过提示注入或幻觉去读取了它不该读的数据(账号、审计日志、工单、其他产线的数据),工业系统面临的是合规与生产安全问题,而不是"回答得不准"。

1.2 本课题的研究问题 ​

不是"能否让 Agent 做故障诊断"——那是已有答案的问题。

而是:

在一个真实的、基于开源框架二次开发的 Agent 系统上,如何设计并实现一层安全管控,使 Agent 的行为边界可约束、可审计、可复现?

本课题的主要实现部分是安全管控插件层,它必须与 Agent 内核、数据存储、边缘终端形成完整的、可运行的、可被验证的原型。

1.3 三条设计主线 ​

主线内容对应文档
边界Agent 与业务数据之间不存在任何通路(双库分离 + 唯一出口)01 / 04 / 05
管控每一次工具调用都被拦截、判定、裁剪、审计02 / 03
验证用真实硬件终端 + 反证实验证明边界成立07 / 09

2. 系统分层架构 ​

2.1 总体分层图 ​

┌─────────────────────────────────────────────────────────────────────┐
│ 【前端层】Vue3 + TypeScript Web 管理界面(工程师人机界面)              │
│   设备看板 │ 数据曲线 │ Agent 分析报告 │ 审计日志 │ 工单 │ RBAC 管理     │
└───────────────────────────┬─────────────────────────────────────────┘
                            │ HTTPS(JWT)
                            ▼
┌─────────────────────────────────────────────────────────────────────┐
│ 【后端服务层】Node.js + TypeScript                                    │
│                                                                      │
│  ┌────────────────────────┐        ┌──────────────────────────────┐ │
│  │ 业务接口服务            │        │ ★ MCP 安全网关(独立服务)    │ │
│  │ business-api           │        │   —— 系统安全边界 ——          │ │
│  │ · 账号 / RBAC          │        │ · 统一入口(Agent + 人类)     │ │
│  │ · 设备 / 工单 CRUD      │        │ · JWT / 设备令牌身份解析       │ │
│  │ · 审计日志查询          │        │ · 安全策略校验                 │ │
│  │ · 报告展示              │        │ · 字段白名单裁剪               │ │
│  └───────────┬────────────┘        │ · 审计落库(fail-closed)      │ │
│              │                     └───────┬───────────┬──────────┘ │
└──────────────┼─────────────────────────────┼───────────┼────────────┘
               │                             │           │
               │ 全量 CRUD                    │ 只读检索   │ 受限读
               ▼                             ▼           ▼
      ┌──────────────────┐          ┌────────────┐  ┌──────────────────┐
      │  business-db     │          │   ai-db    │  │ MQTT Broker      │
      │  账号/RBAC        │          │ 向量切片    │  │ (Mosquitto)      │
      │  遥测/工单/设备    │          │ 会话记忆    │  └────────┬─────────┘
      │  审计日志/报告     │          └────────────┘           │
      └──────────────────┘                                    │ MQTT
              ▲                                               ▼
              │                                  ┌────────────────────────┐
              │                                  │ 【终端层】STM32        │
              │                                  │  + FreeRTOS + MQTT     │
              │                                  │  温度 / 振动 只上报     │
              │                                  └────────────────────────┘
              │
              │ 网关写入遥测与审计
              │
┌─────────────┴───────────────────────────────────────────────────────┐
│ 【Agent 智能体层】OpenClaw 二次开发                                   │
│  ┌────────────────────────────────────────────────────────────────┐ │
│  │ ★ 安全管控插件层(本课题主要实现部分,OpenClaw 原生插件)          │ │
│  │   api.on(...) 类型化钩子 → 策略引擎 → 参数改写 → 脱敏 → 审计上报   │ │
│  └────────────────────────────────────────────────────────────────┘ │
│  · Agent 内核:ReAct 推理循环                                        │
│  · 可插拔 Skill:故障分析 Skill、知识库检索 Skill                     │
│  · ⚠ 无任何数据库直连账号;无任何 MQTT 凭证                            │
│  · 所有数据获取 → 调用 MCP 网关工具接口                                │
└─────────────────────────────────────────────────────────────────────┘

2.2 组件职责表 ​

组件进程职责持有凭证对应包
Web 前端浏览器工程师操作界面、报告与曲线展示、审计查询无(仅 JWT)apps/web
业务接口服务独立 Node 进程面向人类的业务 CRUD,操作 business-dbBUSINESS_DB_URL、JWT 私钥packages/business-api
MCP 安全网关独立 Node 进程系统唯一对外数据出口;身份解析、策略校验、字段裁剪、审计落库BUSINESS_DB_URL、AI_DB_URL、MQTT 凭证、JWT 公钥packages/mcp-gateway
安全管控插件层OpenClaw 进程内工具调用拦截、策略判定、参数改写、脱敏、审计上报、配额仅 Agent 令牌 + 网关地址packages/security-plugin
Agent 内核OpenClaw Gateway 进程ReAct 推理循环、Skill 调度、会话与记忆同上packages/agent-config / OpenClaw 本体
共享契约编译期MCP 工具契约、DTO、策略枚举无packages/shared-contracts
MQTT BrokerMosquitto终端上行、指令下行—deploy/mosquitto
边缘终端STM32采集温度/振动,MQTT 上报,被动接收指令Broker 一机一密凭证firmware/stm32-sensor-node

3. 核心安全设计:双库分离 + 唯一出口 ​

3.1 问题:为什么"数据库只读账号"不够 ​

给 Agent 分配一个只读数据库账号,看似解决了越权写的问题,但它只约束了读写动作,没有约束访问范围:

sql
-- 只读账号完全允许执行
SELECT username, password_hash, email FROM user_account;
SELECT * FROM audit_log ORDER BY ts DESC LIMIT 1000;

提示注入一旦成功,Agent 就可以把审计日志读出来、把账号列表读出来。日志上看起来只是"一条合法的 SELECT"。

3.2 本系统的做法:让 Agent 拿不到凭证 ​

关键不变量:Agent 进程的环境变量中不存在 BUSINESS_DB_URL、AI_DB_URL、MQTT_URL 中的任何一个。

❌ 错误模式(绝对禁止)
   Agent ──SQL──► business-db
   Agent ──MQTT──► Broker(订阅 iot/+/telemetry)

✅ 本系统模式
   Agent ──MCP 工具调用──► MCP 安全网关 ──► business-db / ai-db / Broker
                            (鉴权 + 裁剪 + 审计)

Agent 拿到的只是网关裁剪过的精简数据:

ts
// packages/mcp-gateway/src/tools/mqtt.read_sensor.ts(示意)
export async function tool_read_sensor_data(params: ReadSensorParams) {
  // 1) 策略校验:该 Agent 是否被授权访问该设备
  await policy.assertDeviceScope(ctx.agentId, params.deviceId);

  // 2) 网关以自身凭证访问业务数据库(Agent 侧没有这个凭证)
  //    注意:库里是窄表(metric / value 一行一指标),返回前由网关透视成宽表
  const rows = await businessDb.query(
    `SELECT metric, value, ts FROM sensor_data
      WHERE device_id = ? AND ts BETWEEN ? AND ?
      ORDER BY ts ASC LIMIT ?`,
    [params.deviceId, params.from, params.to, params.limit]
  );

  // 3) 透视 + 字段白名单裁剪:只返回故障分析必需的三个字段
  const simpleData = pivotByTs(rows).map((r) => ({
    temp: r.temperature,        // 单位 ℃
    vibration: r.vibration,     // 单位 mm/s
    time: r.ts,
  }));

  // 4) 审计(fail-closed:落库失败则本次调用失败)
  await audit.record({ tool: 'mqtt.read_sensor', params, rowCount: rows.length });

  return simpleData;
}

Agent 看不到 sensor_data 表的其他列(内部序列号、校准系数、产线编码),也无法执行任意 SQL。

存储形态与返回形态的分离是这里的关键设计:数据库里存什么形状是存储问题(窄表便于扩展指标),Agent 看到什么形状是接口契约与最小权限问题。两者解耦后,Agent 无法通过构造参数去查其他 metric,更无法查其他表。

3.3 双库权限矩阵 ​

角色business-dbai-dbMQTT Broker
Web 前端无直连无无
业务接口服务完整 CRUD无无
MCP 安全网关受限读 + 审计写 + 遥测写只读订阅 + 受限发布
Agent / 安全管控插件层无账号,零权限无账号,零权限无凭证
边缘终端无无仅自身主题

3.4 双库分离的两大收益 ​

收益说明可验证方式
边界隔离Agent 与业务敏感数据之间不存在通路。提示注入即便完全成功,Agent 能做的也只是"多调用几次工具",无法读取账号、审计、工单在 Agent 进程内尝试连接 business-db,观察凭证缺失导致的连接失败
故障域隔离Agent 或 ai-db 崩溃、索引重建、被拖垮时,business-db 与业务接口服务不受影响,业务系统独立可用停掉 Agent 与 ai-db,验证 Web 界面仍可查询设备、曲线、审计

4. 关键数据流 ​

4.1 遥测上行链路 ​

STM32 采集(温度/振动) → 特征粗筛 → MQTT publish iot/{id}/telemetry (QoS1)
   → Mosquitto → 网关订阅 → 校验 deviceId + 一机一密 → 批量写入
   → business-db.sensor_data

网关是唯一的订阅方。Agent 侧不部署 MQTT 客户端。

4.2 Agent 诊断链路(含安全管控) ​

① 工程师在 Web 界面发起"分析 3 号设备振动异常"
      └─► business-api 落一条任务记录 → 触发 Agent(带工程师身份与任务上下文)

② Agent 进入 ReAct 循环
      ├─ Thought: 需要该设备近 1 小时的振动数据
      ├─ Action: mqtt.read_sensor({deviceId, from, to})
      │     │
      │     └─► 【安全管控插件层】api.on(tool-call) 拦截
      │            · 参数校验:deviceId 是否在授权范围
      │            · 行为约束:本会话工具调用配额是否超限
      │            · 注入检测:参数是否含可疑载荷
      │            · 判定:ALLOW / DENY / REWRITE(收窄时间窗口)
      │            · 上报审计(含判定结果)
      │
      └─► 【MCP 安全网关】执行
             · 身份解析(Agent 令牌 → agentId + sessionId)
             · 策略二次校验(不信任插件层的判定,独立复核)
             · 查询 business-db → 字段白名单裁剪 → 落审计 → 返回

③ Agent 继续推理
      ├─ Action: kb.search({query: "轴承外圈磨损 振动特征"})
      │     └─► 同上经插件层 + 网关 → 网关只读检索 ai-db
      ├─ 综合遥测数据与手册知识,形成诊断结论
      └─ Action: report.write({...})
            └─► 经插件层脱敏(去除内部字段)→ 网关 → business-db.agent_report

④ 工程师在 Web 界面查看报告(含 ReAct 链路与每一步的审计 traceId)

注意:插件层与网关都做策略校验,不是冗余。插件层能看到会话上下文("这次调用与当前任务是否相关"),网关能强制凭证边界("Agent 根本没有别的路可走")。这是纵深防御的两层,见 ADR-0004。

4.3 审计写入链路(fail-closed) ​

任意一次工具调用(无论放行/拒绝/改写)
   → 生成 traceId
   → 写入 business-db.audit_log
   → 若写入失败 ⇒ 本次调用判定为失败,不返回数据

审计表是系统唯一的"数据访问事实来源"。不允许只在插件内打日志而不落库。


5. 技术选型汇总 ​

层选型版本/形态理由备选
前端Vue3 + TypeScript + Vite—组合式 API + 强类型,工程化成熟React(团队熟悉度更低)
UI 组件Element Plus / Naive UI—表格、表单、树形权限选择器现成Ant Design Vue
图表ECharts—时序曲线与仪表盘能力成熟,中文文档好Chart.js
后端语言Node.js + TypeScriptNode 24.15+与 OpenClaw 同语言,可共享契约类型Go(无法共享类型)
网关接口MCP 协议—标准工具调用协议,降低框架锁定REST(见 ADR-0002)
Agent 框架OpenClaw原生插件 + 类型化钩子扩展机制与课题需求对齐见 ADR-0003
business-dbSQLite → PostgreSQL原型 / 落地零运维演示 → 强制访问控制见 ADR-0006
ai-dbChroma / Qdrant本地持久化向量检索开箱即用pgvector
消息MQTT (Mosquitto)QoS 1工业物联网事实标准,遗嘱消息与低带宽友好HTTP 上报(见 ADR-0005)
终端STM32 + FreeRTOS见 07真实硬件,答辩可信度高纯软件模拟(说服力弱)
工具链NVM → PNPM → PM2—见 ADR-0007Docker Compose(演示依赖高)

6. 模块清单与目录映射 ​

模块路径文档
MCP 安全网关packages/mcp-gateway/docs/04
安全管控插件层packages/security-plugin/docs/02
Agent 配置与 Skillpackages/agent-config/docs/03
业务接口服务packages/business-api/docs/05、docs/06
共享契约packages/shared-contracts/docs/04
Web 管理界面apps/web/docs/06
边缘终端固件firmware/stm32-sensor-node/docs/07
部署编排deploy/docs/08

7. 系统关键不变量(Invariants) ​

这七条是本系统设计成立的前提,任何改动若违反其中一条,必须显式标注并重新走 ADR 流程。

#不变量违反后果
I1Agent 进程环境变量中不存在 BUSINESS_DB_URL双库分离失效,边界隔离不成立
I2Agent 进程环境变量中不存在 AI_DB_URL"所有访问经网关"出现例外
I3Agent 不持有任何 MQTT 凭证越权订阅其他设备数据,审计出现盲区
I4每次工具调用必落审计,落库失败即调用失败审计链条断裂,事后无法追溯
I5网关返回载荷只含字段白名单内的键最小权限落空
I6ai-db 中不存在业务敏感字段双库分离退化为命名约定
I7下行控制指令必须经网关鉴权与审计Agent 可直接影响生产设备

8. 原型验证的验收目标 ​

完整验证方案见 docs/09-原型验证方案.md,此处给出总体验收口径:

维度验收标准
功能闭环从终端上报 → 网关入库 → Agent 诊断 → 报告展示 → 审计可查,端到端跑通
边界成立(反证)在 Agent 进程内尝试直连 business-db / ai-db / MQTT 均失败,且失败原因可解释为"凭证不存在"
管控生效构造越权调用(访问未授权设备、超配额、参数注入),插件层 DENY 且审计有记录
裁剪生效对比网关返回载荷与数据库原始行,证明敏感字段被剥离
故障域隔离停止 Agent 与 ai-db,Web 端设备查询、曲线、审计查询仍正常
可复现按 docs/08-部署与运维.md 的步骤,在干净机器上可重复搭建成功

9. 本文档的边界 ​

本文件只给出总体方案。以下内容不在此展开:

  • 插件层的钩子清单与策略引擎实现 → docs/02
  • OpenClaw 二次开发的具体改造点与 Skill 实现 → docs/03
  • MCP 工具的完整契约(入参/出参/错误码) → docs/04
  • 表结构与 DDL → docs/05
  • 部署脚本与 PM2 配置 → docs/08
  • 答辩问答预演 → docs/10