Compare commits

...

153 Commits

Author SHA1 Message Date
Google Team Member 7d809eb9d9 Minor typo and grammar correction.
PiperOrigin-RevId: 761119061
2025-05-20 09:42:19 -07:00
Xiang (Sean) Zhou f67ccf32c3 fix: support Callable that has __call__ as coroutine function in FunctionTool
PiperOrigin-RevId: 760913537
2025-05-19 22:09:44 -07:00
Wei Sun (Jack) 5115474f2b chore!: bump version to 1.0.0, updated changelog.md and removed src/google/adk/tools/built_in_code_execution_tool.py
Mark src/google/adk/tools/_built_in_code_execution_tool.py as private and will be fully removed soon.

PiperOrigin-RevId: 760889060
2025-05-19 20:31:27 -07:00
Xiang (Sean) Zhou de7c9c6509 enhance toolbox toolset:
1. use async client
2. expose add headers and bind parameters functionality of toolbox tool

PiperOrigin-RevId: 760845486
2025-05-19 18:08:02 -07:00
Xiang (Sean) Zhou 9eef4464c6 fix: fix toolbox import path in sample toolbox agent
PiperOrigin-RevId: 760837908
2025-05-19 17:43:41 -07:00
Yifan Wang 1bfc7590b4 update minified files to include the latest eval detail changes (only UI)
PiperOrigin-RevId: 760770101
2025-05-19 14:26:28 -07:00
Wei Sun (Jack) 3f21a52853 chore: Fixes the main.py for memory/agent.py sample.
PiperOrigin-RevId: 760741263
2025-05-19 13:08:57 -07:00
Xiang (Sean) Zhou 74454170a3 refactor: refactor and refine LangChainTool
PiperOrigin-RevId: 760726719
2025-05-19 12:29:44 -07:00
Wei Sun (Jack) ae7d19a4c6 chore: Moves toolbox-core to extensions extra dependency.
PiperOrigin-RevId: 760722343
2025-05-19 12:15:55 -07:00
Hangfei Lin 171b1145ee fix:Makes TranscriptionEntry.role optional
For function call or response, the role is None for now.

PiperOrigin-RevId: 760692876
2025-05-19 11:02:08 -07:00
Wei Sun (Jack) 9932015f3b chore: Makes --host backward compatible for cloud_run deploy. --host only available after 0.5.0.
PiperOrigin-RevId: 760681697
2025-05-19 10:35:05 -07:00
Xiang (Sean) Zhou 3f117391a5 refactor: remote remote agent as there is no use case and it's not implemented properly
PiperOrigin-RevId: 760652423
2025-05-19 09:24:37 -07:00
Shangjie Chen 0497fc578c fix: fix return type of get_session.
PiperOrigin-RevId: 760638917
2025-05-19 08:46:54 -07:00
Xiang (Sean) Zhou 3b5232c14f feat: add sample mcp agent that connects to mcp server via sse endpoint directly
PiperOrigin-RevId: 760388717
2025-05-18 17:00:03 -07:00
Wei Sun (Jack) 9e767b3fe1 chore: Creates a sample main.py to demonstrate how to use adk as a library for the workflow agent in docs.
For Issue #573.

PiperOrigin-RevId: 760380509
2025-05-18 16:17:16 -07:00
Xiang (Sean) Zhou 2ad1f79422 refactor: replace logger.warn which is deprecated with logger.warning
PiperOrigin-RevId: 760311574
2025-05-18 10:25:29 -07:00
Wei Sun (Jack) e278ca9541 chore: Refines mcp_agent instruction to include the allowed folder in the instruction.
PiperOrigin-RevId: 760057162
2025-05-17 12:57:11 -07:00
Wei Sun (Jack) 9324801b75 chore: Fixes test_fast_api.py (part I for circular deps).
It still fails due to signal used not in main thread. It will be fixed later.

PiperOrigin-RevId: 760050504
2025-05-17 12:22:04 -07:00
Wei Sun (Jack) f592de4cc0 chore: constructor shouldn't have return type hint.
PiperOrigin-RevId: 760021373
2025-05-17 09:57:30 -07:00
Wei Sun (Jack) 57de9634de chore: Fixes unittests/tools/application_integration_tool/test_application_integration_toolset.py
PiperOrigin-RevId: 760019822
2025-05-17 09:49:35 -07:00
Wei Sun (Jack) 729001fc0b chore: logger = logging.getLogger(__name__) --> logger = logging.getLogger('google_adk.' + __name__)
PiperOrigin-RevId: 760019467
2025-05-17 09:47:55 -07:00
Wei Sun (Jack) 0d7d7918b6 chore: logger = logging.getLogger(__name__) --> logger = logging.getLogger('google_adk.' + __name__)
PiperOrigin-RevId: 759894901
2025-05-16 23:04:02 -07:00
Wei Sun (Jack) 482099c925 chore!: Sets up google_adk for top level logger namespace. Removes --log_to_tmp option in adk web and adk api_server for the same reason.
Context: google-auth commit [1] broke adk log, because it disables the top level logger named "google", which is also adk's top level logger. We establish a separate top level logger with a different name `google_adk` to prevent this in the future.

This commit only changes google_llm.py. All other files will be changed in later commits.

[1] https://github.com/googleapis/google-auth-library-python/commit/77ad53eb00c74b3badc486c8207a16dbc49f37e5#diff-e386c2b2c39b4d746c1e257f503acecbde49b1746b1a34f53b57083ed6094161

PiperOrigin-RevId: 759872317
2025-05-16 21:28:33 -07:00
Wei Sun (Jack) 021aaddf32 chore: Allows BaseAgent in the constructor of InMemoryRunner.
PiperOrigin-RevId: 759818175
2025-05-16 17:42:58 -07:00
Google Team Member 74b8841e62 ADK changes
PiperOrigin-RevId: 759809705
2025-05-16 17:11:03 -07:00
Wei Sun (Jack) 186b5de826 chore: formats google_llm.py.
PiperOrigin-RevId: 759803357
2025-05-16 16:49:45 -07:00
Wei Sun (Jack) 03f167c1d3 chore: Adds toolbox-core to deps and fixes toolbox code error.
PiperOrigin-RevId: 759802478
2025-05-16 16:46:11 -07:00
Google Team Member 93e8f020ed ADK changes
PiperOrigin-RevId: 759775958
2025-05-16 15:24:40 -07:00
Liang Wu a1ddf0b6cc feat!: add --adk_version arg to adk deploy cloud_run.
The default version for Cloud Run deployment is changed to the version in the dev environment instead of the latest version.

PiperOrigin-RevId: 759767654
2025-05-16 15:01:23 -07:00
Google Team Member 801549f734 ADK changes
PiperOrigin-RevId: 759758769
2025-05-16 14:35:37 -07:00
Xiang (Sean) Zhou f83504dffb chore: add toolbox sample agent
PiperOrigin-RevId: 759746416
2025-05-16 14:01:53 -07:00
Jack Wotherspoon 11ca528090 feat!: remove ToolboxTool in favor of using toolbox-core directly
Copybara import of the project:

--
9cefcdde97685bc6966a13019bfb80cc232a399b by Jack Wotherspoon <jackwoth@google.com>:

chore: delete toolbox_tool.py
--
b2607eb0397e72b6b616ac592920f74d42a8ee5d by jackwotherspoon <jackwoth@google.com>:

feat: expose toolbox

--
a4a0859997af9a68e240f78ff351f0fded6a52e2 by Jack Wotherspoon <jackwoth@google.com>:

chore: update formatting
--
070dc93cdc289a5ee5935bd5995d3005bf8396a0 by jackwotherspoon <jackwoth@google.com>:

chore: add base toolbox tests

--
ab84a0f49eccc9b993317b3ffe2b5b6cad278d70 by jackwotherspoon <jackwoth@google.com>:

chore: remove ToolboxTool

--
87f4f909acc294468bcb3053e300f4df252bdb27 by Jack Wotherspoon <jackwoth@google.com>:

chore: update formatting
--
ddc1a11c0ce45fe34e5f2dd43c808d88a7d6af0b by Jack Wotherspoon <jackwoth@google.com>:

chore: Update pyproject.toml
--
aee173d8df40ffefe535b266e1bd6528c9aeb1b9 by Jack Wotherspoon <jackwoth@google.com>:

chore: Update pyproject.toml
--
22fc95922b500ddb0ec4901dccbe2fbfcc53b35f by Jack Wotherspoon <jackwoth@google.com>:

chore: Update __init__.py
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/763 from jackwotherspoon:expose-toolbox 3cb629a9d0d18aaeeeed59fb0d0d1e1b225b7437
PiperOrigin-RevId: 759744557
2025-05-16 13:56:58 -07:00
Ankur Sharma 76116c8008 Minor documentation update to a file.
PiperOrigin-RevId: 759742154
2025-05-16 13:49:46 -07:00
Xiang (Sean) Zhou 939b45a1c8 feat: add Toolbox Toolset
PiperOrigin-RevId: 759741922
2025-05-16 13:48:47 -07:00
Xiang (Sean) Zhou 015c667917 refactor: refactor base toolset to import from relative path
PiperOrigin-RevId: 759735824
2025-05-16 13:33:04 -07:00
Jack Wotherspoon 66a6f94fbc Copybara import of the project:
--
aa863ca851d4c689fbdb431d91189d5ebbc59932 by Jack Wotherspoon <jackwoth@google.com>:

chore: fix variable name in test
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/769 from jackwotherspoon:test-fix aa863ca851d4c689fbdb431d91189d5ebbc59932
PiperOrigin-RevId: 759731577
2025-05-16 13:20:57 -07:00
Selcuk Gun 9e9dfa7472 Prevent session state injection for provider supplied instructions
When the user provides instruction provider, we assume that they will inject the session state parameters if needed. This assumption allows users to return code snippets in the instruction provider without any template replacement.

PiperOrigin-RevId: 759705471
2025-05-16 12:09:48 -07:00
Shangjie Chen 5ee17a3268 feat!: remove close_session from session service as it is not implemented yet.
PiperOrigin-RevId: 759705443
2025-05-16 12:08:57 -07:00
Google Team Member 370eed1c7a Update the adk-web-dev-ui-function-call screenshot.
PiperOrigin-RevId: 759677811
2025-05-16 10:57:24 -07:00
Google Team Member 6e0ea01fcb Added support for dynamic auth in integration connector tool
PiperOrigin-RevId: 759676602
2025-05-16 10:53:53 -07:00
Shangjie Chen 2f006264ce chore: fix python format.
PiperOrigin-RevId: 759674648
2025-05-16 10:49:06 -07:00
Wei Sun (Jack) d0f117ebbc chore: call base class constructor in McpTool constructor.
PiperOrigin-RevId: 759644369
2025-05-16 09:28:15 -07:00
Adrian Cole dcb50effef Copybara import of the project:
--
636685818a512e9de30d5119f0244261cf16af27 by Adrian Cole <64215+codefromthecrypt@users.noreply.github.com>:

fix: corrects typo in bigquery sample

Noticed while reading that google was spelled wrong.

COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/709 from codefromthecrypt:patch-1 b30e819979f81962a2e44922bfd2dadd539fe3ea
PiperOrigin-RevId: 759641065
2025-05-16 09:18:48 -07:00
Xiang (Sean) Zhou f384793649 fix: fix mcp agent filter logic
PiperOrigin-RevId: 759638254
2025-05-16 09:10:49 -07:00
Xiang (Sean) Zhou 05a853bc91 fix:fix mcp toolset close issue
PiperOrigin-RevId: 759636772
2025-05-16 09:05:56 -07:00
Xiang (Sean) Zhou 12507dc6cc fix: fix tool filtering in mcp toolset
PiperOrigin-RevId: 759632573
2025-05-16 08:53:21 -07:00
Xiang (Sean) Zhou 755ce74550 fix: stage correct ui files to adk
PiperOrigin-RevId: 759632290
2025-05-16 08:52:22 -07:00
Wei Sun (Jack) b72573c57d chore: Adds mypy to dev extra.
PiperOrigin-RevId: 759460917
2025-05-15 22:57:54 -07:00
Xiang (Sean) Zhou eb076a9ee8 fix: fix application integration toolset
PiperOrigin-RevId: 759450502
2025-05-15 22:23:49 -07:00
Xiang (Sean) Zhou fe5a5494e9 fix: fix oauth for dev UI
PiperOrigin-RevId: 759433563
2025-05-15 21:24:28 -07:00
Xiang (Sean) Zhou f0e11c72ab refactor: make readonly context optional in tool predicate
PiperOrigin-RevId: 759429453
2025-05-15 21:07:00 -07:00
Xiang (Sean) Zhou 770ecd8bb3 refactor: hide non-public field and cleanup for tools
PiperOrigin-RevId: 759400805
2025-05-15 19:24:10 -07:00
Zhining e62e15e720 fix: sqlalchemy query error in DatabaseSessionService when using custom GetSessionConfig with PostgreSQL
Copybara import of the project:
--
cec6f5044307e3ecdd20a513e0d8202b0854ff4c by ZhiNing <574775237@qq.com>:

COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/705 from czn574775237:fix/issue-655 c15f116d4bc0328e8a90a437958042ef1b087c14
PiperOrigin-RevId: 759381068
2025-05-15 18:07:56 -07:00
Wei Sun (Jack) a786f75968 Uses logs method parameter to set log level.
PiperOrigin-RevId: 759378777
2025-05-15 18:00:40 -07:00
Yifan Wang 01a21e40d0 ADK changes
PiperOrigin-RevId: 759377414
2025-05-15 17:55:53 -07:00
Selcuk Gun 69f7ed8d0e Rename ollama sample script and await create_session
PiperOrigin-RevId: 759369988
2025-05-15 17:29:56 -07:00
Google Team Member ebfe8fe51c Resolve issue where --with_ui flag boolean was not being passed correctly, preventing CMD adk web [...] from being deployed to Cloud Run.
PiperOrigin-RevId: 759364440
2025-05-15 17:13:47 -07:00
Xiang (Sean) Zhou cb000e5a94 refactor: remove async root_agent handling as it no longer needed for MCP toolset
PiperOrigin-RevId: 759364382
2025-05-15 17:12:57 -07:00
Selcuk Gun 01cf186299 Update samples for async session changes and remove exp suffix from gemini model
PiperOrigin-RevId: 759364113
2025-05-15 17:12:07 -07:00
Wei Sun (Jack) 04820cb0a7 chore: Fixes a few samples for the breaking session service change.
PiperOrigin-RevId: 759354632
2025-05-15 16:44:23 -07:00
Selcuk Gun 509db3f9fb Add token usage to gemini (streaming), litellm and anthropic
Also included a token_usage sample that showcases the token usage of subagents with different models under a parent agent.

PiperOrigin-RevId: 759347015
2025-05-15 16:22:36 -07:00
Google Team Member 4d5760917d chore: Add alias_generators to new Eval pydantic models
PiperOrigin-RevId: 759346603
2025-05-15 16:21:20 -07:00
Wei Sun (Jack) d27fe90d37 chore: fix wrong imports.
PiperOrigin-RevId: 759321579
2025-05-15 15:17:51 -07:00
Ankur Sharma 1c23556225 Updated test cases to use the new EvalSet schema to store test data. Also, added a utility to help migrate existing tests files to the new schema.
Also, migrated existing test files to the new schema and deleted test session files as they are no longer needed.

PiperOrigin-RevId: 759318735
2025-05-15 15:10:06 -07:00
Shangjie Chen a71d9ea9a1 fix: fix broken tests.
PiperOrigin-RevId: 759312577
2025-05-15 14:57:04 -07:00
Xiang (Sean) Zhou fccd17df6f fix: adapt oauth calendar agent and bigquery agent to new Google API toolset interface
PiperOrigin-RevId: 759298612
2025-05-15 14:21:45 -07:00
Ankur Sharma 4c6820e78c Update AgentEvaluator to new new EvalSchema
PiperOrigin-RevId: 759293759
2025-05-15 14:09:23 -07:00
Xiang (Sean) Zhou bdd678db31 refactor: refactor google api toolset to expose class instead of instance
PiperOrigin-RevId: 759289358
2025-05-15 13:59:57 -07:00
Yifan Wang f298d07579 ADK changes
PiperOrigin-RevId: 759276411
2025-05-15 13:28:50 -07:00
Liang Wu c399c50be5 Add --host argument to adk web and adk api_server commands and change the default binding host to localhost.
PiperOrigin-RevId: 759276079
2025-05-15 13:27:49 -07:00
Google Team Member 05917cabbd ADK changes
PiperOrigin-RevId: 759259620
2025-05-15 12:46:44 -07:00
Google Team Member 1804ca39a6 feat! Update session service interface to be async.
Also keep the sync version in the InMemorySessionService as create_session_sync() as a temporary migration option.

PiperOrigin-RevId: 759252188
2025-05-15 12:24:13 -07:00
Shangjie Chen 5b3204c356 feat! Update session service interface to be async.
Also keep the sync version in the InMemorySessionService as create_session_sync() as a temporary migration option.

PiperOrigin-RevId: 759224250
2025-05-15 11:17:13 -07:00
Yifan Wang d161a2c3f7 ADK changes
PiperOrigin-RevId: 759218509
2025-05-15 11:04:21 -07:00
Ankur Sharma 95f994d7ca chore:add in memory session service to in memory runner.
PiperOrigin-RevId: 759206471
2025-05-15 10:35:21 -07:00
Shangjie Chen 3ea9eca929 feat! Remove list_events from session service interface as it has many overlap with get_session.
PiperOrigin-RevId: 759184310
2025-05-15 09:41:16 -07:00
Xiang (Sean) Zhou 2214c1558f fix: fix the typo in MCPToolset when parsing the errlog argument to MCPSessionManager
PiperOrigin-RevId: 759018462
2025-05-15 00:31:18 -07:00
Xiang (Sean) Zhou 4a0751941b fix: fix application integration toolset
PiperOrigin-RevId: 759018346
2025-05-15 00:30:19 -07:00
Liang Wu 9c2358e2a5 Update the usage of built-in code execution in documentation and sample agent.
PiperOrigin-RevId: 758997215
2025-05-14 23:17:13 -07:00
Ankur Sharma 3686608f8d Fixes test_cli_eval_success_path test.
PiperOrigin-RevId: 758981214
2025-05-14 22:20:59 -07:00
Ankur Sharma ada24d7171 Update Response Evaluators to use the new eval schema.
PiperOrigin-RevId: 758929683
2025-05-14 19:26:29 -07:00
Ankur Sharma ee674ce0ef Update Eval Run and TrajectoryEvaluator to use the new schema.
PiperOrigin-RevId: 758927160
2025-05-14 19:16:33 -07:00
Ankur Sharma 2cb74dd20e Update Eval Set Manager to use new EvalSet and EvalCase schema.
PiperOrigin-RevId: 758921365
2025-05-14 18:51:38 -07:00
Shangjie Chen 293f406148 fix: fix breaking delete_session.
PiperOrigin-RevId: 758862440
2025-05-14 15:42:44 -07:00
Shangjie Chen bc43a1196a feat: add _sync implementation in the inmemory session sevice.
PiperOrigin-RevId: 758832846
2025-05-14 14:22:46 -07:00
Google Team Member dc90c91ed1 Fix typo in import
PiperOrigin-RevId: 758736571
2025-05-14 10:20:24 -07:00
Liang Wu 22e4210b47 Deprecate BuiltInCodeExecutionTool in favor of BuiltInCodeExecutor.
PiperOrigin-RevId: 758713057
2025-05-14 09:22:49 -07:00
Wei Sun (Jack) b67182c50f chore: Adds docstring for LlmAgent.disallow_transfer_to_parent to clarify the expected behavior.
PiperOrigin-RevId: 758676926
2025-05-14 07:36:51 -07:00
Wei Sun (Jack) 71bd808a14 Fixes: eval_result endpoint throws due to folder not existing.
PiperOrigin-RevId: 758508672
2025-05-13 22:03:38 -07:00
Tanue Eugen-Bleck Mbunwo b33bdb9a03 fix: Display full help text for adk create CLI command when argument…
Copybara import of the project:

--
dcfb9ff720562802f9ce15c90a71b4cd40f77280 by Eugen-Bleck <eugenbleck@gmail.com>:

fix: Display full help text for adk create  CLI command when arguments are missing

--
f2eea8d1e5947b1631ac2de3824d8bf0cf833cbc by Eugen-Bleck <eugenbleck@gmail.com>:

fix: Display full help text for adk run and eval  CLI command when arguments are missing
COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/443 from bl3ck:fix/cli-help-display c2bca420b00aa3391ab8cfb6baedc9ea0dbfb7e1
PiperOrigin-RevId: 758498242
2025-05-13 21:22:05 -07:00
Xiang (Sean) Zhou fc40226ec0 refactor: refactor mcp toolset to hide non-public field
PiperOrigin-RevId: 758494601
2025-05-13 21:06:03 -07:00
Xiang (Sean) Zhou 14cf910ce6 refactor: refactor application integration toolset to hide non-public field
PiperOrigin-RevId: 758469938
2025-05-13 19:28:01 -07:00
Xiang (Sean) Zhou 00e0035c8a refactor: refactor google api toolset to hide non-public field
PiperOrigin-RevId: 758469484
2025-05-13 19:26:05 -07:00
Wei Sun (Jack) 30947b48b8 feat(memory)!: Uses the new MemoryEntry schema for all memory related components.
BREAKING CHANGE. This commit changes all memory related interface to using the newly introduced MemoryEntry class.

PiperOrigin-RevId: 758464887
2025-05-13 19:07:11 -07:00
Wei Sun (Jack) 825f5d4f2e feat: Adds new interface for MemoryEntry.
PiperOrigin-RevId: 758448993
2025-05-13 18:01:33 -07:00
Yifan Wang 6f00df3df0 ADK changes
PiperOrigin-RevId: 758444575
2025-05-13 17:43:53 -07:00
Xiang (Sean) Zhou da55b5a943 fix: update google api toolset to remove 'match' for python 3.9 compliant
PiperOrigin-RevId: 758438091
2025-05-13 17:21:05 -07:00
Wei Sun (Jack) d046367826 chore: Removes logging config in tools/google_api_tool/googleapi_to_openapi_converter.py.
PiperOrigin-RevId: 758436692
2025-05-13 17:16:03 -07:00
Xiang (Sean) Zhou 9647426500 refactor: refactor openapi toolset and tool parser to hide non public field
PiperOrigin-RevId: 758436303
2025-05-13 17:14:20 -07:00
Alec Daling 1f0fd7bfce Copybara import of the project:
--
e4aceb8428b8d2c321e7b44a16869997dd5f0dff by ajdaling <ajdaling@gmail.com>:

Fixes issue #311: Add usage_metadata to llm_response

COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/694 from chapelhillnorth:fix-issue-311 2735bc01a6a57a5302b58af33266bfbeafc8e184
PiperOrigin-RevId: 758435162
2025-05-13 17:10:34 -07:00
Wei Sun (Jack) 66553b18c6 chore: Treats google.adk as known_third_party in pyproject.toml for organizing imports in samples.
PiperOrigin-RevId: 758434037
2025-05-13 17:06:52 -07:00
Liang Wu 933f01b89f fix: Concatenate all text Parts from an AgentTool agent's response.
PiperOrigin-RevId: 758424011
2025-05-13 16:38:54 -07:00
Google Team Member d6cf660506 chore: Migrate json field names to camelCase (4/4)
PiperOrigin-RevId: 758423361
2025-05-13 16:36:45 -07:00
Xiang (Sean) Zhou 931fb338f8 rename tool_set to toolset to uniform the naming
PiperOrigin-RevId: 758422703
2025-05-13 16:34:23 -07:00
Xiang (Sean) Zhou af978fe194 fix apihub toolset ut
PiperOrigin-RevId: 758400203
2025-05-13 15:32:28 -07:00
Google Team Member 4def3f1bd3 chore: Migrate json field names to camelCase (3/n)
PiperOrigin-RevId: 758394880
2025-05-13 15:16:16 -07:00
Selcuk Gun ff9de71869 Add role to the event returned in agent callback sample
Events without a role are filtered out in the next turns.

PiperOrigin-RevId: 758393355
2025-05-13 15:12:06 -07:00
Xiang (Sean) Zhou f6bdd555fb refactor apihub toolset to hide non public field
PiperOrigin-RevId: 758378396
2025-05-13 14:34:04 -07:00
Ankur Sharma cf06cc507a Refactor Eval Set Management into its own class.
PiperOrigin-RevId: 758378377
2025-05-13 14:32:38 -07:00
Selcuk Gun 303af440ee Await canonical instructions in test_llm_agent_fields.py
PiperOrigin-RevId: 758372807
2025-05-13 14:17:31 -07:00
Ankur Sharma 82b8e304ec Convert Session To Invocation.
PiperOrigin-RevId: 758356942
2025-05-13 13:39:52 -07:00
Hangfei Lin 4188673b0f feat(live): Support live mode of sequential agent
Add a `task_completed` function to the agent so when a model finished the task, it can send a signal and the program knows it can go to next agent.

This cl include:
* Implements the `_run_live_impl` in `sequential_agent` so it can handle live case.
* Add an example for sequential agent.
* Improve error message for unimplemented _run_live_impl in other agents.

Note:
1. Compared to non-live case, live agents process a continuous streams of audio
or video, so it doesn't have a native way to tell if it's finished and should pass
to next agent or not. So we introduce a task_compelted() function so the
model can call this function to signal that it's finished the task and we
can move on to next agent.

2. live agents doesn't seems to be very useful or natural in parallel or loop agents so we don't implement it for now. If there is user demand, we can implement it easily using similar approach.

PiperOrigin-RevId: 758315430
2025-05-13 11:56:16 -07:00
Hangfei Lin 39f78dc28f feat(live): Support native(model-side) audio transcription for agent transferring in live mode.
The old implementation:
1. We only started transcription at the beginning of agent transferring.
2. The transcription service we used is not as good / fast as the model/native transcription.

In the current implementation, the live agent will rely on the llm's transcription, instead of our transcription when llm support audio transcription in the input. And in that case, the live agent won't use our own audio transcriber. This reduces the latency from 5secs to 2 secs during agent transferring. It also improves the transcription quality.

When the llm doesn't support audio transcription, we still use our audio transcriber to transcribe audio input.

PiperOrigin-RevId: 758296647
2025-05-13 11:13:08 -07:00
Hangfei Lin c4d5e3b298 feat: Align run_live interface with run_async etc
PiperOrigin-RevId: 758289318
2025-05-13 10:57:26 -07:00
Yanfei Chen 08c9cf86c3 feat: Add an enterprise web search tool for web grounding.
PiperOrigin-RevId: 758206509
2025-05-13 07:15:46 -07:00
Xiang (Sean) Zhou dd8e9b71e5 fix application integration toolset unit tests
PiperOrigin-RevId: 758080966
2025-05-13 00:06:56 -07:00
Google Team Member d740b93e03 feat: trigger in ApplicationIntegrationTools is changed to triggers and is a list of strings
PiperOrigin-RevId: 758034458
2025-05-12 21:13:27 -07:00
Xiang (Sean) Zhou 2d84b13219 fix toolset codes to make it work with python 3.9
PiperOrigin-RevId: 757991503
2025-05-12 18:23:18 -07:00
Yifan Wang 80813a75cf Add debug trace endpoint in api server
Details:
- Add a in-memory SpanExporter to capture all trace information.
- Add /debug/trace/session/{session_id} endpoint to retrieve traces from the in-memory exporter.
- Add Session ID in Telemetry spans.

PiperOrigin-RevId: 757984565
2025-05-12 17:56:50 -07:00
Xiang (Sean) Zhou d35b99e6dd update mcp toolset and sample agent based on new tool_filter definition
PiperOrigin-RevId: 757969950
2025-05-12 17:05:24 -07:00
Xiang (Sean) Zhou 722028801a update application integration toolset agent based on new toolset interface
PiperOrigin-RevId: 757963384
2025-05-12 16:43:41 -07:00
Xiang (Sean) Zhou 57d1315533 adapt application integration toolset to new toolset interface
PiperOrigin-RevId: 757960706
2025-05-12 16:36:43 -07:00
Xiang (Sean) Zhou d19927b1bc update bigquery agent and oauth calendar agent according to new toolset interface
PiperOrigin-RevId: 757949732
2025-05-12 16:06:45 -07:00
Xiang (Sean) Zhou 6a04ff84ba adapt google api toolset and api hub toolset to new toolset interface
PiperOrigin-RevId: 757946541
2025-05-12 15:58:39 -07:00
Google Team Member 27b229719e chore: Migrate json field names to camelCase (2/n)
PiperOrigin-RevId: 757937550
2025-05-12 15:33:34 -07:00
Google Team Member 05a0c6b307 Add 'get_eval_report' and 'list_eval_reports' endpoints.
PiperOrigin-RevId: 757936497
2025-05-12 15:30:53 -07:00
Selcuk Gun df0892a7b8 Update import for override decorator in mcp_toolset for python version < 3.12
PiperOrigin-RevId: 757934273
2025-05-12 15:24:37 -07:00
Google Team Member 660c2efa4d Define EvalReport data model.
PiperOrigin-RevId: 757933585
2025-05-12 15:22:57 -07:00
Ankur Sharma 1237d5334f Adding Pydantic data models for eval set and eval case.
PiperOrigin-RevId: 757920694
2025-05-12 14:48:21 -07:00
Google Team Member 993f9971bb Add new GeminiCodeExecutor to code_executors/ folder.
PiperOrigin-RevId: 757895291
2025-05-12 13:44:17 -07:00
Xiang (Sean) Zhou 5462862795 fix eval unittests failure
PiperOrigin-RevId: 757872670
2025-05-12 12:42:19 -07:00
Shangjie Chen c39f24f072 fix: Refine the confusing error message.
PiperOrigin-RevId: 757841288
2025-05-12 11:20:54 -07:00
Alan 847c8fd11a Copybara import of the project:
--
d481e0604a79470e2c1308827b3ecb78bfb5327e by Alan B <alan@nerds.ai>:

feat: đźš§ catch user transcription

--
bba436bb76d1d2f9d5ba969fce38ff8b8a443254 by Alan B <alan@nerds.ai>:

feat: ✨ send user transcription event as llm_response

--
ad2abf540c60895b79c50f9051a6289ce394b98d by Alan B <death1027@outlook.com>:

style: đź’„ update lint problems

--
744703c06716300c0f9f41633d3bafdf4cb180a1 by Hangfei Lin <hangfeilin@gmail.com>:

fix: set right order for input transcription

--
31a5d42d6155b0e5caad0c73c8df43255322016f by Hangfei Lin <hangfeilin@gmail.com>:

remove print

--
59e5d9c72060f97d124883150989315401a4c1b5 by Hangfei Lin <hangfeilin@gmail.com>:

remove api version

COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/590 from BloodBoy21:feat/api-version-vertex 1ed855249cae398b40691b91c6e468bccec07a3a
PiperOrigin-RevId: 757840099
2025-05-12 11:18:01 -07:00
Google Team Member f15f64af0f chore: Migrate json field names to camelCase (1/n)
PiperOrigin-RevId: 757832114
2025-05-12 10:59:35 -07:00
Shangjie Chen 70a6bfae90 fix: Explictly throw execption when custom id is set for vertex ai session service.
PiperOrigin-RevId: 757815469
2025-05-12 10:19:25 -07:00
Selcuk Gun 4c4cfb74ae Support async instruction and global instruction provider
PiperOrigin-RevId: 757808335
2025-05-12 10:03:34 -07:00
Selcuk Gun 812485fdfa Move callback samples to dedicated directory
Sample chained callback logs can we seen running asyncio_run.py

PiperOrigin-RevId: 757793406
2025-05-12 09:24:29 -07:00
Mukund Jha cdb4cac237 Copybara import of the project:
--
84abc07d2342e88e601949faa67a3014c0f491e8 by mukundjha-mj <mukundjha204@gmail.com>:

Fix spelling mistakes, reorder sections, and improve readability in pyproject.toml

--
122c19d4be0fad394fbd02720734aa4625877637 by mukundjha-mj <mukundjha204@gmail.com>:

fix(pyproject): correct spelling and reorder config sections for clarity

COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/669 from mukundjha-mj:fix/typos-pyproject 122c19d4be0fad394fbd02720734aa4625877637
PiperOrigin-RevId: 757318920
2025-05-10 22:53:20 -07:00
Yifan Wang 16014764b6 Fix eval run without engaging agent result in api key missing error
PiperOrigin-RevId: 757015581
2025-05-09 21:02:23 -07:00
Google Team Member 9a8c77e04a Added filterClause in Update and Delete Request
PiperOrigin-RevId: 757013222
2025-05-09 20:50:36 -07:00
Selcuk Gun 4c191ba6b9 Move uv install under install dependencies
PiperOrigin-RevId: 757008562
2025-05-09 20:33:42 -07:00
Google Team Member 2a0524692b feat: Typo fixes in a few files.
PiperOrigin-RevId: 756921945
2025-05-09 15:10:23 -07:00
Xiang (Sean) Zhou 166df01236 fix eval in api server and cli for below issue:
https://github.com/google/adk-python/issues/651

PiperOrigin-RevId: 756906937
2025-05-09 14:26:29 -07:00
Shangjie Chen c4ecef54bc fix: Generate event id at beginning, and regen for every new yield event. This is because trace module requires an event id.
PiperOrigin-RevId: 756905471
2025-05-09 14:22:42 -07:00
Yifan Wang 415104743d the agent evetn graph is not able to be shown due to missing await keyword. this change is to fix missing await for build_graph
PiperOrigin-RevId: 756876056
2025-05-09 13:01:25 -07:00
Wei Sun (Jack) 33acb26565 chore: Bump min version for google-genai sdk to 1.13.0.
PiperOrigin-RevId: 756806752
2025-05-09 09:57:08 -07:00
Thiago Neves ac97fc638f fix(tests): use mock GCS client in artifact service tests to avoid real credentials
Copybara import of the project:

--
ade1d98e030a966183f56cb5c9c1b04cf51f5337 by Thiago Neves <thiagohneves@gmail.com>:

fix(tests): use mock GCS client in artifact service tests to avoid real credentials

--
becd2925feebf60196129b029a0ab8d490f7b19e by Thiago Neves <thiagohneves@gmail.com>:

test(agents): add unit tests for live_request_queue, readonly_context, and run_config

COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/641 from thiagoneves:feature/increase-test-coverage 0f7a9fc55d97902e190a394f099324fbeb1541af
PiperOrigin-RevId: 756798390
2025-05-09 09:33:40 -07:00
Xiang (Sean) Zhou dc5c23c675 fix predicate class name in MCP toolset
PiperOrigin-RevId: 756761193
2025-05-09 07:39:08 -07:00
Xiang (Sean) Zhou 8c78945ec9 update mcp agent to use latest toolset interface
PiperOrigin-RevId: 756613972
2025-05-08 22:57:49 -07:00
Xiang (Sean) Zhou 7dffb59096 adapt MCP toolset to the latest Toolset interface
PiperOrigin-RevId: 756611140
2025-05-08 22:47:51 -07:00
Xiang (Sean) Zhou 4d7298e4f2 add toolset base class and allow llm agent to accept toolset as tools
PiperOrigin-RevId: 756605470
2025-05-08 22:27:52 -07:00
đť•‚ 8963300518 test(cli): Add unit tests for CLI functionality
Copybara import of the project:

--
f60707a22905f30040808b41b7e3510a47a80fc6 by K <51281148+K-dash@users.noreply.github.com>:

test(cli): Add unit tests for CLI functionality

This commit introduces unit tests for the following CLI-related components:

- cli_deploy.py: Tests for the cloud deployment feature.
- cli_create.py: Tests for the agent creation feature.
- cli.py: Tests for the main CLI execution logic.
- cli_tools_click.py: Tests for the Click-based CLI tools.

--
7be2159a475d0785619fea5e40c70e6461a7f4e1 by K <51281148+K-dash@users.noreply.github.com>:

fix test_cli_eval_success_path

COPYBARA_INTEGRATE_REVIEW=https://github.com/google/adk-python/pull/577 from K-dash:test/add-unit-tests-for-cli 69f12d3a27d9c50a46ef269075e050f498dee67a
PiperOrigin-RevId: 756602765
2025-05-08 22:18:33 -07:00
Selcuk Gun 2cbbf88135 Support chaining for tool callbacks
(before/after) tool callbacks are invoked throughout the provided chain until one callback does not return None. Callbacks can be async and sync.

PiperOrigin-RevId: 756526507
2025-05-08 17:38:04 -07:00
191 changed files with 9088 additions and 2929 deletions
+55
View File
@@ -1,5 +1,60 @@
# Changelog
## 1.0.0
### âš  BREAKING CHANGES
* Evaluation dataset schema is finalized with strong-type pydantic models.
(previously saved eval file needs re-generation, for both adk eval cli and
the eval tab in adk web UI).
* `BuiltInCodeExecutor` (in code_executors package) replaces
`BuiltInCodeExecutionTool` (previously in tools package).
* All methods in services are now async, including session service, artifact
service and memory service.
* `list_events` and `close_session` methods are removed from session service.
* agent.py file structure with MCP tools are now easier and simpler ([now](https://github.com/google/adk-python/blob/3b5232c14f48e1d5b170f3698d91639b079722c8/contributing/samples/mcp_stdio_server_agent/agent.py#L33) vs [before](https://github.com/google/adk-python/blob/a4adb739c0d86b9ae4587547d2653d568f6567f2/contributing/samples/mcp_agent/agent.py#L41)).
Old format is not working anymore.
* `Memory` schema and `MemoryService` is redesigned.
* Mark various class attributes as private in the classes in the `tools` package.
* Disabled session state injection if instruction provider is used.
(so that you can have `{var_name}` in the instruction, which is required for code snippets)
* Toolbox integration is revamped: tools/toolbox_tool.py → tools/toolbox_toolset.py.
* Removes the experimental `remote_agent.py`. We'll redesign it and bring it back.
### Features
* Dev UI:
* A brand new trace view for overall agent invocation.
* A revamped evaluation tab and comparison view for checking eval results.
* Introduced `BaseToolset` to allow dynamically add/remove tools for agents.
* Revamped MCPToolset with the new BaseToolset interface.
* Revamped GoogleApiTool, GoogleApiToolset and ApplicationIntegrationToolset with the new BaseToolset interface.
* Resigned agent.py file structure when needing MCPToolset.
* Added ToolboxToolset.
* Redesigned strong-typed agent evaluation schema.
* Allows users to create more cohesive eval sets.
* Allows evals to be extended for non-text modality.
* Allows for a structured interaction with the uber eval system.
* Redesigned Memory schema and MemoryService interfaces.
* Added token usage to LlmResponse.
* Allowed specifying `--adk_version` in `adk deploy cloud_run` cli. Default is the current version.
### Bug Fixes
* Fixed `adk deploy cloud_run` failing bug.
* Fixed logs not being printed due to `google-auth` library.
### Miscellaneous Chores
* Display full help text when adk cli receives invalid arguments.
* `adk web` now binds `127.0.0.1` by default, instead of 0.0.0.0.
* `InMemoryRunner` now takes `BaseAgent` in constructor.
* Various docstring improvements.
* Various UI tweaks.
* Various bug fixes.
* Update various contributing/samples for contributors to validate the implementation.
## 0.5.0
### âš  BREAKING CHANGES
+27 -30
View File
@@ -4,21 +4,21 @@ We'd love to accept your patches and contributions to this project.
## Table of Contents
- [Before you begin](#before-you-begin)
- [Sign our Contributor License Agreement](#sign-our-contributor-license-agreement)
- [Before you begin](#before-you-begin)
- [Sign our Contributor License Agreement](#sign-our-contributor-license-agreement)
- [Review our community guidelines](#review-our-community-guidelines)
- [Contribution workflow](#contribution-workflow)
- [Finding Issues to Work On](#finding-issues-to-work-on)
- [Requirement for PRs](#requirement-for-prs)
- [Large or Complex Changes](#large-or-complex-changes)
- [Testing Requirements](#testing-requirements)
- [Unit Tests](#unit-tests)
- [End-to-End (E2E) Tests](#manual-end-to-end-e2e-tests)
- [Documentation](#documentation)
- [Development Setup](#development-setup)
- [Contribution workflow](#contribution-workflow)
- [Finding Issues to Work On](#finding-issues-to-work-on)
- [Requirement for PRs](#requirement-for-prs)
- [Large or Complex Changes](#large-or-complex-changes)
- [Testing Requirements](#testing-requirements)
- [Unit Tests](#unit-tests)
- [End-to-End (E2E) Tests](#manual-end-to-end-e2e-tests)
- [Documentation](#documentation)
- [Development Setup](#development-setup)
- [Code reviews](#code-reviews)
## Before you begin
### Sign our Contributor License Agreement
@@ -44,13 +44,13 @@ This project follows
### Finding Issues to Work On
- Browse issues labeled **`good first issue`** (newcomer-friendly) or **`help wanted`** (general contributions).
- Browse issues labeled **`good first issue`** (newcomer-friendly) or **`help wanted`** (general contributions).
- For other issues, please kindly ask before contributing to avoid duplication.
### Requirement for PRs
- All PRs, other than small documentation or typo fixes, should have a Issue assoicated. If not, please create one.
- All PRs, other than small documentation or typo fixes, should have a Issue assoicated. If not, please create one.
- Small, focused PRs. Keep changes minimal—one concern per PR.
- For bug fixes or features, please provide logs or screenshot after the fix is applied to help reviewers better understand the fix.
- Please include a `testing plan` section in your PR to talk about how you will test. This will save time for PR review. See `Testing Requirements` section for more details.
@@ -72,12 +72,12 @@ Please add or update unit tests for your change. Please include a summary of pas
Requirements for unit tests:
- **Coverage:** Cover new features, edge cases, error conditions, and typical use cases.
- **Location:** Add or update tests under `tests/unittests/`, following existing naming conventions (e.g., `test_<module>_<feature>.py`).
- **Framework:** Use `pytest`. Tests should be:
- Fast and isolated.
- Written clearly with descriptive names.
- Free of external dependencies (use mocks or fixtures as needed).
- **Coverage:** Cover new features, edge cases, error conditions, and typical use cases.
- **Location:** Add or update tests under `tests/unittests/`, following existing naming conventions (e.g., `test_<module>_<feature>.py`).
- **Framework:** Use `pytest`. Tests should be:
- Fast and isolated.
- Written clearly with descriptive names.
- Free of external dependencies (use mocks or fixtures as needed).
- **Quality:** Aim for high readability and maintainability; include docstrings or comments for complex scenarios.
#### Manual End-to-End (E2E) Tests
@@ -86,15 +86,15 @@ Manual E2E tests ensure integrated flows work as intended. Your tests should cov
Depending on your change:
- **ADK Web:**
- Use the `adk web` to verify functionality.
- Capture and attach relevant screenshots demonstrating the UI/UX changes or outputs.
- **ADK Web:**
- Use the `adk web` to verify functionality.
- Capture and attach relevant screenshots demonstrating the UI/UX changes or outputs.
- Label screenshots clearly in your PR description.
- **Runner:**
- Provide the testing setup. For example, the agent definition, and the runner setup.
- Execute the `runner` tool to reproduce workflows.
- Include the command used and console output showing test results.
- Execute the `runner` tool to reproduce workflows.
- Include the command used and console output showing test results.
- Highlight sections of the log that directly relate to your change.
### Documentation
@@ -117,19 +117,16 @@ For any changes that impact user-facing documentation (guides, API reference, tu
```shell
source .venv/bin/activate
```
**windows**
```shell
source .\.venv\Scripts\activate
```
```shell
pip install uv
```
3. **Install dependencies:**
```shell
pip install uv
uv sync --all-extras
```
4. **Run unit tests:**
Binary file not shown.

Before

Width:  |  Height:  |  Size: 463 KiB

After

Width:  |  Height:  |  Size: 413 KiB

@@ -20,7 +20,6 @@ from dotenv import load_dotenv
from google.adk.agents.llm_agent import LlmAgent
from google.adk.tools.application_integration_tool import ApplicationIntegrationToolset
# Load environment variables from .env file
load_dotenv()
@@ -29,12 +28,12 @@ connection_project = os.getenv("CONNECTION_PROJECT")
connection_location = os.getenv("CONNECTION_LOCATION")
jira_tool = ApplicationIntegrationToolset(
jira_toolset = ApplicationIntegrationToolset(
project=connection_project,
location=connection_location,
connection=connection_name,
entity_operations={"Issues": [], "Projects": []},
tool_name="jira_issue_manager",
tool_name_prefix="jira_issue_manager",
)
root_agent = LlmAgent(
@@ -46,5 +45,5 @@ root_agent = LlmAgent(
If there is an error in the tool response, understand the error and try and see if you can fix the error and then and execute the tool again. For example if a variable or parameter is missing, try and see if you can find it in the request or user query or default it and then execute the tool again or check for other tools that could give you the details.
If there are any math operations like count or max, min in the user request, call the tool to get the data and perform the math operations and then return the result in the response. For example for maximum, fetch the list and then do the math operation.
""",
tools=jira_tool.get_tools(),
tools=[jira_toolset],
)
@@ -24,7 +24,7 @@ async def log_query(tool_context: ToolContext, query: str):
root_agent = Agent(
model='gemini-2.0-flash-exp',
model='gemini-2.0-flash',
name='log_agent',
description='Log user query.',
instruction="""Always log the user query and reploy "kk, I've logged."
+15 -21
View File
@@ -16,7 +16,7 @@ import os
from dotenv import load_dotenv
from google.adk import Agent
from google.adk.tools.google_api_tool import bigquery_tool_set
from google.adk.tools.google_api_tool import BigQueryToolset
# Load environment variables from .env file
load_dotenv()
@@ -24,24 +24,25 @@ load_dotenv()
# Access the variable
oauth_client_id = os.getenv("OAUTH_CLIENT_ID")
oauth_client_secret = os.getenv("OAUTH_CLIENT_SECRET")
bigquery_tool_set.configure_auth(oauth_client_id, oauth_client_secret)
bigquery_datasets_list = bigquery_tool_set.get_tool("bigquery_datasets_list")
bigquery_datasets_get = bigquery_tool_set.get_tool("bigquery_datasets_get")
bigquery_datasets_insert = bigquery_tool_set.get_tool(
"bigquery_datasets_insert"
tools_to_expose = [
"bigquery_datasets_list",
"bigquery_datasets_get",
"bigquery_datasets_insert",
"bigquery_tables_list",
"bigquery_tables_get",
"bigquery_tables_insert",
]
bigquery_toolset = BigQueryToolset(
client_id=oauth_client_id,
client_secret=oauth_client_secret,
tool_filter=tools_to_expose,
)
bigquery_tables_list = bigquery_tool_set.get_tool("bigquery_tables_list")
bigquery_tables_get = bigquery_tool_set.get_tool("bigquery_tables_get")
bigquery_tables_insert = bigquery_tool_set.get_tool("bigquery_tables_insert")
root_agent = Agent(
model="gemini-2.0-flash",
name="bigquery_agent",
instruction="""
You are a helpful Google BigQuery agent that help to manage users' data on Goolge BigQuery.
You are a helpful Google BigQuery agent that help to manage users' data on Google BigQuery.
Use the provided tools to conduct various operations on users' data in Google BigQuery.
Scenario 1:
@@ -73,12 +74,5 @@ root_agent = Agent(
{userInfo?}
</User>
""",
tools=[
bigquery_datasets_list,
bigquery_datasets_get,
bigquery_datasets_insert,
bigquery_tables_list,
bigquery_tables_get,
bigquery_tables_insert,
],
tools=[bigquery_toolset],
)
+198
View File
@@ -0,0 +1,198 @@
# 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.
import random
from google.adk import Agent
from google.adk.planners import BuiltInPlanner
from google.adk.planners import PlanReActPlanner
from google.adk.tools.tool_context import ToolContext
from google.genai import types
def roll_die(sides: int, tool_context: ToolContext) -> int:
"""Roll a die and return the rolled result.
Args:
sides: The integer number of sides the die has.
Returns:
An integer of the result of rolling the die.
"""
result = random.randint(1, sides)
if not 'rolls' in tool_context.state:
tool_context.state['rolls'] = []
tool_context.state['rolls'] = tool_context.state['rolls'] + [result]
return result
async def check_prime(nums: list[int]) -> str:
"""Check if a given list of numbers are prime.
Args:
nums: The list of numbers to check.
Returns:
A str indicating which number is prime.
"""
primes = set()
for number in nums:
number = int(number)
if number <= 1:
continue
is_prime = True
for i in range(2, int(number**0.5) + 1):
if number % i == 0:
is_prime = False
break
if is_prime:
primes.add(number)
return (
'No prime numbers found.'
if not primes
else f"{', '.join(str(num) for num in primes)} are prime numbers."
)
async def before_agent_callback(callback_context):
print('@before_agent_callback')
return None
async def after_agent_callback(callback_context):
print('@after_agent_callback')
return None
async def before_model_callback(callback_context, llm_request):
print('@before_model_callback')
return None
async def after_model_callback(callback_context, llm_response):
print('@after_model_callback')
return None
def after_agent_cb1(callback_context):
print('@after_agent_cb1')
def after_agent_cb2(callback_context):
print('@after_agent_cb2')
# ModelContent (or Content with role set to 'model') must be returned.
# Otherwise, the event will be excluded from the context in the next turn.
return types.ModelContent(
parts=[
types.Part(
text='(stopped) after_agent_cb2',
),
],
)
def after_agent_cb3(callback_context):
print('@after_agent_cb3')
def before_agent_cb1(callback_context):
print('@before_agent_cb1')
def before_agent_cb2(callback_context):
print('@before_agent_cb2')
def before_agent_cb3(callback_context):
print('@before_agent_cb3')
def before_tool_cb1(tool, args, tool_context):
print('@before_tool_cb1')
def before_tool_cb2(tool, args, tool_context):
print('@before_tool_cb2')
def before_tool_cb3(tool, args, tool_context):
print('@before_tool_cb3')
def after_tool_cb1(tool, args, tool_context, tool_response):
print('@after_tool_cb1')
def after_tool_cb2(tool, args, tool_context, tool_response):
print('@after_tool_cb2')
return {'test': 'after_tool_cb2', 'response': tool_response}
def after_tool_cb3(tool, args, tool_context, tool_response):
print('@after_tool_cb3')
root_agent = Agent(
model='gemini-2.0-flash',
name='data_processing_agent',
description=(
'hello world agent that can roll a dice of 8 sides and check prime'
' numbers.'
),
instruction="""
You roll dice and answer questions about the outcome of the dice rolls.
You can roll dice of different sizes.
You can use multiple tools in parallel by calling functions in parallel(in one request and in one round).
It is ok to discuss previous dice roles, and comment on the dice rolls.
When you are asked to roll a die, you must call the roll_die tool with the number of sides. Be sure to pass in an integer. Do not pass in a string.
You should never roll a die on your own.
When checking prime numbers, call the check_prime tool with a list of integers. Be sure to pass in a list of integers. You should never pass in a string.
You should not check prime numbers before calling the tool.
When you are asked to roll a die and check prime numbers, you should always make the following two function calls:
1. You should first call the roll_die tool to get a roll. Wait for the function response before calling the check_prime tool.
2. After you get the function response from roll_die tool, you should call the check_prime tool with the roll_die result.
2.1 If user asks you to check primes based on previous rolls, make sure you include the previous rolls in the list.
3. When you respond, you must include the roll_die result from step 1.
You should always perform the previous 3 steps when asking for a roll and checking prime numbers.
You should not rely on the previous history on prime results.
""",
tools=[
roll_die,
check_prime,
],
# planner=BuiltInPlanner(
# thinking_config=types.ThinkingConfig(
# include_thoughts=True,
# ),
# ),
generate_content_config=types.GenerateContentConfig(
safety_settings=[
types.SafetySetting( # avoid false alarm about rolling dice.
category=types.HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT,
threshold=types.HarmBlockThreshold.OFF,
),
]
),
before_agent_callback=[
before_agent_cb1,
before_agent_cb2,
before_agent_cb3,
],
after_agent_callback=[after_agent_cb1, after_agent_cb2, after_agent_cb3],
before_model_callback=before_model_callback,
after_model_callback=after_model_callback,
before_tool_callback=[before_tool_cb1, before_tool_cb2, before_tool_cb3],
after_tool_callback=[after_tool_cb1, after_tool_cb2, after_tool_cb3],
)
+80
View File
@@ -0,0 +1,80 @@
# 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.
import asyncio
import time
import warnings
import agent
from dotenv import load_dotenv
from google.adk import Runner
from google.adk.artifacts import InMemoryArtifactService
from google.adk.cli.utils import logs
from google.adk.sessions import InMemorySessionService
from google.adk.sessions import Session
from google.genai import types
load_dotenv(override=True)
warnings.filterwarnings('ignore', category=UserWarning)
logs.log_to_tmp_folder()
async def main():
app_name = 'my_app'
user_id_1 = 'user1'
session_service = InMemorySessionService()
artifact_service = InMemoryArtifactService()
runner = Runner(
app_name=app_name,
agent=agent.root_agent,
artifact_service=artifact_service,
session_service=session_service,
)
session_11 = await session_service.create_session(
app_name=app_name, user_id=user_id_1
)
async def run_prompt(session: Session, new_message: str):
content = types.Content(
role='user', parts=[types.Part.from_text(text=new_message)]
)
print('** User says:', content.model_dump(exclude_none=True))
async for event in runner.run_async(
user_id=user_id_1,
session_id=session.id,
new_message=content,
):
if event.content.parts and event.content.parts[0].text:
print(f'** {event.author}: {event.content.parts[0].text}')
start_time = time.time()
print('Start time:', start_time)
print('------------------------------------')
await run_prompt(session_11, 'Hi')
await run_prompt(session_11, 'Roll a die with 100 sides')
await run_prompt(session_11, 'Roll a die again with 100 sides.')
await run_prompt(session_11, 'What numbers did I got?')
print(
await artifact_service.list_artifact_keys(
app_name=app_name, user_id=user_id_1, session_id=session_11.id
)
)
end_time = time.time()
print('------------------------------------')
print('End time:', end_time)
print('Total time:', end_time - start_time)
if __name__ == '__main__':
asyncio.run(main())
+2 -2
View File
@@ -15,7 +15,7 @@
"""Data science agent."""
from google.adk.agents.llm_agent import Agent
from google.adk.tools import built_in_code_execution
from google.adk.code_executors.built_in_code_executor import BuiltInCodeExecutor
def base_system_instruction():
@@ -96,5 +96,5 @@ When plotting trends, you should make sure to sort and order the data by the x-a
""",
tools=[built_in_code_execution],
code_executor=BuiltInCodeExecutor(),
)
@@ -41,7 +41,7 @@ async def main():
artifact_service=artifact_service,
session_service=session_service,
)
session_11 = session_service.create_session(app_name, user_id_1)
session_11 = await session_service.create_session(app_name, user_id_1)
async def run_prompt(session: Session, new_message: str):
content = types.Content(
@@ -69,44 +69,5 @@ async def main():
print('Total time:', end_time - start_time)
def main_sync():
app_name = 'my_app'
user_id_1 = 'user1'
session_service = InMemorySessionService()
artifact_service = InMemoryArtifactService()
runner = Runner(
app_name=app_name,
agent=agent.root_agent,
artifact_service=artifact_service,
session_service=session_service,
)
session_11 = session_service.create_session(app_name, user_id_1)
def run_prompt(session: Session, new_message: str):
content = types.Content(
role='user', parts=[types.Part.from_text(text=new_message)]
)
print('** User says:', content.model_dump(exclude_none=True))
for event in runner.run_sync(
session=session,
new_message=content,
):
if event.content.parts and event.content.parts[0].text:
print(f'** {event.author}: {event.content.parts[0].text}')
start_time = time.time()
print('Start time:', start_time)
print('------------------------------------')
run_prompt(session_11, 'Hi')
run_prompt(session_11, 'Roll a die.')
run_prompt(session_11, 'Roll a die again.')
run_prompt(session_11, 'What numbers did I got?')
end_time = time.time()
print('------------------------------------')
print('End time:', end_time)
print('Total time:', end_time - start_time)
if __name__ == '__main__':
asyncio.run(main())
main_sync()
+1 -61
View File
@@ -65,60 +65,8 @@ async def check_prime(nums: list[int]) -> str:
else f"{', '.join(str(num) for num in primes)} are prime numbers."
)
async def before_agent_callback(callback_context):
print('@before_agent_callback')
return None
async def after_agent_callback(callback_context):
print('@after_agent_callback')
return None
async def before_model_callback(callback_context, llm_request):
print('@before_model_callback')
return None
async def after_model_callback(callback_context, llm_response):
print('@after_model_callback')
return None
def after_agent_cb1(callback_context):
print('@after_agent_cb1')
def after_agent_cb2(callback_context):
print('@after_agent_cb2')
return types.Content(
parts=[
types.Part(
text='(stopped) after_agent_cb2',
),
],
)
def after_agent_cb3(callback_context):
print('@after_agent_cb3')
def before_agent_cb1(callback_context):
print('@before_agent_cb1')
def before_agent_cb2(callback_context):
print('@before_agent_cb2')
def before_agent_cb3(callback_context):
print('@before_agent_cb3')
root_agent = Agent(
model='gemini-2.0-flash-exp',
model='gemini-2.0-flash',
name='data_processing_agent',
description=(
'hello world agent that can roll a dice of 8 sides and check prime'
@@ -158,12 +106,4 @@ root_agent = Agent(
),
]
),
before_agent_callback=[
before_agent_cb1,
before_agent_cb2,
before_agent_cb3,
],
after_agent_callback=[after_agent_cb1, after_agent_cb2, after_agent_cb3],
before_model_callback=before_model_callback,
after_model_callback=after_model_callback,
)
@@ -14,35 +14,27 @@
import asyncio
import time
import warnings
import agent
from dotenv import load_dotenv
from google.adk import Runner
from google.adk.agents.run_config import RunConfig
from google.adk.artifacts import InMemoryArtifactService
from google.adk.cli.utils import logs
from google.adk.sessions import InMemorySessionService
from google.adk.runners import InMemoryRunner
from google.adk.sessions import Session
from google.genai import types
load_dotenv(override=True)
warnings.filterwarnings('ignore', category=UserWarning)
logs.log_to_tmp_folder()
async def main():
app_name = 'my_app'
user_id_1 = 'user1'
session_service = InMemorySessionService()
artifact_service = InMemoryArtifactService()
runner = Runner(
app_name=app_name,
runner = InMemoryRunner(
agent=agent.root_agent,
artifact_service=artifact_service,
session_service=session_service,
app_name=app_name,
)
session_11 = session_service.create_session(
session_11 = await runner.session_service.create_session(
app_name=app_name, user_id=user_id_1
)
@@ -83,11 +75,11 @@ async def main():
print('------------------------------------')
await run_prompt(session_11, 'Hi')
await run_prompt(session_11, 'Roll a die with 100 sides')
await run_prompt(session_11, 'Roll a die again.')
await run_prompt(session_11, 'Roll a die again with 100 sides.')
await run_prompt(session_11, 'What numbers did I got?')
await run_prompt_bytes(session_11, 'Hi bytes')
print(
await artifact_service.list_artifact_keys(
await runner.artifact_service.list_artifact_keys(
app_name=app_name, user_id=user_id_1, session_id=session_11.id
)
)
@@ -97,49 +89,5 @@ async def main():
print('Total time:', end_time - start_time)
def main_sync():
app_name = 'my_app'
user_id_1 = 'user1'
session_service = InMemorySessionService()
artifact_service = InMemoryArtifactService()
runner = Runner(
app_name=app_name,
agent=agent.root_agent,
artifact_service=artifact_service,
session_service=session_service,
)
session_11 = session_service.create_session(
app_name=app_name, user_id=user_id_1
)
def run_prompt(session: Session, new_message: str):
content = types.Content(
role='user', parts=[types.Part.from_text(text=new_message)]
)
print('** User says:', content.model_dump(exclude_none=True))
for event in runner.run(
user_id=user_id_1,
session_id=session.id,
new_message=content,
):
if event.content.parts and event.content.parts[0].text:
print(f'** {event.author}: {event.content.parts[0].text}')
start_time = time.time()
print('Start time:', start_time)
print('------------------------------------')
run_prompt(session_11, 'Hi')
run_prompt(session_11, 'Roll a die with 100 sides.')
run_prompt(session_11, 'Roll a die again.')
run_prompt(session_11, 'What numbers did I got?')
end_time = time.time()
print('------------------------------------')
print('End time:', end_time)
print('Total time:', end_time - start_time)
if __name__ == '__main__':
print('--------------ASYNC--------------------')
asyncio.run(main())
print('--------------SYNC--------------------')
main_sync()
@@ -12,9 +12,9 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import asyncio
import time
import warnings
import agent
from dotenv import load_dotenv
@@ -26,7 +26,6 @@ from google.adk.sessions import Session
from google.genai import types
load_dotenv(override=True)
warnings.filterwarnings('ignore', category=UserWarning)
logs.log_to_tmp_folder()
@@ -41,7 +40,7 @@ async def main():
artifact_service=artifact_service,
session_service=session_service,
)
session_11 = session_service.create_session(
session_11 = await session_service.create_session(
app_name=app_name, user_id=user_id_1
)
@@ -12,7 +12,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import asyncio
import time
import warnings
@@ -42,7 +41,7 @@ async def main():
artifact_service=artifact_service,
session_service=session_service,
)
session_11 = session_service.create_session(
session_11 = await session_service.create_session(
app_name=app_name, user_id=user_id_1
)
@@ -67,7 +66,7 @@ async def main():
session_11, 'Roll a die with 100 sides and check if it is prime'
)
await run_prompt(session_11, 'Roll it again.')
await run_prompt(session_11, 'What numbers did I got?')
await run_prompt(session_11, 'What numbers did I get?')
end_time = time.time()
print('------------------------------------')
print('End time:', end_time)
-44
View File
@@ -1,44 +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.
import os
from google.adk.agents.llm_agent import LlmAgent
from google.adk.tools.mcp_tool.mcp_toolset import MCPToolset, StdioServerParameters
async def create_agent():
"""Gets tools from MCP Server."""
tools, exit_stack = await MCPToolset.from_server(
connection_params=StdioServerParameters(
command='npx',
args=[
'-y', # Arguments for the command
'@modelcontextprotocol/server-filesystem',
os.path.dirname(os.path.abspath(__file__)),
],
)
)
agent = LlmAgent(
model='gemini-2.0-flash',
name='enterprise_assistant',
instruction='Help user accessing their file systems',
tools=tools,
)
return agent, exit_stack
root_agent = create_agent()
@@ -0,0 +1,8 @@
This agent connects to a local MCP server via sse.
To run this agent, start the local MCP server first by :
```bash
uv run filesystem_server.py
```
+15
View File
@@ -0,0 +1,15 @@
# 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.
from . import agent
+58
View File
@@ -0,0 +1,58 @@
# 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.
import os
from google.adk.agents.llm_agent import LlmAgent
from google.adk.tools.mcp_tool.mcp_toolset import MCPToolset
from google.adk.tools.mcp_tool.mcp_toolset import SseServerParams
_allowed_path = os.path.dirname(os.path.abspath(__file__))
root_agent = LlmAgent(
model='gemini-2.0-flash',
name='enterprise_assistant',
instruction=f"""\
Help user accessing their file systems.
Allowed directory: {_allowed_path}
""",
tools=[
MCPToolset(
connection_params=SseServerParams(
url='http://localhost:3000/sse',
headers={'Accept': 'text/event-stream'},
),
# don't want agent to do write operation
# you can also do below
# tool_filter=lambda tool, ctx=None: tool.name
# not in [
# 'write_file',
# 'edit_file',
# 'create_directory',
# 'move_file',
# ],
tool_filter=[
'read_file',
'read_multiple_files',
'list_directory',
'directory_tree',
'search_files',
'get_file_info',
'list_allowed_directories',
],
)
],
)
@@ -0,0 +1,80 @@
# 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.
import asyncio
import os
from pathlib import Path
import sys
from mcp.server.fastmcp import FastMCP
# Create an MCP server with a name
mcp = FastMCP("Filesystem Server", host="localhost", port=3000)
# Add a tool to read file contents
@mcp.tool(description="Read contents of a file")
def read_file(filepath: str) -> str:
"""Read and return the contents of a file."""
with open(filepath, "r") as f:
return f.read()
# Add a tool to list directory contents
@mcp.tool(description="List contents of a directory")
def list_directory(dirpath: str) -> list:
"""List all files and directories in the given directory."""
return os.listdir(dirpath)
# Add a tool to get current working directory
@mcp.tool(description="Get current working directory")
def get_cwd() -> str:
"""Return the current working directory."""
return str(Path.cwd())
# Graceful shutdown handler
async def shutdown(signal, loop):
"""Cleanup tasks tied to the service's shutdown."""
print(f"\nReceived exit signal {signal.name}...")
# Get all running tasks
tasks = [t for t in asyncio.all_tasks() if t is not asyncio.current_task()]
# Cancel all tasks
for task in tasks:
task.cancel()
print(f"Cancelling {len(tasks)} outstanding tasks")
await asyncio.gather(*tasks, return_exceptions=True)
# Stop the loop
loop.stop()
print("Shutdown complete!")
# Main entry point with graceful shutdown handling
if __name__ == "__main__":
try:
# The MCP run function ultimately uses asyncio.run() internally
mcp.run(transport="sse")
except KeyboardInterrupt:
print("\nServer shutting down gracefully...")
# The asyncio event loop has already been stopped by the KeyboardInterrupt
print("Server has been shut down.")
except Exception as e:
print(f"Unexpected error: {e}")
sys.exit(1)
finally:
print("Thank you for using the Filesystem MCP Server!")

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