Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 40 additions & 27 deletions docs/develop/java/integrations/spring-ai.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,60 +10,61 @@ tags:
- Temporal SDKs
- Integrations
- AI Frameworks
description: Build durable AI agents in Java with the Temporal Spring AI integration.
description: Run Spring AI agents on Temporal with durable model calls, Activity tools, and replay-safe orchestration using Spring Boot.
---

import { ReleaseNoteHeader } from '@site/src/components';

[Spring AI](https://docs.spring.io/spring-ai/reference/) is an agent framework for Java applications — chat clients, tool calling, vector stores, embeddings, and MCP servers, all wired through Spring Boot.

The [Temporal Spring AI integration](https://central.sonatype.com/artifact/io.temporal/temporal-spring-ai) makes Spring AI agents durable: model calls run through Temporal Activities recorded in Event history, and tools are dispatched per their type so each kind lands in the right place in Workflow execution — Activity stubs and Nexus stubs as durable operations, `@SideEffectTool` classes wrapped in `Workflow.sideEffect`, and plain tools running directly in Workflow code. Agents retry on failure and replay deterministically without changing how you write Spring AI code.
The [Temporal Spring AI integration](https://central.sonatype.com/artifact/io.temporal/spring-ai) makes Spring AI agents durable: model calls run through Temporal Activities recorded in Event history, and tools are dispatched per their type so each kind lands in the right place in Workflow execution — Activity stubs and Nexus stubs as durable operations, `@SideEffectTool` classes wrapped in `Workflow.sideEffect`, and plain tools running directly in Workflow code. Agents retry on failure and replay deterministically without changing how you write Spring AI code.

The integration is built on the Temporal Java SDK's [Plugin system](/develop/plugins-guide) and is distributed as the `io.temporal:temporal-spring-ai` module alongside the existing [Spring Boot integration](/develop/java/integrations/spring-boot-integration).
The integration is built on the Temporal Java SDK's [Plugin system](/develop/plugins-guide) and is distributed as the standalone `io.temporal:spring-ai` module alongside the existing [Spring Boot integration](/develop/java/integrations/spring-boot-integration).

<ReleaseNoteHeader type="publicPreview" />

## Prerequisites

The integration requires all of the following on your application's classpath. The plugin won't auto-configure if any of these are missing or below the listed minimum:
Your application needs a Java runtime, with Spring Boot, Spring AI, and the Temporal Java SDK on its classpath. Refer to the [integration's compatibility requirements](https://github.com/temporalio/ai-integrations/tree/main/java/spring-ai#requirements-and-installation) for supported versions.

| Dependency | Minimum version |
| ----------------- | --------------- |
| Java | 17 |
| Spring Boot | 3.x |
| Spring AI | 1.1.0 |
| Temporal Java SDK | 1.35.0 |

You also need the [`temporal-spring-boot-starter`](/develop/java/integrations/spring-boot-integration) and a Spring AI model starter (for example, `spring-ai-starter-model-openai`) — `temporal-spring-ai` does not pull in a model provider on its own.
You also need the [`temporal-spring-boot-starter`](/develop/java/integrations/spring-boot-integration) and a Spring AI model starter (for example, `spring-ai-starter-model-openai`). The integration does not pull in a model provider on its own.

## Add the dependency

Add `temporal-spring-ai` alongside `temporal-spring-boot-starter` and a Spring AI model starter (for example, `spring-ai-starter-model-openai`).
Add `io.temporal:spring-ai` alongside `temporal-spring-boot-starter` and a Spring AI model starter (for example, `spring-ai-starter-model-openai`). The Spring AI integration is versioned separately from the Temporal Java SDK.

**[Apache Maven](https://maven.apache.org/):**

```xml
<dependency>
<groupId>io.temporal</groupId>
<artifactId>temporal-spring-ai</artifactId>
<version>${temporal-sdk.version}</version>
<artifactId>spring-ai</artifactId>
<version>${temporal-spring-ai.version}</version>
</dependency>
```

**[Gradle Groovy DSL](https://gradle.org/):**

```groovy
implementation "io.temporal:temporal-spring-ai:${temporalSdkVersion}"
implementation "io.temporal:spring-ai:${temporalSpringAiVersion}"
```

When `temporal-spring-ai` is on the classpath, the `SpringAiPlugin` auto-registers `ChatModelActivity` with all Temporal Workers created by the Spring Boot integration. Optional Activities are auto-configured when their dependencies are present:
When `io.temporal:spring-ai` is on the classpath, the `SpringAiPlugin` auto-registers `ChatModelActivity` with all Temporal Workers created by the Spring Boot integration. Optional Activities are auto-configured when their dependencies are present:

| Feature | Dependency | Registered Activity |
| ------------ | --------------- | ------------------------ |
| Vector store | `spring-ai-rag` | `VectorStoreActivity` |
| Embeddings | `spring-ai-rag` | `EmbeddingModelActivity` |
| MCP | `spring-ai-mcp` | `McpClientActivity` |

### Upgrade from Spring AI 1.x

`io.temporal:spring-ai:0.1.0` targets Spring AI 2 and Spring Boot 4. Spring AI 1 / Spring Boot 3 applications should remain on `io.temporal:temporal-spring-ai:1.40.x`.

Align your application's Spring AI and Spring Boot BOMs with the integration's compatibility requirements. Spring AI 2 uses Jackson 3 and immutable chat options. Pass option builders to `ChatClient`, such as `.defaultOptions(OpenAiChatOptions.builder().reasoningEffort("high"))`, or call `.mutate()` on existing options.

Spring AI 1 Workflow histories are incompatible with this upgrade. Complete existing executions before switching versions or use separate Worker deployments for the two versions.

## Call a chat model from a Workflow

Use `ActivityChatModel` as a Spring AI `ChatModel` inside a Workflow. Every call goes through a Temporal Activity, so model responses are durable and retried per your Activity options.
Expand Down Expand Up @@ -106,12 +107,16 @@ public ChatWorkflowImpl(String systemPrompt) {
// - Activity stubs (weatherTool) become durable AI tools
// - plain workflow tool classes (stringTools) execute directly in workflow
// - @SideEffectTool classes (timestampTools) are wrapped in sideEffect()
// - PromptChatMemoryAdvisor maintains conversation history
// - MessageChatMemoryAdvisor maintains conversation history
this.chatClient =
TemporalChatClient.builder(activityChatModel)
.defaultSystem(systemPrompt)
.defaultTools(weatherTool, stringTools, timestampTools)
.defaultAdvisors(PromptChatMemoryAdvisor.builder(chatMemory).build())
.defaultAdvisors(
advisors ->
advisors
.advisors(MessageChatMemoryAdvisor.builder(chatMemory).build())
.param(ChatMemory.CONVERSATION_ID, Workflow.getInfo().getWorkflowId()))
.build();
}

Expand Down Expand Up @@ -335,19 +340,27 @@ Keys that neither match a registered `ChatModel` bean nor equal `"default"` caus

`ActivityMcpClient.create()` and `create(ActivityOptions)` work the same way for MCP tool calls, with a 30-second default timeout.

### Disable provider retries

Disable the provider SDK's retries so each Temporal Activity attempt makes one provider request. For the Spring Boot OpenAI chat model, set:

```properties
spring.ai.openai.chat.max-retries=0
```

For manually constructed OpenAI or Anthropic models, set `.maxRetries(0)` on the provider options before building the Worker's model. Setting retries on a Workflow prompt does not reconfigure an existing provider client.

OpenAI HTTP failures retain their native exception types. The integration classifies retryable failures and honors provider retry delays; see the [provider retry reference](https://github.com/temporalio/ai-integrations/tree/main/java/spring-ai#provider-retries) for details.

## Provider-specific chat options

Provider-specific `ChatOptions` subclasses — for example, `AnthropicChatOptions` to enable extended thinking, or `OpenAiChatOptions` to set `reasoning_effort` — pass through the Activity boundary unchanged. Attach them via `ChatClient.defaultOptions(...)` and the plugin re-applies them on the Activity side before calling the underlying model:

<!--SNIPSTART samples-java-spring-ai-provider-options-->
[springai/multimodel/src/main/java/io/temporal/samples/springai/multimodel/MultiModelWorkflowImpl.java](https://github.com/temporalio/samples-java/blob/main/springai/multimodel/src/main/java/io/temporal/samples/springai/multimodel/MultiModelWorkflowImpl.java)
```java
AnthropicChatOptions thinkingOptions =
AnthropicChatOptions.builder()
.thinking(AnthropicApi.ThinkingType.ENABLED, 1024)
.temperature(1.0)
.maxTokens(4096)
.build();
AnthropicChatOptions.Builder thinkingOptions =
AnthropicChatOptions.builder().thinkingEnabled(1024).temperature(1.0).maxTokens(4096);
chatClients.put(
"think",
TemporalChatClient.builder(anthropicModel)
Expand All @@ -360,7 +373,7 @@ chatClients.put(
```
<!--SNIPEND-->

The pass-through relies on the `ChatOptions` subclass overriding `copy()` to return its own type — every provider class shipped with Spring AI does.
Spring AI options are immutable. Pass their builder to `defaultOptions(...)`, or call `.mutate()` on an existing options object. The integration preserves provider-specific fields across the Activity boundary.

## Media in messages

Expand Down Expand Up @@ -389,6 +402,6 @@ new McpPlugin();

## Resources

- [`temporal-spring-ai` README](https://github.com/temporalio/sdk-java/blob/main/contrib/temporal-spring-ai/README.md) — full reference for the module
- [Temporal Spring AI README](https://github.com/temporalio/ai-integrations/tree/main/java/spring-ai) — full reference for the standalone module
- [Spring Boot integration](/develop/java/integrations/spring-boot-integration) — required companion module
- [Plugin system](/develop/plugins-guide) — how integrations are registered with Workers and Clients
Loading