news 2026/8/27 18:53:52

生产级Agent(22):策略即代码与Policy Simulation

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
生产级Agent(22):策略即代码与Policy Simulation

文章摘要

前二十一篇已经把生产级 Agent 的运行、权限、审计、回放、SLO 和多租户隔离逐层搭起来。

到了这一阶段,平台已经有越来越多“规则”:

哪些模型能用 哪些Tool能调 哪些租户能访问哪些数据 什么动作需要审批 什么情况下要Fail Closed 哪个Artifact允许外发 哪个Sandbox可以联网 Error Budget烧到多少要冻结发布

如果这些规则散落在:

System Prompt Java if/else 数据库配置 管理员后台 Kubernetes YAML 审批流程

真正出问题时,团队很难回答:

当时为什么允许? 哪条规则生效? 如果改规则,会影响多少Run? 这次Policy变更会不会把某个租户直接打挂?

所以 Agent Control Plane 下一步必须把“规则”从业务代码里抽出来,变成:

Policy-as-Code

再进一步,在真正生效前运行:

Policy Simulation

也就是拿历史真实 Run、当前配置和候选规则做离线重放,先看“如果昨天就用了新规则,会发生什么”。

这一篇直接把策略模型、版本、决策日志、影子评估、Impact Analysis、Historical Replay、Canary、Break Glass 和发布门禁串成一套。


一、为什么Agent平台特别容易Policy爆炸

一个普通 API 权限可能只是:

Role → Permission

Agent 决策通常同时看:

User Tenant Agent Purpose Capability Resource Data Class Risk Approval Model Region Budget Time

例如:

legal-agent

想调用:

document.export

真正决策可能是:

用户属于Matter吗? Artifact是不是Privileged? 目标是不是外部邮箱? 当前租户允许外发吗? 是否有审批? 审批绑定的Action Hash一致吗?

如果全部写在一个 Service 里:

if(...){if(...){if(...){}}}

半年后没人敢改。

二、Policy首先必须独立版本化

定义:

publicrecordPolicyBundle(StringpolicyId,Stringversion,StringcontentHash,PolicyStatusstatus,InstantcreatedAt,StringcreatedBy){}

状态:

publicenumPolicyStatus{DRAFT,VALIDATED,SHADOW,CANARY,ACTIVE,RETIRED}

不要允许:

编辑ACTIVE Policy并原地保存

每次修改都生成新版本。

三、Policy输入必须结构化

不要把整个 Prompt 丢给另一个 LLM:

“你觉得这次允许吗?”

真正 Policy 输入应该是确定性对象。

publicrecordPolicyInput(StringtenantId,StringsubjectId,StringagentId,Stringpurpose,Stringcapability,StringresourceId,DataClassdataClass,RiskLevelrisk,StringmodelId,Stringregion,StringapprovalId,BigDecimalestimatedCost){}

模型可以帮助提取 Purpose。

最终 Policy 不直接依赖自然语言。

四、Decision至少不是boolean

publicenumPolicyDecision{ALLOW,DENY,REQUIRE_APPROVAL,REQUIRE_STRONG_AUTH,REQUIRE_HUMAN_REVIEW}

生产系统里:

允许 / 禁止

通常太粗。

例如:

email.send

可以允许,但需要:

Action-bound Approval

这就不是 DENY。

五、Decision还必须给出Reason Code

publicrecordPolicyResult(PolicyDecisiondecision,List<String>reasonCodes,StringpolicyId,StringpolicyVersion,StringinputHash){}

例如:

{"decision":"DENY","reasonCodes":["CROSS_TENANT_RESOURCE","EXTERNAL_EGRESS_BLOCKED"],"policyVersion":"v42"}

以后排障不需要重新猜。

六、Policy定义最好声明输入和输出

例如 YAML:

policy:external-sendversion:v42match:capability:-email.send-messages.sendrules:-when:data_class:RESTRICTEDdestination:EXTERNALdecision:DENYreason:restricted_external_egress-when:risk:HIGHdecision:REQUIRE_APPROVAL-otherwise:decision:ALLOW

真实实现可以使用:

OPA/Rego Cedar 自研DSL

关键不是语言。

关键是:

Policy是数据和代码资产

而不是散落逻辑。

七、Policy-as-Code必须进Git

目录:

policies/ ├── model/ ├── capability/ ├──>policies/data-egress/external-send-v42.yaml

每次变更:

PR → Review → CI → Simulation → Canary → Active

和代码发布一样。

八、Policy CI第一层:Schema Validation

最简单但必须有。

例如:

Decision拼错 Reason缺失 Risk Enum非法

直接在 CI 拒绝。

policy_ci:schema_validation:requiredduplicate_rule_check:requiredunreachable_rule_check:required

九、第二层:Static Conflict Detection

两个规则:

Rule A: HIGH → DENY Rule B: HIGH → ALLOW

如果优先级没有明确:

Policy本身就不确定

CI 要发现:

Overlapping Rules Conflicting Outcome

十、第三层:Golden Policy Tests

每条高风险 Policy 都要有固定测试。

例如:

cases:-name:restricted_external_sendinput:data_class:RESTRICTEDdestination:EXTERNALexpect:DENY-name:high_risk_sendinput:data_class:INTERNALrisk:HIGHexpect:REQUIRE_APPROVAL

Policy 修改后自动回归。

十一、但Golden Case远远不够

真正危险的是:

规则本身看起来对 但对真实流量影响巨大

例如:

新的Region Policy

可能误伤 30% 客户。

所以需要:

Policy Simulation

十二、Simulation到底模拟什么

候选:

policy-v43

不要立刻 Active。

拿过去 7 天真实 Decision Input:

100万条

重新评估:

Current Policy v42 vs Candidate v43

然后比较:

Decision Diff

十三、Simulation不需要重跑LLM

Policy 输入已经结构化。

所以只重放:

Decision Input

而不是整个 Agent Run。

成本非常低。

数据模型:

publicrecordPolicySimulationCase(StringdecisionId,PolicyInputinput,PolicyResultbaseline,PolicyResultcandidate){}

十四、最核心指标:Decision Flip

ALLOW → DENY DENY → ALLOW ALLOW → REQUIRE_APPROVAL REQUIRE_APPROVAL → ALLOW

这四种变化风险完全不同。

十五、我会给Flip分类

publicenumDecisionFlipType{MORE_RESTRICTIVE,LESS_RESTRICTIVE,APPROVAL_ADDED,APPROVAL_REMOVED,NO_CHANGE}

尤其:

DENY → ALLOW

必须重点 Review。

因为它在扩大权限面。

十六、Simulation报告至少输出

{"baseline":"v42","candidate":"v43","total_cases":1000000,"changed":18291,"more_restrictive":17200,"less_restrictive":1091,"approval_added":8200,"approval_removed":91}

单看:

changed=1.8%

不够。

必须知道变化方向。

十七、还要按Slice看

总体只变化 1%。

但:

Legal Tenant: 变化 38%

就很危险。

Slice 至少:

Tenant Tier Risk Capability Data Class Agent Region

十八、不要全组合Slice

否则样本爆炸。

只看业务关键:

HIGH_RISK RESTRICTED_DATA EXTERNAL_SEND FINANCE LEGAL

这些 Slice 单独 Gate。

十九、Simulation要计算影响业务对象

不只是 Decision 数。

还要:

涉及多少用户? 多少Agent? 多少Tenant? 多少Scheduled Task? 多少关键Workflow?

例如:

{"tenants_impacted":39,"agents_impacted":112,"critical_workflows_impacted":4}

这才方便 Release Review。

二十、Policy Input必须长期可回放

每次生产 Decision 都保存:

input_hash policy_version decision reason

完整 Input 可以加密保存。

例如:

publicrecordPolicyDecisionRecord(StringdecisionId,StringrunId,StringtenantId,StringinputRef,StringinputHash,StringpolicyVersion,PolicyDecisiondecision,List<String>reasons,InstantoccurredAt){}

没有历史输入,就无法真正 Simulation。

二十一、Privacy要注意

Policy Input 可能包含:

Resource ID Subject Tenant Data Class

不一定要保存原始业务内容。

策略评估应该尽量依赖:

Metadata

而不是完整 Prompt。

这也会让 Simulation 更安全。

二十二、Shadow Policy

Simulation看的是历史。

下一步:

Shadow

Candidate v43 在真实线上请求中同时计算:

但不执行
Active v42: 真正决定 Shadow v43: 只记录结果

二十三、Shadow可以发现历史数据没覆盖的新模式

比如上线后出现:

新Capability 新Tenant类型 新Region

Simulation 数据里根本没有。

Shadow 能看到。

二十四、Shadow结果不能影响用户

即使 Candidate:

DENY

只记录。

不要在 Shadow 阶段偷偷改变:

Latency Approval Tool

否则不是真 Shadow。

二十五、Shadow Metrics

policy_shadow_total policy_shadow_flip_total policy_shadow_less_restrictive_total policy_shadow_error_total

再看:

Evaluation Latency

Policy 本身也不能把 Agent Tool Call 拖慢几百毫秒。

二十六、Policy性能也有SLO

例如:

P95 Decision < 20ms P99 < 50ms

如果 Candidate 正确但慢 10 倍:

不能直接上线

二十七、Canary Policy

Shadow 没问题以后:

1% 5% 20% 100%

真实执行。

Canary Key 可以按:

Tenant Workspace Agent

稳定分配。

不要每个请求随机,这会让同一个用户体验来回变化。

二十八、高风险Tenant不要自动进入Canary

例如:

Legal Finance Critical Production

可以最后再进。

先从:

内部Tenant 测试Tenant 低风险Agent

开始。

二十九、Policy发布要有Risk Classification

publicenumPolicyChangeRisk{LOW,MEDIUM,HIGH,CRITICAL}

比如:

修改Reason文字 → LOW 增加Approval → MEDIUM DENY变ALLOW → HIGH 跨租户访问放开 → CRITICAL

风险越高,发布门禁越严格。

三十、自动判断Risk可以靠Diff

例如:

- decision: DENY + decision: ALLOW

自动:

HIGH

如果涉及:

cross_tenant restricted_data

直接:

CRITICAL

三十一、Policy Diff应该像数据库Migration一样严肃

Review 页面不要只展示整个 YAML。

应该直接告诉 Reviewer:

新增3条 删除1条 Decision扩大91个历史Case 影响4个Critical Workflow

这比手工读文件强太多。

三十二、一个Release Gate

policy_release_gate:schema:passgolden_tests:pass_rate:1.0simulation:less_restrictive_critical:0changed_ratio_max:0.05shadow:error_rate_max:0.001latency:p95_ms:20approvals:high:securitycritical:-security-platform_owner

三十三、Policy不能只管Security

同一套机制还可以管理:

Model Routing Cost Budget Release Fallback Autonomy

例如:

when:error_budget_remaining_lt:0.20decision:BLOCK_RELEASE

这也是 Policy。

三十四、Model Policy也非常适合Simulation

比如昨天那种 Copilot Global Model Policy。

企业准备:

默认Enabled →默认Disabled

先跑 Simulation:

哪些Agent会失去Primary Model? 哪些Fallback也不可用? 哪些自动化会停止?

再改。

三十五、Capability Policy也适合

准备禁掉:

shell.exec

先看过去 30 天:

多少Agent使用? 哪些是Critical Path? 有没有替代Capability?

不是直接关。

三十六、Data Egress Policy更需要Simulation

准备新增:

CONFIDENTIAL 禁止外部Email

这可能影响大量销售 Workflow。

Simulation 告诉你:

过去7天本来会拦多少次

业务 Owner 可以提前调整。

三十七、Policy Exception必须单独建模

现实里总会有:

这个租户临时例外

不要去改主 Policy。

定义:

publicrecordPolicyException(StringexceptionId,StringpolicyId,StringtenantId,StringsubjectId,StringresourcePattern,Stringreason,StringticketId,InstantexpiresAt,StringapprovedBy){}

异常一定要:

有期限 有理由 有审批

三十八、Exception不能无限续

例如:

30天

到期重新 Review。

如果连续续 6 次:

说明主Policy可能不适合

应该进入治理分析。

三十九、Break Glass和Exception不是一回事

Exception:

事先批准

Break Glass:

事故紧急访问

Break Glass 需要更强:

MFA 短TTL 强审计 实时告警 自动撤销

四十、Break Glass仍然走Policy

不要写:

if breakGlass: return ALLOW

而是:

特殊Policy

检查:

Incident ID Approver TTL Scope

四十一、Policy Engine失败怎么办

这是一个非常重要的问题。

如果权限 Policy 服务挂了:

写操作怎么办?

高风险:

Fail Closed

低风险、且有短期签名缓存:

可以有限Fail Open

但必须明确。

四十二、Fail Mode也是Policy

policy_failure:destructive:mode:fail_closedexternal_write:mode:fail_closedinternal_read:mode:signed_cachemax_age:30s

不要等事故时现场讨论。

四十三、缓存Policy Decision要带Version

Key:

tenant agent purpose capability resource_class policy_version

Policy v42 → v43:

缓存自动失效

否则新规则上线后旧 Decision 还能活很久。

四十四、紧急撤权要跳过普通Cache

Security 触发:

Emergency Deny

应该进入:

Global Revocation Layer

优先于普通 Policy Cache。

例如:

disable capability=email.send

立即生效。

四十五、Policy决策链要可解释

最终结果可能来自:

Tenant Policy + Enterprise Policy + Exception + Emergency Deny

Audit 要保存:

Decision Trace

四十六、Decision Trace示例

{"final":"DENY","steps":[{"policy":"enterprise-egress-v42","result":"ALLOW"},{"policy":"tenant-legal-v18","result":"REQUIRE_APPROVAL"},{"policy":"emergency-deny-v3","result":"DENY"}]}

这比一个:

403

可解释太多。

四十七、Policy优先级必须固定

例如:

Emergency Deny > Tenant Restriction > Enterprise Base > Exception

但 Exception 是否能覆盖 Tenant Restriction,要明确。

我一般建议:

Exception只能放宽可放宽的Policy

不能覆盖:

Zero Tolerance Cross Tenant Legal Hold

四十八、Policy层级不要动态由模型决定

模型不能说:

“这个情况特殊,我认为Exception优先。”

优先级是确定性系统规则。

四十九、Policy Simulation还可以做“反事实事故分析”

发生事故:

某个Agent错误外发

你准备新 Policy:

v44

可以拿事故 Run:

Replay Input

问:

如果当时是v44, 会不会挡住?

这就是非常直接的 Regression Evidence。

五十、每个事故最终应该沉淀Policy Regression Case

例如:

incident:INC-2026-081input:data_class:CONFIDENTIALdestination:EXTERNALcapability:email.sendexpected:decision:DENY

以后任何 Policy Candidate 都跑。

五十一、Policy Dataset不要只来自事故

还要有:

Normal Cases Edge Cases Synthetic Cases Abuse Cases

否则 Policy 会过拟合历史事故。

五十二、Property-based Policy Test

例如不变量:

任何CrossTenant Resource 永远不能ALLOW

随机生成:

Tenant A Tenant B Resource Capability

断言:

assertNotEquals(PolicyDecision.ALLOW,evaluate(crossTenantInput));

这比只写几个固定样例强。

五十三、Policy Coverage也要统计

有多少生产 Decision:

命中了显式规则

多少落到:

default

如果:

default hit = 60%

说明 Policy 设计过于粗糙。

五十四、我会看Default Decision Rate

default_decision_total / all_policy_decisions

目标应该逐步下降。

特别是高风险 Capability:

最好0%

每种情况都有显式规则。

五十五、Unknown Input不能默认Allow

新 Data Class:

TOP_SECRET

旧 Policy 不认识。

最危险:

else → ALLOW

更合理:

Unknown → DENY / REVIEW

Policy Schema 演进要采用:

Secure Default

五十六、Policy版本和Run必须绑定

Run 中途 Policy 升级怎么办?

一般有两种:

Snapshot Policy

Run 创建时固定:

v42

整个 Run 使用 v42。

适合:

低风险长任务

Dynamic Policy

每个高风险 Action:

读取当前Active

适合:

安全写操作

两者不能混得不清楚。

五十七、高风险Action我建议Dynamic Re-evaluate

即使 Run 开始时:

允许email.send

半小时后 Security 禁掉。

真正执行前应该重新评估:

current policy

不要因为 Run Snapshot 还允许就继续写。

五十八、但Replay必须知道当时版本

Audit 保存:

Run Policy Snapshot Action Policy Version

事故重放时才能还原。

五十九、Policy Rollback也要一键

Candidate v43 出现问题:

切回v42

不能重新编辑一份“像v42”的文件。

Active Pointer:

policy_id → version

回滚只切 Pointer。

六十、Rollback前也要注意新产生的数据

如果 v43 已经允许了一批新操作:

回滚Policy

不会自动撤销历史副作用。

所以 Release Report 需要:

affected_runs side_effects

方便补救。

六十一、Policy Observability

指标:

policy_decision_total{ policy, version, decision } policy_flip_total{ type } policy_eval_latency_ms policy_default_total policy_exception_total policy_break_glass_total

高基数 Tenant 不一定放 Metric。

细节进 Trace / DB。

六十二、Policy SLO

P95 Decision < 20ms Error Rate < 0.01% Unknown Input Allow = 0 CrossTenant Allow = 0 Critical Default Decision = 0

这些都可以成为平台 SLO。

六十三、Policy Dashboard第一页只看5件事

Active Version Decision Distribution Default Rate Exception Count Recent Less-Restrictive Changes

不要把管理员淹没在上百条规则里。

六十四、Policy Owner必须明确

每条 Policy:

Security Finance Legal Platform Product

谁负责?

publicrecordPolicyOwnership(StringpolicyId,StringownerTeam,StringapproverGroup,StringescalationChannel){}

没人负责的 Policy 最终一定过期。

六十五、Policy要有Review周期

例如:

Security: 90天 Finance Budget: 30天 Temporary Exception: 14天

超过时间:

REVIEW_REQUIRED

不能一写永远有效。

六十六、完整发布链

Policy Change ↓ Schema ↓ Static Conflict ↓ Golden Test ↓ Historical Simulation ↓ Risk Classification ↓ Approval ↓ Shadow ↓ Canary ↓ Active ↓ Observe Burn ↓ Rollback if needed

这套流程看起来很重。

但高风险 Agent 权限本来就不应该“后台改个开关立即全网生效”。

六十七、Spring Boot可以怎么组织

policy/ ├── model ├── loader ├── evaluator ├── simulation ├── shadow ├── release ├── exception ├── audit └── metrics

不要让:

PolicyEvaluator

同时负责 Git、发布、Simulation 和异常。

六十八、Simulation Service接口

publicinterfacePolicySimulationService{PolicySimulationReportsimulate(StringbaselineVersion,StringcandidateVersion,TimeWindowwindow);}

输出:

publicrecordPolicySimulationReport(longtotal,longchanged,longlessRestrictive,longmoreRestrictive,List<ImpactSlice>slices,List<String>criticalCases){}

六十九、Release Gate接口

publicinterfacePolicyReleaseGate{ReleaseDecisionevaluate(PolicySimulationReportsimulation,ShadowReportshadow,PolicyChangeRiskrisk);}

Policy 本身也进入 Control Plane。

七十、本篇上线检查清单

□ Policy独立于Prompt和业务代码 □ 每次修改生成新Version □ Policy输入结构化 □ Decision不是只有Allow/Deny □ 每次Decision记录Reason Code □ Policy进入Git和PR □ CI做Schema和Conflict检查 □ 高风险Policy有Golden Cases □ Candidate上线前做历史Simulation □ Simulation区分权限扩大和收紧 □ 关键Tenant/Risk做Slice分析 □ Candidate支持Shadow □ Shadow不影响真实决策 □ Policy有P95性能SLO □ 高风险变更走Canary □ Exception有Owner/Reason/Expiry □ Break Glass独立治理 □ Policy失败模式提前定义 □ Emergency Deny能绕过普通Cache □ Decision Trace可解释 □ Incident沉淀Regression Case □ Unknown Input默认安全 □ 高风险Action执行前重新评估 □ Active Version可一键Rollback

总结

Agent 平台发展到一定规模以后,真正难维护的往往不再是 Prompt。

而是:

“到底哪些事情允许发生。”

如果这些规则散落在几十个 Service、管理员页面和配置文件里,系统越自动化,风险越难预测。

Policy-as-Code 解决的是:

规则可版本、可Review、可审计

Policy Simulation 解决的是:

改规则之前, 先知道它会改变什么

Shadow 和 Canary 再解决:

历史上没见过的新流量怎么办

做到这一层以后,Agent 权限和风险治理才从:

“配置管理”

真正升级成:

可测试的软件工程。

下一篇继续推进:

生产级Agent(23):Agent配置供应链——模型、Prompt、Skill、Tool与Policy如何做签名发布和可信加载。


版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/27 18:53:51

ONNX 运行时报错 ORT_RUNTIME_EXCEPTION Ort::Exception 未经处理的异常

1.运行报错前段时候推理时遇到一个非常奇怪的bug&#xff0c;ONNX模型在运行时会报ORT_RUNTIME_EXCEPTION的异常&#xff1a;2.错误排查继续运行&#xff0c;断点看到是在Session.Run()的时候报错。断点逐语句跟踪没有更多详情的信息,重新看了好几遍代码后都没有看出任何问题。…

作者头像 李华
网站建设 2026/8/27 18:48:24

Android 封装 Http 请求工具

Android 封装 Http 请求工具 工具类 import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; import java.util.Map;/*** http 请求工具**…

作者头像 李华
网站建设 2026/8/27 18:48:20

Android开发 GradientDrawable详解

前言 GradientDrawable 支持渐变色的Drawable&#xff0c;与shapeDrawable在画型上是类似的&#xff0c;多了支持渐变色。代码上的GradientDrawable比在xml里的shape下gradient属性强大的多&#xff0c;因为shape下gradient属性只支持三色阶渐变&#xff0c;而GradientDrawable…

作者头像 李华
网站建设 2026/8/27 18:44:30

Go 编译过程全景

Go 编译过程全景一、从 go build 到可执行文件&#xff1a;一张全景图 你敲下 go build&#xff0c;几秒钟后一个静态二进制文件就出现了。但在这几秒钟里发生了什么&#xff1f;Go 编译器&#xff08;gc&#xff0c;注意不是 GC 垃圾回收&#xff0c;而是 Go Compiler 的缩写&…

作者头像 李华
网站建设 2026/8/27 18:41:47

基于DEAP数据集的脑电情绪识别:从特征工程到深度学习实战

简介&#xff1a;脑机接口&#xff08;BCI&#xff09;与情感计算是人工智能与神经科学交叉的前沿领域&#xff0c;其核心目标之一是让机器理解人类情绪。实现这一目标的关键在于从生理信号中提取有效的情绪表征&#xff0c;其中脑电图&#xff08;EEG&#xff09;因其高时间分…

作者头像 李华