Generation Generation — Java examples backed by real provider calls. java examples examples/generation src/examples/java/generation example Generation

These Java examples are real runnable files. Edit the source file first; this page is rebuilt from the checked-in example and its metadata header.

Java Prompt-Cached Generation

Runs GPT-6 structured generation with stable OpenAI prompt-cache affinity.

Java
import dev.axllm.ax.*;
import java.nio.file.*;
import java.util.*;

public final class BasicGenerationExample {
  static String apiKey() {
    String apiKey = System.getenv("OPENAI_API_KEY");
    if (apiKey == null || apiKey.isBlank()) apiKey = System.getenv("OPENAI_APIKEY");
    if (apiKey == null || apiKey.isBlank()) {
      throw new IllegalStateException("Set OPENAI_API_KEY or OPENAI_APIKEY to run this example.");
    }
    return apiKey;
  }

  static AxAIService client() {
    return Ax.ai("openai",
        Map.of("api_key", apiKey(), "model", System.getenv().getOrDefault("AX_OPENAI_MODEL", "gpt-6-luna")));
  }

  public static void main(String[] args) throws Exception {
    AxGen program = Ax.ax("question:string -> answer:string");
    Map<String, Object> output = program.forward(
        client(),
        Map.of("question", "In one sentence, explain Ax as a language-agnostic LLM programming library."),
        Map.of("timeout", 30000, "promptCacheKey", "ax-openai-example", "contextCache", Map.of()));
    System.out.println(Json.stringify(output));
  }
}

Java Astra Generation

Runs Astra through the standard generator with automatic Responses routing and prompt caching.

Java
import dev.axllm.ax.*;
import java.nio.file.*;
import java.util.*;

public final class AstraGenerationExample {
  static String apiKey() {
    String apiKey = System.getenv("OPENAI_API_KEY");
    if (apiKey == null || apiKey.isBlank()) apiKey = System.getenv("OPENAI_APIKEY");
    if (apiKey == null || apiKey.isBlank()) {
      throw new IllegalStateException("Set OPENAI_API_KEY or OPENAI_APIKEY to run this example.");
    }
    return apiKey;
  }

  static AxAIService client() {
    return Ax.ai("openai",
        Map.of("api_key", apiKey(), "model", System.getenv().getOrDefault("AX_OPENAI_MODEL", "gpt-6-astra"), "model_config", Map.of("thinkingTokenBudget", "low", "max_tokens", 2048)));
  }

  public static void main(String[] args) throws Exception {
    AxGen program = Ax.ax("question:string -> answer:string");
    Map<String, Object> output = program.forward(
        client(),
        Map.of("question", "In one sentence, explain Ax as a language-agnostic LLM programming library."),
        Map.of("serviceTier", "standard", "promptCacheKey", "ax-openai-example", "contextCache", Map.of()));
    System.out.println(Json.stringify(output));
  }
}

Java GPT-6.1 Sol Generation

Runs GPT-6.1 Sol through the standard generator with automatic Responses routing and prompt caching.

Java
import dev.axllm.ax.*;
import java.nio.file.*;
import java.util.*;

public final class Gpt61SolExample {
  static String apiKey() {
    String apiKey = System.getenv("OPENAI_API_KEY");
    if (apiKey == null || apiKey.isBlank()) apiKey = System.getenv("OPENAI_APIKEY");
    if (apiKey == null || apiKey.isBlank()) {
      throw new IllegalStateException("Set OPENAI_API_KEY or OPENAI_APIKEY to run this example.");
    }
    return apiKey;
  }

  static AxAIService client() {
    return Ax.ai("openai",
        Map.of("api_key", apiKey(), "model", System.getenv().getOrDefault("AX_OPENAI_MODEL", "gpt-6.1-sol"), "model_config", Map.of("thinkingTokenBudget", "low", "max_tokens", 2048)));
  }

  public static void main(String[] args) throws Exception {
    AxGen program = Ax.ax("question:string -> answer:string");
    Map<String, Object> output = program.forward(
        client(),
        Map.of("question", "In one sentence, explain Ax as a language-agnostic LLM programming library."),
        Map.of("serviceTier", "standard", "promptCacheKey", "ax-gpt61-sol-example", "contextCache", Map.of()));
    System.out.println(Json.stringify(output));
  }
}

Java Model Catalog

Lists static models and named OpenAI-compatible profiles with portable thinking levels and service tiers.

Java
import dev.axllm.ax.Ax;
import java.util.*;

public final class ModelCatalogExample {
  private static Map<?, ?> provider(List<Object> catalog, String name) {
    return catalog.stream()
        .map(entry -> (Map<?, ?>) entry)
        .filter(entry -> name.equals(entry.get("name")))
        .findFirst()
        .orElseThrow();
  }

  public static void main(String[] args) {
    List<Object> catalog = Ax.getSupportedAIModels();
    Map<?, ?> azure = provider(catalog, "azure-openai");
    Map<?, ?> openrouter = provider(catalog, "openrouter");
    Map<?, ?> azureCapabilities = (Map<?, ?>) azure.get("capabilities");
    Map<?, ?> openrouterCapabilities = (Map<?, ?>) openrouter.get("capabilities");

    assert Boolean.TRUE.equals(azure.get("isDynamic"));
    assert ((List<?>) azure.get("models")).isEmpty();
    assert ((List<?>) azureCapabilities.get("thinkingLevels")).contains("high");
    assert ((List<?>) azureCapabilities.get("serviceTiers")).contains("priority");
    assert ((List<?>) openrouterCapabilities.get("serviceTiers")).contains("flex");

    System.out.println(catalog.size() + " providers; Azure and OpenRouter named profiles are available");
  }
}

Java Jev Signature Decisions

Converts Jev probabilities into boolean and class outputs with a provider threshold.

Java
import dev.axllm.ax.*;
import java.util.*;

public final class TypesafeExample {
  public static void main(String[] args) throws Exception {
    var model = Ax.ai("typesafe", Map.of("apiKey", System.getenv("TYPESAFE_APIKEY"), "trueThreshold", 0.9));
    var triage = Ax.ax("ticket:string -> urgent:boolean(true \"Customers cannot complete a core task\", false \"Routine request\") \"Needs immediate attention?\", team:class \"support, billing, engineering\"");
    var decision = triage.forward(model, Map.of("ticket", "Checkout is unavailable for all customers after the latest deployment."));
    if (!(decision.get("urgent") instanceof Boolean) || !Set.of("support", "billing", "engineering").contains(decision.get("team"))) throw new AssertionError("Invalid decision");
    System.out.println(Json.stringify(decision));
  }
}

Java OpenAI Signature Decisions

Converts OpenAI probabilities into boolean and class outputs with a provider threshold.

Java
import dev.axllm.ax.*;
import java.util.*;

public final class OpenAIDecisionsExample {
  public static void main(String[] args) throws Exception {
    var model = Ax.ai("openai-decisions", Map.of("apiKey", Optional.ofNullable(System.getenv("OPENAI_API_KEY")).orElse(System.getenv("OPENAI_APIKEY")), "trueThreshold", 0.9));
    var triage = Ax.ax("ticket:string -> urgent:boolean(true \"Customers cannot complete a core task\", false \"Routine request\") \"Needs immediate attention?\", team:class \"support, billing, engineering\"");
    var decision = triage.forward(model, Map.of("ticket", "Checkout is unavailable for all customers after the latest deployment."));
    if (!(decision.get("urgent") instanceof Boolean) || !Set.of("support", "billing", "engineering").contains(decision.get("team"))) throw new AssertionError("Invalid decision");
    System.out.println(Json.stringify(decision));
  }
}

Java Meta Muse Spark

Selects any of Meta’s three protocols through the existing chat API.

Java
import dev.axllm.ax.*;
import java.util.*;

public final class MetaMuseExample {
  public static void main(String[] args) throws Exception {
    String key = System.getenv("MODEL_API_KEY");
    if (key == null || key.isBlank()) throw new IllegalStateException("Set MODEL_API_KEY to run this example.");
    for (String profile : List.of("meta", "meta-chat", "meta-messages")) {
      var client = Ax.ai(profile, Map.of("api_key", key, "model", "muse-spark-1.3"));
      var response = client.chat(Map.of(
          "chat_prompt", List.of(Map.of("role", "user", "content", "Name a solar-powered sailboat.")),
          "model_config", Map.of("thinking_token_budget", "highest")));
      System.out.println(profile + " " + Json.stringify(response));
    }
  }
}

Java Structured Extraction

Extracts structured fields and labels from support text with OpenAI.

Java
import dev.axllm.ax.*;
import java.nio.file.*;
import java.util.*;

public final class StructuredGenerationExample {
  static String apiKey() {
    String apiKey = System.getenv("OPENAI_API_KEY");
    if (apiKey == null || apiKey.isBlank()) apiKey = System.getenv("OPENAI_APIKEY");
    if (apiKey == null || apiKey.isBlank()) {
      throw new IllegalStateException("Set OPENAI_API_KEY or OPENAI_APIKEY to run this example.");
    }
    return apiKey;
  }

  static AxAIService client() {
    return Ax.ai("openai",
        Map.of("api_key", apiKey(), "model", System.getenv().getOrDefault("AX_OPENAI_MODEL", "gpt-5.4-mini"), "model_config", Map.of("temperature", 0.0)));
  }

  public static void main(String[] args) throws Exception {
    AxGen program = Ax.ax("ticket:string -> priority:class \"high, normal, low\", summary:string, labels:string[]");
    Map<String, Object> output = program.forward(client(), Map.of("ticket", "Checkout has failed for enterprise customers since 09:00. Support wants a concise summary and tags."));
    System.out.println(Json.stringify(output));
  }
}

Java Vertex Gemini Routing

Calls Gemini through Vertex with project and multi-region routing.

Java
import dev.axllm.ax.*;
import java.util.*;

public final class VertexGeminiExample {
  private static String required(String name) {
    String value = System.getenv(name);
    if (value == null || value.isBlank()) throw new IllegalStateException("Set " + name + " to run this example.");
    return value;
  }

  public static void main(String[] args) throws Exception {
    GoogleGeminiClient client = new GoogleGeminiClient(Map.of(
        "api_key", required("GOOGLE_VERTEX_ACCESS_TOKEN"),
        "project_id", required("GOOGLE_PROJECT_ID"),
        "region", required("GOOGLE_REGION"),
        "model", System.getenv().getOrDefault("AX_VERTEX_MODEL", "gemini-3.5-flash")));
    Map<String, Object> out = client.chat(Map.of(
        "chat_prompt", List.of(Map.of("role", "user", "content", "Reply with the word ready."))));
    System.out.println(Json.stringify(out));
  }
}

Java Jev Hybrid Reply

Passes Jev decisions to a second Ax program to generate a customer reply.

Java
import dev.axllm.ax.*;
import java.util.*;

public final class TypesafeHybridExample {
  public static void main(String[] args) throws Exception {
    var model = Ax.ai("typesafe", Map.of("apiKey", System.getenv("TYPESAFE_APIKEY"), "trueThreshold", 0.9));
    var triage = Ax.ax("ticket:string -> urgent:boolean(true \"Customers cannot complete a core task\", false \"Routine request\") \"Needs immediate attention?\", team:class \"support, billing, engineering\"");
    var decision = triage.forward(model, Map.of("ticket", "Checkout is unavailable for all customers after the latest deployment."));
    if (!(decision.get("urgent") instanceof Boolean) || !Set.of("support", "billing", "engineering").contains(decision.get("team"))) throw new AssertionError("Invalid decision");
    var key = System.getenv().getOrDefault("OPENAI_API_KEY", System.getenv("OPENAI_APIKEY"));
    var writer = Ax.ai("openai", Map.of("apiKey", key, "model", "gpt-5.6-luna"));
    var inputs = new LinkedHashMap<String,Object>(decision);
    inputs.put("ticket", "Checkout is unavailable for all customers after the latest deployment.");
    var reply = Ax.ax("ticket:string, urgent:boolean, team:string -> reply:string").forward(writer, inputs);
    if (!(reply.get("reply") instanceof String text) || text.isBlank()) throw new AssertionError("Empty reply");
    System.out.println(Json.stringify(Map.of("decision", decision, "reply", reply)));
  }
}

Java Signature Constraints

Builds a constrained signature fluently and runs it with OpenAI.

Java
import dev.axllm.ax.*;
import java.util.*;

public final class SignatureConstraintsExample {
  static String apiKey() {
    String apiKey = System.getenv("OPENAI_API_KEY");
    if (apiKey == null || apiKey.isBlank()) apiKey = System.getenv("OPENAI_APIKEY");
    if (apiKey == null || apiKey.isBlank()) {
      throw new IllegalStateException("Set OPENAI_API_KEY or OPENAI_APIKEY to run this example.");
    }
    return apiKey;
  }

  static AxAIService client() {
    return Ax.ai("openai",
        Map.of(
            "api_key", apiKey(),
            "model", System.getenv().getOrDefault("AX_OPENAI_MODEL", "gpt-5.4-mini"),
            "model_config", Map.of("temperature", 0.0)));
  }

  public static void main(String[] args) throws Exception {
    AxSignature signature =
        Ax.f()
            .call()
            .input("requestText", Ax.f().string("Booking request").min(10).max(500))
            .input("contactEmail", Ax.f().string("Contact email").email())
            .output("partySize", Ax.f().number("Guests").min(1).max(12))
            .output(
                "bookingCode",
                Ax.f()
                    .string("Three letters, a dash, and four digits")
                    .regex("^[A-Z]{3}-\\d{4}$", "Must look like ABC-1234"))
            .output(
                "guestProfile",
                Ax.f()
                    .object(
                        Map.of(
                            "fullName", Ax.f().string("Primary guest").min(2),
                            "dietaryNotes",
                                Ax.f().string("Dietary requirements").optional())))
            .build();
    Map<String, Object> output =
        Ax.ax(signature)
            .forward(
                client(),
                Map.of(
                    "requestText",
                    "Book dinner for four people under the name Ada Lovelace.",
                    "contactEmail",
                    "ada@example.com"));
    System.out.println(Json.stringify(output));
  }
}

Centralized Usage Observer

Attributes every completed model call to a tenant, user, and request from one global observer.

Java
import dev.axllm.ax.*;
import java.util.*;

public final class UsageObserverExample {
  public static void main(String[] args) throws Exception {
    String apiKey = System.getenv("OPENAI_API_KEY");
    if (apiKey == null || apiKey.isBlank()) apiKey = System.getenv("OPENAI_APIKEY");
    if (apiKey == null || apiKey.isBlank()) {
      throw new IllegalStateException("Set OPENAI_API_KEY or OPENAI_APIKEY to run this example.");
    }

    List<AxUsageEvent> events = new ArrayList<>();
    AxGlobals.setUsageObserver(events::add);
    AxAIService client =
        Ax.ai("openai",
            Map.of(
                "api_key", apiKey,
                "model", System.getenv().getOrDefault("AX_OPENAI_MODEL", "gpt-5.4-mini"),
                "usageContext",
                    Map.of(
                        "tenantId", "tenant-42",
                        "feature", "support-chat",
                        "attributes", Map.of("environment", "example"))));
    try {
      client.chat(
          Map.of(
              "chat_prompt",
              List.of(Map.of("role", "user", "content", "Reply with one short greeting."))),
          Map.of(
              "usageContext",
              Map.of("userId", "user-7", "requestId", UUID.randomUUID().toString())));
      System.out.println(Json.stringify(events.stream().map(AxUsageEvent::value).toList()));
    } finally {
      AxGlobals.setUsageObserver(null);
    }
  }
}

Java Incremental Provider Stream

Consumes a lazy, closeable OpenAI SSE stream event by event.

Java
import dev.axllm.ax.*;
import java.util.*;

public final class ProviderStreamExample {
  public static void main(String[] args) throws Exception {
    String apiKey = System.getenv("OPENAI_API_KEY");
    if (apiKey == null || apiKey.isBlank()) apiKey = System.getenv("OPENAI_APIKEY");
    if (apiKey == null || apiKey.isBlank()) throw new IllegalStateException("Set OPENAI_API_KEY or OPENAI_APIKEY to run this example.");
    AxAIService client = Ax.ai("openai", Map.of(
      "api_key", apiKey,
      "model", System.getenv().getOrDefault("AX_OPENAI_MODEL", "gpt-5.6-luna")
    ));
    long started = System.nanoTime();
    try (AxChatStream stream = client.openStream(Map.of(
      "chat_prompt", List.of(Map.of("role", "user", "content", "Reply with exactly: streaming works"))
    ))) {
      for (Map<String, Object> event : stream) {
        List<?> results = (List<?>) event.get("results");
        Object content = results.isEmpty() ? null : ((Map<?, ?>) results.get(0)).get("content");
        if (content != null && !content.toString().isEmpty()) {
          System.out.printf("[%d ms] %s", (System.nanoTime() - started) / 1_000_000, content);
        }
      }
    }
    System.out.println();
  }
}

Java Decision Evidence Reranking

Ranks documents through Ax signatures while retaining decision evidence and candidate IDs.

Java
import dev.axllm.ax.*;
import java.util.*;

public final class DecisionEvidenceExample {
  public static void main(String[] args) throws Exception {
    var model = Ax.ai("openai-decisions", Map.of("apiKey", Optional.ofNullable(System.getenv("OPENAI_API_KEY")).orElse(System.getenv("OPENAI_APIKEY"))));
    var judge = Ax.ax("query:string, document:string -> relevant:boolean(evidence, threshold 0.7), relevance:score \"Irrelevant, Related, Partial answer, Direct answer\"(evidence)");
    var candidates = List.of(Map.of("id", "refund", "text", "Request a refund within 30 days through your account billing page."), Map.of("id", "password", "text", "Reset your password using the sign-in page."));
    var ranked = new ArrayList<Map<String,Object>>();
    for (var item : candidates) {
      var result = new LinkedHashMap<String,Object>(judge.forward(model, Map.of("query", "How do I request a refund?", "document", item.get("text"))));
      result.put("id", item.get("id")); ranked.add(result);
    }
    ranked.sort(Comparator.comparingDouble((Map<String,Object> item) -> ((Number)((Map<?,?>)item.get("relevance")).get("value")).doubleValue()).reversed());
    System.out.println(Json.stringify(ranked));
  }
}

Java Portable Cancellation

Cancels a provider request before transport and preserves the first cancellation reason.

Java
import dev.axllm.ax.*;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;

public final class CancellationExample {
  public static void main(String[] args) throws Exception {
    AtomicInteger calls = new AtomicInteger();
    OpenAICompatibleClient.Transport transport = request -> {
      calls.incrementAndGet();
      return Map.of("status", 200, "json", Map.of());
    };
    AxAIService client = new OpenAICompatibleClient(Map.of(
      "api_key", "test-key", "model", "gpt-5.6-luna", "transport", transport
    ));
    AxCancellationToken token = new AxCancellationToken();
    assert token.cancel("user stopped") && !token.cancel("later reason");

    try {
      client.chatWithCancellation(
        Map.of("chat_prompt", List.of(Map.of("role", "user", "content", "This must not be sent."))),
        Map.of(), token
      );
      throw new AssertionError("pre-cancelled request unexpectedly completed");
    } catch (AxAIServiceAbortedError error) {
      assert "user stopped".equals(error.reason()) && !error.retryable;
    }

    assert calls.get() == 0;
    System.out.println("cancelled before transport: user stopped");
  }
}

Java Sonnet 5.5 Between-Tool Thinking

Disables pre-response thinking while retaining signed updates for replay.

Java
import dev.axllm.ax.*;
import java.util.*;

public final class Sonnet55BetweenToolsExample {
  public static void main(String[] args) throws Exception {
    String apiKey = System.getenv("ANTHROPIC_API_KEY");
    if (apiKey == null || apiKey.isBlank()) apiKey = System.getenv("ANTHROPIC_APIKEY");
    if (apiKey == null || apiKey.isBlank()) throw new IllegalStateException("Set ANTHROPIC_API_KEY or ANTHROPIC_APIKEY to run this example.");
    AxAIService client = Ax.ai("anthropic", Map.of("api_key", apiKey, "model", "claude-sonnet-5-5"));
    Map<String, Object> response = client.chat(Map.of(
      "chat_prompt", List.of(Map.of("role", "user", "content", "Reply with exactly: Sonnet 5.5 works")),
      "model_config", Map.of("thinkingTokenBudget", "none", "effort", "high", "maxTokens", 128)
    ));
    List<?> results = (List<?>) response.get("results");
    System.out.println(((Map<?, ?>) results.get(0)).get("content"));
  }
}

Java Streaming Field Deltas

Streams AxGen output as TypeScript-style {version, index, delta} field deltas and merges them as they arrive.

Java
import dev.axllm.ax.*;
import java.util.*;

public final class StreamingForwardExample {
  public static void main(String[] args) {
    String apiKey = System.getenv("OPENAI_API_KEY");
    if (apiKey == null || apiKey.isBlank()) apiKey = System.getenv("OPENAI_APIKEY");
    if (apiKey == null || apiKey.isBlank()) throw new IllegalStateException("Set OPENAI_API_KEY or OPENAI_APIKEY to run this example.");
    AxAIService client = Ax.ai("openai", Map.of(
        "api_key", apiKey,
        "model", System.getenv().getOrDefault("AX_OPENAI_MODEL", "gpt-5.4-mini")));
    AxGen story = Ax.ax("topic:string -> title:string, story:string \"Three short sentences\"");

    // Each delta holds the new text of one field. Merge a sample's deltas
    // (strings append, other values replace) and start over when the version
    // changes: a retry or a replaced step starts a new version.
    Map<String, Object> merged = new LinkedHashMap<>();
    int version = 0;
    try (AxGenDeltaStream stream = story.streamingForward(client, Map.of("topic", "a lighthouse keeper's cat"), Map.of())) {
      for (AxGenDelta delta : stream) {
        if (delta.version() != version) {
          merged.clear();
          version = delta.version();
          System.out.println("\n[retry: starting over]");
        }
        delta.delta().forEach((field, value) -> {
          if (merged.get(field) instanceof String previous && value instanceof String text) merged.put(field, previous + text);
          else merged.put(field, value);
          if (field.equals("story")) System.out.print(value);
        });
      }
    }
    System.out.println();
    System.out.println("Title: " + merged.get("title"));
  }
}

Java Date Fields

Parses date, datetime and range outputs into ISO 8601 by default as TypeScript does, and passes a java.time value as an input.

Java
import dev.axllm.ax.*;
import java.time.Instant;
import java.util.*;

public final class DateFieldsExample {
  public static void main(String[] args) {
    String apiKey = System.getenv("OPENAI_API_KEY");
    if (apiKey == null || apiKey.isBlank()) apiKey = System.getenv("OPENAI_APIKEY");
    if (apiKey == null || apiKey.isBlank()) throw new IllegalStateException("Set OPENAI_API_KEY or OPENAI_APIKEY to run this example.");
    AxAIService client = Ax.ai("openai", Map.of(
        "api_key", apiKey,
        "model", System.getenv().getOrDefault("AX_OPENAI_MODEL", "gpt-6-luna")));

    // Date outputs parse by default; set parseDates (or parse_dates) to false to keep text.
    AxGen planner = new AxGen(
        AxSignature.create(
            "emailText:string, sentAt:datetime -> meetingStartsAt:datetime \"Start time with its time zone\", "
                + "meetingDay:date, travelWindow:dateRange \"First and last day away\""));
    Map<String, Object> out = planner.forward(client, Map.of(
        "emailText", "Can we meet next Tuesday at 3pm New York time? I'm travelling from the 8th to the 12th.",
        // A java.time value is rendered as TypeScript renders a Date.
        "sentAt", Instant.parse("2024-05-02T16:30:00Z")));
    System.out.println(out.get("meetingStartsAt")); // e.g. 2024-05-07T19:00:00.000Z
    System.out.println(out.get("meetingDay")); // e.g. 2024-05-07T00:00:00.000Z
    System.out.println(out.get("travelWindow")); // {start=2024-05-08T00:00:00.000Z, end=...}
  }
}

Java Field Processor Feedback

Sends a field processor’s note back to the model for another step, as TypeScript does, and trims the final answer with a field transform.

Java
import dev.axllm.ax.*;
import java.util.*;

public final class FieldProcessorsExample {
  public static void main(String[] args) {
    String apiKey = System.getenv("OPENAI_API_KEY");
    if (apiKey == null || apiKey.isBlank()) apiKey = System.getenv("OPENAI_APIKEY");
    if (apiKey == null || apiKey.isBlank()) throw new IllegalStateException("Set OPENAI_API_KEY or OPENAI_APIKEY to run this example.");
    AxAIService client = Ax.ai("openai", Map.of(
        "api_key", apiKey,
        "model", System.getenv().getOrDefault("AX_OPENAI_MODEL", "gpt-6-luna")));
    AxGen summarize = Ax.ax("text:string -> summary:string");

    // A non-null result goes back to the model as a user
    // message, and the next step's answer replaces this one.
    summarize.addFieldProcessor("summary", (value, context) -> {
      int words = String.valueOf(value).trim().split("\\s+").length;
      return words > 12 ? "That summary has " + words + " words; answer again in at most 12 words." : null;
    });
    summarize.addFieldTransform("summary", "trim");

    String text = "The committee met on Tuesday to review the budget. After a long debate about "
        + "the new library wing, they approved the plan and asked staff to find a builder "
        + "who can start in spring, while keeping the reading room open during the work.";
    System.out.println(summarize.forward(client, Map.of("text", text)).get("summary"));
  }
}

Java Haiku 5.5 Adaptive Thinking

Uses Haiku 5.5 adaptive thinking at low effort for a short response.

Java
import dev.axllm.ax.*;
import java.util.*;

public final class Haiku55Example {
  public static void main(String[] args) throws Exception {
    String apiKey = System.getenv("ANTHROPIC_API_KEY");
    if (apiKey == null || apiKey.isBlank()) apiKey = System.getenv("ANTHROPIC_APIKEY");
    if (apiKey == null || apiKey.isBlank()) throw new IllegalStateException("Set ANTHROPIC_API_KEY or ANTHROPIC_APIKEY to run this example.");
    AxAIService client = Ax.ai("anthropic", Map.of("api_key", apiKey, "model", "claude-haiku-5-5"));
    Map<String, Object> response = client.chat(Map.of(
      "chat_prompt", List.of(Map.of("role", "user", "content", "Reply with exactly: Haiku 5.5 works")),
      "model_config", Map.of("thinkingTokenBudget", "low", "showThoughts", false, "maxTokens", 2048)
    ));
    List<?> results = (List<?>) response.get("results");
    System.out.println(((Map<?, ?>) results.get(0)).get("content"));
  }
}

Java Tool Result Formatting

Formats a structured inventory tool result as concise text for the model.

Java
import dev.axllm.ax.*;
import java.util.Map;

public final class FunctionResultFormatterExample {
  public static void main(String[] args) {
    String key = System.getenv("OPENAI_API_KEY");
    if (key == null || key.isBlank()) key = System.getenv("OPENAI_APIKEY");
    if (key == null || key.isBlank()) throw new IllegalStateException("Set OPENAI_API_KEY or OPENAI_APIKEY.");
    var client = Ax.ai("openai", Map.of("api_key", key,
        "model", System.getenv().getOrDefault("AX_OPENAI_MODEL", "gpt-6-luna")));
    var inventory = Ax.fn("inventory").description("Read the current stock count.")
        .handler(values -> Map.of("available", 12, "warehouse", "A")).build();
    var program = Ax.ax("question:string -> answer:string").addTool(inventory);
    // The model receives this text; tool traces retain the original object.
    program.setFunctionResultFormatter(result -> ((Map<?, ?>) result).get("available") + " units available");
    var result = program.forward(client, Map.of("question", "Call inventory and report how many units are available."));
    System.out.println(result.get("answer"));
  }
}

Java Gemini Flex Inference

Sends latency-tolerant work through Gemini Flex and reports the applied tier.

Java
import dev.axllm.ax.*;
import java.util.*;

public final class GeminiServiceTierExample {
  private static String apiKey() {
    String value = System.getenv("GOOGLE_API_KEY");
    if (value == null || value.isBlank()) value = System.getenv("GOOGLE_APIKEY");
    if (value == null || value.isBlank()) {
      throw new IllegalStateException("Set GOOGLE_API_KEY or GOOGLE_APIKEY to run this example.");
    }
    return value;
  }

  public static void main(String[] args) throws Exception {
    GoogleGeminiClient client = new GoogleGeminiClient(Map.of(
        "api_key", apiKey(),
        "model", System.getenv().getOrDefault("AX_GEMINI_MODEL", "gemini-3.8-flash")));
    Map<String, Object> out = client.chat(Map.of(
        "chat_prompt", List.of(Map.of(
            "role", "user",
            "content", "Explain in one sentence why batch evaluations save time."))),
        Map.of("service_tier", "flex"));
    System.out.println(Json.stringify(out));
  }
}

Java Native File Routing

Summarizes a PDF through a provider router without replacing the native file with extracted text.

Java
import dev.axllm.ax.*;
import java.util.*;
public final class NativeFileRoutingExample {
 public static void main(String[] args) throws Exception {
  String key=System.getenv("OPENAI_API_KEY");if(key==null||key.isBlank())key=System.getenv("OPENAI_APIKEY");
  var client=Ax.ai("openai",Map.of("api_key",Objects.requireNonNull(key,"Set OPENAI_API_KEY or OPENAI_APIKEY"),"model","gpt-6-astra","model_config",Map.of("thinkingTokenBudget","low")));
  var router=new AxProviderRouter(Map.of("providers",Map.of("primary",client)));
  var program=Ax.ax("document:file -> summary:string");
  var result=program.forward(router,Map.of("document",Map.of("filename","report.pdf","mimeType","application/pdf","data",Objects.requireNonNull(System.getenv("AX_PDF_BASE64"),"Set AX_PDF_BASE64"))),Map.of("serviceTier","standard"));
  System.out.println(Json.stringify(result));
 }
}

Java Automatic Background Tools

Uses ordinary generation with background tools, steering, and a reasoning update.

Java
import dev.axllm.ax.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;

public final class AstraAsyncExample {
  public static void main(String[] args) throws Exception {
    String key=System.getenv("OPENAI_API_KEY");if(key==null||key.isBlank())key=System.getenv("OPENAI_APIKEY");if(key==null||key.isBlank())throw new IllegalArgumentException("Set OPENAI_API_KEY or OPENAI_APIKEY.");
    AiClient client=Ax.ai("openai",Map.of("api_key",key,"model","gpt-6-astra","model_config",Map.of("thinkingTokenBudget","low","max_tokens",4096)));
    CountDownLatch pending=new CountDownLatch(1);AtomicBoolean finished=new AtomicBoolean(),overlap=new AtomicBoolean(),steered=new AtomicBoolean();AtomicInteger applied=new AtomicInteger();
    AxRunControl control=Ax.runControl();control.onEvent(event->{if("applied".equals(event.get("type")))applied.incrementAndGet();});
    Tool slow=Ax.fn("slow_reference").description("Look up a reference; takes a few seconds.").execution("background").handler(values->{pending.countDown();if(steered.compareAndSet(false,true)){control.steer("Include the word VERIFIED in the final answer.");control.setThinkingTokenBudget("medium");}Thread.sleep(6000);finished.set(true);return "REF-42";}).build();
    Tool label=Ax.fn("local_label").description("Read an independent local label immediately.").handler(values->{if(pending.await(3,TimeUnit.SECONDS)&&!finished.get())overlap.set(true);return "LAUNCH";}).build();
    var program=Ax.ax("question -> answer").addTool(slow).addTool(label);
    var result=program.forward(client,Map.of("question","First call slow_reference. While it is pending, call local_label. Call each tool only once; do not call a tool again while its result is pending. If a required tool result is still pending, end this response with a brief progress message. The application will continue with the result when it arrives; do not spend reasoning tokens waiting for it. Once both results arrive, return them in one sentence."),Map.of("control",control,"serviceTier","standard","maxSteps",6));
    String answer=result.toString();for(String word:List.of("REF-42","LAUNCH","VERIFIED"))if(!answer.contains(word))throw new AssertionError("Missing final result: "+answer);
    if(!overlap.get())throw new AssertionError("No independent work while background tool was pending");if(applied.get()!=2)throw new AssertionError("Control updates were not applied");
    System.out.println(answer);System.out.println("Background overlap verified; steering and reasoning applied at the next response.");
  }
}

Java Cancel Background Work

Cancels a live Astra run through the high-level controller and observes cooperative tool cancellation.

Java
import dev.axllm.ax.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
public final class AstraCancellationExample {
 public static void main(String[] args)throws Exception {
  String key=System.getenv("OPENAI_API_KEY");if(key==null||key.isBlank())key=System.getenv("OPENAI_APIKEY");if(key==null||key.isBlank())throw new IllegalArgumentException("Set OPENAI_API_KEY or OPENAI_APIKEY.");
  var control=Ax.runControl();var settled=new CountDownLatch(1);var started=new AtomicLong();
  var lookup=Ax.fn("lookup").description("Look up the reference.").execution("background").contextHandler((values,cancelled)->{started.set(System.nanoTime());control.abort();long deadline=System.nanoTime()+TimeUnit.SECONDS.toNanos(2);try {while(!cancelled.getAsBoolean()&&System.nanoTime()<deadline)Thread.sleep(1);}catch(InterruptedException interrupted){Thread.currentThread().interrupt();}if(!cancelled.getAsBoolean())throw new IllegalStateException("Tool missed cancellation");settled.countDown();return "LATE: discard this result";}).build();
  var program=Ax.ax("question -> answer").addTool(lookup);
  var client=Ax.ai("openai",Map.of("api_key",key,"model","gpt-6-astra","model_config",Map.of("thinkingTokenBudget","low","max_tokens",2048)));
  try {program.forward(client,Map.of("question","Call lookup once and return its result."),Map.of("control",control,"serviceTier","standard"));throw new AssertionError("Cancelled run returned success");}
  catch(CancellationException error){long elapsed=System.nanoTime()-started.get();if(started.get()==0||!error.getMessage().contains("unresolved calls")||elapsed>TimeUnit.SECONDS.toNanos(2)||!settled.await(2,TimeUnit.SECONDS))throw new AssertionError("Cancellation failed",error);System.out.println("Cancelled in "+TimeUnit.NANOSECONDS.toMillis(elapsed)+"ms; "+error.getMessage());}
 }
}

Java Contextual Generation

Answers from supplied context and returns compact citations with OpenAI.

Java
import dev.axllm.ax.*;
import java.nio.file.*;
import java.util.*;

public final class ContextGenerationExample {
  static String apiKey() {
    String apiKey = System.getenv("OPENAI_API_KEY");
    if (apiKey == null || apiKey.isBlank()) apiKey = System.getenv("OPENAI_APIKEY");
    if (apiKey == null || apiKey.isBlank()) {
      throw new IllegalStateException("Set OPENAI_API_KEY or OPENAI_APIKEY to run this example.");
    }
    return apiKey;
  }

  static AxAIService client() {
    return Ax.ai("openai",
        Map.of("api_key", apiKey(), "model", System.getenv().getOrDefault("AX_OPENAI_MODEL", "gpt-5.4-mini"), "model_config", Map.of("temperature", 0.0)));
  }

  public static void main(String[] args) throws Exception {
    AxGen program = Ax.ax("context:string, question:string -> answer:string, citations:string[]");
    Map<String, Object> output = program.forward(client(), Map.of("context", "Ax uses signatures, ai(), ax(), agent(), flow(), and optimize().", "question", "How should a new developer think about Ax?"));
    System.out.println(Json.stringify(output));
  }
}

Java Jev Native Questions

Uses structured criteria, native scoring, model discovery, and probability-based decisions.

Java
import dev.axllm.ax.*;
import java.util.*;

public final class TypesafeNativeExample {
  public static void main(String[] args) throws Exception {
    var client = Ax.typesafe(Map.of("apiKey", System.getenv("TYPESAFE_APIKEY")));
    if (client.listModels().isEmpty()) throw new AssertionError("Empty model catalog");
    var account = new LinkedHashMap<String, Object>();
    account.put("tier", "enterprise");
    account.put("notes", null);
    var request = new AxAITypesafeClient.Request(
        Map.of("ticket", "Checkout is unavailable for all customers after the latest deployment.",
               "account", account),
        Map.of(
            "urgent", AxAITypesafeClient.Question.noul(
                Map.of("question", "Does this need immediate attention?"),
                Map.of("true", "Customers cannot complete a core task", "false", "Routine request")),
            "team", AxAITypesafeClient.Question.choice(
                "Who should handle the ticket?",
                Map.of("support", "Usage guidance",
                       "billing", Map.of("scope", "Invoices and payments"),
                       "engineering", "Product failures")),
            "severity", AxAITypesafeClient.Question.score(
                "Rate customer impact",
                List.of("Minor inconvenience", "One task blocked",
                        "Core task unavailable", "Widespread outage"))));
    var response = client.systemOne(request);
    double probability = ((AxAITypesafeClient.Noul) response.answers().get("urgent")).noul();
    double score = ((AxAITypesafeClient.Score) response.answers().get("severity")).score();
    if (probability < 0 || probability > 1 || score < 0 || score > 3) throw new AssertionError("Invalid answer bounds");
    // Apply thresholds and custom score scales in application code.
    System.out.println(Json.stringify(Map.of("page_on_call", probability >= 0.9, "severity_1_to_5", 1 + 4 * score / 3, "response", response.toMap())));
  }
}

Java Adaptive Provider Balancing

Routes equivalent chat traffic using shared reliability, latency, and cost statistics.

Java
import dev.axllm.ax.*;
import java.util.*;

public final class AdaptiveBalancerExample {
  static String requiredKey() {
    String value = System.getenv("OPENAI_API_KEY");
    if (value == null || value.isBlank()) value = System.getenv("OPENAI_APIKEY");
    if (value == null || value.isBlank()) throw new IllegalStateException("Set OPENAI_API_KEY or OPENAI_APIKEY to run this example.");
    return value;
  }

  public static void main(String[] args) throws Exception {
    String key = requiredKey();
    String model = System.getenv().getOrDefault("AX_OPENAI_MODEL", "gpt-5.4-mini");
    List<AxAIService> services = List.of(
        new OpenAICompatibleClient(Map.of("api_key", key, "model", model, "base_url", System.getenv().getOrDefault("OPENAI_PRIMARY_BASE_URL", "https://api.openai.com/v1"))),
        new OpenAICompatibleClient(Map.of("api_key", System.getenv().getOrDefault("OPENAI_BACKUP_API_KEY", key), "model", model, "base_url", System.getenv().getOrDefault("OPENAI_BACKUP_BASE_URL", "https://api.openai.com/v1"))));

    var store = new AxInMemoryBalancerStatsStore();
    List<String> routeKeys = List.of("openai-primary", "openai-backup");
    List<String> events = new ArrayList<>();
    var strategy = new AxBalancerAdaptiveStrategy(6_000, 0.02)
        .expectedTokens(1_200, 300)
        .namespace("support-summary-v1")
        .routeKey((service, index) -> routeKeys.get(index))
        .slice(context -> context.get("options") instanceof Map<?, ?> options && Boolean.TRUE.equals(options.get("stream")) ? "streaming" : "interactive")
        .statsStore(store)
        .onRoutingEvent(event -> events.add(event.type()));
    AxBalancer balancer = new AxBalancer(services, new AxBalancerOptions().strategy(strategy));
    Map<String, Object> response = balancer.chat(Map.of("model", model, "chat_prompt", List.of(Map.of("role", "user", "content", "Summarize why shared routing state matters."))));
    System.out.println(Json.stringify(response));
    System.out.println(events);
  }
}

Java OpenAI Native Decisions

Uses ordered predicate, choice, and score questions with explicit rubrics and raw probabilities.

Java
import dev.axllm.ax.*;
import java.util.*;
public final class OpenAIDecisionsNativeExample {
 public static void main(String[] args) throws Exception {
  var client = Ax.openaiDecisions(Map.of("apiKey", Optional.ofNullable(System.getenv("OPENAI_API_KEY")).orElse(System.getenv("OPENAI_APIKEY"))));
  var request = (Map<String, Object>) Json.parse("""
{"input": "Checkout is unavailable for all customers after the latest deployment.", "questions": [{"type": "predicate", "name": "urgent", "instructions": "Are customers unable to complete a core task?"}, {"type": "choice", "name": "team", "instructions": "Who should handle the ticket?", "choices": [{"value": "support", "description": "Usage guidance"}, {"value": "billing", "description": "Invoices and payments"}, {"value": "engineering", "description": "Product failures"}]}, {"type": "score", "name": "severity", "instructions": "Rate customer impact", "levels": [{"label": "Minor inconvenience"}, {"label": "One task blocked"}, {"label": "Core task unavailable"}, {"label": "Widespread outage"}]}]}
""");
  var response = client.create(request);
  // Handle per-question refusals before using probability, choice, or score.
  if (((List<?>) response.get("answers")).size() != 3) throw new AssertionError("Missing answers");
  System.out.println(Json.stringify(response));
 }
}

Portable Runtime Hooks

Applies global and forward-scoped rate limiting, tracing, and metrics to AxGen, AxAgent, and AxFlow.

Java
import dev.axllm.ax.*;
import dev.axllm.ax.runtime.quickjs.*;
import java.util.*;

public final class RuntimeHooksExample {
  static final class LogSpan implements AxSpan {
    private final String name;
    LogSpan(String name) { this.name = name; System.out.println("[span:start] " + name); }
    public void setAttributes(Map<String, Object> attributes) {}
    public void addEvent(String event, Map<String, Object> attributes) { System.out.println("[span:event] " + name + " " + event); }
    public void recordException(Throwable error) { System.out.println("[span:error] " + name + " " + error); }
    public void setStatus(String status, String description) {}
    public void end() { System.out.println("[span:end] " + name); }
  }

  static final class LogMeter implements AxMeter {
    public AxCounter createCounter(String name, AxMetricInstrumentOptions options) {
      return (value, attributes) -> System.out.println("[metric] " + name + " += " + value);
    }
    public AxHistogram createHistogram(String name, AxMetricInstrumentOptions options) {
      return (value, attributes) -> System.out.println("[metric] " + name + " = " + value);
    }
    public AxGauge createGauge(String name, AxMetricInstrumentOptions options) {
      return (value, attributes) -> System.out.println("[metric] " + name + " = " + value);
    }
  }

  static AxRateLimiter limiter(String label) {
    return (next, info) -> {
      System.out.printf("[limit:%s] %s %s/%s stream=%s%n", label, info.operation(), info.provider(), info.model(), info.streaming());
      return next.execute();
    };
  }

  public static void main(String[] args) throws Exception {
    String apiKey = System.getenv("OPENAI_API_KEY");
    if (apiKey == null || apiKey.isBlank()) apiKey = System.getenv("OPENAI_APIKEY");
    if (apiKey == null || apiKey.isBlank()) throw new IllegalStateException("Set OPENAI_API_KEY or OPENAI_APIKEY to run this example.");
    AxAIService client = Ax.ai("openai", Map.of(
        "api_key", apiKey,
        "model", System.getenv().getOrDefault("AX_OPENAI_MODEL", "gpt-5.4-mini"),
        "model_config", Map.of("temperature", 0.0)));
    AxTracer tracer = start -> new LogSpan(start.name());
    AxMeter meter = new LogMeter();
    AxRuntimeHooks overrideHooks = new AxRuntimeHooks(limiter("forward"), tracer, meter);

    AxGlobals.setRateLimiter(limiter("global"));
    AxGlobals.setTracer(tracer);
    AxGlobals.setMeter(meter);
    try {
      System.out.println(Ax.ax("topic:string -> summary:string").forward(client, Map.of("topic", "portable Ax runtime hooks")));
      AxAgent helper = Ax.agent("question:string -> answer:string", Map.of());
      try (AxQuickJsCodeRuntime runtime = new AxQuickJsCodeRuntime()) {
        System.out.println(helper.forward(client, Map.of("question", "What does a rate limiter wrap?"), Map.of("runtime", runtime, "max_actor_steps", 12), overrideHooks));
      }
      AxFlow workflow = Ax.flow(Map.of("id", "examples.runtimeHooks"))
          .execute("outline", Ax.ax("topic:string -> outline:string"))
          .execute("polish", Ax.ax("outline:string -> answer:string"))
          .returns(Map.of("answer", "answer"));
      Map<String, Object> result = workflow.forward(client, Map.of("topic", "Ax runtime hooks"), Map.of(), overrideHooks);
      for (String key : List.of("answer")) {
        if (List.of("null", "\"\"", "[]").contains(Json.stringify(result.get(key)))) {
          throw new AssertionError("flow output field " + key + " is empty: " + Json.stringify(result));
        }
      }
      System.out.println(Json.stringify(result));
    } finally {
      AxGlobals.setRateLimiter(null);
      AxGlobals.setTracer(null);
      AxGlobals.setMeter(null);
    }
  }
}
Docs