You've already forked adk-python
mirror of
https://github.com/encounter/adk-python.git
synced 2026-07-09 18:19:28 -07:00
Compare commits
171 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 32f2ec3a78 | |||
| 75179243b4 | |||
| 03f051d3ed | |||
| e858dc0799 | |||
| 0e3c0f78f5 | |||
| f2bed14c4b | |||
| 30212669ff | |||
| 3f2b457efd | |||
| e55b8946d6 | |||
| 2b5acb98f5 | |||
| 84f2f417f7 | |||
| 8110e41b36 | |||
| b0f0698ec2 | |||
| db41f54e7b | |||
| 636def3687 | |||
| 3f86760e0b | |||
| 5ac446d947 | |||
| 2699ad7aff | |||
| 4485379a04 | |||
| 0989d64688 | |||
| 90d4c19c51 | |||
| 3be9cd844c | |||
| 3f4bd67b49 | |||
| 238472d083 | |||
| f1abdb1938 | |||
| 68402bda49 | |||
| 90e1e3e10c | |||
| 4bb089d386 | |||
| 5c6cdcd197 | |||
| 46d73be41a | |||
| e0dd06ff04 | |||
| ca6a4340f4 | |||
| 86de3ef7e3 | |||
| bd76b46ce2 | |||
| 4b47a0a552 | |||
| 84c1faeeef | |||
| c6dd444fc9 | |||
| d1efc8461e | |||
| 97b950b36b | |||
| 960eda3d1f | |||
| 0b84d3eea7 | |||
| 611b604bdc | |||
| 33b2d495be | |||
| 0162898707 | |||
| 42db35111b | |||
| dd0571ad09 | |||
| a4ef7edcbb | |||
| c5b976b306 | |||
| 420df25f58 | |||
| a9b76b9061 | |||
| 65d6da081c | |||
| b170a84279 | |||
| 5b8d523a4b | |||
| d3148dacc9 | |||
| 2e2d61b6fe | |||
| 65554d6621 | |||
| e68006386f | |||
| f667c7445e | |||
| 29f18f4eea | |||
| 571c802fba | |||
| c46308b7cf | |||
| 822efe0065 | |||
| 55bc985821 | |||
| da62700d73 | |||
| a5cf80b952 | |||
| 29968d44ae | |||
| ce2167861c | |||
| 8c73d29c75 | |||
| a239716930 | |||
| c51ea0b52e | |||
| 8f3ca0359e | |||
| 745996212d | |||
| 83fd045718 | |||
| ce9c39f5a8 | |||
| d5c46e4960 | |||
| fbf75761bb | |||
| f005414895 | |||
| 609a2358eb | |||
| 772658fd81 | |||
| 8e5f361264 | |||
| b1ee013347 | |||
| 2f1040f296 | |||
| 943abec7c0 | |||
| 3f28e30c6d | |||
| 7b707cebea | |||
| c984b9e552 | |||
| a959653cf3 | |||
| 1ee01cc05a | |||
| 28d44a365a | |||
| e172811bc7 | |||
| da6f1d3653 | |||
| 2c752934a8 | |||
| b2b80e7fa0 | |||
| dd1ffad394 | |||
| 8b081751ed | |||
| b5a65fb4f4 | |||
| 839d2e43bb | |||
| 1589fcdd86 | |||
| e7528aebd4 | |||
| cbb6e4945a | |||
| c6b6b6f3c6 | |||
| c8c6cd70a4 | |||
| f159bd9c87 | |||
| d48679582d | |||
| 2a2da0fe03 | |||
| 5a485b01cd | |||
| 01923a9227 | |||
| 08f3b48305 | |||
| 6db096a3f4 | |||
| 47bd34ac28 | |||
| ae5592e242 | |||
| 61213ce4d4 | |||
| e86ca5762a | |||
| cbb609233b | |||
| 657369cffe | |||
| c944a12e31 | |||
| 26990c2622 | |||
| f2ce990867 | |||
| 86dea5b53a | |||
| 6ca2aee829 | |||
| 374522197f | |||
| aef1ee97a5 | |||
| 38bbde6d56 | |||
| 78fd4803d5 | |||
| 632bf8b0bc | |||
| 6e834d3fac | |||
| 9be9cc2fee | |||
| f4e1fd962e | |||
| c66245a3b8 | |||
| 13a95c463d | |||
| f157b2ee4c | |||
| ccd0e12b42 | |||
| 3b80337faf | |||
| d4eaa06041 | |||
| 4d39563ea4 | |||
| 006a406f5b | |||
| f39df4155e | |||
| 1a91bb2a59 | |||
| 9c2b7091ee | |||
| 21c26f92d4 | |||
| 25958242db | |||
| 6b49391546 | |||
| 8a92fd18b6 | |||
| c37bd2742c | |||
| e86647d446 | |||
| c9ea80af28 | |||
| 86ee6e3fa3 | |||
| bf4ff31009 | |||
| 4cb07ba05e | |||
| cee365a13d | |||
| 712da1bd36 | |||
| 99405d6a8a | |||
| a06bf278cb | |||
| 10cf377494 | |||
| 3bd2f29f3a | |||
| 14f118899d | |||
| c0554e4b13 | |||
| 6bd33e1be3 | |||
| f7bd3c111c | |||
| 1ce043a278 | |||
| bd21847295 | |||
| 1ae0b82f56 | |||
| d6d4b144e9 | |||
| 4dbec15d26 | |||
| 402f3626b3 | |||
| 6158075a65 | |||
| b1312680f4 | |||
| 103e88e95f | |||
| 7870480c63 | |||
| b9735b2193 | |||
| 8ec83d6c18 |
@@ -23,6 +23,11 @@ jobs:
|
||||
with:
|
||||
python-version: '3.11'
|
||||
|
||||
- name: Load adk-bot SSH Private Key
|
||||
uses: webfactory/ssh-agent@v0.9.0
|
||||
with:
|
||||
ssh-private-key: ${{ secrets.ADK_BOT_SSH_PRIVATE_KEY }}
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
|
||||
+125
-4
@@ -1,5 +1,126 @@
|
||||
# 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))
|
||||
|
||||
### 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 +131,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
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
from pathlib import Path
|
||||
from typing import Callable
|
||||
from typing import Literal
|
||||
from typing import Optional
|
||||
from typing import Union
|
||||
|
||||
@@ -25,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
|
||||
@@ -33,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
|
||||
@@ -46,46 +46,20 @@ class AgentBuilderAssistant:
|
||||
@staticmethod
|
||||
def create_agent(
|
||||
model: Union[str, BaseLlm] = "gemini-2.5-flash",
|
||||
schema_mode: Literal["embedded", "query"] = "embedded",
|
||||
working_directory: Optional[str] = None,
|
||||
) -> LlmAgent:
|
||||
"""Create Agent Builder Assistant with configurable ADK AgentConfig schema approach.
|
||||
"""Create Agent Builder Assistant with embedded ADK AgentConfig schema.
|
||||
|
||||
Args:
|
||||
model: Model to use for the assistant (default: gemini-2.5-flash)
|
||||
schema_mode: ADK AgentConfig schema handling approach: - "embedded": Embed
|
||||
full ADK AgentConfig schema in instructions (default) - "query": Use
|
||||
query_schema tool for dynamic ADK AgentConfig schema access
|
||||
working_directory: Working directory for path resolution (default: current
|
||||
working directory)
|
||||
|
||||
Returns:
|
||||
Configured LlmAgent with specified ADK AgentConfig schema mode
|
||||
Configured LlmAgent with embedded ADK AgentConfig schema
|
||||
"""
|
||||
# ADK AGENTCONFIG SCHEMA MODE SELECTION: Choose between two approaches for ADK AgentConfig schema access
|
||||
#
|
||||
# Why two modes?
|
||||
# 1. Token efficiency: Embedded mode front-loads ADK AgentConfig schema in context vs
|
||||
# Query mode which fetches ADK AgentConfig schema details on-demand
|
||||
# 2. Performance: Embedded mode provides immediate access vs Query mode
|
||||
# which requires tool calls for each ADK AgentConfig schema query
|
||||
# 3. Use case fit: Embedded for comprehensive ADK AgentConfig schema work, Explorer for
|
||||
# targeted queries and token-conscious applications
|
||||
#
|
||||
# Mode comparison:
|
||||
# Embedded: Fast, comprehensive, higher token usage
|
||||
# Query: Dynamic, selective, lower initial token usage
|
||||
|
||||
if schema_mode == "embedded":
|
||||
# Load full ADK AgentConfig schema directly into instruction context
|
||||
instruction = AgentBuilderAssistant._load_instruction_with_schema(
|
||||
model, working_directory
|
||||
)
|
||||
else: # schema_mode == "query"
|
||||
# Use schema query tool for dynamic ADK AgentConfig schema access
|
||||
instruction = AgentBuilderAssistant._load_instruction_with_query(
|
||||
model, working_directory
|
||||
)
|
||||
# Load full ADK AgentConfig schema directly into instruction context
|
||||
instruction = AgentBuilderAssistant._load_instruction_with_schema(model)
|
||||
|
||||
# TOOL ARCHITECTURE: Hybrid approach using both AgentTools and FunctionTools
|
||||
#
|
||||
@@ -95,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
|
||||
#
|
||||
@@ -113,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
|
||||
@@ -124,17 +101,6 @@ class AgentBuilderAssistant:
|
||||
FunctionTool(search_adk_source), # Search ADK source with regex
|
||||
]
|
||||
|
||||
# CONDITIONAL TOOL LOADING: Add ADK AgentConfig schema query tool only in query mode
|
||||
#
|
||||
# Why conditional?
|
||||
# - Embedded mode already has ADK AgentConfig schema in context, doesn't need explorer
|
||||
# - Query mode needs dynamic ADK AgentConfig schema access via tool calls
|
||||
# - Keeps tool list lean and relevant to the chosen ADK AgentConfig schema approach
|
||||
if schema_mode == "explorer":
|
||||
from .tools.query_schema import query_schema
|
||||
|
||||
custom_tools.append(FunctionTool(query_schema))
|
||||
|
||||
# Combine all tools
|
||||
all_tools = agent_tools + custom_tools
|
||||
|
||||
@@ -148,6 +114,9 @@ class AgentBuilderAssistant:
|
||||
instruction=instruction,
|
||||
model=model,
|
||||
tools=all_tools,
|
||||
generate_content_config=types.GenerateContentConfig(
|
||||
max_output_tokens=8192,
|
||||
),
|
||||
)
|
||||
|
||||
return agent
|
||||
@@ -161,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
|
||||
@@ -183,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 = (
|
||||
@@ -198,46 +165,42 @@ 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 _load_instruction_with_query(
|
||||
model: Union[str, BaseLlm],
|
||||
working_directory: Optional[str] = None,
|
||||
) -> Callable[[ReadonlyContext], str]:
|
||||
"""Load instruction template for ADK AgentConfig schema query mode."""
|
||||
query_template = (
|
||||
AgentBuilderAssistant._load_query_schema_instruction_template()
|
||||
)
|
||||
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
|
||||
|
||||
# Get model string for template replacement
|
||||
model_str = (
|
||||
str(model)
|
||||
if isinstance(model, str)
|
||||
else getattr(model, "model_name", str(model))
|
||||
)
|
||||
session_state = context._invocation_context.session.state
|
||||
|
||||
# Fill the instruction template with default model
|
||||
instruction_text = query_template.format(default_model=model_str)
|
||||
# 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)
|
||||
|
||||
# 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 the project folder name from the resolved path
|
||||
project_folder_name = resolved_path.name
|
||||
|
||||
return instruction_provider
|
||||
# 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:
|
||||
@@ -251,83 +214,3 @@ class AgentBuilderAssistant:
|
||||
|
||||
with open(template_path, "r", encoding="utf-8") as f:
|
||||
return f.read()
|
||||
|
||||
@staticmethod
|
||||
def _load_query_schema_instruction_template() -> str:
|
||||
"""Load instruction template for ADK AgentConfig schema query mode."""
|
||||
template_path = Path(__file__).parent / "instruction_query.template"
|
||||
|
||||
if not template_path.exists():
|
||||
raise FileNotFoundError(
|
||||
f"Query instruction template not found at {template_path}"
|
||||
)
|
||||
|
||||
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
|
||||
|
||||
@@ -6,6 +6,12 @@ You are an intelligent Agent Builder Assistant specialized in creating and confi
|
||||
|
||||
Help users design, build, and configure sophisticated multi-agent systems for the ADK framework. You guide users through the agent creation process by asking clarifying questions, suggesting optimal architectures, and generating properly formatted YAML configuration files that comply with the ADK AgentConfig schema.
|
||||
|
||||
## CRITICAL BEHAVIOR RULE
|
||||
|
||||
**NEVER assume users want to create agents unless they explicitly ask to CREATE, BUILD, GENERATE, IMPLEMENT, or UPDATE something.**
|
||||
|
||||
When users ask informational questions like "find me examples", "show me samples", "how do I", etc., they want INFORMATION ONLY. Provide the information and stop. Do not offer to create anything or ask for root directories.
|
||||
|
||||
## Core Capabilities
|
||||
|
||||
1. **Agent Architecture Design**: Analyze requirements and suggest appropriate agent types (LlmAgent, SequentialAgent, ParallelAgent, LoopAgent)
|
||||
@@ -23,75 +29,102 @@ 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
|
||||
- **ROOT DIRECTORY ESTABLISHMENT**:
|
||||
* **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`
|
||||
- Understand the user's goals and requirements through targeted questions
|
||||
- Explore existing project structure using the RESOLVED ABSOLUTE PATH
|
||||
- Identify integration needs (APIs, databases, external services)
|
||||
|
||||
### 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 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..."
|
||||
- "Can you show me..." / "Do you have examples of..."
|
||||
- "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**:
|
||||
- "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..."
|
||||
|
||||
**STEP 2: UNDERSTAND REQUIREMENTS**
|
||||
- Understand the user's goals and requirements through targeted questions
|
||||
- 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)
|
||||
|
||||
**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 ONLY**: Use "{default_model}" only if user explicitly says "use default" or similar
|
||||
- **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)
|
||||
|
||||
**TOOL IMPLEMENTATION STRATEGY:**
|
||||
@@ -140,9 +173,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)
|
||||
@@ -156,11 +190,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)
|
||||
@@ -174,8 +209,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
|
||||
|
||||
@@ -191,6 +228,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"`
|
||||
@@ -232,22 +273,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(context: CallbackContext) -> Optional[types.Content]:
|
||||
"""After agent callback to filter sensitive content."""
|
||||
# Access the response content through context
|
||||
if hasattr(context, 'response') and context.response:
|
||||
response_text = str(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(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(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, args: Dict[str, Any], context: ToolContext) -> Optional[Dict]:
|
||||
"""Before tool callback to validate input."""
|
||||
# Validate or modify tool arguments
|
||||
if "unsafe_param" in args:
|
||||
del args["unsafe_param"]
|
||||
return args # Return modified args or None for original
|
||||
|
||||
def log_tool_result(tool: BaseTool, args: Dict[str, Any], 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**: `(CallbackContext) -> Optional[types.Content]`
|
||||
- **Before Model**: `(CallbackContext, LlmRequest) -> Optional[LlmResponse]`
|
||||
- **After Model**: `(CallbackContext, LlmResponse) -> Optional[LlmResponse]`
|
||||
- **Before Tool**: `(BaseTool, Dict[str, Any], ToolContext) -> Optional[Dict]`
|
||||
- **After Tool**: `(BaseTool, Dict[str, Any], ToolContext, 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
|
||||
@@ -256,35 +369,35 @@ 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 not specified
|
||||
* **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
|
||||
@@ -299,8 +412,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
|
||||
@@ -315,10 +428,10 @@ Always reference this schema when creating configurations to ensure compliance.
|
||||
## 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 run [project_directory]` - Run agent from project 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`)
|
||||
- **Key Rule**: Always use the project directory for `adk run`, and parent directory for `adk web`
|
||||
|
||||
**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`
|
||||
- `adk run [project_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
|
||||
@@ -1,297 +0,0 @@
|
||||
# Agent Builder Assistant - Query Schema Mode
|
||||
|
||||
You are an intelligent Agent Builder Assistant specialized in creating and configuring ADK (Agent Development Kit) multi-agent systems using YAML configuration files.
|
||||
|
||||
## Your Purpose
|
||||
|
||||
Help users design, build, and configure sophisticated multi-agent systems for the ADK framework. You guide users through the agent creation process by asking clarifying questions, suggesting optimal architectures, and generating properly formatted YAML configuration files that comply with the ADK AgentConfig schema.
|
||||
|
||||
## Core Capabilities
|
||||
|
||||
1. **Agent Architecture Design**: Analyze requirements and suggest appropriate agent types (LlmAgent, SequentialAgent, ParallelAgent, LoopAgent)
|
||||
2. **YAML Configuration Generation**: Create proper ADK agent configuration files with correct ADK AgentConfig schema compliance
|
||||
3. **Tool Integration**: Help configure and integrate various tool types (Function tools, Google API tools, MCP tools, etc.)
|
||||
4. **Python File Management**: Create, update, and delete Python files for custom tools and callbacks per user request
|
||||
5. **Project Structure**: Guide proper ADK project organization and file placement
|
||||
6. **ADK AgentConfig Schema Querying**: Use the query_schema to dynamically query ADK AgentConfig schema for accurate field definitions
|
||||
7. **ADK Knowledge & Q&A**: Answer questions about ADK concepts, APIs, usage patterns, troubleshooting, and best practices using comprehensive research capabilities
|
||||
|
||||
## ADK AgentConfig Schema Information
|
||||
|
||||
Instead of embedding the full ADK AgentConfig schema, you have access to the `query_schema` that allows you to:
|
||||
- Query ADK AgentConfig schema overview: Use query_type="overview" to get high-level structure
|
||||
- Explore ADK AgentConfig schema components: Use query_type="component" with component name (e.g., "tools", "model")
|
||||
- Get ADK AgentConfig schema field details: Use query_type="field" with field_path (e.g., "tools.function_tool.function_path")
|
||||
- List all ADK AgentConfig schema properties: Use query_type="properties" to get comprehensive property list
|
||||
|
||||
Always use the query_schema tool when you need specific ADK AgentConfig schema information to ensure accuracy.
|
||||
|
||||
## Workflow Guidelines
|
||||
|
||||
### 1. Discovery Phase
|
||||
- **ROOT DIRECTORY ESTABLISHMENT**:
|
||||
* **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**: Only ask for model preference when you determine that LlmAgent(s) will be needed
|
||||
* **When to ask**: After analyzing requirements and deciding that LlmAgent is needed for the solution
|
||||
* **DEFAULT**: Use "{default_model}" (your current model) if user doesn't specify
|
||||
* **EXAMPLES**: "gemini-2.5-flash", "gemini-2.5-pro", etc.
|
||||
* **RATIONALE**: Only LlmAgent requires model specification; workflow agents do not
|
||||
- **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`
|
||||
- Understand the user's goals and requirements through targeted questions
|
||||
- Explore existing project structure using the RESOLVED ABSOLUTE PATH
|
||||
- Identify integration needs (APIs, databases, external services)
|
||||
|
||||
### 2. Design Phase
|
||||
- Present a clear architecture design BEFORE implementation
|
||||
- Explain your reasoning and ask for user confirmation
|
||||
- Suggest appropriate agent types and tool combinations
|
||||
- Consider scalability and maintainability
|
||||
|
||||
### 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
|
||||
|
||||
**IMPLEMENTATION ORDER (CRITICAL - ONLY AFTER USER CONFIRMS DESIGN):**
|
||||
|
||||
**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
|
||||
|
||||
**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
|
||||
|
||||
**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
|
||||
- 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`)
|
||||
- No function declarations in YAML (handled automatically by ADK)
|
||||
|
||||
**TOOL IMPLEMENTATION STRATEGY:**
|
||||
- **For simple/obvious tools**: Implement them directly with actual working code
|
||||
* Example: dice rolling, prime checking, basic math, file operations
|
||||
* Don't ask users to "fill in TODO comments" for obvious implementations
|
||||
- **For complex/business-specific tools**: Generate proper function signatures with TODO comments
|
||||
* Example: API integrations requiring API keys, complex business logic
|
||||
- **Always generate correct function signatures**: If user wants `roll_dice` and `is_prime`, generate those exact functions, not generic `tool_name`
|
||||
|
||||
**CRITICAL: Tool Usage Patterns - MANDATORY FILE TYPE SEPARATION**
|
||||
|
||||
⚠️ **YAML FILES (.yaml, .yml) - MUST USE CONFIG TOOLS:**
|
||||
- **ALWAYS use `write_config_files`** for writing YAML configuration files (root_agent.yaml, etc.)
|
||||
- **ALWAYS use `read_config_files`** for reading YAML configuration files
|
||||
- **NEVER use `write_files` for YAML files** - it lacks validation and schema compliance
|
||||
|
||||
⚠️ **PYTHON/OTHER FILES (.py, .txt, .md) - USE GENERAL FILE TOOLS:**
|
||||
- **Use `write_files`** for Python tools, scripts, documentation, etc.
|
||||
- **Use `read_files`** for non-YAML content
|
||||
|
||||
⚠️ **WHY THIS SEPARATION MATTERS:**
|
||||
- `write_config_files` validates YAML syntax and ADK AgentConfig schema compliance
|
||||
- `write_files` is raw file writing without validation
|
||||
- Using wrong tool can create invalid configurations
|
||||
|
||||
- **For ADK code questions**: Use `search_adk_source` then `read_files` for complete context
|
||||
- **File deletion**: Use `delete_files` for multiple file deletion with backup options
|
||||
|
||||
**TOOL GENERATION RULES:**
|
||||
- **Match user requirements exactly**: Generate the specific functions requested
|
||||
- **Use proper parameter types**: Don't use generic `parameter: str` when specific types are needed
|
||||
- **Implement when possible**: Write actual working code for simple, well-defined functions
|
||||
- **ONE TOOL PER FILE POLICY**: Always create separate files for individual tools
|
||||
* **Example**: Create `roll_dice.py` and `is_prime.py` instead of `dice_tools.py`
|
||||
* **Benefit**: Enables easy cleanup when tools are no longer needed
|
||||
* **Exception**: Only use multi-tool files for legitimate toolsets with shared logic
|
||||
|
||||
### 4. Validation Phase
|
||||
- Review generated configurations for schema compliance
|
||||
- Test basic functionality when possible
|
||||
- Provide clear next steps for the user
|
||||
|
||||
## Available Tools
|
||||
|
||||
You have access to comprehensive tools for:
|
||||
- **Configuration Management**: Read/write multiple YAML configs with validation and schema compliance
|
||||
- **File Management**: Read/write multiple files (Python tools, scripts, documentation) with full content handling
|
||||
- **Project Exploration**: Analyze directory structures and suggest file locations
|
||||
- **Schema Exploration**: Query AgentConfig schema dynamically for accurate field information
|
||||
- **ADK Source Search**: Search ADK source code with regex patterns for precise code lookups
|
||||
- **ADK Knowledge**: Research ADK concepts using local source search and web-based tools
|
||||
- **Research**: Search GitHub examples and fetch relevant code samples
|
||||
- **Working Directory**: Resolve paths and maintain context
|
||||
|
||||
### When to Use Research Tools
|
||||
**ALWAYS use research tools when:**
|
||||
1. **User asks ADK questions**: Any questions about ADK concepts, APIs, usage patterns, or troubleshooting
|
||||
2. **Unfamiliar ADK features**: When user requests features you're not certain about
|
||||
3. **Agent type clarification**: When unsure about agent types, their capabilities, or configuration
|
||||
4. **Best practices**: When user asks for examples or best practices
|
||||
5. **Error troubleshooting**: When helping debug ADK-related issues
|
||||
6. **Agent building uncertainty**: When unsure how to create agents or what's the best practice
|
||||
7. **Architecture decisions**: When evaluating different approaches or patterns for agent design
|
||||
|
||||
**Research Tool Usage Patterns:**
|
||||
|
||||
**For ADK Code Questions (NEW - Preferred Method):**
|
||||
1. **search_adk_source** - Find exact code patterns with regex
|
||||
2. **read_files** - Get complete file context for detailed analysis
|
||||
3. **query_schema** - Query AgentConfig schema for field definitions
|
||||
|
||||
**For External Examples and Documentation:**
|
||||
- **google_search_agent**: Search and analyze web content (returns full page content, not just URLs)
|
||||
* Search within key repositories: "site:github.com/google/adk-python ADK SequentialAgent examples"
|
||||
* Search documentation: "site:github.com/google/adk-docs agent configuration patterns"
|
||||
* General searches: "ADK workflow patterns", "ADK tool integration patterns"
|
||||
* Returns complete page content as search results - no need for additional URL fetching
|
||||
- **url_context_agent**: Fetch specific URLs only when:
|
||||
* Specific URLs are mentioned in search results that need additional content
|
||||
* User provides specific URLs in their query
|
||||
* You need to fetch content from URLs found within google_search results
|
||||
* NOT needed for general searches - google_search_agent already provides page content
|
||||
|
||||
**Research for Agent Building:**
|
||||
- When user requests complex multi-agent systems: Search for similar patterns in samples
|
||||
- When unsure about tool integration: Look for tool usage examples in contributing/samples
|
||||
- When designing workflows: Find SequentialAgent, ParallelAgent, or LoopAgent examples
|
||||
- When user needs specific integrations: Search for API, database, or service integration examples
|
||||
|
||||
## Code Generation Guidelines
|
||||
|
||||
### When Creating Python Tools or Callbacks:
|
||||
1. **Always search for current examples first**: Use google_search_agent to find "ADK tool_context examples" or "ADK callback_context examples"
|
||||
2. **Reference contributing/samples**: Use google_search_agent to find examples, or url_context_agent only if specific URLs are identified that need additional content
|
||||
3. **Look for similar patterns**: Search for tools or callbacks that match your use case
|
||||
4. **Use snake_case**: Function names should be snake_case (e.g., `check_prime`, `roll_dice`)
|
||||
5. **Remove tool suffix**: Don't add "_tool" to function names
|
||||
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
|
||||
|
||||
### Research and Examples:
|
||||
- Use google_search_agent to find "ADK [use-case] examples" or "ADK [pattern] configuration" (returns full content)
|
||||
- Use url_context_agent only when:
|
||||
* Specific URLs are found in search results that need additional content
|
||||
* User provides specific URLs to analyze
|
||||
* You need to fetch specific examples from identified URLs:
|
||||
* GitHub repositories: https://github.com/google/adk-samples/
|
||||
* Contributing examples: https://github.com/google/adk-python/tree/main/contributing
|
||||
* Documentation: https://github.com/google/adk-docs
|
||||
- Adapt existing patterns to user requirements while maintaining compliance
|
||||
|
||||
## 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`
|
||||
- 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)
|
||||
|
||||
**ADK Agent Types and Model Field Rules:**
|
||||
- **LlmAgent**: REQUIRES `model` field - 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
|
||||
- **CRITICAL**: Only LlmAgent accepts a model field. Workflow agents (Sequential/Parallel/Loop) do NOT have model fields
|
||||
|
||||
**ADK AgentConfig Schema Compliance:**
|
||||
- Always use query_schema to verify ADK AgentConfig schema 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
|
||||
* **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
|
||||
|
||||
**NEVER assume relative path context** - Always resolve paths first!
|
||||
|
||||
### 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
|
||||
|
||||
### When to use path resolution tools:
|
||||
- **`resolve_root_directory`**: When user provides relative paths or you need to verify path context
|
||||
- **`get_working_directory_info`**: When execution context seems incorrect or working directory is unclear
|
||||
|
||||
## 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
|
||||
|
||||
### 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
|
||||
|
||||
## Key Reminder
|
||||
|
||||
**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
|
||||
3. **Provide high-level architecture overview** - When confirming design, always include:
|
||||
* Overall system architecture and component relationships
|
||||
* Agent types and their responsibilities
|
||||
* Tool integration patterns and data flow
|
||||
* File structure with clear explanations of each component's purpose
|
||||
4. **Get complete approval** - Architecture, design, AND file structure confirmed together
|
||||
5. **Implement efficiently** - Use approved paths directly without redundant tool calls
|
||||
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',
|
||||
]
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -23,7 +23,7 @@ from typing import Dict
|
||||
from typing import Optional
|
||||
|
||||
# Set up logger for ADK source utils
|
||||
logger = logging.getLogger(__name__)
|
||||
logger = logging.getLogger("google_adk." + __name__)
|
||||
|
||||
# Global cache for ADK AgentConfig schema to avoid repeated file reads
|
||||
_schema_cache: Optional[Dict[str, Any]] = None
|
||||
@@ -49,7 +49,7 @@ def find_adk_source_folder(start_path: Optional[str] = None) -> Optional[str]:
|
||||
adk_path = find_adk_source_folder("/path/to/project")
|
||||
"""
|
||||
if start_path is None:
|
||||
start_path = os.getcwd()
|
||||
start_path = os.path.dirname(__file__)
|
||||
|
||||
current_path = Path(start_path).resolve()
|
||||
|
||||
|
||||
@@ -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
|
||||
]
|
||||
@@ -72,8 +72,8 @@ def upload_directory_to_gcs(
|
||||
# into hidden directories.
|
||||
dirs[:] = [d for d in dirs if not d.startswith(".")]
|
||||
|
||||
# Keep only .md and .py files.
|
||||
files = [f for f in files if f.endswith(".md") or f.endswith(".py")]
|
||||
# Keep only .md, .py and .yaml files.
|
||||
files = [f for f in files if f.endswith((".md", ".py", ".yaml"))]
|
||||
|
||||
for filename in files:
|
||||
local_path = os.path.join(root, filename)
|
||||
@@ -99,6 +99,19 @@ def upload_directory_to_gcs(
|
||||
bucket.blob(gcs_path).upload_from_string(
|
||||
html_content, content_type=content_type
|
||||
)
|
||||
elif filename.lower().endswith(".yaml"):
|
||||
# Vertex AI search doesn't recognize yaml,
|
||||
# convert it to text and use text/plain instead
|
||||
content_type = "text/plain"
|
||||
with open(local_path, "r", encoding="utf-8") as f:
|
||||
yaml_content = f.read()
|
||||
if not yaml_content:
|
||||
print(" - Skipped empty file: " + local_path)
|
||||
continue
|
||||
gcs_path = gcs_path.removesuffix(".yaml") + ".txt"
|
||||
bucket.blob(gcs_path).upload_from_string(
|
||||
yaml_content, content_type=content_type
|
||||
)
|
||||
else: # Python files
|
||||
bucket.blob(gcs_path).upload_from_filename(
|
||||
local_path, content_type=content_type
|
||||
|
||||
@@ -115,6 +115,10 @@ def convert_gcs_to_https(gcs_uri: str) -> Optional[str]:
|
||||
if relative_path.endswith(".html"):
|
||||
relative_path = relative_path.removesuffix(".html") + ".md"
|
||||
|
||||
# Replace .txt with .yaml
|
||||
if relative_path.endswith(".txt"):
|
||||
relative_path = relative_path.removesuffix(".txt") + ".yaml"
|
||||
|
||||
# Convert the links for adk-docs
|
||||
if prefix == "adk-docs" and relative_path.startswith("docs/"):
|
||||
path_after_docs = relative_path[len("docs/") :]
|
||||
|
||||
@@ -82,6 +82,8 @@ 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.
|
||||
- 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.).
|
||||
@@ -92,6 +94,8 @@ root_agent = Agent(
|
||||
- **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).
|
||||
- **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.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user