JamJet Java Runtime

May 6, 2026 · View on GitHub

Pure-Java agent runtime. Durable execution, crash recovery, MCP native. No sidecar.


The 10-second demo

@DurableAgent("research-pipeline")
@Service
public class ResearchAgent {

    @Checkpoint("search")
    public String search(String topic) {
        return DurabilityContext.current().replayOrExecute("search", () ->
            searchClient.query(topic)  // real API call
        );
    }

    @Checkpoint("analyze")
    public String analyze(String sources) {
        return DurabilityContext.current().replayOrExecute("analyze", () ->
            llm.chat(SYSTEM_PROMPT, sources)  // real LLM call
        );
    }
}

Kill the process after search completes. Restart. analyze runs. search is replayed from checkpoint — no API call, no charge, instant. Zero code changes.


Why JamJet

  • Crash recovery — kill your process, restart, resume from last checkpoint. Works with any storage backend (H2, Postgres, SQLite).
  • Zero overhead — no REST hops, no sidecar. Runtime lives inside your JVM, shares your DataSource, calls your methods directly.
  • Virtual threads — 1M concurrent agents on standard blocking code. No CompletableFuture chains, no reactive operators.
  • Standard Java — works with Spring AI, LangChain4j, Google ADK, or any Java LLM library. JamJet adds durability; you keep your LLM calls.

How it compares

FeatureJamJetSpring AILangChain4jKoogGoogle ADK
Durable executionYes (event sourced)NoNoNoNo
Crash recoveryCheckpoint-levelNoNoNoNo
Virtual threadsNativeNoNoCoroutinesNo
Plugin hot-reloadClassLoader isolatedNoNoNoNo
MCP nativeClient + ServerClient onlyClient onlyNoClient only
Bytecode instrumentation@DurableAgentNoNoNoNo
Sidecar requiredNoN/AN/AN/AN/A

Examples

ExampleDescription
latency-comparisonBenchmark: embedded runtime vs REST sidecar overhead — p50/p95/p99 latency and 100-concurrent-workflow throughput
crash-recoveryKill the process mid-run, restart, watch completed checkpoints replay instantly
real-agentDocument analysis agent using the OpenAI API — fetch, analyze, summarize with full checkpointing
spring-boot-comparisonSide-by-side: old way (Docker + REST sidecar) vs new way (two annotations)

Quick Start

Add the dependency:

<dependency>
    <groupId>dev.jamjet</groupId>
    <artifactId>jamjet-runtime-instrument</artifactId>
    <version>0.1.0-SNAPSHOT</version>
</dependency>

For Spring Boot auto-configuration, use jamjet-spring-boot-starter instead:

<dependency>
    <groupId>dev.jamjet</groupId>
    <artifactId>jamjet-spring-boot-starter</artifactId>
    <version>0.1.0-SNAPSHOT</version>
</dependency>

Then:

  1. Annotate your agent class with @DurableAgent
  2. Annotate each step with @Checkpoint
  3. Wrap the step body with DurabilityContext.current().replayOrExecute(id, () -> ...)

That is the entire integration. No schema changes, no new infrastructure.


Modules

ModuleDescription
jamjet-runtime-coreFramework-agnostic runtime kernel: IR, event store, scheduler, workers, state backends
jamjet-runtime-protocolsMCP client and server adapters, ProtocolAdapter SPI
jamjet-runtime-instrumentByteBuddy Java agent, @DurableAgent, @Checkpoint, DurabilityContext
jamjet-runtime-pluginsClassLoader-isolated plugin system with ServiceLoader and hot-reload
jamjet-runtime-serverStandalone Javalin REST server — same API surface as the Rust runtime
jamjet-spring-boot-starterSpring Boot auto-configuration: embeds the runtime as Spring beans
jamjet-cloud-sdkDrop-in observability for Spring AI / LangChain4j (mirrors Python jamjet.cloud)
jamjet-cloud-spring-boot-starterSpring Boot auto-config for the Cloud SDK

JamJet Cloud SDK

Drop-in observability for Spring AI and LangChain4j agents. Mirrors the Python jamjet.cloud SDK.

Spring Boot

<dependency>
  <groupId>dev.jamjet</groupId>
  <artifactId>jamjet-cloud-spring-boot-starter</artifactId>
  <version>0.2.0</version>
</dependency>
# application.yml
jamjet:
  cloud:
    api-key: ${JJ_API_KEY}
    project: my-app

That's it. Every Spring AI ChatClient / ChatModel call and every LangChain4j ChatLanguageModel call is captured automatically.

Plain Java (LangChain4j without Spring)

<dependency>
  <groupId>dev.jamjet</groupId>
  <artifactId>jamjet-cloud-sdk</artifactId>
  <version>0.2.0</version>
</dependency>
JamjetCloud.configure(JamjetCloudConfig.builder()
    .apiKey(System.getenv("JJ_API_KEY"))
    .project("my-app")
    .build());

var model = OpenAiChatModel.builder()
    .apiKey(System.getenv("OPENAI_API_KEY"))
    .modelName("gpt-4o-mini")
    .listeners(List.of(new JamjetChatModelListener()))
    .build();

License

Apache 2.0