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 Grounded Support Agent
Answers a support question grounded in a handbook that is kept out of the model prompt via contextFields.
- Provider:
openai - Env:
OPENAI_API_KEY,OPENAI_APIKEY - Level:
beginner - Run:
npm run example -- java src/examples/java/short-agents/BasicAgentExample.java - Source: src/examples/java/short-agents/BasicAgentExample.java
import dev.axllm.ax.*;
import dev.axllm.ax.runtime.quickjs.*;
import java.util.*;
public final class BasicAgentExample {
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 OpenAICompatibleClient client() {
return new OpenAICompatibleClient(Map.of(
"api_key", apiKey(),
"model", System.getenv().getOrDefault("AX_OPENAI_MODEL", "gpt-5.4-mini"),
"model_config", Map.of("temperature", 0.0)));
}
// The handbook can be arbitrarily large. Listing it in `contextFields` keeps it
// in the agent's runtime so it never inflates the model prompt -- the agent reads
// it through code, not through tokens. That is the whole point of an Ax agent
// over a plain gen() call: the source material stays out of the context window.
static final String HANDBOOK = String.join("\n",
"# Acme Cloud -- Support Handbook",
"",
"## Billing",
"- Invoices are issued on the 1st of each month and are due net-15.",
"- Plan downgrades take effect at the END of the current billing cycle, not immediately.",
"- Refunds are issued to the original payment method within 5 business days.",
"",
"## Access",
"- Seats can be added by any workspace Owner under Settings -> Members.",
"- SSO (SAML) is available on Enterprise; SCIM provisioning is Owner-only.",
"",
"## Incidents",
"- Status and uptime are published at status.acme.example.",
"- Sev-1 incidents page the on-call within 5 minutes; updates post every 30 minutes.",
"",
"## Data",
"- Exports are available in CSV and JSON from Settings -> Data.",
"- Deleted workspaces are recoverable for 30 days, then permanently purged.");
public static void main(String[] args) throws Exception {
AxAgent assistant = Ax.agent(
"question:string, handbook:string -> answer:string, citations:string[] \"Handbook sections the answer relies on\"",
// Keep the handbook in the runtime, out of the prompt.
Map.of("contextFields", List.of("handbook"), "runtime", Map.of("language", "JavaScript")));
try (AxQuickJsCodeRuntime runtime = new AxQuickJsCodeRuntime()) {
Map<String, Object> result = assistant.forward(
client(),
Map.of(
"question", "A customer downgraded their plan today. When does it take effect, and can they get a refund for the current cycle?",
"handbook", HANDBOOK),
Map.of("runtime", runtime, "max_actor_steps", 12));
System.out.println(Json.pretty(result));
}
}
}Java Incident Triage Agent
Triages a noisy incident report held in contextFields, using a lean contextPolicy to keep the raw log out of the prompt while it reasons.
- Provider:
openai - Env:
OPENAI_API_KEY,OPENAI_APIKEY - Level:
intermediate - Run:
npm run example -- java src/examples/java/short-agents/ToolsAgentExample.java - Source: src/examples/java/short-agents/ToolsAgentExample.java
import dev.axllm.ax.*;
import dev.axllm.ax.runtime.quickjs.*;
import java.util.*;
public final class ToolsAgentExample {
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 OpenAICompatibleClient client() {
return new OpenAICompatibleClient(Map.of(
"api_key", apiKey(),
"model", System.getenv().getOrDefault("AX_OPENAI_MODEL", "gpt-5.4-mini"),
"model_config", Map.of("temperature", 0.0)));
}
// A raw, noisy incident report. It lives in `contextFields`, so the agent works
// it inside the runtime; `contextPolicy: lean` keeps the prompt compact by
// preferring live runtime state and summaries over replaying the raw text.
static final String REPORT = String.join("\n",
"[2026-03-02 14:01:22Z] INFO gateway deploy svc-checkout-edge v812 -> prod (channel: canary 10%)",
"[2026-03-02 14:03:10Z] WARN checkout-api p95 latency 1180ms (baseline 240ms) region=eu-west-1",
"[2026-03-02 14:04:55Z] ERROR checkout-api 502 from svc-payments-gw: upstream timeout (10s) tenant_tier=enterprise",
"[2026-03-02 14:05:01Z] ERROR checkout-api 502 from svc-payments-gw: upstream timeout (10s) tenant_tier=enterprise",
"[2026-03-02 14:05:40Z] WARN payments-gw circuit half-open, 3 retries exhausted for order=ord_99214",
"[2026-03-02 14:06:12Z] INFO gateway canary widened 10% -> 50% for svc-checkout-edge v812",
"[2026-03-02 14:07:33Z] ERROR checkout-api 502 from svc-payments-gw: upstream timeout (10s) tenant_tier=enterprise",
"[2026-03-02 14:08:02Z] ERROR checkout-api user-visible: \"Payment could not be processed\" shown to 1,284 sessions",
"[2026-03-02 14:09:48Z] WARN payments-gw connection pool exhausted (max=64) waiting=210",
"[2026-03-02 14:11:20Z] INFO on-call paged: SEV-2 opened (eu-west-1 checkout error rate 38%)",
"[2026-03-02 14:14:05Z] INFO gateway rollback svc-checkout-edge v812 -> v811 (channel: prod 100%)",
"[2026-03-02 14:17:41Z] INFO checkout-api p95 latency 260ms, error rate 0.4% region=eu-west-1",
"[2026-03-02 14:19:10Z] INFO on-call SEV-2 mitigated, monitoring for 30m");
public static void main(String[] args) throws Exception {
AxAgent triage = Ax.agent(
"report:string, question:string -> severity:class \"low, medium, high, critical\", rootCause:string, nextSteps:string[], evidence:string[] \"Quoted log lines that support the assessment\"",
Map.of(
"contextFields", List.of("report"),
"contextPolicy", Map.of("preset", "lean", "budget", "balanced"),
"runtime", Map.of("language", "JavaScript")));
try (AxQuickJsCodeRuntime runtime = new AxQuickJsCodeRuntime()) {
Map<String, Object> result = triage.forward(
client(),
Map.of(
"report", REPORT,
"question", "What happened, how bad was it, and what should the on-call do next? Cite the lines you relied on."),
Map.of("runtime", runtime, "max_actor_steps", 12));
System.out.println(Json.pretty(result));
}
}
}Java Specialist Planner Agent
A specialist that plans a migration from a long brief held in contextFields, using a checkpointed contextPolicy and a runtime-output cap to stay compact.
- Provider:
openai - Env:
OPENAI_API_KEY,OPENAI_APIKEY - Level:
advanced - Run:
npm run example -- java src/examples/java/short-agents/HandoffAgentExample.java - Source: src/examples/java/short-agents/HandoffAgentExample.java
import dev.axllm.ax.*;
import dev.axllm.ax.runtime.quickjs.*;
import java.util.*;
public final class HandoffAgentExample {
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 OpenAICompatibleClient client() {
return new OpenAICompatibleClient(Map.of(
"api_key", apiKey(),
"model", System.getenv().getOrDefault("AX_OPENAI_MODEL", "gpt-5.4-mini"),
"model_config", Map.of("temperature", 0.0)));
}
// A long, messy brief -- exactly the kind of input you do not want replayed into
// the prompt on every turn. `contextFields` holds it in the runtime, the
// `checkpointed` policy compacts older turns once the prompt grows, and
// `maxRuntimeChars` caps how much runtime output is echoed back.
static final String BRIEF = String.join("\n",
"# Migration brief: monolith -> services (draft, unordered notes)",
"",
"Current: single Rails monolith, Postgres primary + 1 replica, Sidekiq for jobs.",
"Pain: deploys take 40m, one bad migration locks the orders table, on-call burnout.",
"Constraints: no downtime windows > 5m, PCI scope must shrink, team of 6, 2 quarters.",
"Hot paths: checkout (writes orders, payments), search (read-heavy), notifications (async).",
"Known landmines: payments code has no tests; search shares the orders DB; a nightly",
"cron rebuilds the catalog and pins CPU for ~20m; the replica lags up to 90s under load.",
"Org wants: independent deploys for checkout, smaller blast radius, an audit trail.",
"Nice to have: event log for orders, read-model for search, feature flags.",
"Hard no: a big-bang rewrite; introducing Kubernetes this year.");
public static void main(String[] args) throws Exception {
AxAgent specialist = Ax.agent(
"brief:string, goal:string -> plan:string[] \"Ordered, concrete steps\", answer:string, risks:string[]",
Map.of(
"contextFields", List.of("brief"),
"contextPolicy", Map.of("preset", "checkpointed", "budget", "balanced"),
"maxRuntimeChars", 3000,
"runtime", Map.of("language", "JavaScript")));
try (AxQuickJsCodeRuntime runtime = new AxQuickJsCodeRuntime()) {
Map<String, Object> result = specialist.forward(
client(),
Map.of(
"brief", BRIEF,
"goal", "Propose a safe, incremental 2-quarter plan to split checkout out first, respecting the hard constraints."),
Map.of("runtime", runtime, "max_actor_steps", 12));
System.out.println(Json.pretty(result));
}
}
}Java Multi-Model Panel
Fans one question across three providers (OpenAI, Gemini, Anthropic), then judges the candidates and synthesizes a single grounded answer.
- Provider:
openai - Env:
OPENAI_API_KEY,OPENAI_APIKEY,GOOGLE_APIKEY,ANTHROPIC_APIKEY - Level:
advanced - Run:
npm run example -- java src/examples/java/short-agents/ModelPanelExample.java - Source: src/examples/java/short-agents/ModelPanelExample.java
import dev.axllm.ax.*;
import java.util.*;
public final class ModelPanelExample {
static String firstNonBlank(String... values) {
for (String value : values) {
if (value != null && !value.isBlank()) return value;
}
return null;
}
public static void main(String[] args) throws Exception {
String openaiKey = firstNonBlank(System.getenv("OPENAI_API_KEY"), System.getenv("OPENAI_APIKEY"));
String googleKey = firstNonBlank(System.getenv("GOOGLE_APIKEY"), System.getenv("GOOGLE_API_KEY"));
String anthropicKey = firstNonBlank(System.getenv("ANTHROPIC_APIKEY"), System.getenv("ANTHROPIC_API_KEY"));
if (openaiKey == null || googleKey == null || anthropicKey == null) {
throw new IllegalStateException(
"Set OPENAI_APIKEY, GOOGLE_APIKEY, and ANTHROPIC_APIKEY to run this multi-provider panel.");
}
// A panel of three different providers, each answering the same question
// independently. Plain ax() composition (no agent runtime): fan out to the
// panel, judge the candidates, then synthesize one grounded answer.
List<String> panelModels = List.of(
"openai/gpt-5.4-mini",
"google/gemini-3.5-flash",
"anthropic/claude-haiku-4.5");
List<AiClient> panelClients = List.of(
new OpenAICompatibleClient(Map.of(
"api_key", openaiKey, "model", "gpt-5.4-mini", "model_config", Map.of("temperature", 0.0))),
new GoogleGeminiClient(Map.of(
"api_key", googleKey, "model", "gemini-3.5-flash")),
new AnthropicClient(Map.of(
"api_key", anthropicKey, "model", "claude-haiku-4-5")));
AxGen researcher = Ax.ax(
"question:string -> answer:string, keyFindings:string[], citations:string[], confidence:number");
researcher.setInstruction(
"Answer independently. Use evidence. Call out uncertainty. Do not optimize for consensus.");
AxGen judge = Ax.ax(
"question:string, candidates:json -> consensus:string[], contradictions:string[], uniqueInsights:string[], blindSpots:string[]");
judge.setInstruction(
"Compare the candidates. Find agreement, conflicts, missing coverage, and unique useful points.");
AxGen synthesizer = Ax.ax(
"question:string, candidates:json, review:json -> answer:string, citations:string[], caveats:string[]");
synthesizer.setInstruction(
"Write one final answer grounded in the candidates and review. Resolve conflicts explicitly.");
String question = "What are the strongest arguments for and against a national carbon tax?";
List<Object> candidates = new ArrayList<>();
for (int i = 0; i < panelClients.size(); i++) {
Map<String, Object> response = researcher.forward(panelClients.get(i), Map.of("question", question));
Map<String, Object> candidate = new LinkedHashMap<>();
candidate.put("model", panelModels.get(i));
candidate.putAll(response);
candidates.add(candidate);
System.out.println("[panel] " + panelModels.get(i) + " responded.");
}
// The judge + synthesizer run on one of the panel clients (OpenAI here).
AiClient orchestrator = panelClients.get(0);
Map<String, Object> review = judge.forward(orchestrator, Map.of("question", question, "candidates", candidates));
Map<String, Object> finalAnswer = synthesizer.forward(
orchestrator, Map.of("question", question, "candidates", candidates, "review", review));
System.out.println(Json.pretty(finalAnswer));
}
}