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.aiConfiguration 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)