Bedrock Basics
Your first Converse call against a foundation model via SDK.
Search across all documentation pages
Your first Converse call against a foundation model via SDK.
This page is a hands-on tour of the Bedrock Runtime data plane. Each example is small and builds on the last: a single reply, then a system prompt, then a full multi-turn conversation, then reading usage, and finally listing models and a first stream. The same client-request-response shape repeats throughout, so once the first call clicks the rest are variations.
pip install boto3 (boto3 1.43.x, Python 3.10+). TypeScript: npm install @aws-sdk/client-bedrock-runtime @aws-sdk/client-bedrock (Node.js 18+).aws configure, environment variables, or an IAM role - the SDK finds them automatically. Your identity needs bedrock:InvokeModel (and bedrock:ListFoundationModels for the control-plane example).us-east-1. Model IDs and inference-profile requirements are region/version-specific.Send one user message to a model and print its reply.
# --- Python (boto3) ---
import boto3
brt = boto3.client("bedrock-runtime", region_name="us-east-1")
resp = brt.converse(
modelId="amazon.nova-lite-v1:0", # representative id - verify per region
messages=[{"role": "user", "content": [{"text": "Name three primary colors."}]}],
)
print(resp["output"]["message"]["content"][0]["text"])// --- TypeScript (AWS SDK v3) ---
import { BedrockRuntimeClient, ConverseCommand } from "@aws-sdk/client-bedrock-runtime";
const brt = new BedrockRuntimeClient({ region: "us-east-1" });
const resp = await brt.send(new ConverseCommand({
modelId: "amazon.nova-lite-v1:0", // representative id - verify per region
messages: [{ role: "user", content: [{ text: "Name three primary colors." }] }],
}));
console.log(resp.output?.message?.content?.[0]?.text);bedrock-runtime, distinct from the bedrock control-plane client.role and a content array of blocks; a text block is {"text": ...}.output.message.content[0].text for a simple text answer.Related: Bedrock's Unified Model-Invocation API - the mental model behind this call.
Steer behavior with system, and cap length and randomness with inferenceConfig.
# --- Python (boto3) ---
resp = brt.converse(
modelId="amazon.nova-lite-v1:0",
system=[{"text": "You are a terse assistant. Answer in one sentence."}],
messages=[{"role": "user", "content": [{"text": "Why is the sky blue?"}]}],
inferenceConfig={"maxTokens": 200, "temperature": 0.2, "topP": 0.9},
)
print(resp["output"]["message"]["content"][0]["text"])// --- TypeScript (AWS SDK v3) ---
const resp = await brt.send(new ConverseCommand({
modelId: "amazon.nova-lite-v1:0",
system: [{ text: "You are a terse assistant. Answer in one sentence." }],
messages: [{ role: "user", content: [{ text: "Why is the sky blue?" }] }],
inferenceConfig: { maxTokens: 200, temperature: 0.2, topP: 0.9 },
}));
console.log(resp.output?.message?.content?.[0]?.text);system is a top-level list of instruction blocks, kept separate from the conversation turns.inferenceConfig uses normalized names - maxTokens, temperature, topP, stopSequences - across all model families.temperature makes output more deterministic; higher values make it more varied.maxTokens caps the reply length and your output-token cost, so always set it.Keep context by appending the model's reply and the next question to the same list.
# --- Python (boto3) ---
messages = [{"role": "user", "content": [{"text": "My name is Ada."}]}]
first = brt.converse(modelId="amazon.nova-lite-v1:0", messages=messages)
messages.append(first["output"]["message"]) # the assistant turn
messages.append({"role": "user", "content": [{"text": "What is my name?"}]})
second = brt.converse(modelId="amazon.nova-lite-v1:0", messages=messages)
print(second["output"]["message"]["content"][0]["text"])// --- TypeScript (AWS SDK v3) ---
const messages: any[] = [{ role: "user", content: [{ text: "My name is Ada." }] }];
const first = await brt.send(new ConverseCommand({ modelId: "amazon.nova-lite-v1:0", messages }));
messages.push(first.output!.message!); // the assistant turn
messages.push({ role: "user", content: [{ text: "What is my name?" }] });
const second = await brt.send(new ConverseCommand({ modelId: "amazon.nova-lite-v1:0", messages }));
console.log(second.output?.message?.content?.[0]?.text);output.message verbatim so roles alternate correctly.Every response reports what it cost and why it stopped.
# --- Python (boto3) ---
resp = brt.converse(
modelId="amazon.nova-lite-v1:0",
messages=[{"role": "user", "content": [{"text": "Write a haiku about the sea."}]}],
inferenceConfig={"maxTokens": 60},
)
u = resp["usage"]
print("stop:", resp["stopReason"])
print("tokens in/out/total:", u["inputTokens"], u["outputTokens"], u["totalTokens"])// --- TypeScript (AWS SDK v3) ---
const resp = await brt.send(new ConverseCommand({
modelId: "amazon.nova-lite-v1:0",
messages: [{ role: "user", content: [{ text: "Write a haiku about the sea." }] }],
inferenceConfig: { maxTokens: 60 },
}));
const u = resp.usage!;
console.log("stop:", resp.stopReason);
console.log("tokens in/out/total:", u.inputTokens, u.outputTokens, u.totalTokens);usage reports inputTokens, outputTokens, and totalTokens - the basis for on-demand billing.stopReason is end_turn for a natural finish or max_tokens when the cap was hit.max_tokens stop means the reply was cut off; raise maxTokens if you need more.resp["metrics"]["latencyMs"] reports server-side latency for the call.Use the control-plane client to see what you can call.
# --- Python (boto3) ---
import boto3
bedrock = boto3.client("bedrock", region_name="us-east-1") # control plane
for m in bedrock.list_foundation_models()["modelSummaries"][:10]:
print(m["modelId"], "-", m.get("modelName"))// --- TypeScript (AWS SDK v3) ---
import { BedrockClient, ListFoundationModelsCommand } from "@aws-sdk/client-bedrock";
const bedrock = new BedrockClient({ region: "us-east-1" }); // control plane
const out = await bedrock.send(new ListFoundationModelsCommand({}));
for (const m of (out.modelSummaries ?? []).slice(0, 10)) console.log(m.modelId, "-", m.modelName);bedrock client (not bedrock-runtime) is the control plane for discovery and management.ListFoundationModels returns current, region-specific model IDs - the authoritative source, never a hardcoded list.ListInferenceProfiles shows the cross-region profile IDs some models require for on-demand access.Use converse_stream when you want to show output as it is generated.
# --- Python (boto3) ---
resp = brt.converse_stream(
modelId="amazon.nova-lite-v1:0",
messages=[{"role": "user", "content": [{"text": "Count from 1 to 5."}]}],
)
for event in resp["stream"]:
if "contentBlockDelta" in event:
print(event["contentBlockDelta"]["delta"]["text"], end="", flush=True)// --- TypeScript (AWS SDK v3) ---
import { ConverseStreamCommand } from "@aws-sdk/client-bedrock-runtime";
const resp = await brt.send(new ConverseStreamCommand({
modelId: "amazon.nova-lite-v1:0",
messages: [{ role: "user", content: [{ text: "Count from 1 to 5." }] }],
}));
for await (const event of resp.stream!) {
if (event.contentBlockDelta) process.stdout.write(event.contentBlockDelta.delta?.text ?? "");
}ConverseStream returns an event stream instead of a single response object.contentBlockDelta events; assemble it as it comes.Related: Streaming Responses with ConverseStream - the complete streaming walkthrough.
Because Converse is model-agnostic, changing families is a config change.
# --- Python (boto3) ---
messages = [{"role": "user", "content": [{"text": "Summarize AWS in one line."}]}]
for model_id in ["amazon.nova-lite-v1:0", "meta.llama3-1-8b-instruct-v1:0"]:
resp = brt.converse(modelId=model_id, messages=messages,
inferenceConfig={"maxTokens": 80})
print(model_id, "->", resp["output"]["message"]["content"][0]["text"])// --- TypeScript (AWS SDK v3) ---
const messages = [{ role: "user" as const, content: [{ text: "Summarize AWS in one line." }] }];
for (const modelId of ["amazon.nova-lite-v1:0", "meta.llama3-1-8b-instruct-v1:0"]) {
const resp = await brt.send(new ConverseCommand({ modelId, messages, inferenceConfig: { maxTokens: 80 } }));
console.log(modelId, "->", resp.output?.message?.content?.[0]?.text);
}modelId string changes.bedrock client and verify at build time.Related: Model Selection: Claude, Llama, Nova & Titan Trade-offs.
Stack versions: This page was written for boto3 1.43.x (Python 3.10+) and the AWS SDK for JavaScript v3 (Node.js 18+). Bedrock model IDs and inference profiles are region/version-specific - verify against the current Bedrock catalog at build time.
Reviewed by Chris St. John·Last updated Jul 24, 2026