From 5f62881a9118b7a31bf316b0ef079af5b9e04496 Mon Sep 17 00:00:00 2001 From: Devansh Dubey Date: Mon, 25 May 2026 19:47:39 +0530 Subject: [PATCH] added docs for claude platform on aws --- docs.json | 9 + .../llms/claude-platform-aws/batches.mdx | 479 ++++++++++++++++ .../claude-platform-aws.mdx | 524 ++++++++++++++++++ .../llms/claude-platform-aws/files.mdx | 429 ++++++++++++++ .../setup-assumed-role.mdx | 196 +++++++ 5 files changed, 1637 insertions(+) create mode 100644 integrations/llms/claude-platform-aws/batches.mdx create mode 100644 integrations/llms/claude-platform-aws/claude-platform-aws.mdx create mode 100644 integrations/llms/claude-platform-aws/files.mdx create mode 100644 integrations/llms/claude-platform-aws/setup-assumed-role.mdx diff --git a/docs.json b/docs.json index 13b371e9..4caf1e4e 100644 --- a/docs.json +++ b/docs.json @@ -416,6 +416,15 @@ "integrations/llms/bedrock/bedrock-knowledgebase" ] }, + { + "group": "Claude Platform on AWS", + "pages": [ + "integrations/llms/claude-platform-aws/claude-platform-aws", + "integrations/llms/claude-platform-aws/setup-assumed-role", + "integrations/llms/claude-platform-aws/files", + "integrations/llms/claude-platform-aws/batches" + ] + }, "integrations/llms/bedrock-mantle", "integrations/llms/aws-sagemaker", "integrations/llms/ollama", diff --git a/integrations/llms/claude-platform-aws/batches.mdx b/integrations/llms/claude-platform-aws/batches.mdx new file mode 100644 index 00000000..588dac24 --- /dev/null +++ b/integrations/llms/claude-platform-aws/batches.mdx @@ -0,0 +1,479 @@ +--- +title: Batches +description: Run asynchronous batch jobs on Claude Platform on AWS through Portkey's unified /v1/batches API +--- + + +Self-hosted deployments require **Enterprise Gateway v2.6.1+**. + + +Portkey exposes Anthropic's [Message Batches API](https://docs.anthropic.com/en/docs/build-with-claude/batch-processing) for Claude Platform on AWS through the unified OpenAI-compatible `/v1/batches` endpoints. All five batch operations -- create, retrieve, cancel, list, and get output -- are supported, enabling large asynchronous Claude jobs at 50% lower cost. + +Use batches for offline workloads like nightly evals, bulk summarization, or dataset grading. + +## Supported Endpoints + +| Gateway Endpoint | Anthropic Upstream | Operation | +| ---------------------------------------- | -------------------------------------------------- | ---------------- | +| `POST /v1/batches` | `POST /v1/messages/batches` | Create a batch | +| `GET /v1/batches/{batch_id}` | `GET /v1/messages/batches/{batch_id}` | Retrieve a batch | +| `POST /v1/batches/{batch_id}/cancel` | `POST /v1/messages/batches/{batch_id}/cancel` | Cancel a batch | +| `GET /v1/batches` | `GET /v1/messages/batches` | List batches | +| `GET /v1/batches/{batch_id}/output` | Streams from `results_url` | Get batch output | + +## Request Format + + +Unlike OpenAI's file-based batches, Anthropic batch creation uses an inline `requests[]` array -- there is no `input_file_id`. Each item carries a `custom_id` and a `params` object containing the standard Messages API payload. + + +```json +{ + "requests": [ + { + "custom_id": "req-1", + "params": { + "model": "claude-sonnet-4-6", + "max_tokens": 1024, + "messages": [ + { "role": "user", "content": "Hello" } + ] + } + } + ] +} +``` + +## Create a Batch + + + +```python +from portkey_ai import Portkey + +portkey = Portkey( + api_key="PORTKEY_API_KEY", + provider="@claude-platform-aws-provider" +) + +batch = portkey.post( + "/batches", + requests=[ + { + "custom_id": "req-1", + "params": { + "model": "claude-sonnet-4-6", + "max_tokens": 1024, + "messages": [{"role": "user", "content": "Hello"}] + } + } + ] +) + +print(batch) +``` + + +```js +import Portkey from 'portkey-ai'; + +const portkey = new Portkey({ + apiKey: "PORTKEY_API_KEY", + provider: "@claude-platform-aws-provider" +}); + +const batch = await portkey.post('/batches', { + requests: [ + { + custom_id: "req-1", + params: { + model: "claude-sonnet-4-6", + max_tokens: 1024, + messages: [{ role: "user", content: "Hello" }] + } + } + ] +}); + +console.log(batch); +``` + + +```sh +curl -X POST https://api.portkey.ai/v1/batches \ + -H "x-portkey-api-key: $PORTKEY_API_KEY" \ + -H "x-portkey-provider: @claude-platform-aws-provider" \ + -H "Content-Type: application/json" \ + -d '{ + "requests": [ + { + "custom_id": "req-1", + "params": { + "model": "claude-sonnet-4-6", + "max_tokens": 1024, + "messages": [ + { "role": "user", "content": "Hello" } + ] + } + } + ] + }' +``` + + +```python +from openai import OpenAI +from portkey_ai import PORTKEY_GATEWAY_URL, createHeaders + +client = OpenAI( + api_key="PORTKEY_API_KEY", + base_url=PORTKEY_GATEWAY_URL, + default_headers=createHeaders( + provider="@claude-platform-aws-provider", + api_key="PORTKEY_API_KEY" + ) +) + +batch = client.post( + "/batches", + body={ + "requests": [ + { + "custom_id": "req-1", + "params": { + "model": "claude-sonnet-4-6", + "max_tokens": 1024, + "messages": [{"role": "user", "content": "Hello"}] + } + } + ] + }, + cast_to=object +) + +print(batch) +``` + + +```js +import OpenAI from 'openai'; +import { PORTKEY_GATEWAY_URL, createHeaders } from 'portkey-ai'; + +const client = new OpenAI({ + apiKey: "PORTKEY_API_KEY", + baseURL: PORTKEY_GATEWAY_URL, + defaultHeaders: createHeaders({ + provider: "@claude-platform-aws-provider", + apiKey: "PORTKEY_API_KEY" + }) +}); + +const batch = await client.post('/batches', { + body: { + requests: [ + { + custom_id: "req-1", + params: { + model: "claude-sonnet-4-6", + max_tokens: 1024, + messages: [{ role: "user", content: "Hello" }] + } + } + ] + } +}); + +console.log(batch); +``` + + + +## Retrieve a Batch + +Returns the OpenAI-compatible Batch object. Once processing completes, the response includes `results_url` from Anthropic. + + + +```python +from portkey_ai import Portkey + +portkey = Portkey( + api_key="PORTKEY_API_KEY", + provider="@claude-platform-aws-provider" +) + +batch = portkey.batches.retrieve(batch_id="") + +print(batch) +``` + + +```js +import Portkey from 'portkey-ai'; + +const portkey = new Portkey({ + apiKey: "PORTKEY_API_KEY", + provider: "@claude-platform-aws-provider" +}); + +const batch = await portkey.batches.retrieve(""); + +console.log(batch); +``` + + +```sh +curl https://api.portkey.ai/v1/batches/ \ + -H "x-portkey-api-key: $PORTKEY_API_KEY" \ + -H "x-portkey-provider: @claude-platform-aws-provider" +``` + + +```python +from openai import OpenAI +from portkey_ai import PORTKEY_GATEWAY_URL, createHeaders + +client = OpenAI( + api_key="PORTKEY_API_KEY", + base_url=PORTKEY_GATEWAY_URL, + default_headers=createHeaders( + provider="@claude-platform-aws-provider", + api_key="PORTKEY_API_KEY" + ) +) + +batch = client.batches.retrieve("") + +print(batch) +``` + + +```js +import OpenAI from 'openai'; +import { PORTKEY_GATEWAY_URL, createHeaders } from 'portkey-ai'; + +const client = new OpenAI({ + apiKey: "PORTKEY_API_KEY", + baseURL: PORTKEY_GATEWAY_URL, + defaultHeaders: createHeaders({ + provider: "@claude-platform-aws-provider", + apiKey: "PORTKEY_API_KEY" + }) +}); + +const batch = await client.batches.retrieve(""); + +console.log(batch); +``` + + + +## List Batches + + + +```python +from portkey_ai import Portkey + +portkey = Portkey( + api_key="PORTKEY_API_KEY", + provider="@claude-platform-aws-provider" +) + +batches = portkey.batches.list() + +print(batches) +``` + + +```js +import Portkey from 'portkey-ai'; + +const portkey = new Portkey({ + apiKey: "PORTKEY_API_KEY", + provider: "@claude-platform-aws-provider" +}); + +const batches = await portkey.batches.list(); + +console.log(batches); +``` + + +```sh +curl https://api.portkey.ai/v1/batches \ + -H "x-portkey-api-key: $PORTKEY_API_KEY" \ + -H "x-portkey-provider: @claude-platform-aws-provider" +``` + + +```python +from openai import OpenAI +from portkey_ai import PORTKEY_GATEWAY_URL, createHeaders + +client = OpenAI( + api_key="PORTKEY_API_KEY", + base_url=PORTKEY_GATEWAY_URL, + default_headers=createHeaders( + provider="@claude-platform-aws-provider", + api_key="PORTKEY_API_KEY" + ) +) + +batches = client.batches.list() + +print(batches) +``` + + +```js +import OpenAI from 'openai'; +import { PORTKEY_GATEWAY_URL, createHeaders } from 'portkey-ai'; + +const client = new OpenAI({ + apiKey: "PORTKEY_API_KEY", + baseURL: PORTKEY_GATEWAY_URL, + defaultHeaders: createHeaders({ + provider: "@claude-platform-aws-provider", + apiKey: "PORTKEY_API_KEY" + }) +}); + +const batches = await client.batches.list(); + +console.log(batches); +``` + + + +## Cancel a Batch + + + +```python +from portkey_ai import Portkey + +portkey = Portkey( + api_key="PORTKEY_API_KEY", + provider="@claude-platform-aws-provider" +) + +cancelled = portkey.batches.cancel(batch_id="") + +print(cancelled) +``` + + +```js +import Portkey from 'portkey-ai'; + +const portkey = new Portkey({ + apiKey: "PORTKEY_API_KEY", + provider: "@claude-platform-aws-provider" +}); + +const cancelled = await portkey.batches.cancel(""); + +console.log(cancelled); +``` + + +```sh +curl -X POST https://api.portkey.ai/v1/batches//cancel \ + -H "x-portkey-api-key: $PORTKEY_API_KEY" \ + -H "x-portkey-provider: @claude-platform-aws-provider" +``` + + +```python +from openai import OpenAI +from portkey_ai import PORTKEY_GATEWAY_URL, createHeaders + +client = OpenAI( + api_key="PORTKEY_API_KEY", + base_url=PORTKEY_GATEWAY_URL, + default_headers=createHeaders( + provider="@claude-platform-aws-provider", + api_key="PORTKEY_API_KEY" + ) +) + +cancelled = client.batches.cancel("") + +print(cancelled) +``` + + +```js +import OpenAI from 'openai'; +import { PORTKEY_GATEWAY_URL, createHeaders } from 'portkey-ai'; + +const client = new OpenAI({ + apiKey: "PORTKEY_API_KEY", + baseURL: PORTKEY_GATEWAY_URL, + defaultHeaders: createHeaders({ + provider: "@claude-platform-aws-provider", + apiKey: "PORTKEY_API_KEY" + }) +}); + +const cancelled = await client.batches.cancel(""); + +console.log(cancelled); +``` + + + +## Get Batch Output + + +Before streaming results, Portkey retrieves the batch metadata and verifies that `processing_status === 'ended'`. It then fetches from Anthropic's `results_url`, generating fresh SigV4-signed headers for the output URL. The response body is streamed back as JSONL in Anthropic's native format. + + + + +```sh +curl https://api.portkey.ai/v1/batches//output \ + -H "x-portkey-api-key: $PORTKEY_API_KEY" \ + -H "x-portkey-provider: @claude-platform-aws-provider" +``` + + + +A typical output line: + +```json +{ + "custom_id": "req-1", + "result": { + "type": "succeeded", + "message": { + "id": "msg_01XYZ...", + "type": "message", + "role": "assistant", + "content": [{ "type": "text", "text": "Hello! How can I help?" }], + "model": "claude-sonnet-4-6", + "stop_reason": "end_turn", + "usage": { "input_tokens": 10, "output_tokens": 12 } + } + } +} +``` + +## Response Format + +`createBatch`, `retrieveBatch`, `cancelBatch`, and `listBatches` return the OpenAI Batch shape so existing OpenAI tooling works unchanged: + +- `object: "batch"` and `endpoint: "/v1/batches"` on every batch record +- `status` values normalized to OpenAI-compatible strings (`validating`, `in_progress`, `finalizing`, `completed`, `failed`, `cancelling`, `cancelled`, `expired`) +- Timestamps converted from Anthropic's ISO 8601 to Unix epoch seconds +- Request counts mapped: `succeeded → completed`, `errored → failed` +- `retrieveBatch` surfaces `results_url` from the Anthropic response when the batch has finished processing + +`getBatchOutput` streams the raw Anthropic-native JSONL for full Claude response fidelity (content blocks, tool use, stop reasons, usage). + +## See Also + +- [Unified Batch Guide](/product/ai-gateway/batches) +- [Claude Platform on AWS integration overview](/integrations/llms/claude-platform-aws/claude-platform-aws) +- [Anthropic Message Batches API reference](https://docs.anthropic.com/en/docs/build-with-claude/batch-processing) diff --git a/integrations/llms/claude-platform-aws/claude-platform-aws.mdx b/integrations/llms/claude-platform-aws/claude-platform-aws.mdx new file mode 100644 index 00000000..3322ecfc --- /dev/null +++ b/integrations/llms/claude-platform-aws/claude-platform-aws.mdx @@ -0,0 +1,524 @@ +--- +title: "Claude Platform on AWS" +description: "Integrate Claude models via Claude Platform on AWS with Portkey's AI Gateway" +--- + +[Claude Platform on AWS](https://platform.claude.com/docs/en/build-with-claude/claude-platform-on-aws) is Anthropic's managed Claude offering delivered through AWS. It uses the same Anthropic Messages API with AWS SigV4 authentication and billing through AWS Marketplace. + +Portkey provider slug: `claude-platform-aws` + + + + Opus, Sonnet, and Haiku with plain model IDs + + + Messages, batches, files, token counting + + + Access Key, Assumed Role, and Service Role + + + +## Quick Start + + +```python Python icon="python" +from portkey_ai import Portkey + +# 1. Install: pip install portkey-ai +# 2. Add @claude-platform-aws provider in Model Catalog +# 3. Use it: + +portkey = Portkey(api_key="PORTKEY_API_KEY") + +response = portkey.chat.completions.create( + model="@claude-platform-aws-provider/claude-sonnet-4-6", + messages=[{"role": "user", "content": "What is Portkey's AI Gateway?"}], + max_tokens=250 +) + +print(response.choices[0].message.content) +``` + +```js Javascript icon="square-js" +import Portkey from 'portkey-ai' + +// 1. Install: npm install portkey-ai +// 2. Add @claude-platform-aws provider in Model Catalog +// 3. Use it: + +const portkey = new Portkey({ + apiKey: "PORTKEY_API_KEY" +}) + +const response = await portkey.chat.completions.create({ + model: "@claude-platform-aws-provider/claude-sonnet-4-6", + messages: [{ role: "user", content: "What is Portkey's AI Gateway?" }], + max_tokens: 250 +}) + +console.log(response.choices[0].message.content) +``` + +```python OpenAI Py icon="python" +from openai import OpenAI +from portkey_ai import PORTKEY_GATEWAY_URL + +# 1. Install: pip install openai portkey-ai +# 2. Add @claude-platform-aws provider in Model Catalog +# 3. Use it: + +client = OpenAI( + api_key="PORTKEY_API_KEY", + base_url=PORTKEY_GATEWAY_URL +) + +response = client.chat.completions.create( + model="@claude-platform-aws-provider/claude-sonnet-4-6", + messages=[{"role": "user", "content": "What is Portkey's AI Gateway?"}], + max_tokens=250 +) + +print(response.choices[0].message.content) +``` + +```js OpenAI JS icon="square-js" +import OpenAI from "openai" +import { PORTKEY_GATEWAY_URL } from "portkey-ai" + +// 1. Install: npm install openai portkey-ai +// 2. Add @claude-platform-aws provider in Model Catalog +// 3. Use it: + +const client = new OpenAI({ + apiKey: "PORTKEY_API_KEY", + baseURL: PORTKEY_GATEWAY_URL +}) + +const response = await client.chat.completions.create({ + model: "@claude-platform-aws-provider/claude-sonnet-4-6", + messages: [{ role: "user", content: "What is Portkey's AI Gateway?" }], + max_tokens: 250 +}) + +console.log(response.choices[0].message.content) +``` + +```sh cURL icon="square-terminal" +curl https://api.portkey.ai/v1/chat/completions \ + -H "Content-Type: application/json" \ + -H "x-portkey-api-key: $PORTKEY_API_KEY" \ + -d '{ + "model": "@claude-platform-aws-provider/claude-sonnet-4-6", + "messages": [ + { "role": "user", "content": "What is Portkey's AI Gateway?" } + ], + "max_tokens": 250 + }' +``` + +```python Anthropic Py +import anthropic + +# 1. Install: pip install anthropic portkey-ai +# 2. Add @claude-platform-aws provider in Model Catalog +# 3. Use it: + +client = anthropic.Anthropic( + api_key="dummy", + default_headers={"x-portkey-api-key": "YOUR_PORTKEY_API_KEY"}, + base_url="https://api.portkey.ai" +) + +message = client.messages.create( + model="@claude-platform-aws-provider/claude-sonnet-4-6", + max_tokens=250, + messages=[{"role": "user", "content": "What is Portkey's AI Gateway?"}] +) + +print(message.content) +``` + +```typescript Anthropic TS +import Anthropic from '@anthropic-ai/sdk' + +// 1. Install: npm install @anthropic-ai/sdk portkey-ai +// 2. Add @claude-platform-aws provider in Model Catalog +// 3. Use it: + +const anthropic = new Anthropic({ + apiKey: "YOUR_PORTKEY_API_KEY", + baseURL: "https://api.portkey.ai" +}) + +const msg = await anthropic.messages.create({ + model: "@claude-platform-aws-provider/claude-sonnet-4-6", + max_tokens: 250, + messages: [{ role: "user", content: "What is Portkey's AI Gateway?" }] +}) + +console.log(msg) +``` + + +- **`max_tokens` is required** -- always specify this parameter +- **Model IDs** are identical to the first-party Anthropic API (e.g., `claude-sonnet-4-6`, `claude-opus-4-7`) + +## Prerequisites + + +Enable outbound web identity federation on your AWS account before making any requests: + +```bash +aws iam enable-outbound-web-identity-federation +``` + +Without this, all requests fail with `"Outbound web identity federation is disabled for your account"`. + + +## Add Provider in Model Catalog + +1. Go to [**Model Catalog → Add Provider**](https://app.portkey.ai/model-catalog/providers) +2. Select **Claude Platform on AWS** +3. Choose an authentication mode and enter credentials + +| Auth Mode | Required Fields | +|---|---| +| **AWS Access Key** | `awsAccessKeyId`, `awsSecretAccessKey`, `awsRegion` | +| **Assumed Role** | `awsRoleArn`, `awsExternalId` (optional), `awsRegion` | +| **Service Role** (EKS/IRSA) | `awsRegion` | + +All auth modes accept an optional **Anthropic Workspace ID** (`anthropicAwsWorkspaceId`). Set this to scope requests to a specific workspace (format: `wrkspc_01AbCdEf23GhIj`). + +`awsRegion` determines the endpoint: `aws-external-anthropic.{region}.api.aws` + + + Step-by-step IAM role and trust policy configuration for assumed role auth + + +## IAM Policy + +Claude Platform on AWS uses the `aws-external-anthropic` IAM namespace. Create a permission policy with the actions your workload needs: + + +```json Inference Only +{ + "Version": "2012-10-17", + "Statement": [{ + "Effect": "Allow", + "Action": [ + "aws-external-anthropic:CreateInference", + "aws-external-anthropic:CountTokens" + ], + "Resource": "arn:aws:aws-external-anthropic:us-west-2:123456789012:workspace/wrkspc_01AbCdEf23GhIj" + }] +} +``` + +```json Inference + Batch + Files +{ + "Version": "2012-10-17", + "Statement": [{ + "Effect": "Allow", + "Action": [ + "aws-external-anthropic:CreateInference", + "aws-external-anthropic:CountTokens", + "aws-external-anthropic:CreateBatchInference", + "aws-external-anthropic:GetBatchInference", + "aws-external-anthropic:ListBatchInferences", + "aws-external-anthropic:CancelBatchInference", + "aws-external-anthropic:DeleteBatchInference", + "aws-external-anthropic:CreateFile", + "aws-external-anthropic:GetFile", + "aws-external-anthropic:ListFiles", + "aws-external-anthropic:DeleteFile" + ], + "Resource": "arn:aws:aws-external-anthropic:us-west-2:123456789012:workspace/wrkspc_01AbCdEf23GhIj" + }] +} +``` + + +AWS also provides managed policies for common use cases: + +| Managed Policy | Scope | +|---|---| +| `AnthropicFullAccess` | All `aws-external-anthropic:*` actions | +| `AnthropicInferenceAccess` | Inference + read-only + batch | +| `AnthropicReadOnlyAccess` | `Get*`, `List*`, `CallWithBearerToken` | + +## Basic Usage + +### Chat Completions + + +```python Python icon="python" +from portkey_ai import Portkey + +portkey = Portkey(api_key="PORTKEY_API_KEY") + +response = portkey.chat.completions.create( + model="@claude-platform-aws-provider/claude-sonnet-4-6", + messages=[ + {"role": "system", "content": "You are a helpful assistant."}, + {"role": "user", "content": "Explain quantum computing in simple terms."} + ], + max_tokens=500 +) + +print(response.choices[0].message.content) +``` + +```js Javascript icon="square-js" +import Portkey from 'portkey-ai' + +const portkey = new Portkey({ + apiKey: "PORTKEY_API_KEY" +}) + +const response = await portkey.chat.completions.create({ + model: "@claude-platform-aws-provider/claude-sonnet-4-6", + messages: [ + { role: "system", content: "You are a helpful assistant." }, + { role: "user", content: "Explain quantum computing in simple terms." } + ], + max_tokens: 500 +}) + +console.log(response.choices[0].message.content) +``` + + +### Streaming + + +```python Python icon="python" +response = portkey.chat.completions.create( + model="@claude-platform-aws-provider/claude-sonnet-4-6", + messages=[{"role": "user", "content": "Tell me a story"}], + max_tokens=500, + stream=True +) + +for chunk in response: + if chunk.choices[0].delta.content: + print(chunk.choices[0].delta.content, end="") +``` + +```js Javascript icon="square-js" +const response = await portkey.chat.completions.create({ + model: "@claude-platform-aws-provider/claude-sonnet-4-6", + messages: [{ role: "user", content: "Tell me a story" }], + max_tokens: 500, + stream: true +}) + +for await (const chunk of response) { + if (chunk.choices[0].delta.content) { + process.stdout.write(chunk.choices[0].delta.content) + } +} +``` + + +## Using the /messages Route + +Use Anthropic's native `/messages` endpoint through Portkey with full gateway features. + +### Using Anthropic's Native SDK + + +```python Anthropic Py +import anthropic + +client = anthropic.Anthropic( + api_key="dummy", + default_headers={"x-portkey-api-key": "YOUR_PORTKEY_API_KEY"}, + base_url="https://api.portkey.ai" +) + +message = client.messages.create( + model="@claude-platform-aws-provider/claude-sonnet-4-6", + max_tokens=250, + messages=[{"role": "user", "content": "Hello, Claude"}] +) + +print(message.content) +``` + +```typescript Anthropic TS +import Anthropic from '@anthropic-ai/sdk' + +const anthropic = new Anthropic({ + apiKey: "YOUR_PORTKEY_API_KEY", + baseURL: "https://api.portkey.ai" +}) + +const msg = await anthropic.messages.create({ + model: "@claude-platform-aws-provider/claude-sonnet-4-6", + max_tokens: 1024, + messages: [{ role: "user", content: "Hello, Claude" }] +}) + +console.log(msg) +``` + + +### Using cURL + +```sh cURL icon="square-terminal" +curl https://api.portkey.ai/v1/messages \ + -H "Content-Type: application/json" \ + -H "x-portkey-api-key: $PORTKEY_API_KEY" \ + -H "x-portkey-provider: claude-platform-aws" \ + -d '{ + "model": "@claude-platform-aws-provider/claude-sonnet-4-6", + "max_tokens": 1024, + "messages": [ + { "role": "user", "content": "Hello, Claude" } + ] + }' +``` + + +All Portkey features (caching, observability, configs) work with the `/messages` route. Add `x-portkey-config`, `x-portkey-provider`, and other Portkey headers as needed. + + +## Extended Thinking + +Models like `claude-opus-4-7` and `claude-sonnet-4-6` support [extended thinking](https://docs.anthropic.com/en/docs/build-with-claude/extended-thinking). Set `strict_open_ai_compliance=False` to use this feature: + + +```python Python icon="python" +from portkey_ai import Portkey + +portkey = Portkey( + api_key="PORTKEY_API_KEY", + strict_open_ai_compliance=False +) + +response = portkey.chat.completions.create( + model="@claude-platform-aws-provider/claude-opus-4-7", + max_tokens=16000, + thinking={"type": "enabled", "budget_tokens": 10000}, + messages=[{ + "role": "user", + "content": "Solve this step by step: If a train travels 120km in 2 hours, and another travels 200km in 3 hours, which is faster and by how much?" + }] +) + +print(response) +``` + +```js Javascript icon="square-js" +import Portkey from 'portkey-ai' + +const portkey = new Portkey({ + apiKey: "PORTKEY_API_KEY", + strictOpenAiCompliance: false +}) + +const response = await portkey.chat.completions.create({ + model: "@claude-platform-aws-provider/claude-opus-4-7", + max_tokens: 16000, + thinking: { type: "enabled", budget_tokens: 10000 }, + messages: [{ + role: "user", + content: "Solve this step by step: If a train travels 120km in 2 hours, and another travels 200km in 3 hours, which is faster and by how much?" + }] +}) + +console.log(response) +``` + + + +The thinking response is returned in `response.choices[0].delta.content_blocks`, not `response.choices[0].message.content`. + + +## Supported Models + +| Model | Model ID | +|---|---| +| Claude Opus 4.7 | `claude-opus-4-7` | +| Claude Opus 4.6 | `claude-opus-4-6` | +| Claude Sonnet 4.6 | `claude-sonnet-4-6` | +| Claude Opus 4.5 | `claude-opus-4-5` | +| Claude Sonnet 4.5 | `claude-sonnet-4-5` | +| Claude Haiku 4.5 | `claude-haiku-4-5` | + +Model IDs are identical to the first-party Anthropic API -- no Bedrock-style `anthropic.claude-*` prefixes. + +Dated aliases (e.g., `claude-sonnet-4-5-20250929`, `claude-opus-4-5-20251101`) are also supported. + +## Key Differences from First-Party Anthropic + +| Aspect | First-Party Anthropic | Claude Platform on AWS | +|---|---|---| +| Base URL | `api.anthropic.com` | `aws-external-anthropic.{region}.api.aws` | +| Authentication | API key (`x-api-key`) | AWS SigV4 or AWS-managed API key | +| Billing | Anthropic directly | AWS Marketplace | +| Required headers | `anthropic-version`, `x-api-key` | `anthropic-version`, `anthropic-workspace-id` + SigV4 | +| Rate limits | Automatic tier advancement | Contact Anthropic representative | +| Console access | Direct login | Federated through AWS IAM | +| OAuth | Supported | Not supported | +| OpenAI-compatible endpoints | Available | Not available | +| Webhooks | Available | Not available | + + +Portkey handles all authentication and header translation automatically. From the Portkey SDK, the experience is identical to using first-party Anthropic -- just use a different provider slug. + + +## Making Requests Without Model Catalog + +Pass AWS credentials directly via headers: + +```sh cURL icon="square-terminal" +curl https://api.portkey.ai/v1/chat/completions \ + -H "Content-Type: application/json" \ + -H "x-portkey-api-key: $PORTKEY_API_KEY" \ + -H "x-portkey-provider: claude-platform-aws" \ + -H "x-portkey-aws-access-key-id: $AWS_ACCESS_KEY_ID" \ + -H "x-portkey-aws-secret-access-key: $AWS_SECRET_ACCESS_KEY" \ + -H "x-portkey-aws-region: us-west-2" \ + -H "x-portkey-anthropic-aws-workspace-id: wrkspc_01AbCdEf23GhIj" \ + -d '{ + "model": "claude-sonnet-4-6", + "messages": [{ "role": "user", "content": "Hello" }], + "max_tokens": 250 + }' +``` + +| Header | Description | +|---|---| +| `x-portkey-aws-access-key-id` | AWS access key ID | +| `x-portkey-aws-secret-access-key` | AWS secret access key | +| `x-portkey-aws-session-token` | AWS session token (for STS) | +| `x-portkey-aws-region` | AWS region (e.g., `us-west-2`) | +| `x-portkey-anthropic-aws-workspace-id` | Anthropic workspace ID (optional) | + +## Next Steps + + + + Upload, list, retrieve, and delete files + + + Run large async jobs at 50% lower cost + + + Step-by-step IAM role and trust policy setup + + + Shared features: prompt caching, structured outputs, vision + + + + + + Add gateway configs to your requests + + + Trace and monitor your requests + + diff --git a/integrations/llms/claude-platform-aws/files.mdx b/integrations/llms/claude-platform-aws/files.mdx new file mode 100644 index 00000000..d6c02e98 --- /dev/null +++ b/integrations/llms/claude-platform-aws/files.mdx @@ -0,0 +1,429 @@ +--- +title: Files +description: Upload and manage files with Claude Platform on AWS through Portkey +--- + +Portkey supports Anthropic's [Files API](https://docs.anthropic.com/en/docs/build-with-claude/files) (beta) for Claude Platform on AWS, enabling file upload, listing, retrieval, and deletion through the gateway. Uploaded files can be referenced in chat completions using `file_id` instead of re-uploading content each request. + + +The Files API is in beta and requires the `files-api-2025-04-14` beta header. Portkey sets this automatically for file endpoints when using the SDK. For cURL requests, include the `anthropic-beta: files-api-2025-04-14` header. + + +## Upload a file + + + +```python +from portkey_ai import Portkey + +portkey = Portkey( + api_key="PORTKEY_API_KEY", + provider="@claude-platform-aws-provider" +) + +file = portkey.files.create( + purpose="assistants", + file=open("document.pdf", "rb") +) + +print(file.id) +``` + + +```js +import Portkey from 'portkey-ai'; +import fs from 'fs'; + +const portkey = new Portkey({ + apiKey: "PORTKEY_API_KEY", + provider: "@claude-platform-aws-provider" +}); + +const file = await portkey.files.create({ + purpose: "assistants", + file: fs.createReadStream("document.pdf") +}); + +console.log(file.id); +``` + + +```sh +curl -X POST https://api.portkey.ai/v1/files \ + -H "x-portkey-api-key: $PORTKEY_API_KEY" \ + -H "x-portkey-provider: @claude-platform-aws-provider" \ + -H "anthropic-beta: files-api-2025-04-14" \ + -F 'file=@"document.pdf"' +``` + + +```python +from openai import OpenAI +from portkey_ai import PORTKEY_GATEWAY_URL, createHeaders + +client = OpenAI( + api_key="PORTKEY_API_KEY", + base_url=PORTKEY_GATEWAY_URL, + default_headers=createHeaders( + provider="@claude-platform-aws-provider", + api_key="PORTKEY_API_KEY" + ) +) + +file = client.files.create( + purpose="assistants", + file=open("document.pdf", "rb") +) + +print(file.id) +``` + + +```js +import OpenAI from 'openai'; +import { PORTKEY_GATEWAY_URL, createHeaders } from 'portkey-ai'; +import fs from 'fs'; + +const client = new OpenAI({ + apiKey: "PORTKEY_API_KEY", + baseURL: PORTKEY_GATEWAY_URL, + defaultHeaders: createHeaders({ + provider: "@claude-platform-aws-provider", + apiKey: "PORTKEY_API_KEY" + }) +}); + +const file = await client.files.create({ + purpose: "assistants", + file: fs.createReadStream("document.pdf") +}); + +console.log(file.id); +``` + + + +## Use uploaded files in chat completions + +Once a file is uploaded, reference it by `file_id` in chat completions: + + + +```python +from portkey_ai import Portkey + +portkey = Portkey(api_key="PORTKEY_API_KEY") + +response = portkey.chat.completions.create( + model="@claude-platform-aws-provider/claude-sonnet-4-6", + max_tokens=1024, + messages=[{ + "role": "user", + "content": [ + {"type": "text", "text": "Please summarize this document."}, + {"type": "file", "file": {"file_id": "", "mime_type": "application/pdf"}} + ] + }] +) + +print(response.choices[0].message.content) +``` + + +```js +import Portkey from 'portkey-ai'; + +const portkey = new Portkey({ + apiKey: "PORTKEY_API_KEY" +}); + +const response = await portkey.chat.completions.create({ + model: "@claude-platform-aws-provider/claude-sonnet-4-6", + max_tokens: 1024, + messages: [{ + role: "user", + content: [ + { type: "text", text: "Please summarize this document." }, + { type: "file", file: { file_id: "", mime_type: "application/pdf" } } + ] + }] +}); + +console.log(response.choices[0].message.content); +``` + + +```sh +curl -X POST https://api.portkey.ai/v1/chat/completions \ + -H "x-portkey-api-key: $PORTKEY_API_KEY" \ + -H "anthropic-beta: files-api-2025-04-14" \ + -H "Content-Type: application/json" \ + -d '{ + "model": "@claude-platform-aws-provider/claude-sonnet-4-6", + "max_tokens": 1024, + "messages": [ + { + "role": "user", + "content": [ + {"type": "text", "text": "Please summarize this document."}, + {"type": "file", "file": {"file_id": "", "mime_type": "application/pdf"}} + ] + } + ] + }' +``` + + + + +When using the SDK, the `anthropic-beta` header is set automatically for file endpoints. For chat completions with file references via cURL, include `anthropic-beta: files-api-2025-04-14` in your request headers. + + +## List files + + + +```python +from portkey_ai import Portkey + +portkey = Portkey( + api_key="PORTKEY_API_KEY", + provider="@claude-platform-aws-provider" +) + +files = portkey.files.list() + +print(files) +``` + + +```js +import Portkey from 'portkey-ai'; + +const portkey = new Portkey({ + apiKey: "PORTKEY_API_KEY", + provider: "@claude-platform-aws-provider" +}); + +const files = await portkey.files.list(); + +console.log(files); +``` + + +```sh +curl https://api.portkey.ai/v1/files \ + -H "x-portkey-api-key: $PORTKEY_API_KEY" \ + -H "x-portkey-provider: @claude-platform-aws-provider" \ + -H "anthropic-beta: files-api-2025-04-14" +``` + + +```python +from openai import OpenAI +from portkey_ai import PORTKEY_GATEWAY_URL, createHeaders + +client = OpenAI( + api_key="PORTKEY_API_KEY", + base_url=PORTKEY_GATEWAY_URL, + default_headers=createHeaders( + provider="@claude-platform-aws-provider", + api_key="PORTKEY_API_KEY" + ) +) + +files = client.files.list() + +print(files) +``` + + +```js +import OpenAI from 'openai'; +import { PORTKEY_GATEWAY_URL, createHeaders } from 'portkey-ai'; + +const client = new OpenAI({ + apiKey: "PORTKEY_API_KEY", + baseURL: PORTKEY_GATEWAY_URL, + defaultHeaders: createHeaders({ + provider: "@claude-platform-aws-provider", + apiKey: "PORTKEY_API_KEY" + }) +}); + +const files = await client.files.list(); + +console.log(files); +``` + + + +## Get file + + + +```python +from portkey_ai import Portkey + +portkey = Portkey( + api_key="PORTKEY_API_KEY", + provider="@claude-platform-aws-provider" +) + +file = portkey.files.retrieve(file_id="") + +print(file) +``` + + +```js +import Portkey from 'portkey-ai'; + +const portkey = new Portkey({ + apiKey: "PORTKEY_API_KEY", + provider: "@claude-platform-aws-provider" +}); + +const file = await portkey.files.retrieve(""); + +console.log(file); +``` + + +```sh +curl https://api.portkey.ai/v1/files/ \ + -H "x-portkey-api-key: $PORTKEY_API_KEY" \ + -H "x-portkey-provider: @claude-platform-aws-provider" \ + -H "anthropic-beta: files-api-2025-04-14" +``` + + +```python +from openai import OpenAI +from portkey_ai import PORTKEY_GATEWAY_URL, createHeaders + +client = OpenAI( + api_key="PORTKEY_API_KEY", + base_url=PORTKEY_GATEWAY_URL, + default_headers=createHeaders( + provider="@claude-platform-aws-provider", + api_key="PORTKEY_API_KEY" + ) +) + +file = client.files.retrieve("") + +print(file) +``` + + +```js +import OpenAI from 'openai'; +import { PORTKEY_GATEWAY_URL, createHeaders } from 'portkey-ai'; + +const client = new OpenAI({ + apiKey: "PORTKEY_API_KEY", + baseURL: PORTKEY_GATEWAY_URL, + defaultHeaders: createHeaders({ + provider: "@claude-platform-aws-provider", + apiKey: "PORTKEY_API_KEY" + }) +}); + +const file = await client.files.retrieve(""); + +console.log(file); +``` + + + +## Delete file + + + +```python +from portkey_ai import Portkey + +portkey = Portkey( + api_key="PORTKEY_API_KEY", + provider="@claude-platform-aws-provider" +) + +response = portkey.files.delete(file_id="") + +print(response) +``` + + +```js +import Portkey from 'portkey-ai'; + +const portkey = new Portkey({ + apiKey: "PORTKEY_API_KEY", + provider: "@claude-platform-aws-provider" +}); + +const response = await portkey.files.delete(""); + +console.log(response); +``` + + +```sh +curl -X DELETE https://api.portkey.ai/v1/files/ \ + -H "x-portkey-api-key: $PORTKEY_API_KEY" \ + -H "x-portkey-provider: @claude-platform-aws-provider" \ + -H "anthropic-beta: files-api-2025-04-14" +``` + + +```python +from openai import OpenAI +from portkey_ai import PORTKEY_GATEWAY_URL, createHeaders + +client = OpenAI( + api_key="PORTKEY_API_KEY", + base_url=PORTKEY_GATEWAY_URL, + default_headers=createHeaders( + provider="@claude-platform-aws-provider", + api_key="PORTKEY_API_KEY" + ) +) + +response = client.files.delete("") + +print(response) +``` + + +```js +import OpenAI from 'openai'; +import { PORTKEY_GATEWAY_URL, createHeaders } from 'portkey-ai'; + +const client = new OpenAI({ + apiKey: "PORTKEY_API_KEY", + baseURL: PORTKEY_GATEWAY_URL, + defaultHeaders: createHeaders({ + provider: "@claude-platform-aws-provider", + apiKey: "PORTKEY_API_KEY" + }) +}); + +const response = await client.files.delete(""); + +console.log(response); +``` + + + +## Supported file types + +| Type | MIME types | +|------|-----------| +| PDF | `application/pdf` | +| Images | `image/jpeg`, `image/png`, `image/gif`, `image/webp` | + +## See Also + +- [Claude Platform on AWS integration overview](/integrations/llms/claude-platform-aws/claude-platform-aws) +- [Anthropic Files API documentation](https://docs.anthropic.com/en/docs/build-with-claude/files) diff --git a/integrations/llms/claude-platform-aws/setup-assumed-role.mdx b/integrations/llms/claude-platform-aws/setup-assumed-role.mdx new file mode 100644 index 00000000..df7b8df5 --- /dev/null +++ b/integrations/llms/claude-platform-aws/setup-assumed-role.mdx @@ -0,0 +1,196 @@ +--- +title: "Setup Assumed Role for Claude Platform on AWS" +description: "Configure AWS IAM assumed role authentication for Claude Platform on AWS on Portkey" +--- + + + On the Enterprise plan? See the Helm documentation for assumed role setup in self-hosted deployments. + + +## Enable Outbound Web Identity Federation + + +This is a one-time setup step for your AWS account. Without it, all Claude Platform on AWS requests fail with `"Outbound web identity federation is disabled for your account"`. + +```bash +aws iam enable-outbound-web-identity-federation +``` + + +## Select Assumed Role Authentication + +Create a new integration on Portkey: + +1. Go to [**Model Catalog → Add Provider**](https://app.portkey.ai/model-catalog/providers) +2. Select **Claude Platform on AWS** +3. Choose **AWS Assumed Role** as the authentication method + +## Create an IAM Permission Policy + +Create a permission policy in your AWS account. Claude Platform on AWS uses the `aws-external-anthropic` IAM namespace (not `bedrock`). + +### Inference-only policy + +For workloads that only need chat completions and token counting: + +```json +{ + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "ClaudePlatformInference", + "Effect": "Allow", + "Action": [ + "aws-external-anthropic:CreateInference", + "aws-external-anthropic:CountTokens" + ], + "Resource": "arn:aws:aws-external-anthropic:*:*:workspace/*" + } + ] +} +``` + +### Full access policy + +For workloads that also need batch processing and file management: + +```json +{ + "Version": "2012-10-17", + "Statement": [ + { + "Sid": "ClaudePlatformFullAccess", + "Effect": "Allow", + "Action": [ + "aws-external-anthropic:CreateInference", + "aws-external-anthropic:CountTokens", + "aws-external-anthropic:CreateBatchInference", + "aws-external-anthropic:GetBatchInference", + "aws-external-anthropic:ListBatchInferences", + "aws-external-anthropic:CancelBatchInference", + "aws-external-anthropic:DeleteBatchInference", + "aws-external-anthropic:CreateFile", + "aws-external-anthropic:GetFile", + "aws-external-anthropic:ListFiles", + "aws-external-anthropic:DeleteFile" + ], + "Resource": "arn:aws:aws-external-anthropic:*:*:workspace/*" + } + ] +} +``` + + +To restrict access to a specific workspace and region, replace the `Resource` with: + +``` +arn:aws:aws-external-anthropic:us-west-2:123456789012:workspace/wrkspc_01AbCdEf23GhIj +``` + + +Alternatively, attach one of the AWS-managed policies: + +| Managed Policy | Scope | +|---|---| +| `AnthropicFullAccess` | All `aws-external-anthropic:*` actions | +| `AnthropicInferenceAccess` | Inference + read-only actions | +| `AnthropicReadOnlyAccess` | `Get*`, `List*`, `CallWithBearerToken` | + +## Create an IAM Role + +1. Open the [IAM Console](https://console.aws.amazon.com/iam/) and go to **Roles → Create role** +2. Choose **AWS account** as the trusted entity type +3. Optionally set an **external ID** -- copy it for later +4. Attach the permission policy created above +5. Name the role (e.g., `portkey-claude-platform-role`) and create it + +## Configure the Trust Relationship + +Open the role, navigate to the **Trust relationships** tab, and click **Edit trust policy**. + +Add Portkey's AWS account as a trusted principal: + +```sh Portkey Account ARN +arn:aws:iam::299329113195:role/portkey-app +``` + + +This ARN is for the [hosted Portkey app](https://app.portkey.ai/). For enterprise self-hosted deployments, refer to the [Helm documentation](https://github.com/Portkey-AI/helm/blob/main/charts/portkey-gateway/docs/Bedrock.md). + + +### Trust policy without external ID + +```json +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": { + "AWS": "arn:aws:iam::299329113195:role/portkey-app" + }, + "Action": "sts:AssumeRole", + "Condition": {} + } + ] +} +``` + +### Trust policy with external ID + +```json +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": { + "AWS": "arn:aws:iam::299329113195:role/portkey-app" + }, + "Action": "sts:AssumeRole", + "Condition": { + "StringEquals": { + "sts:ExternalId": "" + } + } + } + ] +} +``` + +## Configure the Integration + +Back in Portkey, enter the following in the Claude Platform on AWS integration modal: + +| Field | Value | +|---|---| +| **Role ARN** | The ARN of the role you created (e.g., `arn:aws:iam::123456789012:role/portkey-claude-platform-role`) | +| **External ID** | The external ID you set (if any) | +| **AWS Region** | The region for your workspace (e.g., `us-west-2`) | +| **Anthropic Workspace ID** | Your workspace ID (optional, format: `wrkspc_01AbCdEf23GhIj`) | + +Save the integration. Portkey will assume the IAM role and sign requests with SigV4 using the `aws-external-anthropic` service name. + +## Verify the Setup + +Test the integration with a simple request: + +```sh cURL icon="square-terminal" +curl https://api.portkey.ai/v1/chat/completions \ + -H "Content-Type: application/json" \ + -H "x-portkey-api-key: $PORTKEY_API_KEY" \ + -d '{ + "model": "@claude-platform-aws-provider/claude-sonnet-4-6", + "messages": [{ "role": "user", "content": "Hello" }], + "max_tokens": 100 + }' +``` + +## Troubleshooting + +| Error | Cause | Fix | +|---|---|---| +| `Outbound web identity federation is disabled` | Federation not enabled on the AWS account | Run `aws iam enable-outbound-web-identity-federation` | +| `Access denied` / `not authorized to perform` | Missing IAM permissions | Verify the permission policy includes the required `aws-external-anthropic:*` actions | +| `Invalid signature` | Incorrect region or credentials | Confirm the region matches your workspace and the role ARN is correct | +| `Trust policy error` | Portkey ARN not in trust policy | Add `arn:aws:iam::299329113195:role/portkey-app` as a trusted principal |