Docs
Integrations
Java SDK

Java SDK

The official Ants Platform Java SDK for monitoring AI agents and LLM applications in Java and JVM-based environments.

Installation

Maven

Add the following dependency to your pom.xml:

<dependency>
    <groupId>ai.agenticants</groupId>
    <artifactId>ants-platform-java</artifactId>
    <version>0.1.1</version>
</dependency>

Gradle

Add the following to your build.gradle:

dependencies {
    implementation 'ai.agenticants:ants-platform-java:0.1.1'
}

Gradle (Kotlin DSL)

Add the following to your build.gradle.kts:

dependencies {
    implementation("ai.agenticants:ants-platform-java:0.1.1")
}

Quick Start

import com.ants.platform.client.AntsPlatformClient;
import com.ants.platform.client.core.AntsPlatformClientApiException;
 
public class MyAgent {
    public static void main(String[] args) {
        // Initialize the client
        AntsPlatformClient client = AntsPlatformClient.builder()
                .url("https://api.agenticants.ai")
                .credentials(
                    System.getenv("ANTS_PLATFORM_PUBLIC_KEY"),
                    System.getenv("ANTS_PLATFORM_SECRET_KEY")
                )
                .build();
 
        try {
            // Your agent logic here
            processQuery(client, "Help me with my order");
        } catch (AntsPlatformClientApiException e) {
            System.err.println("Error: " + e.getBody());
            System.err.println("Status Code: " + e.getStatusCode());
        }
    }
 
    private static void processQuery(AntsPlatformClient client, String query) {
        // Implementation here
    }
}

Core Features

Client Initialization

import com.ants.platform.client.AntsPlatformClient;
 
// Basic initialization
AntsPlatformClient client = AntsPlatformClient.builder()
        .url("https://api.agenticants.ai")
        .credentials(
            System.getenv("ANTS_PLATFORM_PUBLIC_KEY"),
            System.getenv("ANTS_PLATFORM_SECRET_KEY")
        )
        .build();
 
// Custom environment
AntsPlatformClient client = AntsPlatformClient.builder()
        .url(System.getenv("ANTS_PLATFORM_HOST"))
        .credentials(
            System.getenv("ANTS_PLATFORM_PUBLIC_KEY"),
            System.getenv("ANTS_PLATFORM_SECRET_KEY")
        )
        .build();

Tracing

Track your AI agent executions with detailed tracing:

import com.ants.platform.client.AntsPlatformClient;
import com.ants.platform.client.resources.ingestion.requests.IngestionRequest;
import com.ants.platform.client.resources.ingestion.types.*;
import java.util.*;
 
public class AgentTracing {
    private final AntsPlatformClient client;
 
    public AgentTracing() {
        this.client = AntsPlatformClient.builder()
                .url("https://api.agenticants.ai")
                .credentials(
                    System.getenv("ANTS_PLATFORM_PUBLIC_KEY"),
                    System.getenv("ANTS_PLATFORM_SECRET_KEY")
                )
                .build();
    }
 
    public String executeAgent(String userQuery) {
        String traceId = UUID.randomUUID().toString();
        String eventId = UUID.randomUUID().toString();
 
        try {
            // Create trace start event
            Map<String, Object> traceBody = new HashMap<>();
            traceBody.put("id", traceId);
            traceBody.put("name", "agent-execution");
            traceBody.put("userId", "user_123");
            traceBody.put("sessionId", "session_abc");
            traceBody.put("input", Map.of("user_query", userQuery));
            traceBody.put("metadata", Map.of(
                "agent", "my-agent",
                "version", "1.0.0"
            ));
            traceBody.put("tags", Arrays.asList(
                "agent:my-agent",
                "service:my-service"
            ));
 
            // Create ingestion request
            IngestionEvent event = IngestionEvent.builder()
                .id(eventId)
                .type("trace-create")
                .timestamp(new Date())
                .body(traceBody)
                .build();
 
            IngestionRequest request = IngestionRequest.builder()
                .batch(Collections.singletonList(event))
                .build();
 
            // Send trace to Ants Platform
            client.ingestion().batch(request);
 
            // Your agent logic
            String result = processAgentLogic(userQuery);
 
            // Update trace with results
            updateTrace(traceId, result);
 
            return result;
 
        } catch (Exception e) {
            // Handle error and update trace
            handleError(traceId, e);
            throw e;
        }
    }
 
    private String processAgentLogic(String query) {
        // Your agent implementation
        return "Agent response";
    }
 
    private void updateTrace(String traceId, String result) {
        Map<String, Object> updateBody = new HashMap<>();
        updateBody.put("id", traceId);
        updateBody.put("output", Map.of("result", result));
        updateBody.put("status", "success");
 
        IngestionEvent event = IngestionEvent.builder()
            .id(UUID.randomUUID().toString())
            .type("trace-update")
            .timestamp(new Date())
            .body(updateBody)
            .build();
 
        IngestionRequest request = IngestionRequest.builder()
            .batch(Collections.singletonList(event))
            .build();
 
        client.ingestion().batch(request);
    }
 
    private void handleError(String traceId, Exception e) {
        Map<String, Object> errorBody = new HashMap<>();
        errorBody.put("id", traceId);
        errorBody.put("status", "error");
        errorBody.put("output", Map.of("error", e.getMessage()));
 
        IngestionEvent event = IngestionEvent.builder()
            .id(UUID.randomUUID().toString())
            .type("trace-update")
            .timestamp(new Date())
            .body(errorBody)
            .build();
 
        IngestionRequest request = IngestionRequest.builder()
            .batch(Collections.singletonList(event))
            .build();
 
        client.ingestion().batch(request);
    }
}

Spans for Detailed Tracking

Create spans to track individual operations within your agent:

import java.util.*;
 
public class DetailedTracking {
    private final AntsPlatformClient client;
 
    public void executeWithSpans(String traceId, String query) {
        // Create validation span
        createSpan(
            traceId,
            "request_validation",
            Map.of("raw_input", query),
            Map.of(
                "validated_input", query,
                "input_length", query.length()
            ),
            Map.of("step", "validation")
        );
 
        // Process query
        String context = retrieveContext(query);
 
        // Create context retrieval span
        createSpan(
            traceId,
            "context_retrieval",
            Map.of("query", query),
            Map.of("context", context),
            Map.of("step", "context-retrieval")
        );
 
        // Generate response
        String response = generateResponse(query, context);
 
        // Create generation span
        createGenerationSpan(
            traceId,
            "gpt-4_llm_call",
            "gpt-4",
            query,
            response,
            100,  // input tokens
            200,  // output tokens
            Map.of("step", "llm_call")
        );
    }
 
    private void createSpan(
        String traceId,
        String name,
        Map<String, Object> input,
        Map<String, Object> output,
        Map<String, Object> metadata
    ) {
        String spanId = UUID.randomUUID().toString();
 
        Map<String, Object> spanBody = new HashMap<>();
        spanBody.put("id", spanId);
        spanBody.put("traceId", traceId);
        spanBody.put("name", name);
        spanBody.put("input", input);
        spanBody.put("output", output);
        spanBody.put("metadata", metadata);
        spanBody.put("startTime", new Date());
        spanBody.put("endTime", new Date());
 
        IngestionEvent event = IngestionEvent.builder()
            .id(UUID.randomUUID().toString())
            .type("span-create")
            .timestamp(new Date())
            .body(spanBody)
            .build();
 
        IngestionRequest request = IngestionRequest.builder()
            .batch(Collections.singletonList(event))
            .build();
 
        client.ingestion().batch(request);
    }
 
    private void createGenerationSpan(
        String traceId,
        String name,
        String model,
        String prompt,
        String completion,
        int inputTokens,
        int outputTokens,
        Map<String, Object> metadata
    ) {
        String generationId = UUID.randomUUID().toString();
 
        Map<String, Object> generationBody = new HashMap<>();
        generationBody.put("id", generationId);
        generationBody.put("traceId", traceId);
        generationBody.put("name", name);
        generationBody.put("model", model);
        generationBody.put("prompt", prompt);
        generationBody.put("completion", completion);
        generationBody.put("inputTokens", inputTokens);
        generationBody.put("outputTokens", outputTokens);
        generationBody.put("metadata", metadata);
        generationBody.put("startTime", new Date());
        generationBody.put("endTime", new Date());
 
        IngestionEvent event = IngestionEvent.builder()
            .id(UUID.randomUUID().toString())
            .type("generation-create")
            .timestamp(new Date())
            .body(generationBody)
            .build();
 
        IngestionRequest request = IngestionRequest.builder()
            .batch(Collections.singletonList(event))
            .build();
 
        client.ingestion().batch(request);
    }
 
    private String retrieveContext(String query) {
        // Retrieve context implementation
        return "Relevant context";
    }
 
    private String generateResponse(String query, String context) {
        // Generate response implementation
        return "Generated response";
    }
}

Error Handling

import com.ants.platform.client.core.AntsPlatformClientApiException;
 
public class ErrorHandlingExample {
    private final AntsPlatformClient client;
 
    public void processWithErrorHandling(String query) {
        String traceId = UUID.randomUUID().toString();
 
        try {
            // Start trace
            startTrace(traceId, query);
 
            // Process query
            String result = processQuery(query);
 
            // Update trace with success
            updateTraceSuccess(traceId, result);
 
        } catch (AntsPlatformClientApiException e) {
            System.err.println("API Error: " + e.getBody());
            System.err.println("Status Code: " + e.getStatusCode());
 
            // Update trace with error
            updateTraceError(traceId, e.getMessage());
            throw e;
 
        } catch (Exception e) {
            System.err.println("Error: " + e.getMessage());
 
            // Update trace with error
            updateTraceError(traceId, e.getMessage());
            throw e;
        }
    }
 
    private void startTrace(String traceId, String query) {
        // Implementation
    }
 
    private String processQuery(String query) {
        // Implementation
        return "Result";
    }
 
    private void updateTraceSuccess(String traceId, String result) {
        // Implementation
    }
 
    private void updateTraceError(String traceId, String error) {
        // Implementation
    }
}

Configuration

Environment Variables

Create a .env file or set system environment variables:

ANTS_PLATFORM_PUBLIC_KEY=your_public_key
ANTS_PLATFORM_SECRET_KEY=your_secret_key
ANTS_PLATFORM_HOST=https://api.agenticants.ai

Configuration in Code

import com.ants.platform.client.AntsPlatformClient;
 
public class Configuration {
    public static AntsPlatformClient createClient() {
        return AntsPlatformClient.builder()
                .url(getEnvOrDefault("ANTS_PLATFORM_HOST", "https://api.agenticants.ai"))
                .credentials(
                    System.getenv("ANTS_PLATFORM_PUBLIC_KEY"),
                    System.getenv("ANTS_PLATFORM_SECRET_KEY")
                )
                .build();
    }
 
    private static String getEnvOrDefault(String key, String defaultValue) {
        String value = System.getenv(key);
        return value != null ? value : defaultValue;
    }
}

Framework Integrations

Spring Boot

import org.springframework.stereotype.Service;
import org.springframework.beans.factory.annotation.Value;
import com.ants.platform.client.AntsPlatformClient;
 
@Service
public class AntsPlatformService {
    private final AntsPlatformClient client;
 
    public AntsPlatformService(
        @Value("${ants.platform.host}") String host,
        @Value("${ants.platform.public-key}") String publicKey,
        @Value("${ants.platform.secret-key}") String secretKey
    ) {
        this.client = AntsPlatformClient.builder()
                .url(host)
                .credentials(publicKey, secretKey)
                .build();
    }
 
    public void traceAgentExecution(String query) {
        String traceId = UUID.randomUUID().toString();
 
        try {
            // Start trace
            Map<String, Object> traceBody = new HashMap<>();
            traceBody.put("id", traceId);
            traceBody.put("name", "spring-boot-agent");
            traceBody.put("input", Map.of("query", query));
            traceBody.put("metadata", Map.of(
                "framework", "spring-boot",
                "service", "agent-service"
            ));
 
            IngestionEvent event = IngestionEvent.builder()
                .id(UUID.randomUUID().toString())
                .type("trace-create")
                .timestamp(new Date())
                .body(traceBody)
                .build();
 
            IngestionRequest request = IngestionRequest.builder()
                .batch(Collections.singletonList(event))
                .build();
 
            client.ingestion().batch(request);
 
            // Your agent logic here
 
        } catch (Exception e) {
            // Handle error
        }
    }
 
    public AntsPlatformClient getClient() {
        return client;
    }
}

application.properties

ants.platform.host=https://api.agenticants.ai
ants.platform.public-key=${ANTS_PLATFORM_PUBLIC_KEY}
ants.platform.secret-key=${ANTS_PLATFORM_SECRET_KEY}

API Reference

AntsPlatformClient

public class AntsPlatformClient {
    // Build a new client
    public static AntsPlatformClientBuilder builder()
 
    // Access ingestion API
    public IngestionClient ingestion()
 
    // Access trace API
    public TraceClient trace()
 
    // Access other resources
    public PromptsClient prompts()
    public SessionsClient sessions()
    public ObservationsClient observations()
}

AntsPlatformClientBuilder

public class AntsPlatformClientBuilder {
    // Set the API URL
    public AntsPlatformClientBuilder url(String url)
 
    // Set credentials
    public AntsPlatformClientBuilder credentials(String publicKey, String secretKey)
 
    // Build the client
    public AntsPlatformClient build()
}

IngestionClient

public class IngestionClient {
    // Send batch of events
    public IngestionResponse batch(IngestionRequest request)
 
    // Send batch with custom options
    public IngestionResponse batch(IngestionRequest request, RequestOptions options)
}

Best Practices

1. Use Try-Catch Blocks

Always handle exceptions properly:

try {
    // Your tracing code
    client.ingestion().batch(request);
} catch (AntsPlatformClientApiException e) {
    System.err.println("API Error: " + e.getBody());
    System.err.println("Status Code: " + e.getStatusCode());
} catch (Exception e) {
    System.err.println("Error: " + e.getMessage());
}

2. Add Rich Metadata

Include relevant context in your traces:

Map<String, Object> metadata = new HashMap<>();
metadata.put("user_id", "user_123");
metadata.put("session_id", "session_abc");
metadata.put("agent", "my-agent");
metadata.put("version", "1.0.0");
metadata.put("environment", System.getenv("ENVIRONMENT"));
 
traceBody.put("metadata", metadata);
traceBody.put("tags", Arrays.asList(
    "agent:my-agent",
    "service:my-service",
    "version:1.0.0"
));

3. Use Unique IDs

Generate unique IDs for traces and events:

import java.util.UUID;
 
String traceId = UUID.randomUUID().toString();
String eventId = UUID.randomUUID().toString();
String spanId = UUID.randomUUID().toString();

4. Batch Events Efficiently

Group multiple events in a single batch for better performance:

List<IngestionEvent> events = new ArrayList<>();
 
// Add multiple events
events.add(createTraceEvent(traceId));
events.add(createSpanEvent(traceId, "step1"));
events.add(createSpanEvent(traceId, "step2"));
events.add(createGenerationEvent(traceId));
 
// Send all at once
IngestionRequest request = IngestionRequest.builder()
    .batch(events)
    .build();
 
client.ingestion().batch(request);

Note: Batch sizes are limited to 3.5 MB in total.

5. Create Helper Classes

Encapsulate tracing logic in reusable helper classes:

public class TracingHelper {
    private final AntsPlatformClient client;
 
    public TracingHelper(AntsPlatformClient client) {
        this.client = client;
    }
 
    public String startTrace(String name, Map<String, Object> input, Map<String, Object> metadata) {
        String traceId = UUID.randomUUID().toString();
 
        Map<String, Object> traceBody = new HashMap<>();
        traceBody.put("id", traceId);
        traceBody.put("name", name);
        traceBody.put("input", input);
        traceBody.put("metadata", metadata);
 
        IngestionEvent event = IngestionEvent.builder()
            .id(UUID.randomUUID().toString())
            .type("trace-create")
            .timestamp(new Date())
            .body(traceBody)
            .build();
 
        IngestionRequest request = IngestionRequest.builder()
            .batch(Collections.singletonList(event))
            .build();
 
        client.ingestion().batch(request);
 
        return traceId;
    }
 
    public void updateTrace(String traceId, String status, Map<String, Object> output) {
        Map<String, Object> updateBody = new HashMap<>();
        updateBody.put("id", traceId);
        updateBody.put("status", status);
        updateBody.put("output", output);
 
        IngestionEvent event = IngestionEvent.builder()
            .id(UUID.randomUUID().toString())
            .type("trace-update")
            .timestamp(new Date())
            .body(updateBody)
            .build();
 
        IngestionRequest request = IngestionRequest.builder()
            .batch(Collections.singletonList(event))
            .build();
 
        client.ingestion().batch(request);
    }
}
 
// Usage
TracingHelper helper = new TracingHelper(client);
String traceId = helper.startTrace("my-operation", input, metadata);
// ... do work ...
helper.updateTrace(traceId, "success", output);

Complete Example

Here's a complete example of a customer support agent with full tracing:

import com.ants.platform.client.AntsPlatformClient;
import com.ants.platform.client.resources.ingestion.requests.IngestionRequest;
import com.ants.platform.client.resources.ingestion.types.*;
import java.util.*;
 
public class CustomerSupportAgent {
    private final AntsPlatformClient client;
    private final TracingHelper tracingHelper;
 
    public CustomerSupportAgent() {
        this.client = AntsPlatformClient.builder()
                .url("https://api.agenticants.ai")
                .credentials(
                    System.getenv("ANTS_PLATFORM_PUBLIC_KEY"),
                    System.getenv("ANTS_PLATFORM_SECRET_KEY")
                )
                .build();
        this.tracingHelper = new TracingHelper(client);
    }
 
    public String handleQuery(String query, String userId) {
        String traceId = tracingHelper.startTrace(
            "customer-support-agent",
            Map.of("query", query, "userId", userId),
            Map.of("agent", "customer-support", "userId", userId)
        );
 
        try {
            // Validate input
            tracingHelper.createSpan(
                traceId,
                "validate-input",
                Map.of("query", query),
                Map.of("valid", true),
                Map.of("step", "validation")
            );
 
            // Get context
            String context = getContext(query);
            tracingHelper.createSpan(
                traceId,
                "retrieve-context",
                Map.of("query", query),
                Map.of("context", context),
                Map.of("step", "context-retrieval")
            );
 
            // Generate response
            String response = generateResponse(query, context);
            tracingHelper.createGenerationSpan(
                traceId,
                "generate-response",
                "gpt-4",
                query,
                response,
                150,  // input tokens
                200,  // output tokens
                Map.of("step", "generation")
            );
 
            // Update trace with success
            tracingHelper.updateTrace(
                traceId,
                "success",
                Map.of("response", response)
            );
 
            return response;
 
        } catch (Exception e) {
            // Handle error
            tracingHelper.createSpan(
                traceId,
                "error-handling",
                Map.of("error", e.getMessage()),
                Map.of("handled", true),
                Map.of(
                    "error_type", e.getClass().getSimpleName(),
                    "step", "error-handling"
                )
            );
 
            tracingHelper.updateTrace(
                traceId,
                "error",
                Map.of("error", e.getMessage())
            );
 
            throw e;
        }
    }
 
    private String getContext(String query) {
        // Retrieve relevant context from database or vector store
        return "Relevant context...";
    }
 
    private String generateResponse(String query, String context) {
        // Call LLM to generate response
        return "Generated response...";
    }
 
    public static void main(String[] args) {
        CustomerSupportAgent agent = new CustomerSupportAgent();
        String response = agent.handleQuery(
            "What's the status of my order?",
            "user_123"
        );
        System.out.println("Response: " + response);
    }
}

Troubleshooting

Common Issues

"Authentication failed" error

  • Verify your public and secret keys are correct
  • Ensure environment variables are properly set
  • Check that keys have not expired

"Network timeout" error

  • Verify the host URL is correct
  • Check your network connectivity
  • Ensure firewall rules allow outbound HTTPS connections

Traces not appearing in dashboard

  • Ensure you're sending events with correct format
  • Check that the client is properly initialized
  • Verify your API keys have the correct permissions
  • Check batch size is under 3.5 MB limit

Debug Logging

Enable debug logging in your application to troubleshoot issues:

import java.util.logging.*;
 
public class DebugExample {
    static {
        // Enable HTTP logging
        System.setProperty("java.util.logging.config.file", "logging.properties");
    }
 
    public static void main(String[] args) {
        Logger logger = Logger.getLogger("com.ants.platform");
        logger.setLevel(Level.FINE);
 
        ConsoleHandler handler = new ConsoleHandler();
        handler.setLevel(Level.FINE);
        logger.addHandler(handler);
 
        // Your code here
    }
}

Requirements

  • Java 8 or higher
  • Maven 3.x or Gradle 6.x+
  • Dependencies:
    • Jackson 2.18.2+ (for JSON processing)
    • OkHttp 4.11.0+ (for HTTP client)

Next Steps