solace-agent-mesh 1.6.0__py3-none-any.whl → 1.6.2__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.

Potentially problematic release.


This version of solace-agent-mesh might be problematic. Click here for more details.

Files changed (127) hide show
  1. solace_agent_mesh/agent/adk/app_llm_agent.py +26 -0
  2. solace_agent_mesh/agent/adk/artifacts/filesystem_artifact_service.py +1 -1
  3. solace_agent_mesh/agent/adk/embed_resolving_mcp_toolset.py +135 -31
  4. solace_agent_mesh/agent/adk/models/lite_llm.py +5 -0
  5. solace_agent_mesh/agent/adk/runner.py +10 -12
  6. solace_agent_mesh/agent/adk/services.py +50 -14
  7. solace_agent_mesh/agent/adk/setup.py +66 -38
  8. solace_agent_mesh/agent/protocol/event_handlers.py +416 -152
  9. solace_agent_mesh/agent/proxies/a2a/app.py +3 -2
  10. solace_agent_mesh/agent/proxies/base/app.py +3 -2
  11. solace_agent_mesh/agent/proxies/base/component.py +35 -4
  12. solace_agent_mesh/agent/sac/app.py +97 -9
  13. solace_agent_mesh/agent/sac/component.py +284 -145
  14. solace_agent_mesh/agent/sac/task_execution_context.py +79 -2
  15. solace_agent_mesh/agent/tools/tool_config_types.py +3 -0
  16. solace_agent_mesh/agent/utils/artifact_helpers.py +1 -1
  17. solace_agent_mesh/assets/docs/404.html +3 -3
  18. solace_agent_mesh/assets/docs/assets/js/240a0364.c39f8388.js +1 -0
  19. solace_agent_mesh/assets/docs/assets/js/631738c7.7c4594c9.js +1 -0
  20. solace_agent_mesh/assets/docs/assets/js/66d4869e.830d443f.js +1 -0
  21. solace_agent_mesh/assets/docs/assets/js/71da7b71.ddbdfbe2.js +1 -0
  22. solace_agent_mesh/assets/docs/assets/js/{e3d9abda.2b916f9e.js → e3d9abda.6b9493d0.js} +1 -1
  23. solace_agent_mesh/assets/docs/assets/js/e92d0134.4f395c6b.js +1 -0
  24. solace_agent_mesh/assets/docs/assets/js/f284c35a.720d2ef2.js +1 -0
  25. solace_agent_mesh/assets/docs/assets/js/main.d1643f0b.js +2 -0
  26. solace_agent_mesh/assets/docs/assets/js/runtime~main.97f920d4.js +1 -0
  27. solace_agent_mesh/assets/docs/docs/documentation/components/agents/index.html +3 -3
  28. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/artifact-management/index.html +3 -3
  29. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/audio-tools/index.html +3 -3
  30. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/data-analysis-tools/index.html +3 -3
  31. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/embeds/index.html +3 -3
  32. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/index.html +3 -3
  33. solace_agent_mesh/assets/docs/docs/documentation/components/cli/index.html +3 -3
  34. solace_agent_mesh/assets/docs/docs/documentation/components/gateways/index.html +3 -3
  35. solace_agent_mesh/assets/docs/docs/documentation/components/index.html +3 -3
  36. solace_agent_mesh/assets/docs/docs/documentation/components/orchestrator/index.html +3 -3
  37. solace_agent_mesh/assets/docs/docs/documentation/components/plugins/index.html +3 -3
  38. solace_agent_mesh/assets/docs/docs/documentation/components/proxies/index.html +3 -3
  39. solace_agent_mesh/assets/docs/docs/documentation/deploying/debugging/index.html +4 -25
  40. solace_agent_mesh/assets/docs/docs/documentation/deploying/deployment-options/index.html +4 -4
  41. solace_agent_mesh/assets/docs/docs/documentation/deploying/index.html +4 -4
  42. solace_agent_mesh/assets/docs/docs/documentation/deploying/logging/index.html +76 -0
  43. solace_agent_mesh/assets/docs/docs/documentation/deploying/observability/index.html +5 -4
  44. solace_agent_mesh/assets/docs/docs/documentation/developing/create-agents/index.html +3 -3
  45. solace_agent_mesh/assets/docs/docs/documentation/developing/create-gateways/index.html +3 -3
  46. solace_agent_mesh/assets/docs/docs/documentation/developing/creating-python-tools/index.html +3 -3
  47. solace_agent_mesh/assets/docs/docs/documentation/developing/creating-service-providers/index.html +3 -3
  48. solace_agent_mesh/assets/docs/docs/documentation/developing/evaluations/index.html +3 -3
  49. solace_agent_mesh/assets/docs/docs/documentation/developing/index.html +3 -3
  50. solace_agent_mesh/assets/docs/docs/documentation/developing/structure/index.html +3 -3
  51. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/bedrock-agents/index.html +3 -3
  52. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/custom-agent/index.html +3 -3
  53. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/event-mesh-gateway/index.html +3 -3
  54. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/mcp-integration/index.html +3 -3
  55. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/mongodb-integration/index.html +3 -3
  56. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/rag-integration/index.html +3 -3
  57. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/rest-gateway/index.html +3 -3
  58. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/slack-integration/index.html +3 -3
  59. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/sql-database/index.html +3 -3
  60. solace_agent_mesh/assets/docs/docs/documentation/enterprise/index.html +3 -3
  61. solace_agent_mesh/assets/docs/docs/documentation/enterprise/installation/index.html +3 -3
  62. solace_agent_mesh/assets/docs/docs/documentation/enterprise/rbac-setup-guide/index.html +3 -3
  63. solace_agent_mesh/assets/docs/docs/documentation/enterprise/single-sign-on/index.html +3 -3
  64. solace_agent_mesh/assets/docs/docs/documentation/getting-started/architecture/index.html +3 -3
  65. solace_agent_mesh/assets/docs/docs/documentation/getting-started/index.html +3 -3
  66. solace_agent_mesh/assets/docs/docs/documentation/getting-started/introduction/index.html +3 -3
  67. solace_agent_mesh/assets/docs/docs/documentation/getting-started/try-agent-mesh/index.html +3 -3
  68. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/configurations/index.html +3 -6
  69. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/index.html +3 -3
  70. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/installation/index.html +3 -3
  71. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/large_language_models/index.html +3 -3
  72. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/run-project/index.html +3 -3
  73. solace_agent_mesh/assets/docs/docs/documentation/migrations/a2a-upgrade/a2a-gateway-upgrade-to-0.3.0/index.html +3 -3
  74. solace_agent_mesh/assets/docs/docs/documentation/migrations/a2a-upgrade/a2a-technical-migration-map/index.html +3 -3
  75. solace_agent_mesh/assets/docs/lunr-index-1761663789856.json +1 -0
  76. solace_agent_mesh/assets/docs/lunr-index.json +1 -1
  77. solace_agent_mesh/assets/docs/search-doc-1761663789856.json +1 -0
  78. solace_agent_mesh/assets/docs/search-doc.json +1 -1
  79. solace_agent_mesh/assets/docs/sitemap.xml +1 -1
  80. solace_agent_mesh/cli/__init__.py +1 -1
  81. solace_agent_mesh/client/webui/frontend/static/assets/{authCallback-BTf6dqwp.js → authCallback-D4_RMYRh.js} +1 -1
  82. solace_agent_mesh/client/webui/frontend/static/assets/{client-CaY59VuC.js → client-UZ3qU6Bq.js} +1 -1
  83. solace_agent_mesh/client/webui/frontend/static/assets/main--3yJYl7S.css +1 -0
  84. solace_agent_mesh/client/webui/frontend/static/assets/main-DojKHS49.js +342 -0
  85. solace_agent_mesh/client/webui/frontend/static/assets/{vendor-BEmvJSYz.js → vendor-DSqhjwq_.js} +1 -1
  86. solace_agent_mesh/client/webui/frontend/static/auth-callback.html +3 -3
  87. solace_agent_mesh/client/webui/frontend/static/index.html +4 -4
  88. solace_agent_mesh/common/a2a/events.py +2 -1
  89. solace_agent_mesh/common/a2a/protocol.py +78 -0
  90. solace_agent_mesh/common/sac/sam_component_base.py +406 -21
  91. solace_agent_mesh/common/utils/pydantic_utils.py +90 -3
  92. solace_agent_mesh/gateway/base/app.py +15 -0
  93. solace_agent_mesh/gateway/base/component.py +116 -46
  94. solace_agent_mesh/gateway/http_sse/app.py +7 -0
  95. solace_agent_mesh/gateway/http_sse/component.py +18 -10
  96. solace_agent_mesh/gateway/http_sse/dependencies.py +83 -59
  97. solace_agent_mesh/gateway/http_sse/main.py +5 -4
  98. solace_agent_mesh/gateway/http_sse/routers/agent_cards.py +1 -1
  99. solace_agent_mesh/gateway/http_sse/routers/auth.py +103 -6
  100. solace_agent_mesh/gateway/http_sse/routers/config.py +1 -1
  101. solace_agent_mesh/gateway/http_sse/routers/sessions.py +1 -1
  102. solace_agent_mesh/gateway/http_sse/routers/sse.py +15 -5
  103. solace_agent_mesh/gateway/http_sse/routers/tasks.py +3 -3
  104. solace_agent_mesh/gateway/http_sse/routers/users.py +47 -1
  105. solace_agent_mesh/gateway/http_sse/routers/visualization.py +90 -8
  106. solace_agent_mesh/gateway/http_sse/services/session_service.py +1 -1
  107. solace_agent_mesh/gateway/http_sse/session_manager.py +15 -15
  108. solace_agent_mesh/gateway/http_sse/shared/exception_handlers.py +16 -1
  109. solace_agent_mesh/gateway/http_sse/sse_manager.py +15 -6
  110. solace_agent_mesh/templates/logging_config_template.ini +2 -2
  111. {solace_agent_mesh-1.6.0.dist-info → solace_agent_mesh-1.6.2.dist-info}/METADATA +2 -2
  112. {solace_agent_mesh-1.6.0.dist-info → solace_agent_mesh-1.6.2.dist-info}/RECORD +116 -114
  113. solace_agent_mesh/assets/docs/assets/js/240a0364.7eac6021.js +0 -1
  114. solace_agent_mesh/assets/docs/assets/js/631738c7.a8b1ef8b.js +0 -1
  115. solace_agent_mesh/assets/docs/assets/js/71da7b71.38583438.js +0 -1
  116. solace_agent_mesh/assets/docs/assets/js/e92d0134.cf6d6522.js +0 -1
  117. solace_agent_mesh/assets/docs/assets/js/f284c35a.42f59cdd.js +0 -1
  118. solace_agent_mesh/assets/docs/assets/js/main.20feee82.js +0 -2
  119. solace_agent_mesh/assets/docs/assets/js/runtime~main.0d198646.js +0 -1
  120. solace_agent_mesh/assets/docs/lunr-index-1761165361160.json +0 -1
  121. solace_agent_mesh/assets/docs/search-doc-1761165361160.json +0 -1
  122. solace_agent_mesh/client/webui/frontend/static/assets/main-BGTaW0uv.js +0 -342
  123. solace_agent_mesh/client/webui/frontend/static/assets/main-DHJKSW1S.css +0 -1
  124. /solace_agent_mesh/assets/docs/assets/js/{main.20feee82.js.LICENSE.txt → main.d1643f0b.js.LICENSE.txt} +0 -0
  125. {solace_agent_mesh-1.6.0.dist-info → solace_agent_mesh-1.6.2.dist-info}/WHEEL +0 -0
  126. {solace_agent_mesh-1.6.0.dist-info → solace_agent_mesh-1.6.2.dist-info}/entry_points.txt +0 -0
  127. {solace_agent_mesh-1.6.0.dist-info → solace_agent_mesh-1.6.2.dist-info}/licenses/LICENSE +0 -0
@@ -2,79 +2,80 @@
2
2
  Custom Solace AI Connector Component to Host Google ADK Agents via A2A Protocol.
3
3
  """
4
4
 
5
- import logging
6
- from typing import Any, Dict, Optional, Union, Callable, List, Tuple, TYPE_CHECKING
7
5
  import asyncio
8
- import functools
9
- import threading
10
6
  import concurrent.futures
11
7
  import fnmatch
12
- import time
8
+ import functools
9
+ import inspect
13
10
  import json
14
- from solace_ai_connector.common.message import (
15
- Message as SolaceMessage,
16
- )
17
- from solace_ai_connector.common.event import Event, EventType
11
+ import logging
12
+ import threading
13
+ import time
14
+ from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Tuple, Union
18
15
 
19
- from solace_ai_connector.common.utils import import_module
20
- import inspect
21
- from pydantic import BaseModel, ValidationError
22
- from google.adk.agents.invocation_context import (
23
- LlmCallsLimitExceededError,
24
- )
25
- from google.adk.agents import RunConfig
26
- from google.adk.agents.run_config import StreamingMode
27
- from google.adk.sessions import BaseSessionService
28
- from google.adk.artifacts import BaseArtifactService
29
- from google.adk.memory import BaseMemoryService
30
- from google.adk.agents import LlmAgent
31
- from google.adk.runners import Runner
32
- from google.adk.models import LlmResponse
33
- from google.adk.agents.readonly_context import ReadonlyContext
34
- from google.adk.events import Event as ADKEvent
35
- from google.adk.agents.callback_context import CallbackContext
36
- from google.adk.models.llm_request import LlmRequest
37
- from google.genai import types as adk_types
38
- from google.adk.tools.mcp_tool import MCPToolset
39
16
  from a2a.types import (
40
17
  AgentCard,
41
- Artifact as A2AArtifact,
42
- Message as A2AMessage,
43
18
  MessageSendParams,
44
19
  SendMessageRequest,
45
20
  TaskState,
46
21
  TaskStatus,
47
22
  TaskStatusUpdateEvent,
48
23
  )
49
- from ...common import a2a
50
- from ...common.data_parts import AgentProgressUpdateData
51
- from ...common.a2a.translation import format_and_route_adk_event
52
- from ...agent.utils.config_parser import resolve_instruction_provider
24
+ from a2a.types import Artifact as A2AArtifact
25
+ from a2a.types import Message as A2AMessage
26
+ from google.adk.agents import LlmAgent, RunConfig
27
+ from google.adk.agents.callback_context import CallbackContext
28
+ from google.adk.agents.invocation_context import LlmCallsLimitExceededError
29
+ from google.adk.agents.readonly_context import ReadonlyContext
30
+ from google.adk.agents.run_config import StreamingMode
31
+ from google.adk.artifacts import BaseArtifactService
32
+ from google.adk.auth.credential_service.base_credential_service import (
33
+ BaseCredentialService,
34
+ )
35
+ from google.adk.events import Event as ADKEvent
36
+ from google.adk.memory import BaseMemoryService
37
+ from google.adk.models import LlmResponse
38
+ from google.adk.models.llm_request import LlmRequest
39
+ from google.adk.runners import Runner
40
+ from google.adk.sessions import BaseSessionService
41
+ from google.adk.tools.mcp_tool import MCPToolset
42
+ from google.genai import types as adk_types
43
+ from pydantic import BaseModel, ValidationError
44
+ from solace_ai_connector.common.event import Event, EventType
45
+ from solace_ai_connector.common.message import Message as SolaceMessage
46
+ from solace_ai_connector.common.utils import import_module
47
+
48
+ from ...agent.adk.runner import TaskCancelledError, run_adk_async_task_thread_wrapper
53
49
  from ...agent.adk.services import (
54
- initialize_session_service,
55
50
  initialize_artifact_service,
51
+ initialize_credential_service,
56
52
  initialize_memory_service,
53
+ initialize_session_service,
57
54
  )
58
55
  from ...agent.adk.setup import (
59
- load_adk_tools,
60
56
  initialize_adk_agent,
61
57
  initialize_adk_runner,
58
+ load_adk_tools,
62
59
  )
63
- from ...agent.protocol.event_handlers import (
64
- process_event,
65
- publish_agent_card,
66
- )
67
- from ...agent.adk.runner import run_adk_async_task_thread_wrapper, TaskCancelledError
60
+ from ...agent.protocol.event_handlers import process_event, publish_agent_card
68
61
  from ...agent.tools.peer_agent_tool import (
69
62
  CORRELATION_DATA_PREFIX,
70
- PeerAgentTool,
71
63
  PEER_TOOL_PREFIX,
64
+ PeerAgentTool,
72
65
  )
73
- from ...common.middleware.registry import MiddlewareRegistry
74
- from ...common.constants import DEFAULT_COMMUNICATION_TIMEOUT, HEALTH_CHECK_TTL_SECONDS, HEALTH_CHECK_INTERVAL_SECONDS
75
66
  from ...agent.tools.registry import tool_registry
76
- from ...common.sac.sam_component_base import SamComponentBase
67
+ from ...agent.utils.config_parser import resolve_instruction_provider
68
+ from ...common import a2a
69
+ from ...common.a2a.translation import format_and_route_adk_event
77
70
  from ...common.agent_registry import AgentRegistry
71
+ from ...common.constants import (
72
+ DEFAULT_COMMUNICATION_TIMEOUT,
73
+ HEALTH_CHECK_INTERVAL_SECONDS,
74
+ HEALTH_CHECK_TTL_SECONDS,
75
+ )
76
+ from ...common.data_parts import AgentProgressUpdateData
77
+ from ...common.middleware.registry import MiddlewareRegistry
78
+ from ...common.sac.sam_component_base import SamComponentBase
78
79
 
79
80
  log = logging.getLogger(__name__)
80
81
 
@@ -103,7 +104,6 @@ info = {
103
104
  }
104
105
  InstructionProvider = Callable[[ReadonlyContext], str]
105
106
 
106
-
107
107
  class SamAgentComponent(SamComponentBase):
108
108
  """
109
109
  A Solace AI Connector component that hosts a Google ADK agent,
@@ -128,7 +128,7 @@ class SamAgentComponent(SamComponentBase):
128
128
 
129
129
  super().__init__(info, **kwargs)
130
130
  self.agent_name = self.get_config("agent_name")
131
- log.info("%s Initializing A2A ADK Host Component...", self.log_identifier)
131
+ log.info("%s Initializing agent: %s (A2A ADK Host Component)...", self.log_identifier, self.agent_name)
132
132
 
133
133
  # Initialize the agent registry for health tracking
134
134
  self.agent_registry = AgentRegistry()
@@ -226,7 +226,6 @@ class SamAgentComponent(SamComponentBase):
226
226
  "max_message_size_bytes", 10_000_000
227
227
  )
228
228
 
229
- log.info("%s Configuration retrieved successfully.", self.log_identifier)
230
229
  except Exception as e:
231
230
  log.error(
232
231
  "%s Failed to retrieve configuration via get_config: %s",
@@ -237,6 +236,7 @@ class SamAgentComponent(SamComponentBase):
237
236
  self.session_service: BaseSessionService = None
238
237
  self.artifact_service: BaseArtifactService = None
239
238
  self.memory_service: BaseMemoryService = None
239
+ self.credential_service: Optional[BaseCredentialService] = None
240
240
  self.adk_agent: LlmAgent = None
241
241
  self.runner: Runner = None
242
242
  self.agent_card_tool_manifest: List[Dict[str, Any]] = []
@@ -265,9 +265,10 @@ class SamAgentComponent(SamComponentBase):
265
265
  self.session_service = initialize_session_service(self)
266
266
  self.artifact_service = initialize_artifact_service(self)
267
267
  self.memory_service = initialize_memory_service(self)
268
+ self.credential_service = initialize_credential_service(self)
268
269
 
269
270
  log.info(
270
- "%s Synchronous ADK services initialized.", self.log_identifier
271
+ "%s Initialized Synchronous ADK services.", self.log_identifier
271
272
  )
272
273
  except Exception as service_err:
273
274
  log.exception(
@@ -279,8 +280,25 @@ class SamAgentComponent(SamComponentBase):
279
280
  f"Failed to initialize synchronous ADK services: {service_err}"
280
281
  ) from service_err
281
282
 
282
- from .app import AgentInitCleanupConfig # delayed import to avoid circular dependency
283
- if init_func_details and isinstance(init_func_details, AgentInitCleanupConfig):
283
+ # initialize enterprise features if available
284
+ try:
285
+ from solace_agent_mesh_enterprise.init_enterprise_component import (
286
+ init_enterprise_component_features,
287
+ )
288
+
289
+ init_enterprise_component_features(self)
290
+ except ImportError:
291
+ # Community edition
292
+ # Contact Solace support for enterprise features
293
+ pass
294
+
295
+ from .app import (
296
+ AgentInitCleanupConfig,
297
+ ) # delayed import to avoid circular dependency
298
+
299
+ if init_func_details and isinstance(
300
+ init_func_details, AgentInitCleanupConfig
301
+ ):
284
302
  module_name = init_func_details.get("module")
285
303
  func_name = init_func_details.get("name")
286
304
  base_path = init_func_details.get("base_path")
@@ -407,10 +425,12 @@ class SamAgentComponent(SamComponentBase):
407
425
  self.log_identifier,
408
426
  publish_interval_sec,
409
427
  )
428
+ # Register timer with callback
410
429
  self.add_timer(
411
430
  delay_ms=1000,
412
431
  timer_id=self._card_publish_timer_id,
413
432
  interval_ms=publish_interval_sec * 1000,
433
+ callback=lambda timer_data: publish_agent_card(self),
414
434
  )
415
435
  else:
416
436
  log.warning(
@@ -430,6 +450,7 @@ class SamAgentComponent(SamComponentBase):
430
450
  delay_ms=health_check_interval_seconds * 1000,
431
451
  timer_id=self.HEALTH_CHECK_TIMER_ID,
432
452
  interval_ms=health_check_interval_seconds * 1000,
453
+ callback=lambda timer_data: self._check_agent_health(),
433
454
  )
434
455
  else:
435
456
  log.warning(
@@ -438,7 +459,7 @@ class SamAgentComponent(SamComponentBase):
438
459
  )
439
460
 
440
461
  log.info(
441
- "%s Initialization complete for agent: %s",
462
+ "%s Initialized agent: %s",
442
463
  self.log_identifier,
443
464
  self.agent_name,
444
465
  )
@@ -446,79 +467,35 @@ class SamAgentComponent(SamComponentBase):
446
467
  log.exception("%s Initialization failed: %s", self.log_identifier, e)
447
468
  raise
448
469
 
470
+ def _get_component_id(self) -> str:
471
+ """Returns the agent name as the component identifier."""
472
+ return self.agent_name
473
+
474
+ def _get_component_type(self) -> str:
475
+ """Returns 'agent' as the component type."""
476
+ return "agent"
477
+
449
478
  def invoke(self, message: SolaceMessage, data: dict) -> dict:
450
- """Placeholder invoke method. Primary logic resides in process_event."""
479
+ """Placeholder invoke method. Primary logic resides in _handle_message."""
451
480
  log.warning(
452
- "%s 'invoke' method called, but primary logic resides in 'process_event'. This should not happen in normal operation.",
481
+ "%s 'invoke' method called, but primary logic resides in '_handle_message'. This should not happen in normal operation.",
453
482
  self.log_identifier,
454
483
  )
455
484
  return None
456
485
 
457
- def process_event(self, event: Event):
458
- """Processes incoming events (Messages, Timers, etc.)."""
459
- try:
460
- loop = self.get_async_loop()
461
- is_loop_running = loop.is_running() if loop else False
462
- if loop and is_loop_running:
463
- coro = process_event(self, event)
464
- future = asyncio.run_coroutine_threadsafe(coro, loop)
465
- future.add_done_callback(
466
- functools.partial(
467
- self._handle_scheduled_task_completion,
468
- event_type_for_log=event.event_type,
469
- )
470
- )
471
- else:
472
- log.error(
473
- "%s Async loop not available or not running (loop is %s, is_running: %s). Cannot process event: %s",
474
- self.log_identifier,
475
- "present" if loop else "None",
476
- is_loop_running,
477
- event.event_type,
478
- )
479
- if event.event_type == EventType.MESSAGE:
480
- try:
481
- event.data.call_negative_acknowledgements()
482
- log.warning(
483
- "%s NACKed message due to unavailable async loop for event processing.",
484
- self.log_identifier,
485
- )
486
- except Exception as nack_e:
487
- log.error(
488
- "%s Failed to NACK message after async loop issue: %s",
489
- self.log_identifier,
490
- nack_e,
491
- )
492
- except Exception as e:
493
- log.error(
494
- "%s Error processing event: %s. Exception: %s",
495
- self.log_identifier,
496
- event.event_type,
497
- e,
498
- )
499
- if event.event_type == EventType.MESSAGE:
500
- try:
501
- event.data.call_negative_acknowledgements()
502
- log.warning(
503
- "%s NACKed message due to error in event processing.",
504
- self.log_identifier,
505
- )
506
- except Exception as nack_e:
507
- log.error(
508
- "%s Failed to NACK message after error in event processing: %s",
509
- self.log_identifier,
510
- nack_e,
511
- )
486
+ async def _handle_message_async(self, message: SolaceMessage, topic: str) -> None:
487
+ """
488
+ Async handler for incoming messages.
512
489
 
513
- def handle_timer_event(self, timer_data: Dict[str, Any]):
514
- """Handles timer events for agent card publishing and health checks."""
515
- log.debug("%s Received timer event: %s", self.log_identifier, timer_data)
516
- timer_id = timer_data.get("timer_id")
517
-
518
- if timer_id == self._card_publish_timer_id:
519
- publish_agent_card(self)
520
- elif timer_id == self.HEALTH_CHECK_TIMER_ID:
521
- self._check_agent_health()
490
+ Routes the message to the async event handler.
491
+
492
+ Args:
493
+ message: The Solace message
494
+ topic: The topic the message was received on
495
+ """
496
+ # Create event and process asynchronously
497
+ event = Event(EventType.MESSAGE, message)
498
+ await process_event(self, event)
522
499
 
523
500
  async def handle_cache_expiry_event(self, cache_data: Dict[str, Any]):
524
501
  """
@@ -559,6 +536,83 @@ class SamAgentComponent(SamComponentBase):
559
536
  sub_task_id,
560
537
  )
561
538
 
539
+ async def get_main_task_context(
540
+ self, logical_task_id: str
541
+ ) -> Optional["TaskExecutionContext"]:
542
+ """
543
+ Retrieves the main task context for a given logical task ID.
544
+
545
+ This method is used when the current agent is the target agent for the task.
546
+ It returns the TaskExecutionContext which contains the full task state including
547
+ a2a_context, active_peer_sub_tasks, and other task execution details.
548
+
549
+ Args:
550
+ logical_task_id: The unique logical ID of the task
551
+
552
+ Returns:
553
+ The TaskExecutionContext if the task is active, None otherwise
554
+
555
+ Raises:
556
+ ValueError: If logical_task_id is None or empty
557
+ """
558
+ if not logical_task_id:
559
+ raise ValueError("logical_task_id cannot be None or empty")
560
+
561
+ with self.active_tasks_lock:
562
+ active_task_context = self.active_tasks.get(logical_task_id)
563
+ if active_task_context is None:
564
+ log.warning(
565
+ f"No active task context found for logical_task_id: {logical_task_id}"
566
+ )
567
+ return None
568
+
569
+ return active_task_context
570
+
571
+ async def get_all_sub_task_correlation_data_from_logical_task_id(
572
+ self, logical_task_id: str
573
+ ) -> list[dict[str, Any]]:
574
+ """
575
+ Retrieves correlation data for all active peer sub-tasks of a given logical task.
576
+
577
+ This method is used when forwarding requests to other agents in an A2A workflow.
578
+ It returns a list of correlation data dictionaries, each containing information
579
+ about a peer sub-task including peer_task_id, peer_agent_name, and original_task_context.
580
+
581
+ Args:
582
+ logical_task_id: The unique logical ID of the parent task
583
+
584
+ Returns:
585
+ List of correlation data dictionaries for active peer sub-tasks.
586
+ Returns empty list if no active peer sub-tasks exist.
587
+
588
+ Raises:
589
+ ValueError: If logical_task_id is None or empty
590
+ """
591
+ if not logical_task_id:
592
+ raise ValueError("logical_task_id cannot be None or empty")
593
+
594
+ with self.active_tasks_lock:
595
+ active_task_context = self.active_tasks.get(logical_task_id)
596
+ if active_task_context is None:
597
+ log.warning(
598
+ f"No active task context found for logical_task_id: {logical_task_id}"
599
+ )
600
+ return []
601
+
602
+ active_peer_sub_tasks = active_task_context.active_peer_sub_tasks
603
+ if not active_peer_sub_tasks:
604
+ log.debug(
605
+ f"No active peer sub-tasks found for logical_task_id: {logical_task_id}"
606
+ )
607
+ return []
608
+
609
+ results = []
610
+ for sub_task_id, correlation_data in active_peer_sub_tasks.items():
611
+ if sub_task_id is not None and correlation_data is not None:
612
+ results.append(correlation_data)
613
+
614
+ return results
615
+
562
616
  async def _get_correlation_data_for_sub_task(
563
617
  self, sub_task_id: str
564
618
  ) -> Optional[Dict[str, Any]]:
@@ -1168,7 +1222,11 @@ class SamAgentComponent(SamComponentBase):
1168
1222
  """
1169
1223
  if hasattr(tool, "origin") and tool.origin is not None:
1170
1224
  return tool.origin
1171
- elif hasattr(tool, "func") and hasattr(tool.func, "origin") and tool.func.origin is not None:
1225
+ elif (
1226
+ hasattr(tool, "func")
1227
+ and hasattr(tool.func, "origin")
1228
+ and tool.func.origin is not None
1229
+ ):
1172
1230
  return tool.func.origin
1173
1231
  else:
1174
1232
  return getattr(tool, "origin", "unknown")
@@ -1546,7 +1604,7 @@ class SamAgentComponent(SamComponentBase):
1546
1604
  payload_to_publish, target_topic, a2a_context, user_properties
1547
1605
  )
1548
1606
 
1549
- log.info(
1607
+ log.debug(
1550
1608
  "%s Published %s status update to %s.",
1551
1609
  log_identifier,
1552
1610
  status_type,
@@ -1659,6 +1717,19 @@ class SamAgentComponent(SamComponentBase):
1659
1717
  is_run_based_session = a2a_context.get("is_run_based_session", False)
1660
1718
  is_final_turn_event = not adk_event.partial
1661
1719
 
1720
+ try:
1721
+ from solace_agent_mesh_enterprise.auth.tool_auth import handle_tool_auth_event
1722
+ auth_status_update = await handle_tool_auth_event(adk_event, self, a2a_context)
1723
+ if auth_status_update:
1724
+ await self._publish_status_update_with_buffer_flush(
1725
+ auth_status_update,
1726
+ a2a_context,
1727
+ skip_buffer_flush=False,
1728
+ )
1729
+ return
1730
+ except ImportError:
1731
+ pass
1732
+
1662
1733
  if not is_final_turn_event:
1663
1734
  if adk_event.content and adk_event.content.parts:
1664
1735
  for part in adk_event.content.parts:
@@ -1687,7 +1758,7 @@ class SamAgentComponent(SamComponentBase):
1687
1758
  )
1688
1759
 
1689
1760
  if buffer_has_content and (batching_disabled or threshold_met):
1690
- log.info(
1761
+ log.debug(
1691
1762
  "%s Partial event triggered buffer flush due to size/batching config.",
1692
1763
  log_id_main,
1693
1764
  )
@@ -1710,7 +1781,7 @@ class SamAgentComponent(SamComponentBase):
1710
1781
  else:
1711
1782
  buffer_content = task_context.get_streaming_buffer_content()
1712
1783
  if buffer_content:
1713
- log.info(
1784
+ log.debug(
1714
1785
  "%s Final event triggered flush of remaining buffer content.",
1715
1786
  log_id_main,
1716
1787
  )
@@ -1744,7 +1815,7 @@ class SamAgentComponent(SamComponentBase):
1744
1815
 
1745
1816
  if a2a_payload and target_topic:
1746
1817
  self._publish_a2a_event(a2a_payload, target_topic, a2a_context)
1747
- log.info(
1818
+ log.debug(
1748
1819
  "%s Published final turn event (e.g., tool call) to %s.",
1749
1820
  log_id_main,
1750
1821
  target_topic,
@@ -2030,9 +2101,14 @@ class SamAgentComponent(SamComponentBase):
2030
2101
  For STREAMING tasks, it uses the content of the last ADK event.
2031
2102
  """
2032
2103
  logical_task_id = a2a_context.get("logical_task_id")
2033
- original_message: Optional[SolaceMessage] = a2a_context.get(
2034
- "original_solace_message"
2035
- )
2104
+
2105
+ # Retrieve the original Solace message from TaskExecutionContext
2106
+ original_message: Optional[SolaceMessage] = None
2107
+ with self.active_tasks_lock:
2108
+ task_context = self.active_tasks.get(logical_task_id)
2109
+ if task_context:
2110
+ original_message = task_context.get_original_solace_message()
2111
+
2036
2112
  log.info(
2037
2113
  "%s Finalizing task %s successfully.", self.log_identifier, logical_task_id
2038
2114
  )
@@ -2106,7 +2182,7 @@ class SamAgentComponent(SamComponentBase):
2106
2182
  self.log_identifier,
2107
2183
  len(task_context.produced_artifacts),
2108
2184
  )
2109
-
2185
+
2110
2186
  # Add token usage summary
2111
2187
  if task_context:
2112
2188
  token_summary = task_context.get_token_usage_summary()
@@ -2226,9 +2302,14 @@ class SamAgentComponent(SamComponentBase):
2226
2302
  Called by the background ADK thread wrapper when a task is cancelled.
2227
2303
  """
2228
2304
  logical_task_id = a2a_context.get("logical_task_id")
2229
- original_message: Optional[SolaceMessage] = a2a_context.get(
2230
- "original_solace_message"
2231
- )
2305
+
2306
+ # Retrieve the original Solace message from TaskExecutionContext
2307
+ original_message: Optional[SolaceMessage] = None
2308
+ with self.active_tasks_lock:
2309
+ task_context = self.active_tasks.get(logical_task_id)
2310
+ if task_context:
2311
+ original_message = task_context.get_original_solace_message()
2312
+
2232
2313
  log.info(
2233
2314
  "%s Finalizing task %s as CANCELED.", self.log_identifier, logical_task_id
2234
2315
  )
@@ -2430,9 +2511,14 @@ class SamAgentComponent(SamComponentBase):
2430
2511
  Sends a COMPLETED status with an informative message.
2431
2512
  """
2432
2513
  logical_task_id = a2a_context.get("logical_task_id")
2433
- original_message: Optional[SolaceMessage] = a2a_context.get(
2434
- "original_solace_message"
2435
- )
2514
+
2515
+ # Retrieve the original Solace message from TaskExecutionContext
2516
+ original_message: Optional[SolaceMessage] = None
2517
+ with self.active_tasks_lock:
2518
+ task_context = self.active_tasks.get(logical_task_id)
2519
+ if task_context:
2520
+ original_message = task_context.get_original_solace_message()
2521
+
2436
2522
  log.info(
2437
2523
  "%s Finalizing task %s as COMPLETED (LLM call limit reached).",
2438
2524
  self.log_identifier,
@@ -2509,9 +2595,14 @@ class SamAgentComponent(SamComponentBase):
2509
2595
  Called by the background ADK thread wrapper.
2510
2596
  """
2511
2597
  logical_task_id = a2a_context.get("logical_task_id")
2512
- original_message: Optional[SolaceMessage] = a2a_context.get(
2513
- "original_solace_message"
2514
- )
2598
+
2599
+ # Retrieve the original Solace message from TaskExecutionContext
2600
+ original_message: Optional[SolaceMessage] = None
2601
+ with self.active_tasks_lock:
2602
+ task_context = self.active_tasks.get(logical_task_id)
2603
+ if task_context:
2604
+ original_message = task_context.get_original_solace_message()
2605
+
2515
2606
  log.error(
2516
2607
  "%s Finalizing task %s with error: %s",
2517
2608
  self.log_identifier,
@@ -2654,9 +2745,13 @@ class SamAgentComponent(SamComponentBase):
2654
2745
  log_id,
2655
2746
  e,
2656
2747
  )
2657
- original_message: Optional[SolaceMessage] = a2a_context.get(
2658
- "original_solace_message"
2659
- )
2748
+ # Retrieve the original Solace message from TaskExecutionContext for fallback NACK
2749
+ original_message: Optional[SolaceMessage] = None
2750
+ with self.active_tasks_lock:
2751
+ task_context = self.active_tasks.get(logical_task_id)
2752
+ if task_context:
2753
+ original_message = task_context.get_original_solace_message()
2754
+
2660
2755
  if original_message:
2661
2756
  try:
2662
2757
  original_message.call_negative_acknowledgements()
@@ -2857,10 +2952,40 @@ class SamAgentComponent(SamComponentBase):
2857
2952
  "replyTo": reply_to_topic,
2858
2953
  "a2aStatusTopic": status_topic,
2859
2954
  "userId": user_id,
2955
+ "delegating_agent_name": delegating_agent_name,
2860
2956
  }
2861
2957
  if isinstance(user_config, dict):
2862
2958
  user_properties["a2aUserConfig"] = user_config
2863
2959
 
2960
+ # Retrieve and propagate authentication token from parent task context
2961
+ parent_task_id = a2a_message.metadata.get("parentTaskId")
2962
+ if parent_task_id:
2963
+ with self.active_tasks_lock:
2964
+ parent_task_context = self.active_tasks.get(parent_task_id)
2965
+
2966
+ if parent_task_context:
2967
+ auth_token = parent_task_context.get_security_data("auth_token")
2968
+ if auth_token:
2969
+ user_properties["authToken"] = auth_token
2970
+ log.debug(
2971
+ "%s Propagating authentication token to peer agent %s for sub-task %s",
2972
+ log_identifier_helper,
2973
+ target_agent_name,
2974
+ sub_task_id,
2975
+ )
2976
+ else:
2977
+ log.debug(
2978
+ "%s No authentication token found in parent task context for sub-task %s",
2979
+ log_identifier_helper,
2980
+ sub_task_id,
2981
+ )
2982
+ else:
2983
+ log.warning(
2984
+ "%s Parent task context not found for task %s, cannot propagate authentication token",
2985
+ log_identifier_helper,
2986
+ parent_task_id,
2987
+ )
2988
+
2864
2989
  self.publish_a2a_message(
2865
2990
  payload=a2a_request.model_dump(by_alias=True, exclude_none=True),
2866
2991
  topic=peer_request_topic,
@@ -3023,8 +3148,11 @@ class SamAgentComponent(SamComponentBase):
3023
3148
 
3024
3149
  cleanup_func_details = self.get_config("agent_cleanup_function")
3025
3150
 
3026
- from .app import AgentInitCleanupConfig # Avoid circular import
3027
- if cleanup_func_details and isinstance(cleanup_func_details, AgentInitCleanupConfig):
3151
+ from .app import AgentInitCleanupConfig # Avoid circular import
3152
+
3153
+ if cleanup_func_details and isinstance(
3154
+ cleanup_func_details, AgentInitCleanupConfig
3155
+ ):
3028
3156
  module_name = cleanup_func_details.get("module")
3029
3157
  func_name = cleanup_func_details.get("name")
3030
3158
  base_path = cleanup_func_details.get("base_path")
@@ -3356,11 +3484,11 @@ class SamAgentComponent(SamComponentBase):
3356
3484
  resolver_config = context_for_embeds["config"]
3357
3485
 
3358
3486
  try:
3487
+ from ...common.utils.embeds.constants import EARLY_EMBED_TYPES
3359
3488
  from ...common.utils.embeds.resolver import (
3360
- resolve_embeds_in_string,
3361
3489
  evaluate_embed,
3490
+ resolve_embeds_in_string,
3362
3491
  )
3363
- from ...common.utils.embeds.constants import EARLY_EMBED_TYPES
3364
3492
 
3365
3493
  resolved_text, processed_until_index, signals_found = (
3366
3494
  await resolve_embeds_in_string(
@@ -3392,6 +3520,10 @@ class SamAgentComponent(SamComponentBase):
3392
3520
  Main async logic for the agent component.
3393
3521
  This is called by the base class's `_run_async_operations`.
3394
3522
  """
3523
+ # Call base class to initialize Trust Manager
3524
+ await super()._async_setup_and_run()
3525
+
3526
+ # Perform agent-specific async initialization
3395
3527
  await self._perform_async_init()
3396
3528
 
3397
3529
  def _pre_async_cleanup(self) -> None:
@@ -3399,4 +3531,11 @@ class SamAgentComponent(SamComponentBase):
3399
3531
  Pre-cleanup actions for the agent component.
3400
3532
  Called by the base class before stopping the async loop.
3401
3533
  """
3402
- pass
3534
+ # Cleanup Trust Manager if present (ENTERPRISE FEATURE)
3535
+ if self.trust_manager:
3536
+ try:
3537
+ self.trust_manager.cleanup(self.cancel_timer)
3538
+ except Exception as e:
3539
+ log.error(
3540
+ "%s Error during Trust Manager cleanup: %s", self.log_identifier, e
3541
+ )