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

# Spring AI

> Trace Spring AI calls in Braintrust to debug prompts, evaluate models, and monitor production usage

[Spring AI](https://spring.io/projects/spring-ai) is a framework for building AI applications in Java. Braintrust traces chat calls made to OpenAI and Anthropic through Spring AI.

<View title="Java" icon="https://img.logo.dev/java.com?token=pk_BdcHD9e5SCW3j1rnJkNyMQ">
  <h2 id="tracing-java">
    Tracing
  </h2>

  To trace Spring AI with Braintrust's Java SDK, use auto-instrumentation or manual instrumentation. Auto-instrumentation is the recommended path for most users.

  <Tabs>
    <Tab title="Auto-instrumentation">
      The Braintrust Java agent instruments Spring AI chat models at JVM startup, so no changes to your application code are required.

      <h3 id="setup-java-auto">
        Setup
      </h3>

      Install the Braintrust Java SDK alongside the Spring AI module for each provider you use, then configure your API keys.

      <Note>
        Braintrust instruments Spring AI 1.0.0 to 2.0.0 and requires Java 17 or later. Calls made with an unsupported Spring AI version still run, but produce no spans.
      </Note>

      <Steps>
        <Step title="Install packages">
          ```bash theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
          # add to build.gradle dependencies{} block
          implementation 'dev.braintrust:braintrust-sdk-java:<version-goes-here>'

          # add the Spring AI module for each provider you use
          implementation 'org.springframework.ai:spring-ai-openai:<version-goes-here>'
          implementation 'org.springframework.ai:spring-ai-anthropic:<version-goes-here>'
          ```
        </Step>

        <Step title="Set environment variables">
          ```bash title=".env" theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
          OPENAI_API_KEY=<your-openai-api-key>
          ANTHROPIC_API_KEY=<your-anthropic-api-key>
          BRAINTRUST_API_KEY=<your-braintrust-api-key>

          # For organizations on the EU data plane, use https://api-eu.braintrust.dev
          # For self-hosted deployments, use your data plane URL
          # BRAINTRUST_API_URL=<your-braintrust-api-url>
          ```
        </Step>
      </Steps>

      <h3 id="trace-java-auto">
        Trace your application
      </h3>

      To trace Spring AI calls without modifying your application code, attach the [`braintrust-java-agent`](/docs/instrument/trace-llm-calls#auto-instrumentation) at JVM startup. The agent intercepts every Spring AI chat model build and applies Braintrust instrumentation automatically.

      <Steps>
        <Step title="Add the agent dependency">
          The agent is a separate artifact from the SDK. Add it as its own dependency configuration:

          ```bash theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
          # build.gradle
          configurations {
              braintrustAgent
          }

          dependencies {
              braintrustAgent 'dev.braintrust:braintrust-java-agent:+'
          }

          tasks.withType(JavaExec).configureEach {
              jvmArgs "-javaagent:${configurations.braintrustAgent.asPath}"
          }
          ```
        </Step>

        <Step title="Run your app">
          ```bash theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
          ./gradlew run
          ```

          Spring AI chat model builds in your application code are now intercepted automatically. No call to `BraintrustSpringAI.wrap()` is required. For Spring Boot, use `./gradlew bootRun` instead.
        </Step>
      </Steps>

      <h3 id="what-traced-java-auto">
        What Braintrust traces
      </h3>

      Braintrust traces each Spring AI chat model call that routes to a supported provider backend. Spring AI 2.x delegates HTTP to the official OpenAI and Anthropic Java SDKs, so spans carry the same fields as those integrations.

      Braintrust captures:

      * Chat model call spans for `OpenAiChatModel` (OpenAI backend) and `AnthropicChatModel` (Anthropic backend), with the request messages, model, and parameters.
      * Response content for each call.
      * Token usage metrics, including prompt and completion tokens.

      <h3 id="tracing-resources-java-auto">
        Tracing resources
      </h3>

      * [Braintrust Java SDK](https://github.com/braintrustdata/braintrust-sdk-java)
      * [Spring AI reference](https://docs.spring.io/spring-ai/reference/)
    </Tab>

    <Tab title="Manual instrumentation">
      To trace Spring AI calls yourself, wrap a built chat model with `BraintrustSpringAI.wrap()`. Once wrapped, every `call()` on that model emits a span.

      <h3 id="setup-java-manual">
        Setup
      </h3>

      Install the Braintrust Java SDK alongside the Spring AI module for each provider you use, then configure your API keys.

      <Note>
        Braintrust instruments Spring AI 1.0.0 to 2.0.0 and requires Java 17 or later. Calls made with an unsupported Spring AI version still run, but produce no spans.
      </Note>

      <Steps>
        <Step title="Install packages">
          ```bash theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
          # add to build.gradle dependencies{} block
          implementation 'dev.braintrust:braintrust-sdk-java:<version-goes-here>'

          # add the Spring AI module for each provider you use
          implementation 'org.springframework.ai:spring-ai-openai:<version-goes-here>'
          implementation 'org.springframework.ai:spring-ai-anthropic:<version-goes-here>'
          ```
        </Step>

        <Step title="Set environment variables">
          ```bash title=".env" theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
          OPENAI_API_KEY=<your-openai-api-key>
          ANTHROPIC_API_KEY=<your-anthropic-api-key>
          BRAINTRUST_API_KEY=<your-braintrust-api-key>

          # For organizations on the EU data plane, use https://api-eu.braintrust.dev
          # For self-hosted deployments, use your data plane URL
          # BRAINTRUST_API_URL=<your-braintrust-api-url>
          ```
        </Step>
      </Steps>

      <h3 id="trace-java-manual">
        Trace your application
      </h3>

      To trace Spring AI calls manually, build your chat model as usual, then wrap it with `BraintrustSpringAI.wrap()`, which instruments the model in place and returns it so every `call()` emits a span.

      <CodeGroup>
        ```java Java #skip-compile theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
        import dev.braintrust.Braintrust;
        import dev.braintrust.instrumentation.springai.v2_0_0.BraintrustSpringAI;
        import io.opentelemetry.api.OpenTelemetry;
        import org.springframework.ai.chat.prompt.Prompt;
        import org.springframework.ai.openai.OpenAiChatModel;
        import org.springframework.ai.openai.OpenAiChatOptions;

        class SpringAITracing {
            public static void main(String[] args) {
                var braintrust = Braintrust.get();
                OpenTelemetry openTelemetry = braintrust.openTelemetryCreate();

                // Build your Spring AI chat model as usual
                var chatModel = OpenAiChatModel.builder()
                    .options(OpenAiChatOptions.builder()
                        .apiKey(System.getenv("OPENAI_API_KEY"))
                        .model("gpt-5-mini")
                        .build())
                    .build();

                // Instrument the chat model in place
                var model = BraintrustSpringAI.wrap(openTelemetry, chatModel);

                // Every call() is now traced
                var response = model.call(new Prompt("What is machine learning?"));
            }
        }
        ```
      </CodeGroup>

      `AnthropicChatModel` is instrumented the same way: build it, then pass it to `BraintrustSpringAI.wrap()`.

      <Note>
        Spring AI 2.x builds its provider client inside `build()`, so you wrap the finished chat model. For Spring AI 1.x, import `dev.braintrust.instrumentation.springai.v1_0_0.BraintrustSpringAI` and wrap the builder before calling `.build()` instead.
      </Note>

      <Note>
        Async and streaming calls are traced, and each LLM span is parented to the caller's active span even when the request runs on a different thread. `BraintrustSpringAI.wrap()` is idempotent and returns the same model instance. Only `OpenAiChatModel` and `AnthropicChatModel` are instrumented; other Spring AI chat models are logged and skipped.
      </Note>

      <h3 id="what-traced-java-manual">
        What Braintrust traces
      </h3>

      Braintrust traces each Spring AI chat model call that routes to a supported provider backend. Spring AI 2.x delegates HTTP to the official OpenAI and Anthropic Java SDKs, so spans carry the same fields as those integrations.

      Braintrust captures:

      * Chat model call spans for `OpenAiChatModel` (OpenAI backend) and `AnthropicChatModel` (Anthropic backend), with the request messages, model, and parameters.
      * Response content for each call.
      * Token usage metrics, including prompt and completion tokens.

      <h3 id="tracing-resources-java-manual">
        Tracing resources
      </h3>

      * [Braintrust Java SDK](https://github.com/braintrustdata/braintrust-sdk-java)
      * [Spring AI reference](https://docs.spring.io/spring-ai/reference/)
    </Tab>
  </Tabs>
</View>
