谷歌Agent开发套件(ADK) Java版 - 构建智能AI代理的代码优先工具包

124 阅读5分钟

Agent Development Kit (ADK) for Java

Version转存失败,建议直接上传图片文件 License转存失败,建议直接上传图片文件

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代理开发框架。