本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
护栏政策示例
本节中的策略是根据请求获得授权时基岩护栏计算的信号决定的。护栏会读取你指向的内容,返回每个类别的信心分数,然后策略将该分数与阈值进行比较。
Guardrails允许政策对任何静态条件都无法描述的内容采取行动,包括即时注射尝试、仇恨言论或模特回应中的账号。由于底层模型是不确定性的,因此与其他策略评估不同,相同的输入在不同的调用中可能得分不同。
每个示例都对示例资源配置中描述的网关进行授权。有关护栏类别、阈值、所需的 IAM 权限和区域可用性,请参阅策略中的防护措施。
这些示例遵循的规则
五条规则规定了护栏召唤的有效性。四个同步执行,并ValidationException立即CreatePolicy返回。基本许可证规则根本没有得到执行:没有随附许可证的护栏政策是有效的,而且根本不会生效。
- 护栏政策需要基本许可证
-
默认情况下,策略评估是拒绝的:只有当某些
permit请求与之匹配时,才允许该请求。护栏forbid只能移除访问权限,而对已经运行的操作suppressOutput起作用,因此两者都无法访问操作。仅凭护栏政策,在咨询护栏之前,该行动就会被拒绝,因此该请求在没有经过任何筛选的情况下被拒绝。将每项护栏政策与普通人配对,permit以采取相同的行动。 - 效果决定了你可以读哪一面
-
授权效果(
permit或forbid)只能读取入站有效负载。suppressOutput效果只能读取出站的效果。context.output与permit或一起使用forbid会被拒绝Guardrail '<name>' references 'context.output' but the policy has an authorization effect。 - 一个呼叫读取一面
-
单个护栏呼叫不能混合入站和出站路径。要双向筛选,请编写两项策略。
-
SensitiveInformation需要聚合 -
ContentFilter并PromptAttack支持按类别编制索引,例如。["VIOLENCE"].confidenceScoreSensitiveInformation不是:它需要count()categories()、maxConfidenceScore()、或minConfidenceScore()。拒绝按类别将其编入索引Per-category indexing is not supported for SensitiveInformation。 - 只接受已发布的类别
-
每项保障措施都接受一个固定的类别清单。Bedrock Guardrails 记录的敏感信息类型比 Policy 中 AgentCore 接受的要多,因此请从支持的护栏中取类别名称,而不是从 Bedrock 文档中提取类别名称。
注意
when guardrails { … }相当于身体when { … }叫护栏的平原。guardrails标签记录的是意图,而不是限制政策。在授权效力下,护栏由普通的雪松条件组成,政策相同:将护栏卡when和请求或主要条件放在街区内unless或旁边。temporal有关更多信息,请参阅将护栏与请求条件相结合和合并临时条件、护栏条件和请求条件。
使用 jsonPath 访问数组内的文本
护栏的内容参数是一组字符串,这对于标量字段来说很简单。你最想筛选的文本不是:对话或内容块列表嵌套在数组和记录中,裸露的字段路径无法到达。
命名数组本身是一个类型错误,因为参数必须是字符串:
argument `context.input.messages` has type `Set<record>` ... but the provider declares argument type `string`
你也无法对其进行索引。Dogwood 没有数组投影运算符,解析错误messages[].content也是如此messages[*].content,而messages[0]解析为空。messages.items.content
取而代之的是,将内容参数写成以开头的字符串文字 $,Policy 将其 AgentCore解析为 jsonPath:
BedrockGuardrails::ContentFilter(["VIOLENCE"], ["$.messages[*].content"])
$-path 有四个值得了解的属性。
- 它的根源是原始有效载荷,而不是在
context -
写信
$.messages[*].content,永远不要$.context.input.messages[*].content。context.input.和context.output.前缀是字段路径的方向标记,在 JSONPath 中没有位置。 - 它的方向来自效果
-
JSONPath 没有方向标记,因此
suppressOutput使其读取出站有效负载,而任何其他效果都使其读取入站有效负载。因此,出站护栏必须是 asuppressOutput,而入站护栏可以是 aforbid或 apermit— 两者都要读取请求。 - 每场比赛都是串联的
-
所有通配符匹配项都被连接成一个没有分隔符的字符串,因此分成多个内容块的短语保持连续性,并且不会因为分段而滑过探测器。
- 与任何东西都不匹配的路径无济于事
-
这使您可以在一次调用中列出多个候选形状,并让任何存在的形状解析,以下示例就是这样涵盖消息正文的字符串和块形式。
警告
JSONPath 在创建时未经过验证。既不会检查其语法也不检查其是否适合您的架构,因此输入错误或错误的路径会ACTIVE像其他任何路径一样到达。在评估时它关闭失败:路径不产生任何文本,护栏无法运行,请求被拒绝,并命名了它找不到的字段。Authorization denied: request missing field(s) required for guardrail evaluation遇到此错误时,请先检查 JSONPath。
根据应捕获的内容测试每项护栏策略,并从文本位置为每条路径选择路径,而不是根据其他 API 对其进行改编。
重要
不要在下方的同一个护栏呼叫中混合使用 $-path和裸露context.input.*字段。suppressOutput当输入显式字段时,$-path 被推断为输出,并且调用会立即被拒绝:
Guardrail 'BedrockGuardrails::ContentFilter' mixes 'context.input.*' and 'context.output.*' paths; all paths in a single call must be on the same side.
将数组命名为裸字段路径也会被拒绝,但这是异步的 — 该策略返回 202,然后结算为:CREATE_FAILED
provider `BedrockGuardrails::ContentFilter`: argument `context.input.messages` has type `Set<record>` on action `...___POST:/v1/chat/completions` but the provider declares argument type `string`
在字段路径(例如)中写入数组投影在调用时会失败unexpected token '*', expected expression。context.input.messages[*].content
有关每个推理 API 路径上的文本位置,请参阅每个路径的文本位置。
筛选运行时目标
意图:拒绝任何对索赔助手的调用,其提示看起来像是提示注入尝试。
基本许可使运行时操作可访问;当护栏检测到提示注入尝试时,它会forbid移除访问权限。运行时目标prompt是一个标量字符串,因此裸context.input.prompt字段路径起作用并且不需要 jsonPath。第一个参数列出了要评估的类别,第二个参数列出了内容,然后按类别对结果进行索引以读取该类别的分数。
// Base permit: makes the action reachable at all permit( principal, action == AgentCore::Action::"ClaimsAgent___POST:/invocations", resource == AgentCore::Gateway::"arn:aws:bedrock-agentcore:us-west-2:123456789012:gateway/insurance-gw-a1b2c3d4e5" ); // Inbound: reject prompt-injection attempts forbid( principal, action == AgentCore::Action::"ClaimsAgent___POST:/invocations", resource == AgentCore::Gateway::"arn:aws:bedrock-agentcore:us-west-2:123456789012:gateway/insurance-gw-a1b2c3d4e5" ) when guardrails { BedrockGuardrails::PromptAttack(["PROMPT_INJECTION"], [context.input.prompt])["PROMPT_INJECTION"] .confidenceScore .greaterThan(decimal("0.4")) };
Content-filter 而且即时攻击分数是离散的 —— 0、0.2、0.4、0.6、0.8 或 1.0 中的一个 —— 因此,当greaterThan火灾等于 0.6 及0.4以上时,阈值为。即时攻击检测的默认阈值为 0.4。
根据运行时目标的标量completion筛选出站端的工作原理相同:
suppressOutput( principal, action == AgentCore::Action::"ClaimsAgent___POST:/invocations", resource == AgentCore::Gateway::"arn:aws:bedrock-agentcore:us-west-2:123456789012:gateway/insurance-gw-a1b2c3d4e5" ) when guardrails { BedrockGuardrails::ContentFilter(["VIOLENCE", "HATE"], [context.output.completion]) .maxConfidenceScore().greaterThan(decimal("0.2")) };
maxConfidenceScore()在评估的每个类别中取最高分,因此一个阈值涵盖两个类别,每个类别都没有条款。minConfidenceScore()当你需要每个类别都获得高分,以及count()当你关心标记了多少类别而不是有多强时,请使用。
屏幕聊天完成次数
意图:筛选发送给目标和由POST /v1/chat/completions目标返回的对话。
$.messages[*].content收集对话中的每条消息,包括系统和用户,并$.choices[*].message.content收集模型返回的每条完成信息。双向筛查总共需要三项政策:基本许可证forbid、入境许可和出境许可suppressOutput。
// Base permit: makes the action reachable at all permit( principal, action == AgentCore::Action::"ClaimsChat___POST:/v1/chat/completions", resource == AgentCore::Gateway::"arn:aws:bedrock-agentcore:us-west-2:123456789012:gateway/insurance-gw-a1b2c3d4e5" ); // Inbound: what the caller sent forbid( principal, action == AgentCore::Action::"ClaimsChat___POST:/v1/chat/completions", resource == AgentCore::Gateway::"arn:aws:bedrock-agentcore:us-west-2:123456789012:gateway/insurance-gw-a1b2c3d4e5" ) when guardrails { BedrockGuardrails::ContentFilter( ["INSULTS", "MISCONDUCT"], ["$.messages[*].content"] ).maxConfidenceScore().greaterThan(decimal("0.2")) }; // Outbound: what the model returned suppressOutput( principal, action == AgentCore::Action::"ClaimsChat___POST:/v1/chat/completions", resource == AgentCore::Gateway::"arn:aws:bedrock-agentcore:us-west-2:123456789012:gateway/insurance-gw-a1b2c3d4e5" ) when guardrails { BedrockGuardrails::ContentFilter( ["INSULTS", "MISCONDUCT"], ["$.choices[*].message.content"] ).maxConfidenceScore().greaterThan(decimal("0.2")) };
筛选响应 API
意图:筛选POST /v1/responses目标,其提示有两种可能的线形和一个单独的系统提示符。
入站呼叫中会出现三条路径,因为要么input是裸字符串,要么是包含内容块的项目列表,并instructions带有系统提示符。无论来电者发送哪种形状都能解析;其他人什么都不匹配,什么也没贡献。列出所有三种电汇表单是使保单正确的原因,而不必知道哪一份到达。
permit( principal, action == AgentCore::Action::"ClaimsResponses___POST:/v1/responses", resource == AgentCore::Gateway::"arn:aws:bedrock-agentcore:us-west-2:123456789012:gateway/insurance-gw-a1b2c3d4e5" ); forbid( principal, action == AgentCore::Action::"ClaimsResponses___POST:/v1/responses", resource == AgentCore::Gateway::"arn:aws:bedrock-agentcore:us-west-2:123456789012:gateway/insurance-gw-a1b2c3d4e5" ) when guardrails { BedrockGuardrails::ContentFilter( ["VIOLENCE", "MISCONDUCT"], ["$.instructions", "$.input", "$.input[*].content[*].text"] ).maxConfidenceScore().greaterThan(decimal("0.15")) }; suppressOutput( principal, action == AgentCore::Action::"ClaimsResponses___POST:/v1/responses", resource == AgentCore::Gateway::"arn:aws:bedrock-agentcore:us-west-2:123456789012:gateway/insurance-gw-a1b2c3d4e5" ) when guardrails { BedrockGuardrails::ContentFilter( ["VIOLENCE", "MISCONDUCT"], ["$.output[*].content[*].text"] ).maxConfidenceScore().greaterThan(decimal("0.15")) };
包括$.instructions事项:系统提示是注入的指令可以隐藏的地方,在这个 API 上,它是一个单独的入站成员,而不是对话中的一条消息。
筛选消息 API
意图:筛选POST /v1/messages目标,其消息内容可能是字符串或键入的块。
$.messages[*].content涵盖内容为纯字符串的消息,而$.messages[*].content[*].text涵盖内容为类型块数组的消息。 $.system涵盖了顶级系统提示,这在此 API 上不是一条消息。在出站方面,Anthropic 信封返回顶层的内容块,因此路径$.content[*].text而不是下choices方的任何内容。
permit( principal, action == AgentCore::Action::"ClaimsMessages___POST:/v1/messages", resource == AgentCore::Gateway::"arn:aws:bedrock-agentcore:us-west-2:123456789012:gateway/insurance-gw-a1b2c3d4e5" ); forbid( principal, action == AgentCore::Action::"ClaimsMessages___POST:/v1/messages", resource == AgentCore::Gateway::"arn:aws:bedrock-agentcore:us-west-2:123456789012:gateway/insurance-gw-a1b2c3d4e5" ) when guardrails { BedrockGuardrails::ContentFilter( ["VIOLENCE", "HATE"], ["$.messages[*].content", "$.messages[*].content[*].text", "$.system"] ).maxConfidenceScore().greaterThan(decimal("0.1")) }; suppressOutput( principal, action == AgentCore::Action::"ClaimsMessages___POST:/v1/messages", resource == AgentCore::Gateway::"arn:aws:bedrock-agentcore:us-west-2:123456789012:gateway/insurance-gw-a1b2c3d4e5" ) when guardrails { BedrockGuardrails::ContentFilter( ["VIOLENCE", "HATE"], ["$.content[*].text"] ).maxConfidenceScore().greaterThan(decimal("0.1")) };
注意
从每条路径的文本位置获取每个 API 的路径,而不是从其他路径调整路径。这三个信封差异很大,以至于从一个 API 复制的路径在另一个 API 上默默地不匹配任何路径—— forbid 这意味着流量会被取消屏蔽而不是被拒绝。
筛选 MCP 工具参数
意图:拒绝其自由文字描述包含支付卡或银行详细信息的索赔。
MCP 工具的参数是在其架构中声明的,因此标量参数(例如description)可以通过裸露的字段路径到达。 count()以 a 的形式返回检测到的类别数Long,因此将其与普通的整数运算符而不是decimal方法进行比较。任何检测都会拒绝该请求。
// Base permit: makes the action reachable at all permit( principal, action == AgentCore::Action::"InsuranceAPI___file_claim", resource == AgentCore::Gateway::"arn:aws:bedrock-agentcore:us-west-2:123456789012:gateway/insurance-gw-a1b2c3d4e5" ); // Inbound: reject payment card or bank details forbid( principal, action == AgentCore::Action::"InsuranceAPI___file_claim", resource == AgentCore::Gateway::"arn:aws:bedrock-agentcore:us-west-2:123456789012:gateway/insurance-gw-a1b2c3d4e5" ) when guardrails { BedrockGuardrails::SensitiveInformation( ["CREDIT_DEBIT_CARD_NUMBER", "US_BANK_ACCOUNT_NUMBER", "US_BANK_ROUTING_NUMBER"], [context.input.description] ).count() > 0 };
记下类别名称。 ACCOUNT_NUMBER不是有效的类别;可接受的名称是US_BANK_ACCOUNT_NUMBER和INTERNATIONAL_BANK_ACCOUNT_NUMBER。创建策略时,服务无法识别的类别无法通过验证。
一次调用中可以有几个标量场,护栏会一起评估所有标量场。前面显示的基本许可证也适用于此变体:
forbid( principal, action == AgentCore::Action::"InsuranceAPI___file_claim", resource == AgentCore::Gateway::"arn:aws:bedrock-agentcore:us-west-2:123456789012:gateway/insurance-gw-a1b2c3d4e5" ) when guardrails { BedrockGuardrails::ContentFilter( ["INSULTS", "HATE"], [context.input.description, context.input.claimType] ).maxConfidenceScore().greaterThan(decimal("0.4")) };
重要
description是一个可选参数,因此在没有该参数的情况下提交的索赔在护栏的数据路径上没有任何内容。护栏无法运行,缺少字段的请求被拒绝,而不是经过筛查。在所需参数上最好使用护栏。如果该字段必须保持可选状态,请将此策略与 “需要一个可选参数” 中的forbid … unless context.input has description策略配对,这样要求就显式化了,拒绝原因会给它命名。
抑制 MCP 工具响应
意图:当索赔状态回复包含社会安全号码时,将其隐藏,这样来电者只会收到敏感值。
suppressOutput在操作获得授权并产生结果之后运行,它根据该结果采取行动,而不是根据允许呼叫的决定采取行动。该工具仍在运行;呼叫者收到的内容会被抑制。
// Base permit: makes the action reachable at all permit( principal, action == AgentCore::Action::"InsuranceAPI___get_claim_status", resource == AgentCore::Gateway::"arn:aws:bedrock-agentcore:us-west-2:123456789012:gateway/insurance-gw-a1b2c3d4e5" ); // Outbound: suppress the whole response when it carries a social security number suppressOutput( principal, action == AgentCore::Action::"InsuranceAPI___get_claim_status", resource == AgentCore::Gateway::"arn:aws:bedrock-agentcore:us-west-2:123456789012:gateway/insurance-gw-a1b2c3d4e5" ) when guardrails { BedrockGuardrails::SensitiveInformation( ["US_SOCIAL_SECURITY_NUMBER", "CREDIT_DEBIT_CARD_NUMBER"], [context.output.status] ).count() > 0 };
此示例使用count(),因为SensitiveInformation需要聚合。对于允许索引的内容过滤器,两种形式都适用。
警告
Output-phase 评估会改变响应的交付方式。网关会保留响应,直到护栏返回判决,因此流媒体响应会被缓冲而不是流式传输。在评估完成之前,调用者什么也没收到,然后要么立即收到整个响应,要么什么也没收到。在高吞吐量或流媒体目标suppressOutput上启用之前,请考虑增加的延迟以及大响应在保持期间占用的内存。
将护栏与请求条件相结合
意图:屏幕提示注入尝试,但仅适用于可信内部角色之外的来电者。
护栏调用是一个普通的函数调用,因此它与 Cedar 条件组成:这里的 a when 保存护栏检查,a 豁免可unless信角色。when { … }代替写作when guardrails { … }是等同的。
// Base permit: makes the action reachable at all permit( principal, action == AgentCore::Action::"ClaimsAgent___POST:/invocations", resource == AgentCore::Gateway::"arn:aws:bedrock-agentcore:us-west-2:123456789012:gateway/insurance-gw-a1b2c3d4e5" ); // Inbound: screen external callers for injection attempts forbid( principal is AgentCore::OAuthUser, action == AgentCore::Action::"ClaimsAgent___POST:/invocations", resource == AgentCore::Gateway::"arn:aws:bedrock-agentcore:us-west-2:123456789012:gateway/insurance-gw-a1b2c3d4e5" ) when { BedrockGuardrails::PromptAttack(["PROMPT_INJECTION", "JAILBREAK"], [context.input.prompt]) .maxConfidenceScore().greaterThan(decimal("0.4")) } unless { principal.hasTag("role") && principal.getTag("role") == "internal-service" };
订购重要的是成本而不是正确性。每当策略范围匹配的请求时,护栏调用都会调用 Bedrock。尽可能通过操作和委托人来缩小范围,而不是制定一项筛选所有流量的宽泛政策。
创建这些政策
使用创建护栏政策。--validation-mode IGNORE_ALL_FINDINGS这不是默认值:validationMode参数默认为FAIL_ON_ANY_FINDINGS。
语义分析器会推断出政策的广度以及护栏策略所采用的形式:一个命名操作被报告为过于宽松,而一个permit命名操作被报告为过于严格。forbid两者都是这里的预期形状——基本许可证加上目标狭窄的护栏——因此默认模式会拒绝正确的策略集。FAIL_ON_ANY_FINDINGS将其视为对广泛授权策略的设计审查,而不是护栏政策的大门。有关每种模式的检查内容,请参阅验证和分析概述。
拒绝是异步的。 CreatePolicy返回 202(包含状态)CREATING,然后策略CREATE_FAILED以中的原因结算statusReasons,因此请轮询终端状态。
选择阈值
从默认值开始——内容过滤器为0.2,即时攻击检测为0.4,敏感信息为0.2,然后根据自己的流量进行校准,而不是推理数字。
由于分数是离散的,因此阈值仅在两个相邻分数值之间的位置才有意义。使用greaterThan时,区间 [0.4, 0.6) 中的任何阈值的行为都相同,因此从 0.4 移动到 0.5 没有任何改变。
要进行校准,请在LOG_ONLY模式下连接策略引擎,或者将单个策略设置为LOG_ONLY,然后在强制执行之前,读取护栏从策略日志中返回的分数。enforcementMode有关完整过程,包括如何根据记录的分数构建混淆矩阵,请参阅如何选择阈值。要在仅记录模式下运行单个策略,而引擎的其余部分则强制执行,请参阅策略实施模式。
重要
Guardrails 是不确定性的:相同的内容在单独的调用中可能得分不同,因此接近您的阈值的请求可能会被允许一次,而下次则被拒绝。将护栏视为在确定性策略之上分层的概率控制,而不是它们的替代品。如果规则可以表示为请求的条件(角色、索赔类型、金额),则改为以这种方式表达。