# Disable metrics and logs exporters via OpenTelemetry to avoid putting an extra load on the OpenTelemetry collector
otel:
  metrics:
    exporter: none
  logs:
    exporter: none
```

Your Spring AI code will now automatically send traces to Opik:

```java
import io.micrometer.tracing.Span;
import io.micrometer.tracing.Tracer;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.lang.NonNull;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * Service class responsible for handling chat-related operations.
 * Provides functionality to interact with an underlying LLM chat client.
 */
@Service
public class ChatService {

    private static final String TAGS_KEY = "opik.tags";
    private static final String METADATA_PREFIX = "opik.metadata.";

    private final Tracer tracer;
    private final ChatClient chatClient;

    public ChatService(ChatClient.Builder chatClientBuilder, Tracer tracer) {
        this.chatClient = chatClientBuilder.build();
        this.tracer = tracer;
    }

    public String askQuestion(@NonNull String question) {
        return chatClient
                .prompt(new Prompt(question))
                .call()
                .content();
    }

    public String askQuestion(@NonNull String question, List<String> tags, Map<String, String> metadata) {

        Span span = tracer.currentSpan();
        if (Objects.nonNull(span)) {
            setTags(span, tags);
            setMetadata(span, metadata);
        }

        return chatClient
                .prompt(new Prompt(question))
                .call()
                .content();
    }

    private void setTags(@NonNull Span span, List<String> tags) {
        if (!CollectionUtils.isEmpty(tags)) {
            span.tagOfStrings(TAGS_KEY, tags);
        }
    }

    private void setMetadata(@NonNull Span span, Map<String, String> metadata) {
        if ( !CollectionUtils.isEmpty(metadata) ) {
            // populate metadata
            metadata.forEach((String k, String v) ->
                    span.tag(METADATA_PREFIX + k, v));
        }
    }
}
```

## Running the Demo Application

After cloning the [OPIK SpringAI starter](https://github.com/comet-ml/opik-springai-demo) repository,
you can run the demo application using one of the following methods:

### Method 1: Using Maven Spring Boot Plugin

```bash
export OTEL_EXPORTER_OTLP_HEADERS='Comet-Workspace=default,projectName=otel-springai-test' \
export OPENAI_API_KEY=sk-proj-your-api-key \
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:5173/api/v1/private/otel
mvn spring-boot:run
```

### Method 2: Using JAR File

```bash
mvn clean package

export OTEL_EXPORTER_OTLP_HEADERS='Comet-Workspace=default,projectName=otel-springai-test' \
export OPENAI_API_KEY=sk-proj-your-api-key \
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:5173/api/v1/private/otel
java -jar target/spring-ai-demo-opik-0.0.1-SNAPSHOT.jar
```

### Method 3: Development Mode with Auto-reload

```bash
export OTEL_EXPORTER_OTLP_HEADERS='Comet-Workspace=default,projectName=otel-springai-test' \
export OPENAI_API_KEY=sk-proj-your-api-key \
export OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:5173/api/v1/private/otel
mvn spring-boot:run -Dspring-boot.run.jvmArguments="-Dspring.devtools.restart.enabled=true"
```

The application will start on `http://localhost:8085`

## Testing the Demo Application using REST API

After that you can send a request to the application endpoints to interact with the chatbot:

```bash
curl --get --data-urlencode "question=How to integrate Spring AI with OpenAI for building chatbots?" http://localhost:8085/api/chat/ask-me
```

Or POST request to the `/api/chat/ask-enhanced` endpoint with TAGS and METADATA in the body:

```bash
curl -X POST \
  -H "Content-Type: application/json" \
  -d '{
    "question": "What are the benefits of using Spring AI?",
    "tags": ["spring", "ai", "tutorial"],
    "metadata": {
      "userId": "user123",
      "sessionId": "session456",
      "category": "educational"
    }
  }' \
  http://localhost:8085/api/chat/ask-enhanced
```

After running the demo application, you can view the traces in Opik by navigating to the **Traces** tab in the **Projects** page.

![Opik Traces Page](https://files.buildwithfern.com/https://opik.docs.buildwithfern.com/docs/opik/2026-01-30T17:33:07.444Z/img/tracing/springai_opentelemetry_integration.png)

## Further improvements

If you have any questions or suggestions for improving the Spring AI integration, please [open an issue](https://github.com/comet-ml/opik/issues/new/choose) on our GitHub repository.