当 Agent 要动手了:工业实时控制的三层安全护栏设计

37 阅读4分钟

Agent 能诊断、能开工单,但如果它突然说「建议立即停机」呢?工业场景下,Agent 的每个「动作」都可能影响生产线。三层护栏——输入过滤、输出审核、操作拦截——是 Agent 上产线的安全底线。


问题:Agent 的输出不可预测

LLM 的本质是概率模型——你无法保证它的输出 100% 安全。在工业场景下:

  • 输入注入——恶意用户构造特殊提示词,让 Agent 执行危险操作
  • 输出泄露——Agent 可能在回复中暴露 API Key、数据库密码
  • 操作越权——Agent 建议「立即停机」,但它不应该有停机权限

护栏不是限制 Agent 的能力,而是限制它犯错的半径。


三层护栏架构

用户输入 → [InputGuard] → Agent 推理 → [OutputGuard][ActionGuard] → 最终输出
                                                              ↓
                                                    L3/L4 → 需人工审批
                                                    L0-L2 → 直接执行
职责拦截什么
InputGuard输入过滤危险指令、超长输入、SQL 注入
OutputGuard输出审核敏感信息泄露、危险 SQL
ActionGuard操作分级高风险操作需审批

第一层:InputGuard

@Component
public class InputGuard {
    private static final List<Pattern> BLOCKED = List.of(
        Pattern.compile("(?i)(删除|drop|truncate).*数据库"),
        Pattern.compile("(?i)(rm\\s+-rf|format|fdisk)"),
        Pattern.compile("(?i)ignore.*safety|bypass.*guard")
    );

    public GuardResult check(String input) {
        if (input.length() > 2000) return GuardResult.blocked("输入超长");
        for (Pattern p : BLOCKED) {
            if (p.matcher(input).find()) return GuardResult.blocked("危险指令");
        }
        return GuardResult.passed();
    }
}

拦截原则:宁可误拦,不可漏放。 误拦了用户可以重新表述,漏放了可能损坏设备。


第二层:OutputGuard

@Component
public class OutputGuard {
    private static final List<Pattern> SENSITIVE = List.of(
        Pattern.compile("(?i)(api.?key|密码|password|secret)\\s*[:=]\\s*\\S+"),
        Pattern.compile("(?i)(DROP\\s+TABLE|DELETE\\s+FROM)")
    );

    public GuardResult check(String output) {
        for (Pattern p : SENSITIVE) {
            if (p.matcher(output).find()) return GuardResult.blocked("输出含敏感信息");
        }
        return GuardResult.passed();
    }
}

LLM 有时会在回复中输出训练数据中的敏感信息。OutputGuard 在回复发给用户之前做最后一道检查。


第三层:ActionGuard

@Component
public class ActionGuard {
    public RiskLevel classifyRisk(String action) {
        if (action.matches(".*停机|关机|shutdown.*")) return RiskLevel.L3;
        if (action.matches(".*修改参数|调整阈值.*"))  return RiskLevel.L3;
        if (action.matches(".*创建工单.*"))           return RiskLevel.L2;
        if (action.matches(".*诊断|分析.*"))          return RiskLevel.L1;
        return RiskLevel.L0;
    }
}

风险分级:

级别操作处理
L0查询数据、告警直接执行
L1诊断分析直接执行
L2创建工单执行后通知
L3停机、修改参数需人工审批
L4紧急停机需双人审批

熔断器:连续失败时降级

Agent 连续 3 次出错(工具调用失败、LLM 超时等),熔断器开启,暂时阻止新请求:

@Component
public class CircuitBreaker {
    enum State { CLOSED, OPEN, HALF_OPEN }

    private static final int FAILURE_THRESHOLD = 3;
    private static final long RECOVERY_MS = 60_000;  // 1 分钟后尝试恢复

    public boolean isAllowed() {
        if (state == CLOSED) return true;
        if (state == OPEN && elapsed > RECOVERY_MS) {
            state = HALF_OPEN;  // 允许一个测试请求
            return true;
        }
        return state == HALF_OPEN;
    }
}

状态流转:

CLOSED(正常)→ 连续3次失败 → OPEN(熔断)→ 60s后 → HALF_OPEN → 成功 → CLOSED
                                                              → 失败 → OPEN

熔断期间返回:「Agent 暂时不可用,请稍后重试或联系值班工程师」。


GuardrailChain:串联三层护栏

@Component
public class GuardrailChain {

    public GuardResult checkInput(String input) {
        if (!circuitBreaker.isAllowed()) {
            return GuardResult.blocked("熔断器开启,Agent 暂时不可用");
        }
        return inputGuard.check(input);
    }

    public GuardResult checkOutput(String output) {
        return outputGuard.check(output);
    }

    public GuardResult checkAction(String action) {
        return actionGuard.check(action);
    }
}

每次检查都写审计日志(谁、什么时间、什么操作、通过/拦截),事后可追溯。


API 接口

# 检查输入安全性
POST /api/guardrail/check-input
{"input": "删除数据库所有记录"}
→ {"passed": false, "reason": "检测到危险指令"}

# 检查操作风险等级
POST /api/guardrail/check-action
{"action": "CNC-001 立即停机"}
→ {"passed": false, "riskLevel": "L3", "reason": "高风险操作需人工审批"}

# 查看护栏状态
GET /api/guardrail/status
→ {"circuitBreaker": "CLOSED", "auditLogSize": 15}

# 审计日志
GET /api/guardrail/audit

护栏 vs 提示词约束

提示词约束代码护栏
实现SystemMessage 中写「不要...」Java 正则 + 规则
可靠性LLM 可能忽略100% 执行
可审计不可每次拦截有日志
适合软性引导硬性安全底线

两者互补,不能互替。 提示词约束是「建议」,代码护栏是「法律」。


代码仓库:github.com/LaoLiang-ag…


本文由 LaoLiang 原创,首发于掘金/知乎/微信公众号。转载请联系作者。