diff --git a/core/changelog.md b/core/changelog.md
index d3f9c52eb2..ab9118190f 100644
--- a/core/changelog.md
+++ b/core/changelog.md
@@ -1,4 +1,5 @@
- fix: allow setting authorization header through extra headers and in allow list and deny list
+- feat: added image generation support for bedrock
- feat: added support for gemini google search tool
- fix: function response part handling in gemini
- fix: call enrich error in vertex to return raw request and response in bifrost errors
diff --git a/core/providers/bedrock/bedrock.go b/core/providers/bedrock/bedrock.go
index 4c3fab1146..e5706a1c0c 100644
--- a/core/providers/bedrock/bedrock.go
+++ b/core/providers/bedrock/bedrock.go
@@ -1536,9 +1536,82 @@ func (provider *BedrockProvider) TranscriptionStream(ctx *schemas.BifrostContext
return nil, providerUtils.NewUnsupportedOperationError(schemas.TranscriptionStreamRequest, schemas.Bedrock)
}
-// ImageGeneration is not supported by the Bedrock provider.
+// ImageGeneration generates images using Amazon Bedrock.
+// Supports Titan Image Generator v1, Nova Canvas v1, and Titan Image Generator v2.
+// Returns a BifrostImageGenerationResponse containing the generated images and any error that occurred.
func (provider *BedrockProvider) ImageGeneration(ctx *schemas.BifrostContext, key schemas.Key, request *schemas.BifrostImageGenerationRequest) (*schemas.BifrostImageGenerationResponse, *schemas.BifrostError) {
- return nil, providerUtils.NewUnsupportedOperationError(schemas.ImageGenerationRequest, schemas.Bedrock)
+ if err := providerUtils.CheckOperationAllowed(schemas.Bedrock, provider.customProviderConfig, schemas.ImageGenerationRequest); err != nil {
+ return nil, err
+ }
+
+ providerName := provider.GetProviderKey()
+ if key.BedrockKeyConfig == nil {
+ return nil, providerUtils.NewConfigurationError("bedrock key config is not provided", providerName)
+ }
+
+ modelType := DetermineImageGenModelType(request.Model)
+ var rawResponse []byte
+ var jsonData []byte
+ var bifrostError *schemas.BifrostError
+ var latency time.Duration
+ var path string
+ var deployment string
+ switch modelType {
+
+ case "titan-image-generator-v1", "nova-canvas-v1:0", "titan-image-generator-v2:0":
+ jsonData, bifrostError = providerUtils.CheckContextAndGetRequestBody(
+ ctx,
+ request,
+ func() (any, error) { return ToBedrockImageGenerationRequest(request) },
+ provider.GetProviderKey())
+ if bifrostError != nil {
+ return nil, bifrostError
+ }
+ path, deployment = provider.getModelPath("invoke", request.Model, key)
+ rawResponse, latency, bifrostError = provider.completeRequest(ctx, jsonData, path, key)
+ default:
+ return nil, providerUtils.NewConfigurationError("unsupported image generation model type", providerName)
+ }
+ if bifrostError != nil {
+ return nil, providerUtils.EnrichError(ctx, bifrostError, jsonData, nil, provider.sendBackRawRequest, provider.sendBackRawResponse)
+ }
+
+ // Parse response based on model type
+ var bifrostResponse *schemas.BifrostImageGenerationResponse
+ switch modelType {
+ case "titan-image-generator-v1", "nova-canvas-v1:0", "titan-image-generator-v2:0":
+ var imageResp BedrockImageGenerationResponse
+ if err := sonic.Unmarshal(rawResponse, &imageResp); err != nil {
+ return nil, providerUtils.EnrichError(ctx, providerUtils.NewBifrostOperationError("error parsing image generation response", err, providerName), jsonData, rawResponse, provider.sendBackRawRequest, provider.sendBackRawResponse)
+ }
+
+ if imageResp.Error != "" {
+ return nil, providerUtils.EnrichError(ctx, providerUtils.NewBifrostOperationError(imageResp.Error, nil, providerName), jsonData, rawResponse, provider.sendBackRawRequest, provider.sendBackRawResponse)
+ }
+
+ bifrostResponse = ToBifrostImageGenerationResponse(&imageResp)
+ bifrostResponse.Model = request.Model
+ bifrostResponse.ExtraFields.RequestType = schemas.ImageGenerationRequest
+ bifrostResponse.ExtraFields.Provider = providerName
+ bifrostResponse.ExtraFields.ModelRequested = request.Model
+ bifrostResponse.ExtraFields.ModelDeployment = deployment
+ bifrostResponse.ExtraFields.Latency = latency.Milliseconds()
+
+ // Set raw request if enabled
+ if providerUtils.ShouldSendBackRawRequest(ctx, provider.sendBackRawRequest) {
+ providerUtils.ParseAndSetRawRequest(&bifrostResponse.ExtraFields, jsonData)
+ }
+
+ if providerUtils.ShouldSendBackRawResponse(ctx, provider.sendBackRawResponse) {
+ var rawResponseData interface{}
+ if err := sonic.Unmarshal(rawResponse, &rawResponseData); err == nil {
+ bifrostResponse.ExtraFields.RawResponse = rawResponseData
+ }
+ }
+
+ return bifrostResponse, nil
+ }
+ return nil, providerUtils.NewConfigurationError("unsupported image generation model type", providerName)
}
// ImageGenerationStream is not supported by the Bedrock provider.
diff --git a/core/providers/bedrock/images.go b/core/providers/bedrock/images.go
new file mode 100644
index 0000000000..a7398845cf
--- /dev/null
+++ b/core/providers/bedrock/images.go
@@ -0,0 +1,104 @@
+package bedrock
+
+import (
+ "fmt"
+ "strconv"
+ "strings"
+
+ "github.com/maximhq/bifrost/core/schemas"
+)
+
+// ToBedrockImageGenerationRequest converts a Bifrost image generation request to a Bedrock image generation request
+func ToBedrockImageGenerationRequest(request *schemas.BifrostImageGenerationRequest) (*BedrockImageGenerationRequest, error) {
+ if request == nil {
+ return nil, fmt.Errorf("request is nil")
+ }
+
+ if request.Input == nil {
+ return nil, fmt.Errorf("request.Input is required")
+ }
+
+ bedrockReq := &BedrockImageGenerationRequest{
+ TaskType: schemas.Ptr(TaskTypeTextImage),
+ TextToImageParams: &BedrockTextToImageParams{
+ Text: request.Input.Prompt,
+ },
+ ImageGenerationConfig: &ImageGenerationConfig{},
+ }
+
+ if request.Params != nil {
+ if request.Params.N != nil {
+ bedrockReq.ImageGenerationConfig.NumberOfImages = request.Params.N
+ }
+ if request.Params.NegativePrompt != nil {
+ bedrockReq.TextToImageParams.NegativeText = request.Params.NegativePrompt
+ }
+ if request.Params.Seed != nil {
+ bedrockReq.ImageGenerationConfig.Seed = request.Params.Seed
+ }
+ if request.Params.Quality != nil {
+ bedrockReq.ImageGenerationConfig.Quality = request.Params.Quality
+ }
+ if request.Params.Style != nil {
+ bedrockReq.TextToImageParams.Style = request.Params.Style
+ }
+ if request.Params.Size != nil && strings.TrimSpace(strings.ToLower(*request.Params.Size)) != "auto" {
+
+ size := strings.Split(strings.TrimSpace(strings.ToLower(*request.Params.Size)), "x")
+ if len(size) != 2 {
+ return nil, fmt.Errorf("invalid size format: expected 'WIDTHxHEIGHT', got %q", *request.Params.Size)
+ }
+
+ width, err := strconv.Atoi(size[0])
+ if err != nil {
+ return nil, fmt.Errorf("invalid width in size %q: %w", *request.Params.Size, err)
+ }
+
+ height, err := strconv.Atoi(size[1])
+ if err != nil {
+ return nil, fmt.Errorf("invalid height in size %q: %w", *request.Params.Size, err)
+ }
+
+ bedrockReq.ImageGenerationConfig.Width = schemas.Ptr(width)
+ bedrockReq.ImageGenerationConfig.Height = schemas.Ptr(height)
+ }
+ if request.Params.ExtraParams != nil {
+ if cfgScale, ok := schemas.SafeExtractFloat64Pointer(request.Params.ExtraParams["cfgScale"]); ok {
+ bedrockReq.ImageGenerationConfig.CfgScale = cfgScale
+ }
+ }
+ }
+
+ return bedrockReq, nil
+
+}
+
+// ToBifrostImageGenerationResponse converts a Bedrock image generation response to a Bifrost image generation response
+func ToBifrostImageGenerationResponse(response *BedrockImageGenerationResponse) *schemas.BifrostImageGenerationResponse {
+ if response == nil {
+ return nil
+ }
+
+ bifrostResponse := &schemas.BifrostImageGenerationResponse{}
+
+ for index, image := range response.Images {
+ bifrostResponse.Data = append(bifrostResponse.Data, schemas.ImageData{
+ B64JSON: image,
+ Index: index,
+ })
+ }
+
+ return bifrostResponse
+}
+
+// DetermineImageGenModelType determines the image generation model type from the model name
+func DetermineImageGenModelType(model string) string {
+ if strings.Contains(model, "nova-canvas-v1:0") {
+ return "nova-canvas-v1:0"
+ } else if strings.Contains(model, "titan-image-generator-v2:0") {
+ return "titan-image-generator-v2:0"
+ } else if strings.Contains(model, "titan-image-generator-v1") {
+ return "titan-image-generator-v1"
+ }
+ return model
+}
diff --git a/core/providers/bedrock/types.go b/core/providers/bedrock/types.go
index 37e19e6d1d..ef01c7df98 100644
--- a/core/providers/bedrock/types.go
+++ b/core/providers/bedrock/types.go
@@ -569,6 +569,37 @@ type BedrockTitanEmbeddingResponse struct {
InputTextTokenCount int `json:"inputTextTokenCount"` // Number of tokens in input
}
+const TaskTypeTextImage = "TEXT_IMAGE"
+
+// BedrockImageGenerationRequest represents a Bedrock image generation request
+type BedrockImageGenerationRequest struct {
+ TaskType *string `json:"taskType"` // Should be "TEXT_IMAGE"
+ TextToImageParams *BedrockTextToImageParams `json:"textToImageParams"` // Parameters for text-to-image
+ ImageGenerationConfig *ImageGenerationConfig `json:"imageGenerationConfig"` // Image generation config
+}
+
+type BedrockTextToImageParams struct {
+ Text string `json:"text"` // Prompt for image generation
+ NegativeText *string `json:"negativeText,omitempty"` // Negative prompt for image generation
+ Style *string `json:"style,omitempty"` // Style for image generation
+}
+
+type ImageGenerationConfig struct {
+ NumberOfImages *int `json:"numberOfImages,omitempty"`
+ Height *int `json:"height,omitempty"`
+ Width *int `json:"width,omitempty"`
+ CfgScale *float64 `json:"cfgScale,omitempty"`
+ Quality *string `json:"quality,omitempty"`
+ Seed *int `json:"seed,omitempty"`
+}
+
+// BedrockImageGenerationResponse represents a Bedrock image generation response
+type BedrockImageGenerationResponse struct {
+ Images []string `json:"images"` // list of Base64 encoded images
+ MaskImage string `json:"maskImage"` // Base64 encoded mask image (optional)
+ Error string `json:"error"` // error message (if present)
+}
+
// ==================== MODELS TYPES ====================
type BedrockModelLifecycle struct {
Status string `json:"status"`
diff --git a/docs/providers/supported-providers/bedrock.mdx b/docs/providers/supported-providers/bedrock.mdx
index 282ad8a6e6..3bf954567c 100644
--- a/docs/providers/supported-providers/bedrock.mdx
+++ b/docs/providers/supported-providers/bedrock.mdx
@@ -18,14 +18,14 @@ AWS Bedrock supports multiple model families (Claude, Nova, Mistral, Llama, Cohe
### Model Family Support
-| Family | Chat | Responses | Text | Embeddings |
-|--------|------|-----------|------|------------|
-| **Claude (Anthropic)** | ✅ | ✅ | ✅ | ❌ |
-| **Nova (Anthropic)** | ✅ | ✅ | ❌ | ❌ |
-| **Mistral** | ✅ | ✅ | ✅ | ❌ |
-| **Llama** | ✅ | ✅ | ❌ | ❌ |
-| **Cohere** | ✅ | ✅ | ❌ | ✅ |
-| **Titan** | ✅ | ✅ | ❌ | ✅ |
+| Family | Chat | Responses | Text | Embeddings | Image Generation |
+|--------|------|-----------|------|------------|------------|
+| **Claude (Anthropic)** | ✅ | ✅ | ✅ | ❌ | ❌ |
+| **Nova (Anthropic)** | ✅ | ✅ | ❌ | ❌ | ✅ |
+| **Mistral** | ✅ | ✅ | ✅ | ❌ | ❌ |
+| **Llama** | ✅ | ✅ | ❌ | ❌ | ❌ |
+| **Cohere** | ✅ | ✅ | ❌ | ✅ | ❌ |
+| **Titan** | ✅ | ✅ | ❌ | ✅ | ✅ |
### Supported Operations
@@ -38,7 +38,7 @@ AWS Bedrock supports multiple model families (Claude, Nova, Mistral, Llama, Cohe
| Files | ✅ | - | S3 (via SDK) |
| Batch | ✅ | - | `batch` |
| List Models | ✅ | - | `listFoundationModels` |
-| Image Generation | ❌ | ❌ | - |
+| Image Generation | ✅ | ❌ | `invoke` |
| Speech (TTS) | ❌ | ❌ | - |
| Transcriptions (STT) | ❌ | ❌ | - |
@@ -519,7 +519,71 @@ Supported embedding models: **Titan**, **Cohere**
---
-# 5. Batch API
+# 5. Image Generation
+
+Supported image generation models: **Titan Image Generator v1**, **Titan Image Generator v2**, **Nova Canvas v1**
+
+## Request Conversion
+
+| Parameter(Bifrost) | Transformation (Bedrock) |
+|---------------------|----------------|
+| `prompt` | `textToImageParams.text` |
+| `n` | `imageGenerationConfig.numberOfImages` |
+| `negativePrompt` | `textToImageParams.negativeText` |
+| `seed` | `imageGenerationConfig.seed` |
+| `quality` | `imageGenerationConfig.quality` |
+| `style` | `textToImageParams.style` |
+| `size` | `imageGenerationConfig.width` & `imageGenerationConfig.height` |
+
+## Response Conversion
+
+| Parameter(Bedrock) | Transformation (Bifrost) |
+|---------------------|--------------------------|
+| `images` | `data.b64_json` |
+
+### Example Request
+
+
+
+
+```bash
+curl -X POST http://localhost:8080/v1/images/generations \
+ -H "Content-Type: application/json" \
+ -d '{
+ "model": "bedrock/amazon.nova-canvas-v1:0",
+ "prompt": "A futuristic cityscape with a flying car",
+ "size": "1024x1024",
+ "seed": 123,
+ "negative_prompt": "bikes",
+ "n": 2
+ }'
+```
+
+
+
+
+```go
+resp, err := client.ImageGenerationRequest(ctx, &schemas.BifrostImageGenerationRequest{
+ Provider: schemas.Bedrock,
+ Model: "amazon.nova-canvas-v1:0",
+ Input: &schemas.ImageGenerationInput{
+ Prompt: "A futuristic cityscape with a flying car",
+ },
+ Params: &schemas.ImageGenerationParameters{
+ N: schemas.Ptr(2),
+ Seed: schemas.Ptr(123),
+ NegativePrompt: schemas.Ptr("bikes"),
+ Quality: schemas.Ptr("auto"),
+ Style: schemas.Ptr("natural"),
+ Size: schemas.Ptr("1024x1024"),
+ },
+})
+```
+
+
+
+
+# 6. Batch API
**Request formats**: `requests` array (CustomID + Params) or `input_file_id`
@@ -548,7 +612,7 @@ Supported embedding models: **Titan**, **Cohere**
---
-# 6. Files API
+# 7. Files API
S3-backed file operations. Files are stored in S3 buckets integrated with Bedrock.
@@ -574,7 +638,7 @@ S3-backed file operations. Files are stored in S3 buckets integrated with Bedroc
---
-# 7. List Models
+# 8. List Models
**Request**: GET `/v1/models` (no body)
@@ -594,7 +658,7 @@ S3-backed file operations. Files are stored in S3 buckets integrated with Bedroc
---
-# 8. AWS Authentication & Configuration
+# 9. AWS Authentication & Configuration
Bifrost automatically handles AWS Bedrock authentication via multiple methods including explicit credentials, IAM roles, and bearer tokens with automatic Signature Version 4 (SigV4) signing.
@@ -623,7 +687,7 @@ See **[Provider-Specific Authentication - AWS Bedrock](../../quickstart/go-sdk/p
---
-# 9. Error Handling
+# 10. Error Handling
**HTTP Status Mapping**:
diff --git a/docs/providers/supported-providers/overview.mdx b/docs/providers/supported-providers/overview.mdx
index e8bd427e0d..1caa8ec19b 100644
--- a/docs/providers/supported-providers/overview.mdx
+++ b/docs/providers/supported-providers/overview.mdx
@@ -19,7 +19,7 @@ The following table summarizes which operations are supported by each provider v
|----------|--------|------|----------------|------|---------------|-----------|--------------------|--------|-----------------|------------|-----|-------------|-----|--------------|-------|-------|--------------|
| Anthropic (`anthropic/`) | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ |
| Azure (`azure/`) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ |
-| Bedrock (`bedrock/`) | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ |
+| Bedrock (`bedrock/`) | ✅ | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ |
| Cerebras (`cerebras/`) | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Cohere (`cohere/`) | ✅ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ |
| Elevenlabs (`elevenlabs/`) | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ |