Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
ad4ea6f
feat(bedrock): implement model routing logic for Nova support
micahwalter Jan 16, 2026
19b7793
feat(bedrock): implement region prefix handling for Nova models
micahwalter Jan 16, 2026
ecdc525
feat(bedrock): implement Nova language model with AWS SDK Converse API
micahwalter Jan 16, 2026
5d0e935
feat(bedrock): implement request conversion for Nova Converse API
micahwalter Jan 16, 2026
f4ca8c6
feat(bedrock): implement response conversion from Converse API
micahwalter Jan 16, 2026
1c1a09b
feat(bedrock): implement non-streaming generation for Nova models
micahwalter Jan 16, 2026
cf85fdd
feat(bedrock): implement streaming generation for Nova models
micahwalter Jan 16, 2026
3f66d55
feat(bedrock): implement AWS error handling for Nova models
micahwalter Jan 16, 2026
db5bff5
chore: move pgregory.net/rapid to direct dependencies
micahwalter Jan 16, 2026
daef2b1
fix: properly set AdditionalModelRequestFields for TopK parameter
micahwalter Jan 16, 2026
3cb2b7a
feat: add comprehensive integration tests for Nova models
micahwalter Jan 16, 2026
33d5f4b
docs: add Amazon Nova Bedrock support documentation
micahwalter Jan 16, 2026
7a460ff
chore: run `modernize`
andreynering Jan 19, 2026
cd91431
chore: remove unneeded file
andreynering Jan 19, 2026
c7a94bc
fix(bedrock): emit StreamPartTypeToolCall event for agent tool execution
micahwalter Jan 22, 2026
51ed82f
feat(bedrock): add reasoning/thinking block support for streaming
micahwalter Jan 22, 2026
3f1ed14
Fix Nova reasoning config format to use reasoningConfig
micahwalter Jan 22, 2026
6d18ec7
Merge branch 'main' into feature/amazon-nova-bedrock-support
andreynering Feb 5, 2026
9738770
docs: move amazon nova docs to `providers/bedrock`
andreynering Feb 5, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,6 @@ Thumbs.db

manpages/
*.patch

# Property-based testing cache
testdata/
4 changes: 3 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ require (
github.com/RealAlexandreAI/json-repair v0.0.15
github.com/aws/aws-sdk-go-v2 v1.41.1
github.com/aws/aws-sdk-go-v2/config v1.32.7
github.com/aws/aws-sdk-go-v2/service/bedrockruntime v1.47.2
github.com/aws/smithy-go v1.24.0
github.com/charmbracelet/anthropic-sdk-go v0.0.0-20251024181547-21d6f3d9a904
github.com/charmbracelet/x/exp/slice v0.0.0-20250904123553-b4e2667e5ad5
Expand All @@ -20,6 +21,7 @@ require (
github.com/stretchr/testify v1.11.1
golang.org/x/oauth2 v0.34.0
google.golang.org/genai v1.44.0
pgregory.net/rapid v1.2.0
)

require (
Expand All @@ -28,7 +30,7 @@ require (
cloud.google.com/go/compute/metadata v0.9.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0 // indirect
github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.3 // indirect
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.4 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.19.7 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.17 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.17 // indirect
Expand Down
8 changes: 6 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ github.com/RealAlexandreAI/json-repair v0.0.15 h1:AN8/yt8rcphwQrIs/FZeki+cKaIERU
github.com/RealAlexandreAI/json-repair v0.0.15/go.mod h1:GKJi5borR78O8c7HCVbgqjhoiVibZ6hJldxbc6dGrAI=
github.com/aws/aws-sdk-go-v2 v1.41.1 h1:ABlyEARCDLN034NhxlRUSZr4l71mh+T5KAeGh6cerhU=
github.com/aws/aws-sdk-go-v2 v1.41.1/go.mod h1:MayyLB8y+buD9hZqkCW3kX1AKq07Y5pXxtgB+rRFhz0=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.3 h1:tW1/Rkad38LA15X4UQtjXZXNKsCgkshC3EbmcUmghTg=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.3/go.mod h1:UbnqO+zjqk3uIt9yCACHJ9IVNhyhOCnYk8yA19SAWrM=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.4 h1:489krEF9xIGkOaaX3CE/Be2uWjiXrkCH6gUX+bZA/BU=
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.4/go.mod h1:IOAPF6oT9KCsceNTvvYMNHy0+kMF8akOjeDvPENWxp4=
github.com/aws/aws-sdk-go-v2/config v1.32.7 h1:vxUyWGUwmkQ2g19n7JY/9YL8MfAIl7bTesIUykECXmY=
github.com/aws/aws-sdk-go-v2/config v1.32.7/go.mod h1:2/Qm5vKUU/r7Y+zUk/Ptt2MDAEKAfUtKc1+3U1Mo3oY=
github.com/aws/aws-sdk-go-v2/credentials v1.19.7 h1:tHK47VqqtJxOymRrNtUXN5SP/zUTvZKeLx4tH6PGQc8=
Expand All @@ -34,6 +34,8 @@ github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.17 h1:WWLqlh79iO48yLkj1v
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.17/go.mod h1:EhG22vHRrvF8oXSTYStZhJc1aUgKtnJe+aOiFEV90cM=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4 h1:WKuaxf++XKWlHWu9ECbMlha8WOEGm0OUEZqm4K/Gcfk=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.4/go.mod h1:ZWy7j6v1vWGmPReu0iSGvRiise4YI5SkR3OHKTZ6Wuc=
github.com/aws/aws-sdk-go-v2/service/bedrockruntime v1.47.2 h1:p9fvRzUDCTTXd3FuGIHtuMRX21eoh1TB2QMKvdBs9ZM=
github.com/aws/aws-sdk-go-v2/service/bedrockruntime v1.47.2/go.mod h1:siKVmJdui4dwPPtsKr3F5BAeJxW1MANWaLJnTDfgu7c=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.4 h1:0ryTNEdJbzUCEWkVXEXoqlXV72J5keC1GvILMOuD00E=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.4/go.mod h1:HQ4qwNZh32C3CBeO6iJLQlgtMzqeG17ziAA/3KDJFow=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.17 h1:RuNSMoozM8oXlgLG/n6WLaFGoea7/CddrCfIiSA+xdY=
Expand Down Expand Up @@ -185,3 +187,5 @@ gopkg.in/dnaeon/go-vcr.v4 v4.0.6-0.20251110073552-01de4eb40290 h1:g3ah7zaWmw41Et
gopkg.in/dnaeon/go-vcr.v4 v4.0.6-0.20251110073552-01de4eb40290/go.mod h1:sbq5oMEcM4PXngbcNbHhzfCP9OdZodLhrbRYoyg09HY=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
pgregory.net/rapid v1.2.0 h1:keKAYRcjm+e1F0oAuU5F5+YPAWcyxNNRK2wud503Gnk=
pgregory.net/rapid v1.2.0/go.mod h1:PY5XlDGj0+V1FCq0o192FdRhpKHGTRIWBgqjDBTrq04=
67 changes: 67 additions & 0 deletions providers/bedrock/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,70 @@ To see available models, run:
```bash
aws bedrock list-inference-profiles --region us-east-1
```

## Amazon Nova Models via Bedrock

Fantasy supports Amazon's Nova family of foundation models through AWS Bedrock. Nova models offer high-quality text generation with competitive pricing and performance.

### Supported Nova Models

- **amazon.nova-pro-v1:0** - High-performance model for complex tasks
- **amazon.nova-lite-v1:0** - Fast, cost-effective model for simpler tasks
- **amazon.nova-micro-v1:0** - Ultra-fast model for basic text generation
- **amazon.nova-premier-v1:0** - Most capable model with advanced reasoning

### Model ID Format

Nova models use the Bedrock model identifier format: `amazon.nova-{variant}-v{version}:{revision}`

When you create a language model instance, Fantasy automatically applies the appropriate region prefix (e.g., `us.amazon.nova-pro-v1:0` for us-east-1).

### AWS Credential Requirements

To use Nova models, you need AWS credentials configured. Fantasy uses the standard AWS SDK credential chain, which checks:

1. Environment variables (`AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`)
2. AWS credentials file (`~/.aws/credentials`)
3. IAM role (when running on AWS infrastructure)
4. Bearer token (`AWS_BEARER_TOKEN_BEDROCK` for testing/development)

You also need to specify the AWS region:

- Set `AWS_REGION` environment variable (e.g., `us-east-1`)
- If not set, Fantasy defaults to `us-east-1`

### Quick Example

```go
import "charm.land/fantasy/providers/bedrock"

// Create Bedrock provider
provider, err := bedrock.New()
if err != nil {
fmt.Fprintln(os.Stderr, "Error:", err)
os.Exit(1)
}

ctx := context.Background()

// Use a Nova model
model, err := provider.LanguageModel(ctx, "amazon.nova-pro-v1:0")
if err != nil {
fmt.Fprintln(os.Stderr, "Error:", err)
os.Exit(1)
}

// Generate text
agent := fantasy.NewAgent(model,
fantasy.WithSystemPrompt("You are a helpful assistant."),
)

result, err := agent.Generate(ctx, fantasy.AgentCall{
Prompt: "Explain quantum computing in simple terms.",
})
if err != nil {
fmt.Fprintln(os.Stderr, "Error:", err)
os.Exit(1)
}
fmt.Println(result.Response.Content.Text())
```
42 changes: 41 additions & 1 deletion providers/bedrock/bedrock.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
package bedrock

import (
"context"
"fmt"
"strings"

"charm.land/fantasy"
"charm.land/fantasy/providers/anthropic"
"github.com/charmbracelet/anthropic-sdk-go/option"
Expand All @@ -10,6 +14,8 @@ import (
type options struct {
skipAuth bool
anthropicOptions []anthropic.Option
headers map[string]string
client option.HTTPClient
}

const (
Expand All @@ -20,20 +26,52 @@ const (
// Option defines a function that configures Bedrock provider options.
type Option = func(*options)

type provider struct {
options options
anthropicProvider fantasy.Provider
}

// New creates a new Bedrock provider with the given options.
func New(opts ...Option) (fantasy.Provider, error) {
var o options
for _, opt := range opts {
opt(&o)
}
return anthropic.New(

// Create Anthropic provider for anthropic.* models
anthropicProvider, err := anthropic.New(
append(
o.anthropicOptions,
anthropic.WithName(Name),
anthropic.WithBedrock(),
anthropic.WithSkipAuth(o.skipAuth),
)...,
)
if err != nil {
return nil, err
}

return &provider{
options: o,
anthropicProvider: anthropicProvider,
}, nil
}

// Name returns the provider name.
func (p *provider) Name() string {
return Name
}

// LanguageModel routes to the appropriate SDK based on model ID prefix.
func (p *provider) LanguageModel(ctx context.Context, modelID string) (fantasy.LanguageModel, error) {
if strings.HasPrefix(modelID, "anthropic.") {
// Use Anthropic SDK (existing behavior)
return p.anthropicProvider.LanguageModel(ctx, modelID)
} else if strings.HasPrefix(modelID, "amazon.") {
// Use AWS SDK Converse API (new behavior)
return p.createNovaModel(ctx, modelID)
}
return nil, fmt.Errorf("unsupported model prefix for Bedrock: %s", modelID)
}

// WithAPIKey sets the access token for the Bedrock provider.
Expand All @@ -46,13 +84,15 @@ func WithAPIKey(apiKey string) Option {
// WithHeaders sets the headers for the Bedrock provider.
func WithHeaders(headers map[string]string) Option {
return func(o *options) {
o.headers = headers
o.anthropicOptions = append(o.anthropicOptions, anthropic.WithHeaders(headers))
}
}

// WithHTTPClient sets the HTTP client for the Bedrock provider.
func WithHTTPClient(client option.HTTPClient) Option {
return func(o *options) {
o.client = client
o.anthropicOptions = append(o.anthropicOptions, anthropic.WithHTTPClient(client))
}
}
Expand Down
Loading
Loading