# Choosing an `AgentRuntime`

Atmosphere ships nine `AgentRuntime` adapters. Every adapter implements the
same Java SPI, so switching between them is a one-line Maven dependency
swap — but each one is wrapped around a different upstream agent framework
with different strengths. This guide is the decision tree you should walk
before picking, and the per-runtime "when to pick" notes once you have.

> **Source of truth.** The capability flags quoted below come straight from
> [`.harness/capabilities.snapshot.json`](../.harness/capabilities.snapshot.json),
> regenerated by `scripts/regen-capability-snapshot.sh` and pinned by
> `CapabilitySnapshotTest`. The matrix cannot drift from the running code
> without breaking the build (Correctness Invariant #5 — Runtime Truth).

## Decision tree

Walk these questions in order; stop at the first match.

1. **Are you new to Atmosphere AI and just need it to work?**
   → **Built-in (`atmosphere-ai`)**. Zero extra deps, OpenAI-compatible
   client out of the box, the only runtime that emits
   `TOOL_CALL_DELTA` for token-streaming tool-call argument deltas. Use
   `--model` / `LLM_API_KEY` to point at OpenAI / Gemini / Ollama / any
   compatible endpoint.

2. **Are you already on Spring Boot and use Spring AI's `ChatClient` /
   `VectorStore` SPIs elsewhere in your codebase?**
   → **Spring AI (`atmosphere-spring-ai`)**. Reuses your Spring AI
   provider abstraction, threads `Content.Image` / `Content.Audio` into
   Spring AI Media, honors `prompt_cache_key` on the OpenAI path. Lets
   you bring any `VectorStore` you have already configured into RAG.

3. **Are you on a non-Spring JVM stack (plain Spring Framework, Quarkus,
   Micronaut, Vert.x) and want a vendor-neutral LLM/embedding/tool API?**
   → **LangChain4j (`atmosphere-langchain4j`)**. Largest ecosystem of
   vendor adapters, multi-modal vision/audio/image, OpenAI prompt cache,
   embedding-store retriever bridge. Best fit when Spring AI is not
   already in play.

4. **Do you need Gemini-native execution and Google's agent topology
   (sub-agents, ContextCacheConfig, ReAct over Vertex AI)?**
   → **Google ADK (`atmosphere-adk`)**. Only runtime that declares
   `AGENT_ORCHESTRATION` from a hosted vendor; native vision / audio /
   prompt-caching against Gemini; `LlmAgent` graph topology survives the
   bridge.

5. **Are you a Kotlin shop and want JetBrains' coroutine-first agent
   framework with native cancellation?**
   → **Koog (`atmosphere-koog`)**. Only runtime that declares
   `CANCELLATION` natively (`AIAgent.cancel()` propagates from
   `StreamingSession.isCancelled()`); Bedrock prompt-cache control,
   coroutine-cancel + JNI interrupt + Reactor dispose all wired through
   `executeWithHandle`.

6. **Are you doing goal-graph multi-agent work (Embabel's `@Agent`
   declarative planner)?**
   → **Embabel (`atmosphere-embabel`)**. Goal-graph orchestration, Spring
   AI provider underneath, tool bridge layered through Embabel's own
   `Tool.Handler` so `@RequiresApproval` gates still fire.

7. **Do you need Microsoft Semantic Kernel's plugin / planner ecosystem
   (.NET-equivalent surface on the JVM)?**
   → **Semantic Kernel (`atmosphere-semantic-kernel`)**. SK 1.4 surface
   with `KernelFunction` tool bridge through Atmosphere's
   `ToolExecutionHelper`, sidecar bridge for per-request
   `InvocationContext` / `KernelHooks` / `withMaxAutoInvokeAttempts`.

8. **Do you need Alibaba's AgentScope reasoning loop (Qwen-native
   ReAct, Alibaba Cloud AI Studio)?**
   → **AgentScope (`atmosphere-agentscope`)**. Reactor-backed streaming,
   `AgentScopeToolBridge` for portable `@AiTool` calls, the second
   runtime to declare native `CANCELLATION` (Reactor subscription
   cancellation on every event tick).

9. **Do you need Spring AI Alibaba's `ReactAgent` graph and Alibaba
   Cloud DashScope models on Spring Boot 3?**
   → **Spring AI Alibaba (`atmosphere-spring-ai-alibaba`)**. Buffered
   streaming (the upstream `ReactAgent.call()` returns a single
   `AssistantMessage`); Atmosphere still streams that buffered reply over
   WebSocket / SSE; `TOKEN_USAGE` works via the
   `UsageCapturingChatModel` decorator threaded into auto-config.
   **Pin Spring Boot 3 today** — the framework is not yet Spring Boot 4
   compatible (Alibaba `1.1.2.0` hardcodes Spring AI 1.1.2 types).

If multiple options match, pick the lowest-numbered one — the runtimes are
ordered from "most-general / most-portable" at the top to
"most-specialized" at the bottom.

## Per-runtime quick comparison

| Runtime | Best for | Skip if | Streaming | Tool calling | Embeddings |
|---------|----------|---------|-----------|:------------:|:----------:|
| Built-in | Default choice; OpenAI-compatible endpoints; zero extra deps | You need vendor-specific agent topology | Token-by-token | ✅ + `TOOL_CALL_DELTA` | ✅ |
| Spring AI | Spring Boot apps; existing Spring AI `VectorStore` in scope | You are not on Spring | Token-by-token | ✅ | ✅ |
| LangChain4j | Vendor-neutral JVM (Quarkus, Micronaut, Vert.x) | You want OpenAI-only | Token-by-token | ✅ | ✅ |
| Google ADK | Gemini-native + sub-agent orchestration | You're not using Gemini | Token-by-token | ✅ + `AGENT_ORCHESTRATION` | — |
| Embabel | Goal-graph planner workflows | You want imperative dispatch | Token-by-token | ✅ + `AGENT_ORCHESTRATION` | ✅ |
| Koog | Kotlin coroutine + native `CANCELLATION` | You're not on Kotlin | Token-by-token | ✅ + `AGENT_ORCHESTRATION` + `CANCELLATION` | ✅ |
| Semantic Kernel | Microsoft / .NET ecosystem parity on JVM | You don't need SK plugins/planners | Token-by-token | ✅ | ✅ |
| AgentScope | Qwen-native ReAct, Alibaba Cloud AI Studio | You want anything other than Qwen | Token-by-token | ✅ + `CANCELLATION` | — |
| Spring AI Alibaba | DashScope / `ReactAgent` graph on Spring Boot 3 | You're on Spring Boot 4 | **Buffered** (one chunk + complete) | ✅ | ✅ |

## What's the same on every runtime

Some capabilities are declared by every adapter because Atmosphere implements
them once in the pipeline layer or in `AbstractAgentRuntime` — the adapter
only plugs in where it differs:

- **`TEXT_STREAMING`** (every runtime; Spring AI Alibaba is buffered)
- **`SYSTEM_PROMPT`** (every runtime)
- **`STRUCTURED_OUTPUT`** (every runtime — pipeline wraps the session in
  `StructuredOutputCapturingSession` with system-prompt schema injection)
- **`CONVERSATION_MEMORY`** (every runtime — `AbstractAgentRuntime.assembleMessages`
  threads `context.history()` into the outgoing message list)
- **`TOOL_CALLING` / `TOOL_APPROVAL`** (every runtime — each ships a tool
  bridge that routes through `ToolExecutionHelper.executeWithApproval`)
- **`TOKEN_USAGE`** (every runtime — Spring AI Alibaba captures via the
  `UsageCapturingChatModel` decorator)
- **`PER_REQUEST_RETRY`** (every runtime — `executeWithOuterRetry` baseline
  plus the upstream native retry layer)
- **`BUDGET_ENFORCEMENT`** (every runtime — wall-clock + token / step
  budgets honored uniformly)
- **`CONFIDENCE_SCORES`** (every runtime — pipeline parses
  `{"confidence": …}` field on stream completion)
- **`PASSIVATION`** (every runtime — `AgentPassivation` snapshots
  `context.history()` into a `CheckpointStore`)

Use the table at the top to decide on the specialized capabilities
(`AGENT_ORCHESTRATION`, `CANCELLATION`, multi-modal vision/audio,
`PROMPT_CACHING`).

## Swapping runtimes

The Atmosphere CLI handles the swap mechanically:

```bash
# Build a chat sample on the built-in runtime first
atmosphere new my-app --template ai-chat --runtime builtin

# Later, switch the same sample to Spring AI (one-line Maven dep change
# applied to the scaffold's pom.xml)
atmosphere new my-app --template ai-chat --runtime spring-ai --force
```

`--runtime` accepts `builtin`, `spring-ai`, `langchain4j`, `adk`, `embabel`,
`koog`, `semantic-kernel`, `agentscope`, `spring-ai-alibaba`. The `--force`
flag (only valid with `--runtime`) wipes any existing adapter dependency
declared in `cli/runtime-overlays.json` from the scaffolded `pom.xml`
*before* injecting the chosen overlay — required for samples that already
pin a non-default adapter (e.g. `ai-tools` ships with
`atmosphere-langchain4j`).

Samples whose Java code imports provider-specific types directly (e.g.
`OpenAiStreamingChatModel`) still need manual edits after a force-swap;
the transparent templates (`ai-chat`, `multi-agent`, etc.) work end-to-end
with no code changes.
