Python (boto3)
init() hooks the InvokeModel, Converse and ConverseStream operations of every Bedrock Runtime client.
PromptGuardBlockedError from the converse call before AWS is called.
Node.js (AWS SDK v3)
init() hooks send on BedrockRuntimeClient, for InvokeModelCommand, ConverseCommand and their streaming variants. For a streaming command the prompt is scanned and the streamed output is not.
Through the proxy
The proxy takes OpenAI’s chat-completions request for abedrock/ model, calls Bedrock’s Converse operation with your Bedrock API key, and answers in OpenAI’s shape. The model id after bedrock/ is Bedrock’s own: a model id, an inference profile such as us.amazon.nova-lite-v1:0, or an ARN.
1. Store a Bedrock API key with its region
Create a long-term Bedrock API key (its value beginsABSK) for an IAM user that may call only the models you use, and give it an expiry. Store it with the AWS region it is for: in Dashboard → Gateway → Provider Keys → Add Provider Key, choose AWS Bedrock, paste the key and enter the region under AWS region. Or through the provider keys API, as a bedrock key with the region in base_url:
base_url takes a region or the endpoint itself (https://bedrock-runtime.eu-west-1.amazonaws.com, a -fips endpoint, or a China-region .amazonaws.com.cn one; a cn- region is sent to the .amazonaws.com.cn endpoint); any other host is refused, and so is a bedrock key without one. A short-term key (bedrock-api-key-…) is refused too, because it expires within 12 hours.
2. Send the request
Proxy Base URL:
https://api.promptguard.co/api/v1Point your LLM SDK’s base_url / baseURL to this endpoint. Your existing provider API key goes in the Authorization header as usual; add your PromptGuard key via X-API-Key.bedrock key, the proxy forwards the Bedrock API key you send in Authorization only if the deployment sets a default region in AWS_BEDROCK_REGION. PromptGuard Cloud does not, so on Cloud store the key: a request with no region is refused, rather than sent to a region nobody chose.
What the proxy translates
Anything else — tools and tool calls, images and other non-text content,
response_format, n greater than 1, logprobs, penalties, seed — is refused with a 400 that names the field, and nothing is sent to Bedrock. Those change what the model does, so dropping them would answer a different request. Tool calls through the proxy’s bedrock/ route are out of scope today, not an oversight: for them, call Bedrock with your AWS SDK and auto-instrumentation.
The reply’s finish_reason comes from Bedrock’s stopReason: end_turn and stop_sequence are stop, max_tokens is length, and a guardrail or content-filter stop is content_filter. A stop reason Bedrock adds later is answered as stop until PromptGuard maps it. Bedrock’s request id is returned as x-request-id.
Errors
Every error is in OpenAI’s
{"error": {...}} shape, so an OpenAI client raises it as it would any other. Nothing is sent to Bedrock for the first three.
Usage and spend caps
Each answer, streamed or not, records the input and output tokens Bedrock reported, so they appear in your events and usage. A stream you send withoutstream_options still records them; you receive the usage chunk only if you ask for it with stream_options: {"include_usage": true}. PromptGuard does not price Bedrock models, because their price depends on your AWS agreement, so a Bedrock answer has no cost figure.
For the same reason, a project with a spend cap refuses bedrock/ models with a 400 upstream_spend_cap_unpriced_model and sends nothing to Bedrock: the cap cannot count what it cannot price. Use bedrock/ from a project without a cap.
Testing a stored key
Send test request on the Provider Keys page tests a stored Bedrock key withamazon.nova-micro-v1:0, Amazon’s smallest text model, in the key’s region. The test fails if your account has no access to that model in that region; enable it in the Bedrock console first.