> ## Documentation Index
> Fetch the complete documentation index at: https://notes.kodekloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Demo Bedrock API Part 3

> Demonstrates using Amazon Bedrock with Boto3 in two Python examples, model-specific prompt invocation and a vendor-agnostic unified messages approach.

Let's walkthrough a live demo in an editor (I'm using [Visual Studio Code](https://code.visualstudio.com/), but any editor will work). This lesson uses two Python scripts that show two approaches to calling Amazon Bedrock via the runtime API:

| File | Purpose | Notes / Example |
| - | - | - |
| `invoke_model.py` | Direct model invocation using a model-specific prompt (control tokens) | Uses `invoke_model` with a serialized JSON payload containing a `prompt` value. |
| `converse.py` | Vendor-agnostic invocation using the unified `messages` structure | Reuses the same `messages` payload across multiple models for consistent application code. |

Both scripts use the Bedrock runtime client via Boto3.

## invoke\_model.py

This script demonstrates a direct model invocation that includes model-specific control tokens in the `prompt`. These tokens come from the model's required input format and must be provided exactly as specified by that model.

```python theme={null}
# invoke_model.py
import boto3
import json

inference_client = boto3.client("bedrock-runtime", region_name="us-east-1")

payload = {
    "prompt": "<|begin_of_text|><|start_header_id|>user<|end_header_id|>\nWhat is Generative AI? Answer in exactly 2 bullet points",
    "max_gen_len": 200,
    "temperature": 0.3,
    "top_p": 0.9,
}

response = inference_client.invoke_model(
    modelId="meta.llama3-8b-instruct-v1:0",
    body=json.dumps(payload),
)

response_body = json.loads(response["body"].read())
print(response_body["generation"])
```

What this script does:

* Instantiates a Bedrock runtime client with Boto3: `boto3.client("bedrock-runtime", region_name="us-east-1")`.
* Builds a JSON payload that includes a `prompt` with model-specific control tokens.
* Calls `invoke_model` with the chosen `modelId`.
* Reads and parses the response stream and prints the generated text.

Sample terminal output after running `invoke_model.py`:

```bash theme={null}
alistair@HODEI-LEGION5:~/bedrock-demo-02$ /bin/python3 /home/alistair/bedrock-demo-02/invoke-model.py

Here are 2 bullet points that explain what Generative AI is:

• **Generative AI models are designed to create new, original content**: Unlike traditional AI models that are trained to perform specific tasks, generative AI models are trained to generate new data, such as images, music, text, or videos, that are unique and often indistinguishable from human-created content.

• **Generative AI models use machine learning algorithms to learn patterns and relationships in data**: Generative AI models are trained on large datasets and use machine learning algorithms to identify patterns, relationships, and structures in the data. This allows them to generate new content that is coherent, realistic, and often surprising, as they can combine and manipulate the patterns and relationships they've learned to create novel outputs.

alistair@HODEI-LEGION5:~/bedrock-demo-02$
```

<Callout icon="lightbulb" color="#1CB2FE">
  Model-specific control tokens (for example, `"<|begin_of_text|>"`) are required by some providers/models to frame the input correctly. These tokens vary by model—consult the model’s documentation for the exact input format before sending requests.
</Callout>

## converse.py (unified messages format)

This script demonstrates a vendor-agnostic approach using a `messages` array. The unified `messages` structure is easier to reuse across different models and providers because it removes model-specific control tokens from your application logic.

```python theme={null}
# converse.py
import boto3
import json

inference_client = boto3.client("bedrock-runtime", region_name="us-east-1")

messages = [
    {
        "role": "user",
        "content": [
            {"text": "What is generative AI? Answer in one sentence"}
        ],
    }
]

models = [
    "amazon.nova-micro-v1:0",
    "meta.llama3-8b-instruct-v1:0",
]

for model_id in models:
    payload = {"messages": messages}
    response = inference_client.invoke_model(
        modelId=model_id,
        body=json.dumps(payload),
    )
    response_body = json.loads(response["body"].read())
    # Print the entire response body for inspection (format varies by model)
    print(f"\n{model_id}:\n")
    print(json.dumps(response_body, indent=2))
```

Why use the unified `messages` format?

* Vendor-agnostic: keeps your app code consistent when switching models/providers.
* Reusable: the same `messages` payload can be re-used across different model IDs.
* Inspectable: because response schemas vary by model, it's useful to print and inspect the returned JSON to determine how to extract the generated text.

Sample terminal output after running `converse.py` (trimmed for readability):

```bash theme={null}
alistair@HODEI-LEGION5:~/bedrock-demo-02$ /bin/python3 /home/alistair/bedrock-demo-02/converse.py

amazon.nova-micro-v1:0:

Generative AI refers to advanced artificial intelligence systems capable of creating new content, such as text, images, or music, based on learned patterns from training data.

meta.llama3-8b-instruct-v1:0:

Generative AI refers to a type of artificial intelligence that can create new, original content, such as text, images, music, or videos, using algorithms and machine learning models that mimic human creativity and innovation.

alistair@HODEI-LEGION5:~/bedrock-demo-02$
```

<Callout icon="warning" color="#FF6B6B">
  Response schemas vary across models and providers. Do not rely on a single fixed response field—inspect the returned JSON and map the fields your application needs (for example, `generation`, `content`, or provider-specific properties).
</Callout>

<Frame>
  <img src="https://mintcdn.com/kodekloud-c4ac6d9a/tJmUiudNjsCWp_bm/images/Introduction-to-Amazon-Bedrock/Getting-Started-With-Amazon-Bedrock/Demo-Bedrock-API-Part-3/bedrock-results-cards-benefits-integration-architecture.jpg?fit=max&auto=format&n=tJmUiudNjsCWp_bm&q=85&s=d8e1290ba6a393dbbd0a5215bd11ad9d" alt="A &#x22;Results&#x22; slide with four numbered dark-blue cards (01–04), each containing an icon and brief text. The cards list benefits: standardized integration with Bedrock services, faster application development, reduced complexity when interacting with models, and consistent architecture across AWS services." width="1920" height="1080" data-path="images/Introduction-to-Amazon-Bedrock/Getting-Started-With-Amazon-Bedrock/Demo-Bedrock-API-Part-3/bedrock-results-cards-benefits-integration-architecture.jpg" />
</Frame>

There are over 200 AWS services. The common integration pattern is the same across services: instantiate a service client with Boto3 and call the appropriate API methods. For Bedrock:

* Use the control plane APIs (via the SDK or console) to configure model resources and manage the service.
* Use the runtime API (e.g., `bedrock-runtime` via Boto3) for inference/invocations.

<Frame>
  <img src="https://mintcdn.com/kodekloud-c4ac6d9a/tJmUiudNjsCWp_bm/images/Introduction-to-Amazon-Bedrock/Getting-Started-With-Amazon-Bedrock/Demo-Bedrock-API-Part-3/bedrock-control-runtime-apis-aws-sdk-slide.jpg?fit=max&auto=format&n=tJmUiudNjsCWp_bm&q=85&s=2be0537f6e42427c0ce86425ee6f529e" alt="A presentation slide titled &#x22;Key Takeaway&#x22; with text explaining that Amazon Bedrock uses control plane APIs to manage resources and runtime APIs to perform model inference, typically accessed through AWS SDKs. The slide has a dark blue left panel and light background for the text." width="1920" height="1080" data-path="images/Introduction-to-Amazon-Bedrock/Getting-Started-With-Amazon-Bedrock/Demo-Bedrock-API-Part-3/bedrock-control-runtime-apis-aws-sdk-slide.jpg" />
</Frame>

This concludes the demonstration. For hands-on experience, run the scripts locally and experiment with different `modelId` values and payload options such as `temperature`, `top_p`, and `max_gen_len`.

## Quick comparison: direct prompt vs unified messages

| Approach | Best for | Example payload |
| - | - | - |
| Direct model invocation | When a model requires specific control tokens or inline prompt formatting | `{"prompt": "<\|begin_of_text\|>...","temperature":0.3}` |
| Unified `messages` | When you want vendor-agnostic messaging and reuse across models | `{"messages":[{"role":"user","content":[{"text":"..."}]}]}` |

## Links and references

* [Boto3 documentation (Bedrock runtime)](https://boto3.amazonaws.com/v1/documentation/api/latest/index.html)
* [Amazon Bedrock — general documentation](https://docs.aws.amazon.com/bedrock) (reference the AWS docs for control plane vs runtime APIs)
* [Visual Studio Code](https://code.visualstudio.com/)

A hands-on lab is recommended to practice accessing Bedrock with Boto3 and testing both model-specific prompts and the unified `messages` format.

<CardGroup>
  <Card title="Watch Video" icon="video" cta="Learn more" href="https://learn.kodekloud.com/user/courses/introduction-to-amazon-bedrock/module/4f0b1655-3751-4724-a6eb-78d06f3753a7/lesson/3e2af612-77bf-461e-ad7a-2e3f5d1bc10b" />

  <Card title="Practice Lab" icon="flask-conical" cta="Learn more" href="https://learn.kodekloud.com/user/courses/introduction-to-amazon-bedrock/module/4f0b1655-3751-4724-a6eb-78d06f3753a7/lesson/ef55e632-7332-48b7-b463-963ee02b37d6" />
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.