You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: temporal-spring-ai/README.md
+87Lines changed: 87 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -114,6 +114,63 @@ public class MyTools {
114
114
115
115
Auto-detected and executed as Nexus operations, similar to activity stubs.
116
116
117
+
## Migrating from plain Spring AI
118
+
119
+
The plugin is designed so that bringing an existing Spring AI service onto Temporal is a localized change. Outside Temporal, you probably have something like:
|`new WeatherTools()` for a plain POJO tool |`Workflow.newActivityStub(WeatherActivity.class, ...)` for a durable tool |
171
+
172
+
Plain `@Tool` POJOs, `@SideEffectTool`-annotated classes, and Nexus service stubs all work the same way — see **Tool Types** above.
173
+
117
174
## Media in messages
118
175
119
176
If you attach media (images, audio, etc.) to a `UserMessage` or an `AssistantMessage`, prefer passing it by URI rather than raw bytes:
@@ -130,6 +187,36 @@ Raw `byte[]` media gets serialized into every chat activity's input *and* result
130
187
131
188
Override the cap by setting the system property `io.temporal.springai.maxMediaBytes` before your worker starts (pass a positive integer; `0` disables the check). For anything larger than a small thumbnail, the URI route is the right answer — have an activity write the bytes to blob storage, then pass only the URL into the conversation.
132
189
190
+
## Activity options and retry behavior
191
+
192
+
`ActivityChatModel.forDefault()` and `ActivityChatModel.forModel(name)` create the chat activity stub with sensible defaults: a 2-minute start-to-close timeout, 3 attempts, and `org.springframework.ai.retry.NonTransientAiException` + `java.lang.IllegalArgumentException` classified as non-retryable so a bad API key or invalid prompt fails fast.
193
+
194
+
Override with `ActivityChatModel.forModel(name, ActivityOptions)`:
For repeated per-model overrides, declare a `ChatModelActivityOptions` bean and auto-configuration wires the map into the plugin. See that class's javadoc for the pattern.
205
+
206
+
`ActivityMcpClient.create()` / `create(ActivityOptions)` behave the same way with a 30-second default timeout.
207
+
208
+
## Known limitations
209
+
210
+
-**Streaming (`chatClient.stream(...)`)** — not currently supported. Use `.call()` instead.
211
+
-**`defaultToolContext(Map<String, Object>)`** — not supported; tool context holds mutable state that can't safely cross the activity boundary. Pass required context as activity parameters or workflow state.
212
+
-**Child workflow stubs as tools** — not supported. Wrap a plain `@Tool` method that starts the child workflow via `Workflow.newChildWorkflowStub(...)` and call through to it yourself.
213
+
-**Media `byte[]` size** — inline bytes are capped at 1 MiB per payload (see "Media in messages" above). Prefer URI-based media.
214
+
-**Provider-specific `ChatOptions` via `ChatClient.defaultOptions(...)`** — works as long as your `ChatOptions` subclass overrides `copy()` to return its own type (every real provider class does this). A subclass inheriting the default `copy()` loses its identity before the plugin sees it — same behavior as outside Temporal.
215
+
216
+
## Observability
217
+
218
+
`TemporalChatClient.builder(chatModel, observationRegistry, customConvention)` accepts a Micrometer `ObservationRegistry` for Spring AI-side chat client metrics. Temporal-side metrics (activity durations, retries) are emitted by the SDK's `MetricsScope` — see the [Temporal Java SDK observability docs](https://docs.temporal.io/develop/java/observability) for how to wire an OpenTelemetry or Prometheus exporter onto your workers. The two layers compose: Spring AI observations cover what the caller does; Temporal metrics cover what the scheduled activity does.
219
+
133
220
## Optional Integrations
134
221
135
222
Auto-configured when their dependencies are on the classpath:
0 commit comments