Skip to content

Commit e5f7a4c

Browse files
committed
docs(ai): document per-request runtime extensions + model-lifecycle hooks
Add Per-Request Runtime Extensions section covering SpringAiAdvisors / LangChain4jAiServices / KoogStrategy / AdkRootAgent / ToolLoopPolicies (each with the per-module README link); add Model-Lifecycle Observability subsection covering onModelStart/End/Error + AiEventForwardingListener; bundle the AgentScope + Spring AI Alibaba runtime-table rows that were already staged. Tracks main-repo f1493c3f9c (sidecar merge) and c355311493 (Alibaba caveat).
1 parent 046c638 commit e5f7a4c

1 file changed

Lines changed: 74 additions & 0 deletions

File tree

  • docs/src/content/docs/reference

docs/src/content/docs/reference/ai.md

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,83 @@ public interface AgentRuntime {
7676
| `atmosphere-embabel` | Embabel `AgentPlatform` | 100 |
7777
| `atmosphere-koog` | JetBrains Koog `AIAgent` | 100 |
7878
| `atmosphere-semantic-kernel` | Microsoft Semantic Kernel `ChatCompletionService` | 100 |
79+
| `atmosphere-agentscope` | Alibaba AgentScope `ReActAgent` | 100 |
80+
| `atmosphere-spring-ai-alibaba` | Spring AI Alibaba `ReactAgent` *(see runtime caveat below)* | 100 |
7981

8082
To switch runtimes, change a single Maven dependency — no code changes needed.
8183

84+
> **Spring AI Alibaba runtime — Spring Boot 3 only today.** Spring AI Alibaba `1.1.2.0` is compiled against Spring AI `1.1.2`, and `spring-ai-alibaba-graph-core-1.1.2.0` hardcodes Spring AI 1.1.2-only types like `DeepSeekAssistantMessage`, so the runtime requires Spring AI 1.1.2. Spring AI 1.1.2 itself requires Spring Boot 3 — it pins the SB3-era FQN of `RestClientAutoConfiguration`, which Spring Boot 4 ships at a renamed FQN. Drop `atmosphere-spring-ai-alibaba` into a Spring Boot 3 sample (e.g. `samples/spring-boot-ai-chat -Pspring-boot3`) and it round-trips end-to-end (verified via chrome-devtools against Ollama). A Spring Boot 4 path will become possible once Alibaba publishes a Spring AI 2.x-aligned `spring-ai-alibaba-agent-framework`. `atmosphere-agentscope` is unaffected and works on Spring Boot 4.
85+
86+
### Per-Request Runtime Extensions
87+
88+
Each `AgentRuntime` runs its framework's "happy path" by default. For requests
89+
that need framework-native composition (Spring AI advisor chain, LangChain4j
90+
`AiServices`, Koog graph DSL, ADK multi-agent topology), a small per-request
91+
helper attaches the framework-native object to `AgentExecutionContext.metadata()`
92+
and the runtime applies it for that one call — no `AgentRuntime` SPI growth, no
93+
mutation of shared beans. All five helpers follow the `CacheHint` pattern:
94+
`from(context)` and `attach(context, ...)` static methods.
95+
96+
| Helper | Runtime | Slot it drives |
97+
|--------|---------|----------------|
98+
| `SpringAiAdvisors` | Spring AI | `ChatClient.prompt().advisors(...)` — RAG, memory, guardrails, observability |
99+
| `LangChain4jAiServices` | LangChain4j | Routes through caller's `AiServices`-backed interface (`TokenStream` callbacks bridged to session) |
100+
| `KoogStrategy` | Koog | Swaps default `chatAgentStrategy()` with a custom `AIAgentGraphStrategy<String, String>` from the `strategy {}` DSL |
101+
| `AdkRootAgent` | ADK | Replaces the runtime's default `LlmAgent` with `SequentialAgent` / `ParallelAgent` / `LoopAgent` / any `BaseAgent` subclass |
102+
| `ToolLoopPolicies` | Built-in | Per-request `ToolLoopPolicy(maxIterations, OnMaxIterations)` for the OpenAI-compatible tool loop |
103+
104+
Example — Spring AI advisor scoped to one request:
105+
106+
```java
107+
var safeGuard = SafeGuardAdvisor.builder()
108+
.sensitiveWords(List.of("badword"))
109+
.failureResponse("I cannot answer that.")
110+
.build();
111+
112+
var ctx = SpringAiAdvisors.attach(baseContext, safeGuard, new SimpleLoggerAdvisor());
113+
runtime.execute(ctx, session);
114+
```
115+
116+
Each helper ships with a unit-level `*BridgeTest` that proves the runtime
117+
honors the sidecar (e.g. `SpringAiAgentRuntime.execute` calls
118+
`promptSpec.advisors(perRequestAdvisors)` only when `SpringAiAdvisors.from(context)`
119+
returns non-empty). See the per-module READMEs for full DSL examples:
120+
[`modules/spring-ai`](https://github.com/Atmosphere/atmosphere/blob/main/modules/spring-ai/README.md#per-request-advisors-springaiadvisors),
121+
[`modules/langchain4j`](https://github.com/Atmosphere/atmosphere/blob/main/modules/langchain4j/README.md#per-request-aiservices-langchain4jaiservices),
122+
[`modules/koog`](https://github.com/Atmosphere/atmosphere/blob/main/modules/koog/README.md#per-request-strategy-koogstrategy),
123+
[`modules/adk`](https://github.com/Atmosphere/atmosphere/blob/main/modules/adk/README.md#multi-agent-composition-adkrootagent),
124+
and the [`ToolLoopPolicy`](https://github.com/Atmosphere/atmosphere/blob/main/modules/ai/README.md#tool-loop-policy) section.
125+
126+
Other runtimes (`AgentScope`, `Embabel`, `SemanticKernel`, `SpringAiAlibaba`) do
127+
not yet ship a per-request bridge. `Embabel` did get **native streaming** in the
128+
same merge: when `StreamingPromptRunnerBuilder.streaming().generateStream()` is
129+
available the runtime emits `Flux<String>` chunks directly to the session, with
130+
graceful fallback to `runner.generateText(...)` when the streaming API is absent.
131+
132+
### Model-Lifecycle Observability
133+
134+
`AgentLifecycleListener` exposes three model-lifecycle hooks in addition to the
135+
tool hooks (`onToolCall`/`onToolResult`):
136+
137+
```java
138+
default void onModelStart(String model, int messageCount, int toolCount) { }
139+
default void onModelEnd(String model, TokenUsage usage, long durationMillis) { }
140+
default void onModelError(String model, Throwable t) { }
141+
```
142+
143+
Built-in `OpenAiCompatibleClient` fires these around every model dispatch
144+
(including each tool-loop round). `AiEventForwardingListener` is a built-in
145+
adapter that translates the hooks into `AiEvent.Progress` frames on the
146+
streaming session — opt in by attaching it via `context.withListeners(...)`:
147+
148+
```java
149+
var listeners = List.of(new AiEventForwardingListener(session));
150+
runtime.execute(context.withListeners(listeners), session);
151+
// Browser receives wire frames like:
152+
// {"type":"progress","message":"model:start (gpt-4o, msgs=3, tools=2)"}
153+
// {"type":"progress","message":"model:end (gpt-4o, in=120, out=85, ms=842)"}
154+
```
155+
82156
## Conversation Memory
83157

84158
Enable multi-turn conversations with one annotation attribute:

0 commit comments

Comments
 (0)