# 第02章:快速开始 — Hello World ## 📌 本章目标 - 使用 `adk create` 创建第一个 Agent 项目 - 理解 Agent 项目结构 - 编写一个带有自定义工具的 Agent - 通过 CLI 和 Web UI 两种方式运行 Agent --- ## 2.1 创建 Agent 项目 ### 2.1.1 使用 CLI 创建项目 ```bash # 在工作目录下创建一个新的 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: ```python """ 第一个 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 添加一个获取当前时间的工具: ```python """ 带自定义工具的 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: ```bash # 方法一:在 .env 文件中配置(推荐) echo 'GOOGLE_API_KEY="你的_GEMINI_API_KEY"' > hello_world/.env # 方法二:通过环境变量设置 export GOOGLE_API_KEY="你的_GEMINI_API_KEY" # 方法三:直接在代码中设置(不推荐,有安全风险) ``` > 💡 **获取 API Key**:访问 [Google AI Studio](https://aistudio.google.com/app/apikey),点击 "Create API Key" 即可免费获取。 --- ## 2.4 运行 Agent ### 2.4.1 命令行交互模式(CLI) ```bash # 在项目父目录下运行(不是在 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 模式 ```bash # 启动 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 """ 通过 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 - 三种运行方式:CLI(`adk run`)、Web UI(`adk web`)、代码调用 - Runner 是 ADK 的核心执行引擎,负责协调 Agent 和会话 **下一章**:[第03章 - LLM 智能体详解](./03-llm-agent-in-depth.md) → 深入了解 LlmAgent 的配置和高级用法。