JamJet

Java SDK

Schreiben Sie JamJet-Workflows und Agents in Java mit Builders, Records und der @Tool-Annotation.

Java SDK

Das JamJet Java SDK ermöglicht es dir, Workflows, Agents und Tools in Java zu schreiben. Es kompiliert zur selben kanonischen IR und läuft auf derselben Rust-Runtime wie das Python SDK.

Installation

Erfordert Java 21+ (Virtual Threads).

<dependency>
    <groupId>dev.jamjet</groupId>
    <artifactId>jamjet-sdk</artifactId>
    <version>0.1.0</version>
</dependency>

Schnellstart

import dev.jamjet.agent.Agent;
import dev.jamjet.ir.IrValidator;

var agent = Agent.builder("hello-agent")
    .model("claude-haiku-4-5-20251001")
    .instructions("Beantworte Fragen klar und prägnant.")
    .strategy("react")
    .maxIterations(1)
    .build();

var ir = agent.compile();
IrValidator.validateOrThrow(ir);

var result = agent.run("Was ist JamJet?");
System.out.println(result.output());

Workflows

Erstelle gerichtete azyklische Workflows mit typisiertem State. State ist ein Java-Record – unveränderlich, validiert, serialisierbar.

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(), "[Suchergebnisse]", state.answer()))
    .step("synthesize", state ->
        new ResearchState(state.query(), state.results(), "Finale Antwort: ..."))
    .build();

var result = wf.run(new ResearchState("Neueste AI-Frameworks?", "", ""));
System.out.println(result.state().answer());
System.out.printf("Führte %d Schritte in %.1fms aus%n",
    result.stepsExecuted(), result.totalDurationUs() / 1000.0);

Bedingte Routing-Logik

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();

Kompilierung zu IR

Jeder Workflow kompiliert zu kanonischer IR für die Übergabe an die Runtime:

var ir = wf.compile();
System.out.println(ir.toJson());

// Vor der Übergabe validieren
var errors = IrValidator.validate(ir);
errors.forEach(System.err::println);

Agents

Agents kombinieren ein Modell, Tools und eine Reasoning-Strategie. Drei integrierte Strategien:

StrategieVerhalten
reactGedanke → Tool-Nutzung → Beobachtungsschleife
plan-and-executePlanen → Schritte ausführen → Synthetisieren
criticEntwurf → Kritik → Überarbeitungsschleife
import dev.jamjet.agent.Agent;

var agent = Agent.builder("research-agent")
    .model("claude-sonnet-4-6")
    .tools(WebSearch.class, FetchPage.class)
    .instructions("Du bist ein gründlicher Researcher.")
    .strategy("plan-and-execute")
    .maxIterations(8)
    .maxCostUsd(0.50)
    .timeoutSeconds(300)
    .build();

var result = agent.run("Vergleiche JamJet und LangGraph");
System.out.println(result.output());
System.out.printf("Dauer: %.1fms%n", result.durationUs() / 1000.0);

Annotationsbasierte Agents

Für einfache Agents verwenden Sie die @Task-Annotation auf einem 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);
}

// Direkt ausführen
String result = JamjetAgent.run(ResearchTask.class, "Was ist JamJet?");

// Oder einen wiederverwendbaren Proxy erhalten
ResearchTask task = JamjetAgent.proxy(ResearchTask.class);
String answer = task.research("Was ist JamJet?");

Tools

Tools sind Java-Records, die mit @Tool annotiert sind und ToolCall<T> implementieren. Das SDK generiert automatisch JSON Schema aus den Record-Komponententypen.

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() {
        // Mit echter Implementierung ersetzen
        return "Ergebnisse für: " + query;
    }
}

@Tool(description = "Fetch page content from a URL")
record FetchPage(String url) implements ToolCall<String> {
    @Override
    public String execute() {
        return "Seiteninhalt für " + url;
    }
}

Tool-Registry

import dev.jamjet.tool.ToolRegistry;

// Global registrieren
ToolRegistry.global()
    .register(WebSearch.class)
    .register(FetchPage.class);

// Abfragen
ToolRegistry.global().names();          // ["web_search", "fetch_page"]
ToolRegistry.global().toOpenAiFormat(); // OpenAI Function-Calling-Schema

Tool-Namen werden vom Record-Klassennamen abgeleitet (WebSearchweb_search).


Runtime-Client

Der JamjetClient ist ein blockierender HTTP-Client (verwendet Virtual Threads) für die 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")  // oder JAMJET_TOKEN Umgebungsvariable
        .timeoutSeconds(30)
        .build()
);

Workflow-Lebenszyklus

// Workflow registrieren
client.createWorkflow(ir.toMap());

// Ausführung starten
var execId = client.startExecution("research-flow", Map.of("query", "..."));

// Status abfragen
var status = client.getExecution(execId);
System.out.println(status.get("status")); // running | completed | failed

// Event-Timeline abrufen
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-Verwaltung

// 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 agents

State-Management

State ist ein Java Record. Steps erhalten den aktuellen State und geben eine neue Instanz zurück — State ist immer unveränderlich.

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 bieten dir Unveränderlichkeit, equals/hashCode und toString kostenlos. Das SDK generiert automatisch JSON Schema aus Record-Komponenten-Typen für IR-Validierung.


IR-Kompilierung und Validierung

Sowohl Workflows als auch Agents kompilieren zu WorkflowIr — der kanonischen Zwischendarstellung, die mit dem Python SDK und YAML-Workflows geteilt wird.

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

Teste Agents und Workflows gegen Datensätze mit austauschbaren Scorern:

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 Vergleich

FeatureJava SDKPython SDK
Workflow-DefinitionFluent Builder + RecordsDecorators + TypedDict
Tool-Definition@Tool Record + ToolCall<T>@tool Decorator / MCP
Agent-DefinitionAgent.builder()@agent Decorator
StateUnveränderliche Java RecordsTypedDict / Pydantic
HTTP-ClientBlockierend (virtuelle Threads)Asynchron (asyncio)
IR-Kompilierungworkflow.compile()@workflow Decorator
MindestversionJava 21Python 3.10

Beide kompilieren zu identischer kanonischer IR und laufen auf derselben Rust-Runtime.


Beispiele

Funktionierende Beispiele im Examples-Repository:

BeispielWas es zeigt
java-hello-agentMinimaler Agent mit einem einzigen Modellaufruf
java-research-agentTools + Plan-and-Execute-Strategie
java-support-botMehrstufiger Workflow mit bedingtem Routing
java-approval-workflowRuntime-Integration + Human-in-the-Loop
java-multi-tenantMandantengetrennte Workflow-Ausführung
java-data-governancePII-Erkennung und Redaktionsmuster
java-oauth-agentOAuth-Delegation + Scope-Narrowing
git clone https://github.com/jamjet-labs/examples
cd examples/java-hello-agent
mvn compile exec:java

Tipp: Jedes Java-Beispiel hat ein Python/YAML-Äquivalent im selben Repository.

On this page