Commit Graph

315 Commits

Author SHA1 Message Date
Rohit Yanamadala cb19d0714c fix: Optimize Stale Agent with GraphQL and Search API to resolve 429 Quota errors
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
2025-12-01 12:25:51 -08:00
Xuan Yang 786aaed335 feat: Support streaming function call arguments in progressive SSE streaming feature
Co-authored-by: Xuan Yang <xygoogle@google.com>
PiperOrigin-RevId: 837172244
2025-11-26 10:15:31 -08:00
Kathy Wu ec4ccd718f feat: Create APIRegistryToolset to add tools from Cloud API registry to agent
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
2025-11-26 10:01:58 -08:00
Xuan Yang b331d97dfb docs: Remove the list_unlabeled_issues tool from the issue triaging agent
Co-authored-by: Xuan Yang <xygoogle@google.com>
PiperOrigin-RevId: 836416597
2025-11-24 17:14:51 -08:00
Rohit Yanamadala 23f1d8914a docs(agent): Implement stale issue bot
Merge https://github.com/google/adk-python/pull/3546

Co-authored-by: Xuan Yang <xygoogle@google.com>
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/3546 from ryanaiagent:feat/stale-issue-agent bcf45098c1c6406b4a42228e4a8ef02f12840425
PiperOrigin-RevId: 835327931
2025-11-21 12:54:20 -08:00
Issac cd54f48fed fix: fix paths for public docs
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
2025-11-20 12:26:43 -08:00
Xuan Yang 679d543f8e docs: Update ADK triaging agent to only triage planned issues
It also enables the ADK triaging agent to run periodically on planned but not triaged issues.

Co-authored-by: Xuan Yang <xygoogle@google.com>
PiperOrigin-RevId: 834489103
2025-11-19 16:26:55 -08:00
Shangjie Chen ffbab4cf4e chore: Add BigQuery related label handling
Co-authored-by: Shangjie Chen <deanchen@google.com>
PiperOrigin-RevId: 834375503
2025-11-19 11:29:40 -08:00
George Weale b2b7f2d6aa chore: Move adk_agent_builder_assistant to built_in_agents
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 834371390
2025-11-19 11:18:37 -08:00
George Weale 0ac35b23dc docs: Add path sanitization for model-generated file paths
Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 834344352
2025-11-19 10:13:16 -08:00
Shangjie Chen 8eb1bdbc58 chore: Add demo for rewind
Co-authored-by: Shangjie Chen <deanchen@google.com>
PiperOrigin-RevId: 833871446
2025-11-18 10:26:15 -08:00
George Weale 2dea5733b7 fix: add type hints in cleanup_unused_files.py
Updates type annotations to use built-in types like `list` and `dict`, and uses `| None` for optional types, along with adding `from __future__ import annotations`

Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 832522395
2025-11-14 17:58:37 -08:00
George Weale 22eb7e5b06 feat: Add support for parsing inline JSON tool calls in LiteLLM responses
Close #1968

Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 831911719
2025-11-13 10:18:27 -08:00
Hangfei Lin 0ab79b9502 fix: Deprecate save_live_audio in favor of save_live_blob and fix audio event saving
This change:
*   Deprecates the `save_live_audio` configuration option in `RunConfig`, introducing `save_live_blob` as its replacement. A warning is issued if `save_live_audio` is used.
*   Updates `base_llm_flow.py` to use the new `save_live_blob` flag.
*   Ensures that audio events generated by `audio_cache_manager.py` are properly appended to the session service.
*   Adds a utility script `pcm_audio_player.py` for playing raw PCM audio files.

Input sample event: 14a5859f-6b6c-46ed-9f28-e5008793b1c6|live_bidi_streaming_multi_agent|user|1e867c7f-dbe1-4268-a7bc-7a9fa5fbd16c|e-7a28a060-29bf-4483-bc5c-17248698a897|1762916981.5932|{"content":{"parts":[{"file_data":{"file_uri":"artifact://live_bidi_streaming_multi_agent/user/1e867c7f-dbe1-4268-a7bc-7a9fa5fbd16c/_adk_live/adk_live_audio_storage_input_audio_1762916981593.pcm#0","mime_type":"audio/pcm"}}],"role":"user"},"invocation_id":"e-7a28a060-29bf-4483-bc5c-17248698a897","author":"user","actions":{"state_delta":{},"artifact_delta":{},"requested_auth_configs":{},"requested_tool_confirmations":{}},"id":"14a5859f-6b6c-46ed-9f28-e5008793b1c6","timestamp":1762916981.5932002}

output sample event:
506c9df4-e143-4ebc-90a5-2f5b2eb26754|live_bidi_streaming_multi_agent|user|1e867c7f-dbe1-4268-a7bc-7a9fa5fbd16c|e-7a28a060-29bf-4483-bc5c-17248698a897|1762916986.10579|{"content":{"parts":[{"file_data":{"file_uri":"artifact://live_bidi_streaming_multi_agent/user/1e867c7f-dbe1-4268-a7bc-7a9fa5fbd16c/_adk_live/adk_live_audio_storage_output_audio_1762916986105.pcm;rate=24000#0","mime_type":"audio/pcm;rate=24000"}}],"role":"model"},"invocation_id":"e-7a28a060-29bf-4483-bc5c-17248698a897","author":"model","actions":{"state_delta":{},"artifact_delta":{},"requested_auth_configs":{},"requested_tool_confirmations":{}},"id":"506c9df4-e143-4ebc-90a5-2f5b2eb26754","timestamp":1762916986.105794}

Co-authored-by: Hangfei Lin <hangfei@google.com>
PiperOrigin-RevId: 831512074
2025-11-12 13:16:13 -08:00
Shangjie Chen a501c59ac4 feat: Support registering custom services from local files
This change introduces a mechanism for users to register their own custom backend services for sessions, memory, and artifacts without modifying the ADK framework. This enhances the extensibility of ADK.

Two methods of registration are supported, both by placing a file in the parent directory of the agents.

**YAML Configuration (services.yaml or .yml)**

This is the recommended approach for simple services that can be instantiated with a constructor like MyService(uri="...", **kwargs).

Example services.yaml:

```
services:
  - scheme: mysession
    type: session
    class: my_package.my_module.MyCustomSessionService
```

**Python Registration (services.py)**

For services requiring more complex initialization logic, users can define factory functions in a services.py file.

Example services.py

```
from google.adk.cli.service_registry import get_service_registry
from my_package.my_module import MyCustomSessionService

def my_session_factory(uri: str, **kwargs):
    # custom initialization logic
    return MyCustomSessionService(...)

get_service_registry().register_session_service("mysession", my_session_factory)
```

ADK will load services from services.yaml/.yml first, and then from services.py. If the same service scheme is defined in both, the registration in services.py will take precedence.

To use a registered service, specify its URI via the corresponding command-line flag, e.g., `--session_service_uri=mysession://....`

Co-authored-by: Shangjie Chen <deanchen@google.com>
PiperOrigin-RevId: 831211371
2025-11-11 21:59:19 -08:00
Hangfei Lin 01bac62f0c chore: Update agent instructions and retry limit in plugin_reflect_tool_retry sample
The agent's instructions are updated to guide it to guess a positive integer, starting from 50 and decreasing, using the `guess_number_tool` until the target is found. The maximum number of retries for the `CustomRetryPlugin` is increased from 6 to 10.

Co-authored-by: Hangfei Lin <hangfei@google.com>
PiperOrigin-RevId: 830984481
2025-11-11 10:52:44 -08:00
Hangfei Lin 2b0f953255 feat: Add artifact metadata support and a new sample for context offloading
Enhanced `save_artifact` in `callback_context.py` to accept `custom_metadata` and added `get_artifact_version` to retrieve artifact details.

Introduced a new sample, `context_offloading_with_artifact`, demonstrating how to use ADK artifacts to offload large data from the LLM context. The sample includes:
-   `QueryLargeDataTool`: Generates mock sales reports, saves them as artifacts with custom metadata, and injects the artifact content into the LLM request immediately after creation.
-   `CustomLoadArtifactsTool`: Provides summaries of available artifacts to the LLM based on metadata and loads artifact content on demand when `load_artifacts` is called.

Co-authored-by: Hangfei Lin <hangfei@google.com>
PiperOrigin-RevId: 830592786
2025-11-10 14:10:10 -08:00
Max Ind 116b26c33e feat: add plugin for returning GenAI Parts from tools into the model request
Added to mitigate https://github.com/google/adk-python/issues/3064

Co-authored-by: Max Ind <maxind@google.com>
PiperOrigin-RevId: 830135940
2025-11-09 11:47:08 -08:00
Lê Nam Khánh 51dee43f08 docs: fix typos in some files
Merge https://github.com/google/adk-python/pull/3444

This PR fixes typos in the file file using codespell.

COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/3444 from khanhkhanhlele:Fix/typos/20251107165249 e9629a8c0255ddc0764cb0df7f36ebe61bd6515e
PiperOrigin-RevId: 829516217
2025-11-07 11:32:32 -08:00
George Weale e0e762598e docs: Use a trimmed ADK AgentConfig schema in Agent Builder Assistant
This trimmed schema includes only the fields relevant to agent shells, tool wiring, and common generation parameters, improving efficiency and focus.

The default model for the assistant has also been updated to "gemini-2.5-pro"

Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 829513627
2025-11-07 11:26:18 -08:00
Google Team Member a0cf97eba2 feat: Some small infra fixes to the gepa demo colab
PiperOrigin-RevId: 829240716
2025-11-06 20:44:25 -08:00
Google Team Member d118479ccf feat: Improve gepa voter agent demo colab
PiperOrigin-RevId: 829208761
2025-11-06 19:13:11 -08:00
Google Team Member f1f44675e4 ADK changes
PiperOrigin-RevId: 829136628
2025-11-06 15:55:26 -08:00
George Weale 7ea4aed35b fix: Add support for structured output schemas in LiteLLM models
Add `_to_litellm_response_format` to convert ADK's `response_schema` types (Pydantic models, JSON schema dicts) into the format needed by LiteLLM for JSON object/schema constraints

Close #1967

Co-authored-by: George Weale <gweale@google.com>
PiperOrigin-RevId: 829037987
2025-11-06 11:29:10 -08:00
Google Team Member f167890d00 feat: Add documentation and instructions to help configure gepa experiments
PiperOrigin-RevId: 828911323
2025-11-06 05:31:24 -08:00