Skip to content

Commit 72ee62f

Browse files
authored
feat(starter): Spring Boot Starter Integration (#168)
1 parent cffe23f commit 72ee62f

14 files changed

Lines changed: 1321 additions & 0 deletions

File tree

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
~ Copyright 2024-2025 the original author or authors.
4+
~
5+
~ Licensed under the Apache License, Version 2.0 (the "License");
6+
~ you may not use this file except in compliance with the License.
7+
~ You may obtain a copy of the License at
8+
~
9+
~ http://www.apache.org/licenses/LICENSE-2.0
10+
~
11+
~ Unless required by applicable law or agreed to in writing, software
12+
~ distributed under the License is distributed on an "AS IS" BASIS,
13+
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
~ See the License for the specific language governing permissions and
15+
~ limitations under the License.
16+
-->
17+
<project xmlns="http://maven.apache.org/POM/4.0.0"
18+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
19+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
20+
<modelVersion>4.0.0</modelVersion>
21+
22+
<parent>
23+
<groupId>io.agentscope</groupId>
24+
<artifactId>agentscope-spring-boot-starters</artifactId>
25+
<version>${revision}</version>
26+
</parent>
27+
28+
<artifactId>agentscope-spring-boot-starter</artifactId>
29+
<name>AgentScope Java - Spring Boot Starter</name>
30+
<description>Spring Boot starter for integrating AgentScope Java</description>
31+
32+
33+
<properties>
34+
<spring-boot.version>3.5.0</spring-boot.version>
35+
<maven.deploy.skip>false</maven.deploy.skip>
36+
</properties>
37+
38+
<dependencies>
39+
<!-- Core AgentScope library -->
40+
<dependency>
41+
<groupId>io.agentscope</groupId>
42+
<artifactId>agentscope-core</artifactId>
43+
</dependency>
44+
45+
<!-- Spring Boot auto-configuration SPI -->
46+
<dependency>
47+
<groupId>org.springframework.boot</groupId>
48+
<artifactId>spring-boot-autoconfigure</artifactId>
49+
<version>${spring-boot.version}</version>
50+
</dependency>
51+
52+
<!-- Configuration properties metadata processor -->
53+
<dependency>
54+
<groupId>org.springframework.boot</groupId>
55+
<artifactId>spring-boot-configuration-processor</artifactId>
56+
<version>${spring-boot.version}</version>
57+
<optional>true</optional>
58+
</dependency>
59+
60+
<!-- Test dependencies -->
61+
<dependency>
62+
<groupId>org.springframework.boot</groupId>
63+
<artifactId>spring-boot-starter-test</artifactId>
64+
<scope>test</scope>
65+
</dependency>
66+
</dependencies>
67+
68+
</project>
69+
70+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
/*
2+
* Copyright 2024-2025 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* You may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.agentscope.spring.boot;
17+
18+
import io.agentscope.core.ReActAgent;
19+
import io.agentscope.core.memory.InMemoryMemory;
20+
import io.agentscope.core.memory.Memory;
21+
import io.agentscope.core.model.Model;
22+
import io.agentscope.core.tool.Toolkit;
23+
import io.agentscope.spring.boot.model.ModelProviderType;
24+
import io.agentscope.spring.boot.properties.AgentProperties;
25+
import io.agentscope.spring.boot.properties.AgentscopeProperties;
26+
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
27+
import org.springframework.boot.autoconfigure.AutoConfiguration;
28+
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
29+
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
30+
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
31+
import org.springframework.boot.context.properties.EnableConfigurationProperties;
32+
import org.springframework.context.annotation.Bean;
33+
import org.springframework.context.annotation.Scope;
34+
35+
/**
36+
* Spring Boot auto-configuration that exposes default Model, Memory, Toolkit
37+
* and ReActAgent beans
38+
* for AgentScope.
39+
*
40+
* <p>
41+
* Basic configuration with DashScope (default provider):
42+
*
43+
* <pre>{@code
44+
* agentscope:
45+
* # Select model provider (defaults to dashscope when omitted)
46+
* model:
47+
* provider: dashscope
48+
*
49+
* dashscope:
50+
* enabled: true
51+
* api-key: ${DASHSCOPE_API_KEY}
52+
* model-name: qwen-plus
53+
* stream: true
54+
* enable-thinking: true
55+
*
56+
* agent:
57+
* enabled: true
58+
* name: "Assistant"
59+
* sys-prompt: "You are a helpful AI assistant."
60+
* max-iters: 10
61+
* }</pre>
62+
*
63+
* <p>
64+
* Using OpenAI as provider:
65+
*
66+
* <pre>{@code
67+
* agentscope:
68+
* model:
69+
* provider: openai
70+
*
71+
* openai:
72+
* enabled: true
73+
* api-key: ${OPENAI_API_KEY}
74+
* model-name: gpt-4.1-mini
75+
* stream: true
76+
* }</pre>
77+
*
78+
* <p>
79+
* Using Gemini as provider (direct API):
80+
*
81+
* <pre>{@code
82+
* agentscope:
83+
* model:
84+
* provider: gemini
85+
*
86+
* gemini:
87+
* enabled: true
88+
* api-key: ${GEMINI_API_KEY}
89+
* model-name: gemini-2.0-flash
90+
* stream: true
91+
* }</pre>
92+
*
93+
* <p>
94+
* Using Gemini via Vertex AI:
95+
*
96+
* <pre>{@code
97+
* agentscope:
98+
* model:
99+
* provider: gemini
100+
*
101+
* gemini:
102+
* enabled: true
103+
* project: your-gcp-project-id
104+
* location: us-central1
105+
* model-name: gemini-2.0-flash
106+
* vertex-ai: true
107+
* stream: true
108+
* }</pre>
109+
*
110+
* <p>
111+
* Using Anthropic as provider:
112+
*
113+
* <pre>{@code
114+
* agentscope:
115+
* model:
116+
* provider: anthropic
117+
*
118+
* anthropic:
119+
* enabled: true
120+
* api-key: ${ANTHROPIC_API_KEY}
121+
* model-name: claude-sonnet-4.5
122+
* stream: true
123+
* }</pre>
124+
*/
125+
@AutoConfiguration
126+
@EnableConfigurationProperties(AgentscopeProperties.class)
127+
@ConditionalOnClass(ReActAgent.class)
128+
public class AgentscopeAutoConfiguration {
129+
130+
/**
131+
* Default Memory implementation backed by InMemoryMemory.
132+
*
133+
* <p>
134+
* Memory is stateful and not thread-safe, so we expose it as a prototype-scoped
135+
* bean.
136+
* In multi-threaded / web environments, it is recommended to obtain instances
137+
* lazily via
138+
* {@code ObjectProvider<Memory>} or method injection.
139+
*/
140+
@Bean
141+
@ConditionalOnMissingBean
142+
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
143+
public Memory agentscopeMemory() {
144+
return new InMemoryMemory();
145+
}
146+
147+
/**
148+
* Default Toolkit implementation with an initially empty tool set.
149+
*
150+
* <p>
151+
* Toolkit holds mutable state and is not thread-safe, so it is also exposed as
152+
* a
153+
* prototype-scoped bean. In application code, prefer obtaining instances lazily
154+
* via
155+
* {@code ObjectProvider<Toolkit>} or method injection.
156+
*/
157+
@Bean
158+
@ConditionalOnMissingBean
159+
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
160+
public Toolkit agentscopeToolkit() {
161+
return new Toolkit();
162+
}
163+
164+
/**
165+
* Default Model implementation.
166+
*
167+
* <p>
168+
* If DashScopeChatModel is on the classpath and dashscope auto-configuration is
169+
* enabled, this
170+
* method creates a DashScopeChatModel based on {@link ModelProviderType}
171+
* settings.
172+
*/
173+
@Bean
174+
@ConditionalOnMissingBean(Model.class)
175+
public Model agentscopeModel(AgentscopeProperties properties) {
176+
return ModelProviderType.fromProperties(properties).createModel(properties);
177+
}
178+
179+
/**
180+
* Default ReActAgent that wires together the configured Model, Memory and
181+
* Toolkit beans using
182+
* {@link AgentProperties}.
183+
*
184+
* <p>
185+
* ReActAgent keeps session-level state (memory, toolkit, etc.) and is not
186+
* thread-safe,
187+
* so it is exposed as a prototype-scoped bean. In Controllers / Services,
188+
* prefer injecting
189+
* {@code ObjectProvider<ReActAgent>} to obtain a new agent instance per session
190+
* or request.
191+
*/
192+
@Bean
193+
@ConditionalOnMissingBean
194+
@ConditionalOnProperty(
195+
prefix = "agentscope.agent",
196+
name = "enabled",
197+
havingValue = "true",
198+
matchIfMissing = true)
199+
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
200+
public ReActAgent agentscopeReActAgent(
201+
Model model, Memory memory, Toolkit toolkit, AgentscopeProperties properties) {
202+
AgentProperties config = properties.getAgent();
203+
return ReActAgent.builder()
204+
.name(config.getName())
205+
.sysPrompt(config.getSysPrompt())
206+
.model(model)
207+
.memory(memory)
208+
.toolkit(toolkit)
209+
.maxIters(config.getMaxIters())
210+
.build();
211+
}
212+
}

0 commit comments

Comments
 (0)