SDKs & toolsJava SDK

Java SDK

⚠️
Preview — this feature is being built; the design below is the spec.

syntic-java is the planned official client for Java and Kotlin. It is generated from the OpenAPI description with immutable models and builders, and adds hand-written helpers for streaming, tool loops, pagination and batches. It ships in the first wave after Python and TypeScript; see Other languages.

Today, use java.net.http.HttpClient as shown in Quickstart: Java. That code keeps working after the SDK ships.

Install

implementation("ai.syntic:syntic-java:1.0.0")
RequirementValue
Java11 or newer (Kotlin 1.9 or newer)
Artifactai.syntic:syntic-java on Maven Central
HTTPBuilt-in java.net.http client; an OkHttp transport is available as syntic-java-okhttp

Create a client

import ai.syntic.SynticClient;
 
SynticClient client = SynticClient.fromEnv(); // SYNTIC_API_KEY, SYNTIC_BASE_URL
 
SynticClient custom = SynticClient.builder()
    .apiKey(System.getenv("SYNTIC_API_KEY"))
    .baseUrl("https://app.syntic.ai/v1")
    .maxRetries(3)
    .timeout(java.time.Duration.ofMinutes(5))
    .build();
Builder methodDefaultNotes
apiKeySYNTIC_API_KEYPrivate key or workload identity token.
baseUrlSYNTIC_BASE_URL, else https://app.syntic.ai/v1
versionThe release’s API versionSent as syntic-version.
addBetanoneSent as syntic-beta; methods that need a flag add it themselves.
maxRetries2Retries rate_limit, overloaded, api_error and I/O errors with back-off.
timeout10 minutesPer request.

Clients are thread-safe; create one and share it.

A first request

import ai.syntic.models.ChatCompletion;
import ai.syntic.models.ChatCompletionCreateParams;
 
ChatCompletion reply = client.chat().completions().create(
    ChatCompletionCreateParams.builder()
        .model("Amara S1.2")
        .maxTokens(200)
        .addSystemMessage("Answer in one sentence.")
        .addUserMessage("Why is the sky blue?")
        .build());
 
System.out.println(reply.choices().get(0).message().content().orElse(""));
System.out.println(reply.usage().totalTokens() + " tokens, request " + reply.requestId());

createAsync returns a CompletableFuture<ChatCompletion>.

Streaming

try (var stream = client.chat().completions().createStreaming(
        ChatCompletionCreateParams.builder()
            .model("Amara Quick")
            .addUserMessage("Write a haiku about rain.")
            .build())) {
    stream.textDeltas().forEach(System.out::print);
    var finalCompletion = stream.finalCompletion();   // assembled message, tool calls, usage
    System.out.println("\n" + finalCompletion.usage().totalTokens());
}

Closing the stream closes the connection, which stops generation.

Tool loop

record OrderArgs(@JsonPropertyDescription("Order id such as 88123") String orderId) {}
 
var getOrder = Tool.of("get_order", "Look up an order by its id.", OrderArgs.class,
    args -> Map.of("order_id", args.orderId(), "status", "shipped"));
 
var result = client.tools().run(ToolRunParams.builder()
    .model("Amara S1.2")
    .addUserMessage("Where is order 88123?")
    .addTool(getOrder)
    .maxRounds(8)
    .build());
 
System.out.println(result.finalMessage().content().orElse(""));

The argument record becomes the tool’s JSON Schema. Exceptions thrown by a tool are returned to the model as error results.

Errors

Exceptionerror.type
InvalidRequestExceptioninvalid_request
AuthenticationExceptionauthentication
PermissionDeniedExceptionpermission
NotFoundExceptionnot_found
QuotaExhaustedExceptionquota_exhausted
RateLimitExceptionrate_limit
OverloadedExceptionoverloaded
InternalServerExceptionapi_error
SynticIoExceptionNo response received

All extend SynticServiceException, with statusCode(), type(), code(), param(), details() and requestId().

try {
    client.chat().completions().create(params);
} catch (QuotaExhaustedException e) {
    System.out.println("Paused until " + e.details().get("resets_at"));
}

Pagination

for (var agent : client.agents().list(AgentListParams.builder().limit(50).build()).autoPager()) {
    System.out.println(agent.id() + " " + agent.name());
}

Files, batches, agents and admin

var file = client.files().upload(FileUploadParams.builder()
    .file(Path.of("contract.pdf")).purpose("document").build());
 
var batch = client.batches().create(BatchCreateParams.builder().inputFileId(file.id()).build());
batch = client.batches().waitFor(batch.id(), Duration.ofSeconds(30));
 
var session = client.sessions().create(SessionCreateParams.builder()
    .agentId("agt_01JC4R8W6Q2N9X3T5V7Y").build());
client.sessions().stream(session.id()).forEach(event -> {
    if (event.type().equals("message.completed")) System.out.println(event.content());
});
 
SynticAdminClient admin = SynticAdminClient.fromEnv(); // SYNTIC_ADMIN_KEY
admin.users().list().autoPager().forEach(u -> System.out.println(u.email()));

Raw responses

var raw = client.chat().completions().withRawResponse().create(params);
System.out.println(raw.headers().get("x-syntic-billing-source"));
ChatCompletion reply = raw.parse();
Was this page helpful?