Trace Bedrock Requests in Lambda
Invoke Claude Haiku from Lambda and trace IAM failures and token usage.
Introduction
30 Second Summary
Generated answers often arrive in seconds, while the path behind them stays hidden. When that path fails or costs more than expected, the answer alone gives you few clues.
In this project, you will build a request tracer that sends a prompt from AWS Lambda to Claude Haiku 4.5 in Amazon Bedrock. You will expose an IAM permission failure before tracing the successful response with its token usage in Amazon CloudWatch Logs.
What You'll Build
Your final Lambda test returns a Claude sentence with token counts in the console before the matching CloudWatch record reveals the complete trace.
By the end of this project, you'll have:
- A model baseline that lets you compare Claude Haiku 4.5 in the Bedrock playground with the response returned by Lambda.
- A permission boundary demo where AccessDeniedException exposes the missing bedrock:InvokeModel action before the same test succeeds.
- A request trace that shows generated text alongside inputTokens, outputTokens, totalTokens, and sdkVersion in CloudWatch Logs.
- Secret Mission: Accept a custom prompt from each Lambda test event while keeping the original prompt as a safe default.
Are There Any Prerequisites?
You need a Windows computer plus an AWS account with a valid payment method and permission to create Lambda functions, create or update IAM roles, and invoke Amazon Bedrock models. Model requests are usage-based through AWS Marketplace, so this project limits you to three short invocations.
Before We Start
Before the hands-on work begins, this checkpoint connects your Bedrock Request Tracer to the cost-governance dashboard it prepares you to build. Seeing an IAM permission failure reveals which identity controls access. Tracking token usage shows the data that future cost monitoring depends on.
Set Up Windows Tools and AWS Authentication
The later cloud steps assume your Windows terminal can run Python commands through an authenticated AWS CLI. A missing runtime or unsigned session would stop the tracer before it reaches the model.
This step prepares PowerShell with Python 3.14.7 plus the AWS CLI. You also connect the CLI to your AWS identity in us-east-1.
In this step, get ready to:
- Install Python 3.14.7 on Windows.
- Install AWS CLI version 2.32.0 or later.
- Authenticate through your console identity or IAM Identity Center.
Install and verify Python 3.14.7
The Python Install Manager provides the recommended Windows installation path. A version check reveals whether the required runtime is already available.
- Press the Windows key to open the Windows search bar.
- Type PowerShell and press Enter to open it.
- Check the selected Python version by running this command:
python --version
What does this check show?
This version check reports the Python runtime that PowerShell selects. The project requires Python 3.14.7.
✔️ I see the required Python version
Python 3.14.7 is ready. PowerShell can now run the runtime required by this project.
ⓧ I see another Python version
PowerShell is selecting a different Python runtime. Install the required release before continuing.
- Install Python 3.14.7 through the Python Install Manager by following the official Windows guide.
The Python Install Manager reports when the installation is complete.
- Close PowerShell.
- Press the Windows key to reopen the Windows search bar.
- Type PowerShell and press Enter to reopen it.
- Confirm the selected Python runtime by running this command:
python --version
What confirms the installation?
PowerShell should now report Python 3.14.7. This confirms the new terminal session can find the required runtime.
Still seeing another Python version?
Close every PowerShell window after the installation completes. Open a new window so Windows can load the updated Python selection.
Help me get Python 3.14.7 working in PowerShell.
ⓧ PowerShell cannot find Python
Python still needs to be installed for your Windows user. The official Windows guide provides the Python Install Manager setup path.
- Install Python 3.14.7 through the Python Install Manager by following the official Windows guide.
The Python Install Manager reports when the installation is complete.
- Close PowerShell.
- Press the Windows key to reopen the Windows search bar.
- Type PowerShell and press Enter to reopen it.
- Confirm that PowerShell can find Python by running this command:
python --version
What confirms the installation?
PowerShell should report Python 3.14.7. This confirms Windows can find the installed runtime.
PowerShell still cannot find Python?
Confirm that the Python Install Manager finished installing Python 3.14.7. Restart PowerShell after the installation completes.
Help me make Python available in PowerShell.
Install the AWS CLI
The AWS CLI lets PowerShell send authenticated commands to AWS. Version 2.32.0 or later supports the browser-based login used in this project.
- Check the installed AWS CLI version by running this command:
aws --version
What does this check show?
This version check reports the AWS CLI release available in PowerShell. You need version 2.32.0 or later for the next substep.
✔️ I see the required AWS CLI version
The AWS CLI is ready for browser-based authentication. You can continue to the authentication substep.
ⓧ I see an older AWS CLI version
The installed AWS CLI predates the login flow used here. The current-user installer updates it without creating an AWS resource.
- Install the current AWS CLI release for your Windows user by running this command:
irm https://awscli.amazonaws.com/v2/install.ps1 | iex
What does this installer do?
This PowerShell installer downloads the AWS CLI for the current Windows user. The prompt returns when the installation finishes.
- Close PowerShell.
- Press the Windows key to reopen the Windows search bar.
- Type PowerShell and press Enter to reopen it.
- Confirm the updated AWS CLI version by running this command:
aws --version
What confirms the update?
The output should report AWS CLI version 2.32.0 or later. This confirms the new PowerShell session can use the browser login command.
Installer or version check failing?
Check that PowerShell can access the internet. Close every PowerShell window after the installer finishes before checking the version again.
Help me update the AWS CLI on Windows.
ⓧ PowerShell cannot find the AWS CLI
The AWS CLI still needs to be installed for your Windows user. The official installer handles the download from PowerShell.
- Install the AWS CLI for your Windows user by running this command:
irm https://awscli.amazonaws.com/v2/install.ps1 | iex
What does this installer do?
This PowerShell installer downloads the AWS CLI for the current Windows user. The prompt returns when the installation finishes.
- Close PowerShell.
- Press the Windows key to reopen the Windows search bar.
- Type PowerShell and press Enter to reopen it.
- Confirm that PowerShell can find the AWS CLI by running this command:
aws --version
What confirms the installation?
The output should report AWS CLI version 2.32.0 or later. This confirms the CLI is available in your new PowerShell session.
PowerShell still cannot find the AWS CLI?
Confirm that the installer command finished before closing PowerShell. Open a new PowerShell window so Windows can load the installed command.
Help me make the AWS CLI available in PowerShell.
Authenticate and verify your AWS identity
AWS commands run as the identity attached to the active CLI session. This sign-in keeps long-lived access keys out of PowerShell by using short-lived credentials.
Your authentication path depends on how your AWS account is managed. Choose the tab that matches the sign-in method you normally use.
AWS console identity
This path applies to root users plus IAM users or federated identities that sign in to the AWS console. The command opens a browser for authentication in us-east-1.
- Start the browser-based AWS sign-in by running this command:
aws login --region us-east-1
What does this login do?
The AWS CLI opens a browser so you can authenticate with your AWS console identity. It creates a short-lived CLI session for us-east-1.
- Complete the browser sign-in using the same identity you use for the AWS console.
- Return to PowerShell after the browser confirms the sign-in.
IAM identity denied during login?
An IAM identity needs the AWS managed policy SignInLocalDevelopmentAccess for this login flow.
- Ask your AWS administrator to grant the required managed policy.
Help me resolve an AWS CLI login denial.
IAM Identity Center
IAM Identity Center accounts use an organization-managed SSO flow. Your organization controls the correct sign-in instructions for this path.
- Follow your organization's IAM Identity Center sign-in instructions in PowerShell.
- Complete the browser sign-in using your work identity.
- Return to PowerShell after the sign-in succeeds.
Organization sign-in failing?
Your AWS administrator controls the Identity Center configuration. Ask them to confirm the account plus permission set assigned to your work identity.
Help me diagnose my IAM Identity Center sign-in.
Before you run the final check, which AWS account and principal do you expect the CLI to report?
- Verify both tools plus the active AWS identity by running these commands:
python --version
aws --version
aws sts get-caller-identity
What do these checks prove?
- The first check confirms PowerShell selects Python 3.14.7.
- The second check confirms the AWS CLI is version 2.32.0 or later.
- The identity check returns a JSON response containing Account, UserId, and Arn.
You have cleared the setup barrier with working tools plus an authenticated AWS identity. PowerShell now shows Python 3.14.7, an AWS CLI version of 2.32.0 or later, and the active principal details.
Identity check not succeeding?
Complete the authentication flow again if the session has expired. Confirm that your organization allows the selected identity to use the AWS CLI.
Help me diagnose my AWS CLI identity check.
Your Windows environment is ready. Next, you'll use your authenticated identity to run your first prompt in Amazon Bedrock.
Make Your First Bedrock Request
Your verified CLI identity proves that your local tools can reach AWS. A successful Amazon Bedrock playground request checks whether this account can use a foundation model in the selected AWS Region.
The playground gives you a visible baseline before AWS Lambda enters the request path. If the later Lambda request fails, this working result points your investigation toward the function's IAM execution role.
In this step, get ready to:
- Reach the Amazon Bedrock Text playground in US East (N. Virginia).
- Select Claude Haiku 4.5 for the request.
- Capture a saved baseline response from the model.
Reach the Text playground
The model playground lets you test a prompt without writing application code. Keeping it in us-east-1 aligns this check with the Lambda request you build later.
- Sign in to the AWS Management Console using the same AWS identity you verified in PowerShell.
- Use the Region control in the top navigation bar to select US East (N. Virginia) (us-east-1).
The console's Region indicator now shows US East (N. Virginia).
- Enter Amazon Bedrock in the console search field.
- Select Amazon Bedrock from the search results.
- Choose Text under Playgrounds in the left navigation.
You'll see the Text playground with a prompt area plus a model selection control.
Why start in the playground?
A local Boto3 script would add SDK authentication plus package setup before the first model response.
The playground isolates model access from Lambda's execution role. A visible response gives you a clean baseline for later troubleshooting.
Select Claude Haiku 4.5
Claude Haiku 4.5 usage is billed through AWS Marketplace. Billing setup can feel sensitive.
This step limits activity to one short request. Anthropic may require first-time-use details before the first invocation.
- Choose Select model.
- Select Claude Haiku 4.5.
The model panel now shows Claude Haiku 4.5 with an option to apply it.
- Complete Anthropic's First Time Use details if the form opens.
- Add a valid payment method if a billing warning appears.
- Contact your AWS administrator if a Marketplace permissions warning appears.
Blocked by model access?
- Confirm that your AWS account has a valid payment method.
- Ask your administrator to allow aws-marketplace:Subscribe.
- Ask your administrator to allow aws-marketplace:Unsubscribe.
- Ask your administrator to allow aws-marketplace:ViewSubscriptions.
Help me understand my Bedrock model access warning.
- Choose Apply.
That access checkpoint is cleared. Claude Haiku 4.5 now appears as the selected model in the Text playground.
Capture a baseline response
A baseline is a known working response from your human AWS identity. You can compare it with the Lambda result after the execution role enters the request path.
- Review the live Amazon Bedrock pricing page before running the request.
- Check your Billing console to confirm that one short invocation fits your budget.
You now have current pricing plus account-spend context for this request.
- Return to the Text playground from earlier.
- Enter Explain an AWS IAM role in one sentence. in the prompt area.
Before you run it, do you expect the model to answer in exactly one sentence?
- Choose Run.
You'll see generated text below the prompt.
Good work. Your first Bedrock response is now the baseline for the Lambda build.
- Save the generated sentence for later comparison: your Claude Haiku 4.5 baseline response.
Your account can now reach Claude Haiku 4.5 through the Bedrock playground. Next, you'll create a logged Python Lambda with a visible test result.
Create a Logged Python Lambda
Your saved Claude Haiku 4.5 response proves that Amazon Bedrock works for your signed-in console identity. The tracer still needs a function that can receive events under its own cloud identity.
An AWS Lambda function uses an AWS Identity and Access Management (IAM) execution role when it runs. Amazon CloudWatch Logs captures the text that the function prints.
In this step, you'll create that function with basic logging access. You'll deploy a small handler that proves the event path plus the log path with one test.
In this step, get ready to:
- Create the BedrockRequestTracer Lambda function with a basic execution role.
- Deploy a Python handler that returns a readiness message.
- Run a private test event and trace the printed message in CloudWatch Logs.
Create the Lambda function
The function's runtime determines how AWS executes your handler. Its architecture determines the processor type used for each invocation.
- Use the AWS Management Console search to find AWS Lambda.
- Select AWS Lambda to open its service console.
- Confirm the Region in the console header shows US East (N. Virginia) (us-east-1).
- Choose Create function.
- Select Author from scratch.
- Enter BedrockRequestTracer as the Function name.
- Select Python 3.14 from the Runtime menu.
- Select x86_64 for the Architecture.
Why use a separate execution role?
An execution role gives the function its AWS permissions while it runs. The default role created by the Lambda console includes basic permission to send output to CloudWatch Logs.
Keeping permissions attached to the function makes each request traceable to a specific cloud identity.
- Keep the option that creates a new role with basic Lambda permissions.
- Choose Create function.
Your new BedrockRequestTracer function opens with lambda_function.py in the built-in code editor. That is the function shell ready for your tracer handler.
Function creation blocked?
Your AWS identity needs permission to create Lambda functions plus their execution roles. If the console blocks creation, ask your AWS account administrator for those permissions.
Help me diagnose why my AWS identity cannot create the Lambda function or its execution role.
Deploy the logged handler
A Lambda handler receives the test event through its event parameter. This handler converts its result into JSON for both the test response and the log record.
- Select lambda_function.py in the built-in code editor.
- Replace the starter handler with the logged readiness handler by using the code below:
import json
def lambda_handler(event, context):
result = {
"status": "tracer-ready",
"message": "Lambda can receive an event and write logs.",
}
print(json.dumps(result))
return {
"statusCode": 200,
"body": json.dumps(result),
}
What does this code do?
- The import json line provides the conversion used for the response plus the log record.
- The lambda_handler(event, context) function is the entry point that Lambda invokes.
- The result dictionary holds the readiness status plus a human-readable message.
- The print(json.dumps(result)) line sends the result to the function's log stream.
- The return value gives the test runner a statusCode of 200 plus the serialized result in body.
- Choose Deploy in the DEPLOY section to publish lambda_function.py.
- Confirm the function page reports that lambda_function.py was deployed.
Seeing a deployment problem?
- Confirm that lambda_function.py contains only the code shown above.
- Check that both json.dumps(result) calls include their closing parentheses.
- Check that the closing braces align with their matching dictionaries.
Help me find the syntax problem in my Lambda handler.
✔️ Awesome, I've got everything!
Your readiness handler is deployed. Double-check that you chose Deploy after replacing the starter code.
ⓧ I'd like to double check the full code
import json
def lambda_handler(event, context):
result = {
"status": "tracer-ready",
"message": "Lambda can receive an event and write logs.",
}
print(json.dumps(result))
return {
"statusCode": 200,
"body": json.dumps(result),
}
Test the function and inspect its logs
A private test event lets you invoke the handler without creating an external trigger. The empty object {} is enough because this readiness handler does not require input.
- Select the Test tab on the function page.
- Choose Create new event.
- Name the private event TracerTest.
- Keep the event private.
- Set the Event JSON to {}.
- Choose Save changes.
Before you run the event, what status plus readiness message do you expect the handler to return?
- Run TracerTest by choosing Test.
In the OUTPUT area, you'll see status code 200 plus tracer-ready. That is your first complete Lambda execution.
The returned result proves the response path works. Now the printed copy can prove the logging path works.
- Select the Monitor tab on the function page.
- Choose View CloudWatch logs.
- Select the newest log stream in /aws/lambda/BedrockRequestTracer.
- Find the JSON record printed by the handler.
You'll see {"status": "tracer-ready", "message": "Lambda can receive an event and write logs."} in the newest stream. The matching result proves that Lambda can receive an event plus preserve its printed evidence in CloudWatch Logs.
Can't find the tracer record?
- Confirm that TracerTest completed with status code 200 before checking the logs.
- Confirm that you selected the newest stream inside /aws/lambda/BedrockRequestTracer.
- Confirm that the function's execution role still has its basic Lambda logging permissions.
Help me trace why my successful Lambda test is missing from CloudWatch Logs.
Your function now receives test events and leaves a matching CloudWatch record. Next, you'll connect the handler to Claude Haiku 4.5 and test the execution role's current permission boundary.
Hit the IAM Permission Boundary
Your playground request used your console identity. The same model call from AWS Lambda uses the function's execution role.
The role already writes to Amazon CloudWatch Logs through its basic permissions. A request to Amazon Bedrock crosses a separate AWS Identity and Access Management (IAM) boundary.
This step lets a real invocation reveal which identity makes the request. You can then trace the role's current permissions from the test result into the logs.
In this step, get ready to:
- Configure a Boto3 client for the Bedrock runtime.
- Replace the readiness handler with a Bedrock request.
- Trace the test result to the Lambda execution role.
Add the Bedrock client configuration
The Lambda runtime already includes Boto3. The client configuration identifies the model service and Region that the handler uses.
- Return to BedrockRequestTracer in AWS Lambda from the previous step.
- In the existing lambda_function.py editor, select the import section above def lambda_handler(event, context):.
- Replace that selection with the configuration below:
import json
import boto3
MODEL_ID = "anthropic.claude-haiku-4-5-20251001-v1:0"
DEFAULT_PROMPT = "Explain an AWS IAM role in one sentence."
bedrock = boto3.client("bedrock-runtime", region_name="us-east-1")
What does this configuration do?
- The MODEL_ID value points to Claude Haiku 4.5.
- The DEFAULT_PROMPT value holds the sentence that the model receives.
- The bedrock client targets bedrock-runtime in us-east-1.
- Creating the client prepares the service connection. The existing handler still controls what runs during this first check.
- Choose Deploy in the DEPLOY section.
Lambda confirms that the updated source is deployed.
- Select TracerTest from your saved test events.
- Choose Test.
You should still see status code 200 with tracer-ready. The client now loads without changing the handler's response.
Does the readiness test fail?
Confirm that the original lambda_handler() remains below the new configuration. An incomplete selection can remove part of that handler.
Compare the import names and quotation marks with the code block above. Help me diagnose this readiness test
Send the request with the current role
The Converse API accepts a user message and returns generated text. Its response also includes token usage for the request.
The new handler sends the default prompt through the client you just configured. It logs the response fields that the tracer needs.
- In lambda_function.py, select the existing handler from def lambda_handler(event, context): through its closing return block.
- Replace the selected handler with the code below:
def lambda_handler(event, context):
response = bedrock.converse(
modelId=MODEL_ID,
messages=[
{
"role": "user",
"content": [{"text": DEFAULT_PROMPT}],
}
],
inferenceConfig={"maxTokens": 128},
)
result = {
"modelId": MODEL_ID,
"response": response["output"]["message"]["content"][0]["text"],
"usage": response["usage"],
"sdkVersion": boto3.__version__,
}
print(json.dumps(result))
return {
"statusCode": 200,
"body": json.dumps(result),
}
How does the handler trace a request?
- The bedrock.converse() call sends the user message to the model.
- The maxTokens value limits the generated response to 128 tokens.
- The result dictionary collects the generated text and usage data.
- The sdkVersion field records the Boto3 version supplied by the Lambda runtime.
- The print() call sends the result to the function's log stream.
- Choose Deploy in the DEPLOY section.
Lambda confirms that the Bedrock handler is deployed.
Before you run the test, do you think the current execution role can complete the model request?
- Select the existing TracerTest event.
- Choose Test.
You'll see an AccessDeniedException that mentions bedrock:InvokeModel. That failure is the intended result because the request has reached the IAM permission boundary.
- Expand the failed execution details.
- Find the caller identity named in the denial.
The denial identifies the Lambda execution role as the caller. Your console identity only deployed the code and started the test.
Seeing a different result?
If the result points to the model or Region, confirm that MODEL_ID and us-east-1 match the full-file reference below.
If the test still returns tracer-ready, deploy the replacement handler before running the event again. Help me diagnose my Lambda test result
✔️ Awesome, I've got everything!
Your deployed file now contains the complete Bedrock request tracer. The permission failure confirms that the handler reached the model invocation.
ⓧ I'd like to double check the full code
import json
import boto3
MODEL_ID = "anthropic.claude-haiku-4-5-20251001-v1:0"
DEFAULT_PROMPT = "Explain an AWS IAM role in one sentence."
bedrock = boto3.client("bedrock-runtime", region_name="us-east-1")
def lambda_handler(event, context):
response = bedrock.converse(
modelId=MODEL_ID,
messages=[
{
"role": "user",
"content": [{"text": DEFAULT_PROMPT}],
}
],
inferenceConfig={"maxTokens": 128},
)
result = {
"modelId": MODEL_ID,
"response": response["output"]["message"]["content"][0]["text"],
"usage": response["usage"],
"sdkVersion": boto3.__version__,
}
print(json.dumps(result))
return {
"statusCode": 200,
"body": json.dumps(result),
}
How does the full file fit together?
The top section configures the Bedrock client. The handler sends the prompt and prepares the response fields for logging.
Trace the denied caller in CloudWatch Logs
The handler stops when the model request is denied, so it never reaches its own print() call. Lambda still writes the platform-generated failure record through the role's basic logging permissions.
Before you inspect the newest stream, which AWS identity do you expect the denial to name?
- In BedrockRequestTracer, choose Monitor.
- Choose View CloudWatch logs.
- Select the newest log stream.
- Find the failure record from your latest TracerTest invocation.
- Locate bedrock:InvokeModel in the denial.
You should see the Lambda execution role named as the caller and bedrock:InvokeModel named as the missing action. This log proves that the function uses its own AWS identity for the Bedrock request.
You have traced a model request to the exact IAM boundary that stopped it. Next, you'll grant the single missing action and follow the successful response into CloudWatch Logs.
Grant Bedrock Access and Trace the Response
Your earlier test proved that AWS Lambda runs with its execution role. Amazon Bedrock denied the request because that role could only write logs.
You will add only bedrock:InvokeModel through AWS Identity and Access Management (IAM). This completes the request path without granting broad Bedrock administration access.
The successful request creates a record in Amazon CloudWatch Logs. The record shows generated text beside token counts.
In this step, get ready to:
- Embed a minimal invocation policy in the Lambda execution role.
- Run the existing test event with the new permission.
- Trace the generated response through its CloudWatch log record.
Grant the missing Bedrock permission
An inline policy lives directly on one role. Its Action entry defines the API operations that role can perform.
Editing a cloud role can feel high stakes. This policy adds one Bedrock action to the role used by BedrockRequestTracer.
- Switch back to the BedrockRequestTracer function in AWS Lambda.
- Select Configuration.
- Select Permissions.
- Choose the linked role name in the Execution role area.
- Select Permissions on the IAM role page.
- Choose Add permissions.
- Choose Create inline policy.
- Choose JSON in the policy editor.
- Replace the editor document by pasting this policy:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "InvokeClaudeHaiku",
"Effect": "Allow",
"Action": "bedrock:InvokeModel",
"Resource": "*"
}
]
}
What Does This Policy Allow?
- The Effect value grants the permission described by the statement.
- The Action entry allows the operation required by the Converse request.
- The Resource entry applies that action to the Bedrock resources selected by the function.
- The policy keeps its action scope to model invocation. Bedrock administration actions remain unavailable.
- Enter AllowBedrockInvoke as the policy name.
- Choose Create policy.
- Confirm that the role's permissions list shows AllowBedrockInvoke as an inline policy.
That permission gap is now closed. Your function can request model inference while its existing logging access stays intact.
Can't Create the Inline Policy?
- Confirm that you followed the role link from BedrockRequestTracer.
- Ask your AWS account administrator for permission to update the function's execution role.
Get help with adding the inline policy to the Lambda execution role.
Run the request again
The handler already sends the default prompt through the Converse API. The role change supplies the permission that request needs.
This Request Is Usage-Based
This test sends one short request billed through AWS Marketplace. The project limits activity to three short model invocations.
Before you test again, predict whether the execution role can reach Claude this time.
- Return to the BedrockRequestTracer function from the IAM role page.
- Select the Test tab.
- Confirm that TracerTest is the selected test event.
- Choose Test to invoke the function.
This time, the execution result shows status code 200. The response body includes a generated sentence.
That is the boundary crossed: the same function now reaches Claude using its own execution role.
- Expand the successful execution result.
- Compare the generated sentence with the baseline response from the Bedrock playground.
- Inspect the returned usage object.
The usage object shows inputTokens, outputTokens, and totalTokens for this invocation.
Still Seeing AccessDeniedException?
- Confirm that AllowBedrockInvoke appears on the execution role linked from BedrockRequestTracer.
- Confirm that the policy's Action value is exactly bedrock:InvokeModel.
Get help diagnosing the remaining Lambda permission denial.
Your source file stays unchanged because the permission fix belongs to the execution role. Use these tabs to confirm that lambda_function.py still matches the deployed handler.
✔️ Awesome, I've got everything!
Great. Your deployed handler still matches the working Bedrock request tracer.
ⓧ I'd like to double check the full code
- Compare your deployed lambda_function.py with this complete file:
import json
import boto3
MODEL_ID = "anthropic.claude-haiku-4-5-20251001-v1:0"
DEFAULT_PROMPT = "Explain an AWS IAM role in one sentence."
bedrock = boto3.client("bedrock-runtime", region_name="us-east-1")
def lambda_handler(event, context):
response = bedrock.converse(
modelId=MODEL_ID,
messages=[
{
"role": "user",
"content": [{"text": DEFAULT_PROMPT}],
}
],
inferenceConfig={"maxTokens": 128},
)
result = {
"modelId": MODEL_ID,
"response": response["output"]["message"]["content"][0]["text"],
"usage": response["usage"],
"sdkVersion": boto3.__version__,
}
print(json.dumps(result))
return {
"statusCode": 200,
"body": json.dumps(result),
}
Why Does This File Stay the Same?
The handler already contained the complete Bedrock request logic. The new inline policy changes what its execution role can do.
Trace the response in CloudWatch Logs
The execution result proves that the caller received a response. The corresponding log record preserves the model output beside its usage data.
Before the final check, predict which details the successful invocation has recorded.
- Select Monitor on the Lambda function page.
- Choose View CloudWatch logs.
- Select the newest log stream.
- Find the most recent JSON record containing modelId, response, usage, and sdkVersion.
You'll see the generated text in response beside the model identifier. The usage object contains all three token counts.
What Does the Trace Tell You?
- The inputTokens value measures tokens sent to the model.
- The outputTokens value measures tokens generated by the model.
- The totalTokens value measures the complete token usage for the request.
- The sdkVersion value reports the Boto3 version supplied by the Lambda runtime.
Can't Find the Successful Log Record?
- Confirm that you selected the newest log stream after the successful test.
- Search the stream for sdkVersion to locate the JSON record printed by the handler.
Get help finding the successful invocation in CloudWatch Logs.
You now have a complete request trace from the Lambda execution role to Claude. The logs tie model output to measurable token usage.
Secret mission
Accept Prompts from Test Events
Your tracer currently sends the same prompt every time. Extend it so each Lambda test event can supply a prompt while preserving the default for empty events. Then trace the custom response and fresh token usage in CloudWatch Logs.
Clean Up Your Resources
Clean Up Your Resources
Your AWS Lambda function can stay available for later tests. You can also leave it idle or delete it with its logs and execution role.
Future Amazon Bedrock invocations remain usage-based.
Cost warning
Claude Haiku 4.5 invocations are billed through AWS Marketplace. Avoid running more test events if you want to prevent additional model usage.
- Check the live Amazon Bedrock pricing page before running more requests.
- Check your Billing console for the usage recorded by this project.
Resources you used:
- One AWS Lambda function named BedrockRequestTracer.
- One AWS Identity and Access Management (IAM) execution role created for BedrockRequestTracer. It has AWSLambdaBasicExecutionRole plus the AllowBedrockInvoke inline policy.
- One Amazon CloudWatch Logs log group named /aws/lambda/BedrockRequestTracer.
Keep everything running
No action is needed. Choose this option if you plan to start the cost-governance project soon or continue testing the tracer.
- Keep BedrockRequestTracer available for future test events.
- Keep the execution role attached to preserve its logging and Bedrock invocation permissions.
- Keep /aws/lambda/BedrockRequestTracer for your existing trace records.
Pause - I'll come back to this later
Leave the cloud resources in place without running more test events. This preserves your function and existing log data for a later session.
- Stop invoking the TracerTest test event.
- End your authenticated AWS CLI session by running this command:
aws logout
What does this command do?
The aws logout command ends the console-credential CLI session. Your Lambda function and existing CloudWatch Logs data remain available.
Delete - I don't want to use this again
Remove the function and its supporting AWS resources if you do not plan to use the tracer again.
This is permanent
Deleting the function and log group permanently removes the deployed tracer and its recorded output. Your local Python and AWS CLI installations remain on Windows.
- Return to the BedrockRequestTracer function in AWS Lambda.
- Select Configuration.
- Select Permissions.
- Open the execution role in a new browser tab.
- Confirm that you have not attached this execution role to another AWS resource.
- Delete the Lambda function and its CloudWatch Logs log group by running these commands:
aws lambda delete-function --function-name BedrockRequestTracer
aws logs delete-log-group --log-group-name /aws/lambda/BedrockRequestTracer
What do these commands remove?
- The delete-function command removes BedrockRequestTracer.
- The delete-log-group command removes /aws/lambda/BedrockRequestTracer with its stored log events.
- Return to the Lambda console to confirm that BedrockRequestTracer is no longer listed.
- Return to CloudWatch Logs to confirm that /aws/lambda/BedrockRequestTracer is no longer listed.
Cleanup commands blocked?
- Confirm that your CLI session uses the AWS account where you created the resources.
- Confirm that your CLI session uses us-east-1.
- Ask your AWS administrator for permission to delete the function or log group if access is blocked.
Help me diagnose the cleanup issue.
- Return to the IAM execution role page that you kept open.
- Delete the execution role created for BedrockRequestTracer.
- Return to the IAM role list.
- Confirm that the execution role no longer appears.
Nice Work!
Nice Work!
Excellent work! Your BedrockRequestTracer traces each event-driven prompt from AWS Lambda through Amazon Bedrock into Amazon CloudWatch Logs.
What you learned:
- Used short-lived authentication to verify the active principal behind the AWS CLI.
- Exposed an expected IAM permission boundary when the Lambda role lacked bedrock:InvokeModel. Granted only that missing action to complete the Bedrock request path.
- Captured generated text in CloudWatch Logs. The same JSON record exposes token usage. It also reports the runtime's Boto3 version.
- Secret Mission: Added an event-driven prompt to TracerTest. Preserved DEFAULT_PROMPT as the fallback for empty events.
Ready to quiz yourself?