AWS Public Sector Blog
Get started with OpenAI GPT-5.4 on Amazon Bedrock in AWS GovCloud (US)

Amazon Bedrock now supports OpenAI GPT-5.4 in Amazon Web Services (AWS) GovCloud (US-West). Applications use the OpenAI-compatible Responses API through the regional Amazon Bedrock Powered by AWS Mantle endpoint.
OpenAI GPT models on Amazon Bedrock are now FedRAMP High and DoD IL4/5 approved in AWS GovCloud (US). Federal agencies, public sector organizations, and other enterprises with these requirements can use the models to build and scale generative AI applications for government workloads.
In this post, you’ll learn how to build an identity incident review workflow that analyzes an event timeline, converts the findings into a strict incident record, and connects the review to a local account-control lookup. The examples separate observed facts from inferences and keep final incident and remediation decisions with a human reviewer.
What You’ll Build
By the end of this post, you’ll learn to:
- Verify that your terminal is using AWS GovCloud (US) credentials
- Discover
openai.gpt-5.4through the AWS GovCloud (US) Mantle endpoint - Analyze an identity incident with configurable reasoning effort
- Produce a predictable JSON incident record with a strict schema
- Let the model request a local control lookup while your application remains responsible for executing the function
Solution Overview
The runtime examples use one regional path:
- Model ID:
openai.gpt-5.4 - Model discovery:
https://bedrock-mantle.us-gov-west-1.api.aws/v1/models - OpenAI SDK base URL:
https://bedrock-mantle.us-gov-west-1.api.aws/openai/v1 - Authentication: A short-term Amazon Bedrock API key generated from your AWS credentials
Prerequisites
You need the following:
- AWS Command Line Interface (AWS CLI) version 2 configured for the AWS GovCloud (US) runtime workflow
- Python 3.10 or later
Grant Runtime Permissions
Grant the AWS GovCloud (US) runtime identity permission to use a short-term Amazon Bedrock bearer token, list Mantle models, and invoke GPT-5.4 in the account’s default Mantle project. Replace <ACCOUNT_ID> with the 12-digit AWS GovCloud (US) account ID.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "UseBedrockBearerToken",
"Effect": "Allow",
"Action": [
"bedrock:CallWithBearerToken",
"bedrock-mantle:CallWithBearerToken"
],
"Resource": "*"
},
{
"Sid": "ListModelsInDefaultProject",
"Effect": "Allow",
"Action": "bedrock-mantle:ListModels",
"Resource": "arn:aws-us-gov:bedrock-mantle:us-gov-west-1:<ACCOUNT_ID>:project/default"
},
{
"Sid": "InvokeGPT54InDefaultProject",
"Effect": "Allow",
"Action": "bedrock-mantle:CreateInference",
"Resource": "arn:aws-us-gov:bedrock-mantle:us-gov-west-1:<ACCOUNT_ID>:project/default",
"Condition": {
"StringEquals": {
"bedrock-mantle:Model": "openai.gpt-5.4"
}
}
}
]
}
Least privilege note: Every AWS account has a default Mantle project, and requests that omit a project ID use it. The policy keeps bearer-token permissions on Resource: "*", scopes ListModels and CreateInference to the default project, and restricts inference to openai.gpt-5.4. If you use a custom project, create the client with OpenAI(project="<PROJECT_ID>") and scope the resource ARN to that project.
For more information, see the Mantle service authorization reference and Projects documentation.
Verify the AWS GovCloud (US) Session
Run the examples from a local development workstation or approved administrative host with AWS Command Line Interface (AWS CLI) v2, network access to AWS GovCloud (US) endpoints, and credentials for the target AWS GovCloud (US) account. Set the profile and Region, replacing govcloud with your AWS CLI profile name.
export AWS_PROFILE=govcloud
export AWS_REGION=us-gov-west-1
export AWS_DEFAULT_REGION=us-gov-west-1
aws sts get-caller-identity --region "$AWS_REGION"
Confirm that the returned Amazon Resource Name (ARN) starts with arn:aws-us-gov:. The aws-us-gov partition proves that the command is using AWS GovCloud (US) credentials. Stop here if the ARN uses the commercial arn:aws: partition.
Install the Python Packages
Create a virtual environment and install the required packages:
python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install openai==2.41.1 aws-bedrock-token-generator==1.1.0
Short-term Amazon Bedrock API keys inherit the permissions of the AWS principal that creates them. They’re scoped to one Region and last for up to 12 hours or the remaining duration of the underlying AWS session, whichever is shorter. You can visit the Amazon Bedrock API keys documentation to learn more.
Create the Shared Client
Create a file named bedrock_client.py:
from __future__ import annotations
import json
import os
import urllib.request
from aws_bedrock_token_generator import provide_token
from openai import OpenAI
REGION = os.getenv("AWS_REGION", "us-gov-west-1")
MODEL_ID = "openai.gpt-5.4"
HOST = f"https://bedrock-mantle.{REGION}.api.aws"
def validate_region() -> None:
if REGION != "us-gov-west-1":
raise RuntimeError(
"Set AWS_REGION=us-gov-west-1 for OpenAI GPT-5.4 "
"in AWS GovCloud."
)
def new_client() -> OpenAI:
validate_region()
return OpenAI(
base_url=f"{HOST}/openai/v1",
api_key=provide_token(region=REGION),
)
def list_model_ids() -> list[str]:
validate_region()
token = provide_token(region=REGION)
request = urllib.request.Request(
f"{HOST}/v1/models",
headers={"Authorization": f"Bearer {token}"},
)
with urllib.request.urlopen(request, timeout=30) as response:
payload = json.loads(response.read().decode("utf-8"))
return sorted(item["id"] for item in payload.get("data", []))
if __name__ == "__main__":
for model_id in list_model_ids():
print(model_id)
Run the file:
python bedrock_client.py
A successful response includes openai.gpt-5.4 and confirms the identity, Region, short-term key, endpoint, and model availability work together.
Data Retention
Region when store=True, the Responses API default. These examples set store=False, which disables customer-retrievable response storage. store=False alone is not sufficient for zero data retention.
Under the default retention mode, AWS retains classifier-flagged GPT-5.4 inputs and outputs for up to 30 days for automated offline abuse detection. Full zero data retention (ZDR) requires the effective account or project data_retention_mode to be none and none to appear in GPT-5.4’s allowed_modes. Eligible customers can request that model-specific approval through their AWS account team. For more details, check out the Amazon Bedrock data retention and Amazon Bedrock abuse detection documentation.
Example 1: Analyze an Incident Timeline
Reasoning effort and text verbosity are separate request controls. This request asks GPT-5.4 to distinguish facts from inferences while keeping the response concise.
Create reasoning_example.py:
from __future__ import annotations
from bedrock_client import MODEL_ID, new_client
INCIDENT = """
08:04 - Sign-in failures rose from 3/minute to 220/minute.
08:07 - The identity team disabled the affected service account.
08:09 - API error rates returned to baseline.
08:14 - No privileged role changes were found in the audit log.
08:22 - The source IP block mapped to an approved vulnerability scanner.
""".strip()
def run(client) -> str:
response = client.responses.create(
model=MODEL_ID,
store=False,
reasoning={"effort": "medium"},
text={"verbosity": "low"},
input=[
{
"role": "developer",
"content": (
"Separate observed facts, inferences, and unresolved questions. "
"Keep the response under 220 words."
),
},
{
"role": "user",
"content": (
"Analyze the incident timeline. Return an executive summary, "
f"likely cause, immediate actions, and evidence gaps.\n\n{INCIDENT}"
),
},
],
)
return response.output_text
if __name__ == "__main__":
print(run(new_client()))
Run the example:
python reasoning_example.py
A successful response contains an executive summary, likely cause, immediate actions, and evidence gaps. The exact wording can vary between runs. A reviewer should verify every factual statement against the source timeline.
Example 2: Create a Strict Incident Record
Use structured outputs when downstream code needs predictable fields and types. This script turns the same timeline into a JSON incident record while keeping observed facts and missing evidence in separate fields.
Create structured_output_example.py:
from __future__ import annotations
import json
from bedrock_client import MODEL_ID, new_client
INCIDENT = """
08:04 - Sign-in failures rose from 3/minute to 220/minute.
08:07 - The identity team disabled the affected service account.
08:09 - API error rates returned to baseline.
08:14 - No privileged role changes were found in the audit log.
08:22 - The source IP block mapped to an approved vulnerability scanner.
""".strip()
SCHEMA = {
"type": "object",
"properties": {
"incident_summary": {"type": "string"},
"likely_cause": {"type": "string"},
"observed_facts": {
"type": "array",
"items": {"type": "string"},
},
"evidence_gaps": {
"type": "array",
"items": {"type": "string"},
},
"immediate_actions": {
"type": "array",
"items": {"type": "string"},
},
"severity": {
"type": "string",
"enum": ["low", "medium", "high", "critical"],
},
},
"required": [
"incident_summary",
"likely_cause",
"observed_facts",
"evidence_gaps",
"immediate_actions",
"severity",
],
"additionalProperties": False,
}
def run(client) -> dict:
response = client.responses.create(
model=MODEL_ID,
store=False,
reasoning={"effort": "low"},
input=(
"Create an incident record from the timeline. Put only explicit timeline "
"statements in observed_facts. Put missing evidence in evidence_gaps, "
f"and do not present an inference as a fact.\n\n{INCIDENT}"
),
text={
"format": {
"type": "json_schema",
"name": "identity_incident",
"strict": True,
"schema": SCHEMA,
}
},
)
return json.loads(response.output_text)
if __name__ == "__main__":
print(json.dumps(run(new_client()), indent=2))
Run the example:
python structured_output_example.py
Confirm that the output is valid JSON, contains all six required fields, and uses one of the four allowed severity values. Schema validity proves the shape of the response; it doesn’t prove that the content is factually correct.
Example 3: Connect the Review to a Local Control Lookup
With function calling, the application defines tools, executes approved operations, and returns tool results to the model. This script connects the incident review to an example local AC-2 control summary.
Create tool_use_example.py:
from __future__ import annotations
import json
from bedrock_client import MODEL_ID, new_client
CONTROLS = {
"AC-2": (
"Illustrative local summary: Review accounts on the schedule defined by "
"your organization, and disable accounts that no longer meet access "
"requirements."
)
}
TOOLS = [
{
"type": "function",
"name": "lookup_control",
"description": "Return the local summary for a security control.",
"parameters": {
"type": "object",
"properties": {"control_id": {"type": "string"}},
"required": ["control_id"],
"additionalProperties": False,
},
"strict": True,
}
]
PROMPT = (
"Use lookup_control for AC-2, then return a three-item follow-up checklist "
"for the service-account incident."
)
def run(client) -> str:
first = client.responses.create(
model=MODEL_ID,
store=False,
reasoning={"effort": "low"},
tools=TOOLS,
tool_choice="required",
input=PROMPT,
)
tool_outputs = []
for item in first.output:
if item.type == "function_call" and item.name == "lookup_control":
arguments = json.loads(item.arguments)
result = CONTROLS.get(arguments["control_id"], "Control not found")
tool_outputs.append(
{
"type": "function_call_output",
"call_id": item.call_id,
"output": result,
}
)
if not tool_outputs:
raise RuntimeError("The model did not request lookup_control")
final = client.responses.create(
model=MODEL_ID,
store=False,
tools=TOOLS,
input=[
{"role": "user", "content": PROMPT},
*[item.model_dump(exclude_none=True) for item in first.output],
*tool_outputs,
],
)
return final.output_text
if __name__ == "__main__":
print(run(new_client()))
Run the example:
python tool_use_example.py
The script makes two Responses API calls and prints a three-item checklist. In a production application, validate tool names and arguments, authorize each requested operation, limit side effects, and log the application decision before executing a tool.
Evaluate and Operate the Workflow
Evaluate Output Quality
Build a small evaluation set from representative incident timelines, including ambiguous and incomplete cases. Review each response for:
- Source fidelity – Every claimed fact is supported by the supplied timeline
- Fact and inference separation – Likely causes aren’t labeled as observed facts
- Completeness – Required fields and important evidence gaps are present
- Action safety – Recommendations preserve human approval for consequential changes
- Consistency – Repeated runs remain within the required schema and decision criteria
Operate the request path
After your request reaches the approved endpoint, these operational controls confirm it stays more secure, auditable, and cost-effective throughout its lifecycle:
- Use short-lived AWS credentials and the narrowest runtime policy that supports the application
- Apply your agency’s data classification, logging, retention, and incident-handling requirements to prompts, outputs, and application logs
- Add timeouts, bounded retries, quota handling, and cost monitoring before production use
- Keep a named human owner for incident classification, account actions, and final remediation decisions
Considerations for Production
The following settings and patterns address common operational gaps when moving from prototype to production workloads in AWS GovCloud (US):
Control Output Length
The examples omit max_output_tokens for brevity. In production, set an explicit limit to bound cost and latency per request. Choose a value that accommodates your longest expected response. Structured output responses with large schemas might need higher limits than free-text responses.
Rotate Short-Term API Keys in Long-Running Workloads
Bedrock API keys expire after 12 hours or the remaining duration of the underlying AWS session, whichever is shorter. For services that run continuously, such as AWS Lambda APIs, AWS Step Functions workflows, or container workloads, generate a fresh key before each request or cache it for substantially less than 12 hours.
Handle Refusals and Empty Outputs
The model might decline a request or return an empty response if the input conflicts with its usage policy. Check for empty output_text and inspect the status field before passing results downstream.
Set store=False Consistently
All examples in this post disable server-side response storage. Adopt this as the default for AWS GovCloud (US) workloads that don’t require the List or Retrieve Responses API operations. For workloads subject to ZDR requirements, work with your AWS account team on enablement.
Clean Up
These examples create no persistent AWS resources. When you finish, clear the shell variables that contain session state:
unset AWS_PROFILE AWS_REGION AWS_DEFAULT_REGION
Deactivate the virtual environment with deactivate. You can also delete the local virtual environment and example scripts.
Conclusion
You verified an aws-us-gov identity, discovered GPT-5.4 at the regional Mantle endpoint, and used three core capabilities in one incident review workflow: reasoning, structured outputs, and function calling.
Before deployment, verify current regional model availability and test the exact identity, Region, model ID, and endpoint used by your application.
Next Steps
Start by running the examples with representative, non-sensitive incident data in an AWS GovCloud (US) development environment. Then adapt the incident schema, evaluation set, and local control lookup to your agency’s policies and approval workflow before moving toward production.