diff --git a/src/components/organizations/byok/BYOKKeysManager.tsx b/src/components/organizations/byok/BYOKKeysManager.tsx
index 27e3fdfc3..253716bf1 100644
--- a/src/components/organizations/byok/BYOKKeysManager.tsx
+++ b/src/components/organizations/byok/BYOKKeysManager.tsx
@@ -44,6 +44,7 @@ import {
// Hardcoded BYOK providers list
const BYOK_PROVIDERS = [
{ id: VercelUserByokInferenceProviderIdSchema.enum.anthropic, name: 'Anthropic' },
+ { id: VercelUserByokInferenceProviderIdSchema.enum.bedrock, name: 'AWS Bedrock' },
{ id: VercelUserByokInferenceProviderIdSchema.enum.openai, name: 'OpenAI' },
{ id: VercelUserByokInferenceProviderIdSchema.enum.google, name: 'Google AI Studio' },
{ id: VercelUserByokInferenceProviderIdSchema.enum.minimax, name: 'MiniMax' },
@@ -390,26 +391,57 @@ export function BYOKKeysManager({ organizationId }: BYOKKeysManagerProps) {
-
-
-
+ {selectedProvider === VercelUserByokInferenceProviderIdSchema.enum.bedrock
+ ? 'AWS Credentials'
+ : 'API Key'}
+
+ {selectedProvider === VercelUserByokInferenceProviderIdSchema.enum.bedrock ? (
+
+ ) : (
+
+ setApiKey(e.target.value)}
+ placeholder="Enter API key"
+ className="pr-10"
+ />
+
+
+ )}
+ {selectedProvider === VercelUserByokInferenceProviderIdSchema.enum.bedrock && (
+
+
+
+ Enter your AWS credentials as JSON:
+
+ {'{"accessKeyId": "...", "secretAccessKey": "...", "region": "us-east-1"}'}
+
+
+ Your IAM user needs bedrock:InvokeModel and{' '}
+ bedrock:InvokeModelWithResponseStream{' '}
+ permissions.
+
+
+
+ )}
{editingKeyId ? (
diff --git a/src/lib/providers/openrouter/inference-provider-id.ts b/src/lib/providers/openrouter/inference-provider-id.ts
index 0ff353950..ca69641d0 100644
--- a/src/lib/providers/openrouter/inference-provider-id.ts
+++ b/src/lib/providers/openrouter/inference-provider-id.ts
@@ -25,6 +25,7 @@ export const OpenRouterInferenceProviderIdSchema = z.enum([
export const VercelUserByokInferenceProviderIdSchema = z.enum([
'anthropic',
+ 'bedrock',
'google', // Google AI Studio
'openai',
'minimax',
@@ -47,7 +48,7 @@ export const UserByokProviderIdSchema = VercelUserByokInferenceProviderIdSchema.
export type UserByokProviderId = z.infer;
-export const VercelNonUserByokInferenceProviderIdSchema = z.enum(['alibaba', 'bedrock', 'vertex']);
+export const VercelNonUserByokInferenceProviderIdSchema = z.enum(['alibaba', 'vertex']);
export const VercelInferenceProviderIdSchema = VercelUserByokInferenceProviderIdSchema.or(
VercelNonUserByokInferenceProviderIdSchema
@@ -59,7 +60,7 @@ export type VercelInferenceProviderId = z.infer;
diff --git a/src/lib/providers/openrouter/types.ts b/src/lib/providers/openrouter/types.ts
index c4b24ebd3..4e76c3f6b 100644
--- a/src/lib/providers/openrouter/types.ts
+++ b/src/lib/providers/openrouter/types.ts
@@ -2,6 +2,7 @@ import type OpenAI from 'openai';
import type { GatewayProviderOptions } from '@ai-sdk/gateway';
import type { AnthropicProviderOptions } from '@ai-sdk/anthropic';
import type { ReasoningDetailUnion } from '@/lib/custom-llm/reasoning-details';
+import type { AwsCredentials } from '@/lib/providers/openrouter/inference-provider-id';
// Base types for OpenRouter API that don't depend on other lib files
// This breaks circular dependencies with mistral.ts, minimax.ts, etc.
@@ -13,7 +14,7 @@ export type OpenRouterProviderConfig = {
zdr?: boolean;
};
-export type VercelInferenceProviderConfig = { apiKey: string; baseURL?: string };
+export type VercelInferenceProviderConfig = { apiKey: string; baseURL?: string } | AwsCredentials;
export type VercelProviderConfig = {
gateway?: GatewayProviderOptions & {
diff --git a/src/lib/providers/vercel/index.ts b/src/lib/providers/vercel/index.ts
index ab1841f14..7e15306bc 100644
--- a/src/lib/providers/vercel/index.ts
+++ b/src/lib/providers/vercel/index.ts
@@ -4,6 +4,7 @@ import { isAnthropicModel } from '@/lib/providers/anthropic';
import { getGatewayErrorRate } from '@/lib/providers/gateway-error-rate';
import {
AutocompleteUserByokProviderIdSchema,
+ AwsCredentialsSchema,
openRouterToVercelInferenceProviderId,
VercelUserByokInferenceProviderIdSchema,
} from '@/lib/providers/openrouter/inference-provider-id';
@@ -101,6 +102,14 @@ function convertProviderOptions(
};
}
+function parseAwsCredentials(input: string) {
+ try {
+ return AwsCredentialsSchema.parse(JSON.parse(input));
+ } catch {
+ throw new Error('Failed to parse AWS credentials');
+ }
+}
+
export function applyVercelSettings(
requestedModel: string,
requestToMutate: OpenRouterChatCompletionRequest,
@@ -128,6 +137,7 @@ export function applyVercelSettings(
? VercelUserByokInferenceProviderIdSchema.enum.mistral
: provider.providerId;
const list = new Array();
+
if (key === VercelUserByokInferenceProviderIdSchema.enum.zai) {
// Z.AI Coding Plan support
list.push({
@@ -135,7 +145,13 @@ export function applyVercelSettings(
baseURL: 'https://api.z.ai/api/coding/paas/v4',
});
}
- list.push({ apiKey: provider.decryptedAPIKey });
+
+ if (key === VercelUserByokInferenceProviderIdSchema.enum.bedrock) {
+ list.push(parseAwsCredentials(provider.decryptedAPIKey));
+ } else {
+ list.push({ apiKey: provider.decryptedAPIKey });
+ }
+
byokProviders[key] = [...(byokProviders[key] ?? []), ...list];
}