-
Notifications
You must be signed in to change notification settings - Fork 2.4k
feat(agent): Implement stale issue bot #3546
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Summary of ChangesHello @ryanaiagent, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request delivers a new, intelligent 'Stale Issue Auditor' agent aimed at improving repository hygiene by automating the process of identifying and managing inactive GitHub issues. By leveraging the GitHub API and a Large Language Model, the agent can discern when a maintainer's request for information has gone unaddressed, applying appropriate labels and notifications, and eventually closing issues that remain unresolved. This initiative seeks to reduce repository clutter and allow maintainers to focus on actionable items more effectively. Highlights
Ignored Files
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
|
Response from ADK Triaging Agent Hello @ryanaiagent, thank you for creating this PR! I've noticed that the Also, I see that the checkboxes for adding and passing tests are not checked in the PR checklist. Could you please confirm if tests have been added and are passing locally? You can find more information in our contribution guide. This information will help reviewers to review your PR more efficiently. Thanks! |
|
Response from ADK Triaging Agent Hello @ryanaiagent, thank you for creating this PR! To help reviewers review your PR more efficiently, could you please address the following:
Thanks! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request introduces a new 'Stale Issue Auditor' agent, which is a great addition for maintaining repository hygiene. The implementation is well-structured, with clear separation of concerns between settings, API utilities, and the agent logic itself. The use of an LLM for semantic intent analysis is a sophisticated approach.
My review focuses on improving correctness and maintainability. The most critical issue is a lack of pagination when fetching issue timelines, which could lead to incorrect agent behavior on issues with long histories. I've also pointed out some smaller issues like inconsistent documentation, unused code, and incorrect type hints.
Overall, this is a solid feature, and with these changes, it will be even more robust.
|
Hi @Jacksunwei , can you please review this? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request introduces a new "Stale Issue Auditor" agent, which is a well-designed and valuable tool for repository maintenance. The implementation is robust, featuring dynamic maintainer detection and comprehensive issue timeline analysis. The code is well-structured and comes with thorough documentation.
My review focuses on a few areas to enhance robustness, performance, and correctness. In agent.py, I've identified a critical typo in the agent's instruction prompt, suggested removing some unused code to optimize a tool, and recommended reordering API calls for greater resilience. For utils.py, I've proposed using a requests.Session to improve the performance of GitHub API interactions. These changes should further solidify this excellent contribution.
|
@xuanyang15 , could you get this reviewed and merged, given you have the best context of our bots? I think it's likely a good add to our repo bots. |
|
/gemini review |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request introduces a well-designed "Stale Issue Auditor" agent. The architecture is robust, featuring dynamic maintainer detection, full issue timeline analysis with pagination, and semantic intent analysis using an LLM. The code is generally clean, well-documented, and includes a comprehensive README. My review includes a critical fix for the model name and suggestions to remove unused code for better maintainability. I also noted a minor inefficiency in the agent's workflow where multiple tool calls are made to add labels; this could be consolidated into a single tool for better atomicity and performance.
| # --- Agent Definition --- | ||
|
|
||
| root_agent = Agent( | ||
| model="gemini-2.5-flash", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it is working locally when i use that model.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Running into error 503 when i use 2.5 pro
|
/gemini review |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request introduces a new 'Stale Issue Auditor' agent, which is a great addition for repository maintenance. The implementation is well-structured, with clear separation of concerns between settings, utilities, and the agent logic. The agent's decision-making process is well-documented in both the README and the agent's instruction prompt.
My review focuses on improving robustness and correctness. I've identified a critical issue with the configured model name and a high-severity issue with a hardcoded value in a user-facing comment that should be dynamic. I've also included a medium-severity suggestion to improve error handling by catching more specific exceptions.
Overall, this is a solid contribution and a very useful sample agent.
| # --- Agent Definition --- | ||
|
|
||
| root_agent = Agent( | ||
| model="gemini-2.5-flash", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
… ensures all user-facing messages are dynamically configured
|
/gemini review |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request introduces a well-designed "Stale Issue Auditor" agent to automate repository hygiene. The architecture is robust, featuring dynamic maintainer detection, full timeline analysis, and configurable thresholds. The code is generally of high quality and the documentation is clear. My review focuses on increasing the robustness of the agent's logic by improving error handling, ensuring the agent's tools provide all necessary information to its reasoning model, and making the LLM prompts more explicit to prevent ambiguity. These changes will help make the agent's behavior more reliable and predictable.
|
/gemini review |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
This pull request introduces a new autonomous agent, the "Stale Issue Auditor," designed to manage stale issues in a GitHub repository. The agent leverages dynamic maintainer detection, full timeline analysis, and semantic intent analysis using a Gemini model to identify, label, and close issues where maintainers have requested clarification but received no response. The solution is well-architected with clear configuration options and a comprehensive testing plan.
Overall, the code is well-structured and follows good practices for interacting with the GitHub API and integrating with an LLM agent. The README provides a clear overview of the agent's functionality and configuration. My feedback primarily focuses on improving logging practices, clarifying documentation, and addressing a minor design consideration regarding API token handling.
| from datetime import timezone | ||
| from typing import Any |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a good practice to use Python's built-in logging module instead of print statements for debug messages. This allows for more flexible control over log levels, output formats, and destinations without modifying the code. You can configure the logger to output debug messages only in development environments and suppress them in production.
Consider adding import logging at the top and logger = logging.getLogger(__name__) after imports, then replace print("DEBUG: ...") with logger.debug("...").
| from datetime import timezone | |
| from typing import Any | |
| from datetime import datetime | |
| from datetime import timezone | |
| import logging |
| Fetches the list of repository collaborators with 'push' (write) access or higher. | ||
| This should only be called once per run. | ||
| """ | ||
| print("DEBUG: Fetching repository maintainers with push access...") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As mentioned in the previous comment, using the logging module is preferred for debug output. This change replaces the print statement with a logger.debug call, assuming a logger has been initialized.
| print("DEBUG: Fetching repository maintainers with push access...") | |
| logger.debug("Fetching repository maintainers with push access...") |
| collaborators_data = get_request(url, params) | ||
|
|
||
| maintainers = [user["login"] for user in collaborators_data] | ||
| print(f"DEBUG: Found {len(maintainers)} maintainers: {maintainers}") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| print( | ||
| f"\nDEBUG: Fetching a batch of {ISSUES_PER_RUN} oldest open issues for" | ||
| " audit..." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
|
|
||
| async def main(): | ||
| """Initializes and runs the stale issue agent.""" | ||
| print(f"--- Starting Stale Agent at {time.ctime()} ---") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| "Find and process all open issues to manage staleness according to your" | ||
| " rules." | ||
| ) | ||
| print(f"Agent Prompt: {prompt_text}\n") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| and event.content.parts | ||
| and hasattr(event.content.parts[0], "text") | ||
| ): | ||
| # Print the agent's "thoughts" and actions for logging purposes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| # Print the agent's "thoughts" and actions for logging purposes | ||
| print(f"** {event.author} (ADK): {event.content.parts[0].text}") | ||
|
|
||
| print(f"\n--- Stale Agent Finished at {time.ctime()} ---") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| "Authorization": f"token {GITHUB_TOKEN}", | ||
| "Accept": "application/vnd.github.v3+json", | ||
| }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The _session object is initialized globally using GITHUB_TOKEN from settings.py. While this is fine for a script that runs and exits, in a long-running process or if the GITHUB_TOKEN could potentially be refreshed or changed during runtime, the _session would not automatically pick up the new token. For this specific bot, which is likely run on a schedule, this might not be an issue, but it's a design consideration for more dynamic applications. If the token could change, the session headers would need to be updated dynamically or the session re-initialized.
|
/gemini review |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code Review
The pull request introduces a new stale issue bot, which is a valuable addition for repository maintenance. The core logic for identifying stale issues and managing their lifecycle is well-defined within the PROMPT_INSTRUCTION.txt and agent.py files. The README.md provides a clear overview and configuration details. However, there are several areas for improvement, particularly regarding logging practices, potential race conditions in API calls, and clarity in LLM prompt instructions. Specifically, the use of print statements for debugging should be replaced with a proper logging framework, and the requests.Session object in utils.py needs to be handled carefully in a concurrent environment. Additionally, a critical logic error in get_issue_state could lead to incorrect stale label detection.
| while True: | ||
| # Construct the URL for the current page, requesting 100 items per page. | ||
| paginated_url = f"{timeline_url_base}?per_page=100&page={page}" | ||
| print(f"DEBUG: Fetching timeline page {page}...") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| print( | ||
| f"DEBUG: Fetched a total of {len(timeline_data)} timeline events across" | ||
| f" {page} page(s)." | ||
| ) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| collaborators_data = get_request(url, params) | ||
|
|
||
| maintainers = [user["login"] for user in collaborators_data] | ||
| print(f"DEBUG: Found {len(maintainers)} maintainers: {maintainers}") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| "Find and process all open issues to manage staleness according to your" | ||
| " rules." | ||
| ) | ||
| print(f"Agent Prompt: {prompt_text}\n") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| and hasattr(event.content.parts[0], "text") | ||
| ): | ||
| # Print the agent's "thoughts" and actions for logging purposes | ||
| print(f"** {event.author} (ADK): {event.content.parts[0].text}") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Similar to the previous comment, please replace print statements with logging.info for better control and flexibility in managing output verbosity.
| print(f"** {event.author} (ADK): {event.content.parts[0].text}") | |
| logging.info(f"** {event.author} (ADK): {event.content.parts[0].text}") |
| # Print the agent's "thoughts" and actions for logging purposes | ||
| print(f"** {event.author} (ADK): {event.content.parts[0].text}") | ||
|
|
||
| print(f"\n--- Stale Agent Finished at {time.ctime()} ---") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| STALE_LABEL_NAME = "stale" | ||
| REQUEST_CLARIFICATION_LABEL = "request clarification" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These label names are currently hardcoded. While this might be acceptable for a simple bot, making them configurable via environment variables (similar to the thresholds) would increase the bot's flexibility and reusability across different repositories with varying label conventions.
| STALE_LABEL_NAME = "stale" | |
| REQUEST_CLARIFICATION_LABEL = "request clarification" | |
| STALE_LABEL_NAME = os.getenv("STALE_LABEL_NAME", "stale") | |
| REQUEST_CLARIFICATION_LABEL = os.getenv("REQUEST_CLARIFICATION_LABEL", "request clarification") |
| - **CRITICAL CHECK**: Now, you must verify the author has not already responded. Compare the `last_author_event_time` and the `last_maintainer_comment_time`. | ||
| - **IF the author has NOT responded** (i.e., `last_author_event_time` is older than `last_maintainer_comment_time` or is null): | ||
| - **Get Time Difference**: Call `calculate_time_difference` with the `last_maintainer_comment_time`. | ||
| - **Decision & Report**: If `hours_passed` > **{STALE_HOURS_THRESHOLD}**: Report "Analysis for Issue #[number]: PENDING. Stale threshold met ({STALE_HOURS_THRESHOLD} hours)." Action: Marking as stale and then call `add_stale_label_and_comment` and if label name '{REQUEST_CLARIFICATION_LABEL}' is missing then call `add_label_to_issue` with the label name '{REQUEST_CLARIFICATION_LABEL}'. Otherwise, report: "Analysis for Issue #[number]: PENDING. Stale threshold not met. Action: None." |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This instruction combines multiple actions and a conditional check into a single, complex sentence. Breaking this down into clearer, sequential steps or offloading the conditional logic (if label name '{REQUEST_CLARIFICATION_LABEL}' is missing) to the tool itself would make the prompt easier for the LLM to parse and execute reliably. For example, the tool add_stale_label_and_comment could internally handle adding the clarification label if it's missing.
Please ensure you have read the contribution guide before creating a pull request.
Link to Issue or Description of Change
1. Link to an existing issue (if applicable):
2. Or, if no issue exists, describe the change:
Problem:
Active repositories often accumulate issues where a maintainer has requested clarification, but the author has not responded. These "stale" issues create noise, making it difficult for maintainers to focus on actionable items. There is currently no automated process to identify, manage, and eventually close these abandoned issues.
Solution:
This PR introduces a new, autonomous agent, the "Stale Issue Auditor," designed to help maintain repository hygiene. It runs on a daily schedule, proactively audits open issues, and manages their state based on conversational context.
The agent is architected to be highly robust and self-configuring:
A complete README.md with detailed configuration and feature descriptions is included in the contributing/samples/adk_stale_bot/ directory.
Testing Plan
Unit Tests:
Manual End-to-End (E2E) Tests:
This agent was tested on a forked repository by creating a comprehensive suite of test cases to validate every rule in its decision tree.
Setup:
Test Scenarios Executed:
A series of test issues were created to validate the following conditions:
Checklist