JamJet

Java SDK

ビルダー、レコード、@Toolアノテーションを使用してJavaでJamJetワークフローとエージェントを記述します。

Java SDK

JamJet Java SDKを使用すると、ワークフロー、エージェント、ツールをJavaで記述できます。Python SDKと同じ正規IR(中間表現)にコンパイルされ、同じRustランタイム上で実行されます。

インストール

Java 21+(仮想スレッド対応)が必要です。

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

クイックスタート

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

var agent = Agent.builder("hello-agent")
    .model("claude-haiku-4-5-20251001")
    .instructions("質問に明確かつ簡潔に答えてください。")
    .strategy("react")
    .maxIterations(1)
    .build();

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

var result = agent.run("JamJetとは何ですか?");
System.out.println(result.output());

ワークフロー

型付き状態を持つ有向非巡回ワークフローを構築できます。状態はJavaレコード(イミュータブル、検証可能、シリアライズ可能)です。

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(), "[検索結果]", state.answer()))
    .step("synthesize", state ->
        new ResearchState(state.query(), state.results(), "最終回答: ..."))
    .build();

var result = wf.run(new ResearchState("最新のAIフレームワークは?", "", ""));
System.out.println(result.state().answer());
System.out.printf("%dステップを%.1fmsで実行%n",
    result.stepsExecuted(), result.totalDurationUs() / 1000.0);

条件付きルーティング

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

IRへのコンパイル

すべてのワークフローは、ランタイムへの送信用に正規IRにコンパイルされます。

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

// 送信前に検証
var errors = IrValidator.validate(ir);
errors.forEach(System.err::println);

エージェント

エージェントは、モデル、ツール、推論戦略を組み合わせたものです。3つの組み込み戦略があります。

戦略動作
react思考 → ツール使用 → 観察のループ
plan-and-execute計画 → ステップ実行 → 統合
critic下書き → 批評 → 修正のループ
import dev.jamjet.agent.Agent;

var agent = Agent.builder("research-agent")
    .model("claude-sonnet-4-6")
    .tools(WebSearch.class, FetchPage.class)
    .instructions("あなたは徹底したリサーチャーです。")
    .strategy("plan-and-execute")
    .maxIterations(8)
    .maxCostUsd(0.50)
    .timeoutSeconds(300)
    .build();

var result = agent.run("JamJetとLangGraphを比較してください");
System.out.println(result.output());
System.out.printf("実行時間: %.1fms%n", result.durationUs() / 1000.0);

アノテーションベースのエージェント

シンプルなエージェントの場合、インターフェースに@Taskアノテーションを使用します:

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

// 直接実行
String result = JamjetAgent.run(ResearchTask.class, "What is JamJet?");

// または再利用可能なプロキシを取得
ResearchTask task = JamjetAgent.proxy(ResearchTask.class);
String answer = task.research("What is JamJet?");

ツール

ツールは@Toolでアノテーションされた、ToolCall<T>を実装するJavaレコードです。SDKはレコードコンポーネントの型からJSON Schemaを自動生成します。

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() {
        // 実際の実装に置き換えてください
        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;
    }
}

ツールレジストリ

import dev.jamjet.tool.ToolRegistry;

// グローバルに登録
ToolRegistry.global()
    .register(WebSearch.class)
    .register(FetchPage.class);

// クエリ
ToolRegistry.global().names();          // ["web_search", "fetch_page"]
ToolRegistry.global().toOpenAiFormat(); // OpenAI関数呼び出しスキーマ

ツール名はレコードクラス名から派生します(WebSearchweb_search)。


ランタイムクライアント

JamjetClientは、JamJetランタイムAPI用のブロッキングHTTPクライアント(仮想スレッドを使用)です。

import dev.jamjet.JamjetClient;
import dev.jamjet.client.ClientConfig;

var client = new JamjetClient(
    ClientConfig.builder()
        .baseUrl("http://localhost:7700")
        .apiToken("YOUR_TOKEN")  // またはJAMJET_TOKEN環境変数
        .timeoutSeconds(30)
        .build()
);

ワークフローのライフサイクル

// ワークフローを登録
client.createWorkflow(ir.toMap());

// 実行を開始
var execId = client.startExecution("research-flow", Map.of("query", "..."));

// ステータスをポーリング
var status = client.getExecution(execId);
System.out.println(status.get("status")); // running | completed | failed

// イベントタイムラインを取得
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));

エージェント管理

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

ステート管理

ステートはJavaレコードです。ステップは現在のステートを受け取り、新しいインスタンスを返します — ステートは常に不変です。

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

ヒント: Javaレコードは不変性、equals/hashCode、toStringを無償で提供します。SDKはレコードコンポーネント型からJSON Schemaを自動生成し、IR検証を実行します。


IRコンパイルと検証

ワークフローとエージェントは両方ともWorkflowIrにコンパイルされます — Python SDKやYAMLワークフローと共有される正規の中間表現です。

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

評価

プラガブルなスコアラーを使用して、データセットに対してエージェントとワークフローをテストします:

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とJavaの比較

機能Java SDKPython SDK
ワークフロー定義Fluentビルダー + レコードデコレーター + TypedDict
ツール定義@Tool レコード + ToolCall<T>@tool デコレーター / MCP
エージェント定義Agent.builder()@agent デコレーター
状態不変のJavaレコードTypedDict / Pydantic
HTTPクライアントブロッキング(仮想スレッド)非同期(asyncio)
IRコンパイルworkflow.compile()@workflow デコレーター
最小バージョンJava 21Python 3.10

どちらも同一の正規IRにコンパイルされ、同じRustランタイム上で実行されます。


サンプルリポジトリの実用例:

実演内容
java-hello-agent単一のモデル呼び出しを使った最小限のエージェント
java-research-agentツール + 計画・実行戦略
java-support-bot条件分岐を含む複数ステップのワークフロー
java-approval-workflowランタイム統合 + ヒューマン・イン・ザ・ループ
java-multi-tenantテナント分離されたワークフロー実行
java-data-governancePII検出と秘匿化パターン
java-oauth-agentOAuth委譲 + スコープの絞り込み
git clone https://github.com/jamjet-labs/examples
cd examples/java-hello-agent
mvn compile exec:java

tip: すべてのJavaサンプルには、同じリポジトリ内にPython/YAML版の同等例があります。

On this page