Agent Development Kit (ADK) for Java
Agent Development Kit (ADK) 是一个专为开发者设计的开源Java工具包,用于构建、评估和部署复杂的AI代理。它采用代码优先的开发方式,让您能够直接在Java代码中定义代理行为、编排流程和工具使用,实现强大的调试、版本控制和从本地到云端的灵活部署。
✨ 功能特性
丰富的工具生态系统
- 利用预构建工具、自定义函数、OpenAPI规范或集成现有工具
- 紧密集成谷歌生态系统服务
- 支持MCP工具集和远程A2A代理通信
代码优先开发
- 直接在Java中定义代理逻辑、工具和编排
- 提供终极的灵活性、可测试性和版本控制
- 类型安全的工具和代理配置
模块化多代理系统
- 通过组合多个专业代理设计可扩展应用程序
- 支持灵活的代理层次结构
- 顺序代理、并行代理和循环代理模式
开发工具支持
- 内置开发UI,帮助测试、评估、调试和展示代理
- 完整的遥测和日志记录支持
- 内存会话和工件服务
🚀 安装指南
系统要求
- Java 17+
- Maven 3.9+ 或 Gradle
Maven 依赖
在您的 pom.xml 中添加以下依赖:
<dependency>
<groupId>com.google.adk</groupId>
<artifactId>google-adk</artifactId>
<version>0.3.0</version>
</dependency>
<!-- 开发UI(可选) -->
<dependency>
<groupId>com.google.adk</groupId>
<artifactId>google-adk-dev</artifactId>
<version>0.3.0</version>
</dependency>
环境配置
设置Gemini API密钥:
export GOOGLE_GENAI_USE_VERTEXAI=FALSE
export GOOGLE_API_KEY=your_api_key
📚 使用说明
基础代理创建
import com.google.adk.agents.LlmAgent;
import com.google.adk.tools.GoogleSearchTool;
// 创建基础搜索代理
LlmAgent searchAgent = LlmAgent.builder()
.name("search_assistant")
.description("能够搜索网络的助手")
.model("gemini-2.0-flash")
.instruction("你是一个有用的助手。需要时使用谷歌搜索回答用户问题。")
.tools(new GoogleSearchTool())
.build();
骰子滚动和质数检查示例
// HelloWorldAgent.java - 完整的代理实现
public class HelloWorldAgent {
public static final LlmAgent ROOT_AGENT =
LlmAgent.builder()
.name("data_processing_agent")
.description("可以掷骰子和检查质数的代理")
.model("gemini-2.0-flash")
.instruction("""
你掷骰子并回答关于骰子结果的问题。
你可以掷不同面数的骰子。
当被要求掷骰子时,必须调用roll_die工具。
检查质数时,调用check_prime工具并传递整数列表。
""")
.tools(ImmutableList.of(
FunctionTool.create(HelloWorldAgent.class, "rollDie"),
FunctionTool.create(HelloWorldAgent.class, "checkPrime")))
.build();
// 工具方法实现
public static ImmutableMap<String, Object> rollDie(int sides, ToolContext toolContext) {
int result = new Random().nextInt(sides) + 1;
// 状态管理
ArrayList<Integer> rolls = (ArrayList<Integer>)
toolContext.state().computeIfAbsent("rolls", k -> new ArrayList<>());
rolls.add(result);
return ImmutableMap.of("result", result);
}
public static ImmutableMap<String, Object> checkPrime(List<Integer> nums) {
Set<String> primes = new HashSet<>();
for (int num : nums) {
boolean isPrime = true;
for (int i = 2; i <= Math.sqrt(num); i++) {
if (num % i == 0) {
isPrime = false;
break;
}
}
if (isPrime && num > 1) {
primes.add(String.valueOf(num));
}
}
return ImmutableMap.of("result",
primes.isEmpty() ? "未找到质数。" : String.join(", ", primes) + " 是质数。");
}
}
运行代理会话
// HelloWorldRun.java - 代理运行器
public class HelloWorldRun {
private final Runner runner;
private final String sessionId;
public HelloWorldRun() {
String appName = "hello-world-app";
String userId = "hello-world-user";
this.sessionId = UUID.randomUUID().toString();
InMemorySessionService sessionService = new InMemorySessionService();
this.runner = new Runner(
HelloWorldAgent.ROOT_AGENT,
appName,
new InMemoryArtifactService(),
sessionService,
new InMemoryMemoryService());
// 初始化会话
var unused = sessionService.createSession(appName, userId,
new ConcurrentHashMap<>(), sessionId).blockingGet();
}
public void run(String prompt) {
System.out.println("You> " + prompt);
Content userMessage = Content.builder()
.role("user")
.parts(ImmutableList.of(Part.builder().text(prompt).build()))
.build();
RunConfig runConfig = RunConfig.builder().build();
Flowable<Event> eventStream = this.runner.runAsync(
this.userId, this.sessionId, userMessage, runConfig);
// 处理代理响应
List<Event> agentEvents = Lists.newArrayList(eventStream.blockingIterable());
StringBuilder response = new StringBuilder("Agent> ");
for (Event event : agentEvents) {
response.append(event.stringifyContent().stripTrailing());
}
System.out.println(response);
}
public static void main(String[] args) {
HelloWorldRun runner = new HelloWorldRun();
runner.run("掷一个60面的骰子。");
runner.run("检查这个数字是否是质数。");
}
}
A2A远程代理集成
// A2A远程代理通信示例
public class A2AAgent {
public static LlmAgent createRootAgent(String primeAgentBaseUrl) {
BaseAgent primeAgent = createRemoteAgent(primeAgentBaseUrl);
return LlmAgent.builder()
.name("root_agent")
.model("gemini-2.0-flash")
.instruction("""
你可以在本地掷骰子,并将质数检查委托给远程prime_agent。
1. 当用户要求掷骰子时,将请求路由到roll_agent
2. 当用户要求检查质数时,委托给prime_agent
3. 如果用户要求先掷骰子再检查,先由roll_agent处理,然后由prime_agent处理结果
""")
.subAgents(ImmutableList.of(ROLL_AGENT, primeAgent))
.build();
}
private static BaseAgent createRemoteAgent(String primeAgentBaseUrl) {
AgentCard agentCard = new AgentCard.Builder()
.name("prime_agent")
.description("用于第三方A2A演示的存根代理元数据")
.url(primeAgentBaseUrl)
.version("1.0.0")
.build();
A2AClient client = new A2AClient(agentCard, new JdkA2AHttpClient(), null);
return RemoteA2AAgent.builder()
.name(agentCard.name())
.agentCardOrSource(agentCard)
.a2aClient(client)
.build();
}
}
🔧 核心代码解析
基础代理架构
// BaseAgent.java - 代理基类
public abstract class BaseAgent {
private final String name;
private final String description;
private final List<BaseAgent> subAgents;
protected BaseAgent(String name, String description, List<BaseAgent> subAgents) {
this.name = name;
this.description = description;
this.subAgents = subAgents != null ? subAgents : ImmutableList.of();
}
// 异步运行代理
protected abstract Flowable<Event> runAsyncImpl(InvocationContext invocationContext);
// 实时模式运行
protected Flowable<Event> runLiveImpl(InvocationContext invocationContext) {
throw new UnsupportedOperationException("实时模式未实现");
}
}
LLM代理实现
// LlmAgent.java - LLM驱动的代理
public class LlmAgent extends BaseAgent {
private final String model;
private final Instruction instruction;
private final ImmutableList<BaseTool> tools;
private final GenerateContentConfig generateContentConfig;
public static class Builder {
private String name;
private String description = "";
private String model;
private Instruction instruction;
private ImmutableList<BaseTool> tools = ImmutableList.of();
private GenerateContentConfig generateContentConfig;
public LlmAgent build() {
return new LlmAgent(name, description, model, instruction,
tools, generateContentConfig, null, null);
}
}
@Override
protected Flowable<Event> runAsyncImpl(InvocationContext invocationContext) {
// 使用SingleFlow处理LLM请求和响应
BaseFlow flow = new SingleFlow();
return flow.run(invocationContext);
}
}
工具系统
// BaseTool.java - 工具基类
public abstract class BaseTool {
private final String name;
private final String description;
private final boolean isLongRunning;
// 获取工具声明
public abstract Optional<FunctionDeclaration> declaration();
// 执行工具调用
public abstract Single<Map<String, Object>> call(
Map<String, Object> arguments, ToolContext toolContext);
}
函数工具实现
// FunctionTool.java - 基于Java方法的工具
public class FunctionTool extends BaseTool {
private final Method method;
private final Object instance;
private final FunctionDeclaration declaration;
public static FunctionTool create(Class<?> clazz, String methodName) {
try {
Method method = clazz.getMethod(methodName,
int.class, ToolContext.class); // 根据实际参数调整
return new FunctionTool(method, null);
} catch (NoSuchMethodException e) {
throw new IllegalArgumentException("方法未找到: " + methodName, e);
}
}
@Override
public Single<Map<String, Object>> call(Map<String, Object> arguments,
ToolContext toolContext) {
try {
// 参数绑定和验证
Object[] args = bindArguments(arguments, toolContext);
Object result = method.invoke(instance, args);
// 结果验证和转换
return validateAndConvertResult(result);
} catch (Exception e) {
return Single.error(new ToolExecutionException("工具执行失败", e));
}
}
}
会话和状态管理
// Session.java - 会话管理
public final class Session extends JsonBaseModel {
private final String id;
private final String appName;
private final String userId;
private final State state;
private final List<Event> events;
private Instant lastUpdateTime;
// 状态管理支持并发访问
public static class State implements ConcurrentMap<String, Object> {
private final ConcurrentMap<String, Object> state;
private final ConcurrentMap<String, Object> delta;
// 自动跟踪状态变化
@Override
public Object put(String key, Object value) {
Object oldValue = state.put(key, value);
delta.put(key, value); // 记录变化
return oldValue;
}
}
}
这些核心组件共同构成了ADK Java版的强大基础,提供了灵活而强大的AI代理开发框架。