@@ -73,25 +73,8 @@ Use `ActivityChatModel` as a Spring AI `ChatModel` inside a Workflow. Every call
7373
7474Wrap ` ActivityChatModel ` in a ` TemporalChatClient ` to build prompts and register tools:
7575
76- ``` java
77- @WorkflowInit
78- public MyWorkflowImpl(String goal) {
79- ActivityChatModel chatModel = ActivityChatModel . forDefault();
80-
81- WeatherActivity weather = Workflow . newActivityStub(
82- WeatherActivity . class, activityOptions);
83-
84- this . chatClient = TemporalChatClient . builder(chatModel)
85- .defaultSystem(" You are a helpful assistant." )
86- .defaultTools(weather, new TimestampTools ())
87- .build();
88- }
89-
90- @Override
91- public String run(String goal) {
92- return chatClient. prompt(). user(goal). call(). content();
93- }
94- ```
76+ <!--SNIPSTART samples-java-spring-ai-chat-workflow-init-- >
77+ <!--SNIPEND-->
9578
9679`ActivityChatModel.forDefault()` resolves to the default Spring AI `ChatModel` bean. To target a specific model in a multi-model application, pass its bean name to `ActivityChatModel.forModel("openai")`.
9780
@@ -114,20 +97,8 @@ ActivityChatModel chatModel = ActivityChatModel.forDefault(
11497
11598For configuration-driven per-model overrides, declare a `ChatModelActivityOptions` bean. The plugin consults it whenever `forDefault()` or `forModel(name)` runs in a Workflow. Use the special key `ChatModelTypes.DEFAULT_MODEL_NAME` (the literal `"default"`) as a global catch-all that applies to any model not explicitly listed — including models contributed by third-party starters:
11699
117- ``` java
118- @Bean
119- ChatModelActivityOptions chatModelActivityOptions() {
120- ActivityOptions fiveMinute =
121- ActivityOptions . newBuilder(ActivityChatModel . defaultActivityOptions())
122- .setStartToCloseTimeout(Duration . ofMinutes(5 ))
123- .build();
124- return new ChatModelActivityOptions (Map . of(
125- ChatModelTypes . DEFAULT_MODEL_NAME , fiveMinute, // global baseline
126- " claude" , ActivityOptions . newBuilder(fiveMinute) // overrides for "claude"
127- .setTaskQueue(" claude-heavy" )
128- .build()));
129- }
130- ```
100+ <!--SNIPSTART samples-java-spring-ai-per-model-options-- >
101+ <!--SNIPEND-->
131102
132103Keys that neither match a registered `ChatModel` bean nor equal `"default"` cause plugin construction to fail, so a typo surfaces at startup rather than at first call.
133104
@@ -137,17 +108,8 @@ Keys that neither match a registered `ChatModel` bean nor equal `"default"` caus
137108
138109Provider-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:
139110
140- ``` java
141- AnthropicChatOptions thinking = AnthropicChatOptions . builder()
142- .thinking(AnthropicApi . ThinkingType . ENABLED , 1024 )
143- .temperature(1.0 )
144- .maxTokens(4096 )
145- .build();
146-
147- ChatClient client = TemporalChatClient . builder(ActivityChatModel . forModel(" anthropic" ))
148- .defaultOptions(thinking)
149- .build();
150- ```
111+ <!--SNIPSTART samples-java-spring-ai-provider-options-- >
112+ <!--SNIPEND-->
151113
152114The pass-through relies on the `ChatOptions` subclass overriding `copy()` to return its own type — every provider class shipped with Spring AI does.
153115
@@ -170,14 +132,8 @@ Tools passed to `defaultTools()` are dispatched based on their type. The integra
170132
171133An interface annotated with both `@ActivityInterface` and Spring AI `@Tool` methods is auto-detected and executed as a Temporal Activity. Use this for external calls that need retries and timeouts.
172134
173- ``` java
174- @ActivityInterface
175- public interface WeatherActivity {
176- @Tool (description = " Get weather for a city" )
177- @ActivityMethod
178- String getWeather (String city );
179- }
180- ```
135+ <!--SNIPSTART samples-java-spring-ai-activity-tool-- >
136+ <!--SNIPEND-->
181137
182138### Nexus service stubs
183139
@@ -187,29 +143,15 @@ Nexus service stubs with `@Tool` methods are auto-detected and invoked as [Nexus
187143
188144Classes annotated with `@SideEffectTool` have each `@Tool` method wrapped in `Workflow.sideEffect()`. The result is recorded in history on first execution and replayed from history afterward. Use this for cheap, non-deterministic operations such as timestamps or UUIDs.
189145
190- ``` java
191- @SideEffectTool
192- public class TimestampTools {
193- @Tool (description = " Get current time" )
194- public String now () {
195- return Instant . now(). toString();
196- }
197- }
198- ```
146+ <!--SNIPSTART samples-java-spring-ai-side-effect-tool-- >
147+ <!--SNIPEND-->
199148
200149### Plain tools
201150
202151Any class with `@Tool` methods that isn't an Activity stub, Nexus stub, or `@SideEffectTool` runs directly on the Workflow thread. Use this for inherently deterministic tools (such as updating in-memory agent state), or for orchestration of durable primitives as you need, e.g. calling multiple Activities, child Workflows, wait conditions, or other Temporal durable primitives.
203152
204- ``` java
205- public class MyTools {
206- @Tool (description = " Process data" )
207- public String process (String input ) {
208- SomeActivity act = Workflow . newActivityStub(SomeActivity . class, opts);
209- return act. doWork(input);
210- }
211- }
212- ```
153+ <!--SNIPSTART samples-java-spring-ai-plain-tool-- >
154+ <!--SNIPEND-->
213155
214156## Use vector stores, embeddings, and MCP
215157
0 commit comments