Files
Agent-Docs/ADKLearning/google-adk-tutorial/02-quick-start-hello-world.md
Nelson 514723dbe7 init
2026-04-06 12:36:04 +08:00

13 KiB
Raw Permalink Blame History

第02章快速开始 — Hello World

📌 本章目标

  • 使用 adk create 创建第一个 Agent 项目
  • 理解 Agent 项目结构
  • 编写一个带有自定义工具的 Agent
  • 通过 CLI 和 Web UI 两种方式运行 Agent

2.1 创建 Agent 项目

2.1.1 使用 CLI 创建项目

# 在工作目录下创建一个新的 Agent 项目
adk create hello_world

# 创建完成后,会生成以下目录结构:
# hello_world/
# ├── agent.py       # Agent 主代码文件(核心)
# ├── .env           # 环境变量配置文件API Key 等)
# └── __init__.py    # Python 包初始化文件

2.1.2 项目结构说明

hello_world/
│
├── agent.py          # 🔑 核心文件:定义 Agent 的行为和工具
│                     #    - root_agent 变量是 ADK 的入口点
│                     #    - 可以定义自定义工具函数
│
├── .env              # 🔑 配置文件:存储 API Key 等敏感信息
│                     #    - GOOGLE_API_KEY="your_key_here"
│                     #    - 不会被提交到版本控制
│
└── __init__.py       # Python 包标识文件
                      #    - 使目录成为 Python 包
                      #    - 通常为空文件

⚠️ 重要agent.py 中的 root_agent 是 ADK 识别 Agent 的入口点,这个变量名不能修改


2.2 编写第一个 Agent

2.2.1 最简单的 Agent

打开 agent.py,编写最基础的 Agent

"""
第一个 Google ADK Agent 示例
这是一个最简单的 Agent不包含任何自定义工具
"""

# 从 ADK 的 agents 模块导入 Agent 类
# Agent 是 LlmAgent 的别名,是最常用的智能体类型
from google.adk.agents import Agent

# 定义 root_agent —— 这是 ADK 的入口点
# ADK 会自动查找名为 root_agent 的变量
root_agent = Agent(
    name="hello_agent",                    # Agent 的名称,用于标识和日志
    model="gemini-2.0-flash",              # 使用的 LLM 模型
    instruction="你是一个友好的助手。",     # 系统指令,定义 Agent 的角色和行为
)

2.2.2 带工具的 Agent

让我们给 Agent 添加一个获取当前时间的工具:

"""
带自定义工具的 Hello World Agent
演示如何为 Agent 添加自定义函数工具
"""

# 导入 ADK 的 Agent 类
from google.adk.agents import Agent

# 导入标准库:日期时间处理
import datetime                            # 用于获取当前时间
from zoneinfo import ZoneInfo              # 用于处理时区信息


# ========================================
# 定义自定义工具函数
# ========================================

def get_current_time(city: str) -> dict:
    """
    获取指定城市的当前时间

    这个函数会被 ADK 自动转换为工具FunctionTool
    Agent 可以在对话中调用这个工具来获取时间信息。

    Args:
        city (str): 需要查询时间的城市名称,例如"北京"、"东京"、"纽约"

    Returns:
        dict: 包含状态和结果的字典
            - status: "success" 或 "error"
            - report: 时间信息或错误消息
    """
    # 定义城市到时区的映射字典
    city_timezone_map = {                    # 常见城市对应的时区
        "北京": "Asia/Shanghai",             # 北京使用上海时区
        "上海": "Asia/Shanghai",             # 上海使用上海时区
        "东京": "Asia/Tokyo",               # 东京时区
        "纽约": "America/New_York",         # 纽约时区
        "伦敦": "Europe/London",            # 伦敦时区
        "巴黎": "Europe/Paris",             # 巴黎时区
    }

    # 查找城市对应的时区标识符
    tz_identifier = city_timezone_map.get(city)  # 从字典中获取时区

    # 如果找不到该城市的时区信息
    if not tz_identifier:
        return {                            # 返回错误信息
            "status": "error",              # 状态标记为错误
            "error_message": f"未找到'{city}'的时区信息,请尝试其他城市。"  # 错误描述
        }

    # 根据时区标识符创建时区对象
    tz = ZoneInfo(tz_identifier)            # 创建 ZoneInfo 时区对象

    # 获取该时区的当前时间
    now = datetime.datetime.now(tz)         # 获取指定时区的当前时间

    # 格式化时间字符串
    time_str = now.strftime(                # 将时间格式化为字符串
        "%Y-%m-%d %H:%M:%S %Z%z"           # 格式:年-月-日 时:分:秒 时区
    )

    # 返回成功结果
    return {                                # 返回包含时间信息的字典
        "status": "success",                # 状态标记为成功
        "city": city,                       # 城市名称
        "time": time_str                    # 格式化后的时间字符串
    }


# ========================================
# 定义 Agent
# ========================================

root_agent = Agent(
    name="hello_agent",                     # Agent 的唯一标识名称
    model="gemini-2.0-flash",               # 使用 Gemini 2.0 Flash 模型
    description="一个能查询城市时间的友好助手。",  # Agent 的描述,用于多 Agent 场景
    instruction=(                           # 系统指令(多行字符串)
        "你是一个友好的助手,可以帮助用户查询世界各城市的当前时间。\n"
        "当用户询问某个城市的时间时,使用 get_current_time 工具来获取。\n"
        "如果工具返回错误,请友好地告知用户并建议尝试其他城市。\n"
        "回复时请使用中文。"
    ),
    tools=[get_current_time],               # 将自定义函数注册为 Agent 的工具
)

2.3 配置 API Key

在运行 Agent 之前,需要配置 API Key

# 方法一:在 .env 文件中配置(推荐)
echo 'GOOGLE_API_KEY="你的_GEMINI_API_KEY"' > hello_world/.env

# 方法二:通过环境变量设置
export GOOGLE_API_KEY="你的_GEMINI_API_KEY"

# 方法三:直接在代码中设置(不推荐,有安全风险)

💡 获取 API Key:访问 Google AI Studio,点击 "Create API Key" 即可免费获取。


2.4 运行 Agent

2.4.1 命令行交互模式CLI

# 在项目父目录下运行(不是在 hello_world 目录内)
adk run hello_world

# 运行后进入交互式对话界面:
# Running agent hello_agent, type exit to exit.
# [user]: 北京现在几点?
# [hello_agent]: 北京当前时间是 2025-04-05 14:30:00 CST+0800。
# [user]: exit

2.4.2 Web UI 模式

# 启动 Web 服务器(默认端口 8000
adk web --port 8000

# 浏览器打开 http://localhost:8000
# 在左上角选择 Agent然后输入问题进行对话

Web UI 提供以下功能:

  • 💬 对话界面:与 Agent 进行交互式对话
  • 📊 Event 面板:查看工具调用和事件流
  • 📋 Request/Response:查看原始请求和响应数据
  • 🔍 调试信息:帮助排查问题

2.4.3 代码方式运行

除了 CLI 和 Web UI还可以通过 Python 代码直接运行 Agent

"""
通过 Python 代码直接运行 Agent
适用于集成到自己的应用中
"""

# 导入必要的模块
from google.adk.agents import Agent          # Agent 类
from google.adk.runners import Runner        # 运行器,负责执行 Agent
from google.adk.sessions import InMemorySessionService  # 内存会话服务
from google.genai import types               # Google GenAI 类型定义

# 导入异步运行支持
import asyncio                               # 异步编程库


# ========================================
# 定义工具函数
# ========================================

def get_current_time(city: str) -> dict:
    """获取指定城市的当前时间"""
    import datetime                          # 导入日期时间模块
    from zoneinfo import ZoneInfo            # 导入时区模块

    city_timezone_map = {                    # 城市时区映射
        "北京": "Asia/Shanghai",
        "上海": "Asia/Shanghai",
        "东京": "Asia/Tokyo",
        "纽约": "America/New_York",
        "伦敦": "Europe/London",
    }

    tz_identifier = city_timezone_map.get(city)  # 查找时区
    if not tz_identifier:                    # 如果找不到时区
        return {                             # 返回错误
            "status": "error",
            "error_message": f"未找到'{city}'的时区信息"
        }

    tz = ZoneInfo(tz_identifier)             # 创建时区对象
    now = datetime.datetime.now(tz)          # 获取当前时间
    time_str = now.strftime("%Y-%m-%d %H:%M:%S %Z%z")  # 格式化时间

    return {                                 # 返回结果
        "status": "success",
        "city": city,
        "time": time_str
    }


# ========================================
# 定义 Agent
# ========================================

root_agent = Agent(
    name="hello_agent",                      # Agent 名称
    model="gemini-2.0-flash",                # 使用 Gemini 模型
    instruction="你是一个友好的时间查询助手。使用工具获取城市时间。",  # 系统指令
    tools=[get_current_time],                # 注册工具
)


# ========================================
# 定义运行逻辑
# ========================================

# 定义应用名称、用户ID和会话ID
APP_NAME = "hello_world_app"                # 应用名称,用于标识
USER_ID = "user_001"                        # 用户唯一标识
SESSION_ID = "session_001"                  # 会话唯一标识


async def main():
    """主函数:异步运行 Agent"""

    # 第一步:创建会话服务
    # InMemorySessionService 将会话数据存储在内存中
    # 适用于开发和测试,数据在程序重启后会丢失
    session_service = InMemorySessionService()

    # 第二步:创建会话
    # 会话Session代表一次对话交互
    # 包含消息历史、状态数据等
    session = await session_service.create_session(
        app_name=APP_NAME,                   # 关联的应用名称
        user_id=USER_ID,                     # 用户标识
        session_id=SESSION_ID,               # 会话标识
    )

    # 第三步:创建运行器
    # Runner 是 ADK 的核心执行引擎
    # 负责协调 Agent、会话服务和工具调用
    runner = Runner(
        agent=root_agent,                    # 要运行的 Agent
        app_name=APP_NAME,                   # 应用名称
        session_service=session_service,     # 会话服务
    )

    # 第四步:构造用户消息
    # Content 对象表示一条消息
    # role='user' 表示这是用户发送的消息
    content = types.Content(
        role='user',                         # 消息角色:用户
        parts=[types.Part(text='北京现在几点?')]  # 消息内容
    )

    # 第五步:运行 Agent 并获取响应
    # run_async 返回一个异步事件流
    # 我们需要遍历所有事件来获取最终响应
    events = runner.run_async(
        user_id=USER_ID,                     # 用户标识
        session_id=SESSION_ID,               # 会话标识
        new_message=content,                 # 用户消息
    )

    # 第六步:处理事件流
    async for event in events:               # 遍历所有事件
        if event.is_final_response():        # 如果是最终响应事件
            # 从事件中提取文本内容
            final_response = event.content.parts[0].text
            print(f"Agent 回复: {final_response}")  # 打印 Agent 的回复


# 运行主函数
if __name__ == "__main__":                  # 当脚本被直接运行时
    asyncio.run(main())                      # 使用 asyncio 运行异步主函数

2.5 理解 Agent 的核心参数

Agent 构造函数接受以下关键参数:

参数 类型 必需 说明
name str Agent 的唯一标识名称
model str 使用的 LLM 模型名称
instruction str 系统指令,定义 Agent 的角色和行为
description str Agent 描述,用于多 Agent 场景中的路由
tools list Agent 可用的工具列表
sub_agents list 子 Agent 列表,用于多 Agent 系统
output_key str 输出保存到 State 的键名
before_model_callback func 模型调用前的回调函数
after_model_callback func 模型调用后的回调函数
before_tool_callback func 工具调用前的回调函数
after_tool_callback func 工具调用后的回调函数

2.6 完整代码示例

详见 code/hello_world.py — 包含完整的带工具的 Hello World Agent 示例。


📌 本章小结

  • 使用 adk create 快速创建 Agent 项目
  • agent.py 中的 root_agent 是 ADK 的入口点
  • 自定义工具就是普通的 Python 函数ADK 会自动转换为 FunctionTool
  • 三种运行方式CLIadk run、Web UIadk web)、代码调用
  • Runner 是 ADK 的核心执行引擎,负责协调 Agent 和会话

下一章第03章 - LLM 智能体详解 → 深入了解 LlmAgent 的配置和高级用法。