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

# Arconia

> Trace Arconia + Spring AI Spring Boot apps with OpenInference and send spans to Arize AX for LLM observability.

[Arconia](https://www.arconia.io/) is a third-party Spring Boot starter suite that bundles OpenTelemetry, OpenInference, and Spring AI auto-configuration into a single dependency. Arize AX captures every Spring AI call routed through Arconia's OTel pipeline by configuring the OTLP exporter to point at Arize — no manual instrumentor wiring required.

## Prerequisites

* Java 17+ (Spring Boot 4 requires 17; this guide is tested against Java 21)
* An Arize AX account ([sign up](https://arize.com/sign-up/))
* An `OPENAI_API_KEY` from the [OpenAI Platform](https://platform.openai.com/api-keys)

## Launch Arize

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

Add the dependencies to `build.gradle`. The OpenInference work is auto-configured by the Arconia starter — you don't import any `com.arize:*` artifacts directly. The only OpenTelemetry artifact you have to wire explicitly is the **OTLP gRPC sender provider**, since Arize uses gRPC OTLP and Spring Boot's default sender is HTTP-only:

```groovy theme={null}
plugins {
    id 'java'
    id 'org.springframework.boot' version '4.0.6'
    id 'io.spring.dependency-management' version '1.1.7'
}

java {
    toolchain { languageVersion = JavaLanguageVersion.of(21) }
}

repositories {
    mavenCentral()
}

dependencies {
    // Arconia: OTel auto-config + OpenInference semantic conventions
    implementation 'io.arconia:arconia-openinference-ai-semantic-conventions'
    implementation 'io.arconia:arconia-opentelemetry-spring-boot-starter'

    // Spring Boot Web + Spring AI OpenAI provider
    implementation 'org.springframework.boot:spring-boot-starter-webmvc'
    implementation 'org.springframework.ai:spring-ai-starter-model-openai'

    // gRPC sender for the OTLP exporter — version pinned to match
    // the OpenTelemetry SDK that Arconia / Spring Boot resolves.
    implementation(
        'io.opentelemetry:opentelemetry-exporter-sender-okhttp:1.61.0')
}

dependencyManagement {
    imports {
        mavenBom "io.arconia:arconia-bom:0.27.0"
        mavenBom "org.springframework.ai:spring-ai-bom:2.0.0-M5"
    }
}
```

## Configure credentials

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

## Setup tracing

Arconia is configuration-first — there is no `instrumentation.java` to write. Configure Spring AI to use OpenAI and Arconia's OTel exporter to ship traces to Arize, all in `src/main/resources/application.yml`:

```yaml theme={null}
spring:
  ai:
    openai:
      api-key: ${OPENAI_API_KEY}
      chat:
        options:
          model: gpt-5

arconia:
  observations:
    conventions:
      openinference:
        ai:
          # Arconia's OpenInference auto-config turns this into the
          # `openinference.project.name` resource attribute Arize uses
          # to route the trace into a project.
          project-name: ${ARIZE_PROJECT_NAME}
  otel:
    # We only want traces in Arize. Disable logs + metrics export so
    # Arconia's auto-config doesn't try to wire OTLP for those signals
    # at their default localhost endpoints.
    logs:
      enabled: false
    metrics:
      enabled: false
    traces:
      exporter:
        type: otlp
        otlp:
          endpoint: https://otlp.arize.com:443
          protocol: grpc
          headers:
            authorization: ${ARIZE_API_KEY}
            arize-space-id: ${ARIZE_SPACE_ID}
            arize-interface: java
    resource:
      attributes:
        service.name: arconia-tracing-example
```

The Spring Boot app itself stays minimal — Arconia + Spring AI handle everything else. A `ChatController` exposes `/chat?question=...`:

```java theme={null}
// src/main/java/example/Application.java
package example;

import org.springframework.ai.chat.client.ChatClient;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

@RestController
class ChatController {
    private final ChatClient chatClient;

    ChatController(ChatClient.Builder builder) {
        this.chatClient = builder.clone().build();
    }

    @GetMapping("/chat")
    String chat(@RequestParam("question") String question) {
        return chatClient.prompt(question).call().content();
    }
}
```

## Run Arconia

```bash theme={null}
gradle bootRun
```

In another terminal, drive the agent:

```bash theme={null}
curl "http://localhost:8080/chat?question=\
Why+is+the+ocean+salty%3F+Answer+in+two+sentences."
```

### Expected output

```text wrap theme={null}
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

1. Open your Arize AX space and select project **`arconia-tracing-example`**.
2. You should see a new trace within \~30–60 seconds containing an `http get /chat` root span wrapping a `spring_ai chat_client` AGENT span, a `call` CHAIN span, and a `chat gpt-5` LLM span (model = the dated stamp the OpenAI API returns, e.g. `gpt-5-2025-08-07`, with prompt, response, and token usage attributes attached).
3. If no traces appear, see [Troubleshooting](#troubleshooting).

## Troubleshooting

* **`No GrpcSenderProvider found on classpath`.** Add `io.opentelemetry:opentelemetry-exporter-sender-okhttp` (or `opentelemetry-exporter-sender-grpc-managed-channel`) to your dependencies. The version must align with the OpenTelemetry SDK that Spring Boot / Arconia resolves — `gradle dependencies --configuration runtimeClasspath | grep opentelemetry-sdk` shows the version to pin against.
* **`Requested protocol HTTP_PROTOBUF doesn't match configured protocol GRPC`.** Arconia auto-configures OTLP for *all three* signals (traces, logs, metrics) and they must agree on protocol. The `arconia.otel.logs.enabled: false` + `arconia.otel.metrics.enabled: false` lines in `application.yml` above disable the unused signals so this conflict can't happen.
* **No traces in Arize.** Confirm `ARIZE_SPACE_ID` and `ARIZE_API_KEY` are set in the same shell that runs `gradle bootRun`. The Spring Boot app captures the environment at process start; setting env vars after the server is running has no effect.
* **`401` from OpenAI.** Verify `OPENAI_API_KEY` is set and has access to `gpt-5`. Swap `spring.ai.openai.chat.options.model` in `application.yml` for a model your key can call.
* **Want logs and metrics too.** Drop the `logs.enabled: false` + `metrics.enabled: false` lines and the auto-config will export those signals against the same OTLP endpoint. Arize ingests the trace stream; the logs/metrics streams are silently accepted but not surfaced in the UI.

## Resources

<CardGroup>
  <Card icon="book-open" href="https://docs.arconia.io/arconia/latest/" title="Arconia Documentation" horizontal />

  <Card icon="book-open" href="https://docs.spring.io/spring-ai/reference/" title="Spring AI Documentation" horizontal />

  <Card icon="github" href="https://github.com/arconia-io/arconia" title="Arconia GitHub" horizontal />

  <Card icon="github" href="https://github.com/arconia-io/arconia-examples/tree/main/arconia-openinference" title="Arconia OpenInference Example" horizontal />
</CardGroup>
