AWS Public Sector Blog

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

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.4 through 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:

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.

David Sperry

David Sperry

David Sperry is an AI Success Engineer at OpenAI, where he helps government organizations adopt and operationalize AI. He works with public-sector leaders to turn OpenAI’s capabilities into practical solutions that drive mission outcomes.

Arun Mandalika

Arun Mandalika

Arun is a Technical Program Manager at Amazon Web Services. He focuses on driving AWS service expansion and Generative AI adoption across AWS GovCloud regions, helping customers build secure, compliant solutions at scale.

Karan Lakhwani

Karan Lakhwani

Karan Lakhwani is a Solutions Engineer at OpenAI, where he helps customers design and deploy production AI systems. His work centers on bridging AI capabilities and real-world applications, with an emphasis on scalability, reliability, and integration.

Kirk Horne

Kirk Horne

Kirk is a Senior Solutions Architect supporting the government regions at Amazon Web Services (AWS). He has helped customers migrating existing workloads into AWS and developing cloud-native workloads in AWS since 2015.

Shawn Asfeld

Shawn Asfeld

Shawn Asfeld is a Senior Solutions Architect for the AWS Global Government team. He has extensive experience working with federal and civilian agencies to build a large variety of secure and compliant workloads both on premises and in the cloud. Shawn's current focus is on helping customers and partners build solutions on AWS GovCloud (US) to meet various levels of compliance, including FedRAMP, CMMC, and DoD authorization — increasingly including how they adopt generative AI securely within those boundaries. Shawn earned a BS degree from Texas A&M University and is an AWS Certified Solutions Architect – Professional.