The warning message shows that ADK Web is for development purposes only and should not be used in production, as it has access to all data. This warning is displayed when the `--with-ui` flag is used with `adk deploy` and `adk deploy to-gke`
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 839795361
Merge https://github.com/google/adk-python/pull/3583
**Please ensure you have read the [contribution guide](https://github.com/google/adk-python/blob/main/CONTRIBUTING.md) before creating a pull request.**
### Link to Issue or Description of Change
**1. Link to an existing issue (if applicable):**
- Closes: #3582
**2. Or, if no issue exists, describe the change:**
_If applicable, please follow the issue templates to provide as much detail as
possible._
**Problem:**
Currently, the BigQuery tool in ADK does not provide a way for developers to add custom labels to BigQuery jobs created by their agents. This makes it difficult to:
Track and monitor BigQuery costs associated with specific agents or use cases
Organize and filter BigQuery jobs in the Google Cloud Console
Implement billing attribution and resource organization strategies
Differentiate between jobs from different environments (dev, staging, production)
While the tool automatically adds an internal adk-bigquery-tool label with the caller_id, there's no mechanism for users to add their own custom labels for tracking and monitoring purposes.
**Solution:**
Add a labels configuration field to BigQueryToolConfig that allows users to specify custom key-value pairs to be applied to all BigQuery jobs executed by the agent. The solution should:
Configuration Option: Add an optional labels parameter to BigQueryToolConfig accepting a dictionary of string key-value pairs
Validation: Ensure labels follow BigQuery's requirements (non-empty string keys, string values)
Job Application: Automatically apply configured labels to all BigQuery jobs alongside the existing internal labels Documentation: Provide clear documentation on how to use labels for tracking and monitoring
### Testing Plan
_Please describe the tests that you ran to verify your changes. This is required
for all PRs that are not small documentation or typo fixes._
**Unit Tests:**
- [x] I have added or updated unit tests for my change.
- [x] All unit tests pass locally.
_Please include a summary of passed `pytest` results._
```
pytest tests/unittests/tools/bigquery/test_bigquery_tool_config.py -v --tb=line -W ignore::UserWarning
========================================= test session starts ==========================================
platform darwin -- Python 3.11.14, pytest-9.0.1, pluggy-1.6.0 -- *****redacted******
cachedir: .pytest_cache
rootdir: *****redacted******
configfile: pyproject.toml
plugins: mock-3.15.1, anyio-4.11.0, xdist-3.8.0, langsmith-0.4.43, asyncio-1.3.0
asyncio: mode=Mode.AUTO, debug=False, asyncio_default_fixture_loop_scope=function, asyncio_default_test_loop_scope=function
collected 14 items
tests/unittests/tools/bigquery/test_bigquery_tool_config.py::test_bigquery_tool_config_experimental_warning PASSED [ 7%]
tests/unittests/tools/bigquery/test_bigquery_tool_config.py::test_bigquery_tool_config_invalid_property PASSED [ 14%]
tests/unittests/tools/bigquery/test_bigquery_tool_config.py::test_bigquery_tool_config_invalid_application_name PASSED [ 21%]
tests/unittests/tools/bigquery/test_bigquery_tool_config.py::test_bigquery_tool_config_max_query_result_rows_default PASSED [ 28%]
tests/unittests/tools/bigquery/test_bigquery_tool_config.py::test_bigquery_tool_config_max_query_result_rows_custom PASSED [ 35%]
tests/unittests/tools/bigquery/test_bigquery_tool_config.py::test_bigquery_tool_config_valid_maximum_bytes_billed PASSED [ 42%]
tests/unittests/tools/bigquery/test_bigquery_tool_config.py::test_bigquery_tool_config_invalid_maximum_bytes_billed PASSED [ 50%]
tests/unittests/tools/bigquery/test_bigquery_tool_config.py::test_bigquery_tool_config_valid_labels PASSED [ 57%]
tests/unittests/tools/bigquery/test_bigquery_tool_config.py::test_bigquery_tool_config_empty_labels PASSED [ 64%]
tests/unittests/tools/bigquery/test_bigquery_tool_config.py::test_bigquery_tool_config_none_labels PASSED [ 71%]
tests/unittests/tools/bigquery/test_bigquery_tool_config.py::test_bigquery_tool_config_invalid_labels_type PASSED [ 78%]
tests/unittests/tools/bigquery/test_bigquery_tool_config.py::test_bigquery_tool_config_invalid_label_key_type PASSED [ 85%]
tests/unittests/tools/bigquery/test_bigquery_tool_config.py::test_bigquery_tool_config_invalid_label_value_type PASSED [ 92%]
tests/unittests/tools/bigquery/test_bigquery_tool_config.py::test_bigquery_tool_config_empty_label_key PASSED [100%]
==================================================================================================== 14 passed in 2.02s ====================================================================================================
```
**Manual End-to-End (E2E) Tests:**
_Please provide instructions on how to manually test your changes, including any
necessary setup or configuration. Please provide logs or screenshots to help
reviewers better understand the fix._
### Checklist
- [x] I have read the [CONTRIBUTING.md](https://github.com/google/adk-python/blob/main/CONTRIBUTING.md) document.
- [x] I have performed a self-review of my own code.
- [x] I have commented my code, particularly in hard-to-understand areas.
- [x] I have added tests that prove my fix is effective or that my feature works.
- [x] New and existing unit tests pass locally with my changes.
- [x] I have manually tested my changes end-to-end.
- [x] Any dependent changes have been merged and published in downstream modules.
### Additional context
_Add any other context or screenshots about the feature request here._
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/3583 from Faraaz1994:feature/bq_label 0fd7fe6a3b1ee20a36f73562e425d007b8d7dc9d
PiperOrigin-RevId: 839523588
The vector_store_similarity_search tool performs similarity search against data in a Spanner vector store table, using the provided Spanner tool settings for configuration.
PiperOrigin-RevId: 839352057
The Gemini API may not always send an explicit transcription finished signal. This change ensures that any buffered input or output transcription text is yielded as a finished transcription when a turn is completed, generation is complete, or the session is interrupted.
Also, refined the check for `event.partial` in runners.py to be more explicit.
Co-authored-by: Hangfei Lin <hangfei@google.com>
PiperOrigin-RevId: 839008606
LlmAgentConfig.model now accepts either a plain model string or a CodeConfig. This lets YAML configs pass a LiteLLM instance with managed API settings (e.g., api_base and fallbacks) so agents can hit KimiK2’s managed endpoint instead of only the default modelID.
Close#3579
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 838978654
This change adds new `POST` endpoint `/apps/{app_name}/users/{user_id}/sessions/{session_id}/artifacts` to the ADK web server. This endpoint lets clients to save new artifacts associated with a specific session. The endpoint uses `SaveArtifactRequest` and returns `SaveArtifactResponse`, including the version and canonical URI of the saved artifact.
Close#1975
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 838977880
Default CLI session storage to SQLite instead of in-memory
Previously, adk run and adk web used in-memory session storage by default, causing sessions to be lost on restart. Now sessions persist to .adk/session.db automatically. To use in-memory storage, pass --session-service-uri memory://
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 838975328
Merge https://github.com/google/adk-python/pull/3700
### Description
This PR refactors the `adk_stale_agent` to address `429 RESOURCE_EXHAUSTED` errors encountered during workflow execution. The previous implementation was inefficient in fetching issue history (using pagination over the REST API) and lacked server-side filtering, causing excessive API calls and huge token consumption that breached Gemini API quotas.
The new implementation switches to a **GraphQL-first approach**, implements server-side filtering via the Search API, adds robust concurrency controls, and significantly improves code maintainability through modular refactoring.
### Root Cause of Failure
The previous workflow failed with the following error due to passing too much context to the LLM and processing too many irrelevant issues:
```text
google.genai.errors.ClientError: 429 RESOURCE_EXHAUSTED.
Quota exceeded for metric: generativelanguage.googleapis.com/generate_content_paid_tier_input_token_count
```
### Key Changes
#### 1. Optimization: REST → GraphQL (`agent.py`)
* **Old:** Fetched issue comments and timeline events using multiple paginated REST API calls (`/timeline`).
* **New:** Implemented `get_issue_state` using a single **GraphQL** query. This fetches comments, `userContentEdits`, and specific timeline events (Labels, Renames) in one network request.
* **Refactoring:** The complex analysis logic has been decomposed into focused helper functions (_fetch_graphql_data, _build_history_timeline, _replay_history_to_find_state) for better readability and testing.
* **Configurable:** Added GRAPHQL_COMMENT_LIMIT and GRAPHQL_TIMELINE_LIMIT settings to tune context depth
* **Impact:** Drastically reduces the data payload size and eliminates multiple API round-trips, significantly lowering the token count sent to the LLM.
#### 2. Optimization: Server-Side Filtering (`utils.py`)
* **Old:** Fetched *all* open issues via REST and filtered them in Python memory.
* **New:** Uses the GitHub Search API (`get_old_open_issue_numbers`) with `created:<DATE` syntax.
* **Impact:** Only fetches issue numbers that actually meet the age threshold, preventing the agent from wasting cycles and tokens on brand-new issues.
#### 3. Concurrency & Rate Limiting (`main.py` & `settings.py`)
* **Old:** Sequential execution loop.
* **New:** Implemented `asyncio.gather` with a configurable `CONCURRENCY_LIMIT` (set to 3).
* **New:** Added `urllib3` retry strategies (exponential backoff) in `utils.py` to handle GitHub API rate limits (HTTP 429) gracefully.
#### 4. Logic Improvements ("Ghost Edits")
* **New Feature:** The agent now detects "Ghost Edits" (where an author updates the issue description without posting a new comment).
* **Action:** If a silent edit is detected on a stale candidate, the agent now alerts maintainers instead of marking it stale, preventing false positives.
### File Comparison Summary
| File | Change |
| :--- | :--- |
| `main.py` | Switched from `InMemoryRunner` loop to `asyncio` chunked processing. Added execution timing and API usage logging. |
| `agent.py` | Replaced REST logic with GraphQL query. Added logic to handle silent body edits. Decomposed giant get_issue_state into helper functions with docstrings. Added _format_days helper. |
| `utils.py` | Added `HTTPAdapter` with Retries. Added `get_old_open_issue_numbers` using Search API. |
| `settings.py` | Removed `ISSUES_PER_RUN`; added configuration for CONCURRENCY_LIMIT, SLEEP_BETWEEN_CHUNKS, and GraphQL limits. |
| `PROMPT_INSTRUCTIONS.txt` | Simplified decision tree; removed date calculation responsibility from LLM. |
### Verification
The new logic minimizes token usage by offloading date calculations to Python and strictly limiting the context passed to the LLM to semantic intent analysis (e.g., "Is this a question?").
* **Metric Check:** The workflow now tracks API calls per issue to ensure we stay within limits.
* **Safety:** Silent edits by users now correctly reset the "Stale" timer.
* **Maintainability:** All complex logic is now isolated in typed helper functions with comprehensive docstrings.
Co-authored-by: Xuan Yang <xygoogle@google.com>
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/3700 from ryanaiagent:feat/improve-stale-agent 888064eff125ae74f7c3a9ad6c74f98de80243a2
PiperOrigin-RevId: 838885530
This change introduces an `AnthropicLlm` base class for direct Anthropic API calls using `AsyncAnthropic`. The existing `Claude` class now inherits from `AnthropicLlm` and is specialized to use `AsyncAnthropicVertex` for models hosted on Vertex AI. The `messages.create` call is now properly awaited
Merge: https://github.com/google/adk-python/pull/2904
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 838851026
This change updates the docstring for `agent_engine_id` to clarify that only the resource ID is expected. It also adds a warning log if the provided `agent_engine_id` contains a '/' character, suggesting it might be a full resource path, and provides guidance on how to extract the ID. Unit tests are added to verify the warning behavior.
Merge: https://github.com/google/adk-python/pull/2941
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 838845022
Also provide a command line tool `adk migrate session` for DB migration
Addresses https://github.com/google/adk-python/discussions/3605
Addresses https://github.com/google/adk-python/issues/3681
To verify:
```
# Start one postgres DB
docker run --name my-postgres -d -e POSTGRES_DB=agent -e POSTGRES_USER=agent -e POSTGRES_PASSWORD=agent -e PGDATA=/var/lib/postgresql/data/pgdata -v pgvolume:/var/lib/postgresql/data -p 5532:5432 postgres
# Connect to an old version of ADK and produce some query data
adk web --session_service_uri=postgresql://agent:agent@localhost:5532/agent
# Check out to the latest branch and restart ADK web
# You should see error log ask you to migrate the DB
# Start a new DB
docker run --name migration-test-db \
-d \ --rm \ -e POSTGRES_DB=agent \ -e POSTGRES_USER=agent \ -e POSTGRES_PASSWORD=agent -e PGDATA=/var/lib/postgresql/data/pgdata -v migration_test_vol:/var/lib/postgresql/data -p 5533:5432 postgres
# DB Migration
adk migrate session \
--source_db_url="postgresql://agent:agent@localhost:5532/agent" \
--dest_db_url="postgresql://agent:agent@localhost:5533/agent"
# Run ADK web with the new DB
adk web --session_service_uri=postgresql+asyncpg://agent:agent@localhost:5533/agent
# You should see the data from old DB is migrated
```
Co-authored-by: Shangjie Chen <deanchen@google.com>
PiperOrigin-RevId: 837341139
This calls the cloudapiregistry.googleapis.com API to get MCP tools from the project's registry, and adds them to ADK.
Co-authored-by: Kathy Wu <wukathy@google.com>
PiperOrigin-RevId: 837166909
Adds the shared adk_services_options decorator to adk run and other commands so developers can pass session/artifact URIs from the CLI
Has new warning for the unsupported memory service on adk run, and removes the legacy --session_db_url/--artifact_storage_uri flags with tests
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 836743358
This change routes adk run and the FastAPI server through the new session/artifact service factory, keeps the default experience backed by per-agent .adk storage
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 836733234
Previously, image parts were always filtered out when converting content to Anthropic message parameters. This change updates the logic to only filter out image parts and log a warning when the content role is not "user". This enables sending image data as part of user prompts to Claude models
Merges: https://github.com/google/adk-python/pull/3286
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 836725196
Merge https://github.com/google/adk-python/pull/3284
**Problem:**
When debugging agents that utilize the `VertexAiSearchTool`, it's currently difficult to inspect the specific configuration parameters (datastore ID, engine ID, filter, max_results, etc.) being passed to the underlying Vertex AI Search API via the `LlmRequest`. This lack of visibility can hinder troubleshooting efforts related to tool configuration.
**Solution:**
This PR enhances the `VertexAiSearchTool` by adding a **debug-level log statement** within the `process_llm_request` method. This log precisely records the parameters being used for the Vertex AI Search configuration just before it's appended to the `LlmRequest`.
This provides developers with crucial visibility into the tool's runtime behavior when debug logging is enabled, significantly improving the **debuggability** of agents using this tool. Corresponding unit tests were updated to rigorously verify this new logging output using `caplog`. Additionally, minor fixes were made to the tests to resolve Pydantic validation errors.
Co-authored-by: Xuan Yang <xygoogle@google.com>
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/3284 from omkute10:feat/add-logging-vertex-search-tool 199c12bf00a57abe202401591088c0423b39b928
PiperOrigin-RevId: 836419886
Merge https://github.com/google/adk-python/pull/2588
## Description
Fixes an issue in `base_llm_flow.py` where, in Bidi-streaming (live) mode, the multi-agent structure causes duplicated responses after tool calling.
## Problem
In Bidi-streaming (live) mode, when utilizing a multi-agent structure, the leaf-level sub-agent and its parent agent both process the same function call response, leading to duplicate replies. This duplication occurs because the parent agent's live connection remains open while initiating a new connection with the child agent.
## Root Cause
The issue originated from the placement of agent transfer logic in the `_postprocess_live` method at lines 547-557. When a `transfer_to_agent` function call was made:
1. The function response was processed in `_postprocess_live`
2. A recursive call to `agent_to_run.run_live` was initiated
3. This prevented the closure of the parent agent's connection at line 175 of the `run_live` method, as that code path was never reached
4. Both the parent and child agents remained active, causing both to process subsequent function responses
## Solution
This PR addresses the issue by ensuring the parent agent's live connection is closed before initiating a new one with the child agent. Changes made:
**Connection Management**: Moved the agent transfer logic from `_postprocess_live` method to the `run_live` method, specifically:
- Removed agent transfer handling from lines 547-557 in `_postprocess_live`
- Added agent transfer handling after connection closure at lines 176-184 in `run_live`
**Code Refactoring**: The agent transfer now occurs in the proper sequence:
1. Parent agent processes the `transfer_to_agent` function response
2. Parent agent's live connection is properly closed (line 175)
3. New connection with child agent is initiated (line 182)
4. Child agent handles subsequent function calls without duplication
**Improved Flow Control**: This ensures that each agent processes function call responses without duplication, maintaining proper connection lifecycle management in multi-agent structures.
## Testing
To verify this fix works correctly:
1. **Multi-Agent Structure Test**: Set up a multi-agent structure with a parent agent that transfers to a child agent via `transfer_to_agent` function call
2. **Bidi-Streaming Mode**: Enable Bidi-streaming (live) mode in the configuration
3. **Function Call Verification**: Trigger a function call that results in agent transfer
4. **Response Monitoring**: Verify that only one response is generated (not duplicated)
5. **Connection Management**: Confirm that parent agent's connection is properly closed before child agent starts
**Expected Behavior**:
- Single function response per call
- Clean agent handoffs without connection leaks
- Proper connection lifecycle management
## Backward Compatibility
This change is **fully backward compatible**:
- No changes to public APIs or method signatures
- Existing single-agent flows remain unaffected
- Non-live (regular async) flows continue to work as before
- Only affects the internal flow control in live multi-agent scenarios
Co-authored-by: Hangfei Lin <hangfei@google.com>
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/2588 from AlexeyChernenkoPlato:fix/double-function-response-processing-issue 3339260a4e007251137d199bdcef0ddef4487b03
PiperOrigin-RevId: 835619170
This change replaces the use of `ChatCompletionDeveloperMessage` with `ChatCompletionSystemMessage` and sets the role to "system" for providing system instructions to LiteLLM models
Close#3657
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 835388738
Merge https://github.com/google/adk-python/pull/3576
**Please ensure you have read the [contribution guide](https://github.com/google/adk-python/blob/main/CONTRIBUTING.md) before creating a pull request.**
### Link to Issue or Description of Change
**1. Link to an existing issue (if applicable):**
- Closes: #3557
- Related: #_issue_number_
**2. Or, if no issue exists, describe the change:**
_If applicable, please follow the issue templates to provide as much detail as
possible._
**Problem:**
When creating a BaseAgent with multiple sub-agents, there was no validation to ensure that all sub-agents have unique names. This could lead to confusion when trying to find or reference specific sub-agents by name, as duplicate names would make it ambiguous which agent is being referenced.
**Solution:**
Added a @field_validator for the sub_agents field in BaseAgent that validates all sub-agents have unique names. The validator:
Checks for duplicate names in the sub-agents list
Raises a ValueError with a clear error message listing all duplicate names found
Returns the validated list if all names are unique
Handles edge cases like empty lists gracefully
### Testing Plan
_Please describe the tests that you ran to verify your changes. This is required
for all PRs that are not small documentation or typo fixes._
**Unit Tests:**
- [x] I have added or updated unit tests for my change.
- [x] All unit tests pass locally.
_Please include a summary of passed `pytest` results._
Added 4 new test cases in tests/unittests/agents/test_base_agent.py:
test_validate_sub_agents_unique_names_single_duplicate: Verifies that a single duplicate name raises ValueError
test_validate_sub_agents_unique_names_multiple_duplicates: Verifies that multiple duplicate names are all reported in the error message
test_validate_sub_agents_unique_names_no_duplicates: Verifies that unique names pass validation successfully
test_validate_sub_agents_unique_names_empty_list: Verifies that empty sub-agents list passes validation
All tests pass locally. You can run with:
pytest tests/unittests/agents/test_base_agent.py::test_validate_sub_agents_unique_names_single_duplicate tests/unittests/agents/test_base_agent.py::test_validate_sub_agents_unique_names_multiple_duplicates tests/unittests/agents/test_base_agent.py::test_validate_sub_agents_unique_names_no_duplicates tests/unittests/agents/test_base_agent.py::test_validate_sub_agents_unique_names_empty_list -v
**Manual End-to-End (E2E) Tests:**
_Please provide instructions on how to manually test your changes, including any
necessary setup or configuration. Please provide logs or screenshots to help
reviewers better understand the fix._
Test Case 1: Duplicate names should raise error
from google.adk.agents import Agent
agent1 = Agent(name="sub_agent", model="gemini-2.5-flash")
agent2 = Agent(name="sub_agent", model="gemini-2.5-flash") # Same name
# This should raise ValueError
try:
parent = Agent(
name="parent",
model="gemini-2.5-flash",
sub_agents=[agent1, agent2]
)
except ValueError as e:
print(f"Expected error: {e}")
# Output: Found duplicate sub-agent names: `sub_agent`. All sub-agents must have unique names.
Test Case 2: Unique names should work
from google.adk.agents import Agent
agent1 = Agent(name="agent1", model="gemini-2.5-flash")
agent2 = Agent(name="agent2", model="gemini-2.5-flash")
# This should work without error
parent = Agent(
name="parent",
model="gemini-2.5-flash",
sub_agents=[agent1, agent2]
)
print("Success: Unique names validated correctly")
### Checklist
- [x] I have read the [CONTRIBUTING.md](https://github.com/google/adk-python/blob/main/CONTRIBUTING.md) document.
- [x] I have performed a self-review of my own code.
- [x] I have commented my code, particularly in hard-to-understand areas.
- [x] I have added tests that prove my fix is effective or that my feature works.
- [x] New and existing unit tests pass locally with my changes.
- [x] I have manually tested my changes end-to-end.
- [x] Any dependent changes have been merged and published in downstream modules.
### Additional context
This change adds validation at the BaseAgent level, so it automatically applies to all agent types that inherit from BaseAgent (e.g., LlmAgent, LoopAgent, etc.). The validation uses Pydantic's field validator system, which runs during object initialization, ensuring the constraint is enforced early and consistently.
The error message clearly identifies which names are duplicated, making it easy for developers to fix the issue:
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/3576 from sarojrout:feat/validate-unique-sub-agent-names 07adf1f9a5fc935389eb9dfa3cbc1311f551ebe3
PiperOrigin-RevId: 835358118
Merge https://github.com/google/adk-python/pull/3538
Main change from:
E(inv=2, role=user), E(inv=2, role=model), E(inv=2, role=user),
To:
E(inv=2, role=user), E(inv=2, role=model)
I think the last E(inv=2, role=user) was wrong. Also reformatted.
Co-authored-by: Hangfei Lin <hangfei@google.com>
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/3538 from adrianad:patch-1 627b933bdc3e00e45f704edf95448281e32d127c
PiperOrigin-RevId: 835346467
The `database_session_service` now updates the `update_time` of a session to the event's timestamp when an event is appended
Close#2721
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 834994070
LlmResponse/Event now keep both provider reasoning output and the raw vendor payload so callbacks and loggers can inspect hidden “thoughts” or trace bugs without rewriting adapters.
LiteLLM’s adapter and streaming loop emit reasoning chunks alongside text and aggregate them into final events -> all responses now carry a JSON-safe copy of the source payload for debug. UnsafeLocalCodeExecutor uses the documented exec(code, globals, globals) form, letting helper functions defined inside snippets call each other.
Close#1749
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 834956847
Merge https://github.com/google/adk-python/pull/3430
**Please ensure you have read the [contribution guide](https://github.com/google/adk-python/blob/main/CONTRIBUTING.md) before creating a pull request.**
### Link to Issue or Description of Change
**1. Link to an existing issue (if applicable):**
- Closes: #3429
**2. Or, if no issue exists, describe the change:**
_If applicable, please follow the issue templates to provide as much detail as
possible._
**Problem:**
The existing `/list-apps` endpoint only returns the name of the folder that each agent is in
**Solution:**
This adds a new endpoint `/list-apps-detailed` which will load each agent using the existing `AgentLoader.load_agent` method, and then return the folder name, display name (with underscores replaced with spaces for a more readable version), description, and the agent type.
This does introduce overhead if you had multiple agents since they all need to be loaded, but by maintaining the existing `/list-apps` endpoint, users can choose which one to hit if they don't want to load all agents. Since the existing `load_agents` method will cache results, there's only a penalty on the first hit.
### Testing Plan
Created a unit test for this, similar to the `/list-apps`. Also tested this with my own ADK instance to verify it loaded correctly.
```
curl --location "localhost:8000/list-apps-detailed"
```
```json
{
"apps": [
{
"name": "agent_1",
"displayName": "Agent 1",
"description": "A test description for a test agent",
"agentType": "package"
},
{
"name": "agent_2",
"displayName": "Agent 2",
"description": "A test description for a test agent ",
"agentType": "package"
},
{
"name": "agent_3",
"displayName": "Agent 3",
"description": "A test description for a test agent",
"agentType": "package"
}
]
}
```
**Unit Tests:**
- [X] I have added or updated unit tests for my change.
- [X] All unit tests pass locally.
3054 passed, 2383 warnings in 46.96s
### Checklist
- [X] I have read the [CONTRIBUTING.md](https://github.com/google/adk-python/blob/main/CONTRIBUTING.md) document.
- [X] I have performed a self-review of my own code.
- [X] I have commented my code, particularly in hard-to-understand areas.
- [X] I have added tests that prove my fix is effective or that my feature works.
- [X] New and existing unit tests pass locally with my changes.
- [X] I have manually tested my changes end-to-end.
- [X] Any dependent changes have been merged and published in downstream modules.
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/3430 from dylan-apex:more-detailed-list-apps e6864fd61a673da5fd2fb28d2d7d72cb90f5af0a
PiperOrigin-RevId: 834907771
Merge https://github.com/google/adk-python/pull/3572
**Please ensure you have read the [contribution guide](https://github.com/google/adk-python/blob/main/CONTRIBUTING.md) 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:**
Docs fix
### Checklist
- [ ] I have read the [CONTRIBUTING.md](https://github.com/google/adk-python/blob/main/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.
Co-authored-by: Hangfei Lin <hangfei@google.com>
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/3572 from issacg:patch-1 b7c7ed46ff0fb018f4da1537535eff27c323daf5
PiperOrigin-RevId: 834864431
The `Parameter` class now provides default Python names based on the parameter location when the original name is empty. This prevents parameters from having an empty string as their Python name, especially for request bodies defined without a top-level name.
Close#2213
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 834850255
Make sure that the adk run --save_session writes session JSON using the Pydantic camelCase aliases (by_alias=True), matching ADK Web and keeping session files consistent
Close#3558
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 834847209
Merge https://github.com/google/adk-python/pull/3603
**Please ensure you have read the [contribution guide](https://github.com/google/adk-python/blob/main/CONTRIBUTING.md) before creating a pull request.**
### Link to Issue or Description of Change
**1. Link to an existing issue (if applicable):**
- Closes: #_issue_number_
- Related: #_issue_number_
**2. Or, if no issue exists, describe the change:**
_If applicable, please follow the issue templates to provide as much detail as
possible._
**Problem:**
_A clear and concise description of what the problem is._
**Solution:**
_A clear and concise description of what you want to happen and why you choose
this solution._
### Testing Plan
_Please describe the tests that you ran to verify your changes. This is required
for all PRs that are not small documentation or typo fixes._
**Unit Tests:**
- [ ] I have added or updated unit tests for my change.
- [ ] All unit tests pass locally.
_Please include a summary of passed `pytest` results._
**Manual End-to-End (E2E) Tests:**
_Please provide instructions on how to manually test your changes, including any
necessary setup or configuration. Please provide logs or screenshots to help
reviewers better understand the fix._
### Checklist
- [ ] I have read the [CONTRIBUTING.md](https://github.com/google/adk-python/blob/main/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.
### Additional context
_Add any other context or screenshots about the feature request here._
Co-authored-by: Hangfei Lin <hangfei@google.com>
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/3603 from holtskinner:patch-1 833405898b747438e3f8a1b8c34095e25135fca3
PiperOrigin-RevId: 834805195
Retrying only on closed_resource error is not enough to be reliable for production environments due to the other network errors that may occur -- remote protocol error, read timeout, etc. We will update this to retry on all errors. Since it is only a one-time retry, it should not affect latency significantly. Fixes https://github.com/google/adk-python/issues/2561.
Co-authored-by: Kathy Wu <wukathy@google.com>
PiperOrigin-RevId: 834514264
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
2025-11-19 16:26:55 -08:00
169 changed files with 7818 additions and 1756 deletions
* Add enum constraint to `agent_name` for `transfer_to_agent` ([4a42d0d](https://github.com/google/adk-python/commit/4a42d0d9d81b7aab98371427f70a7707dbfb8bc4))
* Add validation for unique sub-agent names ([#3557](https://github.com/google/adk-python/issues/3557)) ([2247a45](https://github.com/google/adk-python/commit/2247a45922afdf0a733239b619f45601d9b325ec))
* Support streaming function call arguments in progressive SSE streaming feature ([786aaed](https://github.com/google/adk-python/commit/786aaed335e1ce64b7e92dff2f4af8316b2ef593))
* **[Models]**
* Enable multi-provider support for Claude and LiteLLM ([d29261a](https://github.com/google/adk-python/commit/d29261a3dc9c5a603feef27ea657c4a03bb8a089))
* **[Tools]**
* Create APIRegistryToolset to add tools from Cloud API registry to agent ([ec4ccd7](https://github.com/google/adk-python/commit/ec4ccd718feeadeb6b2b59fcc0e9ff29a4fd0bac))
* Add an option to disallow propagating runner plugins to AgentTool runner ([777dba3](https://github.com/google/adk-python/commit/777dba3033a9a14667fb009ba017f648177be41d))
* **[Web]**
* Added an endpoint to list apps with details ([b57fe5f](https://github.com/google/adk-python/commit/b57fe5f4598925ec7592917bb32c7f0d6eca287a))
### Bug Fixes
* Allow image parts in user messages for Anthropic Claude ([5453b5b](https://github.com/google/adk-python/commit/5453b5bfdedc91d9d668c9eac39e3bb009a7bbbf))
* Mark the Content as non-empty if its first part contains text or inline_data or file_data or func call/response ([631b583](https://github.com/google/adk-python/commit/631b58336d36bfd93e190582be34069613d38559))
* Fixes double response processing issue in `base_llm_flow.py` where, in Bidi-streaming (live) mode, the multi-agent structure causes duplicated responses after tool calling. ([cf21ca3](https://github.com/google/adk-python/commit/cf21ca358478919207049695ba6b31dc6e0b2673))
* Fix out of bounds error in _run_async_impl ([8fc6128](https://github.com/google/adk-python/commit/8fc6128b62ba576480d196d4a2597564fd0a7006))
* Fix paths for public docs ([cd54f48](https://github.com/google/adk-python/commit/cd54f48fed0c87b54fb19743c9c75e790c5d9135))
* Ensure request bodies without explicit names are named 'body' ([084c2de](https://github.com/google/adk-python/commit/084c2de0dac84697906e2b4beebf008bbd9ae8e1)), closes [#2213](https://github.com/google/adk-python/issues/2213)
* Optimize Stale Agent with GraphQL and Search API to resolve 429 Quota errors ([cb19d07](https://github.com/google/adk-python/commit/cb19d0714c90cd578551753680f39d8d6076c79b))
* Update AgentTool to use Agent's description when input_schema is provided in FunctionDeclaration ([52674e7](https://github.com/google/adk-python/commit/52674e7fac6b7689f0e3871d41c4523e13471a7e))
* Update LiteLLM system instruction role from "developer" to "system" ([2e1f730](https://github.com/google/adk-python/commit/2e1f730c3bc0eb454b76d7f36b7b9f1da7304cfe)), closes [#3657](https://github.com/google/adk-python/issues/3657)
* Update session last update time when appending events ([a3e4ad3](https://github.com/google/adk-python/commit/a3e4ad3cd130714affcaa880f696aeb498cd93af)), closes [#2721](https://github.com/google/adk-python/issues/2721)
* Update the retry_on_closed_resource decorator to retry on all errors ([a3aa077](https://github.com/google/adk-python/commit/a3aa07722a7de3e08807e86fd10f28938f0b267d))
* Windows Path Handling and Normalize Cross-Platform Path Resolution in AgentLoader ([a1c09b7](https://github.com/google/adk-python/commit/a1c09b724bb37513eaabaff9643eeaa68014f14d))
### Documentation
* Add Code Wiki badge to README ([caf23ac](https://github.com/google/adk-python/commit/caf23ac49fe08bc7f625c61eed4635c26852c3ba))
* Add `id` and `custom_metadata` fields to `MemoryEntry` ([4dd28a3](https://github.com/google/adk-python/commit/4dd28a3970d0f76c571caf80b3e1bea1b79e9dde))
* Add a2a_request_meta_provider to RemoteAgent init ([d12468e](https://github.com/google/adk-python/commit/d12468ee5a2b906b6699ccdb94c6a5a4c2822465))
* Add feature decorator for the feature registry system ([871da73](https://github.com/google/adk-python/commit/871da731f1c09c6a62d51b137d9d2e7c9fb3897a))
* Breaking: Raise minimum Python version to 3_10 ([8402832](https://github.com/google/adk-python/commit/840283228ee77fb3dbd737cfe7eb8736d9be5ec8))
* Refactor and rename BigQuery agent analytics plugin ([6b14f88](https://github.com/google/adk-python/commit/6b14f887262722ccb85dcd6cef9c0e9b103cfa6e))
* Pass custom_metadata through forwarding artifact service ([c642f13](https://github.com/google/adk-python/commit/c642f13f216fb64bc93ac46c1c57702c8a2add8c))
* Update save_files_as_artifacts_plugin to never keep inline data ([857de04](https://github.com/google/adk-python/commit/857de04debdeba421075c2283c9bd8518d586624))
* **[Evals]**
* Add support for InOrder and AnyOrder match in ToolTrajectoryAvgScore Metric ([e2d3b2d](https://github.com/google/adk-python/commit/e2d3b2d862f7fc93807d16089307d4df25367a24))
* **[Integrations]**
* Enhance BQ Plugin Schema, Error Handling, and Logging ([5ac5129](https://github.com/google/adk-python/commit/5ac5129fb01913516d6f5348a825ca83d024d33a))
* Schema Enhancements with Descriptions, Partitioning, and Truncation Indicator ([7c993b0](https://github.com/google/adk-python/commit/7c993b01d1b9d582b4e2348f73c0591d47bf2f3a))
* **[Services]**
* Add file-backed artifact service ([99ca6aa](https://github.com/google/adk-python/commit/99ca6aa6e6b4027f37d091d9c93da6486def20d7))
* Add service factory for configurable session and artifact backends ([a12ae81](https://github.com/google/adk-python/commit/a12ae812d367d2d00ab246f85a73ed679dd3828a))
* Add SqliteSessionService and a migration script to migrate existing DB using DatabaseSessionService to SqliteSessionService ([e218254](https://github.com/google/adk-python/commit/e2182544952c0174d1a8307fbba319456dca748b))
* Add transcription fields to session events ([3ad30a5](https://github.com/google/adk-python/commit/3ad30a58f95b8729f369d00db799546069d7b23a))
* Full async implementation of DatabaseSessionService ([7495941](https://github.com/google/adk-python/commit/74959414d8ded733d584875a49fb4638a12d3ce5))
* **[Models]**
* Add experimental feature to use `parameters_json_schema` and `response_json_schema` for McpTool ([1dd97f5](https://github.com/google/adk-python/commit/1dd97f5b45226c25e4c51455c78ebf3ff56ab46a))
* Add support for parsing inline JSON tool calls in LiteLLM responses ([22eb7e5](https://github.com/google/adk-python/commit/22eb7e5b06c9e048da5bb34fe7ae9135d00acb4e))
* Expose artifact URLs to the model when available ([e3caf79](https://github.com/google/adk-python/commit/e3caf791395ce3cc0b10410a852be6e7b0d8d3b1))
* **[Tools]**
* Add BigQuery related label handling ([ffbab4c](https://github.com/google/adk-python/commit/ffbab4cf4ed6ceb313241c345751214d3c0e11ce))
* Allow setting max_billed_bytes in BigQuery tools config ([ffbb0b3](https://github.com/google/adk-python/commit/ffbb0b37e128de50ebf57d76cba8b743a8b970d5))
* Propagate `application_name` set for the BigQuery Tools as BigQuery job labels ([f13a11e](https://github.com/google/adk-python/commit/f13a11e1dc27c5aa46345154fbe0eecfe1690cbb))
* Set per-tool user agent in BQ calls and tool label in BQ jobs ([c0be1df](https://github.com/google/adk-python/commit/c0be1df0521cfd4b84585f404d4385b80d08ba59))
* **[Observability]**
* Migrate BigQuery logging to Storage Write API ([a2ce34a](https://github.com/google/adk-python/commit/a2ce34a0b9a8403f830ff637d0e2094e82dee8e7))
### Bug Fixes
* Add `jsonschema` dependency for Agent Builder config validation ([0fa7e46](https://github.com/google/adk-python/commit/0fa7e4619d589dc834f7508a18bc2a3b93ec7fd9))
* Add None check for `event` in `remote_a2a_agent.py` ([744f94f](https://github.com/google/adk-python/commit/744f94f0c8736087724205bbbad501640b365270))
* Add vertexai initialization for code being deployed to AgentEngine ([b8e4aed](https://github.com/google/adk-python/commit/b8e4aedfbf0eb55b34599ee24e163b41072a699c))
* Change LiteLLM content and tool parameter handling ([a19be12](https://github.com/google/adk-python/commit/a19be12c1f04bb62a8387da686499857c24b45c0))
* Change name for builder agent ([131d39c](https://github.com/google/adk-python/commit/131d39c3db1ae25e3911fa7f72afbe05e24a1c37))
* Ensure event compaction completes by awaiting task ([b5f5df9](https://github.com/google/adk-python/commit/b5f5df9fa8f616b855c186fcef45bade00653c77))
* Fix deploy to cloud run on Windows ([29fea7e](https://github.com/google/adk-python/commit/29fea7ec1fb27989f07c90494b2d6acbe76c03d8))
* Fix error handling when MCP server is unreachable ([ee8106b](https://github.com/google/adk-python/commit/ee8106be77f253e3687e72ae0e236687d254965c))
* Fix error when query job destination is None ([0ccc43c](https://github.com/google/adk-python/commit/0ccc43cf49dc0882dc896455d6603a602d8a28e7))
* Fix Improve logic for checking if a MCP session is disconnected ([a754c96](https://github.com/google/adk-python/commit/a754c96d3c4fd00f9c2cd924fc428b68cc5115fb))
* Fix McpToolset crashing with anyio.BrokenResourceError ([8e0648d](https://github.com/google/adk-python/commit/8e0648df23d0694afd3e245ec4a3c41aa935120a))
* Fix Safely handle `FunctionDeclaration` without a `required` attribute ([93aad61](https://github.com/google/adk-python/commit/93aad611983dc1daf415d3a73105db45bbdd1988))
* Fix status code in error message in RestApiTool ([9b75456](https://github.com/google/adk-python/commit/9b754564b3cc5a06ad0c6ae2cd2d83082f9f5943))
* Fix Use `async for` to loop through event iterator to get all events in vertex_ai_session_service ([9211f4c](https://github.com/google/adk-python/commit/9211f4ce8cc6d918df314d6a2ff13da2e0ef35fa))
* Fix: Fixes DeprecationWarning when using send method ([2882995](https://github.com/google/adk-python/commit/28829952890c39dbdb4463b2b67ff241d0e9ef6d))
* Improve logic for checking if a MCP session is disconnected ([a48a1a9](https://github.com/google/adk-python/commit/a48a1a9e889d4126e6f30b56c93718dfbacef624))
* Improve handling of partial and complete transcriptions in live calls ([1819ecb](https://github.com/google/adk-python/commit/1819ecb4b8c009d02581c2d060fae49cd7fdf653))
* Keep vertex session event after the session update time ([0ec0195](https://github.com/google/adk-python/commit/0ec01956e86df6ae8e6553c70e410f1f8238ba88))
* Let part converters also return multiple parts so they can support more usecases ([824ab07](https://github.com/google/adk-python/commit/824ab072124e037cc373c493f43de38f8b61b534))
* Load agent/app before creating session ([236f562](https://github.com/google/adk-python/commit/236f562cd275f84837be46f7dfb0065f85425169))
* Remove app name from FileArtifactService directory structure ([12db84f](https://github.com/google/adk-python/commit/12db84f5cd6d8b6e06142f6f6411f6b78ff3f177))
* Remove hardcoded `google-cloud-aiplatform` version in agent engine requirements ([e15e19d](https://github.com/google/adk-python/commit/e15e19da05ee1b763228467e83f6f73e0eced4b5))
* Stop updating write mode in the global settings during tool execution ([5adbf95](https://github.com/google/adk-python/commit/5adbf95a0ab0657dd7df5c4a6bac109d424d436e))
* Update description for `load_artifacts` tool ([c485889](https://github.com/google/adk-python/commit/c4858896ff085bedcfbc42b2010af8bd78febdd0))
### Improvements
* Add BigQuery related label handling ([ffbab4c](https://github.com/google/adk-python/commit/ffbab4cf4ed6ceb313241c345751214d3c0e11ce))
* Add demo for rewind ([8eb1bdb](https://github.com/google/adk-python/commit/8eb1bdbc58dc709006988f5b6eec5fda25bd0c89))
* Add debug logging for live connection ([5d5708b](https://github.com/google/adk-python/commit/5d5708b2ab26cb714556311c490b4d6f0a1f9666))
* Add debug logging for missing function call events ([f3d6fcf](https://github.com/google/adk-python/commit/f3d6fcf44411d07169c14ae12189543f44f96c27))
* Add default retry options as fall back to llm_request that are made during evals ([696852a](https://github.com/google/adk-python/commit/696852a28095a024cbe76413ee7617356e19a9e3))
* Add plugin for returning GenAI Parts from tools into the model request ([116b26c](https://github.com/google/adk-python/commit/116b26c33e166bf1a22964e2b67013907fbfcb80))
* Add support for abstract types in AFC ([2efc184](https://github.com/google/adk-python/commit/2efc184a46173529bdfc622db0d6f3866e7ee778))
* Add support for structured output schemas in LiteLLM models ([7ea4aed](https://github.com/google/adk-python/commit/7ea4aed35ba70ec5a38dc1b3b0a9808183c2bab1))
* Add tests for `max_query_result_rows` in BigQuery tool config ([fd33610](https://github.com/google/adk-python/commit/fd33610e967ad814bc02422f5d14dae046bee833))
* Add type hints in `cleanup_unused_files.py` ([2dea573](https://github.com/google/adk-python/commit/2dea5733b759a7a07d74f36a4d6da7b081afc732))
* Add util to build our llms.txt and llms-full.txt files
* Defer import of `google.cloud.storage` in `GCSArtifactService` ([999af55](https://github.com/google/adk-python/commit/999af5588005e7b29451bdbf9252265187ca992d))
* Defer import of `live`, `Client` and `_transformers` in `google.genai` ([22c6dbe](https://github.com/google/adk-python/commit/22c6dbe83cd1a8900d0ac6fd23d2092f095189fa))
* Enhance the messaging with possible fixes for RESOURCE_EXHAUSTED errors from Gemini ([b2c45f8](https://github.com/google/adk-python/commit/b2c45f8d910eb7bca4805c567279e65aff72b58a))
* Improve gepa tau-bench colab for external use ([e02f177](https://github.com/google/adk-python/commit/e02f177790d9772dd253c9102b80df1a9418aa7f))
* Lazy import DatabaseSessionService in the adk/sessions/ module ([5f05749](https://github.com/google/adk-python/commit/5f057498a274d3b3db0be0866f04d5225334f54a))
* Move adk_agent_builder_assistant to built_in_agents ([b2b7f2d](https://github.com/google/adk-python/commit/b2b7f2d6aa5b919a00a92abaf2543993746e939e))
* Plumb memory service from LocalEvalService to EvaluationGenerator ([dc3f60c](https://github.com/google/adk-python/commit/dc3f60cc939335da49399a69c0b4abc0e7f25ea4))
* Removes the unrealistic todo comment of visibility management ([e511eb1](https://github.com/google/adk-python/commit/e511eb1f70f2a3fccc9464ddaf54d0165db22feb))
* Returns agent state regardless if ctx.is_resumable ([d6b928b](https://github.com/google/adk-python/commit/d6b928bdf7cdbf8f1925d4c5227c7d580093348e))
* Stop logging the full content of LLM blobs ([0826755](https://github.com/google/adk-python/commit/082675546f501a70f4bc8969b9431a2e4808bd13))
* Update ADK web to match main branch ([14e3802](https://github.com/google/adk-python/commit/14e3802643a2d8ce436d030734fafd163080a1ad))
* Update agent instructions and retry limit in `plugin_reflect_tool_retry` sample ([01bac62](https://github.com/google/adk-python/commit/01bac62f0c14cce5d454a389b64a9f44a03a3673))
* Update conformance test CLI to handle long-running tool calls ([dd706bd](https://github.com/google/adk-python/commit/dd706bdc4563a2a815459482237190a63994cb6f))
* Update Gemini Live model names in live bidi streaming sample ([aa77834](https://github.com/google/adk-python/commit/aa77834e2ecd4b77dfb4e689ef37549b3ebd6134))
[](https://github.com/google/adk-python/actions/workflows/python-unit-tests.yml)
This directory contains an autonomous, **GraphQL-powered** agent designed to audit a GitHub repository for stale issues. It maintains repository hygiene by ensuring all open items are actionable and responsive.
Unlike traditional "Stale Bots" that only look at timestamps, this agent uses a **Unified History Trace** and an **LLM (Large Language Model)** to understand the *context* of a conversation. It distinguishes between a maintainer asking a question (stale candidate) vs. a maintainer providing a status update (active).
---
## Core Logic & Features
The agent operates as a "Repository Auditor," proactively scanning open issues using a high-efficiency decision tree.
### 1. Smart State Verification (GraphQL)
Instead of making multiple expensive API calls, the agent uses a single **GraphQL** query per issue to reconstruct the entire history of the conversation. It combines:
***Comments**
***Description/Body Edits** ("Ghost Edits")
***Title Renames**
***State Changes** (Reopens)
It sorts these events chronologically to determine the **Last Active Actor**.
### 2. The "Last Actor" Rule
The agent follows a precise logic flow based on who acted last:
***If Author/User acted last:** The issue is **ACTIVE**.
* This includes comments, title changes, and *silent* description edits.
***Action:** The agent immediately removes the `stale` label.
***Silent Update Alert:** If the user edited the description but *did not* comment, the agent posts a specific alert: *"Notification: The author has updated the issue description..."* to ensure maintainers are notified (since GitHub does not trigger notifications for body edits).
***Spam Prevention:** The agent checks if it has already alerted about a specific silent edit to avoid spamming the thread.
***If Maintainer acted last:** The issue is **POTENTIALLY STALE**.
* The agent passes the text of the maintainer's last comment to the LLM.
### 3. Semantic Intent Analysis (LLM)
If the maintainer was the last person to speak, the LLM analyzes the comment text to determine intent:
***Question/Request:** "Can you provide logs?" / "Please try v2.0."
***Verdict:****STALE** (Waiting on Author).
***Action:** If the time threshold is met, the agent adds the `stale` label. It also checks for the `request clarification` label and adds it if missing.
***Status Update:** "We are working on a fix." / "Added to backlog."
***Verdict:****ACTIVE** (Waiting on Maintainer).
***Action:** No action taken. The issue remains open without stale labels.
### 4. Lifecycle Management
***Marking Stale:** After `STALE_HOURS_THRESHOLD` (default: 7 days) of inactivity following a maintainer's question.
***Closing:** After `CLOSE_HOURS_AFTER_STALE_THRESHOLD` (default: 7 days) of continued inactivity while marked stale.
---
## Performance & Safety
***GraphQL Optimized:** Fetches comments, edits, labels, and timeline events in a single network request to minimize latency and API quota usage.
***Search API Filtering:** Uses the GitHub Search API to pre-filter issues created recently, ensuring the bot doesn't waste cycles analyzing brand-new issues.
***Rate Limit Aware:** Includes intelligent sleeping and retry logic (exponential backoff) to handle GitHub API rate limits (HTTP 429) gracefully.
***Execution Metrics:** Logs the time taken and API calls consumed for every issue processed.
---
## Configuration
The agent is configured via environment variables, typically set as secrets in GitHub Actions.
### Required Secrets
| Secret Name | Description |
| :--- | :--- |
| `GITHUB_TOKEN` | A GitHub Personal Access Token (PAT) or Service Account Token with `repo` scope. |
| `GOOGLE_API_KEY` | An API key for the Google AI (Gemini) model used for reasoning. |
### Optional Configuration
These variables control the timing thresholds and model selection.
| Variable Name | Description | Default |
| :--- | :--- | :--- |
| `STALE_HOURS_THRESHOLD` | Hours of inactivity after a maintainer's question before marking as `stale`. | `168` (7 days) |
| `CLOSE_HOURS_AFTER_STALE_THRESHOLD` | Hours after being marked `stale` before the issue is closed. | `168` (7 days) |
| `LLM_MODEL_NAME`| The specific Gemini model version to use. | `gemini-2.5-flash` |
f"Searching for issues in '{owner}/{repo}' created before {cutoff_str}..."
)
issue_numbers=[]
page=1
url="https://api.github.com/search/issues"
whileTrue:
params={"q":query,"per_page":100,"page":page}
try:
data=get_request(url,params=params)
items=data.get("items",[])
ifnotitems:
break
foriteminitems:
if"pull_request"notinitem:
issue_numbers.append(item["number"])
iflen(items)<100:
break
page+=1
exceptrequests.exceptions.RequestExceptionase:
logger.error(f"GitHub search failed on page {page}: {e}")
break
logger.info(f"Found {len(issue_numbers)} stale issues.")
returnissue_numbers
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.