Lab 01 — Invoke a foundation model from Lambda
Scaffold: 5/5 (almost complete). The infrastructure and the wiring are done. You write one function body.
The scenario
A team wants the simplest possible thing: an HTTP-triggerable function that takes a prompt, asks a Bedrock model, and returns the answer. Everything around the model call is already built. The Lambda exists, it has an execution role that is allowed to call Bedrock, and the model id is handed to it in an environment variable.
The requirement
POST a prompt to the function and get the model’s answer back as JSON:
{ "answer": "Amazon Bedrock is a managed service that ..." }
What’s provided
template.yaml— a Lambda function and an IAM role scoped tobedrock:InvokeModelon Bedrock foundation models, plus the inference profiles in your account.src/handler.py— the function, with the request parsing and response helpers written. The one gap is the Bedrock call itself.scripts/— deploy, test, and teardown.solution/handler.py— the reference answer, if you want to check.
Your task
Open src/handler.py and implement the body of handler():
- Create a
bedrock-runtimeclient with boto3. - Call the Converse API with
MODEL_IDand the user’s prompt. - Return the assistant’s text through
_ok().
The docstring in src/handler.py has the exact request and response shapes. It
is about five lines of real code.
Run it
# 0. Prerequisite: in the Bedrock console, enable Model access for the model
# you plan to use, in your region. Nothing works until you do.
# 1. Deploy your version (defaults: stack genai-lab-01, region us-east-1,
# model amazon.nova-lite-v1:0).
./scripts/deploy.sh
# 2. Prove it.
./scripts/test.sh
./scripts/test.sh "Explain retrieval-augmented generation in two sentences."
# 3. Clean up when you are done.
./scripts/teardown.sh
Override the defaults with environment variables:
AWS_REGION=ap-southeast-2 MODEL_ID=amazon.nova-lite-v1:0 ./scripts/deploy.sh
The model id has to be one that region actually serves. Sydney has Nova Lite
in-region, so the bare id works there; a us. inference-profile id can only be
called from a US region.
What success looks like
./scripts/test.sh prints a JSON body with an answer field containing a real
sentence from the model. Before you fill the gap, you get a 501 (the template
placeholder) or a NotImplementedError in the logs.
If it fails
AccessDeniedExceptionnaming the model — nearly always the console gate: Model access is not enabled for that model, in that region. Turn it on in the Bedrock console. IAM refusals come back as the same error, so read the ARN in the message and check it against the role’s policy before you assume which gate is shut.ValidationExceptionabout on-demand throughput / “isn’t supported” — the model is only served through a cross-region inference profile. Redeploy with the profile id for the geography you are calling from, for exampleMODEL_ID=us.amazon.nova-lite-v1:0 ./scripts/deploy.shin a US region.- A different region — model availability varies by region, and so do the
ids: a
us.profile is callable only from a US region.us-east-1has the widest selection.
Reveal the solution
Deploy the reference answer without editing anything:
SRC=solution ./scripts/deploy.sh && ./scripts/test.sh
What you just learned
- A Bedrock call is an ordinary AWS SDK call from code with the right IAM permission; there is no endpoint to stand up for on-demand inference.
- The permission that matters is
bedrock:InvokeModel, and it is scoped to model ARNs. Model access (console) and IAM permission (policy) are two separate gates, and you need both. - The Converse API gives one message shape across model providers, which is why the handler did not care which model id you passed.
Next
Lab 02 — Put a Guardrail in front of the model. Same app, but now every prompt and every completion passes through an Amazon Bedrock Guardrail.