拓冰建站拓冰建站
首页 / 资讯中心 / 正文

生产级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 → PermissionAgent 决策通常同时看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至少不是booleanpublicenumPolicyDecision{ALLOW,DENY,REQUIRE_APPROVAL,REQUIRE_STRONG_AUTH,REQUIRE_HUMAN_REVIEW}生产系统里允许 / 禁止通常太粗。例如email.send可以允许但需要Action-bound Approval这就不是 DENY。五、Decision还必须给出Reason CodepublicrecordPolicyResult(PolicyDecisiondecision,ListStringreasonCodes,StringpolicyId,StringpolicyVersion,StringinputHash){}例如{decision:DENY,reasonCodes:[CROSS_TENANT_RESOURCE,EXTERNAL_EGRESS_BLOCKED],policyVersion:v42}以后排障不需要重新猜。六、Policy定义最好声明输入和输出例如 YAMLpolicy: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_APPROVALPolicy 修改后自动回归。十一、但Golden Case远远不够真正危险的是规则本身看起来对 但对真实流量影响巨大例如新的Region Policy可能误伤 30% 客户。所以需要Policy Simulation十二、Simulation到底模拟什么候选policy-v43不要立刻 Active。拿过去 7 天真实 Decision Input100万条重新评估Current Policy v42 vs Candidate v43然后比较Decision Diff十三、Simulation不需要重跑LLMPolicy 输入已经结构化。所以只重放Decision Input而不是整个 Agent Run。成本非常低。数据模型publicrecordPolicySimulationCase(StringdecisionId,PolicyInputinput,PolicyResultbaseline,PolicyResultcandidate){}十四、最核心指标Decision FlipALLOW → 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}单看changed1.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,ListStringreasons,InstantoccurredAt){}没有历史输入就无法真正 Simulation。二十一、Privacy要注意Policy Input 可能包含Resource ID Subject Tenant Data Class不一定要保存原始业务内容。策略评估应该尽量依赖Metadata而不是完整 Prompt。这也会让 Simulation 更安全。二十二、Shadow PolicySimulation看的是历史。下一步ShadowCandidate v43 在真实线上请求中同时计算但不执行Active v42: 真正决定 Shadow v43: 只记录结果二十三、Shadow可以发现历史数据没覆盖的新模式比如上线后出现新Capability 新Tenant类型 新RegionSimulation 数据里根本没有。Shadow 能看到。二十四、Shadow结果不能影响用户即使 CandidateDENY只记录。不要在 Shadow 阶段偷偷改变Latency Approval Tool否则不是真 Shadow。二十五、Shadow Metricspolicy_shadow_total policy_shadow_flip_total policy_shadow_less_restrictive_total policy_shadow_error_total再看Evaluation LatencyPolicy 本身也不能把 Agent Tool Call 拖慢几百毫秒。二十六、Policy性能也有SLO例如P95 Decision 20ms P99 50ms如果 Candidate 正确但慢 10 倍不能直接上线二十七、Canary PolicyShadow 没问题以后1% 5% 20% 100%真实执行。Canary Key 可以按Tenant Workspace Agent稳定分配。不要每个请求随机这会让同一个用户体验来回变化。二十八、高风险Tenant不要自动进入Canary例如Legal Finance Critical Production可以最后再进。先从内部Tenant 测试Tenant 低风险Agent开始。二十九、Policy发布要有Risk ClassificationpublicenumPolicyChangeRisk{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 Gatepolicy_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也是Policypolicy_failure:destructive:mode:fail_closedexternal_write:mode:fail_closedinternal_read:mode:signed_cachemax_age:30s不要等事故时现场讨论。四十三、缓存Policy Decision要带VersionKeytenant agent purpose capability resource_class policy_versionPolicy v42 → v43缓存自动失效否则新规则上线后旧 Decision 还能活很久。四十四、紧急撤权要跳过普通CacheSecurity 触发Emergency Deny应该进入Global Revocation Layer优先于普通 Policy Cache。例如disable capabilityemail.send立即生效。四十五、Policy决策链要可解释最终结果可能来自Tenant Policy Enterprise Policy Exception Emergency DenyAudit 要保存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错误外发你准备新 Policyv44可以拿事故 RunReplay 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 Ratedefault_decision_total / all_policy_decisions目标应该逐步下降。特别是高风险 Capability最好0%每种情况都有显式规则。五十五、Unknown Input不能默认Allow新 Data ClassTOP_SECRET旧 Policy 不认识。最危险else → ALLOW更合理Unknown → DENY / REVIEWPolicy Schema 演进要采用Secure Default五十六、Policy版本和Run必须绑定Run 中途 Policy 升级怎么办一般有两种Snapshot PolicyRun 创建时固定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 Pointerpolicy_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 SLOP95 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必须明确每条 PolicySecurity 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,ListImpactSliceslices,ListStringcriticalCases){}六十九、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 权限和风险治理才从“配置管理”真正升级成可测试的软件工程。下一篇继续推进生产级Agent23Agent配置供应链——模型、Prompt、Skill、Tool与Policy如何做签名发布和可信加载。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门