Ever try to use a newly released model on Bedrock and hit the following error?
Error invoking model: An error occurred (AccessDeniedException) when calling the InvokeModel operation: You don't have access to the model with the specified model ID.
Welp, you haven't logged in to the console yet and requested access to said model. But, what if you don't have console access or try not to use the console at all?
Tough - you have to. (kind of)
In their Add or remove access to Amazon Bedrock foundation models documentation AWS states:
To add or remove access to foundation models:
1. Make sure you have permissions to request access, or modify access, to Amazon Bedrock foundation models.
2. Sign into the Amazon Bedrock console at https://console.aws.amazon.com/bedrock/.
3. In the left navigation pane, under Bedrock configurations, choose Model access.
4. On the Model access page, choose Modify model access.
5. Select the models that you want the account to have access to and unselect the models that you don't want the account to have access to. You have the following options:
Be sure to review the End User License Agreement (EULA) for terms and conditions of using a model before requesting access to it.
- Select the check box next to an individual model to check or uncheck it.
- Select the top check box to check or uncheck all models.
- Select how the models are grouped and then check or uncheck all the models in a group by selecting the check box next to the group. For example, you can choose to Group by provider and then select the check box next to Cohere to check or uncheck all Cohere models.
6. Choose Next.
7. If you add access to Anthropic models, you must describe your use case details. Choose Submit use case details, fill out the form, and then select Submit form. Notification of access is granted or denied based on your answers when completing the form for the provider.
8. Review the access changes you're making, and then read the Terms.
9. If you agree with the terms, choose Submit. The changes can take several minutes to be reflected in the console.
10. If your request is successful, the Access status changes to Access granted or Available to request.
Until now...
Even after AWS Support confirmed that the Console must be used in enabling new models:
After thorough investigation, I can confirm that model activation in Amazon Bedrock can currently only be performed through the AWS Management Console. While there are APIs available (create-foundation-model-agreement and put-use-case-for-model-access), these are solely for documentation and compliance purposes and do not actually enable model access.
However, it CAN be done via some undocumented API's. More details in this StackOverflow post for reverse engineering what the console actually does behind the scenes.
You're basically doing three things from within the Console:
1. Submit a use case form (one time per account)
When you first request model access, AWS wants to know what you're planning to do with it. Makes sense. There's a PutUseCaseForModelAccess API for this.
2. Create model agreements (for some models)
Some models like Claude need you to agree to their terms. You can do this with ListFoundationModelAgreementOffers API and CreateFoundationModelAgreement API. But some models don't require a FoundationModelAgreement - models like Amazon's Titan don't need agreements at all. From what I've seen it's only 3rd party models that need this Agreement.
3. Request entitlements
This is the part that isn't documented anywhere. Even after you've got agreements sorted, you need to hit an internal FoundationModelEntitlement
endpoint to actually turn on access. You can call it directly with proper AWS request signing.
The Script
import boto3
import json
import base64
import urllib.request
import sys
import os
from botocore.auth import SigV4Auth
from botocore.awsrequest import AWSRequest
from botocore.exceptions import ClientError
def enable_bedrock_model_access(model_ids, region=None):
# Auto-detect region if not specified
if region is None:
# Check AWS_REGION first (standard env var used by AWS CLI)
region = os.environ.get('AWS_REGION')
if not region:
# Fall back to boto3 session detection
session = boto3.Session()
region = session.region_name or 'us-east-1'
print(f"Using region: {region}")
bedrock_client = boto3.client('bedrock', region_name=region)
print("Checking use case status...")
# Submit use case (one time per account)
try:
bedrock_client.get_use_case_for_model_access()
print("✓ Use case already exists")
except ClientError as e:
if "You have not filled out the request form" not in str(e):
raise
print("Submitting use case...")
form_data = {
"companyName": "Your Company",
"companyWebsite": "https://yourcompany.com/",
"intendedUsers": "0", # 0 = internal employees
"industryOption": "Technology",
"otherIndustryOption": "",
"useCases": "Enterprise AI development and testing for internal applications. Building conversational AI tools for employee engagement and productivity improvements."
}
try:
# For boto3, do NOT base64 encode (only CLI needs base64)
bedrock_client.put_use_case_for_model_access(formData=json.dumps(form_data))
print("✓ Use case submitted")
except ClientError as form_error:
# If it fails in current region, try us-east-1 (use case might be global)
if region != 'us-east-1':
print(f"Use case submission failed in {region}, trying us-east-1...")
us_east_client = boto3.client('bedrock', region_name='us-east-1')
try:
us_east_client.put_use_case_for_model_access(formData=json.dumps(form_data))
print("✓ Use case submitted in us-east-1")
except ClientError as us_error:
print(f"ERROR: Use case submission failed in both {region} and us-east-1: {str(us_error)}")
raise
else:
print(f"ERROR: Use case submission failed: {str(form_error)}")
raise
for model_id in model_ids:
print(f"\nProcessing {model_id}...")
# Create agreement (if needed)
try:
offers = bedrock_client.list_foundation_model_agreement_offers(modelId=model_id)
if offers.get('offers'):
offer_token = offers['offers'][0]['offerToken']
bedrock_client.create_foundation_model_agreement(
modelId=model_id,
offerToken=offer_token
)
print(f"✓ Agreement created for {model_id}")
except ClientError as e:
if "Agreement not supported for this model" in str(e):
print(f"✓ {model_id} doesn't need an agreement")
elif "Agreement already exists" in str(e):
print(f"✓ Agreement already exists for {model_id}")
else:
raise
# Request entitlement
session = boto3.Session()
creds = session.get_credentials().get_frozen_credentials()
url = f'https://bedrock.{region}.amazonaws.com/foundation-model-entitlement'
request = AWSRequest(
method='POST',
url=url,
data=json.dumps({'modelId': model_id}),
headers={'Content-Type': 'application/x-amz-json-1.1'}
)
SigV4Auth(creds, 'bedrock', region).add_auth(request)
urllib_request = urllib.request.Request(
url, data=request.body, headers=dict(request.headers), method='POST'
)
urllib.request.urlopen(urllib_request)
print(f"✓ Entitlement successful for {model_id}")
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Usage: python3 bedrock_access.py <model_id> [model_id2] ...")
print("Example: python3 bedrock_access.py anthropic.claude-3-haiku-20240307-v1:0")
sys.exit(1)
models = sys.argv[1:]
enable_bedrock_model_access(models)
Important: Update the company details in
form_data
with your actual info.
How to use it
Model ID's can be found using the ListFoundationModels API. Or some can be found on AWS docs like here. Once you know the model ID you're requesting save the script as bedrock_access.py
and run it:
python3 bedrock_access.py anthropic.claude-3-haiku-20240307-v1:0
Here's what the output looks like when it works:
Checking use case status...
Submitting use case...
✓ Use case submitted
Processing anthropic.claude-3-haiku-20240307-v1:0...
✓ Agreement created for anthropic.claude-3-haiku-20240307-v1:0
✓ Entitlement successful for anthropic.claude-3-haiku-20240307-v1:0
You can also customise it:
# Single model
python3 bedrock_access.py anthropic.claude-3-haiku-20240307-v1:0
# Multiple models
python3 bedrock_access.py anthropic.claude-3-haiku-20240307-v1:0 amazon.titan-text-express-v1
# Any model you want
python3 bedrock_access.py meta.llama3-1-70b-instruct-v1:0
What's happening here
The console does three things that we're replicating:
Use case submission - AWS wants to know what you're building. This only happens once per account using
put_use_case_for_model_access
.Model agreements - Some models (like Claude) need you to agree to terms. Others (like Titan) don't. The script handles both by catching the "Agreement not supported" error.
Entitlement requests - This is the undocumented bit. Even with agreements sorted, you need to hit an internal endpoint to actually enable access.
Things to know
- You still need proper IAM permissions for Bedrock
- Be honest about your use case - you should edit this in the script
- The entitlement endpoint isn't officially documented, so it could change
Wrapping up
No more ClickOps to try out a new model. This script enables both the agreement-required models (like Claude) and the ones that don't need agreements (like Titan) automatically.
Now you can enable new models without ever accessing the console.
Big thanks to sihil who found the FoundationModelEntitlement
API and posted it on StackOverflow.
I'm trying to write a script that keeps the available Bedrock models in sync across multiple accounts (primarily to be sure that we have the same models available in DR as we do in production).
I've figured out how to check for and submit the use case (see this question…
Top comments (0)