Skip to main content
The AWS Bedrock Guardrail policy evaluates text against a guardrail you have already defined in Amazon Bedrock and applies the verdict at the gateway. One call covers everything that guardrail contains: denied topics, content filters, word lists, and the sensitive-information policy. It either blocks the request, or rewrites it in place — replacing the spans AWS anonymised with the masked text AWS itself returns, before the request reaches the model.
Only the last user message is sent. Not the system prompt. Not the earlier turns. Not tool definitions, tool calls or tool results. Not attachments. The gateway walks back through the messages, takes the most recent one whose role is user, and sends that single string — and if there is no user message with text in it, the request is forwarded without calling AWS at all.This is the single biggest limit on the policy, and it is not configurable. An instruction planted in a system prompt, smuggled into a tool result, or built up across several turns is invisible to this guardrail. Size your expectations around one message.
This policy puts a synchronous call in front of every request. What that costs depends on your region, your guardrail and the size of the message, so measure it in your own environment rather than assuming.

Part 1 — Build the guardrail in AWS

Everything in this part happens in your own AWS account. TrustGate never creates or changes anything there, and it reads the guardrail rather than configuring it: every decision below is made here and cannot be overridden from the policy later.

Finding Guardrails, which is harder than it should be

Two things get in the way, and both send you somewhere that looks right.
Amazon Bedrock now opens on a console that has no Guardrails in it. The landing experience lists Models, Workbench and Getting started, and Guardrails is in none of them. Its own welcome panel is where this is explained, in a comparison table: guardrails belong to the other Bedrock experience.And searching for “Guardrails” returns two unrelated features. The first result is AWS Control Tower’s, which governs accounts and has nothing to do with filtering content. The one you want is labelled Amazon Bedrock feature.
So: search for Guardrails in the console search bar and pick the Amazon Bedrock result. The page you want is headed Guardrails with Amazon Bedrock in the breadcrumb.

Choose the region before you create anything

A guardrail belongs to one region. The gateway calls the Bedrock endpoint for the region you configure on the policy, so a guardrail created anywhere else simply does not exist as far as TrustGate is concerned — you get a failure, not a warning. Pick the region you will actually use, confirm it in the console’s region selector, and leave it alone for the rest of this walkthrough. You will enter the same region on the policy in Part 3.

Create the guardrail

Create guardrail opens a seven-step wizard, and only the first and the last are mandatory: Provide guardrail details and Review and create. Steps 2 to 6 — every step that actually filters anything — are each marked optional, and that is worth pausing on.
A guardrail with no filters at all is a valid guardrail. Skip every optional step and AWS creates it, marks it Ready, and gives it an identifier. Dropped into a policy it inspects every request, costs a call each time, and allows everything — and from TrustGate it is indistinguishable from a guardrail that works. Configure at least one filter before you leave.
1

Provide guardrail details

A Name, an optional Description, and Messaging for blocked prompts — the text AWS returns when the guardrail blocks something. There is a checkbox to apply the same message to responses.
This message does not reach anyone calling through TrustGate. AWS does return it, but the gateway builds its own refusal and discards it. Set it for whatever else calls this guardrail directly. A TrustGate caller sees the gateway’s own wording, described in When triggered.
2

Configure content filters

Five harmful categories — Hate, Insults, Sexual, Violence and Misconduct — each with a strength of None, Low, Medium or High, and a separate Prompt attacks filter with its own strength. A checkbox applies the same filters to responses.Each category also has an action, and the choice matters more than the strength:Detect is not a gentler block — it is no block. A category set to Detect produces nothing for the gateway to act on, so TrustGate forwards the request as clean. The detection exists only in your AWS telemetry.Content filters tier is a choice between Classic and Standard. Classic covers English, French and Spanish. Standard covers over fifty languages but requires you to opt into cross-Region inference, which means the text leaves the region you just chose. If data residency is a constraint for you, that is the deciding factor rather than language coverage.
3

Add denied topics

Up to thirty topics, each a Name, a Definition, and up to five optional sample phrases. AWS asks you to describe the topic rather than the prohibition — its own guidance is to avoid starting the definition with “don’t”.The definition is capped at 200 characters on Classic and 1,000 on Standard, which is a consequence of the tier choice in the previous step that is easy to meet unexpectedly.Each topic takes an Input action and an Output action, independently.
4

Add word filters

A profanity filter using AWS’s own list, and up to 10,000 custom words or phrases of 100 characters each. Custom terms can be typed in, uploaded from a local file, or read from an S3 object — worth knowing if you already maintain a term list somewhere.Each entry again takes separate input and output actions.
5

Add sensitive information filters

This is the step that decides whether anything is ever masked, and the one most worth getting right.PII types are chosen from a fixed list, grouped as General, Finance, IT, USA Specific, Canada Specific and UK Specific. Each entity you add takes an Input action and an Output action.
AWS calls it Mask. The policy in TrustGate calls it Anonymize. They are the two halves of one decision and they do not share a word, which is exactly how people get this wrong.Setting an entity to Mask here is only half of it. The policy’s PII action decides what the gateway does with that verdict, and its default — Block request — turns AWS’s mask into a hard refusal. An entity you carefully set to Mask, in a policy left at its defaults, refuses the request.Masking needs Mask here and Anonymize on the policy. An entity AWS returns as blocked is always a block, whatever the policy says.
There are no entities for Spain or continental Europe. The list covers the United States with five, Canada with two and the United Kingdom with three; there is no national identity document for anywhere else. For a Spanish DNI or an equivalent, your only route here is a regex pattern — up to thirty are allowed, alongside the PII types, each with its own actions.
6

Add contextual grounding check

Two independent toggles, Grounding and Relevance, each with a score threshold from 0 to 0.99 and an action.
Neither can ever fire through this policy. Both need a reference source and a query marked as such — AWS’s own test panel has a Reference source field for exactly this — and the gateway sends one unmarked block of text, on the request leg and on the response leg alike.Configure them if other things call this guardrail. Through TrustGate they are inert, and a guardrail whose only active policy is contextual grounding allows everything while looking configured.
7

Review and create

Check the summary and create. The guardrail is usually Ready immediately.
Output actions are read only when Inspect model responses is on. Leave that toggle off, in the policy’s Inspection section, and the guardrail’s output actions are never looked at — setting them does no harm and costs nothing, but they sit unused until you turn the response leg on.

The identifier, and why the version matters

The guardrail’s page shows its ID — a short string such as ln5mkuwnz801, not the name you gave it. That identifier is what goes on the policy. Below it sits a Working draft and a Versions list that starts empty. Create version takes an optional description and assigns the number itself: the first is Version 1.
Leave the version empty on the policy and it follows the working draft, which moves. Anyone editing the guardrail in AWS changes what your gateway enforces — with no deployment, no change in TrustGate, and nothing in your own change log to point at afterwards.Publish a version and name it on the policy. Then an edit in AWS is a new version that nothing uses until someone chooses it.
Creating a version does not select it. The console’s own test panel stays on Working draft until you change it, and so does anything else.

Test it before you leave AWS

The guardrail’s page has a Test panel, and it has one option that makes it far more useful than it looks: Use ApplyGuardrail API. That is the same operation the gateway calls. Testing through it tells you what AWS itself decides, separately from what TrustGate does with that answer — which is the difference you will want when something behaves unexpectedly later. Choose the version, tick Use ApplyGuardrail API, set the source to Input, and paste text that should trip one of your filters. View trace breaks the result down by policy. Two behaviours are worth seeing here rather than discovering in production: A masked entity comes back as rewritten text. An email address set to Mask returns the whole input with the address replaced by {EMAIL} — the entity name in braces. That rewritten text is exactly what the gateway reinjects when the policy’s PII action is Anonymize, so the model receives the placeholder and never the address. A block hides everything else. Send text containing both a blocked entity and a masked one, and the trace reports only the blocked one. The masked entity is not listed as masked, and not listed as detected either. A block ends the evaluation, so the first thing to reach for when a trace looks thinner than you expected is whether something blocked earlier in it.

Part 2 — Give the gateway access to AWS

The gateway needs to call bedrock:ApplyGuardrail on your guardrail. There are two ways, and they are the only two.

Method A — IAM role (STS)

You create a role in your account that may call the guardrail, and the gateway assumes it. Choosing IAM role (STS) in the policy hides the key fields entirely: the gateway assumes the role as its own identity — the instance or pod identity it already runs with — and stores nothing of yours but the ARN. The role needs bedrock:ApplyGuardrail on the guardrail, and its trust policy has to permit the gateway’s identity to assume it. Ask your NeuralTrust contact for that identity.
The policy cannot send an external ID. It assumes the role with a session name and nothing else, so a trust policy that requires an sts:ExternalId condition will refuse every call. Write the trust policy without one.

Method B — Static keys

Create an IAM user with bedrock:ApplyGuardrail on the guardrail and paste its access key ID and secret into the policy. Session token is there for temporary credentials. The secret is never returned to the browser. Reopen the policy and the field shows only that a secret is set, not the secret itself: you replace it rather than read it. AWS shows a secret access key once, when the key is created, and never again, so keep your own copy where you keep your other secrets. Rotate on your normal schedule, and prefer the role where it is available to you.
Nothing refreshes a session token. Temporary credentials expire, and when they do every request fails open, unscreened, until someone pastes new ones. Static keys without a session token, or a role, are what you want for anything long-lived.

Part 3 — Configure the policy in TrustGate

Open Policies → Library → AWS Bedrock Guardrail.

AWS connection

Guardrail

Guardrail ID — the guardrail’s identifier in AWS: the identifier itself or the full guardrail ARN. Required. The console checks its shape when you save; whether the guardrail exists is discovered on the first request, and an identifier AWS does not accept is a configuration problem that fails open.

Inspection

The request is always screened. Every call on its way to the model goes through this guardrail — there is no control to turn that off, and it is one call to AWS per request. Inspect model responses, in this Inspection section — off by default. Turn it on and the model’s answer is evaluated against the same guardrail too, and masked in place under the same PII action as the request: a second call to AWS on every turn. There is no way to screen the response only — the request is always the first call. Start with the request alone, measure what it costs you, and only then turn this on.
A streamed response is not inspected, even with Inspect model responses on. Only a non-streamed response is evaluated, because every part of a stream would be another call to AWS, which limits how many it accepts per account and region.

When triggered

PII action — Block request (the default) or Anonymize. Read the warning in Part 1 before changing it: this decides what the gateway does with an anonymised verdict from AWS, and it does nothing at all unless the entity is set to anonymise on the AWS side. There is no block message to write. The 403 always says This content violates our usage policy. It also names which of the guardrail’s policies matched, and the name it matched where AWS provides one, so you can still tell which filter fired.

Advanced Settings

Guardrail version — DRAFT or a published version number, checked when you save. Defaults to DRAFT. Point production at a published version number instead: DRAFT changes the moment anyone edits the guardrail in AWS, with no change to this policy and no event to tell you. Session name — the STS session name, for the IAM role method. Defaults to BedrockClientSession. It shows up in CloudTrail, which is the only reason to change it. The console checks it when you save: 2 to 64 characters from letters, digits and + = , . @ _ -.

Stage and mode

Start in Observe, which records every decision without refusing or rewriting anything, and switch to Enforce once the decisions look right.

How the decision is made

1

One message is sent to the guardrail

The most recent user message, as described at the top of this page. One call per request.
2

AWS's assessments are read in a fixed order

Denied topics, then content filters, then word lists, then sensitive information, then contextual grounding. The first blocking finding wins and is the one named in the response — regardless of how many others also matched, and regardless of which you would consider the more serious.
3

A blocking finding refuses the request

The request never reaches the model. The caller gets 403, and the response names which of the guardrail’s policies fired — denied topics, content filters, word lists, sensitive information or contextual grounding — and, where AWS provides one, the name it matched.
4

Masking applies only if nothing blocked

With PII action set to Anonymize, and AWS coming back with an anonymised verdict, the masked text AWS returned replaces the original message and the request continues to the model. The model never sees the original.
5

Otherwise the request passes through untouched

A block anywhere discards the masking. If sensitive data would be masked but another policy blocks the same message, the block wins and nothing is sent. And if masking is chosen but cannot be carried out — AWS returned no masked text, the request format has no re-encoder, or the body cannot be re-encoded with the masked text — the gateway blocks rather than forward the original. Masking that fails is never a silent pass-through.

Modes and failures

Observe never masks. It records what would have happened and forwards the original text. Masking is only ever applied in Enforce. The decision recorded on the event is allowed, block, anonymized, reported or failed_open. anonymized is Enforce-only: in Observe a prompt that would have been masked records reported instead, which is also what Observe records in place of a block. failed_open is the one to look for first on a new policy — it is what AWS being unreachable, a missing permission, a wrong region or a credential that cannot be resolved records on every request, in Enforce and Observe alike. The event’s failure_reason field says why: transport (the call failed, timed out, was throttled, or was denied), verdict_incomplete (AWS intervened but with no finding this plugin reads), config_invalid (the stored settings could not be used), or decode_failed (the gateway’s own body could not be decoded before AWS was ever called).
An AWS outage or a configuration problem fails open in Enforce. If AWS cannot be reached, requests are forwarded unscreened rather than refused. An expired credential, a denied permission, a wrong region, a throttle or quota error, and a guardrail ID, version or role that AWS rejects all look the same to the caller: a normal reply. Only the event and the trace record it, as failed_open with a failure_reason — the gateway logs the underlying error at debug level, so at a default log level it is invisible on the gateway too.A failure caused by the content is different. Content AWS rejects, a text AWS evaluated only in part, an AWS intervention this plugin cannot read, a body the gateway cannot decode, or Anonymize when AWS reports sensitive information but the masked text cannot be applied: in Enforce the request is refused with 403, because forwarding it would send the content unscreened. In Observe these are only recorded and never block.

Limits

  • Only the last user message is inspected on the request leg. No system prompt, no conversation history, no tool definitions, no tool calls or results.
  • Contextual grounding can never fire. See the note in Part 1. A guardrail relying on it looks healthy and allows everything.
  • Inspect model responses is off by default. Only the request is screened until you turn it on; turning it on doubles the calls to AWS per turn.
  • A streamed response is not inspected, even with Inspect model responses on.
  • Text only. Files, images and audio are not sent to AWS. A request on a route that carries no chat is not inspected: it is forwarded and recorded as not inspected, never refused. The same holds for an upstream error response.
  • Long texts are sent whole. The gateway does not shorten or split the message. AWS judges it, rejects it, or evaluates only part of it, and a part evaluated only in part blocks in Enforce.
  • LLM traffic only. The policy does not apply to MCP (Model Context Protocol) tool calls.

Verify the policy

Open the Playground, pick the application the policy applies to, and send these three prompts in this order. Starting with the control means a failure tells you something specific.
1

Control — the path works at all

Expect a normal reply and the decision allowed. A decision of failed_open here means the gateway could not get an answer out of AWS at all: region, credentials, permission or guardrail ID. The reply looks normal, so read the decision. Nothing below will work until this does.
2

Sensitive information — masking works

Send a prompt containing an entity your guardrail is configured to anonymise, for example an email address:
With PII action set to Anonymize and the policy in Enforce, expect the decision anonymized. In Observe the same prompt records reported and the original address still reaches the model, so switch to Enforce before reading this step.Read the reply, not just the status. It must not contain the address. That is what proves the model never received it.If you get a 403 instead, the two settings disagree: either the entity is set to Block in AWS, or PII action is still Block request. If you get a plain allowed, the entity is not in your guardrail at all.
3

A denied topic — blocking works

Send something your guardrail’s denied topics or content filters should refuse.Expect the decision block and a 403 naming the policy that fired. To prove the request never reached the model, open Activity, open the request, and read its Policies tab: the Aggregated Latency breakdown there has a Provider row, and that row is empty. The Playground shows a single latency figure and does not break it down.
Every decision is emitted as a metadata event, in Observe mode too, where nothing is blocked. See the event schema for the fields recorded.

Troubleshooting