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関数呼び出しスキーマツール名はレコードクラス名から派生します(WebSearch → web_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 SDK | Python SDK |
|---|---|---|
| ワークフロー定義 | Fluentビルダー + レコード | デコレーター + TypedDict |
| ツール定義 | @Tool レコード + ToolCall<T> | @tool デコレーター / MCP |
| エージェント定義 | Agent.builder() | @agent デコレーター |
| 状態 | 不変のJavaレコード | TypedDict / Pydantic |
| HTTPクライアント | ブロッキング(仮想スレッド) | 非同期(asyncio) |
| IRコンパイル | workflow.compile() | @workflow デコレーター |
| 最小バージョン | Java 21 | Python 3.10 |
どちらも同一の正規IRにコンパイルされ、同じRustランタイム上で実行されます。
例
サンプルリポジトリの実用例:
| 例 | 実演内容 |
|---|---|
java-hello-agent | 単一のモデル呼び出しを使った最小限のエージェント |
java-research-agent | ツール + 計画・実行戦略 |
java-support-bot | 条件分岐を含む複数ステップのワークフロー |
java-approval-workflow | ランタイム統合 + ヒューマン・イン・ザ・ループ |
java-multi-tenant | テナント分離されたワークフロー実行 |
java-data-governance | PII検出と秘匿化パターン |
java-oauth-agent | OAuth委譲 + スコープの絞り込み |
git clone https://github.com/jamjet-labs/examples
cd examples/java-hello-agent
mvn compile exec:javatip: すべてのJavaサンプルには、同じリポジトリ内にPython/YAML版の同等例があります。