Java SDK
Write JamJet workflows and agents in Java using builders, records, and the @Tool annotation.
Java SDK
The JamJet Java SDK lets you write workflows, agents, and tools in Java. It compiles to the same canonical IR and runs on the same Rust runtime as the Python SDK.
Installation
Requires Java 21+ (virtual threads).
<dependency>
<groupId>dev.jamjet</groupId>
<artifactId>jamjet-sdk</artifactId>
<version>0.1.0</version>
</dependency>Quick start
import dev.jamjet.agent.Agent;
import dev.jamjet.ir.IrValidator;
var agent = Agent.builder("hello-agent")
.model("claude-haiku-4-5-20251001")
.instructions("Answer questions clearly and concisely.")
.strategy("react")
.maxIterations(1)
.build();
var ir = agent.compile();
IrValidator.validateOrThrow(ir);
var result = agent.run("What is JamJet?");
System.out.println(result.output());Workflows
Build directed acyclic workflows with typed state. State is a Java record — immutable, validated, serializable.
import dev.jamjet.workflow.Workflow;
record ResearchState(String query, String results, String answer) {}
var wf = Workflow.builder("research-flow")
.version("0.1.0")
.state(ResearchState.class)
.step("search", state ->
new ResearchState(state.query(), "[search results]", state.answer()))
.step("synthesize", state ->
new ResearchState(state.query(), state.results(), "Final answer: ..."))
.build();
var result = wf.run(new ResearchState("Latest AI frameworks?", "", ""));
System.out.println(result.state().answer());
System.out.printf("Ran %d steps in %.1fms%n",
result.stepsExecuted(), result.totalDurationUs() / 1000.0);Conditional routing
import dev.jamjet.workflow.Step;
var route = Step.builder("route")
.handler(state -> state)
.when("approved", state -> state.approved())
.when("rejected", state -> !state.approved())
.defaultNext("escalate")
.timeout("30s")
.retryPolicy("exponential")
.build();Compiling to IR
Every workflow compiles to canonical IR for submission to the runtime:
var ir = wf.compile();
System.out.println(ir.toJson());
// Validate before submission
var errors = IrValidator.validate(ir);
errors.forEach(System.err::println);Agents
Agents combine a model, tools, and a reasoning strategy. Three built-in strategies:
| Strategy | Behavior |
|---|---|
react | Thought → tool use → observation loop |
plan-and-execute | Plan → execute steps → synthesize |
critic | Draft → criticize → revise loop |
import dev.jamjet.agent.Agent;
var agent = Agent.builder("research-agent")
.model("claude-sonnet-4-6")
.tools(WebSearch.class, FetchPage.class)
.instructions("You are a thorough researcher.")
.strategy("plan-and-execute")
.maxIterations(8)
.maxCostUsd(0.50)
.timeoutSeconds(300)
.build();
var result = agent.run("Compare JamJet and LangGraph");
System.out.println(result.output());
System.out.printf("Duration: %.1fms%n", result.durationUs() / 1000.0);Annotation-based agents
For simple agents, use the @Task annotation on an interface:
import dev.jamjet.agent.JamjetAgent;
import dev.jamjet.agent.Task;
@Task(
model = "gpt-4o",
tools = { WebSearch.class },
strategy = "react",
maxIterations = 5,
instructions = "You are helpful.",
maxCostUsd = 1.0
)
interface ResearchTask {
String research(String topic);
}
// Run directly
String result = JamjetAgent.run(ResearchTask.class, "What is JamJet?");
// Or get a reusable proxy
ResearchTask task = JamjetAgent.proxy(ResearchTask.class);
String answer = task.research("What is JamJet?");Tools
Tools are Java records annotated with @Tool that implement ToolCall<T>. The SDK auto-generates JSON Schema from record component types.
import dev.jamjet.tool.Tool;
import dev.jamjet.tool.ToolCall;
@Tool(description = "Search the web for information")
record WebSearch(String query) implements ToolCall<String> {
@Override
public String execute() {
// Replace with real implementation
return "Results for: " + query;
}
}
@Tool(description = "Fetch page content from a URL")
record FetchPage(String url) implements ToolCall<String> {
@Override
public String execute() {
return "Page content for " + url;
}
}Tool registry
import dev.jamjet.tool.ToolRegistry;
// Register globally
ToolRegistry.global()
.register(WebSearch.class)
.register(FetchPage.class);
// Query
ToolRegistry.global().names(); // ["web_search", "fetch_page"]
ToolRegistry.global().toOpenAiFormat(); // OpenAI function-calling schemaTool names are derived from the record class name (WebSearch → web_search).
Runtime client
JamjetClient is a blocking HTTP client (uses virtual threads) for the JamJet runtime API.
import dev.jamjet.JamjetClient;
import dev.jamjet.client.ClientConfig;
var client = new JamjetClient(
ClientConfig.builder()
.baseUrl("http://localhost:7700")
.apiToken("YOUR_TOKEN") // or JAMJET_TOKEN env var
.timeoutSeconds(30)
.build()
);Workflow lifecycle
// Register workflow
client.createWorkflow(ir.toMap());
// Start execution
var execId = client.startExecution("research-flow", Map.of("query", "..."));
// Poll for status
var status = client.getExecution(execId);
System.out.println(status.get("status")); // running | completed | failed
// Get event timeline
var events = client.getEvents(execId);Human-in-the-loop
// Approve a paused execution
client.approve(execId, "approved", "Looks good", Map.of("priority", "high"));
// Send external event to wake a waiting execution
client.sendExternalEvent(execId, "payment-received", Map.of("amount", 500));Agent management
// Register agent
client.registerAgent(agentCard);
// Discovery
client.discoverAgent("https://remote-agent.example.com");
// Lifecycle
client.activateAgent(agentId);
client.deactivateAgent(agentId);
// List with filters
client.listAgents(); // all agentsState management
State is a Java record. Steps receive the current state and return a new instance — state is always immutable.
record OrderState(
String orderId,
double amount,
boolean approved,
String result
) {}
// Steps return new state instances
.step("validate", state ->
new OrderState(state.orderId(), state.amount(), state.amount() < 10000, state.result()))tip: Java records give you immutability, equals/hashCode, and toString for free. The SDK auto-generates JSON Schema from record component types for IR validation.
IR compilation and validation
Both workflows and agents compile to WorkflowIr — the canonical intermediate representation shared with the Python SDK and YAML workflows.
import dev.jamjet.ir.IrCompiler;
import dev.jamjet.ir.IrValidator;
// Compile
var ir = IrCompiler.compileWorkflow(wf);
// or: var ir = IrCompiler.compileAgent(agent);
// Inspect
System.out.println(ir.id()); // workflow name
System.out.println(ir.version()); // version string
System.out.println(ir.nodes()); // node definitions
System.out.println(ir.toJson()); // canonical JSON
// Validate
var errors = IrValidator.validate(ir);
if (!errors.isEmpty()) {
errors.forEach(System.err::println);
System.exit(1);
}
// Or throw on first error
IrValidator.validateOrThrow(ir);Evaluation
Test agents and workflows against datasets with pluggable scorers:
import dev.jamjet.eval.EvalRunner;
import dev.jamjet.eval.Scorer;
var results = EvalRunner.builder()
.dataset(dataset)
.agent(myAgent)
.scorers(new Scorer.ExactMatchScorer("expected"))
.parallelism(4)
.failBelow(0.8) // fail if mean score < 0.8
.build()
.run();Python vs Java comparison
| Feature | Java SDK | Python SDK |
|---|---|---|
| Workflow definition | Fluent builder + records | Decorators + TypedDict |
| Tool definition | @Tool record + ToolCall<T> | @tool decorator / MCP |
| Agent definition | Agent.builder() | @agent decorator |
| State | Immutable Java records | TypedDict / Pydantic |
| HTTP client | Blocking (virtual threads) | Async (asyncio) |
| IR compilation | workflow.compile() | @workflow decorator |
| Minimum version | Java 21 | Python 3.10 |
Both compile to identical canonical IR and run on the same Rust runtime.
Examples
Working examples in the examples repository:
| Example | What it demonstrates |
|---|---|
java-hello-agent | Minimal agent with a single model call |
java-research-agent | Tools + plan-and-execute strategy |
java-support-bot | Multi-step workflow with conditional routing |
java-approval-workflow | Runtime integration + human-in-the-loop |
java-multi-tenant | Tenant-isolated workflow execution |
java-data-governance | PII detection and redaction patterns |
java-oauth-agent | OAuth delegation + scope narrowing |
git clone https://github.com/jamjet-labs/examples
cd examples/java-hello-agent
mvn compile exec:javatip: Every Java example has a Python/YAML equivalent in the same repository.