Skip to content

Commit 48f880b

Browse files
committed
docs(spring-boot-starter): rewrite READMEs for the post-rebase shape
Starter README now documents: - The new artifactId (google-adk-spring-boot-starter) - The recommended pairing with google-adk-spring-ai for LLMs - The new @bean Runner autoconfig (users no longer hand-write a Runner) - The full adk.* property surface including Firestore + extended RunConfig - The persistence-backend matrix (IN_MEMORY / VERTEX_AI / FIRESTORE / GCS) - A dedicated 'Multiple business-unit agents in one Spring Boot app' section showing the @ConditionalOnSingleCandidate(App.class) escape hatch - All eight auto-config classes by name + activation rules - Fail-fast conditions with remediation messages - The follow-up Spring AI bridges as a documented roadmap item Sample README: - Java 17 (not 21) - mvn -pl ... -am verify from repo root (no separate starter install) - Optional Spring AI substrate via google-adk-spring-ai - New lowercase package paths
1 parent a13cf32 commit 48f880b

2 files changed

Lines changed: 164 additions & 113 deletions

File tree

Lines changed: 132 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,102 +1,174 @@
11
# ADK Spring Boot Starter
22

3-
This starter integrates the Google Agent Development Kit (ADK) into Spring Boot applications.
4-
It provides auto-configuration for core services like Artifacts, Session, and Memory management.
3+
Spring Boot auto-configuration for the [Agent Development Kit (ADK)](https://github.com/google/adk-java) runtime.
54

6-
## Installation
5+
After adding this starter, declare a single `@Bean App` (your agent topology) and the starter wires the rest: `Runner`, `BaseSessionService`, `BaseArtifactService`, optionally `BaseMemoryService`, and `RunConfig`. The starter is **LLM-agnostic** — pair it with `google-adk-spring-ai` for Spring AI LLMs, or declare your own `@Bean BaseLlm`.
76

8-
Add the following dependency to your `pom.xml`:
7+
## Installation
98

109
```xml
1110
<dependency>
1211
<groupId>com.google.adk</groupId>
13-
<artifactId>adk-spring-boot-starter</artifactId>
14-
<version>${adk-starter.version}</version>
12+
<artifactId>google-adk-spring-boot-starter</artifactId>
13+
<version>${adk.version}</version>
14+
</dependency>
15+
16+
<!-- Recommended companion for Spring AI users (OpenAI / Anthropic / Gemini / Ollama / Azure OpenAI / Bedrock): -->
17+
<dependency>
18+
<groupId>com.google.adk</groupId>
19+
<artifactId>google-adk-spring-ai</artifactId>
20+
<version>${adk.version}</version>
1521
</dependency>
1622
```
1723

18-
## Configuration
24+
The starter declares `google-adk-firestore-session-service` as an `<optional>true</optional>` dependency. It is on your runtime classpath by default — explicitly exclude it if you do not want Firestore-related auto-configurations to activate.
1925

20-
By default, the starter configures all services to use **In-Memory** implementations. This is great for local development and testing.
26+
## Quick Start
2127

22-
You can configure the behavior using `application.yaml`:
28+
```java
29+
@SpringBootApplication
30+
class MyApp {
31+
public static void main(String[] args) { SpringApplication.run(MyApp.class, args); }
32+
}
2333

24-
### 1. Artifacts Service
34+
@Configuration
35+
class MyAgents {
36+
@Bean public LlmAgent rootAgent(SpringAI llm) { // SpringAI bean comes from google-adk-spring-ai
37+
return LlmAgent.builder()
38+
.name("root_agent")
39+
.model(llm)
40+
.instruction("Answer concisely.")
41+
.build();
42+
}
43+
@Bean public App app(LlmAgent rootAgent,
44+
@Value("${spring.application.name}") String appName) {
45+
return App.builder().name(appName).rootAgent(rootAgent).build();
46+
}
47+
}
2548

26-
* **Default**: `InMemoryArtifactService`
27-
* **Production**: `GcsArtifactService` (Google Cloud Storage)
49+
@RestController
50+
class ChatController {
51+
private final Runner runner; // provided by starter
52+
private final RunConfig runConfig; // provided by starter
53+
private final BaseSessionService sessionService; // provided by starter
54+
ChatController(Runner r, RunConfig c, BaseSessionService s) {
55+
this.runner = r; this.runConfig = c; this.sessionService = s;
56+
}
57+
@PostMapping("/chat") String chat(@RequestBody String prompt) {
58+
String userId = "alice";
59+
String sessionId = UUID.randomUUID().toString();
60+
sessionService.createSession(runner.appName(), userId, null, sessionId).blockingGet();
61+
Content msg = Content.builder().role("user").parts(List.of(Part.builder().text(prompt).build())).build();
62+
return runner.runAsync(userId, sessionId, msg, runConfig)
63+
.toList().blockingGet()
64+
.stream().map(Event::stringifyContent).collect(joining());
65+
}
66+
}
67+
```
2868

29-
To enable GCS:
69+
## Property Reference
3070

3171
```yaml
72+
spring:
73+
application:
74+
name: my_app # used as the App's appName (must match validateAppName regex)
75+
3276
adk:
3377
artifacts:
34-
gcs-enabled: true
35-
bucket-name: "my-agent-artifacts-bucket"
36-
```
37-
38-
### 2. Session Service
39-
40-
* **Default**: `InMemorySessionService`
41-
* **Production**: `VertexAiSessionService`
78+
gcs-enabled: false # default; switch to true to use Google Cloud Storage
79+
# bucket-name: my-artifacts-bucket # required when gcs-enabled=true (fail-fast otherwise)
4280

43-
To enable Vertex AI Sessions:
44-
45-
```yaml
46-
adk:
4781
session:
48-
type: VERTEX_AI
49-
project-id: "my-gcp-project"
50-
location: "us-central1"
51-
```
82+
type: IN_MEMORY # IN_MEMORY | VERTEX_AI | FIRESTORE
83+
# project-id: my-gcp-project # required for VERTEX_AI
84+
# location: us-central1 # required for VERTEX_AI
5285

53-
### 3. Memory Service
86+
memory:
87+
type: IN_MEMORY # IN_MEMORY | FIRESTORE
88+
# VERTEX_AI is reserved — fails fast (no impl exists in ADK)
5489

55-
* **Default**: `InMemoryMemoryService`
90+
run-config:
91+
streaming-mode: NONE # NONE | SSE | BIDI
92+
max-llm-calls: 500
93+
tool-execution-mode: NONE # NONE | SEQUENTIAL | PARALLEL | PARALLEL_SUBSCRIBE
94+
save-input-blobs-as-artifacts: false
95+
auto-create-session: false
96+
97+
firestore: # only consulted when session/memory type=FIRESTORE
98+
# project-id: my-gcp-project # optional — falls back to ADC project
99+
# database-id: "(default)" # optional — falls back to "(default)"
100+
```
56101

57-
Currently, only In-Memory memory service is supported by default.
102+
## Persistence Backends
58103

104+
| Concern | `IN_MEMORY` | `VERTEX_AI` | `FIRESTORE` | GCS (artifacts only) |
105+
|------------|-------------|------------------------------------|--------------------------------------------|----------------------|
106+
| Sessions | default | `VertexAiSessionService` (managed) | `FirestoreSessionService` (contrib module) ||
107+
| Memory | default | n/a — fails fast | `FirestoreMemoryService` (contrib module) ||
108+
| Artifacts | default | n/a | n/a | `GcsArtifactService` |
59109

60-
### 4. Run Configuration
110+
The Firestore branches activate only when the `google-adk-firestore-session-service` module is on the classpath (gated by `@ConditionalOnClass`). The starter declares it as an optional dependency — exclude it from your application pom if you want to keep Firestore wiring off the classpath entirely.
61111

62-
* **Default Streaming Mode**: `NONE`
112+
## Multiple business-unit agents in one Spring Boot app
63113

64-
To enable streaming (e.g., SSE or BIDI):
114+
ADK's `appName` is the partition key for sessions, memory, and artifacts. A single Spring Boot app can host multiple independent agentic applications (one per business unit) by declaring multiple `@Bean App`. The starter's `@Bean Runner` auto-config uses `@ConditionalOnSingleCandidate(App.class)`, so it steps aside cleanly when multiple Apps exist — wire one `Runner` per `App` explicitly:
65115

66-
```yaml
67-
adk:
68-
run-config:
69-
streaming-mode: SSE # Options: NONE, SSE, BIDI
116+
```java
117+
@Configuration
118+
class BusinessUnits {
119+
120+
@Bean App salesApp(SpringAI llm) {
121+
return App.builder().name("sales").rootAgent(salesRootAgent(llm)).build();
122+
}
123+
@Bean App supportApp(SpringAI llm) {
124+
return App.builder().name("support").rootAgent(supportRootAgent(llm)).build();
125+
}
126+
// ... per-BU rootAgent bean factories ...
127+
128+
@Bean Runner salesRunner(
129+
@Qualifier("salesApp") App app,
130+
BaseArtifactService artifactService,
131+
BaseSessionService sessionService) {
132+
return Runner.builder().app(app).artifactService(artifactService).sessionService(sessionService).build();
133+
}
134+
@Bean Runner supportRunner(
135+
@Qualifier("supportApp") App app,
136+
BaseArtifactService artifactService,
137+
BaseSessionService sessionService) {
138+
return Runner.builder().app(app).artifactService(artifactService).sessionService(sessionService).build();
139+
}
140+
}
70141
```
71142

72-
*Note: Other `RunConfig` options (like modalities, audio config) will be added in future versions.*
143+
The shared `BaseSessionService`, `BaseArtifactService`, `BaseMemoryService`, and `RunConfig` beans are singletons partitioned internally by `appName`. No duplication — and no per-BU service wiring boilerplate.
73144

74145
## Architecture
75146

76-
The starter follows the Single Responsibility Principle by splitting configuration into:
77-
* `AdkArtifactsAutoConfiguration`
78-
* `AdkSessionAutoConfiguration`
79-
* `AdkMemoryAutoConfiguration`
80-
* `AdkRunConfigAutoConfiguration`
147+
Eight auto-configuration classes, each owning one concern:
81148

82-
Each has its own properties class (e.g., `AdkArtifactProperties`).
149+
| Auto-config | Produces | Activation |
150+
|------------------------------------------------|---------------------------------------|-------------------------------------------------------------------------------|
151+
| `AdkArtifactsAutoConfiguration` | `BaseArtifactService`, conditional `Storage` | always; `Storage` only when `adk.artifacts.gcs-enabled=true` |
152+
| `AdkSessionAutoConfiguration` | `BaseSessionService` (IN_MEMORY, VERTEX_AI) | always; FIRESTORE falls through to the Firestore variant when on classpath |
153+
| `AdkFirestoreSessionAutoConfiguration` | `BaseSessionService` (FIRESTORE) | `@ConditionalOnClass(FirestoreSessionService.class)`; `@AutoConfigureBefore` |
154+
| `AdkMemoryAutoConfiguration` | `BaseMemoryService` (IN_MEMORY) | always; FIRESTORE falls through; VERTEX_AI fails fast |
155+
| `AdkFirestoreMemoryAutoConfiguration` | `BaseMemoryService` (FIRESTORE) | `@ConditionalOnClass(FirestoreMemoryService.class)`; `@AutoConfigureBefore` |
156+
| `AdkRunConfigAutoConfiguration` | `RunConfig` | always |
157+
| `AdkFirestoreAutoConfiguration` | `Firestore` client | `@ConditionalOnClass(Firestore.class)` |
158+
| `AdkRunnerAutoConfiguration` | `Runner` | `@ConditionalOnBean(App.class)` + `@ConditionalOnSingleCandidate(App.class)` |
83159

84-
## Usage
160+
Every `@Bean` factory uses `@ConditionalOnMissingBean` so any user-declared override (`Storage`, `Firestore`, `BaseSessionService`, `Runner`, etc.) always wins.
85161

86-
Simply inject the beans into your application:
162+
## Failure Modes
87163

88-
```java
89-
@Service
90-
public class MyAgentService {
164+
The starter fails fast at startup (throwing `BeanCreationException` with a clear remediation message) when:
91165

92-
private final Runner runner;
93-
// Agent bean is no longer auto-configured by default.
94-
// You must define your own Agent bean or use the Runner directly.
166+
- `adk.artifacts.gcs-enabled=true` but `adk.artifacts.bucket-name` is blank.
167+
- `adk.session.type=VERTEX_AI` but `project-id` or `location` is blank.
168+
- `adk.session.type=FIRESTORE` but `google-adk-firestore-session-service` is not on the classpath.
169+
- `adk.memory.type=VERTEX_AI` (no Vertex AI memory service exists in ADK today).
170+
- `adk.memory.type=FIRESTORE` but the contrib jar is missing.
95171

96-
public MyAgentService(Runner runner) {
97-
this.runner = runner;
98-
}
172+
## Roadmap — not in this module
99173

100-
// ... use runner
101-
}
102-
```
174+
Bridges from Spring AI primitives into ADK service interfaces (`ChatMemory` → sessions, `VectorStore` → memory, `ToolCallback` → tools incl. MCP) are planned for `contrib/spring-ai` as a follow-up PR. Once they land, this starter will gain `SPRING_AI_CHAT_MEMORY` / `SPRING_AI_VECTOR_STORE` enum values that activate the bridges when the contrib classes are on the classpath. New artifact backends (S3, Azure Blob, filesystem) require new `BaseArtifactService` impls upstream in ADK first.
Lines changed: 32 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,76 +1,55 @@
11
# Spring Boot ADK Template
22

3-
This project is a Spring Boot application that serves as a template and verification app for the **Google ADK Spring Boot Starter**.
3+
Sample Spring Boot application demonstrating the **`google-adk-spring-boot-starter`** in its simplest form. The user code consists of:
44

5-
It demonstrates how to integrate the Google Agent Development Kit (ADK) into a Spring Boot application using the custom starter.
5+
- One `@Bean LlmAgent rootAgent()` — the agent topology
6+
- One `@Bean App` — wraps the root agent under an app name
7+
- One `@Service AgentService` — illustrates injection of the starter-provided `Runner`
68

7-
## Features
8-
9-
* **ADK Integration**: Uses `adk-spring-boot-starter` for auto-configuration.
10-
* **Agent Configuration**: Defines a sample `LlmAgent` bean.
11-
* **Bean Verification**: Verifies the injection of core ADK components (`Runner`, `RunConfig`, `ArtifactService`, etc.) on startup.
12-
* **Reactive Web**: Built on Spring WebFlux (though the current test scenario is console-based).
9+
Everything else (`Runner`, `BaseSessionService`, `BaseArtifactService`, `RunConfig`) is wired by the starter.
1310

1411
## Prerequisites
1512

16-
* Java 21
17-
* Maven
18-
* **adk-spring-boot-starter**: This project depends on the local `adk-spring-boot-starter` artifact. You must build and install the starter first.
19-
20-
## Getting Started
13+
- Java 17
14+
- Maven
15+
- This module is built as part of the ADK aggregator; no separate install of the starter is required.
2116

22-
### 1. Build the ADK Starter
17+
## Build and run
2318

24-
Before running this application, ensure the starter is installed in your local Maven repository:
19+
From the repository root:
2520

2621
```bash
27-
cd ../adk-spring-boot-starter
28-
./mvnw clean install -DskipTests
22+
mvn -pl contrib/samples/spring-boot-adk-template -am verify
2923
```
3024

31-
### 2. Build and Run the Template
25+
To run interactively:
3226

3327
```bash
34-
cd ../SpringBootAdkTemplate
35-
./mvnw spring-boot:run
28+
mvn -pl contrib/samples/spring-boot-adk-template -am spring-boot:run
3629
```
3730

38-
### 3. Verify Output
31+
## Configuration
3932

40-
On successful startup, you should see logs indicating the ADK components have been initialized:
33+
`src/main/resources/application.yaml` shows the full property surface as comments. The defaults give an all-in-memory configuration with no GCP credentials required — switch backends by uncommenting the relevant blocks (`adk.session.type=VERTEX_AI`, `adk.session.type=FIRESTORE`, `adk.artifacts.gcs-enabled=true`, etc.).
4134

42-
```text
43-
=== ADK Starter Verification ===
44-
Service Info: Agent created: LlmAgent, Runner: ...
45-
Run Config streaming mode: NONE
46-
RunConfig: com.google.adk.agents.RunConfig
47-
Runner: com.google.adk.runner.Runner
48-
BaseArtifactService: com.google.adk.artifacts.BaseArtifactService
49-
...
50-
================================
51-
```
35+
See the [starter README](../../adk-spring-boot-starter/README.md) for the full property reference.
5236

53-
## Configuration
37+
## Use Spring AI as the LLM substrate (optional)
5438

55-
The application is configured via `src/main/resources/application.yaml`.
56-
57-
Key ADK properties (managed by the starter):
58-
59-
```yaml
60-
adk:
61-
run-config:
62-
streaming-mode: NONE # Options: NONE, SSE, BIDI
63-
artifacts:
64-
gcs-enabled: false # Set to true to use Google Cloud Storage
65-
# bucket-name: my-bucket
66-
session:
67-
type: IN_MEMORY # Options: IN_MEMORY, VERTEX_AI
68-
memory:
69-
type: IN_MEMORY
70-
```
39+
This sample uses a string model name (`"gemini-2.5-flash"`). To swap to Spring AI's `ChatModel` ecosystem (OpenAI, Anthropic, Gemini, Ollama, Vertex AI, Azure OpenAI, Bedrock):
40+
41+
1. Add `com.google.adk:google-adk-spring-ai` and your preferred Spring AI provider artifact to `pom.xml`.
42+
2. Configure the provider via `spring.ai.*` properties (e.g. `spring.ai.openai.api-key`).
43+
3. Inject the auto-configured `SpringAI` bean into `AgentConfig.rootAgent()` and pass it to `.model(...)`.
7144

72-
## Project Structure
45+
## Project structure
7346

74-
* `src/main/java/com/example/SpringBootAdkTemplate/config/AgentConfig.java`: Defines the `LlmAgent` and `Runner` beans.
75-
* `src/main/java/com/example/SpringBootAdkTemplate/AgentService.java`: Service that uses the `Runner`.
76-
* `src/main/java/com/example/SpringBootAdkTemplate/SpringBootAdkTemplateApplication.java`: Main entry point with verification logic.
47+
```
48+
src/main/java/com/example/springbootadktemplate/
49+
├── SpringBootAdkTemplateApplication.java — @SpringBootApplication entry point
50+
├── AgentService.java — sample @Service injecting Runner + LlmAgent
51+
└── config/AgentConfig.java — @Bean LlmAgent + @Bean App
52+
src/main/resources/application.yaml — spring.application.name + (commented) adk.* properties
53+
src/test/java/com/example/springbootadktemplate/
54+
└── SpringBootAdkTemplateApplicationTest.java — context-load test asserting every starter bean is reachable
55+
```

0 commit comments

Comments
 (0)