You've already forked adk-python
mirror of
https://github.com/encounter/adk-python.git
synced 2026-03-30 10:57:20 -07:00
docs: Update ADK triaging agent to only triage planned issues
It also enables the ADK triaging agent to run periodically on planned but not triaged issues. Co-authored-by: Xuan Yang <xygoogle@google.com> PiperOrigin-RevId: 834489103
This commit is contained in:
committed by
Copybara-Service
parent
f13a11e1dc
commit
679d543f8e
@@ -2,11 +2,16 @@ name: ADK Issue Triaging Agent
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [opened, reopened]
|
||||
types: [labeled]
|
||||
schedule:
|
||||
# Run every 6 hours to triage planned but not triaged issues
|
||||
- cron: '0 */6 * * *'
|
||||
|
||||
jobs:
|
||||
agent-triage-issues:
|
||||
runs-on: ubuntu-latest
|
||||
# Only run if labeled with "planned" or if it's a scheduled run
|
||||
if: github.event_name == 'schedule' || github.event.label.name == 'planned'
|
||||
permissions:
|
||||
issues: write
|
||||
contents: read
|
||||
|
||||
@@ -110,6 +110,42 @@ def list_unlabeled_issues(issue_count: int) -> dict[str, Any]:
|
||||
return {"status": "success", "issues": unlabeled_issues}
|
||||
|
||||
|
||||
def list_planned_untriaged_issues(issue_count: int) -> dict[str, Any]:
|
||||
"""List planned issues without component labels (e.g., core, tools, etc.).
|
||||
|
||||
Args:
|
||||
issue_count: number of issues to return
|
||||
|
||||
Returns:
|
||||
The status of this request, with a list of issues when successful.
|
||||
"""
|
||||
url = f"{GITHUB_BASE_URL}/search/issues"
|
||||
query = f"repo:{OWNER}/{REPO} is:open is:issue label:planned"
|
||||
params = {
|
||||
"q": query,
|
||||
"sort": "created",
|
||||
"order": "desc",
|
||||
"per_page": issue_count,
|
||||
"page": 1,
|
||||
}
|
||||
|
||||
try:
|
||||
response = get_request(url, params)
|
||||
except requests.exceptions.RequestException as e:
|
||||
return error_response(f"Error: {e}")
|
||||
issues = response.get("items", [])
|
||||
|
||||
# Filter out issues that already have component labels
|
||||
component_labels = set(LABEL_TO_OWNER.keys())
|
||||
untriaged_issues = []
|
||||
for issue in issues:
|
||||
issue_labels = {label["name"] for label in issue.get("labels", [])}
|
||||
# If the issue only has "planned" but no component labels, it's untriaged
|
||||
if not (issue_labels & component_labels):
|
||||
untriaged_issues.append(issue)
|
||||
return {"status": "success", "issues": untriaged_issues}
|
||||
|
||||
|
||||
def add_label_and_owner_to_issue(
|
||||
issue_number: int, label: str
|
||||
) -> dict[str, Any]:
|
||||
@@ -241,6 +277,7 @@ root_agent = Agent(
|
||||
""",
|
||||
tools=[
|
||||
list_unlabeled_issues,
|
||||
list_planned_untriaged_issues,
|
||||
add_label_and_owner_to_issue,
|
||||
change_issue_type,
|
||||
],
|
||||
|
||||
@@ -16,6 +16,7 @@ import asyncio
|
||||
import time
|
||||
|
||||
from adk_triaging_agent import agent
|
||||
from adk_triaging_agent.agent import LABEL_TO_OWNER
|
||||
from adk_triaging_agent.settings import EVENT_NAME
|
||||
from adk_triaging_agent.settings import GITHUB_BASE_URL
|
||||
from adk_triaging_agent.settings import ISSUE_BODY
|
||||
@@ -37,21 +38,32 @@ USER_ID = "adk_triage_user"
|
||||
|
||||
|
||||
async def fetch_specific_issue_details(issue_number: int):
|
||||
"""Fetches details for a single issue if it's unlabelled."""
|
||||
"""Fetches details for a single issue if it needs triaging."""
|
||||
url = f"{GITHUB_BASE_URL}/repos/{OWNER}/{REPO}/issues/{issue_number}"
|
||||
print(f"Fetching details for specific issue: {url}")
|
||||
|
||||
try:
|
||||
issue_data = get_request(url)
|
||||
if not issue_data.get("labels", None):
|
||||
print(f"Issue #{issue_number} is unlabelled. Proceeding.")
|
||||
labels = issue_data.get("labels", [])
|
||||
label_names = {label["name"] for label in labels}
|
||||
|
||||
# Check if issue has "planned" label but no component labels
|
||||
component_labels = set(LABEL_TO_OWNER.keys())
|
||||
has_planned = "planned" in label_names
|
||||
has_component = bool(label_names & component_labels)
|
||||
|
||||
if has_planned and not has_component:
|
||||
print(f"Issue #{issue_number} is planned but not triaged. Proceeding.")
|
||||
return {
|
||||
"number": issue_data["number"],
|
||||
"title": issue_data["title"],
|
||||
"body": issue_data.get("body", ""),
|
||||
}
|
||||
else:
|
||||
print(f"Issue #{issue_number} is already labelled. Skipping.")
|
||||
print(
|
||||
f"Issue #{issue_number} is already triaged or doesn't have"
|
||||
" 'planned' label. Skipping."
|
||||
)
|
||||
return None
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f"Error fetching issue #{issue_number}: {e}")
|
||||
@@ -108,26 +120,32 @@ async def main():
|
||||
specific_issue = await fetch_specific_issue_details(issue_number)
|
||||
if specific_issue is None:
|
||||
print(
|
||||
f"No unlabelled issue details found for #{issue_number} or an error"
|
||||
" occurred. Skipping agent interaction."
|
||||
f"No issue details found for #{issue_number} that needs triaging,"
|
||||
" or an error occurred. Skipping agent interaction."
|
||||
)
|
||||
return
|
||||
|
||||
issue_title = ISSUE_TITLE or specific_issue["title"]
|
||||
issue_body = ISSUE_BODY or specific_issue["body"]
|
||||
prompt = (
|
||||
f"A new GitHub issue #{issue_number} has been opened or"
|
||||
f' reopened. Title: "{issue_title}"\nBody:'
|
||||
f"A GitHub issue #{issue_number} has been labeled as 'planned'."
|
||||
f' Title: "{issue_title}"\nBody:'
|
||||
f' "{issue_body}"\n\nBased on the rules, recommend an'
|
||||
" appropriate label and its justification."
|
||||
" Then, use the 'add_label_to_issue' tool to apply the label "
|
||||
"directly to this issue. Only label it, do not"
|
||||
" appropriate component label and its justification."
|
||||
" Then, use the 'add_label_and_owner_to_issue' tool to apply the"
|
||||
" label directly to this issue. Only label it, do not"
|
||||
" process any other issues."
|
||||
)
|
||||
else:
|
||||
print(f"EVENT: Processing batch of issues (event: {EVENT_NAME}).")
|
||||
issue_count = parse_number_string(ISSUE_COUNT_TO_PROCESS, default_value=3)
|
||||
prompt = f"Please triage the most recent {issue_count} issues."
|
||||
prompt = (
|
||||
"Please use the 'list_planned_untriaged_issues' tool to find the"
|
||||
f" most recent {issue_count} planned issues that haven't been"
|
||||
" triaged yet (i.e., issues with 'planned' label but no component"
|
||||
" labels like 'core', 'tools', etc.). Then triage each of them by"
|
||||
" applying appropriate component labels."
|
||||
)
|
||||
|
||||
response = await call_agent_async(runner, USER_ID, session.id, prompt)
|
||||
print(f"<<<< Agent Final Output: {response}\n")
|
||||
|
||||
Reference in New Issue
Block a user