Skip to content

AWS Bedrock plugin

An AWS Bedrock plugin for Genkit Go that provides text generation, image generation, and embedding capabilities using AWS Bedrock foundation models via the Converse API. The plugin is maintained in the aws-bedrock-go-plugin repository.

Terminal window
go get github.com/xavidop/genkit-aws-bedrock-go

The plugin covers text generation through the Converse API, streaming, tool calling, multimodal input, image generation, embeddings, and reranking. This page covers text generation, custom models, and prompt caching; for the rest, see the examples directory in the plugin’s repository, which has one runnable program per capability.

package main
import (
"context"
"log"
"github.com/firebase/genkit/go/ai"
"github.com/firebase/genkit/go/genkit"
bedrock "github.com/xavidop/genkit-aws-bedrock-go"
)
func main() {
ctx := context.Background()
bedrockPlugin := &bedrock.Bedrock{
Region: "us-east-1",
}
// Initialize Genkit
g := genkit.Init(ctx,
genkit.WithPlugins(bedrockPlugin),
genkit.WithDefaultModel("bedrock/anthropic.claude-sonnet-4-20250514-v1:0"),
)
// Required: the plugin registers nothing at Init, so the default model
// above does not resolve until something defines it.
bedrock.DefineCommonModels(bedrockPlugin, g)
log.Println("Starting basic Bedrock example...")
// Example: Generate text (basic usage)
response, err := genkit.Generate(ctx, g,
ai.WithPrompt("What are the key benefits of using AWS Bedrock for AI applications?"),
)
if err != nil {
log.Printf("Error generating text: %v", err)
} else {
log.Printf("Generated response: %s", response.Text())
}
log.Println("Basic Bedrock example completed")
}

Nothing is registered at Init, and the plugin has no dynamic resolver. Every model you generate with has to be defined first, either one at a time with DefineModel or in bulk with DefineCommonModels. A model name that was never defined fails to resolve at Generate time.

DefineCommonModels(b *bedrock.Bedrock, g *genkit.Genkit) map[string]ai.Model registers 17 models. Note the argument order: the plugin comes first, unlike the g-first order used elsewhere in Genkit Go.

Model IDType
anthropic.claude-3-haiku-20240307-v1:0chat
anthropic.claude-3-5-sonnet-20241022-v2:0chat
anthropic.claude-3-7-sonnet-20250219-v1:0chat
anthropic.claude-opus-4-20250514-v1:0chat
anthropic.claude-sonnet-4-20250514-v1:0chat
amazon.nova-micro-v1:0chat
amazon.nova-lite-v1:0chat
amazon.nova-pro-v1:0chat
amazon.titan-text-premier-v1:0chat
meta.llama3-8b-instruct-v1:0chat
meta.llama3-1-8b-instruct-v1:0chat
meta.llama3-2-3b-instruct-v1:0chat
meta.llama4-maverick-17b-instruct-v1:0chat
meta.llama4-scout-17b-instruct-v1:0chat
deepseek.r1-v1:0chat
amazon.titan-image-generator-v1image
amazon.nova-canvas-v1:0image

Anything else, including newer Claude, Mistral, Cohere, AI21, and Writer models, goes through DefineModel. See the AWS list of supported foundation models for the IDs Bedrock serves in your region.

package main
import (
"context"
"log"
"github.com/firebase/genkit/go/ai"
"github.com/firebase/genkit/go/genkit"
bedrock "github.com/xavidop/genkit-aws-bedrock-go"
)
func main() {
ctx := context.Background()
// Initialize Bedrock plugin
bedrockPlugin := &bedrock.Bedrock{
Region: "us-east-1", // Optional, defaults to AWS_REGION or us-east-1
}
// Initialize Genkit
g := genkit.Init(ctx,
genkit.WithPlugins(bedrockPlugin),
)
// Define a Claude model
claudeModel := bedrockPlugin.DefineModel(g, bedrock.ModelDefinition{
Name: "us.anthropic.claude-sonnet-4-5-20250929-v1:0",
Type: "chat",
}, nil)
// Generate text
response, err := genkit.Generate(ctx, g,
ai.WithModel(claudeModel),
ai.WithMessages(ai.NewUserMessage(
ai.NewTextPart("Hello! How are you?"),
)),
)
if err != nil {
log.Fatal(err)
}
log.Println(response.Text())
}

ModelDefinition describes one model:

FieldTypeDescription
NamestringThe model ID as AWS Bedrock spells it, including any inference-profile prefix.
Typestring"chat", "text", "image", or "embedding".

Type decides how the plugin describes the model and, for "image", which API it calls. "chat" and "text" behave identically: both go through the Converse API and get multiturn, system-role, and tool support. "image" gets media output, no tools, and an open config schema, because image config shapes differ per model family. "embedding" gets no tools, no media, and no multiturn.

DefineModel’s third parameter is an *ai.ModelInfo, the model’s capabilities. Pass nil to let the plugin infer them from the model ID and Type. An ID the plugin’s capability registry does not know is inferred as multimodal and tool-capable, and marked unstable, so pass a value instead when the inference would be wrong:

model := bedrockPlugin.DefineModel(g, bedrock.ModelDefinition{
Name: "us.example.some-text-only-model-v1:0",
Type: "chat",
}, &ai.ModelInfo{
Label: "Some text-only model",
Supports: &ai.ModelSupports{
Multiturn: true,
Tools: true,
SystemRole: true,
Media: false,
},
})

The plugin supports various configuration options:

bedrockPlugin := &bedrock.Bedrock{
Region: "us-west-2", // AWS region
MaxRetries: 3, // Max retry attempts
RequestTimeout: 30 * time.Second, // Request timeout
AWSConfig: customAWSConfig, // Custom AWS config (optional)
}
OptionTypeDefaultDescription
Regionstring"us-east-1"AWS region for Bedrock
MaxRetriesint3Maximum retry attempts
RequestTimeouttime.Duration30sRequest timeout
AWSConfig*aws.ConfignilCustom AWS configuration

The plugin uses the standard AWS SDK v2 configuration methods:

  1. Environment Variables:
Terminal window
export AWS_ACCESS_KEY_ID="your-access-key"
export AWS_SECRET_ACCESS_KEY="your-secret-key"
export AWS_REGION="us-east-1"
  1. AWS Credentials File (~/.aws/credentials):
[default]
aws_access_key_id = your-access-key
aws_secret_access_key = your-secret-key
region = us-east-1
  1. IAM Roles (when running on AWS services like EC2, ECS, Lambda)

  2. AWS SSO/CLI (aws configure sso)

Create an IAM policy with these permissions:

{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"bedrock:InvokeModel",
"bedrock:InvokeModelWithResponseStream"
],
"Resource": [
"arn:aws:bedrock:*::foundation-model/*",
"arn:aws:bedrock:*:*:inference-profile/*"
]
}
]
}

The inference-profile entry is what lets a us., eu., or apac. prefixed model ID through. Without it, a cross-region inference profile is denied even though the underlying foundation model is allowed.

// Prompt caching helps to save input token costs and reduce latency for repeated contexts.
// The first cache point must be defined after 1,024 tokens for most models.
// More about prompt caching: https://docs.aws.amazon.com/bedrock/latest/userguide/prompt-caching.html
response, err := genkit.Generate(ctx, g,
ai.WithMessages(
ai.NewSystemMessage(
ai.NewTextPart(sysprompt), // A big system prompt that is reused
bedrock.NewCachePointPart(), // A cache point after the system prompt
),
ai.NewUserTextMessage(input),
),
)