Skip to Content
Welcome to the new Evolvable AI docs! đź‘‹
Developer GuideJava SDK

Evolvable.ai Java SDK Documentation

Version: 0.1.10 | Java: 11+ | Package: ai.datawise:evolvable-ai-java-client


Table of Contents

  1. Installation
  2. Client Setup
  3. Chat Operations
  4. Authentication Operations
  5. Admin Operations
  6. Spring Boot Integration
  7. Error Handling
  8. Data Models Reference

Installation

Add to your pom.xml:

<repositories> <repository> <id>github</id> <url>https://maven.pkg.github.com/evolvable-ai/evolvable-ai-java-client</url> </repository> </repositories> <dependencies> <dependency> <groupId>ai.datawise</groupId> <artifactId>evolvable-ai-java-client</artifactId> <version>0.1.10</version> </dependency> </dependencies>

Client Setup

Standard Client

EvolvableAiClient client = EvolvableAiClient.builder() .baseUrl("https://your-api-endpoint.com") .apiKey("your-api-key") .tenant("your-tenant-id") .connectionTimeout(Duration.ofSeconds(30)) // optional, default 30s .readTimeout(Duration.ofSeconds(60)) // optional, default 60s .writeTimeout(Duration.ofSeconds(60)) // optional, default 60s .debug(false) // optional, enables debug logging .build();

Admin Client

EvolvableAiAdmin admin = EvolvableAiAdmin.builder() .baseUrl("https://your-api-endpoint.com") .username("admin-username") .password("admin-password") .build(); // Login before using admin operations admin.adminLogin(new AdminLoginRequest()).join();

All operations return CompletableFuture<T>. Call .join() to block for the result or compose with .thenApply(), .thenAccept(), etc.


Chat Operations

Access via client.chat().

Send a Message

ChatRequest request = ChatRequest.simple("Hello, how can you help me?"); Message response = client.chat().send(request).join(); System.out.println(response.getValue()); System.out.println("Conversation ID: " + response.getConversationId());

Continue a Conversation

// Use the conversationId from a previous message to maintain context Message reply = client.chat() .send(request, previousMessage.getConversationId()) .join();

Chat with a Specific Agent

Message response = client.chat() .sendWithAgent(request, "agent-id-123") .join(); // Combine: continue a conversation with a specific agent Message response = client.chat() .send(request, conversationId, "agent-id-123") .join();

Streaming Chat

Receive chunks in real-time via a callback:

ChatRequest request = ChatRequest.simple("Tell me a story."); Message finalMessage = client.chat().stream(request, event -> { if (event instanceof StreamingChunkDto) { System.out.print(((StreamingChunkDto) event).getChunk()); } else if (event instanceof StreamingStartDto) { System.out.println("[Stream started]"); } else if (event instanceof StreamingEndDto) { System.out.println("\n[Stream ended]"); } else if (event instanceof StreamingErrorDto) { System.err.println("Error: " + ((StreamingErrorDto) event).getMessage()); } }).join();

Streaming variants mirror the non-streaming API:

// Stream within a conversation client.chat().stream(request, conversationId, onEvent).join(); // Stream with a specific agent client.chat().streamWithAgent(request, "agent-id", onEvent).join(); // Stream within a conversation with a specific agent client.chat().stream(request, conversationId, "agent-id", onEvent).join();

Streaming Event Types

TypeClassDescription
STARTStreamingStartDtoStream has begun
CHUNKStreamingChunkDtoText chunk (.getChunk())
ENDStreamingEndDtoStream completed
ERRORStreamingErrorDtoError occurred
INFOStreamingInfoDtoInformational message
EVENT—Custom domain event
TITLE—Title event
OPTION—Option selection event

ChatRequest Fields

ChatRequest request = ChatRequest.builder() .message("Your message here") .starterMessage(false) // optional: is this a conversation starter? .metadata(List.of( // optional: key-value metadata new SystemMetadataPair("key", "value") )) .build();

Message Response Fields

FieldTypeDescription
idLongMessage ID
valueStringResponse text content
conversationIdLongConversation thread ID
tokensIntegerTokens consumed
createdAtInstantTimestamp
typeMessageTypeBot or Human
eventsList<Event>Domain events emitted

Authentication Operations

Access via client.auth().

Server-to-Server Authentication

Generate a token for a user to authenticate with the widget/API:

// For a widget user ServerToServerAuthRequest request = ServerToServerAuthRequest.builder() .userId("user-123") .username("johndoe") .email("john@example.com") .source(UserSource.WIDGET_USER) .build(); ServerToServerAuthResponse auth = client.auth() .serverToServer(request) .join(); String accessToken = auth.getAccessToken();

For external users, use UserSource.EXTERNAL_USER. You can also include MCP auth entries for tool authentication.


Admin Operations

All admin operations require an authenticated EvolvableAiAdmin client. Token refresh is handled automatically, or can be triggered manually:

admin.refreshToken().join();

Tenants

Access via admin.tenants().

TenantOperations tenants = admin.tenants(); // List tenants (paginated) PageResponse<TenantDto> page = tenants.list(0, 20).join(); page.getContent().forEach(t -> System.out.println(t.getName())); // Create a tenant CreateTenantRequest request = CreateTenantRequest.builder() .name("Acme Corp") .schema("acme") .adminEmail("admin@acme.com") .tokenLimit(100000L) .expirationDays(365) .build(); CreateTenantResponse created = tenants.create(request).join(); UUID tenantId = created.getTenantId(); // Deactivate a tenant tenants.deactivate(tenantId).join(); // Deactivate all expired tenants tenants.deactivateExpired().join();

Settings

Access via admin.settings().

SettingsOperations settings = admin.settings(); // Get tenant settings SettingsDto current = settings.get("my-tenant").join(); // Update tenant settings SettingsDto updated = settings.update("my-tenant", modified).join();

SettingsDto covers API keys, endpoints, RAG defaults, chat defaults, widget configuration, and rate limits.


LLM Servers

Access via admin.llmServers().

LlmServerOperations llmServers = admin.llmServers(); // Create a server LlmServerCreateRequest request = LlmServerCreateRequest.builder() .name("OpenAI Production") .type(LlmServerType.OPENAI) .url("https://api.openai.com") .apiKey("sk-...") .build(); LlmServerViewDto server = llmServers.create("my-tenant", request).join(); // List servers (paginated) PageResponse<LlmServerViewDto> page = llmServers.list("my-tenant", 0, 10).join(); // Update a server LlmServerViewDto updated = llmServers.update("my-tenant", server.getId(), updateRequest).join(); // Delete a server llmServers.delete("my-tenant", server.getId()).join(); // List supported server types LlmServerTypesViewDto types = llmServers.listTypes("my-tenant").join();

Models

Access via admin.models().

ModelOperations models = admin.models(); // Sync models from configured LLM servers String result = models.sync("my-tenant").join(); // List models with search/filter params ModelSearchParams params = ModelSearchParams.builder() .type(ModelType.CHAT) .enabled(true) .build(); PageResponse<ModelViewDto> page = models.list("my-tenant", params).join(); // Enable or disable a model models.setEnabled("my-tenant", SetModelEnabledRequest.builder() .modelId("model-id") .enabled(true) .build()).join(); // Update embedding settings models.updateEmbeddingSettings("my-tenant", SetModelEmbeddingSettingsRequest.builder() .modelId("model-id") .dimensions(1536) .distanceType(DistanceType.COSINE) .build()).join(); // Delete a model models.delete("my-tenant", DeleteModelRequest.builder() .modelId("model-id") .build()).join();

Agencies

Access via admin.agencies().

Agencies are organizational groups that contain agents and members.

AgencyOperations agencies = admin.agencies(); // List agencies PageResponse<AgencyViewListDto> page = agencies.list("my-tenant", "search-term", 0, 20).join(); // Get a single agency AgencyViewDto agency = agencies.get("my-tenant", "agency-id").join(); // Create an agency String agencyId = agencies.create("my-tenant", CreateAgencyRequest.builder() .name("Support Team") .description("Customer support agency") .documentTags(List.of("support", "faq")) .build()).join(); // Update an agency agencies.update("my-tenant", agencyId, UpdateAgencyRequest.builder() .name("Support Team v2") .build()).join(); // Delete an agency agencies.delete("my-tenant", agencyId).join();

Agency Members & Admins

// List members PageResponse<AgencyMemberDto> members = agencies .listMembers("my-tenant", agencyId, null, 0, 20).join(); // List admins PageResponse<AgencyAdminDto> admins = agencies .listAdmins("my-tenant", agencyId, null, 0, 10).join(); // Add an admin agencies.addAdmin("my-tenant", agencyId, AddAgencyMemberRequest.builder() .userId("user-id-456") .build()).join(); // Remove an admin agencies.removeAdmin("my-tenant", agencyId, "user-id-456").join();

Conversation Flows

// Get conversation flows List<ConversationFlowDto> flows = agencies .getConversationFlows("my-tenant", agencyId).join(); // Update conversation flows agencies.updateConversationFlows("my-tenant", agencyId, UpdateConversationFlowsRequest.builder() .flows(updatedFlows) .build()).join();

Agents

Access via admin.agents().

Agents are AI assistants configured with instructions, tools, and guardrails.

CRUD

AgentOperations agents = admin.agents(); // List all agents in a tenant List<AgentWithAgencyViewDto> all = agents.listAll("my-tenant", true).join(); // true = top-level only // List agents in an agency (paginated) PageResponse<AgentViewDto> page = agents .listByAgency("my-tenant", agencyId, "search", 0, 20).join(); // Get a single agent AgentViewDto agent = agents.get("my-tenant", "agent-id").join(); // Create an agent String agentId = agents.create("my-tenant", agencyId, CreateUpdateAgentRequest.builder() .name("Customer Support Bot") .description("Handles customer inquiries") .customInstructions("Always be polite and helpful.") .build()).join(); // Create with an avatar image String agentId = agents.create("my-tenant", agencyId, request, imageBytes, "avatar.png").join(); // Update an agent agents.update("my-tenant", agentId, CreateUpdateAgentRequest.builder() .name("Updated Name") .build()).join(); // Delete an agent agents.delete("my-tenant", agentId).join();

Tools

List<AgentToolDto> tools = agents.getTools("my-tenant", agentId).join();

Events

// Add an event definition AgentEventDefinitionDto event = agents.addEvent("my-tenant", agentId, AgentAddEventRequest.builder() .name("order_placed") .description("Triggered when a customer places an order") .build()).join(); // Remove an event agents.removeEvent("my-tenant", agentId, event.getId()).join();

MCP Servers

Connect external tool servers to an agent using the Model Context Protocol (MCP):

// Connect via HTTP McpServerViewDto mcpServer = agents.connectMcpServerHttp("my-tenant", agentId, ConnectMcpServerHttpRequest.builder() .name("My Tools") .url("https://tools.example.com/mcp") .build()).join(); // Connect via SSE agents.connectMcpServerSse("my-tenant", agentId, ConnectMcpServerSseRequest.builder() .name("SSE Tools") .url("https://tools.example.com/sse") .build()).join(); // Connect via STDIO agents.connectMcpServerStdio("my-tenant", agentId, ConnectMcpServerStdioRequest.builder() .name("Local Tool") .command("node /path/to/tool.js") .build()).join(); // List connected MCP servers List<McpServerViewDto> servers = agents.listMcpServers("my-tenant", agentId).join(); // Sync tools from an MCP server McpServerViewDto synced = agents.syncMcpServer("my-tenant", agentId, mcpServer.getId()).join(); // Update MCP server config agents.updateMcpServer("my-tenant", agentId, mcpServer.getId(), UpdateMcpServerRequest.builder().name("Renamed").build()).join(); // Delete an MCP server connection agents.deleteMcpServer("my-tenant", agentId, mcpServer.getId()).join();

Guardrails

// List guardrails attached to an agent List<AgentGuardrailViewResponse> guardrails = agents .listGuardrails("my-tenant", agentId).join(); // Add a guardrail AgentGuardrailIdResponse result = agents.addGuardrail("my-tenant", agentId, AddGuardrailRequest.builder() .guardrailId(42L) .build()).join(); // Remove a guardrail agents.removeGuardrail("my-tenant", agentId, result.getGuardrailId()).join();

Evaluations

// Create an evaluation CreateEvalResponse eval = agents.createEval("my-tenant", agentId, CreateEvalRequest.builder() .name("Response Quality Check") .build()).join(); // Get evaluation details AgentEvalViewDto evalDetails = agents.getEval("my-tenant", agentId, eval.getEvalId()).join(); // List evaluations (paginated) PageResponse<AgentEvalViewDto> evals = agents.listEvals("my-tenant", agentId, 0, 10).join(); // Run an evaluation ExecuteEvalResponse result = agents.executeEval("my-tenant", agentId, eval.getEvalId()).join();

UI Coordinates

Used for positioning agents on a visual canvas:

agents.updateUiCoordinates("my-tenant", agentId, UpdateAgentUiCoordinatesRequest.builder() .x(100.0) .y(200.0) .build()).join();

Spring Boot Integration

Configuration

evolvable: ai: base-url: https://your-api-endpoint.com api-key: your-api-key tenant: your-tenant-id enabled: true connection-timeout: 30s read-timeout: 60s write-timeout: 60s debug: false admin: enabled: true username: admin-username password: admin-password

Usage

Inject the auto-configured beans:

@Service public class MyService { private final EvolvableAiClient client; private final EvolvableAiAdmin admin; // inject only if admin is enabled public MyService(EvolvableAiClient client, EvolvableAiAdmin admin) { this.client = client; this.admin = admin; } public String chat(String message) { return client.chat() .send(ChatRequest.simple(message)) .thenApply(Message::getValue) .join(); } }

Error Handling

All exceptions extend EvolvableAiException (a RuntimeException):

ExceptionCause
ApiExceptionNon-2xx HTTP response from the API
AuthenticationExceptionInvalid credentials or expired token
NetworkExceptionConnection failure or timeout
try { Message response = client.chat().send(request).join(); } catch (ApiException e) { System.err.println("API error " + e.getStatusCode() + ": " + e.getMessage()); } catch (AuthenticationException e) { System.err.println("Auth failed: " + e.getMessage()); } catch (NetworkException e) { System.err.println("Network error: " + e.getMessage()); } catch (EvolvableAiException e) { System.err.println("SDK error: " + e.getMessage()); }

When using CompletableFuture without .join():

client.chat().send(request) .thenAccept(msg -> System.out.println(msg.getValue())) .exceptionally(ex -> { Throwable cause = ex.getCause(); // unwrap CompletionException if (cause instanceof ApiException apiEx) { // handle API error } return null; });

Data Models Reference

Enums

EnumValues
MessageTypeBot, Human
UserSourceWIDGET_USER, EXTERNAL_USER
ModelTypeCHAT, EMBEDDING
LlmServerTypeOPENAI, ANTHROPIC, and others
LlmServerAuthorizationTypeBEARER_TOKEN, API_KEY_HEADER, and others
McpTransportSTDIO, HTTP, SSE
McpAuthTypeENV, STATIC, DYNAMIC
DistanceTypeCOSINE, EUCLIDEAN, and others
StreamingEventSTART, CHUNK, OPTION, EVENT, END, ERROR, TITLE, INFO

PageResponse<T>

All paginated endpoints return PageResponse<T>:

FieldTypeDescription
contentList<T>Items on the current page
pageNumberintCurrent page (0-indexed)
pageSizeintItems per page
totalElementslongTotal item count
totalPagesintTotal number of pages

Resource Cleanup

Close clients when done to release underlying HTTP connections:

client.close(); admin.close();

In Spring Boot, beans are closed automatically on application shutdown.

Last updated on