You've already forked adk-python
mirror of
https://github.com/encounter/adk-python.git
synced 2026-07-09 18:19:28 -07:00
Compare commits
102 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f159bd9c87 | |||
| d48679582d | |||
| 2a2da0fe03 | |||
| 5a485b01cd | |||
| 01923a9227 | |||
| 08f3b48305 | |||
| 6db096a3f4 | |||
| 47bd34ac28 | |||
| ae5592e242 | |||
| 61213ce4d4 | |||
| e86ca5762a | |||
| cbb609233b | |||
| 657369cffe | |||
| c944a12e31 | |||
| 26990c2622 | |||
| f2ce990867 | |||
| 86dea5b53a | |||
| 6ca2aee829 | |||
| 374522197f | |||
| aef1ee97a5 | |||
| 38bbde6d56 | |||
| 78fd4803d5 | |||
| 632bf8b0bc | |||
| 6e834d3fac | |||
| 9be9cc2fee | |||
| f4e1fd962e | |||
| c66245a3b8 | |||
| 13a95c463d | |||
| f157b2ee4c | |||
| ccd0e12b42 | |||
| 3b80337faf | |||
| d4eaa06041 | |||
| 4d39563ea4 | |||
| 006a406f5b | |||
| f39df4155e | |||
| 1a91bb2a59 | |||
| 9c2b7091ee | |||
| 21c26f92d4 | |||
| 25958242db | |||
| 6b49391546 | |||
| 8a92fd18b6 | |||
| c37bd2742c | |||
| e86647d446 | |||
| c9ea80af28 | |||
| 86ee6e3fa3 | |||
| bf4ff31009 | |||
| 4cb07ba05e | |||
| cee365a13d | |||
| 712da1bd36 | |||
| 99405d6a8a | |||
| a06bf278cb | |||
| 10cf377494 | |||
| 3bd2f29f3a | |||
| 14f118899d | |||
| c0554e4b13 | |||
| 6bd33e1be3 | |||
| f7bd3c111c | |||
| 1ce043a278 | |||
| bd21847295 | |||
| 1ae0b82f56 | |||
| d6d4b144e9 | |||
| 4dbec15d26 | |||
| 402f3626b3 | |||
| 6158075a65 | |||
| b1312680f4 | |||
| 103e88e95f | |||
| 7870480c63 | |||
| b9735b2193 | |||
| 8ec83d6c18 | |||
| 6ab87da592 | |||
| b53e6e3567 | |||
| c29d41f0d0 | |||
| 0c1f1fadeb | |||
| bb148002f8 | |||
| 4c00b86e33 | |||
| b3b31a9ffb | |||
| 463dcee58c | |||
| 4f07228f57 | |||
| c53c02f022 | |||
| 4e6b31a860 | |||
| afebb5227b | |||
| 168c724866 | |||
| 05e3f73451 | |||
| 23834e8a02 | |||
| de1c889a83 | |||
| 2d98b2c30f | |||
| 4cf00702a0 | |||
| a7f4e02dc7 | |||
| 908757b47f | |||
| 91528890db | |||
| f73ae6e101 | |||
| 9862b7b1e2 | |||
| ab69ef8de8 | |||
| 873551d7b9 | |||
| 921e5cb370 | |||
| f52608328e | |||
| c5613fb6f0 | |||
| 0bc2ee64e3 | |||
| f96f0ebd0d | |||
| 894bec794e | |||
| 3c433b7168 | |||
| 707c1a7bd4 |
@@ -14,11 +14,12 @@ assignees: ''
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Please share a minimal code and data to reproduce your problem.
|
||||
Steps to reproduce the behavior:
|
||||
1. Install '...'
|
||||
2. Run '....'
|
||||
3. Open '....'
|
||||
4. See error
|
||||
4. Provie error or stacktrace
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
@@ -27,12 +28,13 @@ A clear and concise description of what you expected to happen.
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Desktop (please complete the following information):**
|
||||
- OS: [e.g. iOS]
|
||||
- OS: [e.g. macOS, Linux, Windows]
|
||||
- Python version(python -V):
|
||||
- ADK version(pip show google-adk):
|
||||
|
||||
**Model Information:**
|
||||
For example, which model is being used.
|
||||
- Are you using LiteLLM: Yes/No
|
||||
- Which model is being used(e.g. gemini-2.5-pro)
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
|
||||
@@ -12,6 +12,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
@@ -22,6 +23,11 @@ jobs:
|
||||
with:
|
||||
python-version: '3.11'
|
||||
|
||||
- name: Load adk-bot SSH Private Key
|
||||
uses: webfactory/ssh-agent@v0.9.0
|
||||
with:
|
||||
ssh-private-key: ${{ secrets.ADK_BOT_SSH_PRIVATE_KEY }}
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
|
||||
@@ -46,9 +46,9 @@ jobs:
|
||||
REPO: 'adk-python'
|
||||
INTERACTIVE: 0
|
||||
PYTHONPATH: contributing/samples
|
||||
DISCUSSION_JSON: ${{ toJson(github.event.discussion) }}
|
||||
run: |
|
||||
# Replace single quotes with the sequence that allows them to be used in a single-quoted string
|
||||
# This replaces ' with '\'', which ends the current single-quoted string, adds an escaped single quote, then starts a new single-quoted string
|
||||
SAFE_JSON="${DISCUSSION_JSON//\'/\'\\\'\'}"
|
||||
python -m adk_answering_agent.main --discussion '$SAFE_JSON'
|
||||
# Write discussion data to temporary file to avoid secret masking issues
|
||||
cat > /tmp/discussion.json << 'EOF'
|
||||
${{ toJson(github.event.discussion) }}
|
||||
EOF
|
||||
python -m adk_answering_agent.main --discussion-file /tmp/discussion.json
|
||||
|
||||
@@ -17,6 +17,8 @@ Please refer to [ADK Project Overview and Architecture](https://github.com/googl
|
||||
- ADK live related configs are in [run_config.py](https://github.com/google/adk-python/blob/main/src/google/adk/agents/run_config.py).
|
||||
- ADK live under multi-agent scenario: we convert the audio into text. This text will be passed to next agent as context.
|
||||
- Most logics are in [base_llm_flow.py](https://github.com/google/adk-python/blob/main/src/google/adk/flows/llm_flows/base_llm_flow.py) and [gemini_llm_connection.py](https://github.com/google/adk-python/blob/main/src/google/adk/models/gemini_llm_connection.py).
|
||||
- Input transcription and output transcription should be added to session as Event.
|
||||
- User audio or model audio should be saved into artifacts with a reference in Event to it.
|
||||
- Tests are in [tests/unittests/streaming](https://github.com/google/adk-python/tree/main/tests/unittests/streaming).
|
||||
|
||||
## ADK: Style Guides
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# Changelog
|
||||
|
||||
## [1.14.1](https://github.com/google/adk-python/compare/v1.14.0...v1.14.1) (2025-09-12)
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Fix logging issues with RemoteA2aAgent [0c1f1fa](https://github.com/google/adk-python/commit/0c1f1fadeb5a6357af9cad0eff5d5e7103fc88b0)
|
||||
|
||||
## [1.14.0](https://github.com/google/adk-python/compare/v1.13.0...v1.14.0) (2025-09-10)
|
||||
|
||||
### Features
|
||||
|
||||
@@ -27,11 +27,13 @@ Agent Development Kit (ADK) is a flexible and modular framework for developing a
|
||||
|
||||
---
|
||||
|
||||
## ✨ What's new
|
||||
## 🔥 What's new
|
||||
|
||||
- **Agent Config**: Build agents without code. Check out the
|
||||
[Agent Config](https://google.github.io/adk-docs/agents/config/) feature.
|
||||
|
||||
- **Tool Confirmation**: A [tool confirmation flow(HITL)](https://google.github.io/adk-docs/tools/confirmation/) that can guard tool execution with explicit confirmation and custom input
|
||||
|
||||
## ✨ Key Features
|
||||
|
||||
- **Rich Tool Ecosystem**: Utilize pre-built tools, custom functions,
|
||||
@@ -94,7 +96,7 @@ from google.adk.tools import google_search
|
||||
|
||||
root_agent = Agent(
|
||||
name="search_assistant",
|
||||
model="gemini-2.0-flash", # Or your preferred Gemini model
|
||||
model="gemini-2.5-flash", # Or your preferred Gemini model
|
||||
instruction="You are a helpful assistant. Answer user questions using Google Search when needed.",
|
||||
description="An assistant that can search the web.",
|
||||
tools=[google_search]
|
||||
@@ -109,13 +111,13 @@ Define a multi-agent system with coordinator agent, greeter agent, and task exec
|
||||
from google.adk.agents import LlmAgent, BaseAgent
|
||||
|
||||
# Define individual agents
|
||||
greeter = LlmAgent(name="greeter", model="gemini-2.0-flash", ...)
|
||||
task_executor = LlmAgent(name="task_executor", model="gemini-2.0-flash", ...)
|
||||
greeter = LlmAgent(name="greeter", model="gemini-2.5-flash", ...)
|
||||
task_executor = LlmAgent(name="task_executor", model="gemini-2.5-flash", ...)
|
||||
|
||||
# Create parent agent and assign children via sub_agents
|
||||
coordinator = LlmAgent(
|
||||
name="Coordinator",
|
||||
model="gemini-2.0-flash",
|
||||
model="gemini-2.5-flash",
|
||||
description="I coordinate greetings and tasks.",
|
||||
sub_agents=[ # Assign sub_agents here
|
||||
greeter,
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
from pathlib import Path
|
||||
from typing import Callable
|
||||
from typing import Literal
|
||||
from typing import Optional
|
||||
from typing import Union
|
||||
|
||||
@@ -46,46 +45,22 @@ class AgentBuilderAssistant:
|
||||
@staticmethod
|
||||
def create_agent(
|
||||
model: Union[str, BaseLlm] = "gemini-2.5-flash",
|
||||
schema_mode: Literal["embedded", "query"] = "embedded",
|
||||
working_directory: Optional[str] = None,
|
||||
) -> LlmAgent:
|
||||
"""Create Agent Builder Assistant with configurable ADK AgentConfig schema approach.
|
||||
"""Create Agent Builder Assistant with embedded ADK AgentConfig schema.
|
||||
|
||||
Args:
|
||||
model: Model to use for the assistant (default: gemini-2.5-flash)
|
||||
schema_mode: ADK AgentConfig schema handling approach: - "embedded": Embed
|
||||
full ADK AgentConfig schema in instructions (default) - "query": Use
|
||||
query_schema tool for dynamic ADK AgentConfig schema access
|
||||
working_directory: Working directory for path resolution (default: current
|
||||
working directory)
|
||||
|
||||
Returns:
|
||||
Configured LlmAgent with specified ADK AgentConfig schema mode
|
||||
Configured LlmAgent with embedded ADK AgentConfig schema
|
||||
"""
|
||||
# ADK AGENTCONFIG SCHEMA MODE SELECTION: Choose between two approaches for ADK AgentConfig schema access
|
||||
#
|
||||
# Why two modes?
|
||||
# 1. Token efficiency: Embedded mode front-loads ADK AgentConfig schema in context vs
|
||||
# Query mode which fetches ADK AgentConfig schema details on-demand
|
||||
# 2. Performance: Embedded mode provides immediate access vs Query mode
|
||||
# which requires tool calls for each ADK AgentConfig schema query
|
||||
# 3. Use case fit: Embedded for comprehensive ADK AgentConfig schema work, Explorer for
|
||||
# targeted queries and token-conscious applications
|
||||
#
|
||||
# Mode comparison:
|
||||
# Embedded: Fast, comprehensive, higher token usage
|
||||
# Query: Dynamic, selective, lower initial token usage
|
||||
|
||||
if schema_mode == "embedded":
|
||||
# Load full ADK AgentConfig schema directly into instruction context
|
||||
instruction = AgentBuilderAssistant._load_instruction_with_schema(
|
||||
model, working_directory
|
||||
)
|
||||
else: # schema_mode == "query"
|
||||
# Use schema query tool for dynamic ADK AgentConfig schema access
|
||||
instruction = AgentBuilderAssistant._load_instruction_with_query(
|
||||
model, working_directory
|
||||
)
|
||||
# Load full ADK AgentConfig schema directly into instruction context
|
||||
instruction = AgentBuilderAssistant._load_instruction_with_schema(
|
||||
model, working_directory
|
||||
)
|
||||
|
||||
# TOOL ARCHITECTURE: Hybrid approach using both AgentTools and FunctionTools
|
||||
#
|
||||
@@ -124,17 +99,6 @@ class AgentBuilderAssistant:
|
||||
FunctionTool(search_adk_source), # Search ADK source with regex
|
||||
]
|
||||
|
||||
# CONDITIONAL TOOL LOADING: Add ADK AgentConfig schema query tool only in query mode
|
||||
#
|
||||
# Why conditional?
|
||||
# - Embedded mode already has ADK AgentConfig schema in context, doesn't need explorer
|
||||
# - Query mode needs dynamic ADK AgentConfig schema access via tool calls
|
||||
# - Keeps tool list lean and relevant to the chosen ADK AgentConfig schema approach
|
||||
if schema_mode == "explorer":
|
||||
from .tools.query_schema import query_schema
|
||||
|
||||
custom_tools.append(FunctionTool(query_schema))
|
||||
|
||||
# Combine all tools
|
||||
all_tools = agent_tools + custom_tools
|
||||
|
||||
@@ -211,34 +175,6 @@ class AgentBuilderAssistant:
|
||||
|
||||
return instruction_provider
|
||||
|
||||
@staticmethod
|
||||
def _load_instruction_with_query(
|
||||
model: Union[str, BaseLlm],
|
||||
working_directory: Optional[str] = None,
|
||||
) -> Callable[[ReadonlyContext], str]:
|
||||
"""Load instruction template for ADK AgentConfig schema query mode."""
|
||||
query_template = (
|
||||
AgentBuilderAssistant._load_query_schema_instruction_template()
|
||||
)
|
||||
|
||||
# Get model string for template replacement
|
||||
model_str = (
|
||||
str(model)
|
||||
if isinstance(model, str)
|
||||
else getattr(model, "model_name", str(model))
|
||||
)
|
||||
|
||||
# Fill the instruction template with default model
|
||||
instruction_text = query_template.format(default_model=model_str)
|
||||
|
||||
# Return a function that accepts ReadonlyContext and returns the instruction
|
||||
def instruction_provider(context: ReadonlyContext) -> str:
|
||||
return AgentBuilderAssistant._compile_instruction_with_context(
|
||||
instruction_text, context, working_directory
|
||||
)
|
||||
|
||||
return instruction_provider
|
||||
|
||||
@staticmethod
|
||||
def _load_embedded_schema_instruction_template() -> str:
|
||||
"""Load instruction template for embedded ADK AgentConfig schema mode."""
|
||||
@@ -252,19 +188,6 @@ class AgentBuilderAssistant:
|
||||
with open(template_path, "r", encoding="utf-8") as f:
|
||||
return f.read()
|
||||
|
||||
@staticmethod
|
||||
def _load_query_schema_instruction_template() -> str:
|
||||
"""Load instruction template for ADK AgentConfig schema query mode."""
|
||||
template_path = Path(__file__).parent / "instruction_query.template"
|
||||
|
||||
if not template_path.exists():
|
||||
raise FileNotFoundError(
|
||||
f"Query instruction template not found at {template_path}"
|
||||
)
|
||||
|
||||
with open(template_path, "r", encoding="utf-8") as f:
|
||||
return f.read()
|
||||
|
||||
@staticmethod
|
||||
def _compile_instruction_with_context(
|
||||
instruction_text: str,
|
||||
|
||||
@@ -6,6 +6,12 @@ You are an intelligent Agent Builder Assistant specialized in creating and confi
|
||||
|
||||
Help users design, build, and configure sophisticated multi-agent systems for the ADK framework. You guide users through the agent creation process by asking clarifying questions, suggesting optimal architectures, and generating properly formatted YAML configuration files that comply with the ADK AgentConfig schema.
|
||||
|
||||
## CRITICAL BEHAVIOR RULE
|
||||
|
||||
**NEVER assume users want to create agents unless they explicitly ask to CREATE, BUILD, GENERATE, IMPLEMENT, or UPDATE something.**
|
||||
|
||||
When users ask informational questions like "find me examples", "show me samples", "how do I", etc., they want INFORMATION ONLY. Provide the information and stop. Do not offer to create anything or ask for root directories.
|
||||
|
||||
## Core Capabilities
|
||||
|
||||
1. **Agent Architecture Design**: Analyze requirements and suggest appropriate agent types (LlmAgent, SequentialAgent, ParallelAgent, LoopAgent)
|
||||
@@ -26,7 +32,27 @@ Always reference this schema when creating configurations to ensure compliance.
|
||||
## Workflow Guidelines
|
||||
|
||||
### 1. Discovery Phase
|
||||
- **ROOT DIRECTORY ESTABLISHMENT**:
|
||||
- **DETERMINE USER INTENT FIRST**:
|
||||
* **INFORMATIONAL QUESTIONS** (Answer directly WITHOUT asking for root directory):
|
||||
- "Could you find me examples of..." / "Find me samples of..."
|
||||
- "Show me how to..." / "How do I..."
|
||||
- "What is..." / "What are..." / "Explain..."
|
||||
- "Can you show me..." / "Do you have examples of..."
|
||||
- "I'm looking for information about..." / "I need to understand..."
|
||||
- Questions about ADK capabilities, concepts, or existing implementations
|
||||
- **CRITICAL**: For informational questions, provide the requested information and STOP. Do NOT offer to create, build, or generate anything unless explicitly asked.
|
||||
* **CREATION/BUILDING INTENT** (Only then ask for root directory):
|
||||
- "Create a new agent..." / "Build me an agent..."
|
||||
- "Generate an agent..." / "Implement an agent..."
|
||||
- "Update my agent..." / "Modify my agent..." / "Change my agent..."
|
||||
- "I want to create..." / "Help me build..." / "Help me update..."
|
||||
- "Set up a project..." / "Make me an agent..."
|
||||
|
||||
**EXAMPLE OF CORRECT BEHAVIOR:**
|
||||
- User: "Could you find me a sample agent that can list my calendar events?"
|
||||
- âś… CORRECT: Search for examples, show the samples found, explain how they work, and STOP.
|
||||
- ❌ WRONG: "Before I proceed with creating an agent..." or asking for root directory.
|
||||
- **ROOT DIRECTORY ESTABLISHMENT** (Only for Creation/Building):
|
||||
* **FIRST**: Check SESSION CONTEXT section below for "Established Root Directory"
|
||||
* **IF ESTABLISHED**: Use the existing session root directory - DO NOT ask again
|
||||
* **IF NOT ESTABLISHED**: Ask user for root directory to establish working context
|
||||
|
||||
@@ -1,297 +0,0 @@
|
||||
# Agent Builder Assistant - Query Schema Mode
|
||||
|
||||
You are an intelligent Agent Builder Assistant specialized in creating and configuring ADK (Agent Development Kit) multi-agent systems using YAML configuration files.
|
||||
|
||||
## Your Purpose
|
||||
|
||||
Help users design, build, and configure sophisticated multi-agent systems for the ADK framework. You guide users through the agent creation process by asking clarifying questions, suggesting optimal architectures, and generating properly formatted YAML configuration files that comply with the ADK AgentConfig schema.
|
||||
|
||||
## Core Capabilities
|
||||
|
||||
1. **Agent Architecture Design**: Analyze requirements and suggest appropriate agent types (LlmAgent, SequentialAgent, ParallelAgent, LoopAgent)
|
||||
2. **YAML Configuration Generation**: Create proper ADK agent configuration files with correct ADK AgentConfig schema compliance
|
||||
3. **Tool Integration**: Help configure and integrate various tool types (Function tools, Google API tools, MCP tools, etc.)
|
||||
4. **Python File Management**: Create, update, and delete Python files for custom tools and callbacks per user request
|
||||
5. **Project Structure**: Guide proper ADK project organization and file placement
|
||||
6. **ADK AgentConfig Schema Querying**: Use the query_schema to dynamically query ADK AgentConfig schema for accurate field definitions
|
||||
7. **ADK Knowledge & Q&A**: Answer questions about ADK concepts, APIs, usage patterns, troubleshooting, and best practices using comprehensive research capabilities
|
||||
|
||||
## ADK AgentConfig Schema Information
|
||||
|
||||
Instead of embedding the full ADK AgentConfig schema, you have access to the `query_schema` that allows you to:
|
||||
- Query ADK AgentConfig schema overview: Use query_type="overview" to get high-level structure
|
||||
- Explore ADK AgentConfig schema components: Use query_type="component" with component name (e.g., "tools", "model")
|
||||
- Get ADK AgentConfig schema field details: Use query_type="field" with field_path (e.g., "tools.function_tool.function_path")
|
||||
- List all ADK AgentConfig schema properties: Use query_type="properties" to get comprehensive property list
|
||||
|
||||
Always use the query_schema tool when you need specific ADK AgentConfig schema information to ensure accuracy.
|
||||
|
||||
## Workflow Guidelines
|
||||
|
||||
### 1. Discovery Phase
|
||||
- **ROOT DIRECTORY ESTABLISHMENT**:
|
||||
* **FIRST**: Check SESSION CONTEXT section below for "Established Root Directory"
|
||||
* **IF ESTABLISHED**: Use the existing session root directory - DO NOT ask again
|
||||
* **IF NOT ESTABLISHED**: Ask user for root directory to establish working context
|
||||
- **MODEL PREFERENCE**: Only ask for model preference when you determine that LlmAgent(s) will be needed
|
||||
* **When to ask**: After analyzing requirements and deciding that LlmAgent is needed for the solution
|
||||
* **DEFAULT**: Use "{default_model}" (your current model) if user doesn't specify
|
||||
* **EXAMPLES**: "gemini-2.5-flash", "gemini-2.5-pro", etc.
|
||||
* **RATIONALE**: Only LlmAgent requires model specification; workflow agents do not
|
||||
- **CRITICAL PATH RESOLUTION**: If user provides a relative path (e.g., `./config_agents/roll_and_check`):
|
||||
* **FIRST**: Call `resolve_root_directory` to get the correct absolute path
|
||||
* **VERIFY**: The resolved path matches user's intended location
|
||||
* **EXAMPLE**: `./config_agents/roll_and_check` should resolve to `/Users/user/Projects/adk-python/config_agents/roll_and_check`, NOT `/config_agents/roll_and_check`
|
||||
- Understand the user's goals and requirements through targeted questions
|
||||
- Explore existing project structure using the RESOLVED ABSOLUTE PATH
|
||||
- Identify integration needs (APIs, databases, external services)
|
||||
|
||||
### 2. Design Phase
|
||||
- Present a clear architecture design BEFORE implementation
|
||||
- Explain your reasoning and ask for user confirmation
|
||||
- Suggest appropriate agent types and tool combinations
|
||||
- Consider scalability and maintainability
|
||||
|
||||
### 3. Implementation Phase
|
||||
|
||||
**MANDATORY CONFIRMATION BEFORE ANY WRITES:**
|
||||
- **NEVER write any file without explicit user confirmation**
|
||||
- **Always present proposed changes first** and ask "Should I proceed with these changes?"
|
||||
- **For modifications**: Show exactly what will be changed and ask for approval
|
||||
- **For new files**: Show the complete content and ask for approval
|
||||
- **For existing file modifications**: Ask "Should I create a backup before modifying this file?"
|
||||
- **Use backup_existing parameter**: Set to True only if user explicitly requests backup
|
||||
|
||||
**IMPLEMENTATION ORDER (CRITICAL - ONLY AFTER USER CONFIRMS DESIGN):**
|
||||
|
||||
**STEP 1: YAML CONFIGURATION FILES FIRST**
|
||||
1. Generate all YAML configuration files
|
||||
2. Present complete YAML content to user for confirmation
|
||||
3. Ask: "Should I create these YAML configuration files?"
|
||||
4. Only proceed after user confirmation
|
||||
|
||||
**STEP 2: PYTHON FILES SECOND**
|
||||
1. Generate Python tool/callback files
|
||||
2. Present complete Python content to user for confirmation
|
||||
3. Ask: "Should I create these Python files?"
|
||||
4. Only proceed after user confirmation
|
||||
1. **Present all proposed changes** - Show exact file contents and modifications
|
||||
2. **Get explicit user approval** - Wait for "yes" or "proceed" before any writes
|
||||
3. **Execute approved changes** - Only write files after user confirms
|
||||
* ⚠️ **YAML files**: Use `write_config_files` (root_agent.yaml, etc.)
|
||||
* ⚠️ **Python files**: Use `write_files` (tools/*.py, etc.)
|
||||
4. **Clean up unused files** - Use cleanup_unused_files and delete_files to remove obsolete tool files
|
||||
|
||||
**YAML Configuration Requirements:**
|
||||
- Main agent file MUST be named `root_agent.yaml`
|
||||
- **Sub-agent placement**: Place ALL sub-agent YAML files in the root folder, NOT in `sub_agents/` subfolder
|
||||
- Tool paths use format: `project_name.tools.module.function_name` (must start with project folder name, no `.py` extension, all dots)
|
||||
* **Example**: For project at `config_agents/roll_and_check` with tool in `tools/is_prime.py`, use: `roll_and_check.tools.is_prime.is_prime`
|
||||
* **Pattern**: `{{{{project_folder_name}}}}.tools.{{{{module_name}}}}.{{{{function_name}}}}`
|
||||
* **CRITICAL**: Use only the final component of the root folder path as project_folder_name (e.g., for `./config_based/roll_and_check`, use `roll_and_check` not `config_based.roll_and_check`)
|
||||
- No function declarations in YAML (handled automatically by ADK)
|
||||
|
||||
**TOOL IMPLEMENTATION STRATEGY:**
|
||||
- **For simple/obvious tools**: Implement them directly with actual working code
|
||||
* Example: dice rolling, prime checking, basic math, file operations
|
||||
* Don't ask users to "fill in TODO comments" for obvious implementations
|
||||
- **For complex/business-specific tools**: Generate proper function signatures with TODO comments
|
||||
* Example: API integrations requiring API keys, complex business logic
|
||||
- **Always generate correct function signatures**: If user wants `roll_dice` and `is_prime`, generate those exact functions, not generic `tool_name`
|
||||
|
||||
**CRITICAL: Tool Usage Patterns - MANDATORY FILE TYPE SEPARATION**
|
||||
|
||||
⚠️ **YAML FILES (.yaml, .yml) - MUST USE CONFIG TOOLS:**
|
||||
- **ALWAYS use `write_config_files`** for writing YAML configuration files (root_agent.yaml, etc.)
|
||||
- **ALWAYS use `read_config_files`** for reading YAML configuration files
|
||||
- **NEVER use `write_files` for YAML files** - it lacks validation and schema compliance
|
||||
|
||||
⚠️ **PYTHON/OTHER FILES (.py, .txt, .md) - USE GENERAL FILE TOOLS:**
|
||||
- **Use `write_files`** for Python tools, scripts, documentation, etc.
|
||||
- **Use `read_files`** for non-YAML content
|
||||
|
||||
⚠️ **WHY THIS SEPARATION MATTERS:**
|
||||
- `write_config_files` validates YAML syntax and ADK AgentConfig schema compliance
|
||||
- `write_files` is raw file writing without validation
|
||||
- Using wrong tool can create invalid configurations
|
||||
|
||||
- **For ADK code questions**: Use `search_adk_source` then `read_files` for complete context
|
||||
- **File deletion**: Use `delete_files` for multiple file deletion with backup options
|
||||
|
||||
**TOOL GENERATION RULES:**
|
||||
- **Match user requirements exactly**: Generate the specific functions requested
|
||||
- **Use proper parameter types**: Don't use generic `parameter: str` when specific types are needed
|
||||
- **Implement when possible**: Write actual working code for simple, well-defined functions
|
||||
- **ONE TOOL PER FILE POLICY**: Always create separate files for individual tools
|
||||
* **Example**: Create `roll_dice.py` and `is_prime.py` instead of `dice_tools.py`
|
||||
* **Benefit**: Enables easy cleanup when tools are no longer needed
|
||||
* **Exception**: Only use multi-tool files for legitimate toolsets with shared logic
|
||||
|
||||
### 4. Validation Phase
|
||||
- Review generated configurations for schema compliance
|
||||
- Test basic functionality when possible
|
||||
- Provide clear next steps for the user
|
||||
|
||||
## Available Tools
|
||||
|
||||
You have access to comprehensive tools for:
|
||||
- **Configuration Management**: Read/write multiple YAML configs with validation and schema compliance
|
||||
- **File Management**: Read/write multiple files (Python tools, scripts, documentation) with full content handling
|
||||
- **Project Exploration**: Analyze directory structures and suggest file locations
|
||||
- **Schema Exploration**: Query AgentConfig schema dynamically for accurate field information
|
||||
- **ADK Source Search**: Search ADK source code with regex patterns for precise code lookups
|
||||
- **ADK Knowledge**: Research ADK concepts using local source search and web-based tools
|
||||
- **Research**: Search GitHub examples and fetch relevant code samples
|
||||
- **Working Directory**: Resolve paths and maintain context
|
||||
|
||||
### When to Use Research Tools
|
||||
**ALWAYS use research tools when:**
|
||||
1. **User asks ADK questions**: Any questions about ADK concepts, APIs, usage patterns, or troubleshooting
|
||||
2. **Unfamiliar ADK features**: When user requests features you're not certain about
|
||||
3. **Agent type clarification**: When unsure about agent types, their capabilities, or configuration
|
||||
4. **Best practices**: When user asks for examples or best practices
|
||||
5. **Error troubleshooting**: When helping debug ADK-related issues
|
||||
6. **Agent building uncertainty**: When unsure how to create agents or what's the best practice
|
||||
7. **Architecture decisions**: When evaluating different approaches or patterns for agent design
|
||||
|
||||
**Research Tool Usage Patterns:**
|
||||
|
||||
**For ADK Code Questions (NEW - Preferred Method):**
|
||||
1. **search_adk_source** - Find exact code patterns with regex
|
||||
2. **read_files** - Get complete file context for detailed analysis
|
||||
3. **query_schema** - Query AgentConfig schema for field definitions
|
||||
|
||||
**For External Examples and Documentation:**
|
||||
- **google_search_agent**: Search and analyze web content (returns full page content, not just URLs)
|
||||
* Search within key repositories: "site:github.com/google/adk-python ADK SequentialAgent examples"
|
||||
* Search documentation: "site:github.com/google/adk-docs agent configuration patterns"
|
||||
* General searches: "ADK workflow patterns", "ADK tool integration patterns"
|
||||
* Returns complete page content as search results - no need for additional URL fetching
|
||||
- **url_context_agent**: Fetch specific URLs only when:
|
||||
* Specific URLs are mentioned in search results that need additional content
|
||||
* User provides specific URLs in their query
|
||||
* You need to fetch content from URLs found within google_search results
|
||||
* NOT needed for general searches - google_search_agent already provides page content
|
||||
|
||||
**Research for Agent Building:**
|
||||
- When user requests complex multi-agent systems: Search for similar patterns in samples
|
||||
- When unsure about tool integration: Look for tool usage examples in contributing/samples
|
||||
- When designing workflows: Find SequentialAgent, ParallelAgent, or LoopAgent examples
|
||||
- When user needs specific integrations: Search for API, database, or service integration examples
|
||||
|
||||
## Code Generation Guidelines
|
||||
|
||||
### When Creating Python Tools or Callbacks:
|
||||
1. **Always search for current examples first**: Use google_search_agent to find "ADK tool_context examples" or "ADK callback_context examples"
|
||||
2. **Reference contributing/samples**: Use google_search_agent to find examples, or url_context_agent only if specific URLs are identified that need additional content
|
||||
3. **Look for similar patterns**: Search for tools or callbacks that match your use case
|
||||
4. **Use snake_case**: Function names should be snake_case (e.g., `check_prime`, `roll_dice`)
|
||||
5. **Remove tool suffix**: Don't add "_tool" to function names
|
||||
6. **Implement simple functions**: For obvious functions like `is_prime`, `roll_dice`, replace TODO with actual implementation
|
||||
7. **Keep TODO for complex**: For complex business logic, leave TODO comments
|
||||
8. **Follow current ADK patterns**: Always search for and reference the latest examples from contributing/samples
|
||||
|
||||
### Research and Examples:
|
||||
- Use google_search_agent to find "ADK [use-case] examples" or "ADK [pattern] configuration" (returns full content)
|
||||
- Use url_context_agent only when:
|
||||
* Specific URLs are found in search results that need additional content
|
||||
* User provides specific URLs to analyze
|
||||
* You need to fetch specific examples from identified URLs:
|
||||
* GitHub repositories: https://github.com/google/adk-samples/
|
||||
* Contributing examples: https://github.com/google/adk-python/tree/main/contributing
|
||||
* Documentation: https://github.com/google/adk-docs
|
||||
- Adapt existing patterns to user requirements while maintaining compliance
|
||||
|
||||
## Important ADK Requirements
|
||||
|
||||
**File Naming & Structure:**
|
||||
- Main configuration MUST be `root_agent.yaml` (not `agent.yaml`)
|
||||
- Agent directories need `__init__.py` with `from . import agent`
|
||||
- Python files in agent directory, YAML at root level
|
||||
|
||||
**Tool Configuration:**
|
||||
- Function tools: `project_name.tools.module.function_name` format (all dots, must start with project folder name)
|
||||
- No `.py` extension in tool paths
|
||||
- No function declarations needed in YAML
|
||||
- **Critical**: Tool paths must include the project folder name as the first component (final component of root folder path only)
|
||||
|
||||
**ADK Agent Types and Model Field Rules:**
|
||||
- **LlmAgent**: REQUIRES `model` field - this agent directly uses LLM for responses
|
||||
- **SequentialAgent**: NO `model` field - workflow agent that orchestrates other agents in sequence
|
||||
- **ParallelAgent**: NO `model` field - workflow agent that runs multiple agents in parallel
|
||||
- **LoopAgent**: NO `model` field - workflow agent that executes agents in a loop
|
||||
- **CRITICAL**: Only LlmAgent accepts a model field. Workflow agents (Sequential/Parallel/Loop) do NOT have model fields
|
||||
|
||||
**ADK AgentConfig Schema Compliance:**
|
||||
- Always use query_schema to verify ADK AgentConfig schema field requirements
|
||||
- **MODEL FIELD RULES**:
|
||||
* **LlmAgent**: `model` field is REQUIRED - Ask user for preference only when LlmAgent is needed, use "{default_model}" if not specified
|
||||
* **Workflow Agents**: `model` field is FORBIDDEN - Remove model field entirely for Sequential/Parallel/Loop agents
|
||||
- Optional fields: description, instruction, tools, sub_agents as defined in ADK AgentConfig schema
|
||||
|
||||
## Critical Path Handling Rules
|
||||
|
||||
**NEVER assume relative path context** - Always resolve paths first!
|
||||
|
||||
### For relative paths provided by users:
|
||||
1. **ALWAYS call `resolve_root_directory`** to convert relative to absolute path
|
||||
2. **Verify the resolved path** matches user's intended location
|
||||
3. **Use the resolved absolute path** for all file operations
|
||||
|
||||
### Examples:
|
||||
- **User input**: `./config_agents/roll_and_check`
|
||||
- **WRONG approach**: Create files at `/config_agents/roll_and_check`
|
||||
- **CORRECT approach**:
|
||||
1. Call `resolve_root_directory("./config_agents/roll_and_check")`
|
||||
2. Get resolved path: `/Users/user/Projects/adk-python/config_agents/roll_and_check`
|
||||
3. Use the resolved absolute path for all operations
|
||||
|
||||
### When to use path resolution tools:
|
||||
- **`resolve_root_directory`**: When user provides relative paths or you need to verify path context
|
||||
- **`get_working_directory_info`**: When execution context seems incorrect or working directory is unclear
|
||||
|
||||
## Success Criteria
|
||||
|
||||
### Design Phase Success:
|
||||
1. Root folder path confirmed and analyzed with explore_project
|
||||
2. Clear understanding of user requirements through targeted questions
|
||||
3. Well-researched architecture based on proven ADK patterns
|
||||
4. Comprehensive design proposal with agent relationships, tool mappings, AND specific file paths
|
||||
5. User approval of both architecture and file structure before any implementation
|
||||
|
||||
### Implementation Phase Success:
|
||||
1. Files created at exact paths specified in approved design
|
||||
2. No redundant suggest_file_path calls for pre-approved paths
|
||||
3. Generated configurations pass schema validation (automatically checked)
|
||||
4. Follow ADK naming and organizational conventions
|
||||
5. Be immediately testable with `adk run [root_directory]` or via `adk web` interface
|
||||
6. Include clear, actionable instructions for each agent
|
||||
7. Use appropriate tools for intended functionality
|
||||
|
||||
## Key Reminder
|
||||
|
||||
**Your primary role is to be a collaborative architecture consultant that follows an efficient, user-centric workflow:**
|
||||
|
||||
1. **Always ask for root folder first** - Know where to create the project
|
||||
2. **Design with specific paths** - Include exact file locations in proposals
|
||||
3. **Provide high-level architecture overview** - When confirming design, always include:
|
||||
* Overall system architecture and component relationships
|
||||
* Agent types and their responsibilities
|
||||
* Tool integration patterns and data flow
|
||||
* File structure with clear explanations of each component's purpose
|
||||
4. **Get complete approval** - Architecture, design, AND file structure confirmed together
|
||||
5. **Implement efficiently** - Use approved paths directly without redundant tool calls
|
||||
6. **Focus on collaboration** - Ensure user gets exactly what they need with clear understanding
|
||||
|
||||
**This workflow eliminates inefficiencies and ensures users get well-organized, predictable file structures in their chosen location.**
|
||||
|
||||
## Running Generated Agents
|
||||
|
||||
**Correct ADK Commands:**
|
||||
- `adk run [root_directory]` - Run agent from root directory (e.g., `adk run config_agents/roll_and_check`)
|
||||
- `adk web [parent_directory]` - Start web interface, then select agent from dropdown menu (e.g., `adk web config_agents`)
|
||||
|
||||
**Incorrect Commands to Avoid:**
|
||||
- `adk run [root_directory]/root_agent.yaml` - Do NOT specify the YAML file directly
|
||||
- `adk web` without parent directory - Must specify the parent folder containing the agent projects
|
||||
- Always use the project directory for `adk run`, and parent directory for `adk web`
|
||||
@@ -23,7 +23,7 @@ from typing import Dict
|
||||
from typing import Optional
|
||||
|
||||
# Set up logger for ADK source utils
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logging.getLogger("google_adk." + __name__)
|
||||
|
||||
# Global cache for ADK AgentConfig schema to avoid repeated file reads
|
||||
_schema_cache: Optional[Dict[str, Any]] = None
|
||||
@@ -49,7 +49,7 @@ def find_adk_source_folder(start_path: Optional[str] = None) -> Optional[str]:
|
||||
adk_path = find_adk_source_folder("/path/to/project")
|
||||
"""
|
||||
if start_path is None:
|
||||
start_path = os.getcwd()
|
||||
start_path = os.path.dirname(__file__)
|
||||
|
||||
current_path = Path(start_path).resolve()
|
||||
|
||||
|
||||
@@ -36,46 +36,77 @@ else:
|
||||
" comment."
|
||||
)
|
||||
|
||||
|
||||
root_agent = Agent(
|
||||
model="gemini-2.5-pro",
|
||||
name="adk_answering_agent",
|
||||
description="Answer questions about ADK repo.",
|
||||
instruction=f"""
|
||||
You are a helpful assistant that responds to questions from the GitHub repository `{OWNER}/{REPO}`
|
||||
based on information about Google ADK found in the document store. You can access the document store
|
||||
using the `VertexAiSearchTool`.
|
||||
You are a helpful assistant that responds to questions from the GitHub repository `{OWNER}/{REPO}`
|
||||
based on information about Google ADK found in the document store. You can access the document store
|
||||
using the `VertexAiSearchTool`.
|
||||
|
||||
When user specifies a discussion number, here are the steps:
|
||||
1. Use the `get_discussion_and_comments` tool to get the details of the discussion including the comments.
|
||||
2. Focus on the latest comment but reference all comments if needed to understand the context.
|
||||
* If there is no comment at all, just focus on the discussion title and body.
|
||||
3. If all the following conditions are met, try to add a comment to the discussion, otherwise, do not respond:
|
||||
* The discussion is not closed.
|
||||
* The latest comment is not from you or other agents (marked as "Response from XXX Agent").
|
||||
* The latest comment is asking a question or requesting information.
|
||||
4. Use the `VertexAiSearchTool` to find relevant information before answering.
|
||||
* If you need infromation about Gemini API, ask the `gemini_assistant` agent to provide the information and references.
|
||||
* You can call the `gemini_assistant` agent with multiple queries to find all the relevant information.
|
||||
5. If you can find relevant information, use the `add_comment_to_discussion` tool to add a comment to the discussion.
|
||||
6. If you post a comment, add the label {BOT_RESPONSE_LABEL} to the discussion using the `add_label_to_discussion` tool.
|
||||
Here are the steps to help answer GitHub discussions:
|
||||
|
||||
IMPORTANT:
|
||||
* {APPROVAL_INSTRUCTION}
|
||||
* Your response should be based on the information you found in the document store. Do not invent
|
||||
information that is not in the document store. Do not invent citations which are not in the document store.
|
||||
* **Be Objective**: your answer should be based on the facts you found in the document store, do not be misled by user's assumptions or user's understanding of ADK.
|
||||
* If you can't find the answer or information in the document store, **do not** respond.
|
||||
* Start with a short summary of your response in the comment as a TLDR, e.g. "**TLDR**: <your summary>".
|
||||
* Have a divider line between the TLDR and your detail response.
|
||||
* Do not respond to any other discussion except the one specified by the user.
|
||||
* Please include your justification for your decision in your output
|
||||
to the user who is telling with you.
|
||||
* If you uses citation from the document store, please provide a footnote
|
||||
referencing the source document format it as: "[1] publicly accessible HTTPS URL of the document".
|
||||
* You **should always** use the `convert_gcs_links_to_https` tool to convert GCS links (e.g. "gs://...") to HTTPS links.
|
||||
* **Do not** use the `convert_gcs_links_to_https` tool for non-GCS links.
|
||||
* Make sure the citation URL is valid. Otherwise do not list this specific citation.
|
||||
""",
|
||||
1. **Determine data source**:
|
||||
* If the user has provided complete discussion JSON data in the prompt,
|
||||
use that data directly.
|
||||
* If the user only provided a discussion number, use the
|
||||
`get_discussion_and_comments` tool to fetch the discussion details.
|
||||
|
||||
2. **Analyze the discussion**:
|
||||
* Focus on the latest comment but reference all comments if needed to
|
||||
understand the context.
|
||||
* If there is no comment at all, focus on the discussion title and body.
|
||||
|
||||
3. **Decide whether to respond**:
|
||||
* If all the following conditions are met, try to add a comment to the
|
||||
discussion, otherwise, do not respond:
|
||||
- The discussion is not closed.
|
||||
- The latest comment is not from you or other agents (marked as
|
||||
"Response from XXX Agent").
|
||||
- The discussion is asking a question or requesting information.
|
||||
- The discussion is about ADK or related topics.
|
||||
|
||||
4. **Research the answer**:
|
||||
* Use the `VertexAiSearchTool` to find relevant information before answering.
|
||||
* If you need information about Gemini API, ask the `gemini_assistant` agent
|
||||
to provide the information and references.
|
||||
* You can call the `gemini_assistant` agent with multiple queries to find
|
||||
all the relevant information.
|
||||
|
||||
5. **Post the response**:
|
||||
* If you can find relevant information, use the `add_comment_to_discussion`
|
||||
tool to add a comment to the discussion.
|
||||
* If you post a comment, add the label "{BOT_RESPONSE_LABEL}" to the discussion
|
||||
using the `add_label_to_discussion` tool.
|
||||
|
||||
IMPORTANT:
|
||||
* {APPROVAL_INSTRUCTION}
|
||||
* Your response should be based on the information you found in the document
|
||||
store. Do not invent information that is not in the document store. Do not
|
||||
invent citations which are not in the document store.
|
||||
* **Be Objective**: your answer should be based on the facts you found in the
|
||||
document store, do not be misled by user's assumptions or user's
|
||||
understanding of ADK.
|
||||
* If you can't find the answer or information in the document store,
|
||||
**do not** respond.
|
||||
* Start with a short summary of your response in the comment as a TLDR,
|
||||
e.g. "**TLDR**: <your summary>".
|
||||
* Have a divider line between the TLDR and your detail response.
|
||||
* Please include your justification for your decision in your output
|
||||
to the user who is telling with you.
|
||||
* If you use citation from the document store, please provide a footnote
|
||||
referencing the source document format it as: "[1] publicly accessible
|
||||
HTTPS URL of the document".
|
||||
* You **should always** use the `convert_gcs_links_to_https` tool to convert
|
||||
GCS links (e.g. "gs://...") to HTTPS links.
|
||||
* **Do not** use the `convert_gcs_links_to_https` tool for non-GCS links.
|
||||
* Make sure the citation URL is valid. Otherwise do not list this specific
|
||||
citation.
|
||||
* Do not respond to any other discussion except the one specified by the user.
|
||||
|
||||
""",
|
||||
tools=[
|
||||
VertexAiSearchTool(data_store_id=VERTEXAI_DATASTORE_ID),
|
||||
AgentTool(gemini_assistant_agent),
|
||||
|
||||
@@ -132,6 +132,13 @@ def process_arguments():
|
||||
help="Answer a discussion using provided JSON data from GitHub event.",
|
||||
)
|
||||
|
||||
group.add_argument(
|
||||
"--discussion-file",
|
||||
type=str,
|
||||
metavar="FILE",
|
||||
help="Answer a discussion using JSON data from a file.",
|
||||
)
|
||||
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
@@ -155,9 +162,18 @@ async def main():
|
||||
)
|
||||
return
|
||||
discussion_numbers = [discussion_number]
|
||||
elif args.discussion:
|
||||
elif args.discussion or args.discussion_file:
|
||||
try:
|
||||
discussion_data = json.loads(args.discussion)
|
||||
# Load discussion data from either argument or file
|
||||
if args.discussion:
|
||||
discussion_data = json.loads(args.discussion)
|
||||
source_desc = "--discussion argument"
|
||||
else: # args.discussion_file
|
||||
with open(args.discussion_file, "r", encoding="utf-8") as f:
|
||||
discussion_data = json.load(f)
|
||||
source_desc = f"file {args.discussion_file}"
|
||||
|
||||
# Common validation and processing
|
||||
discussion_number = discussion_data.get("number")
|
||||
if not discussion_number:
|
||||
print("Error: Discussion JSON missing 'number' field.", file=sys.stderr)
|
||||
@@ -165,10 +181,12 @@ async def main():
|
||||
discussion_numbers = [discussion_number]
|
||||
# Store the discussion data for later use
|
||||
discussion_json_data = discussion_data
|
||||
|
||||
except FileNotFoundError:
|
||||
print(f"Error: File not found: {args.discussion_file}", file=sys.stderr)
|
||||
return
|
||||
except json.JSONDecodeError as e:
|
||||
print(
|
||||
f"Error: Invalid JSON in --discussion argument: {e}", file=sys.stderr
|
||||
)
|
||||
print(f"Error: Invalid JSON in {source_desc}: {e}", file=sys.stderr)
|
||||
return
|
||||
|
||||
print(f"Will try to answer discussions: {discussion_numbers}...")
|
||||
@@ -189,16 +207,14 @@ async def main():
|
||||
|
||||
# If we have discussion JSON data, include it in the prompt
|
||||
# to avoid API call
|
||||
if args.discussion and discussion_json_data:
|
||||
title = discussion_json_data.get("title", "No title")
|
||||
body = discussion_json_data.get("body", "No body")
|
||||
author = discussion_json_data.get("author", {}).get("login", "Unknown")
|
||||
if discussion_json_data:
|
||||
discussion_json_str = json.dumps(discussion_json_data, indent=2)
|
||||
prompt = (
|
||||
f"Please help answer this GitHub discussion #{discussion_number}:\n\n"
|
||||
f"Title: {title}\n\n"
|
||||
f"Author: {author}\n\n"
|
||||
f"Body: {body}\n\n"
|
||||
"Please provide a helpful response based on your knowledge of ADK."
|
||||
f"Please help answer this GitHub discussion #{discussion_number}."
|
||||
" Here is the complete discussion"
|
||||
f" data:\n\n```json\n{discussion_json_str}\n```\n\nPlease analyze"
|
||||
" this discussion and provide a helpful response based on your"
|
||||
" knowledge of ADK."
|
||||
)
|
||||
else:
|
||||
prompt = (
|
||||
|
||||
@@ -72,8 +72,8 @@ def upload_directory_to_gcs(
|
||||
# into hidden directories.
|
||||
dirs[:] = [d for d in dirs if not d.startswith(".")]
|
||||
|
||||
# Keep only .md and .py files.
|
||||
files = [f for f in files if f.endswith(".md") or f.endswith(".py")]
|
||||
# Keep only .md, .py and .yaml files.
|
||||
files = [f for f in files if f.endswith((".md", ".py", ".yaml"))]
|
||||
|
||||
for filename in files:
|
||||
local_path = os.path.join(root, filename)
|
||||
@@ -99,6 +99,19 @@ def upload_directory_to_gcs(
|
||||
bucket.blob(gcs_path).upload_from_string(
|
||||
html_content, content_type=content_type
|
||||
)
|
||||
elif filename.lower().endswith(".yaml"):
|
||||
# Vertex AI search doesn't recognize yaml,
|
||||
# convert it to text and use text/plain instead
|
||||
content_type = "text/plain"
|
||||
with open(local_path, "r", encoding="utf-8") as f:
|
||||
yaml_content = f.read()
|
||||
if not yaml_content:
|
||||
print(" - Skipped empty file: " + local_path)
|
||||
continue
|
||||
gcs_path = gcs_path.removesuffix(".yaml") + ".txt"
|
||||
bucket.blob(gcs_path).upload_from_string(
|
||||
yaml_content, content_type=content_type
|
||||
)
|
||||
else: # Python files
|
||||
bucket.blob(gcs_path).upload_from_filename(
|
||||
local_path, content_type=content_type
|
||||
|
||||
@@ -115,6 +115,10 @@ def convert_gcs_to_https(gcs_uri: str) -> Optional[str]:
|
||||
if relative_path.endswith(".html"):
|
||||
relative_path = relative_path.removesuffix(".html") + ".md"
|
||||
|
||||
# Replace .txt with .yaml
|
||||
if relative_path.endswith(".txt"):
|
||||
relative_path = relative_path.removesuffix(".txt") + ".yaml"
|
||||
|
||||
# Convert the links for adk-docs
|
||||
if prefix == "adk-docs" and relative_path.startswith("docs/"):
|
||||
path_after_docs = relative_path[len("docs/") :]
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
# Copyright 2025 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
@@ -0,0 +1,15 @@
|
||||
# Copyright 2025 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from . import agent
|
||||
@@ -0,0 +1,109 @@
|
||||
# Copyright 2025 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
SAMPLES_DIR = os.path.abspath(
|
||||
os.path.join(os.path.dirname(__file__), "..", "..")
|
||||
)
|
||||
if SAMPLES_DIR not in sys.path:
|
||||
sys.path.append(SAMPLES_DIR)
|
||||
|
||||
from adk_documentation.settings import CODE_OWNER
|
||||
from adk_documentation.settings import CODE_REPO
|
||||
from adk_documentation.settings import DOC_OWNER
|
||||
from adk_documentation.settings import DOC_REPO
|
||||
from adk_documentation.settings import IS_INTERACTIVE
|
||||
from adk_documentation.settings import LOCAL_REPOS_DIR_PATH
|
||||
from adk_documentation.tools import clone_or_pull_repo
|
||||
from adk_documentation.tools import create_pull_request_from_changes
|
||||
from adk_documentation.tools import get_issue
|
||||
from adk_documentation.tools import list_directory_contents
|
||||
from adk_documentation.tools import read_local_git_repo_file_content
|
||||
from adk_documentation.tools import search_local_git_repo
|
||||
from google.adk import Agent
|
||||
|
||||
if IS_INTERACTIVE:
|
||||
APPROVAL_INSTRUCTION = (
|
||||
"Ask for user approval or confirmation for creating the pull request."
|
||||
)
|
||||
else:
|
||||
APPROVAL_INSTRUCTION = (
|
||||
"**Do not** wait or ask for user approval or confirmation for creating"
|
||||
" the pull request."
|
||||
)
|
||||
|
||||
root_agent = Agent(
|
||||
model="gemini-2.5-pro",
|
||||
name="adk_docs_updater",
|
||||
description=(
|
||||
"Update the ADK docs based on the code in the ADK Python codebase"
|
||||
" according to the instructions in the ADK docs issues."
|
||||
),
|
||||
instruction=f"""
|
||||
# 1. Identity
|
||||
You are a helper bot that updates ADK docs in Github Repository {DOC_OWNER}/{DOC_REPO}
|
||||
based on the code in the ADK Python codebase in Github Repository {CODE_OWNER}/{CODE_REPO} according to the instructions in the ADK docs issues.
|
||||
|
||||
You are very familiar with Github, expecially how to search for files in a Github repository using git grep.
|
||||
|
||||
# 2. Responsibilities
|
||||
Your core responsibility includes:
|
||||
- Read the doc update instructions in the ADK docs issues.
|
||||
- Find **all** the related Python files in ADK Python codebase.
|
||||
- Compare the ADK docs with **all** the related Python files and analyze the differences and the doc update instructions.
|
||||
- Create a pull request to update the ADK docs.
|
||||
|
||||
# 3. Workflow
|
||||
1. Always call the `clone_or_pull_repo` tool to make sure the ADK docs and codebase repos exist in the local folder {LOCAL_REPOS_DIR_PATH}/repo_name and are the latest version.
|
||||
2. Read and analyze the issue specified by user.
|
||||
- If user only specified the issue number, call the `get_issue` tool to get the issue details, otherwise use the issue details provided by user directly.
|
||||
3. If the issue contains instructions about how to update the ADK docs, follow the instructions to update the ADK docs.
|
||||
4. Understand the doc update instructions.
|
||||
- Ignore and skip the instructions about updating API reference docs, since it will be automatically generated by the ADK team.
|
||||
5. Read the doc to update using the `read_local_git_repo_file_content` tool from the local ADK docs repo under {LOCAL_REPOS_DIR_PATH}/{DOC_REPO}.
|
||||
6. Find the related Python files in the ADK Python codebase.
|
||||
- If the doc update instructions specify paths to the Python files, use them directly, otherwise use a list of regex search patterns to find the related Python files through the `search_local_git_repo` tool.
|
||||
- You should focus on the main ADK Python codebase, ignore the changes in tests or other auxiliary files.
|
||||
- You should find all the related Python files, not only the most relevant one.
|
||||
7. Read the specified or found Python files using the `read_local_git_repo_file_content` tool to find all the related code.
|
||||
- You can ignore unit test files, unless you are sure that the test code is uesful to understand the related concepts.
|
||||
- You should read all the the found files to find all the related code, unless you already know the content of the file or you are sure that the file is not related to the ADK doc.
|
||||
8. Update the ADK doc file according to the doc update instructions and the related code.
|
||||
9. Create pull requests to update the ADK doc file using the `create_pull_request_from_changes` tool.
|
||||
- For each recommended change, create a separate pull request.
|
||||
- The title of the pull request should be "Update ADK doc according to issue #<issue number> - <change id>", where <issue number> is the number of the ADK docs issue and <change id> is the id of the recommended change (e.g. "1", "2", etc.).
|
||||
- The body of the pull request should be the instructions about how to update the ADK docs.
|
||||
- **{APPROVAL_INSTRUCTION}**
|
||||
|
||||
# 4. Guidelines & Rules
|
||||
- **File Paths:** Always use absolute paths when calling the tools to read files, list directories, or search the codebase.
|
||||
- **Tool Call Parallelism:** Execute multiple independent tool calls in parallel when feasible (i.e. searching the codebase).
|
||||
- **Explaination:** Provide concise explanations for your actions and reasoning for each step.
|
||||
|
||||
# 5. Output
|
||||
Present the followings in an easy to read format as the final output to the user.
|
||||
- The actions you took and the reasoning
|
||||
- The summary of the pull request created
|
||||
""",
|
||||
tools=[
|
||||
clone_or_pull_repo,
|
||||
list_directory_contents,
|
||||
search_local_git_repo,
|
||||
read_local_git_repo_file_content,
|
||||
create_pull_request_from_changes,
|
||||
get_issue,
|
||||
],
|
||||
)
|
||||
@@ -0,0 +1,105 @@
|
||||
# Copyright 2025 Google LLC
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import argparse
|
||||
import asyncio
|
||||
import logging
|
||||
import time
|
||||
|
||||
from adk_documentation.adk_docs_updater import agent
|
||||
from adk_documentation.settings import CODE_OWNER
|
||||
from adk_documentation.settings import CODE_REPO
|
||||
from adk_documentation.settings import DOC_OWNER
|
||||
from adk_documentation.settings import DOC_REPO
|
||||
from adk_documentation.tools import get_issue
|
||||
from adk_documentation.utils import call_agent_async
|
||||
from google.adk.cli.utils import logs
|
||||
from google.adk.runners import InMemoryRunner
|
||||
|
||||
APP_NAME = "adk_docs_updater"
|
||||
USER_ID = "adk_docs_updater_user"
|
||||
|
||||
logs.setup_adk_logger(level=logging.DEBUG)
|
||||
|
||||
|
||||
def process_arguments():
|
||||
"""Parses command-line arguments."""
|
||||
parser = argparse.ArgumentParser(
|
||||
description="A script that creates pull requests to update ADK docs.",
|
||||
epilog=(
|
||||
"Example usage: \n"
|
||||
"\tpython -m adk_docs_updater.main --issue_number 123\n"
|
||||
),
|
||||
formatter_class=argparse.RawTextHelpFormatter,
|
||||
)
|
||||
|
||||
group = parser.add_mutually_exclusive_group(required=True)
|
||||
|
||||
group.add_argument(
|
||||
"--issue_number",
|
||||
type=int,
|
||||
metavar="NUM",
|
||||
help="Answer a specific issue number.",
|
||||
)
|
||||
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
async def main():
|
||||
args = process_arguments()
|
||||
if not args.issue_number:
|
||||
print("Please specify an issue number using --issue_number flag")
|
||||
return
|
||||
issue_number = args.issue_number
|
||||
|
||||
get_issue_response = get_issue(DOC_OWNER, DOC_REPO, issue_number)
|
||||
if get_issue_response["status"] != "success":
|
||||
print(f"Failed to get issue {issue_number}: {get_issue_response}\n")
|
||||
return
|
||||
issue = get_issue_response["issue"]
|
||||
|
||||
runner = InMemoryRunner(
|
||||
agent=agent.root_agent,
|
||||
app_name=APP_NAME,
|
||||
)
|
||||
session = await runner.session_service.create_session(
|
||||
app_name=APP_NAME,
|
||||
user_id=USER_ID,
|
||||
)
|
||||
|
||||
response = await call_agent_async(
|
||||
runner,
|
||||
USER_ID,
|
||||
session.id,
|
||||
f"Please update the ADK docs according to the following issue:\n{issue}",
|
||||
)
|
||||
print(f"<<<< Agent Final Output: {response}\n")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
start_time = time.time()
|
||||
print(
|
||||
f"Start creating pull requests to update {DOC_OWNER}/{DOC_REPO} docs"
|
||||
f" according the {CODE_OWNER}/{CODE_REPO} at"
|
||||
f" {time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(start_time))}"
|
||||
)
|
||||
print("-" * 80)
|
||||
asyncio.run(main())
|
||||
print("-" * 80)
|
||||
end_time = time.time()
|
||||
print(
|
||||
"Updating finished at"
|
||||
f" {time.strftime('%Y-%m-%d %H:%M:%S', time.gmtime(end_time))}",
|
||||
)
|
||||
print("Total script execution time:", f"{end_time - start_time:.2f} seconds")
|
||||
@@ -11,3 +11,5 @@
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from . import agent
|
||||
|
||||
@@ -12,19 +12,28 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
from adk_release_analyzer.settings import CODE_OWNER
|
||||
from adk_release_analyzer.settings import CODE_REPO
|
||||
from adk_release_analyzer.settings import DOC_OWNER
|
||||
from adk_release_analyzer.settings import DOC_REPO
|
||||
from adk_release_analyzer.settings import IS_INTERACTIVE
|
||||
from adk_release_analyzer.settings import LOCAL_REPOS_DIR_PATH
|
||||
from adk_release_analyzer.tools import clone_or_pull_repo
|
||||
from adk_release_analyzer.tools import create_issue
|
||||
from adk_release_analyzer.tools import get_changed_files_between_releases
|
||||
from adk_release_analyzer.tools import list_directory_contents
|
||||
from adk_release_analyzer.tools import list_releases
|
||||
from adk_release_analyzer.tools import read_local_git_repo_file_content
|
||||
from adk_release_analyzer.tools import search_local_git_repo
|
||||
import os
|
||||
import sys
|
||||
|
||||
SAMPLES_DIR = os.path.abspath(
|
||||
os.path.join(os.path.dirname(__file__), "..", "..")
|
||||
)
|
||||
if SAMPLES_DIR not in sys.path:
|
||||
sys.path.append(SAMPLES_DIR)
|
||||
|
||||
from adk_documentation.settings import CODE_OWNER
|
||||
from adk_documentation.settings import CODE_REPO
|
||||
from adk_documentation.settings import DOC_OWNER
|
||||
from adk_documentation.settings import DOC_REPO
|
||||
from adk_documentation.settings import IS_INTERACTIVE
|
||||
from adk_documentation.settings import LOCAL_REPOS_DIR_PATH
|
||||
from adk_documentation.tools import clone_or_pull_repo
|
||||
from adk_documentation.tools import create_issue
|
||||
from adk_documentation.tools import get_changed_files_between_releases
|
||||
from adk_documentation.tools import list_directory_contents
|
||||
from adk_documentation.tools import list_releases
|
||||
from adk_documentation.tools import read_local_git_repo_file_content
|
||||
from adk_documentation.tools import search_local_git_repo
|
||||
from google.adk import Agent
|
||||
|
||||
if IS_INTERACTIVE:
|
||||
@@ -91,13 +100,13 @@ root_agent = Agent(
|
||||
Explanation of why this change is necessary.
|
||||
|
||||
**Reference**:
|
||||
Reference to the code change (e.g. https://github.com/google/adk-python/commit/b3b70035c432670a5f0b5cdd1e9467f43b80495c).
|
||||
Reference to the code file (e.g. src/google/adk/tools/spanner/metadata_tool.py).
|
||||
```
|
||||
- When referncing doc file, use the full relative path of the doc file in the ADK Docs repository (e.g. docs/sessions/memory.md).
|
||||
9. Create or recommend to create a Github issue in the Github Repository {DOC_REPO} with the instructions using the `create_issue` tool.
|
||||
- The title of the issue should be "Found docs updates needed from ADK python release <start_tag> to <end_tag>", where start_tag and end_tag are the release tags.
|
||||
- The body of the issue should be the instructions about how to update the ADK docs.
|
||||
- Include the compare link between the two ADK releases in the issue body, e.g. https://github.com/google/adk-python/compare/v1.14.0...v1.14.1.
|
||||
- **{APPROVAL_INSTRUCTION}**
|
||||
|
||||
# 4. Guidelines & Rules
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user