> ## Documentation Index
> Fetch the complete documentation index at: https://arize-ax.mintlify.site/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Amazon Bedrock

> Trace AWS Bedrock invoke_model and converse calls in Python and TypeScript with OpenInference and send spans to Arize AX.

[Amazon Bedrock](https://aws.amazon.com/bedrock/) is AWS's managed foundation-model service — Claude, Llama, Mistral, Titan, and others are reachable through a single AWS SDK client. Arize AX captures every Bedrock model call (`invoke_model`, `converse`, `converse_stream`) via the OpenInference instrumentors for [Python](https://github.com/Arize-ai/openinference/tree/main/python/instrumentation/openinference-instrumentation-bedrock) and [JavaScript / TypeScript](https://github.com/Arize-ai/openinference/tree/main/js/packages/openinference-instrumentation-bedrock).

<CardGroup>
  <Card horizontal icon="https://storage.googleapis.com/arize-phoenix-assets/assets/images/phoenix-docs-images/gc.ico" href="https://colab.research.google.com/github/Arize-ai/tutorials/blob/35f5d3557b13188be4addb37baf3aa492b43b9b3/python/llm/tracing/bedrock/bedrock-tracing.ipynb#L23" title="Bedrock Tracing Tutorial (Google Colab)" />
</CardGroup>

## Prerequisites

* Python 3.10+ or Node.js 18+
* An Arize AX account ([sign up](https://arize.com/sign-up/))
* An AWS account with [Bedrock model access enabled](https://docs.aws.amazon.com/bedrock/latest/userguide/model-access.html) for the model you want to call (the example below uses Anthropic Claude Sonnet 4.6 — request access from the Bedrock console under **Model access** if you haven't already)

## Launch Arize AX

1. Sign in to your [Arize AX account](https://app.arize.com/).
2. From **Space Settings**, copy your **Space ID** and **API Key**. You will set them as `ARIZE_SPACE_ID` and `ARIZE_API_KEY` below.

## Install

<CodeGroup>
  ```bash Python theme={null}
  pip install arize-otel openinference-instrumentation-bedrock boto3
  ```

  ```bash TypeScript theme={null}
  npm install @aws-sdk/client-bedrock-runtime \
    @arizeai/openinference-instrumentation-bedrock \
    @arizeai/openinference-semantic-conventions \
    @opentelemetry/api \
    @opentelemetry/exporter-trace-otlp-proto \
    @opentelemetry/instrumentation \
    @opentelemetry/resources \
    @opentelemetry/sdk-trace-base \
    @opentelemetry/sdk-trace-node \
    @opentelemetry/semantic-conventions
  ```
</CodeGroup>

## Configure credentials

```bash theme={null}
export ARIZE_SPACE_ID="<your-space-id>"
export ARIZE_API_KEY="<your-api-key>"
export ARIZE_PROJECT_NAME="amazon-bedrock-tracing-example"

# AWS credentials — long-lived or SSO/STS temporary.
export AWS_ACCESS_KEY_ID="<your-aws-access-key-id>"
export AWS_SECRET_ACCESS_KEY="<your-aws-secret-access-key>"
export AWS_REGION="us-east-1"

# Only required when using SSO / STS / federated logins. Leave unset
# for long-lived IAM user keys.
export AWS_SESSION_TOKEN=""  # optional
```

## Setup tracing

<CodeGroup>
  ```python Python theme={null}
  # instrumentation.py
  import os

  from arize.otel import register
  from openinference.instrumentation.bedrock import BedrockInstrumentor

  tracer_provider = register(
      space_id=os.environ["ARIZE_SPACE_ID"],
      api_key=os.environ["ARIZE_API_KEY"],
      project_name=os.environ["ARIZE_PROJECT_NAME"],
  )

  BedrockInstrumentor().instrument(tracer_provider=tracer_provider)
  print("Arize AX tracing initialized for Amazon Bedrock.")
  ```

  ```typescript TypeScript theme={null}
  // instrumentation.ts
  import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-proto";
  import { registerInstrumentations } from "@opentelemetry/instrumentation";
  import { resourceFromAttributes } from "@opentelemetry/resources";
  import { SimpleSpanProcessor } from "@opentelemetry/sdk-trace-base";
  import { NodeTracerProvider } from "@opentelemetry/sdk-trace-node";
  import { ATTR_SERVICE_NAME } from "@opentelemetry/semantic-conventions";
  import {
    SEMRESATTRS_PROJECT_NAME,
  } from "@arizeai/openinference-semantic-conventions";
  import { createRequire } from "module";

  // The published @arizeai/openinference-instrumentation-bedrock ESM build
  // value-imports type-only names from the AWS SDK, so importing it from an
  // ESM app throws. Load its CommonJS build via createRequire until the fix
  // (https://github.com/Arize-ai/openinference/issues/3393) ships.
  const require = createRequire(import.meta.url);
  const {
    BedrockInstrumentation,
  } = require("@arizeai/openinference-instrumentation-bedrock");

  const projectName =
    process.env.ARIZE_PROJECT_NAME ?? "amazon-bedrock-tracing-example";

  export const provider = new NodeTracerProvider({
    resource: resourceFromAttributes({
      [ATTR_SERVICE_NAME]: projectName,
      [SEMRESATTRS_PROJECT_NAME]: projectName,
    }),
    spanProcessors: [
      new SimpleSpanProcessor(
        new OTLPTraceExporter({
          url: "https://otlp.arize.com/v1/traces",
          headers: {
            "arize-space-id": process.env.ARIZE_SPACE_ID ?? "",
            "arize-api-key": process.env.ARIZE_API_KEY ?? "",
          },
        }),
      ),
    ],
  });

  provider.register();

  registerInstrumentations({
    instrumentations: [new BedrockInstrumentation()],
    tracerProvider: provider,
  });

  console.log("Arize AX tracing initialized for Amazon Bedrock.");
  ```
</CodeGroup>

<Note>
  **TypeScript: load the instrumentor as CommonJS.** The current `@arizeai/openinference-instrumentation-bedrock` **ESM** build value-imports type-only names from the AWS SDK, so a direct `import` throws `does not provide an export named 'ContentBlock'` under ESM / `tsx` ([openinference#3393](https://github.com/Arize-ai/openinference/issues/3393)). The example loads the instrumentor and the AWS SDK through `createRequire` so the working CommonJS build is used and the require-hook auto-instrumentation patches the client. Once the upstream fix ships you can switch to plain `import`.
</Note>

## Run Amazon Bedrock

<CodeGroup>
  ```python Python theme={null}
  # example.py

  # Importing instrumentation first ensures BedrockInstrumentor patches
  # boto3 before the bedrock-runtime client is created.
  from instrumentation import tracer_provider

  import os

  import boto3

  # boto3 reads AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY /
  # AWS_SESSION_TOKEN (optional) / AWS_REGION from the environment.
  client = boto3.client(
      "bedrock-runtime",
      region_name=os.environ.get("AWS_REGION", "us-east-1"),
  )

  # Cross-region inference profile for Claude Sonnet 4.6. The `us.` prefix
  # tells Bedrock to route across US regions automatically. Drop the
  # prefix and use `anthropic.claude-sonnet-4-6` for region-pinned calls.
  response = client.converse(
      modelId="us.anthropic.claude-sonnet-4-6",
      messages=[
          {
              "role": "user",
              "content": [
                  {"text": "Why is the ocean salty? Answer in two sentences."}
              ],
          }
      ],
      inferenceConfig={"maxTokens": 256, "temperature": 0.0},
  )

  print(response["output"]["message"]["content"][0]["text"])
  ```

  ```typescript TypeScript theme={null}
  // example.ts

  // Importing instrumentation first ensures BedrockInstrumentation patches
  // the AWS SDK before the bedrock-runtime client is created.
  import { provider } from "./instrumentation";
  import { createRequire } from "module";

  // Load the AWS SDK via require so the instrumentor's require hook patches
  // it — auto-instrumentation patches CommonJS requires, and it keeps the
  // client on the same module instance the instrumentor patched.
  const require = createRequire(import.meta.url);
  const {
    BedrockRuntimeClient,
    ConverseCommand,
  } = require("@aws-sdk/client-bedrock-runtime");

  // The client reads AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY /
  // AWS_SESSION_TOKEN (optional) / AWS_REGION from the environment.
  const client = new BedrockRuntimeClient({
    region: process.env.AWS_REGION ?? "us-east-1",
  });

  // Cross-region inference profile for Claude Sonnet 4.6. The `us.` prefix
  // tells Bedrock to route across US regions automatically. Drop the
  // prefix and use `anthropic.claude-sonnet-4-6` for region-pinned calls.
  const response = await client.send(
    new ConverseCommand({
      modelId: "us.anthropic.claude-sonnet-4-6",
      messages: [
        {
          role: "user",
          content: [
            { text: "Why is the ocean salty? Answer in two sentences." },
          ],
        },
      ],
      inferenceConfig: { maxTokens: 256, temperature: 0.0 },
    }),
  );

  const text = response.output?.message?.content?.[0]?.text ?? "";
  console.log(text);

  // Flush any pending spans before the process exits.
  await provider.forceFlush();
  ```
</CodeGroup>

### Expected output

```text wrap theme={null}
Arize AX tracing initialized for Amazon Bedrock.
The ocean is salty because rivers continuously dissolve mineral salts from rocks and soil and carry them to the sea, where they accumulate over millions of years. Water leaves the ocean through evaporation but the salts remain, steadily concentrating until reaching today's roughly 3.5% salinity.
```

## Verify in Arize AX

1. Open your Arize AX space and select project **`amazon-bedrock-tracing-example`**.
2. You should see a new trace within \~30 seconds containing a `bedrock.converse` LLM span with the prompt, response, and token usage attached. The span's `llm.model_name` is the model id you called (e.g. `us.anthropic.claude-sonnet-4-6`).
3. If no traces appear, see [Troubleshooting](#troubleshooting).

### Check from the skill, CLI, or SDK

Confirm spans are actually reaching your Arize AX project. Use whichever fits your workflow — the skill and CLI work for any framework; the SDK check is shown for each language.

<Tabs>
  <Tab title="Arize skill (agent)">
    Install the [Arize Skills](https://github.com/Arize-ai/arize-skills) plugin and let your coding agent check for you:

    ```bash theme={null}
    npx skills add Arize-ai/arize-skills
    ```

    Then prompt your agent:

    > Use the `arize-trace` skill to export and analyze recent traces from my project. Confirm spans are arriving, and summarize any errors or latency issues.
  </Tab>

  <Tab title="AX CLI">
    Export recent spans for your project — any rows mean traces are landing:

    ```bash theme={null}
    ax spans export "$ARIZE_PROJECT_NAME" --space "$ARIZE_SPACE_ID" \
      --limit 5 --stdout | jq 'length'
    ```

    A non-zero count confirms spans reached Arize AX. Run `ax auth login` first if you have not authenticated. See the [`ax spans` reference](/docs/api-clients/cli/spans).
  </Tab>

  <Tab title="SDK">
    Query the project's spans and check that at least one came back.

    <CodeGroup>
      ```python Python theme={null}
      import os
      from arize import ArizeClient

      client = ArizeClient(api_key=os.environ["ARIZE_API_KEY"])
      resp = client.spans.list(
          project=os.environ["ARIZE_PROJECT_NAME"],
          space=os.environ["ARIZE_SPACE_ID"],
          limit=5,
      )
      count = len(resp.spans)
      print(
          f"{count} span(s) found" if count else "No spans yet — recheck setup"
      )
      ```

      ```typescript TypeScript theme={null}
      // Reads ARIZE_API_KEY from the environment.
      import { listSpans } from "@arizeai/ax-client";

      const { data: spans } = await listSpans({
        project: process.env.ARIZE_PROJECT_NAME!,
        space: process.env.ARIZE_SPACE_ID!,
        limit: 5,
      });
      const count = spans.length;
      console.log(
        count ? `${count} span(s) found` : "No spans yet — recheck setup",
      );
      ```

      ```go Go theme={null}
      client, err := arize.NewClient(
          arize.Config{APIKey: os.Getenv("ARIZE_API_KEY")},
      )
      if err != nil {
          log.Fatal(err)
      }
      resp, err := client.Spans.List(ctx, spans.ListRequest{
          Project: os.Getenv("ARIZE_PROJECT_NAME"),
          Space:   os.Getenv("ARIZE_SPACE_ID"),
          Limit:   5,
      })
      if err != nil {
          log.Fatal(err)
      }
      fmt.Printf("%d span(s) found\n", len(resp.Spans))
      ```
    </CodeGroup>

    SDK span references: [Python](/docs/api-clients/python/version-8/client-resources/spans) · [TypeScript](/docs/api-clients/typescript/version-1/client-resources/spans) · [Go](/docs/api-clients/go/version-2/client-resources/spans).
  </Tab>
</Tabs>

## Troubleshooting

* **No traces in Arize AX.** Confirm `ARIZE_SPACE_ID` and `ARIZE_API_KEY` are set in the same shell that runs `example.py`. Enable OpenTelemetry debug logs with `export OTEL_LOG_LEVEL=debug` and re-run.
* **Bedrock spans missing but other spans present.** `BedrockInstrumentor().instrument(...)` must run before `boto3.client("bedrock-runtime", ...)` is called. Make sure `instrumentation.py` is the first import in your entry point — `boto3` clients created before instrumentation aren't patched.
* **`AccessDeniedException` / `Could not assume role`.** Your IAM principal doesn't have `bedrock:InvokeModel` permission, or model access isn't enabled for the model id in the example. Enable access in the Bedrock console under **Model access** and confirm your IAM policy grants `bedrock:InvokeModel` on `arn:aws:bedrock:*::foundation-model/*`.
* **`ValidationException: Invocation of model ID anthropic.claude-sonnet-4-6 ... isn't supported`.** Some Claude models on Bedrock are only available through [cross-region inference profiles](https://docs.aws.amazon.com/bedrock/latest/userguide/cross-region-inference.html). Prefix the model id with your geography slug — `us.anthropic.claude-sonnet-4-6` (the example uses this) or `eu.anthropic.claude-sonnet-4-6`.
* **`ExpiredTokenException`.** Your `AWS_SESSION_TOKEN` (SSO / STS temporary credentials) has expired. Re-run the SSO login and re-export the new triple of `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `AWS_SESSION_TOKEN`.
* **Meta Llama spans missing with `invoke_model`.** The instrumentor doesn't currently capture Llama responses via the `invoke_model` API — use `converse` (which the example above already does) for any non-Anthropic model.

## Resources

<CardGroup>
  <Card icon="book-open" href="https://docs.aws.amazon.com/bedrock/" title="Amazon Bedrock Documentation" horizontal />

  <Card icon="terminal" href="https://github.com/Arize-ai/openinference/tree/main/python/instrumentation/openinference-instrumentation-bedrock" title="OpenInference Bedrock Instrumentor (Python)" horizontal />

  <Card icon="terminal" href="https://github.com/Arize-ai/openinference/tree/main/js/packages/openinference-instrumentation-bedrock" title="OpenInference Bedrock Instrumentor (JavaScript / TypeScript)" horizontal />

  <Card icon="github" href="https://github.com/boto/boto3" title="boto3 (AWS SDK for Python)" horizontal />

  <Card icon="code" href="https://github.com/Arize-ai/openinference/tree/main/python/instrumentation/openinference-instrumentation-bedrock/examples" title="Bedrock Examples (Converse, Streaming, Tools, Agents)" horizontal />
</CardGroup>
