ai-integrations/java/spring-ai at main · temporalio/ai-integrations · GitHub
Skip to content

Latest commit

 

History

History

spring-ai

Folders and files

README.md

Temporal Spring AI

Public Preview integration for Spring AI 2.0.x and Spring Boot 4. Model calls execute as Temporal Activities; Activity, Nexus, side-effect, and deterministic tools execute through the ChatClient tool-calling advisor on the workflow thread.

The new coordinate is io.temporal:spring-ai on Maven Central. CI tests Java 17 and 25; published bytecode targets Java 17.

Requirements and installation

  • Java 17 or later.
  • Spring AI 2.0.1 and Spring Boot 4.0.8; Boot 4.1.1 is also tested.
  • Temporal Java SDK and temporal-spring-boot-starter 1.40.0 or later.
  • A Spring AI provider starter for your chosen model. This integration supplies no provider.

Install the standalone integration:

implementation 'io.temporal:spring-ai:0.1.0'
implementation 'io.temporal:temporal-spring-boot-starter:1.40.0'
implementation 'io.temporal:temporal-sdk:1.40.0'

Inside a workflow, construct the client with TemporalChatClient.builder(ActivityChatModel.forDefault()) and register tools with defaultTools(...). The entry points TemporalChatClient, ActivityChatModel, and Temporal tool annotations retain their names and packages. Model calls run as Activities; tool calls remain durable Temporal operations.

Moving from Spring AI 1

io.temporal:spring-ai:0.1.0 targets Spring AI 2 / Boot 4 exclusively. Spring AI 1 / Boot 3 applications remain on io.temporal:temporal-spring-ai:1.40.x. Align your application with the Spring AI 2 and Boot 4 BOMs; Spring AI 2 uses immutable options and Jackson 3. Pass option builders to ChatClient, for example .defaultOptions(OpenAiChatOptions.builder().reasoningEffort("high")). ActivityChatModel.call(...) returns a raw model response; use ChatClient's advisor loop to execute tools. The removed internalToolExecutionEnabled flag is unnecessary.

Do not move in-flight Spring AI 1 workflows onto these workers: the upgrade does not provide replay compatibility with Spring AI 1 histories. Use separate worker deployments or complete the existing executions before switching versions.

Streaming and tool context remain unsupported. Provider-specific options survive Activity serialization through their public builders; callbacks are transported as definitions and execute only in the workflow. Retry, per-model Activity options, response metadata, and media-size guards retain their behavior. Optional vector-store, embedding, and MCP modules are detected through Spring auto-configuration.

Provider retries

For OpenAI chat Activities, native OpenAI HTTP errors retain their status, error body, and diagnostic response headers (retry-after, retry-after-ms, x-request-id, x-ratelimit-*, and x-should-retry) in ApplicationFailure details. insufficient_quota responses are always non-retryable. Otherwise, X-Should-Retry: true or false overrides the HTTP status. Without a recognized directive, rate limits (429), request timeouts (408), conflicts (409), and server errors are retryable; other HTTP client errors are non-retryable.

Retry-After (seconds or an HTTP date) and retry-after-ms set Temporal's next retry delay; missing or invalid delays leave the Activity's configured backoff in effect. A positive provider delay overrides maximumInterval, which does not cap it. Maximum attempts and schedule-to-close timeouts still apply. To exclude additional errors with RetryOptions.Builder.setDoNotRetry(...), use the exact failure type, such as com.openai.errors.RateLimitException.

Disable provider SDK retries on models registered with Temporal so each Activity attempt makes one provider request. For a manually constructed OpenAI model, use OpenAiChatOptions.builder().maxRetries(0) when building the worker's model. For Spring Boot's OpenAI chat model:

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

These options configure the provider client at construction time; setting them on a workflow prompt does not disable retries on an existing client. Keep a separate model/client if calls outside Temporal need SDK retries. Without this configuration, Spring AI 2.0.1's three internal OpenAI retries can produce twelve requests across the default three Activity attempts.

Development

./gradlew spotlessCheck test stageDist

The full Java/OS matrix runs for each supported Boot version, using committed locks. Deliberately update locks with ./gradlew resolveAndLockAll --write-locks (and -PspringBootVersion=4.1.1 for that compatibility lane).

Nightly CI and manual runs with latest-deps=true test stable releases in Temporal 1.x, Spring AI 2.x, and Spring Boot 4.x. To run that check locally:

./gradlew -PdependencyMode=latest resolveAndLockAll --write-locks --refresh-dependencies
./gradlew -PdependencyMode=latest spotlessCheck test stageDist

Latest mode writes a separate ignored lockfile and reuses its selected versions through testing and building. Ordinary CI uses the committed locks.

The implementation and tests use the repository's MIT license.