Compare commits

..

185 Commits

Author SHA1 Message Date
Xuan Yang b8644ef32c Make additional_headers kwargs 2025-10-21 12:44:50 -07:00
Xuan Yang ace3e5a3a5 Merge branch 'main' into feature/google-api-toolset-additional-headers-3105 2025-10-20 09:58:15 -07:00
Xuan Yang 37179a6e1f Format conditional statement for setting headers 2025-10-20 09:36:25 -07:00
Parham Alizadeh d8ded07eb3 addressing comments - tidy ups 2025-10-20 10:18:27 +01:00
Shangjie Chen d327538724 chore: Throw 409 already exist error when trying to create a session with existing id
Resolves https://github.com/google/adk-python/issues/2950

PiperOrigin-RevId: 821362008
2025-10-19 11:21:36 -07:00
Google Team Member a5b742b360 feat: introduces a new AgentEngineSandboxCodeExecutor class that supports executes agent generated code
The AgentEngineSandboxCodeExecutor uses the Vertex AI Code Execution Sandbox API to execute code

PiperOrigin-RevId: 821197794
2025-10-18 20:24:04 -07:00
Parham MohammadAlizadeh a09dd4d31f Merge branch 'main' into feature/google-api-toolset-additional-headers-3105 2025-10-18 12:09:45 +01:00
Wei Sun (Jack) af74eba695 test: Skips test_langchain_tool.py temporarily after their new 1.0.0 release breaks existings deps of langchain
PiperOrigin-RevId: 820875043
2025-10-17 16:53:11 -07:00
Google Team Member dbd818be0b feat: introduces a new AgentEngineSandboxCodeExecutor class that supports executes agent generated code
The AgentEngineSandboxCodeExecutor uses the Vertex AI Code Execution Sandbox API to execute code

PiperOrigin-RevId: 820854185
2025-10-17 15:42:24 -07:00
Xiang (Sean) Zhou a2d9f13fa1 chore: Add span for context caching handling and new cache creation
PiperOrigin-RevId: 820852233
2025-10-17 15:37:35 -07:00
Wei Sun (Jack) 0df67599c0 chore: Checks gemini version for 2 and above for gemini-builtin tools
PiperOrigin-RevId: 820848897
2025-10-17 15:27:47 -07:00
Shangjie Chen 8b3ed059c2 chore: Refactor and fix state management in the session service
Also refactoring the test cases to focus on the expected behaviors

PiperOrigin-RevId: 820734484
2025-10-17 10:04:36 -07:00
Parham MohammadAlizadeh 71999b0ef7 Merge branch 'main' into feature/google-api-toolset-additional-headers-3105 2025-10-17 16:37:23 +01:00
Ankur Sharma cf3403231d chore: Fix evaluation test cases to only use pytest features
PiperOrigin-RevId: 820700378
2025-10-17 08:25:17 -07:00
Parham MohammadAlizadeh 3d6d6132cd Merge branch 'main' into feature/google-api-toolset-additional-headers-3105 2025-10-17 16:23:25 +01:00
Parham Alizadeh 78e4d81579 feat(tools): support additional headers for google api toolset #non-breaking 2025-10-17 16:22:55 +01:00
Shangjie Chen 9dce06f9b0 feat: Add rewind_async to support rewinding the session to before a previous invocation
PiperOrigin-RevId: 820552460
2025-10-16 23:24:40 -07:00
George Weale 307896aece fix: Exclude additionalProperties from Gemini schemas
PiperOrigin-RevId: 820542466
2025-10-16 22:40:43 -07:00
Kathy Wu 6dcbb5aca6 feat: Support dynamic per-request headers in MCPToolset
Add a header_provider param which is a callable[ReadonlyContext, Dict[str, Any]] for users to build headers in MCPToolset
fix: https://github.com/google/adk-python/issues/3156
PiperOrigin-RevId: 820412372
2025-10-16 15:12:43 -07:00
Xiang (Sean) Zhou 2a8fdd94e1 chore: Add computer use sample agent
PiperOrigin-RevId: 820407078
2025-10-16 14:59:27 -07:00
Xuan Yang 37a153ef94 ci: Fix the logs importing for PR triaging agent
PiperOrigin-RevId: 820395414
2025-10-16 14:27:18 -07:00
Giovanni Galloro ce4638651f docs: Bump models in llms and llms-full to Gemini 2.5
Merge https://github.com/google/adk-python/pull/3166

COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/3166 from ggalloro:model-updates e741c8b266ef8cd7def203f94e8d9f8608c06685
PiperOrigin-RevId: 820381464
2025-10-16 13:53:45 -07:00
Doug Gebert e6e2767c39 chore: Update gemini_llm_connection.py - typo spelling correction
Merge https://github.com/google/adk-python/pull/3168

Fixed misspelling on line 228 from:
- logger.info('Redeived session...

To:
- logger.info('Received session...
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/3168 from DHHHG:patch-1 90b76d72ba474cd0092b2cc8d955b918c18d05bd
PiperOrigin-RevId: 820369618
2025-10-16 13:23:58 -07:00
Kacper Jawoszek e50f05a9fc feat(otel): env variable for disabling llm_request and llm_response in spans
The default without the variable set is to keep the content in spans to keep backward compatible behavior for existing users.

This allows to enable tracing without potential PII data from request and response. Google GenAI instrumentation lib requires an explicit opt-in to enable request and response content - see https://github.com/open-telemetry/opentelemetry-python-contrib/tree/main/instrumentation-genai/opentelemetry-instrumentation-google-genai#enabling-message-content.

PiperOrigin-RevId: 820351154
2025-10-16 13:07:27 -07:00
Xuan Yang 9dc00360e3 ci: Add state info for PR triaging agent
PiperOrigin-RevId: 820340584
2025-10-16 13:07:18 -07:00
Google Team Member 5a543c00df feat: implement new methods in in-memory artifact service
* save_artifact with custom_metadata
* list_artifact_versions
* get_artifact_version

PiperOrigin-RevId: 820321444
2025-10-16 13:07:09 -07:00
Alexey Guseynov 1e1d63f34c fix: Internal change
PiperOrigin-RevId: 820159440
2025-10-16 13:07:00 -07:00
Xuan Yang f51380f9ea feat: Extend ReflectAndRetryToolPlugin to support hallucinating function calls
PiperOrigin-RevId: 820051762
2025-10-16 13:06:51 -07:00
Xuan Yang 3734ceaa6c fix: Use the agent's model when creating Google search agent tool
PiperOrigin-RevId: 819980797
2025-10-16 13:06:41 -07:00
Google Team Member 86097afe49 feat: Update AgentEvaluator to handle async ADK agent definitions
AgentEvaluator should recognize root_agent and get_agent_async as valid structures for ADK agent definitions.

PiperOrigin-RevId: 819976635
2025-10-16 13:06:31 -07:00
Google Team Member a17f3b2e6d feat: Allow custom request and event converters in A2aAgentExecutor
This change introduces type aliases for request and event conversion functions:
- `A2ARequestToADKRunArgsConverter`: For converting A2A `RequestContext` to an `ADKRunArgs` Pydantic model.
- `AdkEventToA2AEventsConverter`: For converting ADK `Event` to a list of A2A `A2AEvent` objects.

The `convert_a2a_request_to_adk_run_args` function now returns a structured `ADKRunArgs` model instead of a generic dictionary, improving type safety.

These converter types can now be provided via the `A2aAgentExecutorConfig` to customize the conversion logic used by the `A2aAgentExecutor`. The executor defaults to the existing `convert_a2a_request_to_adk_run_args` and `convert_event_to_a2a_events` functions if no custom converters are specified.

This allows users to inject their own logic for handling request and event conversions, for example, to add custom metadata or transform data types, without modifying the core executor.

PiperOrigin-RevId: 819934960
2025-10-16 13:06:21 -07:00
Shangjie Chen 6ab1498aa0 fix: Add usage_metadata and citation_metadata to DatabaseSessionService
PiperOrigin-RevId: 819900773
2025-10-16 13:05:52 -07:00
Google Team Member 2424d6a3b1 feat: Reorder create_time and mime_type to ArtifactVersion
Before: http://sponge2/ba05f9ac-c13d-43b6-bb8a-3e1b029cc705(failed)
After: http://sponge2/a623ba76-62c1-4d17-b4b6-22044333a801
PiperOrigin-RevId: 819896989
2025-10-15 13:46:12 -07:00
Lin Nikaido 36c96ec5b3 fix: #2883 pickle data was truncated error in database session using MySql
Merge https://github.com/google/adk-python/pull/2884

closes: #2883
# Fix
When put leage data into event and load it. the _pickle.UnpicklingError was occurred.
The root caurse is `DynamicPickleType` mapping `BLOB` as default in case of MySql, not `LONGBLOB`. And learge data will be able to cut off tail of data. And raise pickle error.

# What todo
Defined `LONFBLOB` as default explicitly.

# Question
Where should we code the test code like this case? I cannot found the test code the DB and table was created expectedly.

COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/2884 from Lin-Nikaido:fix/#2883-mysql-datatype-fix 2be9b38fc3f5d5083b0b6715a2bf7b4eff5d947b
PiperOrigin-RevId: 819891727
2025-10-15 13:33:22 -07:00
Shangjie Chen a985cc38ec feat: Support return all sessions when user id is none
PiperOrigin-RevId: 819884236
2025-10-15 13:14:24 -07:00
machache b650181384 feat: add support for ContetxtWindowCompressionConfig in RunConfig
Merge https://github.com/google/adk-python/pull/2206

### Summary

This PR adds support for `ContextWindowCompressionConfig` in `RunConfig`.
This enables context window compression using a `trigger_tokens` threshold and a sliding window with a `target_tokens` limit.

This feature is useful for managing long-running audio inputs.

### Related Issue

Closes #2188

### Testing Plan

- Added new unit test: `test_streaming_with_context_window_compression_config`

COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/2206 from ac-machache:support/add-context-compression-config c8a5b15cae2d2b72f331797d07ae0bbaf977ed3c
PiperOrigin-RevId: 819855786
2025-10-15 12:00:21 -07:00
Kathy Wu 78e74b5bf2 feat: Add require_confirmation param for MCP tool/toolset
This allows users to require human approval for using MCP tools.

PiperOrigin-RevId: 819800747
2025-10-15 09:58:31 -07:00
Ankur Sharma d82c492140 chore: Remove deprecated convert_session_to_eval_format function
This change removes the `convert_session_to_eval_format` function and its associated unit tests. New tests for `create_gcs_eval_managers_from_uri` are also added.

PiperOrigin-RevId: 819576620
2025-10-14 22:37:49 -07:00
Xuan Yang 05aa3fa38b fix: Remove the PR triaging agent's dependence on "bot triaged" label
PiperOrigin-RevId: 819427872
2025-10-14 15:35:59 -07:00
Google Team Member f9c09ef075 feat: Support returning all sessions when user_id is none in the request
resolves https://github.com/google/adk-python/issues/3154

PiperOrigin-RevId: 819417330
2025-10-14 15:10:41 -07:00
Shangjie Chen 141318f775 feat: Support returning all sessions when user_id is none in the request
resolves https://github.com/google/adk-python/issues/3154

PiperOrigin-RevId: 819401023
2025-10-14 14:30:47 -07:00
Google Team Member 85c95a8cbf feat: Add create_time and mime_type to ArtifactVersion
PiperOrigin-RevId: 819396924
2025-10-14 14:21:02 -07:00
Hangfei Lin cb6d583cad chore: Add RSVP link to ADK Community Call
This change adds a link to a Qualtrics form for RSVPing to the ADK Community Call in the README.

PiperOrigin-RevId: 819376219
2025-10-14 13:36:33 -07:00
Shangjie Chen 2c7a342593 feat: Add create_time and mime_type to ArtifactVersion
PiperOrigin-RevId: 819372593
2025-10-14 13:29:24 -07:00
Joseph Pagadora 9fbed0b15a fix: Overall eval status should be NOT_EVALUATED if no invocations were evaluated
PiperOrigin-RevId: 819322513
2025-10-14 11:36:33 -07:00
Xuan Yang bae21027d9 chore: Disable the scheduled execution for issue triage workflow
PiperOrigin-RevId: 819312327
2025-10-14 11:15:12 -07:00
George Weale 89344da813 chore: Update agent builder instructions and remove run command details
PiperOrigin-RevId: 819299339
2025-10-14 10:46:53 -07:00
Xiang (Sean) Zhou d22b8bf890 chore: Clarify how to use adk built-in tool in instruction
PiperOrigin-RevId: 818987709
2025-10-13 21:43:37 -07:00
George Weale dfb8638eae chore: fix the cleanup_unused_files tool in yaml agent to use the same directory as other tools
PiperOrigin-RevId: 818846060
2025-10-13 15:01:36 -07:00
George Weale 3c0b99a19e fix: rollback of add structured JSON logging with Cloud Trace correlation Close #1683
PiperOrigin-RevId: 818844025
2025-10-13 14:57:23 -07:00
George Weale d8548aabd2 feat: add structured JSON logging with Cloud Trace correlation Close #1683
- add a shared --structured_logs flag to adk web and adk api_server so users can opt into JSON-formatted output
- introduce CloudTraceJSONFormatter that emits structured entries and attaches current Cloud Trace/Span IDs when an OpenTelemetry context is active
- update CLI logging setup to clear duplicate stdout handlers when Cloud Logging is enabled and to reconfigure existing handlers (like from Uvicorn) so they also pick up the structured format and requested log level

With the flag disabled the CLIs keep their existing text logs; when enabled, the services now produce Cloud Logging–friendly JSON that can be correlated with distributed traces.

PiperOrigin-RevId: 818823818
2025-10-13 14:08:45 -07:00
Google Team Member df05ed6b3b feat: migrate invocation_context to callback_context
Update plugin manager and built-in plugins to prioritize CallbackContext. Keep InvocationContext access for legacy plugins with adapter. Change callback docs/tests to cover the new context.

PiperOrigin-RevId: 818822267
2025-10-13 14:05:44 -07:00
Google Team Member 2158b3c915 fix: correctly populate context_id in remote_a2a_agent library when constructing a2a request
PiperOrigin-RevId: 818813897
2025-10-13 13:45:54 -07:00
George Weale e2072af69f feat: migrate invocation_context to callback_context
Update plugin manager and built-in plugins to prioritize CallbackContext. Keep InvocationContext access for legacy plugins with adapter. Change callback docs/tests to cover the new context.

PiperOrigin-RevId: 818798087
2025-10-13 13:09:15 -07:00
Xiang (Sean) Zhou fa84bcb575 chore: Correct the callback signatures
PiperOrigin-RevId: 818781277
2025-10-13 12:30:37 -07:00
Shangjie Chen bb1ea74924 chore: Delegate the agent state reset logic to LoopAgent
This is so we don't need to worry about side effect of Loop in all agent type. Custom agent should do the same if there exists loop inside.

PiperOrigin-RevId: 818766305
2025-10-13 11:53:59 -07:00
Xiang (Sean) Zhou 214986ebeb chore: Adjust the instruction about default model
PiperOrigin-RevId: 818765464
2025-10-13 11:52:11 -07:00
Ankur Sharma 348e552ba6 chore: Remove deprecated run_evals from cli_eval.py
This change removes the `run_evals` function and its helper `_get_evaluator` from `cli_eval.py`, as they were marked as deprecated. Corresponding test mocks and patches in `test_fast_api.py` are also removed.

PiperOrigin-RevId: 818719422
2025-10-13 10:13:12 -07:00
Google Team Member e212ff558e feat: Add new methods in the artifact service interface
PiperOrigin-RevId: 818473733
2025-10-12 21:19:20 -07:00
Xuan Yang e63180cb62 feat: Add the support for returning struct_data.uri in DiscoveryEngineSearchTool
For https://github.com/google/adk-python/issues/3146

PiperOrigin-RevId: 818458080
2025-10-12 20:28:08 -07:00
Google Team Member 6da7274858 feat: Set default for bypass_multi_tools_limit to False for GoogleSearchTool and VertexAiSearchTool
PiperOrigin-RevId: 818053371
2025-10-11 09:57:36 -07:00
Xuan Yang b21d0a50d6 fix: Add more clear instruction to the doc updater agent about one PR for each recommended change
PiperOrigin-RevId: 817831087
2025-10-10 16:37:12 -07:00
Joe Fernandez 16b030b2b2 fix: Add a guideline to avoid content deletion
Directs agent to avoid deleting existing content

PiperOrigin-RevId: 817823999
2025-10-10 16:12:16 -07:00
Xinran (Sherry) Tang 59670d240e feat: Support resuming from a paused invocation starting from a sub-agent
PiperOrigin-RevId: 817766247
2025-10-10 13:24:02 -07:00
Google Team Member bddc70b5d0 fix: Better handling the A2A streaming tasks so calling Agent can tell whether it's in progress updates (thought) or the final response
PiperOrigin-RevId: 817682171
2025-10-10 09:46:54 -07:00
George Weale 85ed500871 fix: Add support for file URIs in LiteLLM content conversion to fix issue #3131
changed the LiteLLM content conversion so Part.file_data.file_uri (like the gs://…) becomes a file object with file_id, making sure GCS-backed files reach LiteLLM proxies instead of being dropped add unit tests covering both _get_content and _content_to_message_param paths for file URIs

PiperOrigin-RevId: 817658432
2025-10-10 08:39:17 -07:00
Ankur Sharma 998264a5b1 fix: Only exclude scores that are None
Scores with values 0 (or 0.0) were also getting excluded.

PiperOrigin-RevId: 817658059
2025-10-10 08:38:18 -07:00
Xuan Yang 9a6b8507f0 feat: Add bypass_multi_tools_limit option to GoogleSearchTool and VertexAiSearchTool
PiperOrigin-RevId: 817493869
2025-10-09 23:05:02 -07:00
Ankur Sharma 64646e0002 chore: Remove deprecated static methods from TrajectoryEvaluator
This change removes the `evaluate`, `_evaluate_row`, `are_tools_equal`, `_remove_tool_outputs`, `_report_failures`, and `_print_results` static methods from `TrajectoryEvaluator`, along with their corresponding unit tests. These methods were previously marked as deprecated.

PiperOrigin-RevId: 817477494
2025-10-09 22:02:24 -07:00
Hangfei Lin 81913c85f4 chore: Update README md with recent ADK features
This CL updates the "What's new" section to include Resumability, ReflectRetryToolPlugin, Context compaction, and Search tool support. It also moves "Agent Config" and "Tool Confirmation" from "What's new" to "Key Features".

PiperOrigin-RevId: 817469210
2025-10-09 21:23:37 -07:00
Xiang (Sean) Zhou 9e0b1fb62b fix: Create context cache only when prefix matches with previous request
PiperOrigin-RevId: 817468275
2025-10-09 21:19:28 -07:00
Hangfei Lin 731bb9078d chore: Announce the first ADK Community Call in the README
The added section provides details for the community call on Oct 15, 2025, including the agenda and links to join and add to calendars.

PiperOrigin-RevId: 817457276
2025-10-09 20:35:47 -07:00
Ankur Sharma ae139bb461 feat: ADK cli allows developers to create an eval set and add an eval case
Agent developers can now create an eval set and add eval cases through command line itself. Adding an eval case is limited only to specifying conversation scenarios.

Sample comamnds:
- Create an eval set:
adk eval_set create \
    contributing/samples/hello_world \
    set_01

- Add an eval case with scenario file
Content of scenarios.json file:
'{"scenarios": [{"starting_prompt": "hello", "conversation_plan": "world"}]}'

adk eval_set add_eval_case \
    contributing/samples/hello_world \
    set_01 \
    --scenarios scenarios.json

PiperOrigin-RevId: 817456117
2025-10-09 20:31:01 -07:00
Xinran (Sherry) Tang 9939e0b087 feat: Support resuming a parallel agent with multiple branches paused on tool confirmation requests
PiperOrigin-RevId: 817373403
2025-10-09 16:04:55 -07:00
Xiang (Sean) Zhou cc24d616f8 feat: Support ContentUnion as static instruction
PiperOrigin-RevId: 817278990
2025-10-09 11:52:24 -07:00
Wei Sun (Jack) 0aede9f1a1 docs: Update CHANGELOG with [847df16](https://github.com/google/adk-python/commit/847df1638cbf1686aa43e8e094121d4e23e40245)
PiperOrigin-RevId: 817267158
2025-10-09 11:24:48 -07:00
George Weale 847df1638c fix: handle App instances returned by agent_loader.load_agent
The `agent_loader.load_agent` method can now return an `App` object. This change unwraps the `App` to get its `root_agent` before passing it to the graph builder, makes sure a `BaseAgent` instance is always used

PiperOrigin-RevId: 817209601
2025-10-09 09:00:30 -07:00
Kacper Jawoszek 55aa6f669b feat(otel): set default_log_name for GCP logging exporter
Uses value of GCP_DEFAULT_LOG_NAME env var if it exists, defaults to literal adk-otel.

PiperOrigin-RevId: 817125337
2025-10-09 04:38:26 -07:00
Xuan Yang 9b8a4aad6f chore: Add an sample agent for the ReflectAndRetryToolPlugin
PiperOrigin-RevId: 817024977
2025-10-08 23:05:25 -07:00
Xiang (Sean) Zhou cac9fae829 chore: Don't label 'bot triaged' for PR
PiperOrigin-RevId: 816959715
2025-10-08 19:21:35 -07:00
Wei Sun (Jack) 24342e95f8 chore: Remove temp state deltas before appending an event
PiperOrigin-RevId: 816902208
2025-10-08 16:13:52 -07:00
Ankur Sharma cbe60c47aa feat: Adds data model to support UserSimulation
Details:
- Introduces a concept of `ConversationScenario` to represent a scenario that user simulator is supposed to follow.
- Introduces a `UserSimulator` interface, that one should implement. UserSimulator interface will be integrated with LocalEvalService in subsequent PRs.
PiperOrigin-RevId: 816883699
2025-10-08 15:23:57 -07:00
Xiang (Sean) Zhou 2efaa57575 chore: Don't label issue as bot triaged
PiperOrigin-RevId: 816873967
2025-10-08 14:58:49 -07:00
Xinran (Sherry) Tang 32f2ec3a78 feat: Set agent_state in invocation context right before yielding the checkpoint event
PiperOrigin-RevId: 816804179
2025-10-08 12:01:57 -07:00
Shangjie Chen 75179243b4 chore: Update human_tool_confirmation agent to use resumability feature
PiperOrigin-RevId: 816793131
2025-10-08 11:35:13 -07:00
Wei Sun (Jack) 03f051d3ed chore: Bumps version to v1.16.0 and updates CHANGELOG
PiperOrigin-RevId: 816788551
2025-10-08 11:26:58 -07:00
George Weale e858dc0799 chore: change how agent builder assistant instructions for model selection asking, to make it ask once for plan and one for model selection
PiperOrigin-RevId: 816788530
2025-10-08 11:22:54 -07:00
Google Team Member 0e3c0f78f5 feat: Make session_id optional in BaseArtifactService methods
PiperOrigin-RevId: 816782982
2025-10-08 11:08:41 -07:00
Xiang (Sean) Zhou f2bed14c4b chore: Adjust the LLM Request logging
1. function declarations is not necessary in the first tool
2. log the config

PiperOrigin-RevId: 816547534
2025-10-07 23:07:18 -07:00
Haoming Chen 30212669ff docs: Update BigQuery samples README
Add the new analyze_contribution tool and renumbering as the Github cannot display it correctly.

PiperOrigin-RevId: 816517893
2025-10-07 21:19:40 -07:00
Hangfei Lin 3f2b457efd fix: fix compaction logic
When there are multiple intervals and compactions, the original implementation only keep the last one. The right implementation is to keep as many compaction events/summary as the requested internals.

PiperOrigin-RevId: 816516662
2025-10-07 21:16:07 -07:00
Che Liu e55b8946d6 feat: Add ReflectRetryToolPlugin to reflect from errors and retry with different arguments when tool errors
This plugin intercepts tool failures, provides structured guidance to the LLM for reflection and correction, and retries the operation up to a configurable limit.

**Key Features:**

- **Concurrency Safe:** Uses locking to safely handle parallel tool
executions
- **Configurable Scope:** Tracks failures per-invocation (default) or globally
  using the `TrackingScope` enum.
- **Extensible Scoping:** The `_get_scope_key` method can be overridden to
  implement custom tracking logic (e.g., per-user or per-session).
- **Granular Tracking:** Failure counts are tracked per-tool within the
  defined scope. A success with one tool resets its counter without affecting
  others.
- **Custom Error Extraction:** Supports detecting errors in normal tool
responses
that
  don't throw exceptions, by overriding the `extract_error_from_result`
  method.

**Example:**
```python
from my_project.plugins import ReflectAndRetryToolPlugin, TrackingScope

# Example 1: (MOST COMMON USAGE):
# Track failures only within the current agent invocation (default).
error_handling_plugin = ReflectAndRetryToolPlugin(max_retries=3)

# Example 2:
# Track failures globally across all turns and users.
global_error_handling_plugin = ReflectAndRetryToolPlugin(max_retries=5,
scope=TrackingScope.GLOBAL)

# Example 3:
# Retry on failures but do not throw exceptions.
error_handling_plugin =
  ReflectAndRetryToolPlugin(max_retries=3,
  throw_exception_if_retry_exceeded=False)

# Example 4:
# Track failures in successful tool responses that contain errors.
class CustomRetryPlugin(ReflectAndRetryToolPlugin):
  async def extract_error_from_result(self, *, tool, tool_args,tool_context,
  result):
    # Detect error based on response content
    if result.get('status') == 'error':
        return result
    return None  # No error detected
error_handling_plugin = CustomRetryPlugin(max_retries=5)
```
PiperOrigin-RevId: 816456549
2025-10-07 17:56:54 -07:00
Douglas Reid 2b5acb98f5 feat(models): add support for gemma model via gemini api
Merge https://github.com/google/adk-python/pull/2857

Adds support for invoking Gemma models via the Gemini API endpoint. To support agentic function, callbacks are added which can extract and transform function calls and responses into user and model messages in the history.

This change is intended to allow developers to explore the use of Gemma models for agentic purposes without requiring local deployment of the models. This should ease the burden of experimentation and testing for developers.

A basic "hello world" style agent example is provided to demonstrate proper functioning of Gemma 3 models inside an Agent container, using the dice roll + prime check framework of similar examples for other models.

## Testing

### Testing Plan
- add and run integration and unit tests
- manual run of example `multi_tool_agent` from quickstart using new `Gemma` model
- manual run of `hello_world_gemma` agent

### Automated Test Results:
| Test Command | Results |
|----------------|---------|
| pytest ./tests/unittests | 4386 passed, 2849 warnings in 58.43s |
| pytest ./tests/unittests/models/test_google_llm.py | 100 passed, 4 warnings in 5.83s |
| pytest ./tests/integration/models/test_google_llm.py | 5 passed, 2 warnings in 3.73s |

### Manual Testing

Here is a log of `multi_tool_agent` run with locally-built wheel and using Gemma model.
```
❯ adk run multi_tool_agent
Log setup complete: /var/folders/bg/_133c0ds2kb7cn699cpmmh_h0061bp/T/agents_log/agent.20250904_152617.log
To access latest log: tail -F /var/folders/bg/_133c0ds2kb7cn699cpmmh_h0061bp/T/agents_log/agent.latest.log
/Users/<redacted>/venvs/adk-quickstart/lib/python3.11/site-packages/google/adk/cli/cli.py:143: UserWarning: [EXPERIMENTAL] InMemoryCredentialService: This feature is experimental and may change or be removed in future versions without notice. It may introduce breaking changes at any time.
  credential_service = InMemoryCredentialService()
/Users/<redacted>/venvs/adk-quickstart/lib/python3.11/site-packages/google/adk/auth/credential_service/in_memory_credential_service.py:33: UserWarning: [EXPERIMENTAL] BaseCredentialService: This feature is experimental and may change or be removed in future versions without notice. It may introduce breaking changes at any time.
  super().__init__()
Running agent weather_time_agent, type exit to exit.
[user]: what's the weather like today?
[weather_time_agent]: Which city are you asking about?

[user]: new york
[weather_time_agent]: OK. The weather in New York is sunny with a temperature of 25 degrees Celsius (77 degrees Fahrenheit).
```

And here is a snippet of a log generated with DEBUG level logging of the `hello_world_gemma` sample. It demonstrates how function calls are extracted and inserted based on Gemma model interactions:

```
...
2025-09-04 15:32:41,708 - DEBUG - google_llm.py:138 -
LLM Request:
-----------------------------------------------------------
System Instruction:
None
-----------------------------------------------------------
Contents:
{"parts":[{"text":"\n      You roll dice and answer questions about the outcome of the dice rolls.\n      You can roll dice of different sizes...\n"}],"role":"user"}
{"parts":[{"text":"Hi, introduce yourself."}],"role":"user"}
{"parts":[{"text":"Hello! I am data_processing_agent, a hello world agent that can roll many-sided dice and check if numbers are prime. I'm ready to assist you with those tasks. Let's begin!\n\n\n\n"}],"role":"model"}
{"parts":[{"text":"Roll a die with 100 sides and check if it is prime"}],"role":"user"}
{"parts":[{"text":"{\"args\":{\"sides\":100},\"name\":\"roll_die\"}"}],"role":"model"}
{"parts":[{"text":"Invoking tool `roll_die` produced: `{\"result\": 82}`."}],"role":"user"}
{"parts":[{"text":"{\"args\":{\"nums\":[82]},\"name\":\"check_prime\"}"}],"role":"model"}
{"parts":[{"text":"Invoking tool `check_prime` produced: `{\"result\": \"No prime numbers found.\"}`."}],"role":"user"}
{"parts":[{"text":"The die roll was 82, and it is not a prime number.\n\n\n\n"}],"role":"model"}
{"parts":[{"text":"Roll it again."}],"role":"user"}
-----------------------------------------------------------
Functions:

-----------------------------------------------------------

2025-09-04 15:32:41,708 - INFO - models.py:8165 - AFC is enabled with max remote calls: 10.
2025-09-04 15:32:42,693 - INFO - google_llm.py:180 - Response received from the model.
2025-09-04 15:32:42,693 - DEBUG - google_llm.py:181 -
LLM Response:
-----------------------------------------------------------
Text:
{"args":{"sides":100},"name":"roll_die"}
-----------------------------------------------------------
...
```
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/2857 from douglas-reid:add-gemma-via-api e6d015f6a9ccbcf20ef7a7af8e4bbe1e9a5936b6
PiperOrigin-RevId: 816451001
2025-10-07 17:38:35 -07:00
Hangfei Lin 84f2f417f7 fix: Rollback compaction handling from _get_contents
The sorting may cause problems in complex cases so rolling it back. Will implement it with a non-sorting approach.

PiperOrigin-RevId: 816420710
2025-10-07 16:11:36 -07:00
Google Team Member 8110e41b36 fix: VertexSessionService with adding base_url override to base api override without removing initialized http_options
PiperOrigin-RevId: 816409410
2025-10-07 15:43:17 -07:00
Xuan Yang b0f0698ec2 chore: Add a sample agent to demonstrate that built-in google search tool and VertexAiSearchTool can be used together with other tools
PiperOrigin-RevId: 816396360
2025-10-07 15:08:53 -07:00
Xinran (Sherry) Tang db41f54e7b chore: When processing pending tool confirmation requests, only look at events in the same branch
PiperOrigin-RevId: 816387687
2025-10-07 14:48:19 -07:00
Shangjie Chen 636def3687 fix: Add AuthConfig json serialization in vertex ai session service
Resolves https://github.com/google/adk-python/issues/2035

PiperOrigin-RevId: 816387628
2025-10-07 14:47:28 -07:00
Xiang (Sean) Zhou 3f86760e0b chore: Remove unnecessary check tool type and tool attribute
tool in config.tools cann't be ToolDict and must have computer_use attr

PiperOrigin-RevId: 816368064
2025-10-07 14:01:53 -07:00
Yifan Wang 5ac446d947 chore: add invocation_id to AgentRunRequest for resuming long running functions
PiperOrigin-RevId: 816362937
2025-10-07 13:49:50 -07:00
Xuan Yang 2699ad7aff chore: fix the test_llm_agent_fields.py by adding a mock for google.auth.default
PiperOrigin-RevId: 816319357
2025-10-07 12:05:48 -07:00
Xuan Yang 4485379a04 ADK changes
PiperOrigin-RevId: 816288113
2025-10-07 10:59:19 -07:00
Xiang (Sean) Zhou 0989d64688 chore: Remove unnecessary check tool type and tool attribute
tool in config.tools cann't be ToolDict and must have computer_use attr

PiperOrigin-RevId: 816283438
2025-10-07 10:48:48 -07:00
Shangjie Chen 90d4c19c51 feat: Migrate vertex ai session service to use agent engine sdk
PiperOrigin-RevId: 816259798
2025-10-07 09:58:27 -07:00
Xiang (Sean) Zhou 3be9cd844c chore: Let tools to handle root directory resolvement and model only knows the project name and always use relative path
PiperOrigin-RevId: 816213558
2025-10-07 08:11:06 -07:00
Hangfei Lin 3f4bd67b49 fix: Make compactor optional in EventsCompactionConfig and add a default
If `EventsCompactionConfig` is provided without a `compactor`, a `SlidingWindowCompactor` is now automatically instantiated using the `root_agent`'s LLM. This simplifies configuration by providing a sensible default.

PiperOrigin-RevId: 816038579
2025-10-06 22:20:49 -07:00
Bo Yang 238472d083 fix: Updates the load_artifacts tool so that the model can reliability call it for follow up questions about the same artifact
PiperOrigin-RevId: 816025399
2025-10-06 21:34:51 -07:00
Hangfei Lin f1abdb1938 fix: Rename SlidingWindowCompactor to LlmEventSummarizer and refine its docstring
The class is now named `LlmEventSummarizer` to better reflect that its primary function is to use an LLM to summarize events. The docstring has been updated to clarify that this class is responsible *only* for the LLM-based summarization of a given set of events, while the logic for determining *when* and *which* events form the sliding window is handled by an external component, such as an ADK Runner.

PiperOrigin-RevId: 815976264
2025-10-06 18:54:20 -07:00
Hangfei Lin 68402bda49 fix: Set default response modality to AUDIO in run_session
Some native audio models require the modality to be set, so we default to AUDIO if not specified in `RunConfig`.

PiperOrigin-RevId: 815952039
2025-10-06 17:37:10 -07:00
Xiang (Sean) Zhou 90e1e3e10c chore: Add sample agent for testing oatuh2 client credentials grant type
PiperOrigin-RevId: 815863131
2025-10-06 13:34:09 -07:00
Haoming Chen 4bb089d386 feat: Add BigQuery analyze_contribution tool
This change introduces a new `analyze_contribution` function in `query_tool.py` which uses BigQuery ML's `CREATE MODEL` with `CONTRIBUTION_ANALYSIS` type and `ML.GET_INSIGHTS` to analyze the contribution of different dimensions to a given metric. The new function is also added to the `bigquery_toolset`.

PiperOrigin-RevId: 815849281
2025-10-06 12:59:09 -07:00
Xiang (Sean) Zhou 5c6cdcd197 feat: Support Oauth2 client credentials grant type
PiperOrigin-RevId: 815813477
2025-10-06 11:28:17 -07:00
George Weale 46d73be41a chore: Add more info to "Session not found" error message in ADK runners for differently named app and folder
PiperOrigin-RevId: 815795412
2025-10-06 10:48:28 -07:00
Hangfei Lin e0dd06ff04 feat: implementation of LLM context compaction
Provide a more efficient way to compact LLM context for better agentic performance.

PiperOrigin-RevId: 815785898
2025-10-06 10:28:46 -07:00
Xiang (Sean) Zhou ca6a4340f4 chore: Move adk knowledge agent out of adk agent builder folder
PiperOrigin-RevId: 815771308
2025-10-06 09:57:21 -07:00
George Weale 86de3ef7e3 chore: google.genai instead of `google.generativeai'
PiperOrigin-RevId: 815759570
2025-10-06 09:27:13 -07:00
Max Ind bd76b46ce2 feat(otel): Switch CloudTraceSpanExporter to telemetry.googleapis.com
PiperOrigin-RevId: 815675872
2025-10-06 05:14:32 -07:00
Xiang (Sean) Zhou 4b47a0a552 chore: Add instructions for callback signatures
PiperOrigin-RevId: 815549924
2025-10-05 21:47:53 -07:00
Xuan Yang 84c1faeeef chore: Introduce the remote A2A ADK Knowledge Agent to Agent Builder Assistant
PiperOrigin-RevId: 815543707
2025-10-05 21:21:19 -07:00
Xiang (Sean) Zhou c6dd444fc9 fix: Adapt to new computer use tool name in genai sdk 1.41.0
1.40.0 has some bug that caused some UT tests failures

PiperOrigin-RevId: 815098429
2025-10-04 08:53:13 -07:00
Google Team Member d1efc8461e feat: Migrate vertex_ai_session_service to use Agent Engine SDK
PiperOrigin-RevId: 814967790
2025-10-03 22:14:23 -07:00
Shangjie Chen 97b950b36b feat: Migrate vertex_ai_session_service to use Agent Engine SDK
PiperOrigin-RevId: 814948921
2025-10-03 21:00:15 -07:00
Google Team Member 960eda3d1f feat: Add dry_run functionality to BigQuery execute_sql tool
PiperOrigin-RevId: 814854520
2025-10-03 15:36:58 -07:00
Xiang (Sean) Zhou 0b84d3eea7 chore: Show relative path in response if root directory already set in session state
PiperOrigin-RevId: 814768273
2025-10-03 11:33:24 -07:00
Xiang (Sean) Zhou 611b604bdc chore: Emphasize not to ask for root_directory if it's set in the context
PiperOrigin-RevId: 814738676
2025-10-03 10:14:44 -07:00
Xiang (Sean) Zhou 33b2d495be chore: Emphasize "model" property can inherit from parent LlmAgent
PiperOrigin-RevId: 814715394
2025-10-03 09:06:33 -07:00
Max Ind 0162898707 ADK changes
PiperOrigin-RevId: 814614027
2025-10-03 02:56:51 -07:00
Xuan Yang 42db35111b chore: fix typo for GenerateContentConfig in Agent Builder Assistant
PiperOrigin-RevId: 814495803
2025-10-02 19:56:55 -07:00
George Weale dd0571ad09 chore: Clarify write_config_files usage for sub-agent YAML files
PiperOrigin-RevId: 814489632
2025-10-02 19:36:15 -07:00
George Weale a4ef7edcbb chore: add __init__.py prompt for tool imports
PiperOrigin-RevId: 814488943
2025-10-02 19:33:58 -07:00
Xiang (Sean) Zhou c5b976b306 chore: Create the context cache based on the token count of previous request
before this change, we estimate the token count of the contents to cache and use it to compare with the threshold user set. but that's not precise , so we use the actual prompt token count of previous llm request.

We won't create cache for the very initial request

PiperOrigin-RevId: 814484840
2025-10-02 19:22:00 -07:00
Xuan Yang 420df25f58 chore: add a remote A2A knowledge agent for Agent Builder Assistant
PiperOrigin-RevId: 814484204
2025-10-02 19:20:36 -07:00
Google Team Member a9b76b9061 ADK changes
PiperOrigin-RevId: 814417092
2025-10-02 15:49:48 -07:00
Google Team Member 65d6da081c ADK changes
PiperOrigin-RevId: 814413627
2025-10-02 15:49:35 -07:00
Shangjie Chen b170a84279 chore: Handle exception in preload_memory_tool to not fail the llm request
Resolves https://github.com/google/adk-python/issues/3069

PiperOrigin-RevId: 814391260
2025-10-02 14:41:27 -07:00
Wei Sun (Jack) 5b8d523a4b ADK changes
PiperOrigin-RevId: 814367778
2025-10-02 13:44:16 -07:00
Xuan Yang d3148dacc9 ADK changes
PiperOrigin-RevId: 814319961
2025-10-02 13:44:05 -07:00
George Weale 2e2d61b6fe fix: Set max_output_tokens for the agent builder
PiperOrigin-RevId: 814317909
2025-10-02 13:43:55 -07:00
Ankur Sharma 65554d6621 chore: Update AgentEvaluator to use EvalConfig
We updated the one of the public methods on AgentEvaluator to take in eval metric configurations using a more formal EvalConfig data model.

We also mark "criteria" field on the method as deprecated.

Updated some integration test cases.

PiperOrigin-RevId: 814314134
2025-10-02 13:43:44 -07:00
George Weale e68006386f fix: Fixes a bug that causes intermittent pydantic validation errors when uploading files
The root cause is an unsafe in-memory mutation. The `SaveFilesAsArtifactsPlugin` was saving a direct reference to the message part and then modifying the message list in-place. This created a race condition where downstream code could alter the original part *after* it had been saved as an artifact, leading to a corrupted state.
This CL saves a `copy.copy()` of the artifact, which create a snapshot of the data.
Also Changes the plugin to return a new `types.Content` object instead of modifying the original message in-place

PiperOrigin-RevId: 814308070
2025-10-02 13:43:34 -07:00
George Weale f667c7445e chore: deprecate global_instructions and make it a plugin instead
PiperOrigin-RevId: 814307563
2025-10-02 13:43:22 -07:00
Xiang (Sean) Zhou 29f18f4eea chore: Add a sample agent to test pydantic models as function tool argument
PiperOrigin-RevId: 814293450
2025-10-02 13:43:10 -07:00
Xiang (Sean) Zhou 571c802fba fix: Convert argument to pydantic model when tool declare to accept pydantic model as argument
PiperOrigin-RevId: 814273005
2025-10-02 13:43:00 -07:00
Xiang (Sean) Zhou c46308b7cf chore: Add session patch endpoint to api server for state update
This is allow user to update session state without running the agent. e.g. if I want to test some case when session has certain state on adk web.

PiperOrigin-RevId: 814252851
2025-10-02 13:42:49 -07:00
Hoonji Baek 822efe0065 feat: Adds adk web options for custom logo
Allows users to configure a custom text and logo for their ADK Web app using `--logo-text` and `--logo-image-url` flags.

PiperOrigin-RevId: 814016542
2025-10-02 13:42:38 -07:00
Shangjie Chen 55bc985821 chore: Fix vertexai import rule of memory service for google internal dependencies
PiperOrigin-RevId: 813941520
2025-10-02 13:42:23 -07:00
Google Team Member da62700d73 feat: Spanner ADK toolset supports customizable template SQL and parameterized SQL
PiperOrigin-RevId: 813909122
2025-10-01 14:15:01 -07:00
Google Team Member a5cf80b952 fix: Handling of A2ATaskStatusUpdateEvent when streaming in remote_a2a_agent
The proto has the Message object in the TaskStatus.

PiperOrigin-RevId: 813844289
2025-10-01 11:43:03 -07:00
Xuan Yang 29968d44ae chore: Remove get_working_directory_info from instruction template for agent builder assistant
PiperOrigin-RevId: 813495752
2025-09-30 17:29:33 -07:00
Yifan Wang ce2167861c chore: Adding builder endpoints, WIP
PiperOrigin-RevId: 813489379
2025-09-30 17:10:38 -07:00
Joseph Pagadora 8c73d29c75 feat: Add HallucinationsV1 evaluation metric
PiperOrigin-RevId: 813456369
2025-09-30 15:39:10 -07:00
Xuan Yang a239716930 ADK changes
PiperOrigin-RevId: 813321782
2025-09-30 10:18:30 -07:00
Google Team Member c51ea0b52e fix: VertexSessionService with adding base_url override to base api override without removing initialized http_options
PiperOrigin-RevId: 813319796
2025-09-30 10:14:58 -07:00
Liang Wu 8f3ca0359e fix: fix the instruction in workflow_triage example agent
PiperOrigin-RevId: 813305068
2025-09-30 09:37:54 -07:00
Joe Fernandez 745996212d fix: Added more agent instructions for doc content changes
Add directives for content updates and writing style

PiperOrigin-RevId: 813284600
2025-09-30 08:44:59 -07:00
Shangjie Chen 83fd045718 feat: Migrate VertexAiMemoryBankService to use Agent Engine SDK
PiperOrigin-RevId: 813104746
2025-09-29 23:14:50 -07:00
Shangjie Chen ce9c39f5a8 feat: Implement checkpoint and resume logic for LoopAgent
PiperOrigin-RevId: 813096880
2025-09-29 22:45:57 -07:00
Wei Sun (Jack) d5c46e4960 fix: Do not re-create App object when loader returns an App
PiperOrigin-RevId: 813083541
2025-09-29 22:02:19 -07:00
Xinran (Sherry) Tang fbf75761bb feat: Modify runner to support resuming an invocation (optionally with a function response)
PiperOrigin-RevId: 813008406
2025-09-29 17:35:18 -07:00
Xinran (Sherry) Tang f005414895 feat: Make resumable llm agents yield checkpoint events
PiperOrigin-RevId: 813001108
2025-09-29 17:08:58 -07:00
Ankur Sharma 609a2358eb chore: PrettyPrint the output of detailed results generated from adk eval cli command
PiperOrigin-RevId: 812912413
2025-09-29 13:09:31 -07:00
Xinran (Sherry) Tang 772658fd81 chore: Refactor runner run_async flow to extract out execution context setup logic
PiperOrigin-RevId: 812894540
2025-09-29 12:21:45 -07:00
Google Team Member 8e5f361264 fix: Update remote_a2a_agent to better handle streaming events and avoid duplicate responses
Currently, the A2A Task -> ADK event conversion is producing the same events on the last two update events (the last is a status update marking the task complete)

The change here based on A2AClientEvent(task, update):
 - if the update == None: handle the non-streaming task case and also streaming case for the initial task creation event
 - if the update = TaskStatusUpdateEvent AND a message is set: emit an event with that message
 - if a task status update AND no message is set: don't emit event (for example, the final status update)
 - if the update is ArtifactUpdateEvent and it's final artifact: emit the event

PiperOrigin-RevId: 812878869
2025-09-29 11:42:49 -07:00
Google Team Member b1ee013347 chore: Remove debug print from get_agent_graph
PiperOrigin-RevId: 812767234
2025-09-29 06:48:06 -07:00
Shangjie Chen 2f1040f296 feat: Implement checkpoint and resume logic for ParallelAgent
PiperOrigin-RevId: 812658378
2025-09-29 00:26:32 -07:00
Xiang (Sean) Zhou 943abec7c0 chore: Clarify the rule for getting tool name prefix in instruction
PiperOrigin-RevId: 812097390
2025-09-26 23:10:24 -07:00
Google Team Member 3f28e30c6d feat: add citation_metadata to LlmResponse
PiperOrigin-RevId: 811997009
2025-09-26 16:31:01 -07:00
Shangjie Chen 7b707cebea chore: Simplfiy the parallel agent py version handling logic
PiperOrigin-RevId: 811992425
2025-09-26 16:15:51 -07:00
Ankur Sharma c984b9e552 feat: Add Rubric based tool use metric
The PR does two main things:
1) Introduces a new rubric based tool use metric
2) Given that we now have two rubric based metric, we refactor and create a new RubricBasedEvaluator interface.

PiperOrigin-RevId: 811983514
2025-09-26 15:47:42 -07:00
Xuan Yang a959653cf3 chore: bump version to 1.15.1 with a patch for Agent Engine
PiperOrigin-RevId: 811981894
2025-09-26 15:42:12 -07:00
Shangjie Chen 1ee01cc05a feat: Implement checkpoint and resume logic for SequentialAgent
PiperOrigin-RevId: 811977004
2025-09-26 15:26:42 -07:00
Xinran (Sherry) Tang 28d44a365a test: Make testing_utils.InMemoryRunner support ADK App and add utils for extracting event contents for testing resumability
PiperOrigin-RevId: 811933527
2025-09-26 13:22:11 -07:00
Sasha Sobran e172811bc7 fix: unbreak client closed errors when using vertexai session service
PiperOrigin-RevId: 811911528
2025-09-26 12:16:37 -07:00
Xuan Yang da6f1d3653 chore: Release ADK 1.15.0
PiperOrigin-RevId: 811655912
2025-09-25 22:17:23 -07:00
Shangjie Chen 2c752934a8 feat: Skip running a workflow agent if it has no sub-agents
PiperOrigin-RevId: 811528166
2025-09-25 15:39:38 -07:00
Xinran (Sherry) Tang b2b80e7fa0 feat: Pause invocations on long running function calls for resumable apps
PiperOrigin-RevId: 811518771
2025-09-25 15:11:11 -07:00
Xuan Yang dd1ffad394 chore: Update google-genai version constraint
Fixes https://github.com/google/adk-python/issues/2968

PiperOrigin-RevId: 811475972
2025-09-25 13:21:45 -07:00
Shangjie Chen 8b081751ed feat: Add core checkpointing primitive for base agent
PiperOrigin-RevId: 811458903
2025-09-25 12:35:36 -07:00
Xinran (Sherry) Tang b5a65fb4f4 chore: Remove the too-detailed edge case descriptions for resumability
PiperOrigin-RevId: 811432962
2025-09-25 11:32:38 -07:00
Shangjie Chen 839d2e43bb feat: Define an AgentState to be used for resuming agent invocation
PiperOrigin-RevId: 811414736
2025-09-25 10:49:49 -07:00
Xiang (Sean) Zhou 1589fcdd86 chore: Replace github HTTP URIs with GCS HTTP URIs in static non-text content sample agent
mainly because http://github.com/robots.txt disallows `/*/raw/` path. using GCS HTTP URIs is more reliable with Gemini model.

PiperOrigin-RevId: 811409688
2025-09-25 10:38:04 -07:00
Max Ind e7528aebd4 feat(otel): adjust telemetry to follow OTLP 1.37 GenAI semconv
Changes include:
- Implementing missing attributes. e.g. 'gen_ai.agent.name'
- Specifying reasons for not filling out some conditionally required attributes. e.g. 'gen_ai.data_source.id'
- Specifying reasons for not including certain attributes which are specified in current semconv. e.g. inference attributes on agent spans

PiperOrigin-RevId: 811379706
2025-09-25 09:25:15 -07:00
Xinran (Sherry) Tang cbb6e4945a feat: Add a app level config for resumable applications
PiperOrigin-RevId: 811272046
2025-09-25 03:14:34 -07:00
Xiang (Sean) Zhou c6b6b6f3c6 chore: Add log-level parameter to cache analysis experiments
this is to allow turning on debug log for debugging if some unexpected behavior observed during running cache analysis experiments.

PiperOrigin-RevId: 811189954
2025-09-24 22:44:41 -07:00
Google Team Member c8c6cd70a4 feat: Introduce ExtendedOAuth2 scheme that auto-populates auth/token URLs
Use auto-discovered auth_endpoint and token_endpoint in CredentialManager.

PiperOrigin-RevId: 811183929
2025-09-24 22:21:07 -07:00
272 changed files with 24992 additions and 4984 deletions
+8 -2
View File
@@ -3,10 +3,16 @@ name: ADK Pull Request Triaging Agent
on:
pull_request_target:
types: [opened, reopened, edited]
workflow_dispatch:
inputs:
pr_number:
description: 'The Pull Request number to triage'
required: true
type: 'string'
jobs:
agent-triage-pull-request:
if: "!contains(github.event.pull_request.labels.*.name, 'bot triaged') && !contains(github.event.pull_request.labels.*.name, 'google-contributor')"
if: github.event_name == 'workflow_dispatch' || !contains(github.event.pull_request.labels.*.name, 'google-contributor')
runs-on: ubuntu-latest
permissions:
pull-requests: write
@@ -33,7 +39,7 @@ jobs:
GOOGLE_GENAI_USE_VERTEXAI: 0
OWNER: 'google'
REPO: 'adk-python'
PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number }}
PULL_REQUEST_NUMBER: ${{ github.event.pull_request.number || github.event.inputs.pr_number }}
INTERACTIVE: ${{ vars.PR_TRIAGE_INTERACTIVE }}
PYTHONPATH: contributing/samples
run: python -m adk_pr_triaging_agent.main
-2
View File
@@ -3,8 +3,6 @@ name: ADK Issue Triaging Agent
on:
issues:
types: [opened, reopened]
schedule:
- cron: '0 */6 * * *' # every 6h
jobs:
agent-triage-issues:
+126 -4
View File
@@ -1,5 +1,127 @@
# Changelog
## [1.16.0](https://github.com/google/adk-python/compare/v1.15.1...v1.16.0) (2025-10-08)
### Features
* **[Core]**
* Implementation of LLM context compaction ([e0dd06f](https://github.com/google/adk-python/commit/e0dd06ff04f9d3c2f022873ce145aaae2de02f45))
* Support pause and resume an invocation in ADK ([ce9c39f](https://github.com/google/adk-python/commit/ce9c39f5a85ed12c22009693b5e6bc65f4641633),
[2f1040f](https://github.com/google/adk-python/commit/2f1040f296db365080b62d6372474d90196ce0d6),
[1ee01cc](https://github.com/google/adk-python/commit/1ee01cc05add44ce460d2cfd3726dceb0c76dceb),
[f005414](https://github.com/google/adk-python/commit/f005414895a57befe880fd58c0d778e499a20d8e),
[fbf7576](https://github.com/google/adk-python/commit/fbf75761bb8d89a70b32c43bbd3fa2f48b81d67c))
* **[Models]**
* Add `citation_metadata` to `LlmResponse` ([3f28e30](https://github.com/google/adk-python/commit/3f28e30c6da192e90a8100f270274cb9a55a5348))
* Add support for gemma model via gemini api ([2b5acb9](https://github.com/google/adk-python/commit/2b5acb98f577f5349e788bcf9910c8d7107e63b3))
* **[Tools]**
* Add `dry_run` functionality to BigQuery `execute_sql` tool ([960eda3](https://github.com/google/adk-python/commit/960eda3d1f2f46dc93a365eb3de03dc3483fe9bb))
* Add BigQuery analyze_contribution tool ([4bb089d](https://github.com/google/adk-python/commit/4bb089d386d4e8133e9aadbba5c42d31ff281cf6))
* Spanner ADK toolset supports customizable template SQL and parameterized SQL ([da62700](https://github.com/google/adk-python/commit/da62700d739cb505149554962a8bcfb30f9428cc))
* Support Oauth2 client credentials grant type ([5c6cdcd](https://github.com/google/adk-python/commit/5c6cdcd197a6780fc86d9183fa208f78c8a975d9))
* Add `ReflectRetryToolPlugin` to reflect from errors and retry with different arguments when tool errors ([e55b894](https://github.com/google/adk-python/commit/e55b8946d6a2e01aaf018d6a79d11d13c5286152))
* Support using `VertexAiSearchTool` built-in tool with other tools in the same agent ([4485379](https://github.com/google/adk-python/commit/4485379a049a5c84583a43c85d444ea1f1ba6f12))
* Support using google search built-in tool with other tools in the same agent ([d3148da](https://github.com/google/adk-python/commit/d3148dacc97f0a9a39b6d7a9640f7b7b0d6f9a6c))
* **[Evals]**
* Add HallucinationsV1 evaluation metric ([8c73d29](https://github.com/google/adk-python/commit/8c73d29c7557a75d64917ac503da519361d1d762))
* Add Rubric based tool use metric ([c984b9e](https://github.com/google/adk-python/commit/c984b9e5529b48fff64865a8b805e7e93942ea53))
* **[UI]**
* Adds `adk web` options for custom logo ([822efe0](https://github.com/google/adk-python/commit/822efe00659607bad2d19ec9a2d14c649fca2d8d))
* **[Observability]**
* **otel:** Switch CloudTraceSpanExporter to telemetry.googleapis.com ([bd76b46](https://github.com/google/adk-python/commit/bd76b46ce296409d929ae69c5c43347c73e7b365))
### Bug Fixes
* Adapt to new computer use tool name in genai sdk 1.41.0 ([c6dd444](https://github.com/google/adk-python/commit/c6dd444fc947571d089b784fde3a81e17b10cf28))
* Add AuthConfig json serialization in vertex ai session service ([636def3](https://github.com/google/adk-python/commit/636def3687a85e274e3ab44d906f6d92d49e84c0))
* Added more agent instructions for doc content changes ([7459962](https://github.com/google/adk-python/commit/745996212db156878554386be34f58658482e687))
* Convert argument to pydantic model when tool declares it accepts pydantic model as argument ([571c802](https://github.com/google/adk-python/commit/571c802fbaa80b3e65f9ce2db772b9db5a13dbc4))
* Do not re-create `App` object when loader returns an `App` ([d5c46e4](https://github.com/google/adk-python/commit/d5c46e496009eb55d78637f47162df7fcaf3a7ac))
* Fix compaction logic ([3f2b457](https://github.com/google/adk-python/commit/3f2b457efd27ed47160811705e30efa6dd09d7c0))
* Fix the instruction in workflow_triage example agent ([8f3ca03](https://github.com/google/adk-python/commit/8f3ca0359e5b1306c1395770759a74aa48a52347))
* Fixes a bug that causes intermittent `pydantic` validation errors when uploading files ([e680063](https://github.com/google/adk-python/commit/e68006386fdd0da98feb9c3dce9322e44a9c914d))
* Handle A2A Task Status Update Event when streaming in remote_a2a_agent ([a5cf80b](https://github.com/google/adk-python/commit/a5cf80b952887c07bb1d56b7bdec28808edcc4a9))
* Make compactor optional in Events Compaction Config and add a default ([3f4bd67](https://github.com/google/adk-python/commit/3f4bd67b49cd60e6a2e43ccd5192efe450a6e009))
* Rename SlidingWindowCompactor to LlmEventSummarizer and refine its docstring ([f1abdb1](https://github.com/google/adk-python/commit/f1abdb1938e474564a3a76279a1a0a511f74a750))
* Rollback compaction handling from _get_contents ([84f2f41](https://github.com/google/adk-python/commit/84f2f417f77ead3748c5bbeac7f144164b9a9416))
* Set `max_output_tokens` for the agent builder ([2e2d61b](https://github.com/google/adk-python/commit/2e2d61b6fecb90cd474d6f51255678ff74b67a9b))
* Set default response modality to AUDIO in run_session ([68402bd](https://github.com/google/adk-python/commit/68402bda49083f2d56f8e8488fe13aa58b3bc18c))
* Update remote_a2a_agent to better handle streaming events and avoid duplicate responses ([8e5f361](https://github.com/google/adk-python/commit/8e5f36126498f751171bb2639c7f5a9e7dca2558))
* Update the load_artifacts tool so that the model can reliably call it for follow up questions about the same artifact ([238472d](https://github.com/google/adk-python/commit/238472d083b5aa67551bde733fc47826ff062679))
* Fix VertexAiSessionService base_url override to preserve initialized http_options ([8110e41](https://github.com/google/adk-python/commit/8110e41b36cceddb8b92ba17cffaacf701706b36), [c51ea0b](https://github.com/google/adk-python/commit/c51ea0b52e63de8e43d3dccb24f9d20987784aa5))
* Handle `App` instances returned by `agent_loader.load_agent` ([847df16](https://github.com/google/adk-python/commit/847df1638cbf1686aa43e8e094121d4e23e40245))
### Improvements
* Migrate VertexAiSessionService to use Agent Engine SDK ([90d4c19](https://github.com/google/adk-python/commit/90d4c19c5115c7af361effa8e12c248225ccf6ab))
* Migrate VertexAiMemoryBankService to use Agent Engine SDK ([d1efc84](https://github.com/google/adk-python/commit/d1efc8461e82fc31df940b701f1d1b5422214296), [97b950b](https://github.com/google/adk-python/commit/97b950b36b9c16467f0f42216b2dc8395346d7fe), [83fd045](https://github.com/google/adk-python/commit/83fd0457188decdabeae58b4e8be25daa89f2943))
* Add support for resolving $ref and $defs in OpenAPI schemas ([a239716](https://github.com/google/adk-python/commit/a239716930c72a0dbd2ccabeea69be46110ca48d))
### Documentation
* Update BigQuery samples README ([3021266](https://github.com/google/adk-python/commit/30212669ff61f3cbd6603c3dceadfbcc4cec42f8))
## [1.15.1](https://github.com/google/adk-python/compare/v1.15.0...v1.15.1) (2025-09-26)
### Bug Fixes
* Fix the deployment failure for Agent Engine ([e172811](https://github.com/google/adk-python/commit/e172811bc7173b9004572f2a2afc7024145d7713))
## [1.15.0](https://github.com/google/adk-python/compare/v1.14.1...v1.15.0) (2025-09-24)
### Features
* **[Core]**
* Adding the ContextFilterPlugin ([a06bf27](https://github.com/google/adk-python/commit/a06bf278cbc89f521c187ed51b032d82ffdafe2d))
* Adds plugin to save artifacts for issue [#2176](https://github.com/google/adk-python/issues/2176) ([657369c](https://github.com/google/adk-python/commit/657369cffe142ef3745cd5950d0d24a49f42f7fd))
* Expose log probs of candidates in LlmResponse ([f7bd3c1](https://github.com/google/adk-python/commit/f7bd3c111c211e880d7c1954dd4508b952704c68))
* **[Context Caching]**
* Support context caching ([c66245a](https://github.com/google/adk-python/commit/c66245a3b80192c16cb67ee3194f82c9a7c901e5))
- Support explicit context caching auto creation and lifecycle management.
Usage: `App(root_agent=..., plugins=..., context_cache_config=...)`
* Support non-text content in static instruction ([61213ce](https://github.com/google/adk-python/commit/61213ce4d4c10f7ecaf6ddb521672059cee27942))
* Support static instructions ([9be9cc2](https://github.com/google/adk-python/commit/9be9cc2feee92241fd2fbf9dea3a42de5a78e9ce))
- Support static instruction that won't change, put at the beginning of
the instruction.
Static instruction support inline_data and file_data as contents.
Dynamic instruction moved to the end of LlmRequest, increasing prefix
caching matching size.
Usage:
`LlmAgent(model=...,static_instruction =types.Content(parts=...), ... )`
* **[Observability]**
* Add --otel_to_cloud experimental support ([1ae0b82](https://github.com/google/adk-python/commit/1ae0b82f5602a57ad1ca975ca0b7c85003d1a28a), [b131268](https://github.com/google/adk-python/commit/b1312680f4ea9f21c3246a1d24392619643d71f5), [7870480](https://github.com/google/adk-python/commit/7870480c63bb4fc08cfb3cabc0e1f0458f0e85bd))
* Add GenAI Instrumentation if --otel_to_cloud is enabled ([cee365a](https://github.com/google/adk-python/commit/cee365a13d0d1b1f2be046c1cc29e24a8d1fdbcc))
* Support standard OTel env variables for exporter endpoints ([f157b2e](https://github.com/google/adk-python/commit/f157b2ee4caf4055e78f4657254e45913895f5de))
* Temporarily disable Cloud Monitoring integration in --otel_to_cloud ([3b80337](https://github.com/google/adk-python/commit/3b80337faf427460e4743e25dbb92578f823513f))
* **[Services]**
* Add endpoint to generate memory from session ([2595824](https://github.com/google/adk-python/commit/25958242db890b4d2aac8612f7f7cfbb561727fa))
* **[Tools]**
* Add Google Maps Grounding Tool to ADK ([6b49391](https://github.com/google/adk-python/commit/6b493915469ecb42068e24818ab547b0856e4709))
* **MCP:** Initialize tool_name_prefix in MCPToolse ([86dea5b](https://github.com/google/adk-python/commit/86dea5b53ac305367283b7e353b60d0f4515be3b))
* **[Evals]**
* Data model for storing App Details and data model for steps ([01923a9](https://github.com/google/adk-python/commit/01923a9227895906ca8ae32712d65b178e2cd7d5))
* Adds Rubric based final response evaluator ([5a485b0](https://github.com/google/adk-python/commit/5a485b01cd64cb49735e13ebd5e7fa3da02cd85f))
* Populate AppDetails to each Invocation ([d486795](https://github.com/google/adk-python/commit/d48679582de91050ca9c5106402319be9a8ae7e8))
* **[Samples]**
* Make the bigquery sample agent run with ADC out-of-the-box ([10cf377](https://github.com/google/adk-python/commit/10cf37749417856e394e62896231e41b13420f18))
### Bug Fixes
* Close runners after running eval ([86ee6e3](https://github.com/google/adk-python/commit/86ee6e3fa3690148d60358fc3dacb0e0ab40942b))
* Filter out thought parts when saving agent output to state ([632bf8b](https://github.com/google/adk-python/commit/632bf8b0bcf18ff4e4505e4e5f4c626510f366a2))
* Ignore empty function chunk in LiteLlm streaming response ([8a92fd1](https://github.com/google/adk-python/commit/8a92fd18b600da596c22fd80c6148511a136dfd0))
* Introduces a `raw_mcp_tool` method in `McpTool` to provide direct access to the underlying MCP tool ([6158075](https://github.com/google/adk-python/commit/6158075a657f8fe0835679e509face6191905403))
* Make a copy of the `columns` instead of modifying it in place ([aef1ee9](https://github.com/google/adk-python/commit/aef1ee97a55a310f3959d475b8d7d6bc3915ae48))
* Prevent escaping of Latin characters in LLM response ([c9ea80a](https://github.com/google/adk-python/commit/c9ea80af28e586c9cc1f643b365cdba82f80c700))
* Retain the consumers and transport registry when recreating the ClientFactory in remote_a2a_agent.py ([6bd33e1](https://github.com/google/adk-python/commit/6bd33e1be36f741a6ed0514197550f9f336262ed))
* Remove unsupported 'type': 'unknown' in test_common.py for fastapi 0.117.1 ([3745221](https://github.com/google/adk-python/commit/374522197fa6843f786bfd12d17ce0fc20461dfd))
### Documentation
* Correct the documentation of `after_agent_callback` ([b9735b2](https://github.com/google/adk-python/commit/b9735b2193267645781b268231d63c23c6fec654))
## [1.14.1](https://github.com/google/adk-python/compare/v1.14.0...v1.14.1) (2025-09-12)
### Bug Fixes
@@ -10,22 +132,22 @@
### Features
* [A2A]
* **[A2A]**
* Allow users to pass their own agent card to to_a2a method [a1679da](https://github.com/google/adk-python/commit/a1679dae3fef70f1231afba3e97d45b59c314ae3)
* Allow custom part converters in A2A classes [b05fef9](https://github.com/google/adk-python/commit/b05fef9ba71f95ab2658eb4eb5608c141d49f82f)
* [Tools]
* **[Tools]**
* Allow setting agent/application name and compute project for BigQuery tools [11a2ffe](https://github.com/google/adk-python/commit/11a2ffe35adbae977b49ceccf0e76e20c6dc90b6)
* Add BigQuery forecast tool [0935a40](https://github.com/google/adk-python/commit/0935a40011a3276ee7f7fa3b91678b4d63f22ba5)
* Add GkeCodeExecutor for sandboxed code execution on GKE [72ff9c6](https://github.com/google/adk-python/commit/72ff9c64a291aebb50b07446378f375e58882c4e)
* Add a tool confirmation flow that can guard tool execution with explicit confirmation and custom input [a17bcbb](https://github.com/google/adk-python/commit/a17bcbb2aa0f5c6aca460db96ed1cb7dd86fef84)
* Add audience and prompt as configurable for OAuth flows [edda922](https://github.com/google/adk-python/commit/edda922791f15ac37830ed95ebf76b9f836d9db4)
* Allow user specify embedding model for file retrieval [67f23df](https://github.com/google/adk-python/commit/67f23df25ad47aff3cb36d0fc9ce2c9b97bde09b)
* [Core]
* **[Core]**
* Allow all possible values for `agent_class` field in all Agent Configs [3bc2d77](https://github.com/google/adk-python/commit/3bc2d77b4d180e9c42b30d4d1ce580aa75abe501)
* Allow agent loader to load built-in agents from special directories in adk folder [578fad7](https://github.com/google/adk-python/commit/578fad7034a7b369a490ad0afa4dd2820463c22d)
* Upgrade ADK runner to use App in addition to root_agent [4df79dd](https://github.com/google/adk-python/commit/4df79dd5c92d96096d031b26470458d0bca79a79)
* Allow inject artifact into instructions [bb4cfde](https://github.com/google/adk-python/commit/bb4cfdec12370955d4038d6d8c86e04691f2308e)
* [Misc] Create an initial ADK release analyzer agent to find the doc updates needed between releases [e3422c6](https://github.com/google/adk-python/commit/e3422c616d18ec3850454ee83f2ef286198543ec)
* **[Misc]** Create an initial ADK release analyzer agent to find the doc updates needed between releases [e3422c6](https://github.com/google/adk-python/commit/e3422c616d18ec3850454ee83f2ef286198543ec)
### Bug Fixes
+38 -3
View File
@@ -25,14 +25,44 @@
Agent Development Kit (ADK) is a flexible and modular framework for developing and deploying AI agents. While optimized for Gemini and the Google ecosystem, ADK is model-agnostic, deployment-agnostic, and is built for compatibility with other frameworks. ADK was designed to make agent development feel more like software development, to make it easier for developers to create, deploy, and orchestrate agentic architectures that range from simple tasks to complex workflows.
---
## 🔥 ADK's very first community call on Oct 15
Join our ADK Community Call! Our first virtual community call is on Oct 15!
Meet our team, and talk with us about our roadmap and how to contribute.
First Call Details:
Topic: ADK Roadmap
Date: October 15, 2025
Time: 9:30-10:30am PST
Meeting link:
[Join the call](http://meet.google.com/gjm-gfim-ctz)
Add to your calendar
[Event calendar invite](https://calendar.google.com/calendar/event?action=TEMPLATE&tmeid=MDUydWo1dHV1dHFtNzJuM3E0bmEyMW12ZnZfMjAyNTEwMTVUMTYzMDAwWiBjXzljNWVjODhhMmQyYWU5YjY5Mzk4ODU1MGZkNDA5MjVmYjgxYjM4MTI1NGNjYTgzNmRkMjMwNzRiMjNmYzcyZDVAZw&tmsrc=c_9c5ec88a2d2ae9b693988550fd40925fb81b381254cca836dd23074b23fc72d5%40group.calendar.google.com), [.ics file](https://calendar.google.com/calendar/ical/c_9c5ec88a2d2ae9b693988550fd40925fb81b381254cca836dd23074b23fc72d5%40group.calendar.google.com/public/basic.ics), [ADK community calendar](https://calendar.google.com/calendar/embed?src=c_9c5ec88a2d2ae9b693988550fd40925fb81b381254cca836dd23074b23fc72d5%40group.calendar.google.com&ctz=America%2FLos_Angeles), [ADK Community Call RSVP](https://google.qualtrics.com/jfe/form/SV_3K0RJZ64H1BexqS)
Agenda:
[Julia] ADK Roadmap
[ Bo & Hangfei] Eng Deep Dive: Context Caching
[Kris] How to Contribute
[Shubham] Upcoming Events
---
## 🔥 What's new
- **Agent Config**: Build agents without code. Check out the
[Agent Config](https://google.github.io/adk-docs/agents/config/) feature.
- **Context compaction**: Supports context compaction to reduce context length. Here is a [sample](https://github.com/google/adk-python/blob/main/contributing/samples/hello_world_app/agent.py#L156) and [compaction config](https://github.com/google/adk-python/blob/main/src/google/adk/apps/app.py#L51).
- **Tool Confirmation**: A [tool confirmation flow(HITL)](https://google.github.io/adk-docs/tools/confirmation/) that can guard tool execution with explicit confirmation and custom input
- **Resumability**: Support pause and resume an invocation in ADK.
- **ReflectRetryToolPlugin**: Add [`ReflectRetryToolPlugin`](https://github.com/google/adk-python/blob/main/src/google/adk/plugins/reflect_retry_tool_plugin.py) to reflect from errors and retry with different arguments when tool errors.
- **Search tool**: Support using Google built-in search and built-in `VertexAiSearchTool` with other tools in the same agent.
## ✨ Key Features
@@ -43,6 +73,11 @@ Agent Development Kit (ADK) is a flexible and modular framework for developing a
- **Code-First Development**: Define agent logic, tools, and orchestration
directly in Python for ultimate flexibility, testability, and versioning.
- **Agent Config**: Build agents without code. Check out the
[Agent Config](https://google.github.io/adk-docs/agents/config/) feature.
- **Tool Confirmation**: A [tool confirmation flow(HITL)](https://google.github.io/adk-docs/tools/confirmation/) that can guard tool execution with explicit confirmation and custom input.
- **Modular Multi-Agent Systems**: Design scalable applications by composing
multiple specialized agents into flexible hierarchies.
@@ -24,7 +24,9 @@ from google.adk.agents.readonly_context import ReadonlyContext
from google.adk.models import BaseLlm
from google.adk.tools import AgentTool
from google.adk.tools import FunctionTool
from google.genai import types
from .sub_agents.adk_knowledge_agent import create_adk_knowledge_agent
from .sub_agents.google_search_agent import create_google_search_agent
from .sub_agents.url_context_agent import create_url_context_agent
from .tools.cleanup_unused_files import cleanup_unused_files
@@ -32,7 +34,6 @@ from .tools.delete_files import delete_files
from .tools.explore_project import explore_project
from .tools.read_config_files import read_config_files
from .tools.read_files import read_files
from .tools.resolve_root_directory import resolve_root_directory
from .tools.search_adk_source import search_adk_source
from .tools.write_config_files import write_config_files
from .tools.write_files import write_files
@@ -58,9 +59,7 @@ class AgentBuilderAssistant:
Configured LlmAgent with embedded ADK AgentConfig schema
"""
# Load full ADK AgentConfig schema directly into instruction context
instruction = AgentBuilderAssistant._load_instruction_with_schema(
model, working_directory
)
instruction = AgentBuilderAssistant._load_instruction_with_schema(model)
# TOOL ARCHITECTURE: Hybrid approach using both AgentTools and FunctionTools
#
@@ -70,9 +69,14 @@ class AgentBuilderAssistant:
# - Maintains compatibility with existing ADK tool ecosystem
# Built-in ADK tools wrapped as sub-agents
adk_knowledge_agent = create_adk_knowledge_agent()
google_search_agent = create_google_search_agent()
url_context_agent = create_url_context_agent()
agent_tools = [AgentTool(google_search_agent), AgentTool(url_context_agent)]
agent_tools = [
AgentTool(adk_knowledge_agent),
AgentTool(google_search_agent),
AgentTool(url_context_agent),
]
# CUSTOM FUNCTION TOOLS: Agent Builder specific capabilities
#
@@ -88,8 +92,6 @@ class AgentBuilderAssistant:
write_config_files
), # Write/validate multiple YAML configs
FunctionTool(explore_project), # Analyze project structure
# Working directory context tools
FunctionTool(resolve_root_directory),
# File management tools (multi-file support)
FunctionTool(read_files), # Read multiple files
FunctionTool(write_files), # Write multiple files
@@ -112,6 +114,9 @@ class AgentBuilderAssistant:
instruction=instruction,
model=model,
tools=all_tools,
generate_content_config=types.GenerateContentConfig(
max_output_tokens=8192,
),
)
return agent
@@ -125,7 +130,6 @@ class AgentBuilderAssistant:
# ADK AgentConfig schema loading with caching and error handling.
schema_content = load_agent_config_schema(
raw_format=True, # Get as JSON string
escape_braces=True, # Escape braces for template embedding
)
# Format as indented code block for instruction embedding
@@ -147,7 +151,6 @@ class AgentBuilderAssistant:
@staticmethod
def _load_instruction_with_schema(
model: Union[str, BaseLlm],
working_directory: Optional[str] = None,
) -> Callable[[ReadonlyContext], str]:
"""Load instruction template and embed ADK AgentConfig schema content."""
instruction_template = (
@@ -162,19 +165,43 @@ class AgentBuilderAssistant:
else getattr(model, "model_name", str(model))
)
# Fill the instruction template with ADK AgentConfig schema content and default model
instruction_text = instruction_template.format(
schema_content=schema_content, default_model=model_str
)
# Return a function that accepts ReadonlyContext and returns the instruction
def instruction_provider(context: ReadonlyContext) -> str:
return AgentBuilderAssistant._compile_instruction_with_context(
instruction_text, context, working_directory
# Extract project folder name from session state
project_folder_name = AgentBuilderAssistant._extract_project_folder_name(
context
)
# Fill the instruction template with all variables
instruction_text = instruction_template.format(
schema_content=schema_content,
default_model=model_str,
project_folder_name=project_folder_name,
)
return instruction_text
return instruction_provider
@staticmethod
def _extract_project_folder_name(context: ReadonlyContext) -> str:
"""Extract project folder name from session state using resolve_file_path."""
from .utils.resolve_root_directory import resolve_file_path
session_state = context._invocation_context.session.state
# Use resolve_file_path to get the full resolved path for "."
# This handles all the root_directory resolution logic consistently
resolved_path = resolve_file_path(".", session_state)
# Extract the project folder name from the resolved path
project_folder_name = resolved_path.name
# Fallback to "project" if we somehow get an empty name
if not project_folder_name:
project_folder_name = "project"
return project_folder_name
@staticmethod
def _load_embedded_schema_instruction_template() -> str:
"""Load instruction template for embedded ADK AgentConfig schema mode."""
@@ -187,70 +214,3 @@ class AgentBuilderAssistant:
with open(template_path, "r", encoding="utf-8") as f:
return f.read()
@staticmethod
def _compile_instruction_with_context(
instruction_text: str,
context: ReadonlyContext,
working_directory: Optional[str] = None,
) -> str:
"""Compile instruction with session context and working directory information.
This method enhances instructions with:
1. Working directory information for path resolution
2. Session-based root directory binding if available
Args:
instruction_text: Base instruction text
context: ReadonlyContext from the agent session
working_directory: Optional working directory for path resolution
Returns:
Enhanced instruction text with context information
"""
import os
# Get working directory (use provided or current working directory)
actual_working_dir = working_directory or os.getcwd()
# Check for existing root directory in session state
session_root_directory = context._invocation_context.session.state.get(
"root_directory"
)
# Compile additional context information
context_info = f"""
## SESSION CONTEXT
**Working Directory**: `{actual_working_dir}`
- Use this as the base directory for path resolution when calling resolve_root_directory
- Pass this as the working_directory parameter to resolve_root_directory tool
"""
if session_root_directory:
context_info += f"""**Established Root Directory**: `{session_root_directory}`
- This session is bound to root directory: {session_root_directory}
- DO NOT ask the user for root directory - use this established path
- All agent building should happen within this root directory
- If user wants to work in a different directory, ask them to start a new chat session
"""
else:
context_info += f"""**Root Directory**: Not yet established
- You MUST ask the user for their desired root directory first
- Use resolve_root_directory tool to validate the path
- Once confirmed, this session will be bound to that root directory
"""
context_info += """**Session Binding Rules**:
- Each chat session is bound to ONE root directory
- Once established, work only within that root directory
- To switch directories, user must start a new chat session
- Always verify paths using resolve_root_directory tool before creating files
"""
return instruction_text + context_info
@@ -29,11 +29,16 @@ You have access to the complete ADK AgentConfig schema embedded in your context:
Always reference this schema when creating configurations to ensure compliance.
## Current Context
**Current Project Folder Name**: `{project_folder_name}`
## Workflow Guidelines
### 1. Discovery Phase
- **DETERMINE USER INTENT FIRST**:
* **INFORMATIONAL QUESTIONS** (Answer directly WITHOUT asking for root directory):
**STEP 1: DETERMINE USER INTENT FIRST**
* **INFORMATIONAL QUESTIONS** (Answer directly):
- "Could you find me examples of..." / "Find me samples of..."
- "Show me how to..." / "How do I..."
- "What is..." / "What are..." / "Explain..."
@@ -41,85 +46,126 @@ Always reference this schema when creating configurations to ensure compliance.
- "I'm looking for information about..." / "I need to understand..."
- Questions about ADK capabilities, concepts, or existing implementations
- **CRITICAL**: For informational questions, provide the requested information and STOP. Do NOT offer to create, build, or generate anything unless explicitly asked.
* **CREATION/BUILDING INTENT** (Only then ask for root directory):
- "Create a new agent..." / "Build me an agent..."
* **CREATION/BUILDING INTENT**:
- "Create a new agent..." / "Build me an agent..."
- "Generate an agent..." / "Implement an agent..."
- "Update my agent..." / "Modify my agent..." / "Change my agent..."
- "I want to create..." / "Help me build..." / "Help me update..."
- "Set up a project..." / "Make me an agent..."
**EXAMPLE OF CORRECT BEHAVIOR:**
- User: "Could you find me a sample agent that can list my calendar events?"
- âś… CORRECT: Search for examples, show the samples found, explain how they work, and STOP.
- ❌ WRONG: "Before I proceed with creating an agent..." or asking for root directory.
- **ROOT DIRECTORY ESTABLISHMENT** (Only for Creation/Building):
* **FIRST**: Check SESSION CONTEXT section below for "Established Root Directory"
* **IF ESTABLISHED**: Use the existing session root directory - DO NOT ask again
* **IF NOT ESTABLISHED**: Ask user for root directory to establish working context
- **MODEL PREFERENCE**: Always ask for explicit model confirmation when LlmAgent(s) will be needed
* **When to ask**: After analyzing requirements and deciding that LlmAgent is needed for the solution
* **MANDATORY CONFIRMATION**: Say "Please confirm what model you want to use" - do NOT assume or suggest defaults
* **EXAMPLES**: "gemini-2.5-flash", "gemini-2.5-pro", etc.
* **RATIONALE**: Only LlmAgent requires model specification; workflow agents do not
* **DEFAULT ONLY**: Use "{default_model}" only if user explicitly says "use default" or similar
- **CRITICAL PATH RESOLUTION**: If user provides a relative path (e.g., `./config_agents/roll_and_check`):
* **FIRST**: Call `resolve_root_directory` to get the correct absolute path
* **VERIFY**: The resolved path matches user's intended location
* **EXAMPLE**: `./config_agents/roll_and_check` should resolve to `/Users/user/Projects/adk-python/config_agents/roll_and_check`, NOT `/config_agents/roll_and_check`
**STEP 2: UNDERSTAND REQUIREMENTS**
- Understand the user's goals and requirements through targeted questions
- Explore existing project structure using the RESOLVED ABSOLUTE PATH
- Explore existing project structure using the explore_project tool
- Identify integration needs (APIs, databases, external services)
- Analyze which agent types are needed (LlmAgent, SequentialAgent, ParallelAgent, LoopAgent)
### 2. Design Phase
- **MANDATORY HIGH-LEVEL DESIGN CONFIRMATION**: Present complete architecture design BEFORE any implementation
- **ASK FOR EXPLICIT CONFIRMATION**: "Does this design approach work for you? Should I proceed with implementation?"
- **INCLUDE IN DESIGN PRESENTATION**:
* Agent types and their roles
* Tool requirements and purposes
* File structure overview
* Model selection (if applicable)
- **WAIT FOR USER CONFIRMATION**: Do not proceed to implementation until user confirms the design
- **NO FILE CONTENT**: Do not show any file content during design phase - only architecture overview
**STEP 3: MODEL SELECTION (COMPLETE BEFORE MOVING TO DESIGN PHASE)**
- **CRITICAL TIMING**: Ask for model selection IMMEDIATELY after determining LlmAgent is needed, BEFORE presenting any design
- **MANDATORY CONFIRMATION**: Say "Please confirm what model you want to use" - do NOT assume or suggest defaults
- **EXAMPLES**: "gemini-2.5-flash", "gemini-2.5-pro", etc.
- **RATIONALE**: Only LlmAgent requires model specification; workflow agents do not
- **DEFAULT MODEL**: If user says "use default" or "proceed with default model", use: {default_model}
* This is the actual model name, NOT the literal string "default"
* The default model for this session is: {default_model}
- **WORKFLOW**: Complete all Discovery steps (including this model selection) → Then proceed to Design Phase with model already chosen
### 2. Design Phase
- **NOTE**: Model selection has ALREADY been completed in Discovery Phase (Step 3) - do NOT ask for model again
**PRESENT COMPLETE IMPLEMENTATION** - Show everything the user needs to review in one place:
* High-level architecture overview (agent types and their roles)
* Selected model (already chosen in Discovery Phase)
* **Complete YAML configuration files** - Show full content of all YAML files
* **Complete Python files** - Show full content of all Python tool/callback files
* File structure with paths
- **SINGLE CONFIRMATION REQUIRED**: Ask ONCE after showing everything - "Should I proceed with creating these files?"
- **WAIT FOR USER CONFIRMATION**: Do not proceed to implementation until user confirms
- **ONE APPROVAL FOR EVERYTHING**: User reviews plan + all file contents, then gives single approval
- **WORKFLOW**: Model already selected → Present plan + all file contents → ONE "Should I proceed?" → Execute without asking again
### 3. Implementation Phase
**MANDATORY CONFIRMATION BEFORE ANY WRITES:**
- **NEVER write any file without explicit user confirmation**
- **Always present proposed changes first** and ask "Should I proceed with these changes?"
- **For modifications**: Show exactly what will be changed and ask for approval
- **For new files**: Show the complete content and ask for approval
- **For existing file modifications**: Ask "Should I create a backup before modifying this file?"
- **Use backup_existing parameter**: Set to True only if user explicitly requests backup
**NOTE: User has ALREADY approved everything in Design Phase - DO NOT ask for confirmation again**
**IMPLEMENTATION ORDER (CRITICAL - ONLY AFTER USER CONFIRMS DESIGN):**
**🚨 PATH DISPLAY RULE**: ALWAYS show relative paths in responses (e.g., `root_agent.yaml`, `tools/dice_tool.py`) instead of full absolute paths
**STEP 1: YAML CONFIGURATION FILES FIRST**
1. Generate all YAML configuration files
2. Present complete YAML content to user for confirmation
3. Ask: "Should I create these YAML configuration files?"
4. Only proceed after user confirmation
**🚨 CRITICAL TOOL PATH RULE**:
- **NEVER include project folder name in tool calls**
- **Use paths like `root_agent.yaml`, NOT `{project_folder_name}/root_agent.yaml`**
- **Tools automatically resolve relative to project folder**
**STEP 2: PYTHON FILES SECOND**
1. Generate Python tool/callback files
2. Present complete Python content to user for confirmation
3. Ask: "Should I create these Python files?"
4. Only proceed after user confirmation
1. **Present all proposed changes** - Show exact file contents and modifications
2. **Get explicit user approval** - Wait for "yes" or "proceed" before any writes
3. **Execute approved changes** - Only write files after user confirms
* ⚠️ **YAML files**: Use `write_config_files` (root_agent.yaml, etc.)
* ⚠️ **Python files**: Use `write_files` (tools/*.py, etc.)
4. **Clean up unused files** - Use cleanup_unused_files and delete_files to remove obsolete tool files
**IMPLEMENTATION ORDER (Execute immediately after Design Phase approval):**
**STEP 1: WRITE YAML CONFIGURATION FILES**
1. Write all YAML configuration files using `write_config_files`
* Use paths like `"root_agent.yaml"` (NO project folder prefix)
* Files were already shown and approved in Design Phase
**STEP 2: WRITE PYTHON FILES**
1. Write Python tool/callback files using `write_files`
* Use paths like `"tools/dice_tool.py"` (NO project folder prefix)
* Files were already shown and approved in Design Phase
**STEP 3: CLEANUP**
1. Use `cleanup_unused_files` and `delete_files` to remove obsolete tool files if needed
**For file modifications (updates to existing files):**
- Show exactly what will be changed and ask for approval
- Ask "Should I create a backup before modifying this file?" if modifying existing files
- Use backup_existing parameter: Set to True only if user explicitly requests backup
**YAML Configuration Requirements:**
- Main agent file MUST be named `root_agent.yaml`
- **Sub-agent placement**: Place ALL sub-agent YAML files in the root folder, NOT in `sub_agents/` subfolder
- **Sub-agent placement**: Place ALL sub-agent YAML files in the main project folder, NOT in `sub_agents/` subfolder
- Tool paths use format: `project_name.tools.module.function_name` (must start with project folder name, no `.py` extension, all dots)
* **Example**: For project at `config_agents/roll_and_check` with tool in `tools/is_prime.py`, use: `roll_and_check.tools.is_prime.is_prime`
* **Pattern**: `{{{{project_folder_name}}}}.tools.{{{{module_name}}}}.{{{{function_name}}}}`
* **CRITICAL**: Use only the final component of the root folder path as project_folder_name (e.g., for `./config_based/roll_and_check`, use `roll_and_check` not `config_based.roll_and_check`)
* **Pattern**: `{{project_folder_name}}.tools.{{module_name}}.{{function_name}}`
* **🚨 CRITICAL TOOL NAMING RULE**: Use ONLY the FINAL/LAST component of the project folder path as project_folder_name
- âś… CORRECT: For project path `projects/workspace/my_agent`, use `my_agent` (last component)
- ❌ WRONG: `projects.workspace.my_agent` (full dotted path)
- âś… CORRECT: For `./config_based/roll_and_check`, use `roll_and_check` (last component)
- ❌ WRONG: `config_based.roll_and_check` (includes parent directories)
* **Remember**: Always extract just the folder name after the last slash/separator
- No function declarations in YAML (handled automatically by ADK)
**🚨 CRITICAL: Built-in Tools vs Custom Tools**
**ADK Built-in Tools** (use directly, NO custom Python file needed):
- **Naming**: Use simple name WITHOUT dots (e.g., `google_search`, NOT `google.adk.tools.google_search`)
- **No custom code**: Do NOT create Python files for built-in tools
- **Available built-in tools**:
* `google_search` - Google Search tool
* `enterprise_web_search` - Enterprise web search
* `google_maps_grounding` - Google Maps grounding
* `url_context` - URL context fetching
* `VertexAiSearchTool` - Vertex AI Search (class name)
* `exit_loop` - Exit loop control
* `get_user_choice` - User choice interaction
* `load_artifacts` - Load artifacts
* `load_memory` - Load memory
* `preload_memory` - Preload memory
* `transfer_to_agent` - Transfer to another agent
**Example - Built-in Tool Usage (CORRECT):**
```yaml
tools:
- name: google_search
- name: url_context
```
**Example - Built-in Tool Usage (WRONG):**
```yaml
tools:
- name: cb.tools.google_search_tool.google_search_tool # ❌ WRONG - treating built-in as custom
```
**DO NOT create Python files like `tools/google_search_tool.py` for built-in tools!**
**Custom Tools** (require Python implementation):
- **Naming**: Use dotted path: `{{project_folder_name}}.tools.{{module_name}}.{{function_name}}`
- **Require Python file**: Must create actual Python file in `tools/` directory
- **Example**: `my_project.tools.dice_tool.roll_dice` → requires `tools/dice_tool.py` with `roll_dice()` function
**TOOL IMPLEMENTATION STRATEGY:**
- **For simple/obvious tools**: Implement them directly with actual working code
* Example: dice rolling, prime checking, basic math, file operations
@@ -166,9 +212,10 @@ Always reference this schema when creating configurations to ensure compliance.
### Core Agent Building Tools
#### Configuration Management (MANDATORY FOR .yaml/.yml FILES)
- **write_config_files**: ⚠️ REQUIRED for ALL YAML files (root_agent.yaml, sub-agents/*.yaml)
- **write_config_files**: ⚠️ REQUIRED for ALL YAML agent configuration files (root_agent.yaml, any sub-agent YAML files in main project folder)
* Validates YAML syntax and ADK AgentConfig schema compliance
* Example: `write_config_files({{"./project/root_agent.yaml": yaml_content}})`
* Example: `write_config_files({{"./project/root_agent.yaml": yaml_content, "./project/researcher_agent.yaml": sub_agent_content}})`
* **CRITICAL**: All agent YAML files must be in the root project folder, NOT in a sub_agents/ subdirectory
- **read_config_files**: Read and parse multiple YAML configuration files with validation and metadata extraction
- **config_file_reader**: Legacy function (use read_config_files instead)
- **config_file_writer**: Legacy function (use write_config_files instead)
@@ -182,11 +229,12 @@ Always reference this schema when creating configurations to ensure compliance.
#### Project Organization
- **explore_project**: Explore project structure and suggest conventional file paths
- **get_working_directory_info**: Get current working directory and execution context information
- **resolve_root_directory**: Resolve path issues when execution context differs from user's working directory
### ADK Knowledge and Research Tools
#### Remote Semantic Search
- **adk_knowledge_agent**: Search ADK knowledge base for ADK examples, patterns, and documentation
#### Web-based Research
- **google_search_agent**: Search web for ADK examples, patterns, and documentation (returns full page content as results)
- **url_context_agent**: Fetch content from specific URLs when mentioned in search results or user queries (use only when specific URLs need additional fetching)
@@ -200,8 +248,10 @@ Always reference this schema when creating configurations to ensure compliance.
* Follow up with **read_files** to get complete file contents
**Research Workflow for ADK Questions:**
Mainly rely on **adk_knowledge_agent** for ADK questions. Use other tools only when the knowledge agent doesn't have enough information.
1. **search_adk_source** - Find specific code patterns with regex
2. **read_files** - Read complete source files for detailed analysis
2. **read_files** - Read complete source files for detailed analysis
3. **google_search_agent** - Find external examples and documentation
4. **url_context_agent** - Fetch specific GitHub files or documentation pages
@@ -217,6 +267,10 @@ Always reference this schema when creating configurations to ensure compliance.
**Research Tool Usage Patterns:**
**Default Research Tool:**
Use **adk_knowledge_agent** as the primary research tool for ADK questions.
Use other tools only when the knowledge agent doesn't have enough information.
**For ADK Code Questions (NEW - Preferred Method):**
1. **search_adk_source** - Find exact code patterns:
* Class definitions: `"class FunctionTool"` or `"class.*Agent"`
@@ -258,22 +312,94 @@ Always reference this schema when creating configurations to ensure compliance.
6. **Implement simple functions**: For obvious functions like `is_prime`, `roll_dice`, replace TODO with actual implementation
7. **Keep TODO for complex**: For complex business logic, leave TODO comments
8. **Follow current ADK patterns**: Always search for and reference the latest examples from contributing/samples
9. **Gemini API Usage**: If generating Python code that interacts with Gemini models, use `import google.genai as genai`, not `google.generativeai`.
### 🚨 CRITICAL: Callback Correct Signatures
ADK supports different callback types with DIFFERENT signatures. Use FUNCTION-based callbacks (never classes):
## 1. Agent Callbacks (before_agent_callbacks / after_agent_callbacks)
**âś… CORRECT Agent Callback:**
```python
from typing import Optional
from google.genai import types
from google.adk.agents.callback_context import CallbackContext
def content_filter_callback(callback_context: CallbackContext) -> Optional[types.Content]:
"""After agent callback to filter sensitive content."""
# Access the response content through callback_context
if hasattr(callback_context, 'response') and callback_context.response:
response_text = str(callback_context.response)
if "confidential" in response_text.lower():
filtered_text = response_text.replace("confidential", "[FILTERED]")
return types.Content(parts=[types.Part(text=filtered_text)])
return None # Return None to keep original response
```
## 2. Model Callbacks (before_model_callbacks / after_model_callbacks)
**âś… CORRECT Model Callback:**
```python
from typing import Optional
from google.adk.models.llm_request import LlmRequest
from google.adk.models.llm_response import LlmResponse
from google.adk.agents.callback_context import CallbackContext
def log_model_request(callback_context: CallbackContext, request: LlmRequest) -> Optional[LlmResponse]:
"""Before model callback to log requests."""
print(f"Model request: {{request.contents}}")
return None # Return None to proceed with original request
def modify_model_response(callback_context: CallbackContext, response: LlmResponse) -> Optional[LlmResponse]:
"""After model callback to modify response."""
# Modify response if needed
return response # Return modified response or None for original
```
## 3. Tool Callbacks (before_tool_callbacks / after_tool_callbacks)
**âś… CORRECT Tool Callback:**
```python
from typing import Any, Dict, Optional
from google.adk.tools.base_tool import BaseTool
from google.adk.tools.tool_context import ToolContext
def validate_tool_input(tool: BaseTool, tool_args: Dict[str, Any], tool_context: ToolContext) -> Optional[Dict]:
"""Before tool callback to validate input."""
# Validate or modify tool arguments
if "unsafe_param" in tool_args:
del tool_args["unsafe_param"]
return tool_args # Return modified args or None for original
def log_tool_result(tool: BaseTool, tool_args: Dict[str, Any], tool_context: ToolContext, result: Dict) -> Optional[Dict]:
"""After tool callback to log results."""
print(f"Tool {{tool.name}} executed with result: {{result}}")
return None # Return None to keep original result
```
## Callback Signature Summary:
- **Agent Callbacks**: `(callback_context: CallbackContext) -> Optional[types.Content]`
- **Before Model**: `(callback_context: CallbackContext, request: LlmRequest) -> Optional[LlmResponse]`
- **After Model**: `(callback_context: CallbackContext, response: LlmResponse) -> Optional[LlmResponse]`
- **Before Tool**: `(tool: BaseTool, tool_args: Dict[str, Any], tool_context: ToolContext) -> Optional[Dict]`
- **After Tool**: `(tool: BaseTool, tool_args: Dict[str, Any], tool_context: ToolContext, result: Dict) -> Optional[Dict]`
## Important ADK Requirements
**File Naming & Structure:**
- Main configuration MUST be `root_agent.yaml` (not `agent.yaml`)
- Agent directories need `__init__.py` with `from . import agent`
- Agent directories need `__init__.py` with `from . import agent`
- **Tools directory MUST have `__init__.py`** - The `tools/` folder requires an empty `__init__.py` file to be a valid Python package (required for imports)
- Python files in agent directory, YAML at root level
**Tool Configuration:**
- Function tools: `project_name.tools.module.function_name` format (all dots, must start with project folder name)
- No `.py` extension in tool paths
- No function declarations needed in YAML
- **Critical**: Tool paths must include the project folder name as the first component (final component of root folder path only)
- **Critical**: Tool paths must include the project folder name as the first component (final component of project folder path only)
**ADK Agent Types and Model Field Rules:**
- **LlmAgent**: REQUIRES `model` field - this agent directly uses LLM for responses
- **LlmAgent**: REQUIRES `model` field (unless inherited from ancestor) - this agent directly uses LLM for responses
- **SequentialAgent**: NO `model` field - workflow agent that orchestrates other agents in sequence
- **ParallelAgent**: NO `model` field - workflow agent that runs multiple agents in parallel
- **LoopAgent**: NO `model` field - workflow agent that executes agents in a loop
@@ -282,42 +408,41 @@ Always reference this schema when creating configurations to ensure compliance.
**ADK AgentConfig Schema Compliance:**
- Always reference the embedded ADK AgentConfig schema to verify field requirements
- **MODEL FIELD RULES**:
* **LlmAgent**: `model` field is REQUIRED - Ask user for preference only when LlmAgent is needed, use "{default_model}" if not specified
* **LlmAgent**: `model` field is REQUIRED (unless inherited from ancestor) - Ask user for preference only when LlmAgent is needed, use {default_model} if user says to use default
* **Workflow Agents**: `model` field is FORBIDDEN - Remove model field entirely for Sequential/Parallel/Loop agents
- Optional fields: description, instruction, tools, sub_agents as defined in ADK AgentConfig schema
## Critical Path Handling Rules
## File Operation Guidelines
**NEVER assume relative path context** - Always resolve paths first!
**CRITICAL PATH RULE FOR TOOL CALLS**:
- **NEVER include the project folder name in paths when calling tools**
- **Tools automatically resolve paths relative to the project folder**
- **Use simple relative paths like `root_agent.yaml`, `tools/dice_tool.py`**
- **WRONG**: `{project_folder_name}/root_agent.yaml` (includes project folder name)
- **CORRECT**: `root_agent.yaml` (just the file path within project)
### For relative paths provided by users:
1. **ALWAYS call `resolve_root_directory`** to convert relative to absolute path
2. **Verify the resolved path** matches user's intended location
3. **Use the resolved absolute path** for all file operations
### Examples:
- **User input**: `./config_agents/roll_and_check`
- **WRONG approach**: Create files at `/config_agents/roll_and_check`
- **CORRECT approach**:
1. Call `resolve_root_directory("./config_agents/roll_and_check")`
2. Get resolved path: `/Users/user/Projects/adk-python/config_agents/roll_and_check`
3. Use the resolved absolute path for all operations
**Examples**:
- Current project folder: `basic`
- âś… **CORRECT tool calls**:
* `write_config_files({{"root_agent.yaml": "..."}})`
* `write_files({{"tools/dice_tool.py": "..."}})`
- ❌ **WRONG tool calls**:
* `write_config_files({{"basic/root_agent.yaml": "..."}})` (duplicates project folder!)
* This would create `projects/basic/basic/root_agent.yaml` instead of `projects/basic/root_agent.yaml`
## Success Criteria
### Design Phase Success:
1. Root folder path confirmed and analyzed with explore_project
2. Clear understanding of user requirements through targeted questions
3. Well-researched architecture based on proven ADK patterns
4. Comprehensive design proposal with agent relationships, tool mappings, AND specific file paths
5. User approval of both architecture and file structure before any implementation
1. Clear understanding of user requirements through targeted questions
2. Well-researched architecture based on proven ADK patterns
3. Comprehensive design proposal with agent relationships, tool mappings, AND specific file paths
4. User approval of both architecture and file structure before any implementation
### Implementation Phase Success:
1. Files created at exact paths specified in approved design
2. No redundant suggest_file_path calls for pre-approved paths
3. Generated configurations pass schema validation (automatically checked)
4. Follow ADK naming and organizational conventions
5. Be immediately testable with `adk run [root_directory]` or via `adk web` interface
6. Include clear, actionable instructions for each agent
7. Use appropriate tools for intended functionality
@@ -325,8 +450,8 @@ Always reference this schema when creating configurations to ensure compliance.
**Your primary role is to be a collaborative architecture consultant that follows an efficient, user-centric workflow:**
1. **Always ask for root folder first** - Know where to create the project
2. **Design with specific paths** - Include exact file locations in proposals
1. **Understand requirements first** - Know what the user wants to build
2. **Design the architecture** - Plan the agent structure and components
3. **Provide high-level architecture overview** - When confirming design, always include:
* Overall system architecture and component relationships
* Agent types and their responsibilities
@@ -337,14 +462,3 @@ Always reference this schema when creating configurations to ensure compliance.
6. **Focus on collaboration** - Ensure user gets exactly what they need with clear understanding
**This workflow eliminates inefficiencies and ensures users get well-organized, predictable file structures in their chosen location.**
## Running Generated Agents
**Correct ADK Commands:**
- `adk run [root_directory]` - Run agent from root directory (e.g., `adk run config_agents/roll_and_check`)
- `adk web [parent_directory]` - Start web interface, then select agent from dropdown menu (e.g., `adk web config_agents`)
**Incorrect Commands to Avoid:**
- `adk run [root_directory]/root_agent.yaml` - Do NOT specify the YAML file directly
- `adk web` without parent directory - Must specify the parent folder containing the agent projects
- Always use the project directory for `adk run`, and parent directory for `adk web`
@@ -14,7 +14,12 @@
"""Sub-agents for Agent Builder Assistant."""
from .adk_knowledge_agent import create_adk_knowledge_agent
from .google_search_agent import create_google_search_agent
from .url_context_agent import create_url_context_agent
__all__ = ['create_google_search_agent', 'create_url_context_agent']
__all__ = [
'create_adk_knowledge_agent',
'create_google_search_agent',
'create_url_context_agent',
]
@@ -0,0 +1,33 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Sub-agent for ADK Knowledge."""
from google.adk.agents.llm_agent import Agent
from google.adk.agents.remote_a2a_agent import AGENT_CARD_WELL_KNOWN_PATH
from google.adk.agents.remote_a2a_agent import RemoteA2aAgent
def create_adk_knowledge_agent() -> Agent:
"""Create a sub-agent that only uses google_search tool."""
return RemoteA2aAgent(
name="adk_knowledge_agent",
description=(
"Agent for performing Vertex AI Search to find ADK knowledge and"
" documentation"
),
agent_card=(
f"https://adk-agent-builder-knowledge-service-654646711756.us-central1.run.app/a2a/adk_knowledge_agent{AGENT_CARD_WELL_KNOWN_PATH}"
),
)
@@ -19,7 +19,6 @@ from .delete_files import delete_files
from .explore_project import explore_project
from .read_config_files import read_config_files
from .read_files import read_files
from .resolve_root_directory import resolve_root_directory
from .search_adk_source import search_adk_source
from .write_config_files import write_config_files
from .write_files import write_files
@@ -33,5 +32,4 @@ __all__ = [
'write_files',
'search_adk_source',
'explore_project',
'resolve_root_directory',
]
@@ -14,16 +14,20 @@
"""Cleanup unused files tool for Agent Builder Assistant."""
from pathlib import Path
from typing import Any
from typing import Dict
from typing import List
from typing import Optional
from google.adk.tools.tool_context import ToolContext
from ..utils.resolve_root_directory import resolve_file_path
from ..utils.resolve_root_directory import resolve_file_paths
async def cleanup_unused_files(
root_directory: str,
used_files: List[str],
tool_context: ToolContext,
file_patterns: Optional[List[str]] = None,
exclude_patterns: Optional[List[str]] = None,
) -> Dict[str, Any]:
@@ -31,27 +35,32 @@ async def cleanup_unused_files(
This tool helps clean up unused tool files when agent configurations change.
It identifies files that match patterns but aren't referenced in used_files
list.
list. Paths are resolved automatically using the tool context.
Args:
root_directory: Root directory to scan for unused files
used_files: List of file paths currently in use (should not be deleted)
tool_context: Tool execution context (provides session state)
file_patterns: List of glob patterns to match files (default: ["*.py"])
exclude_patterns: List of patterns to exclude (default: ["__init__.py"])
Returns:
Dict containing cleanup results:
- success: bool indicating if scan succeeded
- root_directory: absolute path to scanned directory
- unused_files: list of unused files found
- deleted_files: list of files actually deleted
- backup_files: list of backup files created
- errors: list of error messages
- total_freed_space: total bytes freed by deletions
"""
session_state = tool_context.state
root_path = resolve_file_path(".", session_state)
try:
root_path = Path(root_directory).resolve()
used_files_set = {Path(f).resolve() for f in used_files}
root_path = root_path.resolve()
resolved_used_files = {
path.resolve()
for path in resolve_file_paths(used_files or [], session_state)
}
# Set defaults
if file_patterns is None:
@@ -61,7 +70,6 @@ async def cleanup_unused_files(
result = {
"success": False,
"root_directory": str(root_path),
"unused_files": [],
"deleted_files": [],
"backup_files": [],
@@ -85,7 +93,7 @@ async def cleanup_unused_files(
# Identify unused files
unused_files = []
for file_path in all_files:
if file_path not in used_files_set:
if file_path.resolve() not in resolved_used_files:
unused_files.append(file_path)
result["unused_files"] = [str(f) for f in unused_files]
@@ -99,7 +107,6 @@ async def cleanup_unused_files(
except Exception as e:
return {
"success": False,
"root_directory": root_directory,
"unused_files": [],
"deleted_files": [],
"backup_files": [],
@@ -21,9 +21,14 @@ from typing import Any
from typing import Dict
from typing import List
from google.adk.tools.tool_context import ToolContext
from ..utils.resolve_root_directory import resolve_file_paths
async def delete_files(
file_paths: List[str],
tool_context: ToolContext,
create_backup: bool = False,
confirm_deletion: bool = True,
) -> Dict[str, Any]:
@@ -54,6 +59,10 @@ async def delete_files(
- errors: list of general error messages
"""
try:
# Resolve file paths using session state
session_state = tool_context._invocation_context.session.state
resolved_paths = resolve_file_paths(file_paths, session_state)
result = {
"success": True,
"files": {},
@@ -68,8 +77,8 @@ async def delete_files(
result["errors"].append("Deletion not confirmed by user")
return result
for file_path in file_paths:
file_path_obj = Path(file_path).resolve()
for resolved_path in resolved_paths:
file_path_obj = resolved_path.resolve()
file_info = {
"existed": False,
"backup_created": False,
@@ -19,23 +19,24 @@ from typing import Any
from typing import Dict
from typing import List
from google.adk.tools.tool_context import ToolContext
async def explore_project(root_directory: str) -> Dict[str, Any]:
from ..utils.resolve_root_directory import resolve_file_path
async def explore_project(tool_context: ToolContext) -> Dict[str, Any]:
"""Analyze project structure and suggest optimal file paths for ADK agents.
This tool performs comprehensive project analysis to understand the existing
structure and recommend appropriate locations for new agent configurations,
tools, and related files following ADK best practices.
Args:
root_directory: Absolute or relative path to the root directory to explore
and analyze
The tool automatically determines the project directory from session state.
Returns:
Dict containing analysis results:
Dict containing analysis results with ALL PATHS RELATIVE TO PROJECT FOLDER:
Always included:
- success: bool indicating if exploration succeeded
- root_path: absolute path to the analyzed directory
Success cases only (success=True):
- project_info: dict with basic project metadata. Contains:
@@ -54,8 +55,7 @@ async def explore_project(root_directory: str) -> Dict[str, Any]:
- existing_configs: list of dicts for found YAML configuration files.
Each dict contains:
• "filename": name of the config file
• "path": absolute path to the file
• "relative_path": path relative to project root
• "relative_path": path relative to project folder
• "size": file size in bytes
• "is_valid_yaml": bool indicating if YAML parses
correctly
@@ -80,7 +80,7 @@ async def explore_project(root_directory: str) -> Dict[str, Any]:
Examples:
Basic project exploration:
result = await explore_project("/path/to/my_adk_project")
result = await explore_project(tool_context)
Check project structure:
if result["project_info"]["has_tools_directory"]:
@@ -96,20 +96,21 @@ async def explore_project(root_directory: str) -> Dict[str, Any]:
directories = result["suggestions"]["directories"]["tools"]
"""
try:
root_path = Path(root_directory).resolve()
# Resolve root directory using session state (use "." as current project directory)
session_state = tool_context._invocation_context.session.state
resolved_path = resolve_file_path(".", session_state)
root_path = resolved_path.resolve()
if not root_path.exists():
return {
"success": False,
"error": f"Root directory does not exist: {root_directory}",
"root_path": str(root_path),
"error": f"Project directory does not exist: {root_path}",
}
if not root_path.is_dir():
return {
"success": False,
"error": f"Path is not a directory: {root_directory}",
"root_path": str(root_path),
"error": f"Path is not a directory: {root_path}",
}
# Analyze project structure
@@ -121,7 +122,6 @@ async def explore_project(root_directory: str) -> Dict[str, Any]:
return {
"success": True,
"root_path": str(root_path),
"project_info": project_info,
"existing_configs": existing_configs,
"directory_structure": directory_structure,
@@ -132,14 +132,12 @@ async def explore_project(root_directory: str) -> Dict[str, Any]:
except PermissionError:
return {
"success": False,
"error": f"Permission denied accessing directory: {root_directory}",
"root_path": root_directory,
"error": "Permission denied accessing project directory",
}
except Exception as e:
return {
"success": False,
"error": f"Error exploring project: {str(e)}",
"root_path": root_directory,
}
@@ -191,12 +189,12 @@ def _find_existing_configs(root_path: Path) -> List[Dict[str, Any]]:
# Look for YAML files in root directory (ADK convention)
for yaml_file in root_path.glob("*.yaml"):
if yaml_file.is_file():
config_info = _analyze_config_file(yaml_file)
config_info = _analyze_config_file(yaml_file, root_path)
configs.append(config_info)
for yml_file in root_path.glob("*.yml"):
if yml_file.is_file():
config_info = _analyze_config_file(yml_file)
config_info = _analyze_config_file(yml_file, root_path)
configs.append(config_info)
# Sort by name for consistent ordering
@@ -209,12 +207,18 @@ def _find_existing_configs(root_path: Path) -> List[Dict[str, Any]]:
return configs
def _analyze_config_file(config_path: Path) -> Dict[str, Any]:
def _analyze_config_file(config_path: Path, root_path: Path) -> Dict[str, Any]:
"""Analyze a single configuration file."""
# Compute relative path from project root
try:
relative_path = config_path.relative_to(root_path)
except ValueError:
# Fallback if not relative to root_path
relative_path = config_path.name
info = {
"filename": config_path.name,
"path": str(config_path),
"relative_path": config_path.name, # In root directory
"relative_path": str(relative_path),
"size": 0,
"is_valid_yaml": False,
"agent_name": None,
@@ -300,10 +304,10 @@ def _generate_path_suggestions(
"root_agent.yaml",
]
# Directory suggestions
# Directory suggestions (relative paths)
directories = {
"tools": {
"path": str(root_path / "tools"),
"path": "tools",
"exists": (root_path / "tools").exists(),
"purpose": "Custom tool implementations",
"example_files": [
@@ -312,7 +316,7 @@ def _generate_path_suggestions(
],
},
"callbacks": {
"path": str(root_path / "callbacks"),
"path": "callbacks",
"exists": (root_path / "callbacks").exists(),
"purpose": "Custom callback functions",
"example_files": ["logging.py", "security.py"],
@@ -19,12 +19,15 @@ from typing import Any
from typing import Dict
from typing import List
from google.adk.tools.tool_context import ToolContext
import yaml
from .read_files import read_files
async def read_config_files(file_paths: List[str]) -> Dict[str, Any]:
async def read_config_files(
file_paths: List[str], tool_context: ToolContext
) -> Dict[str, Any]:
"""Read multiple YAML configuration files and extract metadata.
Args:
@@ -49,7 +52,7 @@ async def read_config_files(file_paths: List[str]) -> Dict[str, Any]:
- errors: list of general error messages
"""
# Read all files using the file_manager read_files tool
read_result = await read_files(file_paths)
read_result = await read_files(file_paths, tool_context)
result = {
"success": True,
@@ -19,8 +19,14 @@ from typing import Any
from typing import Dict
from typing import List
from google.adk.tools.tool_context import ToolContext
async def read_files(file_paths: List[str]) -> Dict[str, Any]:
from ..utils.resolve_root_directory import resolve_file_paths
async def read_files(
file_paths: List[str], tool_context: ToolContext
) -> Dict[str, Any]:
"""Read content from multiple files.
This tool reads content from multiple files and returns their contents.
@@ -43,6 +49,10 @@ async def read_files(file_paths: List[str]) -> Dict[str, Any]:
- errors: list of general error messages
"""
try:
# Resolve file paths using session state
session_state = tool_context._invocation_context.session.state
resolved_paths = resolve_file_paths(file_paths, session_state)
result = {
"success": True,
"files": {},
@@ -51,8 +61,8 @@ async def read_files(file_paths: List[str]) -> Dict[str, Any]:
"errors": [],
}
for file_path in file_paths:
file_path_obj = Path(file_path).resolve()
for resolved_path in resolved_paths:
file_path_obj = resolved_path.resolve()
file_info = {
"content": "",
"file_size": 0,
@@ -72,7 +82,7 @@ async def read_files(file_paths: List[str]) -> Dict[str, Any]:
result["successful_reads"] += 1
except Exception as e:
file_info["error"] = f"Failed to read {file_path}: {str(e)}"
file_info["error"] = f"Failed to read {file_path_obj}: {str(e)}"
result["success"] = False
result["files"][str(file_path_obj)] = file_info
@@ -1,100 +0,0 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Working directory helper tool to resolve path context issues."""
import os
from pathlib import Path
from typing import Any
from typing import Dict
from typing import Optional
async def resolve_root_directory(
root_directory: str, working_directory: Optional[str] = None
) -> Dict[str, Any]:
"""Resolve the root directory from user-provided path for agent building.
This tool determines where to create or update agent configurations by
resolving the user-provided path. It handles both absolute and relative paths,
using the current working directory when needed for relative path resolution.
Args:
root_directory: Path provided by user (can be relative or absolute)
indicating where to build agents
working_directory: Optional explicit working directory to use as base for
relative path resolution (defaults to os.getcwd())
Returns:
Dict containing path resolution results:
Always included:
- success: bool indicating if resolution succeeded
- original_path: the provided root directory path
- resolved_path: absolute path to the resolved location
- resolution_method: explanation of how path was resolved
- path_exists: bool indicating if resolved path exists
Conditionally included:
- alternative_paths: list of other possible path interpretations
- warnings: list of potential issues or ambiguities
- working_directory_used: the working directory used for resolution
Examples:
Resolve relative path:
result = await resolve_root_directory("./my_project",
"/home/user/projects")
Resolve with auto-detection:
result = await resolve_root_directory("my_agent.yaml")
# Will use current working directory for relative paths
"""
try:
current_cwd = os.getcwd()
root_path_obj = Path(root_directory)
# If user provided an absolute path, use it directly
if root_path_obj.is_absolute():
resolved_path = root_path_obj
else:
# For relative paths, prefer user-provided working directory
if working_directory:
resolved_path = Path(working_directory) / root_directory
else:
# Fallback to actual current working directory
resolved_path = Path(current_cwd) / root_directory
return {
"success": True,
"original_path": root_directory,
"resolved_path": str(resolved_path.resolve()),
"exists": resolved_path.exists(),
"is_absolute": root_path_obj.is_absolute(),
"current_cwd": current_cwd,
"working_directory_used": working_directory,
"recommendation": (
f"Use resolved path: {resolved_path.resolve()}"
if resolved_path.exists()
else (
"Path does not exist. Create parent directories first:"
f" {resolved_path.parent}"
)
),
}
except Exception as e:
return {
"success": False,
"error": f"Failed to resolve path: {str(e)}",
"original_path": root_directory,
}
@@ -18,6 +18,7 @@ from pathlib import Path
from typing import Any
from typing import Dict
from google.adk.tools.tool_context import ToolContext
import jsonschema
import yaml
@@ -27,6 +28,7 @@ from .write_files import write_files
async def write_config_files(
configs: Dict[str, str],
tool_context: ToolContext,
backup_existing: bool = False, # Changed default to False - user should decide
create_directories: bool = True,
) -> Dict[str, Any]:
@@ -143,6 +145,7 @@ async def write_config_files(
if result["success"] and validated_configs:
write_result: Dict[str, Any] = await write_files(
validated_configs,
tool_context,
create_backup=backup_existing,
create_directories=create_directories,
)
@@ -20,9 +20,14 @@ import shutil
from typing import Any
from typing import Dict
from google.adk.tools.tool_context import ToolContext
from ..utils.resolve_root_directory import resolve_file_path
async def write_files(
files: Dict[str, str],
tool_context: ToolContext,
create_backup: bool = False,
create_directories: bool = True,
) -> Dict[str, Any]:
@@ -50,6 +55,9 @@ async def write_files(
- errors: list of general error messages
"""
try:
# Get session state for path resolution
session_state = tool_context._invocation_context.session.state
result = {
"success": True,
"files": {},
@@ -59,7 +67,9 @@ async def write_files(
}
for file_path, content in files.items():
file_path_obj = Path(file_path).resolve()
# Resolve file path using session state
resolved_path = resolve_file_path(file_path, session_state)
file_path_obj = resolved_path.resolve()
file_info = {
"file_size": 0,
"existed_before": False,
@@ -0,0 +1,87 @@
# Copyright 2025 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Working directory helper tool to resolve path context issues."""
import os
from pathlib import Path
from typing import Any
from typing import Dict
from typing import List
from typing import Optional
def resolve_file_path(
file_path: str,
session_state: Optional[Dict[str, Any]] = None,
working_directory: Optional[str] = None,
) -> Path:
"""Resolve a file path using root directory from session state.
This is a helper function that other tools can use to resolve file paths
without needing to be async or return detailed resolution information.
Args:
file_path: File path (relative or absolute)
session_state: Session state dict that may contain root_directory
working_directory: Working directory to use as base (defaults to cwd)
Returns:
Resolved absolute Path object
"""
file_path_obj = Path(file_path)
# If already absolute, use as-is
if file_path_obj.is_absolute():
return file_path_obj
# Get root directory from session state, default to "./"
root_directory = "./"
if session_state and "root_directory" in session_state:
root_directory = session_state["root_directory"]
# Use the same resolution logic as the main function
root_path_obj = Path(root_directory)
if root_path_obj.is_absolute():
resolved_root = root_path_obj
else:
if working_directory:
resolved_root = Path(working_directory) / root_directory
else:
resolved_root = Path(os.getcwd()) / root_directory
# Resolve file path relative to root directory
return resolved_root / file_path
def resolve_file_paths(
file_paths: List[str],
session_state: Optional[Dict[str, Any]] = None,
working_directory: Optional[str] = None,
) -> List[Path]:
"""Resolve multiple file paths using root directory from session state.
Args:
file_paths: List of file paths (relative or absolute)
session_state: Session state dict that may contain root_directory
working_directory: Working directory to use as base (defaults to cwd)
Returns:
List of resolved absolute Path objects
"""
return [
resolve_file_path(path, session_state, working_directory)
for path in file_paths
]
@@ -82,8 +82,18 @@ root_agent = Agent(
- You can ignore unit test files, unless you are sure that the test code is uesful to understand the related concepts.
- You should read all the the found files to find all the related code, unless you already know the content of the file or you are sure that the file is not related to the ADK doc.
8. Update the ADK doc file according to the doc update instructions and the related code.
- Use active voice phrasing in your doc updates.
- Use second person "you" form of address in your doc updates.
9. Create pull requests to update the ADK doc file using the `create_pull_request_from_changes` tool.
- For each recommended change, create a separate pull request.
- For each recommended change, create a separate pull request. Make sure the recommended change has exactly one pull request.
For example, if the ADK doc issue contains the following 2 recommended changes:
```
1. Title of recommended change 1
<content of recommended change 1>
2. Title of recommended change 2
<content of recommended change 2>
```
Then you should create 2 pull requests, one for each recommended change, even if each recommended change needs to update multiple ADK doc files.
- The title of the pull request should be "Update ADK doc according to issue #<issue number> - <change id>", where <issue number> is the number of the ADK docs issue and <change id> is the id of the recommended change (e.g. "1", "2", etc.).
- The body of the pull request should be the instructions about how to update the ADK docs.
- **{APPROVAL_INSTRUCTION}**
@@ -91,7 +101,10 @@ root_agent = Agent(
# 4. Guidelines & Rules
- **File Paths:** Always use absolute paths when calling the tools to read files, list directories, or search the codebase.
- **Tool Call Parallelism:** Execute multiple independent tool calls in parallel when feasible (i.e. searching the codebase).
- **Avoid deletion:** Do not delete any existing content unless specifically directed to do so.
- **Explaination:** Provide concise explanations for your actions and reasoning for each step.
- **Minimize changes:** When making updates to documentation pages, make the minimum amount of changes to achieve the communication goal. Only make changes that are necessary, and leave everything else as-is.
- **Avoid trivial code sample changes:** Update code samples only when adding or modifying functionality. Do not reformat code samples, change variable names, or change code syntax unless you are specifically directed to make those updates.
# 5. Output
Present the followings in an easy to read format as the final output to the user.
@@ -0,0 +1,25 @@
# Agent Knowledge Agent
An intelligent assistant for performing Vertex AI Search to find ADK knowledge
and documentation.
## Deployment
This agent is deployed to Google Could Run as an A2A agent, which is used by
the parent ADK Agent Builder Assistant.
Here are the steps to deploy the agent:
1. Set environment variables
```bash
export GOOGLE_CLOUD_PROJECT=your-project-id
export GOOGLE_CLOUD_LOCATION=us-central1 # Or your preferred location
export GOOGLE_GENAI_USE_VERTEXAI=True
```
2. Run the deployment command
```bash
$ adk deploy cloud_run --project=your-project-id --region=us-central1 --service_name=adk-agent-builder-knowledge-service --with_ui --a2a ./adk_knowledge_agent
```

Some files were not shown because too many files have changed in this diff Show More