Skip to content

Conversation

@ryanaiagent
Copy link
Collaborator

@ryanaiagent ryanaiagent commented Nov 13, 2025

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):

  • N/A

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:

  • Dynamic Maintainer Detection: On each run, it uses the GitHub API to dynamically fetch the list of repository maintainers, removing the need for manual configuration.
  • Full Timeline Analysis: A sophisticated get_issue_state tool analyzes the issue's entire timeline to reliably detect the last human activity, including comments and body edits.
  • Semantic Intent Analysis: It uses a Gemini model to analyze the text of the last maintainer comment. It only triggers the "stale" process if the comment is a genuine request for information, avoiding false positives from simple statements.
  • Configurable State Management: Based on configurable time thresholds, it adds a stale label, posts a notification comment, removes the stale label upon new activity, and ultimately closes issues that remain stale for too long.

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:

  1. A forked repository was configured with ADK_TRIAGE_AGENT and GOOGLE_API_KEY secrets.
  2. 'stale' and 'request clarification' labels were created.
  3. The agent's time thresholds were set to 1 minute for rapid testing (STALE_HOURS_THRESHOLD=0.017).
  4. A second GitHub account was used to simulate third-party comments.

Test Scenarios Executed:
A series of test issues were created to validate the following conditions:

  • Stale Labeling: Verified that an issue with an unanswered maintainer question is correctly marked stale after the time threshold.
  • Stale Closing: Verified that an already-stale issue is correctly closed after the second time threshold.
  • Author Activity (Comment): Verified that a new comment from the author correctly removes the stale label.
  • Third-Party Activity: Verified that a comment from a non-author/non-maintainer correctly removes the stale label but leaves the request clarification label.
  • Proactive Labeling: Verified that the agent correctly adds the request-clarification label to a stale issue if a maintainer forgot to add it.
  • Intent Analysis: Verified that the bot correctly ignored issues where the last maintainer comment was not a request for information.

Checklist

  • I have read the CONTRIBUTING.md document.
  • I have performed a self-review of my own code.
  • I have commented my code, particularly in hard-to-understand areas.
  • I have added tests that prove my fix is effective or that my feature works.
  • New and existing unit tests pass locally with my changes.
  • I have manually tested my changes end-to-end.
  • Any dependent changes have been merged and published in downstream modules.

@gemini-code-assist
Copy link

Summary of Changes

Hello @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

  • New Stale Issue Auditor Agent: This pull request introduces a new autonomous agent, the 'Stale Issue Auditor', designed to manage and close inactive GitHub issues where maintainers have requested clarification but received no response.
  • Intelligent Issue Management: The agent uses a Gemini LLM for semantic intent analysis of maintainer comments, dynamically fetches repository maintainers, and analyzes the full issue timeline to accurately determine issue state and activity.
  • Configurable Lifecycle: It implements a configurable lifecycle for stale issues, including applying a 'stale' label, posting notification comments, removing the stale label upon new activity, and ultimately closing issues that remain inactive past a second threshold.
  • Deployment and Configuration: The agent is designed for daily execution via a GitHub Actions workflow and is configured entirely through environment variables, allowing for flexible threshold settings and API key management.
  • Comprehensive Testing: The agent has undergone extensive manual end-to-end testing on a forked repository, validating its decision tree across various scenarios, including stale labeling, closing, and activity-based label removal.
Ignored Files
  • Ignored by pattern: .github/workflows/** (1)
    • .github/workflows/stale-bot.yml
Using Gemini Code Assist

The 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 /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

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 .gemini/ folder in the base of the repository. Detailed instructions can be found here.

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

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@adk-bot
Copy link
Collaborator

adk-bot commented Nov 13, 2025

Response from ADK Triaging Agent

Hello @ryanaiagent, thank you for creating this PR!

I've noticed that the pyink-check and isort-check are failing. Please run ./autoformat.sh to fix the formatting issues.

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!

@adk-bot adk-bot added the tools [Component] This issue is related to tools label Nov 13, 2025
@adk-bot
Copy link
Collaborator

adk-bot commented Nov 13, 2025

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:

  • It looks like the pyink-check and isort-check are failing. Could you please run ./autoformat.sh to fix the formatting issues?
  • This PR is a new feature. Could you please associate a GitHub issue with this PR? If there is no existing issue, could you please create one?
  • Could you please add unit tests for your changes and ensure that they pass locally?

Thanks!

Copy link

@gemini-code-assist gemini-code-assist bot left a 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.

@ryanaiagent
Copy link
Collaborator Author

Hi @Jacksunwei , can you please review this?

Copy link

@gemini-code-assist gemini-code-assist bot left a 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.

@Jacksunwei Jacksunwei assigned xuanyang15 and unassigned Jacksunwei Nov 14, 2025
@Jacksunwei
Copy link
Collaborator

Jacksunwei commented Nov 14, 2025

@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.

@ryanaiagent
Copy link
Collaborator Author

/gemini review

Copy link

@gemini-code-assist gemini-code-assist bot left a 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",

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

There appears to be a typo in the model name. gemini-2.5-flash is not a valid model name; it should likely be gemini-1.5-flash. This typo will cause the agent to fail at runtime when trying to initialize the model.

Suggested change
model="gemini-2.5-flash",
model="gemini-1.5-flash",

Copy link
Collaborator Author

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.

Copy link
Collaborator Author

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

@ryanaiagent
Copy link
Collaborator Author

/gemini review

Copy link

@gemini-code-assist gemini-code-assist bot left a 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",

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The model name gemini-2.5-flash appears to be incorrect and will likely cause a runtime error as it does not correspond to a known model. The intended model is probably gemini-1.5-flash.

Suggested change
model="gemini-2.5-flash",
model="gemini-1.5-flash",

@ryanaiagent
Copy link
Collaborator Author

/gemini review

Copy link

@gemini-code-assist gemini-code-assist bot left a 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.

@ryanaiagent
Copy link
Collaborator Author

/gemini review

Copy link

@gemini-code-assist gemini-code-assist bot left a 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.

Comment on lines 2 to 3
from datetime import timezone
from typing import Any

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

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("...").

Suggested change
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...")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

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.

Suggested change
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}")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Consistent use of the logging module for debug messages.

Suggested change
print(f"DEBUG: Found {len(maintainers)} maintainers: {maintainers}")
logger.debug("Found %d maintainers: %s", len(maintainers), maintainers)

Comment on lines +47 to +49
print(
f"\nDEBUG: Fetching a batch of {ISSUES_PER_RUN} oldest open issues for"
" audit..."

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Consistent use of the logging module for debug messages.

Suggested change
print(
f"\nDEBUG: Fetching a batch of {ISSUES_PER_RUN} oldest open issues for"
" audit..."
logger.debug(
"Fetching a batch of %d oldest open issues for audit...",
ISSUES_PER_RUN,


async def main():
"""Initializes and runs the stale issue agent."""
print(f"--- Starting Stale Agent at {time.ctime()} ---")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Replace print with logger.info for consistent logging practices. Ensure a logger is initialized (e.g., logger = logging.getLogger(__name__)).

Suggested change
print(f"--- Starting Stale Agent at {time.ctime()} ---")
logger.info("--- Starting Stale Agent at %s ---", time.ctime())

"Find and process all open issues to manage staleness according to your"
" rules."
)
print(f"Agent Prompt: {prompt_text}\n")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Replace print with logger.info for consistent logging practices.

Suggested change
print(f"Agent Prompt: {prompt_text}\n")
logger.info("Agent Prompt: %s", prompt_text)

and event.content.parts
and hasattr(event.content.parts[0], "text")
):
# Print the agent's "thoughts" and actions for logging purposes

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Replace print with logger.info for consistent logging practices.

Suggested change
# Print the agent's "thoughts" and actions for logging purposes
logger.info("** %s (ADK): %s", event.author, 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()} ---")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Replace print with logger.info for consistent logging practices.

Suggested change
print(f"\n--- Stale Agent Finished at {time.ctime()} ---")
logger.info("--- Stale Agent Finished at %s ---", time.ctime())

Comment on lines +8 to +10
"Authorization": f"token {GITHUB_TOKEN}",
"Accept": "application/vnd.github.v3+json",
})

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

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.

@ryanaiagent
Copy link
Collaborator Author

/gemini review

Copy link

@gemini-code-assist gemini-code-assist bot left a 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}...")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Please replace print statements with logging.debug for better control and flexibility in managing output verbosity.

      logging.debug(f"Fetching timeline page {page}...")

Comment on lines +135 to +138
print(
f"DEBUG: Fetched a total of {len(timeline_data)} timeline events across"
f" {page} page(s)."
)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Please replace print statements with logging.debug for better control and flexibility in managing output verbosity.

    logging.debug(
        f"Fetched a total of {len(timeline_data)} timeline events across" f" {page} page(s)."
    )

collaborators_data = get_request(url, params)

maintainers = [user["login"] for user in collaborators_data]
print(f"DEBUG: Found {len(maintainers)} maintainers: {maintainers}")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Similar to the previous comment, please replace print statements with logging.debug for better control and flexibility in managing output verbosity.

    logging.debug(f"Found {len(maintainers)} maintainers: {maintainers}")

"Find and process all open issues to manage staleness according to your"
" rules."
)
print(f"Agent Prompt: {prompt_text}\n")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Similar to the previous comment, please replace print statements with logging.info for better control and flexibility in managing output verbosity.

Suggested change
print(f"Agent Prompt: {prompt_text}\n")
logging.info(f"Agent Prompt: {prompt_text}")

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}")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Similar to the previous comment, please replace print statements with logging.info for better control and flexibility in managing output verbosity.

Suggested change
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()} ---")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Similar to the previous comment, please replace print statements with logging.info for better control and flexibility in managing output verbosity.

Suggested change
print(f"\n--- Stale Agent Finished at {time.ctime()} ---")
logging.info(f"--- Stale Agent Finished at {time.ctime()} ---")

Comment on lines +18 to +19
STALE_LABEL_NAME = "stale"
REQUEST_CLARIFICATION_LABEL = "request clarification"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

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.

Suggested change
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."

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

tools [Component] This issue is related to tools

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants