google-adk 1.6.1__py3-none-any.whl → 1.8.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- google/adk/a2a/converters/event_converter.py +5 -85
- google/adk/a2a/converters/request_converter.py +1 -2
- google/adk/a2a/executor/a2a_agent_executor.py +45 -16
- google/adk/a2a/logs/log_utils.py +1 -2
- google/adk/a2a/utils/__init__.py +0 -0
- google/adk/a2a/utils/agent_card_builder.py +544 -0
- google/adk/a2a/utils/agent_to_a2a.py +118 -0
- google/adk/agents/__init__.py +5 -0
- google/adk/agents/agent_config.py +46 -0
- google/adk/agents/base_agent.py +239 -41
- google/adk/agents/callback_context.py +41 -0
- google/adk/agents/common_configs.py +79 -0
- google/adk/agents/config_agent_utils.py +184 -0
- google/adk/agents/config_schemas/AgentConfig.json +566 -0
- google/adk/agents/invocation_context.py +5 -1
- google/adk/agents/live_request_queue.py +15 -0
- google/adk/agents/llm_agent.py +201 -9
- google/adk/agents/loop_agent.py +35 -1
- google/adk/agents/parallel_agent.py +24 -3
- google/adk/agents/remote_a2a_agent.py +17 -5
- google/adk/agents/sequential_agent.py +22 -1
- google/adk/artifacts/gcs_artifact_service.py +110 -20
- google/adk/auth/auth_handler.py +3 -3
- google/adk/auth/credential_manager.py +23 -23
- google/adk/auth/credential_service/base_credential_service.py +6 -6
- google/adk/auth/credential_service/in_memory_credential_service.py +10 -8
- google/adk/auth/credential_service/session_state_credential_service.py +8 -8
- google/adk/auth/exchanger/oauth2_credential_exchanger.py +3 -3
- google/adk/auth/oauth2_credential_util.py +2 -2
- google/adk/auth/refresher/oauth2_credential_refresher.py +4 -4
- google/adk/cli/agent_graph.py +3 -1
- google/adk/cli/browser/index.html +2 -2
- google/adk/cli/browser/main-W7QZBYAR.js +3914 -0
- google/adk/cli/browser/polyfills-B6TNHZQ6.js +17 -0
- google/adk/cli/cli_eval.py +87 -12
- google/adk/cli/cli_tools_click.py +143 -82
- google/adk/cli/fast_api.py +150 -69
- google/adk/cli/utils/agent_loader.py +35 -1
- google/adk/code_executors/base_code_executor.py +14 -19
- google/adk/code_executors/built_in_code_executor.py +4 -1
- google/adk/evaluation/base_eval_service.py +46 -2
- google/adk/evaluation/eval_metrics.py +4 -0
- google/adk/evaluation/eval_sets_manager.py +5 -1
- google/adk/evaluation/evaluation_generator.py +1 -1
- google/adk/evaluation/final_response_match_v2.py +2 -2
- google/adk/evaluation/gcs_eval_sets_manager.py +2 -1
- google/adk/evaluation/in_memory_eval_sets_manager.py +151 -0
- google/adk/evaluation/local_eval_service.py +389 -0
- google/adk/evaluation/local_eval_set_results_manager.py +2 -2
- google/adk/evaluation/local_eval_sets_manager.py +24 -9
- google/adk/evaluation/metric_evaluator_registry.py +16 -6
- google/adk/evaluation/vertex_ai_eval_facade.py +7 -1
- google/adk/events/event.py +7 -2
- google/adk/flows/llm_flows/auto_flow.py +6 -11
- google/adk/flows/llm_flows/base_llm_flow.py +66 -29
- google/adk/flows/llm_flows/contents.py +16 -10
- google/adk/flows/llm_flows/functions.py +89 -52
- google/adk/memory/in_memory_memory_service.py +21 -15
- google/adk/memory/vertex_ai_memory_bank_service.py +12 -10
- google/adk/models/anthropic_llm.py +46 -6
- google/adk/models/base_llm_connection.py +2 -0
- google/adk/models/gemini_llm_connection.py +17 -6
- google/adk/models/google_llm.py +46 -11
- google/adk/models/lite_llm.py +52 -22
- google/adk/plugins/__init__.py +17 -0
- google/adk/plugins/base_plugin.py +317 -0
- google/adk/plugins/plugin_manager.py +265 -0
- google/adk/runners.py +122 -18
- google/adk/sessions/database_session_service.py +51 -52
- google/adk/sessions/vertex_ai_session_service.py +27 -12
- google/adk/tools/__init__.py +2 -0
- google/adk/tools/_automatic_function_calling_util.py +20 -2
- google/adk/tools/agent_tool.py +15 -3
- google/adk/tools/apihub_tool/apihub_toolset.py +38 -39
- google/adk/tools/application_integration_tool/application_integration_toolset.py +35 -37
- google/adk/tools/application_integration_tool/integration_connector_tool.py +2 -3
- google/adk/tools/base_tool.py +9 -9
- google/adk/tools/base_toolset.py +29 -5
- google/adk/tools/bigquery/__init__.py +3 -3
- google/adk/tools/bigquery/metadata_tool.py +2 -0
- google/adk/tools/bigquery/query_tool.py +15 -1
- google/adk/tools/computer_use/__init__.py +13 -0
- google/adk/tools/computer_use/base_computer.py +265 -0
- google/adk/tools/computer_use/computer_use_tool.py +166 -0
- google/adk/tools/computer_use/computer_use_toolset.py +220 -0
- google/adk/tools/enterprise_search_tool.py +4 -2
- google/adk/tools/exit_loop_tool.py +1 -0
- google/adk/tools/google_api_tool/google_api_tool.py +16 -1
- google/adk/tools/google_api_tool/google_api_toolset.py +9 -7
- google/adk/tools/google_api_tool/google_api_toolsets.py +41 -20
- google/adk/tools/google_search_tool.py +4 -2
- google/adk/tools/langchain_tool.py +16 -6
- google/adk/tools/long_running_tool.py +21 -0
- google/adk/tools/mcp_tool/mcp_toolset.py +27 -28
- google/adk/tools/openapi_tool/openapi_spec_parser/openapi_spec_parser.py +5 -0
- google/adk/tools/openapi_tool/openapi_spec_parser/openapi_toolset.py +8 -8
- google/adk/tools/openapi_tool/openapi_spec_parser/rest_api_tool.py +4 -6
- google/adk/tools/retrieval/vertex_ai_rag_retrieval.py +3 -2
- google/adk/tools/tool_context.py +0 -10
- google/adk/tools/url_context_tool.py +4 -2
- google/adk/tools/vertex_ai_search_tool.py +4 -2
- google/adk/utils/model_name_utils.py +90 -0
- google/adk/version.py +1 -1
- {google_adk-1.6.1.dist-info → google_adk-1.8.0.dist-info}/METADATA +3 -2
- {google_adk-1.6.1.dist-info → google_adk-1.8.0.dist-info}/RECORD +108 -91
- google/adk/cli/browser/main-RXDVX3K6.js +0 -3914
- google/adk/cli/browser/polyfills-FFHMD2TL.js +0 -17
- {google_adk-1.6.1.dist-info → google_adk-1.8.0.dist-info}/WHEEL +0 -0
- {google_adk-1.6.1.dist-info → google_adk-1.8.0.dist-info}/entry_points.txt +0 -0
- {google_adk-1.6.1.dist-info → google_adk-1.8.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,46 @@
|
|
1
|
+
# Copyright 2025 Google LLC
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
from __future__ import annotations
|
16
|
+
|
17
|
+
from typing import Union
|
18
|
+
|
19
|
+
from pydantic import RootModel
|
20
|
+
|
21
|
+
from ..utils.feature_decorator import working_in_progress
|
22
|
+
from .llm_agent import LlmAgentConfig
|
23
|
+
from .loop_agent import LoopAgentConfig
|
24
|
+
from .parallel_agent import ParallelAgentConfig
|
25
|
+
from .sequential_agent import SequentialAgentConfig
|
26
|
+
|
27
|
+
# A discriminated union of all possible agent configurations.
|
28
|
+
ConfigsUnion = Union[
|
29
|
+
LlmAgentConfig,
|
30
|
+
LoopAgentConfig,
|
31
|
+
ParallelAgentConfig,
|
32
|
+
SequentialAgentConfig,
|
33
|
+
]
|
34
|
+
|
35
|
+
|
36
|
+
# Use a RootModel to represent the agent directly at the top level.
|
37
|
+
# The `discriminator` is applied to the union within the RootModel.
|
38
|
+
@working_in_progress("AgentConfig is not ready for use.")
|
39
|
+
class AgentConfig(RootModel[ConfigsUnion]):
|
40
|
+
"""The config for the YAML schema to create an agent."""
|
41
|
+
|
42
|
+
class Config:
|
43
|
+
# Pydantic v2 requires this for discriminated unions on RootModel
|
44
|
+
# This tells the model to look at the 'agent_class' field of the input
|
45
|
+
# data to decide which model from the `ConfigsUnion` to use.
|
46
|
+
discriminator = "agent_class"
|
google/adk/agents/base_agent.py
CHANGED
@@ -19,24 +19,32 @@ from typing import Any
|
|
19
19
|
from typing import AsyncGenerator
|
20
20
|
from typing import Awaitable
|
21
21
|
from typing import Callable
|
22
|
+
from typing import Dict
|
22
23
|
from typing import final
|
24
|
+
from typing import List
|
25
|
+
from typing import Literal
|
23
26
|
from typing import Mapping
|
24
27
|
from typing import Optional
|
28
|
+
from typing import Type
|
25
29
|
from typing import TYPE_CHECKING
|
26
30
|
from typing import TypeVar
|
27
31
|
from typing import Union
|
28
32
|
|
29
33
|
from google.genai import types
|
30
34
|
from opentelemetry import trace
|
35
|
+
from pydantic import alias_generators
|
31
36
|
from pydantic import BaseModel
|
32
37
|
from pydantic import ConfigDict
|
33
38
|
from pydantic import Field
|
34
39
|
from pydantic import field_validator
|
40
|
+
from pydantic import model_validator
|
35
41
|
from typing_extensions import override
|
36
42
|
from typing_extensions import TypeAlias
|
37
43
|
|
38
44
|
from ..events.event import Event
|
45
|
+
from ..utils.feature_decorator import working_in_progress
|
39
46
|
from .callback_context import CallbackContext
|
47
|
+
from .common_configs import CodeConfig
|
40
48
|
|
41
49
|
if TYPE_CHECKING:
|
42
50
|
from .invocation_context import InvocationContext
|
@@ -223,11 +231,18 @@ class BaseAgent(BaseModel):
|
|
223
231
|
"""
|
224
232
|
with tracer.start_as_current_span(f'agent_run [{self.name}]'):
|
225
233
|
ctx = self._create_invocation_context(parent_context)
|
226
|
-
|
234
|
+
|
235
|
+
if event := await self.__handle_before_agent_callback(ctx):
|
236
|
+
yield event
|
237
|
+
if ctx.end_invocation:
|
238
|
+
return
|
227
239
|
|
228
240
|
async for event in self._run_live_impl(ctx):
|
229
241
|
yield event
|
230
242
|
|
243
|
+
if event := await self.__handle_after_agent_callback(ctx):
|
244
|
+
yield event
|
245
|
+
|
231
246
|
async def _run_async_impl(
|
232
247
|
self, ctx: InvocationContext
|
233
248
|
) -> AsyncGenerator[Event, None]:
|
@@ -331,73 +346,99 @@ class BaseAgent(BaseModel):
|
|
331
346
|
) -> Optional[Event]:
|
332
347
|
"""Runs the before_agent_callback if it exists.
|
333
348
|
|
349
|
+
Args:
|
350
|
+
ctx: InvocationContext, the invocation context for this agent.
|
351
|
+
|
334
352
|
Returns:
|
335
353
|
Optional[Event]: an event if callback provides content or changed state.
|
336
354
|
"""
|
337
|
-
ret_event = None
|
338
|
-
|
339
|
-
if not self.canonical_before_agent_callbacks:
|
340
|
-
return ret_event
|
341
|
-
|
342
355
|
callback_context = CallbackContext(ctx)
|
343
356
|
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
if inspect.isawaitable(before_agent_callback_content):
|
349
|
-
before_agent_callback_content = await before_agent_callback_content
|
350
|
-
if before_agent_callback_content:
|
351
|
-
ret_event = Event(
|
352
|
-
invocation_id=ctx.invocation_id,
|
353
|
-
author=self.name,
|
354
|
-
branch=ctx.branch,
|
355
|
-
content=before_agent_callback_content,
|
356
|
-
actions=callback_context._event_actions,
|
357
|
+
# Run callbacks from the plugins.
|
358
|
+
before_agent_callback_content = (
|
359
|
+
await ctx.plugin_manager.run_before_agent_callback(
|
360
|
+
agent=self, callback_context=callback_context
|
357
361
|
)
|
358
|
-
|
359
|
-
return ret_event
|
362
|
+
)
|
360
363
|
|
361
|
-
|
364
|
+
# If no overrides are provided from the plugins, further run the canonical
|
365
|
+
# callbacks.
|
366
|
+
if (
|
367
|
+
not before_agent_callback_content
|
368
|
+
and self.canonical_before_agent_callbacks
|
369
|
+
):
|
370
|
+
for callback in self.canonical_before_agent_callbacks:
|
371
|
+
before_agent_callback_content = callback(
|
372
|
+
callback_context=callback_context
|
373
|
+
)
|
374
|
+
if inspect.isawaitable(before_agent_callback_content):
|
375
|
+
before_agent_callback_content = await before_agent_callback_content
|
376
|
+
if before_agent_callback_content:
|
377
|
+
break
|
378
|
+
|
379
|
+
# Process the override content if exists, and further process the state
|
380
|
+
# change if exists.
|
381
|
+
if before_agent_callback_content:
|
362
382
|
ret_event = Event(
|
383
|
+
invocation_id=ctx.invocation_id,
|
384
|
+
author=self.name,
|
385
|
+
branch=ctx.branch,
|
386
|
+
content=before_agent_callback_content,
|
387
|
+
actions=callback_context._event_actions,
|
388
|
+
)
|
389
|
+
ctx.end_invocation = True
|
390
|
+
return ret_event
|
391
|
+
|
392
|
+
if callback_context.state.has_delta():
|
393
|
+
return Event(
|
363
394
|
invocation_id=ctx.invocation_id,
|
364
395
|
author=self.name,
|
365
396
|
branch=ctx.branch,
|
366
397
|
actions=callback_context._event_actions,
|
367
398
|
)
|
368
399
|
|
369
|
-
return
|
400
|
+
return None
|
370
401
|
|
371
402
|
async def __handle_after_agent_callback(
|
372
403
|
self, invocation_context: InvocationContext
|
373
404
|
) -> Optional[Event]:
|
374
405
|
"""Runs the after_agent_callback if it exists.
|
375
406
|
|
407
|
+
Args:
|
408
|
+
invocation_context: InvocationContext, the invocation context for this
|
409
|
+
agent.
|
410
|
+
|
376
411
|
Returns:
|
377
412
|
Optional[Event]: an event if callback provides content or changed state.
|
378
413
|
"""
|
379
|
-
ret_event = None
|
380
|
-
|
381
|
-
if not self.canonical_after_agent_callbacks:
|
382
|
-
return ret_event
|
383
414
|
|
384
415
|
callback_context = CallbackContext(invocation_context)
|
385
416
|
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
if after_agent_callback_content:
|
391
|
-
ret_event = Event(
|
392
|
-
invocation_id=invocation_context.invocation_id,
|
393
|
-
author=self.name,
|
394
|
-
branch=invocation_context.branch,
|
395
|
-
content=after_agent_callback_content,
|
396
|
-
actions=callback_context._event_actions,
|
417
|
+
# Run callbacks from the plugins.
|
418
|
+
after_agent_callback_content = (
|
419
|
+
await invocation_context.plugin_manager.run_after_agent_callback(
|
420
|
+
agent=self, callback_context=callback_context
|
397
421
|
)
|
398
|
-
|
422
|
+
)
|
399
423
|
|
400
|
-
|
424
|
+
# If no overrides are provided from the plugins, further run the canonical
|
425
|
+
# callbacks.
|
426
|
+
if (
|
427
|
+
not after_agent_callback_content
|
428
|
+
and self.canonical_after_agent_callbacks
|
429
|
+
):
|
430
|
+
for callback in self.canonical_after_agent_callbacks:
|
431
|
+
after_agent_callback_content = callback(
|
432
|
+
callback_context=callback_context
|
433
|
+
)
|
434
|
+
if inspect.isawaitable(after_agent_callback_content):
|
435
|
+
after_agent_callback_content = await after_agent_callback_content
|
436
|
+
if after_agent_callback_content:
|
437
|
+
break
|
438
|
+
|
439
|
+
# Process the override content if exists, and further process the state
|
440
|
+
# change if exists.
|
441
|
+
if after_agent_callback_content:
|
401
442
|
ret_event = Event(
|
402
443
|
invocation_id=invocation_context.invocation_id,
|
403
444
|
author=self.name,
|
@@ -405,8 +446,17 @@ class BaseAgent(BaseModel):
|
|
405
446
|
content=after_agent_callback_content,
|
406
447
|
actions=callback_context._event_actions,
|
407
448
|
)
|
449
|
+
return ret_event
|
408
450
|
|
409
|
-
|
451
|
+
if callback_context.state.has_delta():
|
452
|
+
return Event(
|
453
|
+
invocation_id=invocation_context.invocation_id,
|
454
|
+
author=self.name,
|
455
|
+
branch=invocation_context.branch,
|
456
|
+
content=after_agent_callback_content,
|
457
|
+
actions=callback_context._event_actions,
|
458
|
+
)
|
459
|
+
return None
|
410
460
|
|
411
461
|
@override
|
412
462
|
def model_post_init(self, __context: Any) -> None:
|
@@ -439,3 +489,151 @@ class BaseAgent(BaseModel):
|
|
439
489
|
)
|
440
490
|
sub_agent.parent_agent = self
|
441
491
|
return self
|
492
|
+
|
493
|
+
@classmethod
|
494
|
+
@working_in_progress('BaseAgent.from_config is not ready for use.')
|
495
|
+
def from_config(
|
496
|
+
cls: Type[SelfAgent],
|
497
|
+
config: BaseAgentConfig,
|
498
|
+
config_abs_path: str,
|
499
|
+
) -> SelfAgent:
|
500
|
+
"""Creates an agent from a config.
|
501
|
+
|
502
|
+
This method converts fields in a config to the corresponding
|
503
|
+
fields in an agent.
|
504
|
+
|
505
|
+
Child classes should re-implement this method to support loading from their
|
506
|
+
custom config types.
|
507
|
+
|
508
|
+
Args:
|
509
|
+
config: The config to create the agent from.
|
510
|
+
|
511
|
+
Returns:
|
512
|
+
The created agent.
|
513
|
+
"""
|
514
|
+
from .config_agent_utils import build_sub_agent
|
515
|
+
from .config_agent_utils import resolve_callbacks
|
516
|
+
|
517
|
+
kwargs: Dict[str, Any] = {
|
518
|
+
'name': config.name,
|
519
|
+
'description': config.description,
|
520
|
+
}
|
521
|
+
if config.sub_agents:
|
522
|
+
sub_agents = []
|
523
|
+
for sub_agent_config in config.sub_agents:
|
524
|
+
sub_agent = build_sub_agent(
|
525
|
+
sub_agent_config, config_abs_path.rsplit('/', 1)[0]
|
526
|
+
)
|
527
|
+
sub_agents.append(sub_agent)
|
528
|
+
kwargs['sub_agents'] = sub_agents
|
529
|
+
|
530
|
+
if config.before_agent_callbacks:
|
531
|
+
kwargs['before_agent_callback'] = resolve_callbacks(
|
532
|
+
config.before_agent_callbacks
|
533
|
+
)
|
534
|
+
if config.after_agent_callbacks:
|
535
|
+
kwargs['after_agent_callback'] = resolve_callbacks(
|
536
|
+
config.after_agent_callbacks
|
537
|
+
)
|
538
|
+
return cls(**kwargs)
|
539
|
+
|
540
|
+
|
541
|
+
class SubAgentConfig(BaseModel):
|
542
|
+
"""The config for a sub-agent."""
|
543
|
+
|
544
|
+
model_config = ConfigDict(extra='forbid')
|
545
|
+
|
546
|
+
config: Optional[str] = None
|
547
|
+
"""The YAML config file path of the sub-agent.
|
548
|
+
|
549
|
+
Only one of `config` or `code` can be set.
|
550
|
+
|
551
|
+
Example:
|
552
|
+
|
553
|
+
```
|
554
|
+
sub_agents:
|
555
|
+
- config: search_agent.yaml
|
556
|
+
- config: my_library/my_custom_agent.yaml
|
557
|
+
```
|
558
|
+
"""
|
559
|
+
|
560
|
+
code: Optional[str] = None
|
561
|
+
"""The agent instance defined in the code.
|
562
|
+
|
563
|
+
Only one of `config` or `code` can be set.
|
564
|
+
|
565
|
+
Example:
|
566
|
+
|
567
|
+
For the following agent defined in Python code:
|
568
|
+
|
569
|
+
```
|
570
|
+
# my_library/custom_agents.py
|
571
|
+
from google.adk.agents import LlmAgent
|
572
|
+
|
573
|
+
my_custom_agent = LlmAgent(
|
574
|
+
name="my_custom_agent",
|
575
|
+
instruction="You are a helpful custom agent.",
|
576
|
+
model="gemini-2.0-flash",
|
577
|
+
)
|
578
|
+
```
|
579
|
+
|
580
|
+
The yaml config should be:
|
581
|
+
|
582
|
+
```
|
583
|
+
sub_agents:
|
584
|
+
- code: my_library.custom_agents.my_custom_agent
|
585
|
+
```
|
586
|
+
"""
|
587
|
+
|
588
|
+
@model_validator(mode='after')
|
589
|
+
def validate_exactly_one_field(self):
|
590
|
+
code_provided = self.code is not None
|
591
|
+
config_provided = self.config is not None
|
592
|
+
|
593
|
+
if code_provided and config_provided:
|
594
|
+
raise ValueError('Only one of code or config should be provided')
|
595
|
+
if not code_provided and not config_provided:
|
596
|
+
raise ValueError('Exactly one of code or config must be provided')
|
597
|
+
|
598
|
+
return self
|
599
|
+
|
600
|
+
|
601
|
+
@working_in_progress('BaseAgentConfig is not ready for use.')
|
602
|
+
class BaseAgentConfig(BaseModel):
|
603
|
+
"""The config for the YAML schema of a BaseAgent.
|
604
|
+
|
605
|
+
Do not use this class directly. It's the base class for all agent configs.
|
606
|
+
"""
|
607
|
+
|
608
|
+
model_config = ConfigDict(
|
609
|
+
extra='forbid',
|
610
|
+
alias_generator=alias_generators.to_camel,
|
611
|
+
populate_by_name=True,
|
612
|
+
)
|
613
|
+
|
614
|
+
agent_class: Literal['BaseAgent'] = 'BaseAgent'
|
615
|
+
"""Required. The class of the agent. The value is used to differentiate
|
616
|
+
among different agent classes."""
|
617
|
+
|
618
|
+
name: str
|
619
|
+
"""Required. The name of the agent."""
|
620
|
+
|
621
|
+
description: str = ''
|
622
|
+
"""Optional. The description of the agent."""
|
623
|
+
|
624
|
+
sub_agents: Optional[List[SubAgentConfig]] = None
|
625
|
+
"""Optional. The sub-agents of the agent."""
|
626
|
+
|
627
|
+
before_agent_callbacks: Optional[List[CodeConfig]] = None
|
628
|
+
"""Optional. The before_agent_callbacks of the agent.
|
629
|
+
|
630
|
+
Example:
|
631
|
+
|
632
|
+
```
|
633
|
+
before_agent_callbacks:
|
634
|
+
- name: my_library.security_callbacks.before_agent_callback
|
635
|
+
```
|
636
|
+
"""
|
637
|
+
|
638
|
+
after_agent_callbacks: Optional[List[CodeConfig]] = None
|
639
|
+
"""Optional. The after_agent_callbacks of the agent."""
|
@@ -24,6 +24,8 @@ from .readonly_context import ReadonlyContext
|
|
24
24
|
if TYPE_CHECKING:
|
25
25
|
from google.genai import types
|
26
26
|
|
27
|
+
from ..auth.auth_credential import AuthCredential
|
28
|
+
from ..auth.auth_tool import AuthConfig
|
27
29
|
from ..events.event_actions import EventActions
|
28
30
|
from ..sessions.state import State
|
29
31
|
from .invocation_context import InvocationContext
|
@@ -105,3 +107,42 @@ class CallbackContext(ReadonlyContext):
|
|
105
107
|
)
|
106
108
|
self._event_actions.artifact_delta[filename] = version
|
107
109
|
return version
|
110
|
+
|
111
|
+
async def list_artifacts(self) -> list[str]:
|
112
|
+
"""Lists the filenames of the artifacts attached to the current session."""
|
113
|
+
if self._invocation_context.artifact_service is None:
|
114
|
+
raise ValueError("Artifact service is not initialized.")
|
115
|
+
return await self._invocation_context.artifact_service.list_artifact_keys(
|
116
|
+
app_name=self._invocation_context.app_name,
|
117
|
+
user_id=self._invocation_context.user_id,
|
118
|
+
session_id=self._invocation_context.session.id,
|
119
|
+
)
|
120
|
+
|
121
|
+
async def save_credential(self, auth_config: AuthConfig) -> None:
|
122
|
+
"""Saves a credential to the credential service.
|
123
|
+
|
124
|
+
Args:
|
125
|
+
auth_config: The authentication configuration containing the credential.
|
126
|
+
"""
|
127
|
+
if self._invocation_context.credential_service is None:
|
128
|
+
raise ValueError("Credential service is not initialized.")
|
129
|
+
await self._invocation_context.credential_service.save_credential(
|
130
|
+
auth_config, self
|
131
|
+
)
|
132
|
+
|
133
|
+
async def load_credential(
|
134
|
+
self, auth_config: AuthConfig
|
135
|
+
) -> Optional[AuthCredential]:
|
136
|
+
"""Loads a credential from the credential service.
|
137
|
+
|
138
|
+
Args:
|
139
|
+
auth_config: The authentication configuration for the credential.
|
140
|
+
|
141
|
+
Returns:
|
142
|
+
The loaded credential, or None if not found.
|
143
|
+
"""
|
144
|
+
if self._invocation_context.credential_service is None:
|
145
|
+
raise ValueError("Credential service is not initialized.")
|
146
|
+
return await self._invocation_context.credential_service.load_credential(
|
147
|
+
auth_config, self
|
148
|
+
)
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# Copyright 2025 Google LLC
|
2
|
+
#
|
3
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
# you may not use this file except in compliance with the License.
|
5
|
+
# You may obtain a copy of the License at
|
6
|
+
#
|
7
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
#
|
9
|
+
# Unless required by applicable law or agreed to in writing, software
|
10
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
# See the License for the specific language governing permissions and
|
13
|
+
# limitations under the License.
|
14
|
+
|
15
|
+
"""Common configuration classes for agent YAML configs."""
|
16
|
+
from __future__ import annotations
|
17
|
+
|
18
|
+
from typing import Any
|
19
|
+
from typing import List
|
20
|
+
from typing import Optional
|
21
|
+
|
22
|
+
from pydantic import BaseModel
|
23
|
+
from pydantic import ConfigDict
|
24
|
+
|
25
|
+
from ..utils.feature_decorator import working_in_progress
|
26
|
+
|
27
|
+
|
28
|
+
@working_in_progress("ArgumentConfig is not ready for use.")
|
29
|
+
class ArgumentConfig(BaseModel):
|
30
|
+
"""An argument passed to a function or a class's constructor."""
|
31
|
+
|
32
|
+
model_config = ConfigDict(extra="forbid")
|
33
|
+
|
34
|
+
name: Optional[str] = None
|
35
|
+
"""Optional. The argument name.
|
36
|
+
|
37
|
+
When the argument is for a positional argument, this can be omitted.
|
38
|
+
"""
|
39
|
+
|
40
|
+
value: Any
|
41
|
+
"""The argument value."""
|
42
|
+
|
43
|
+
|
44
|
+
@working_in_progress("CodeConfig is not ready for use.")
|
45
|
+
class CodeConfig(BaseModel):
|
46
|
+
"""Code reference config for a variable, a function, or a class.
|
47
|
+
|
48
|
+
This config is used for configuring callbacks and tools.
|
49
|
+
"""
|
50
|
+
|
51
|
+
model_config = ConfigDict(extra="forbid")
|
52
|
+
|
53
|
+
name: str
|
54
|
+
"""Required. The name of the variable, function, class, etc. in code.
|
55
|
+
|
56
|
+
Examples:
|
57
|
+
|
58
|
+
When used for tools,
|
59
|
+
- It can be ADK built-in tools, such as `google_search` and `AgentTool`.
|
60
|
+
- It can also be users' custom tools, e.g. my_library.my_tools.my_tool.
|
61
|
+
|
62
|
+
When used for callbacks, it refers to a function, e.g. `my_library.my_callbacks.my_callback`
|
63
|
+
"""
|
64
|
+
|
65
|
+
args: Optional[List[ArgumentConfig]] = None
|
66
|
+
"""Optional. The arguments for the code when `name` refers to a function or a
|
67
|
+
class's contructor.
|
68
|
+
|
69
|
+
Examples:
|
70
|
+
```
|
71
|
+
tools
|
72
|
+
- name: AgentTool
|
73
|
+
args:
|
74
|
+
- name: agent
|
75
|
+
value: search_agent.yaml
|
76
|
+
- name: skip_summarization
|
77
|
+
value: True
|
78
|
+
```
|
79
|
+
"""
|