solace-agent-mesh 1.0.1__py3-none-any.whl → 1.0.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 (82) hide show
  1. solace_agent_mesh/__init__.py +5 -0
  2. solace_agent_mesh/agent/adk/callbacks.py +23 -1
  3. solace_agent_mesh/agent/adk/filesystem_artifact_service.py +2 -2
  4. solace_agent_mesh/agent/adk/runner.py +10 -6
  5. solace_agent_mesh/agent/adk/services.py +1 -1
  6. solace_agent_mesh/agent/protocol/event_handlers.py +14 -39
  7. solace_agent_mesh/agent/sac/component.py +145 -37
  8. solace_agent_mesh/agent/sac/task_execution_context.py +15 -6
  9. solace_agent_mesh/agent/tools/general_agent_tools.py +4 -2
  10. solace_agent_mesh/agent/tools/peer_agent_tool.py +6 -5
  11. solace_agent_mesh/assets/docs/404.html +3 -3
  12. solace_agent_mesh/assets/docs/assets/js/1c6e87d2.a8c5ce5a.js +1 -0
  13. solace_agent_mesh/assets/docs/assets/js/f897a61a.f8c53b0f.js +1 -0
  14. solace_agent_mesh/assets/docs/assets/js/{main.7ed3319f.js → main.c6286d7c.js} +2 -2
  15. solace_agent_mesh/assets/docs/assets/js/{runtime~main.d9520ae2.js → runtime~main.d5133813.js} +1 -1
  16. solace_agent_mesh/assets/docs/docs/documentation/concepts/agents/index.html +3 -3
  17. solace_agent_mesh/assets/docs/docs/documentation/concepts/architecture/index.html +3 -3
  18. solace_agent_mesh/assets/docs/docs/documentation/concepts/cli/index.html +3 -3
  19. solace_agent_mesh/assets/docs/docs/documentation/concepts/gateways/index.html +3 -3
  20. solace_agent_mesh/assets/docs/docs/documentation/concepts/orchestrator/index.html +3 -3
  21. solace_agent_mesh/assets/docs/docs/documentation/concepts/plugins/index.html +3 -3
  22. solace_agent_mesh/assets/docs/docs/documentation/deployment/debugging/index.html +21 -4
  23. solace_agent_mesh/assets/docs/docs/documentation/deployment/deploy/index.html +3 -3
  24. solace_agent_mesh/assets/docs/docs/documentation/deployment/observability/index.html +3 -3
  25. solace_agent_mesh/assets/docs/docs/documentation/enterprise/index.html +3 -3
  26. solace_agent_mesh/assets/docs/docs/documentation/getting-started/component-overview/index.html +3 -3
  27. solace_agent_mesh/assets/docs/docs/documentation/getting-started/installation/index.html +3 -3
  28. solace_agent_mesh/assets/docs/docs/documentation/getting-started/introduction/index.html +3 -3
  29. solace_agent_mesh/assets/docs/docs/documentation/getting-started/quick-start/index.html +4 -4
  30. solace_agent_mesh/assets/docs/docs/documentation/tutorials/bedrock-agents/index.html +3 -3
  31. solace_agent_mesh/assets/docs/docs/documentation/tutorials/custom-agent/index.html +3 -3
  32. solace_agent_mesh/assets/docs/docs/documentation/tutorials/event-mesh-gateway/index.html +3 -3
  33. solace_agent_mesh/assets/docs/docs/documentation/tutorials/mcp-integration/index.html +3 -3
  34. solace_agent_mesh/assets/docs/docs/documentation/tutorials/mongodb-integration/index.html +3 -3
  35. solace_agent_mesh/assets/docs/docs/documentation/tutorials/rest-gateway/index.html +3 -3
  36. solace_agent_mesh/assets/docs/docs/documentation/tutorials/slack-integration/index.html +3 -3
  37. solace_agent_mesh/assets/docs/docs/documentation/tutorials/sql-database/index.html +3 -3
  38. solace_agent_mesh/assets/docs/docs/documentation/user-guide/builtin-tools/artifact-management/index.html +3 -3
  39. solace_agent_mesh/assets/docs/docs/documentation/user-guide/builtin-tools/audio-tools/index.html +3 -3
  40. solace_agent_mesh/assets/docs/docs/documentation/user-guide/builtin-tools/data-analysis-tools/index.html +3 -3
  41. solace_agent_mesh/assets/docs/docs/documentation/user-guide/builtin-tools/embeds/index.html +3 -3
  42. solace_agent_mesh/assets/docs/docs/documentation/user-guide/builtin-tools/index.html +3 -3
  43. solace_agent_mesh/assets/docs/docs/documentation/user-guide/create-agents/index.html +3 -3
  44. solace_agent_mesh/assets/docs/docs/documentation/user-guide/create-gateways/index.html +3 -3
  45. solace_agent_mesh/assets/docs/docs/documentation/user-guide/creating-service-providers/index.html +3 -3
  46. solace_agent_mesh/assets/docs/docs/documentation/user-guide/solace-ai-connector/index.html +3 -3
  47. solace_agent_mesh/assets/docs/docs/documentation/user-guide/structure/index.html +3 -3
  48. solace_agent_mesh/assets/docs/lunr-index-1754075282978.json +1 -0
  49. solace_agent_mesh/assets/docs/lunr-index.json +1 -1
  50. solace_agent_mesh/assets/docs/search-doc-1754075282978.json +1 -0
  51. solace_agent_mesh/assets/docs/search-doc.json +1 -1
  52. solace_agent_mesh/cli/__init__.py +1 -1
  53. solace_agent_mesh/cli/commands/init_cmd/env_step.py +8 -0
  54. solace_agent_mesh/cli/commands/init_cmd/orchestrator_step.py +20 -0
  55. solace_agent_mesh/cli/commands/plugin_cmd/catalog_cmd.py +1 -0
  56. solace_agent_mesh/cli/commands/plugin_cmd/official_registry.py +2 -1
  57. solace_agent_mesh/client/webui/frontend/static/assets/main-D11Lmy9p.css +1 -0
  58. solace_agent_mesh/client/webui/frontend/static/assets/{main-An0a5j5k.js → main-Gfk3BYn5.js} +96 -96
  59. solace_agent_mesh/client/webui/frontend/static/index.html +2 -2
  60. solace_agent_mesh/common/utils/initializer.py +51 -0
  61. solace_agent_mesh/config_portal/backend/plugin_catalog/constants.py +2 -1
  62. solace_agent_mesh/config_portal/backend/plugin_catalog/registry_manager.py +6 -2
  63. solace_agent_mesh/config_portal/backend/plugin_catalog/scraper.py +1 -5
  64. solace_agent_mesh/config_portal/backend/plugin_catalog_server.py +1 -0
  65. solace_agent_mesh/config_portal/backend/server.py +1 -0
  66. solace_agent_mesh/config_portal/frontend/static/client/assets/{_index-DNxCwAGB.js → _index-_7yox_eh.js} +25 -25
  67. solace_agent_mesh/config_portal/frontend/static/client/assets/{manifest-d2b54a97.js → manifest-e5c3acfe.js} +1 -1
  68. solace_agent_mesh/config_portal/frontend/static/client/index.html +1 -1
  69. solace_agent_mesh/gateway/http_sse/routers/artifacts.py +9 -3
  70. solace_agent_mesh/templates/gateway_component_template.py +75 -44
  71. solace_agent_mesh/templates/logging_config_template.ini +64 -0
  72. {solace_agent_mesh-1.0.1.dist-info → solace_agent_mesh-1.0.2.dist-info}/METADATA +2 -2
  73. {solace_agent_mesh-1.0.1.dist-info → solace_agent_mesh-1.0.2.dist-info}/RECORD +77 -75
  74. solace_agent_mesh/assets/docs/assets/js/1c6e87d2.23bccffb.js +0 -1
  75. solace_agent_mesh/assets/docs/assets/js/f897a61a.2c2e152c.js +0 -1
  76. solace_agent_mesh/assets/docs/lunr-index-1753813536522.json +0 -1
  77. solace_agent_mesh/assets/docs/search-doc-1753813536522.json +0 -1
  78. solace_agent_mesh/client/webui/frontend/static/assets/main-Bu5-4Bac.css +0 -1
  79. /solace_agent_mesh/assets/docs/assets/js/{main.7ed3319f.js.LICENSE.txt → main.c6286d7c.js.LICENSE.txt} +0 -0
  80. {solace_agent_mesh-1.0.1.dist-info → solace_agent_mesh-1.0.2.dist-info}/WHEEL +0 -0
  81. {solace_agent_mesh-1.0.1.dist-info → solace_agent_mesh-1.0.2.dist-info}/entry_points.txt +0 -0
  82. {solace_agent_mesh-1.0.1.dist-info → solace_agent_mesh-1.0.2.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,5 @@
1
+ """
2
+ Solace Agent Mesh Initialization
3
+ """
4
+ from .common.utils.initializer import initialize
5
+ initialize()
@@ -785,6 +785,26 @@ It can span multiple lines.
785
785
 
786
786
  The system will automatically save the content and give you a confirmation in the next turn."""
787
787
 
788
+ def _generate_artifact_creation_instruction() -> str:
789
+ return """
790
+ **Creating Text-Based Artifacts:**
791
+
792
+ **When to Create Text-based Artifacts:**
793
+ Create an artifact when the content provides value as a standalone file:
794
+ - Content with special formatting (HTML, Markdown, CSS, structured markup) that requires proper rendering
795
+ - Content explicitly intended for use outside this conversation (reports, emails, presentations, reference documents)
796
+ - Structured reference content users will save or follow (schedules, guides, templates)
797
+ - Content that will be edited, expanded, or reused
798
+ - Substantial text documents
799
+ - Technical documentation meant as reference material
800
+
801
+ **When NOT to Create Text-based Artifacts:**
802
+ - Simple answers, explanations, or conversational responses
803
+ - Brief advice, opinions, or quick information
804
+ - Short lists, summaries, or single paragraphs
805
+ - Temporary content only relevant to the immediate conversation
806
+ - Basic explanations that don't require reference material
807
+ """
788
808
 
789
809
  def _generate_embed_instruction(
790
810
  include_artifact_content: bool,
@@ -918,7 +938,7 @@ When faced with a complex goal or request that involves multiple steps, data ret
918
938
  Simple, direct requests like 'create an image of a dog' or 'write an email to thank my boss' do not require a plan.
919
939
 
920
940
  If a plan is created:
921
- 1. It should be a terse, hierarchical list describing the steps needed.
941
+ 1. It should be a terse, hierarchical list describing the steps needed, with each checkbox item on its own line.
922
942
  2. Use '☐' (empty checkbox emoji) for pending items and '☑' (checked checkbox emoji) for completed items.
923
943
  3. If the plan changes significantly during execution, restate the updated plan.
924
944
  4. As items are completed, update the plan to check them off.
@@ -926,6 +946,8 @@ If a plan is created:
926
946
  """
927
947
  injected_instructions.append(planning_instruction)
928
948
  log.debug("%s Added hardcoded planning instructions.", log_identifier)
949
+ artifact_creation_instruction = _generate_artifact_creation_instruction()
950
+ injected_instructions.append(artifact_creation_instruction)
929
951
  fenced_artifact_instruction = _generate_fenced_artifact_instruction()
930
952
  injected_instructions.append(fenced_artifact_instruction)
931
953
 
@@ -371,11 +371,11 @@ class FilesystemArtifactService(BaseArtifactService):
371
371
  sorted_versions = sorted(versions)
372
372
  logger.debug("%sFound versions: %s", log_prefix, sorted_versions)
373
373
  return sorted_versions
374
-
374
+
375
375
  def _normalize_filename_unicode(self, filename: str) -> str:
376
376
  """
377
377
  Normalizes Unicode characters in a filename to their standard form.
378
378
  Specifically targets compatibility characters like non-breaking spaces (\u202f)
379
379
  and converts them to their regular ASCII equivalents (a standard space).
380
380
  """
381
- return unicodedata.normalize('NFKC', filename)
381
+ return unicodedata.normalize("NFKC", filename)
@@ -132,7 +132,7 @@ async def run_adk_async_task_thread_wrapper(
132
132
  logical_task_id,
133
133
  tce,
134
134
  )
135
- sub_tasks_to_cancel = task_context.peer_sub_tasks if task_context else []
135
+ sub_tasks_to_cancel = task_context.active_peer_sub_tasks if task_context else {}
136
136
 
137
137
  if sub_tasks_to_cancel:
138
138
  log.info(
@@ -141,18 +141,22 @@ async def run_adk_async_task_thread_wrapper(
141
141
  len(sub_tasks_to_cancel),
142
142
  logical_task_id,
143
143
  )
144
- for sub_task_info in sub_tasks_to_cancel:
144
+ for sub_task_id, sub_task_info in sub_tasks_to_cancel.items():
145
145
  try:
146
- sub_task_id = sub_task_info.get("sub_task_id")
147
146
  target_peer_agent_name = sub_task_info.get("peer_agent_name")
148
147
  if not sub_task_id or not target_peer_agent_name:
149
148
  log.warning(
150
- "%s Incomplete sub-task info found, cannot cancel: %s",
149
+ "%s Incomplete sub-task info found for sub-task %s, cannot cancel: %s",
151
150
  component.log_identifier,
151
+ sub_task_id,
152
152
  sub_task_info,
153
153
  )
154
154
  continue
155
- peer_cancel_params = TaskIdParams(id=sub_task_id)
155
+
156
+ task_id_for_peer = sub_task_id.replace(
157
+ component.CORRELATION_DATA_PREFIX, "", 1
158
+ )
159
+ peer_cancel_params = TaskIdParams(id=task_id_for_peer)
156
160
  peer_cancel_request = CancelTaskRequest(params=peer_cancel_params)
157
161
  peer_cancel_user_props = {"clientId": component.agent_name}
158
162
  peer_request_topic = component._get_agent_request_topic(
@@ -167,7 +171,7 @@ async def run_adk_async_task_thread_wrapper(
167
171
  log.error(
168
172
  "%s Failed to send CancelTaskRequest for sub-task %s: %s",
169
173
  component.log_identifier,
170
- sub_task_info.get("sub_task_id"),
174
+ sub_task_id,
171
175
  e_peer_cancel,
172
176
  exc_info=True,
173
177
  )
@@ -28,7 +28,7 @@ from google.adk.memory import (
28
28
  from .filesystem_artifact_service import FilesystemArtifactService
29
29
 
30
30
  try:
31
- from tests.integration.infrastructure.artifact_service.service import (
31
+ from sam_test_infrastructure.artifact_service.service import (
32
32
  TestInMemoryArtifactService,
33
33
  )
34
34
  except ImportError:
@@ -248,7 +248,7 @@ async def process_event(component, event: Event):
248
248
  elif topic.startswith(agent_response_sub_prefix) or topic.startswith(
249
249
  agent_status_sub_prefix
250
250
  ):
251
- handle_a2a_response(component, message)
251
+ await handle_a2a_response(component, message)
252
252
  else:
253
253
  log.warning(
254
254
  "%s Received message on unhandled topic: %s",
@@ -264,31 +264,8 @@ async def process_event(component, event: Event):
264
264
  if timer_data.get("timer_id") == component._card_publish_timer_id:
265
265
  publish_agent_card(component)
266
266
  elif event.event_type == EventType.CACHE_EXPIRY:
267
- cache_data = event.data
268
- log.info(
269
- "%s Received cache expiry event: %s",
270
- component.log_identifier,
271
- cache_data,
272
- )
273
- sub_task_id = cache_data.get("key")
274
- if sub_task_id and sub_task_id.startswith(
275
- component.CORRELATION_DATA_PREFIX
276
- ):
277
- expired_data = cache_data.get("expired_data")
278
- if expired_data:
279
- await component._handle_peer_timeout(sub_task_id, expired_data)
280
- else:
281
- log.error(
282
- "%s Missing expired_data in cache expiry event for sub-task %s. Cannot process timeout.",
283
- component.log_identifier,
284
- sub_task_id,
285
- )
286
- else:
287
- log.debug(
288
- "%s Cache expiry for key '%s' is not a peer sub-task timeout.",
289
- component.log_identifier,
290
- sub_task_id,
291
- )
267
+ # Delegate cache expiry handling to the component itself.
268
+ await component.handle_cache_expiry_event(event.data)
292
269
  else:
293
270
  log.warning(
294
271
  "%s Received unknown event type: %s",
@@ -854,10 +831,9 @@ def handle_agent_card_message(component, message: SolaceMessage):
854
831
  component.handle_error(e, Event(EventType.MESSAGE, message))
855
832
 
856
833
 
857
- def handle_a2a_response(component, message: SolaceMessage):
834
+ async def handle_a2a_response(component, message: SolaceMessage):
858
835
  """Handles incoming responses/status updates from peer agents."""
859
836
  sub_task_id = None
860
- agent_name = component.get_config("agent_name")
861
837
  payload_to_queue = None
862
838
  is_final_response = False
863
839
 
@@ -932,10 +908,8 @@ def handle_a2a_response(component, message: SolaceMessage):
932
908
  component.log_identifier,
933
909
  sub_task_id,
934
910
  )
935
- correlation_data = (
936
- component.cache_service.get_data(
937
- sub_task_id
938
- )
911
+ correlation_data = await component._get_correlation_data_for_sub_task(
912
+ sub_task_id
939
913
  )
940
914
  if not correlation_data:
941
915
  log.warning(
@@ -1227,7 +1201,12 @@ def handle_a2a_response(component, message: SolaceMessage):
1227
1201
  "error": f"Failed to parse response from peer: {parse_error}",
1228
1202
  "code": "PEER_PARSE_ERROR",
1229
1203
  }
1230
- is_final_response = True
1204
+ # Print out the stack trace for debugging
1205
+ log.exception(
1206
+ "%s Exception stack trace: %s",
1207
+ component.log_identifier,
1208
+ parse_error,
1209
+ )
1231
1210
 
1232
1211
  if not is_final_response:
1233
1212
  # This is an intermediate status update for monitoring.
@@ -1240,13 +1219,9 @@ def handle_a2a_response(component, message: SolaceMessage):
1240
1219
  message.call_acknowledgements()
1241
1220
  return
1242
1221
 
1243
- correlation_data = component.cache_service.get_data(sub_task_id)
1222
+ correlation_data = await component._claim_peer_sub_task_completion(sub_task_id)
1244
1223
  if not correlation_data:
1245
- log.warning(
1246
- "%s No correlation data found for sub-task %s. Cannot process response. Ignoring.",
1247
- component.log_identifier,
1248
- sub_task_id,
1249
- )
1224
+ # The helper method logs the reason (timeout, already claimed, etc.)
1250
1225
  message.call_acknowledgements()
1251
1226
  return
1252
1227
 
@@ -53,6 +53,8 @@ from ...common.types import (
53
53
  TaskStatusUpdateEvent,
54
54
  TaskArtifactUpdateEvent,
55
55
  SendTaskRequest,
56
+ CancelTaskRequest,
57
+ TaskIdParams,
56
58
  )
57
59
  from ...common.a2a_protocol import (
58
60
  get_a2a_base_topic,
@@ -536,49 +538,123 @@ class SamAgentComponent(ComponentBase):
536
538
  if timer_data.get("timer_id") == self._card_publish_timer_id:
537
539
  publish_agent_card(self)
538
540
 
539
- def handle_cache_expiry_event(self, cache_data: Dict[str, Any]):
540
- """Handles cache expiry events, specifically for peer timeouts."""
541
+ async def handle_cache_expiry_event(self, cache_data: Dict[str, Any]):
542
+ """
543
+ Handles cache expiry events for peer timeouts by calling the atomic claim helper.
544
+ """
541
545
  log.debug("%s Received cache expiry event: %s", self.log_identifier, cache_data)
542
- expired_key = cache_data.get("key")
543
- expired_data = cache_data.get("expired_data")
546
+ sub_task_id = cache_data.get("key")
547
+ logical_task_id = cache_data.get("expired_data")
548
+
549
+ if not (
550
+ sub_task_id
551
+ and sub_task_id.startswith(CORRELATION_DATA_PREFIX)
552
+ and logical_task_id
553
+ ):
554
+ log.debug(
555
+ "%s Cache expiry for key '%s' is not a peer sub-task timeout or is missing data.",
556
+ self.log_identifier,
557
+ sub_task_id,
558
+ )
559
+ return
560
+
561
+ correlation_data = await self._claim_peer_sub_task_completion(
562
+ sub_task_id=sub_task_id, logical_task_id_from_event=logical_task_id
563
+ )
544
564
 
545
- if expired_key and expired_key.startswith(CORRELATION_DATA_PREFIX):
546
- sub_task_id = expired_key
565
+ if correlation_data:
547
566
  log.warning(
548
- "%s Detected timeout for sub-task ID: %s",
567
+ "%s Detected timeout for sub-task %s (Main Task: %s). Claimed successfully.",
549
568
  self.log_identifier,
550
569
  sub_task_id,
570
+ logical_task_id,
551
571
  )
552
- if expired_data:
553
- try:
554
- original_task_context = expired_data.get("original_task_context")
555
- if original_task_context:
556
- self._handle_peer_timeout(sub_task_id, expired_data)
557
- else:
558
- log.error(
559
- "%s Missing 'original_task_context' in expired cache data for sub-task %s. Cannot process timeout.",
560
- self.log_identifier,
561
- sub_task_id,
562
- )
563
- except Exception as e:
564
- log.exception(
565
- "%s Error handling peer timeout for sub-task %s: %s",
566
- self.log_identifier,
567
- sub_task_id,
568
- e,
569
- )
570
- else:
571
- log.error(
572
- "%s Missing expired_data in cache expiry event for sub-task %s. Cannot process timeout.",
573
- self.log_identifier,
574
- sub_task_id,
575
- )
572
+ await self._handle_peer_timeout(sub_task_id, correlation_data)
576
573
  else:
577
- log.debug(
578
- "%s Cache expiry for key '%s' is not a peer sub-task timeout.",
574
+ log.info(
575
+ "%s Ignoring timeout event for sub-task %s as it was already completed.",
576
+ self.log_identifier,
577
+ sub_task_id,
578
+ )
579
+
580
+ async def _get_correlation_data_for_sub_task(
581
+ self, sub_task_id: str
582
+ ) -> Optional[Dict[str, Any]]:
583
+ """
584
+ Non-destructively retrieves correlation data for a sub-task.
585
+ Used for intermediate events where the sub-task should remain active.
586
+ """
587
+ logical_task_id = self.cache_service.get_data(sub_task_id)
588
+ if not logical_task_id:
589
+ log.warning(
590
+ "%s No cache entry for sub-task %s. Cannot get correlation data.",
591
+ self.log_identifier,
592
+ sub_task_id,
593
+ )
594
+ return None
595
+
596
+ with self.active_tasks_lock:
597
+ task_context = self.active_tasks.get(logical_task_id)
598
+
599
+ if not task_context:
600
+ log.error(
601
+ "%s TaskExecutionContext not found for task %s, but cache entry existed for sub-task %s. This may indicate a cleanup issue.",
579
602
  self.log_identifier,
580
- expired_key,
603
+ logical_task_id,
604
+ sub_task_id,
605
+ )
606
+ return None
607
+
608
+ with task_context.lock:
609
+ return task_context.active_peer_sub_tasks.get(sub_task_id)
610
+
611
+ async def _claim_peer_sub_task_completion(
612
+ self, sub_task_id: str, logical_task_id_from_event: Optional[str] = None
613
+ ) -> Optional[Dict[str, Any]]:
614
+ """
615
+ Atomically claims a sub-task as complete, preventing race conditions.
616
+ This is a destructive operation that removes state.
617
+
618
+ Args:
619
+ sub_task_id: The ID of the sub-task to claim.
620
+ logical_task_id_from_event: The parent task ID, if provided by the event (e.g., a timeout).
621
+ If not provided, it will be looked up from the cache.
622
+ """
623
+ log_id = f"{self.log_identifier}[ClaimSubTask:{sub_task_id}]"
624
+ logical_task_id = logical_task_id_from_event
625
+
626
+ if not logical_task_id:
627
+ logical_task_id = self.cache_service.get_data(sub_task_id)
628
+ if not logical_task_id:
629
+ log.warning(
630
+ "%s No cache entry found. Task has likely timed out and been cleaned up. Cannot claim.",
631
+ log_id,
632
+ )
633
+ return None
634
+
635
+ with self.active_tasks_lock:
636
+ task_context = self.active_tasks.get(logical_task_id)
637
+
638
+ if not task_context:
639
+ log.error(
640
+ "%s TaskExecutionContext not found for task %s. Cleaning up stale cache entry.",
641
+ log_id,
642
+ logical_task_id,
581
643
  )
644
+ self.cache_service.remove_data(sub_task_id)
645
+ return None
646
+
647
+ correlation_data = task_context.claim_sub_task_completion(sub_task_id)
648
+
649
+ if correlation_data:
650
+ # If we successfully claimed the task, remove the timeout tracker from the cache.
651
+ self.cache_service.remove_data(sub_task_id)
652
+ log.info("%s Successfully claimed completion.", log_id)
653
+ return correlation_data
654
+ else:
655
+ # This means the task was already claimed by a competing event (e.g., timeout vs. response).
656
+ log.warning("%s Failed to claim; it was already completed.", log_id)
657
+ return None
582
658
 
583
659
  async def _retrigger_agent_with_peer_responses(
584
660
  self,
@@ -686,8 +762,9 @@ class SamAgentComponent(ComponentBase):
686
762
  correlation_data: Dict[str, Any],
687
763
  ):
688
764
  """
689
- Handles the timeout of a peer agent task by updating the completion counter
690
- and potentially re-triggering the runner if all parallel tasks are now complete.
765
+ Handles the timeout of a peer agent task. It sends a cancellation request
766
+ to the peer, updates the local completion counter, and potentially
767
+ re-triggers the runner if all parallel tasks are now complete.
691
768
  """
692
769
  logical_task_id = correlation_data.get("logical_task_id")
693
770
  invocation_id = correlation_data.get("invocation_id")
@@ -700,6 +777,36 @@ class SamAgentComponent(ComponentBase):
700
777
  invocation_id,
701
778
  )
702
779
 
780
+ # Proactively send a cancellation request to the peer agent.
781
+ peer_agent_name = correlation_data.get("peer_agent_name")
782
+ if peer_agent_name:
783
+ try:
784
+ log.info(
785
+ "%s Sending CancelTaskRequest to peer '%s' for timed-out sub-task %s.",
786
+ log_retrigger,
787
+ peer_agent_name,
788
+ sub_task_id,
789
+ )
790
+ task_id_for_peer = sub_task_id.replace(CORRELATION_DATA_PREFIX, "", 1)
791
+ cancel_params = TaskIdParams(id=task_id_for_peer)
792
+ cancel_request = CancelTaskRequest(params=cancel_params)
793
+ user_props = {"clientId": self.agent_name}
794
+ peer_topic = self._get_agent_request_topic(peer_agent_name)
795
+ self._publish_a2a_message(
796
+ payload=cancel_request.model_dump(exclude_none=True),
797
+ topic=peer_topic,
798
+ user_properties=user_props,
799
+ )
800
+ except Exception as e:
801
+ log.error(
802
+ "%s Failed to send CancelTaskRequest to peer '%s' for sub-task %s: %s",
803
+ log_retrigger,
804
+ peer_agent_name,
805
+ sub_task_id,
806
+ e,
807
+ )
808
+
809
+ # Process the timeout locally.
703
810
  with self.active_tasks_lock:
704
811
  task_context = self.active_tasks.get(logical_task_id)
705
812
 
@@ -1841,7 +1948,8 @@ class SamAgentComponent(ComponentBase):
1841
1948
  len(unprocessed_tail.encode("utf-8")),
1842
1949
  )
1843
1950
  else:
1844
- resolved_text = resolved_text + unprocessed_tail
1951
+ if unprocessed_tail is not None and unprocessed_tail != "":
1952
+ resolved_text = resolved_text + unprocessed_tail
1845
1953
 
1846
1954
  if signals_found:
1847
1955
  log.info(
@@ -27,7 +27,7 @@ class TaskExecutionContext:
27
27
  self.cancellation_event: asyncio.Event = asyncio.Event()
28
28
  self.streaming_buffer: str = ""
29
29
  self.run_based_response_buffer: str = ""
30
- self.peer_sub_tasks: List[Dict[str, Any]] = []
30
+ self.active_peer_sub_tasks: Dict[str, Dict[str, Any]] = {}
31
31
  self.parallel_tool_calls: Dict[str, Dict[str, Any]] = {}
32
32
  self.produced_artifacts: List[Dict[str, Any]] = []
33
33
  self.artifact_signals_to_return: List[Dict[str, Any]] = []
@@ -64,12 +64,21 @@ class TaskExecutionContext:
64
64
  with self.lock:
65
65
  self.run_based_response_buffer += text
66
66
 
67
- def register_peer_sub_task(self, sub_task_id: str, peer_agent_name: str) -> None:
68
- """Adds a new peer sub-task to the tracking list."""
67
+ def register_peer_sub_task(
68
+ self, sub_task_id: str, correlation_data: Dict[str, Any]
69
+ ) -> None:
70
+ """Adds a new peer sub-task's correlation data to the tracking dictionary."""
69
71
  with self.lock:
70
- self.peer_sub_tasks.append(
71
- {"sub_task_id": sub_task_id, "peer_agent_name": peer_agent_name}
72
- )
72
+ self.active_peer_sub_tasks[sub_task_id] = correlation_data
73
+
74
+ def claim_sub_task_completion(self, sub_task_id: str) -> Optional[Dict[str, Any]]:
75
+ """
76
+ Atomically retrieves and removes a sub-task's correlation data.
77
+ This is the core atomic operation to prevent race conditions.
78
+ Returns the correlation data if the claim is successful, otherwise None.
79
+ """
80
+ with self.lock:
81
+ return self.active_peer_sub_tasks.pop(sub_task_id, None)
73
82
 
74
83
  def register_parallel_call_sent(self, invocation_id: str) -> None:
75
84
  """
@@ -397,7 +397,8 @@ async def mermaid_diagram_generator(
397
397
  "message": "Failed to render Mermaid diagram. No image data returned.",
398
398
  }
399
399
  try:
400
- image_data = await _convert_svg_to_png_with_playwright(svg_image_data.decode("utf-8"))
400
+ scale = max(2, len(mermaid_syntax.splitlines()) // 10)
401
+ image_data = await _convert_svg_to_png_with_playwright(svg_image_data.decode("utf-8"), scale)
401
402
  except Exception as e:
402
403
  log.error(
403
404
  "%s Failed to convert SVG to PNG with Playwright: %s",
@@ -410,8 +411,9 @@ async def mermaid_diagram_generator(
410
411
  }
411
412
 
412
413
  log.debug(
413
- "%s Mermaid diagram rendered successfully, image_data length: %d bytes",
414
+ "%s Mermaid diagram rendered successfully with scale %d, image_data length: %d bytes",
414
415
  log_identifier,
416
+ scale,
415
417
  len(image_data),
416
418
  )
417
419
 
@@ -243,13 +243,18 @@ class PeerAgentTool(BaseTool):
243
243
  "adk_function_call_id": tool_context.function_call_id,
244
244
  "original_task_context": original_task_context,
245
245
  "peer_tool_name": self.name,
246
+ "peer_agent_name": self.target_agent_name,
246
247
  "logical_task_id": main_logical_task_id,
247
248
  "invocation_id": invocation_id,
248
249
  }
249
250
 
251
+ # Register the sub-task's state within the parent task's context.
252
+ task_context_obj.register_peer_sub_task(sub_task_id, correlation_data)
253
+
254
+ # Add a simple mapping to the cache for timeout tracking.
250
255
  self.host_component.cache_service.add_data(
251
256
  key=sub_task_id,
252
- value=correlation_data,
257
+ value=main_logical_task_id,
253
258
  expiry=timeout_sec,
254
259
  component=self.host_component,
255
260
  )
@@ -264,10 +269,6 @@ class PeerAgentTool(BaseTool):
264
269
  sub_task_id=sub_task_id,
265
270
  function_call_id=tool_context.function_call_id,
266
271
  )
267
-
268
- task_context_obj.register_peer_sub_task(
269
- sub_task_id=sub_task_id, peer_agent_name=self.target_agent_name
270
- )
271
272
  log.info(
272
273
  "%s Registered active peer sub-task %s for main task %s.",
273
274
  log_identifier,
@@ -4,13 +4,13 @@
4
4
  <meta charset="UTF-8">
5
5
  <meta name="generator" content="Docusaurus v3.8.1">
6
6
  <title data-rh="true">Page Not Found | Solace Agent Mesh</title><meta data-rh="true" name="viewport" content="width=device-width,initial-scale=1"><meta data-rh="true" name="twitter:card" content="summary_large_image"><meta data-rh="true" property="og:image" content="https://solacelabs.github.io/solace-agent-mesh/img/logo.png"><meta data-rh="true" name="twitter:image" content="https://solacelabs.github.io/solace-agent-mesh/img/logo.png"><meta data-rh="true" property="og:url" content="https://solacelabs.github.io/solace-agent-mesh/404.html"><meta data-rh="true" property="og:locale" content="en"><meta data-rh="true" name="docusaurus_locale" content="en"><meta data-rh="true" name="docusaurus_tag" content="default"><meta data-rh="true" name="docsearch:language" content="en"><meta data-rh="true" name="docsearch:docusaurus_tag" content="default"><meta data-rh="true" property="og:title" content="Page Not Found | Solace Agent Mesh"><link data-rh="true" rel="icon" href="/solace-agent-mesh/img/logo.png"><link data-rh="true" rel="canonical" href="https://solacelabs.github.io/solace-agent-mesh/404.html"><link data-rh="true" rel="alternate" href="https://solacelabs.github.io/solace-agent-mesh/404.html" hreflang="en"><link data-rh="true" rel="alternate" href="https://solacelabs.github.io/solace-agent-mesh/404.html" hreflang="x-default"><link rel="stylesheet" href="/solace-agent-mesh/assets/css/styles.906a1503.css">
7
- <script src="/solace-agent-mesh/assets/js/runtime~main.d9520ae2.js" defer="defer"></script>
8
- <script src="/solace-agent-mesh/assets/js/main.7ed3319f.js" defer="defer"></script>
7
+ <script src="/solace-agent-mesh/assets/js/runtime~main.d5133813.js" defer="defer"></script>
8
+ <script src="/solace-agent-mesh/assets/js/main.c6286d7c.js" defer="defer"></script>
9
9
  </head>
10
10
  <body class="navigation-with-keyboard">
11
11
  <svg xmlns="http://www.w3.org/2000/svg" style="display: none;"><defs>
12
12
  <symbol id="theme-svg-external-link" viewBox="0 0 24 24"><path fill="currentColor" d="M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"/></symbol>
13
13
  </defs></svg>
14
- <script>!function(){var t=function(){try{return new URLSearchParams(window.location.search).get("docusaurus-theme")}catch(t){}}()||function(){try{return window.localStorage.getItem("theme")}catch(t){}}();document.documentElement.setAttribute("data-theme",t||(window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light")),document.documentElement.setAttribute("data-theme-choice",t||"system")}(),function(){try{const c=new URLSearchParams(window.location.search).entries();for(var[t,e]of c)if(t.startsWith("docusaurus-data-")){var a=t.replace("docusaurus-data-","data-");document.documentElement.setAttribute(a,e)}}catch(t){}}()</script><div id="__docusaurus"><link rel="preload" as="image" href="/solace-agent-mesh/img/logo.png"><link rel="preload" as="image" href="/solace-agent-mesh/img/solace-logo.png"><div role="region" aria-label="Skip to main content"><a class="skipToContent_fXgn" href="#__docusaurus_skipToContent_fallback">Skip to main content</a></div><nav aria-label="Main" class="theme-layout-navbar navbar navbar--fixed-top"><div class="navbar__inner"><div class="theme-layout-navbar-left navbar__items"><button aria-label="Toggle navigation bar" aria-expanded="false" class="navbar__toggle clean-btn" type="button"><svg width="30" height="30" viewBox="0 0 30 30" aria-hidden="true"><path stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" d="M4 7h22M4 15h22M4 23h22"></path></svg></button><a class="navbar__brand" href="/solace-agent-mesh/docs/documentation/getting-started/introduction"><div class="navbar__logo"><img src="/solace-agent-mesh/img/logo.png" alt="Solace Agent Mesh Logo" class="themedComponent_mlkZ themedComponent--light_NVdE"><img src="/solace-agent-mesh/img/logo.png" alt="Solace Agent Mesh Logo" class="themedComponent_mlkZ themedComponent--dark_xIcU"></div><b class="navbar__title text--truncate">Solace Agent Mesh</b></a><a class="navbar__item navbar__link" href="/solace-agent-mesh/docs/documentation/getting-started/introduction">Documentation</a></div><div class="theme-layout-navbar-right navbar__items navbar__items--right"><a href="https://github.com/SolaceLabs/solace-agent-mesh/" target="_blank" rel="noopener noreferrer" class="navbar__item navbar__link">GitHub<svg width="13.5" height="13.5" aria-hidden="true" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a><div class="toggle_vylO colorModeToggle_DEke"><button class="clean-btn toggleButton_gllP toggleButtonDisabled_aARS" type="button" disabled="" title="system mode" aria-label="Switch between dark and light mode (currently system mode)"><svg viewBox="0 0 24 24" width="24" height="24" aria-hidden="true" class="toggleIcon_g3eP lightToggleIcon_pyhR"><path fill="currentColor" d="M12,9c1.65,0,3,1.35,3,3s-1.35,3-3,3s-3-1.35-3-3S10.35,9,12,9 M12,7c-2.76,0-5,2.24-5,5s2.24,5,5,5s5-2.24,5-5 S14.76,7,12,7L12,7z M2,13l2,0c0.55,0,1-0.45,1-1s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S1.45,13,2,13z M20,13l2,0c0.55,0,1-0.45,1-1 s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S19.45,13,20,13z M11,2v2c0,0.55,0.45,1,1,1s1-0.45,1-1V2c0-0.55-0.45-1-1-1S11,1.45,11,2z M11,20v2c0,0.55,0.45,1,1,1s1-0.45,1-1v-2c0-0.55-0.45-1-1-1C11.45,19,11,19.45,11,20z M5.99,4.58c-0.39-0.39-1.03-0.39-1.41,0 c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0s0.39-1.03,0-1.41L5.99,4.58z M18.36,16.95 c-0.39-0.39-1.03-0.39-1.41,0c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0c0.39-0.39,0.39-1.03,0-1.41 L18.36,16.95z M19.42,5.99c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06c-0.39,0.39-0.39,1.03,0,1.41 s1.03,0.39,1.41,0L19.42,5.99z M7.05,18.36c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06 c-0.39,0.39-0.39,1.03,0,1.41s1.03,0.39,1.41,0L7.05,18.36z"></path></svg><svg viewBox="0 0 24 24" width="24" height="24" aria-hidden="true" class="toggleIcon_g3eP darkToggleIcon_wfgR"><path fill="currentColor" d="M9.37,5.51C9.19,6.15,9.1,6.82,9.1,7.5c0,4.08,3.32,7.4,7.4,7.4c0.68,0,1.35-0.09,1.99-0.27C17.45,17.19,14.93,19,12,19 c-3.86,0-7-3.14-7-7C5,9.07,6.81,6.55,9.37,5.51z M12,3c-4.97,0-9,4.03-9,9s4.03,9,9,9s9-4.03,9-9c0-0.46-0.04-0.92-0.1-1.36 c-0.98,1.37-2.58,2.26-4.4,2.26c-2.98,0-5.4-2.42-5.4-5.4c0-1.81,0.89-3.42,2.26-4.4C12.92,3.04,12.46,3,12,3L12,3z"></path></svg><svg viewBox="0 0 24 24" width="24" height="24" aria-hidden="true" class="toggleIcon_g3eP systemToggleIcon_QzmC"><path fill="currentColor" d="m12 21c4.971 0 9-4.029 9-9s-4.029-9-9-9-9 4.029-9 9 4.029 9 9 9zm4.95-13.95c1.313 1.313 2.05 3.093 2.05 4.95s-0.738 3.637-2.05 4.95c-1.313 1.313-3.093 2.05-4.95 2.05v-14c1.857 0 3.637 0.737 4.95 2.05z"></path></svg></button></div><div class="navbarSearchContainer_Bca1"><div class="navbar__search"><span aria-label="expand searchbar" role="button" class="search-icon" tabindex="0"></span><input id="search_input_react" type="search" placeholder="Loading..." aria-label="Search" class="navbar__search-input search-bar" disabled=""></div></div></div></div><div role="presentation" class="navbar-sidebar__backdrop"></div></nav><div id="__docusaurus_skipToContent_fallback" class="theme-layout-main main-wrapper mainWrapper_z2l0"><main class="container margin-vert--xl"><div class="row"><div class="col col--6 col--offset-3"><h1 class="hero__title">Page Not Found</h1><p>We could not find what you were looking for.</p><p>Please contact the owner of the site that linked you to the original URL and let them know their link is broken.</p></div></div></main></div><footer class="theme-layout-footer footer footer--dark"><div class="container container-fluid"><div class="row footer__links"><div class="theme-layout-footer-column col footer__col"><div class="footer__title">Solace Agent Mesh</div><ul class="footer__items clean-list"><li class="footer__item"><a class="footer__link-item" href="/solace-agent-mesh/docs/documentation/getting-started/introduction">Documentation</a></li><li class="footer__item"><a href="https://github.com/SolaceLabs/solace-agent-mesh/" target="_blank" rel="noopener noreferrer" class="footer__link-item">GitHub<svg width="13.5" height="13.5" aria-hidden="true" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a></li><li class="footer__item"><a href="https://github.com/SolaceLabs/solace-agent-mesh-core-plugins/" target="_blank" rel="noopener noreferrer" class="footer__link-item">Official Plugins<svg width="13.5" height="13.5" aria-hidden="true" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a></li></ul></div><div class="theme-layout-footer-column col footer__col"><div class="footer__title">Company</div><ul class="footer__items clean-list"><li class="footer__item"><a href="https://solace.com/products/" target="_blank" rel="noopener noreferrer" class="footer__link-item">Products<svg width="13.5" height="13.5" aria-hidden="true" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a></li><li class="footer__item"><a href="https://solace.com/contact/" target="_blank" rel="noopener noreferrer" class="footer__link-item">Contact<svg width="13.5" height="13.5" aria-hidden="true" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a></li><li class="footer__item"><a href="https://solace.com/support/" target="_blank" rel="noopener noreferrer" class="footer__link-item">Support<svg width="13.5" height="13.5" aria-hidden="true" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a></li><li class="footer__item"><a href="https://solace.com/legal/" target="_blank" rel="noopener noreferrer" class="footer__link-item">Privacy and Legal<svg width="13.5" height="13.5" aria-hidden="true" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a></li></ul></div><div class="theme-layout-footer-column col footer__col"><div class="footer__title">Community</div><ul class="footer__items clean-list"><li class="footer__item"><a href="https://www.linkedin.com/company/solacedotcom/" target="_blank" rel="noopener noreferrer" class="footer__link-item">LinkedIn<svg width="13.5" height="13.5" aria-hidden="true" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a></li><li class="footer__item"><a href="https://github.com/SolaceLabs" target="_blank" rel="noopener noreferrer" class="footer__link-item">GitHub<svg width="13.5" height="13.5" aria-hidden="true" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a></li><li class="footer__item"><a href="https://www.youtube.com/SolaceSystems" target="_blank" rel="noopener noreferrer" class="footer__link-item">YouTube<svg width="13.5" height="13.5" aria-hidden="true" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a></li><li class="footer__item"><a href="https://twitter.com/solacedotcom" target="_blank" rel="noopener noreferrer" class="footer__link-item">X<svg width="13.5" height="13.5" aria-hidden="true" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a></li></ul></div></div><div class="footer__bottom text--center"><div class="margin-bottom--sm"><img src="/solace-agent-mesh/img/solace-logo.png" alt="Solace Logo" class="footer__logo themedComponent_mlkZ themedComponent--light_NVdE" width="10%" height="10%"><img src="/solace-agent-mesh/img/solace-logo.png" alt="Solace Logo" class="footer__logo themedComponent_mlkZ themedComponent--dark_xIcU" width="10%" height="10%"></div><div class="footer__copyright">Solace Agent Mesh. Copyright © 2025 Solace. Version: 1.0.1</div></div></div></footer></div>
14
+ <script>!function(){var t=function(){try{return new URLSearchParams(window.location.search).get("docusaurus-theme")}catch(t){}}()||function(){try{return window.localStorage.getItem("theme")}catch(t){}}();document.documentElement.setAttribute("data-theme",t||(window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light")),document.documentElement.setAttribute("data-theme-choice",t||"system")}(),function(){try{const c=new URLSearchParams(window.location.search).entries();for(var[t,e]of c)if(t.startsWith("docusaurus-data-")){var a=t.replace("docusaurus-data-","data-");document.documentElement.setAttribute(a,e)}}catch(t){}}()</script><div id="__docusaurus"><link rel="preload" as="image" href="/solace-agent-mesh/img/logo.png"><link rel="preload" as="image" href="/solace-agent-mesh/img/solace-logo.png"><div role="region" aria-label="Skip to main content"><a class="skipToContent_fXgn" href="#__docusaurus_skipToContent_fallback">Skip to main content</a></div><nav aria-label="Main" class="theme-layout-navbar navbar navbar--fixed-top"><div class="navbar__inner"><div class="theme-layout-navbar-left navbar__items"><button aria-label="Toggle navigation bar" aria-expanded="false" class="navbar__toggle clean-btn" type="button"><svg width="30" height="30" viewBox="0 0 30 30" aria-hidden="true"><path stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" stroke-width="2" d="M4 7h22M4 15h22M4 23h22"></path></svg></button><a class="navbar__brand" href="/solace-agent-mesh/docs/documentation/getting-started/introduction"><div class="navbar__logo"><img src="/solace-agent-mesh/img/logo.png" alt="Solace Agent Mesh Logo" class="themedComponent_mlkZ themedComponent--light_NVdE"><img src="/solace-agent-mesh/img/logo.png" alt="Solace Agent Mesh Logo" class="themedComponent_mlkZ themedComponent--dark_xIcU"></div><b class="navbar__title text--truncate">Solace Agent Mesh</b></a><a class="navbar__item navbar__link" href="/solace-agent-mesh/docs/documentation/getting-started/introduction">Documentation</a></div><div class="theme-layout-navbar-right navbar__items navbar__items--right"><a href="https://github.com/SolaceLabs/solace-agent-mesh/" target="_blank" rel="noopener noreferrer" class="navbar__item navbar__link">GitHub<svg width="13.5" height="13.5" aria-hidden="true" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a><div class="toggle_vylO colorModeToggle_DEke"><button class="clean-btn toggleButton_gllP toggleButtonDisabled_aARS" type="button" disabled="" title="system mode" aria-label="Switch between dark and light mode (currently system mode)"><svg viewBox="0 0 24 24" width="24" height="24" aria-hidden="true" class="toggleIcon_g3eP lightToggleIcon_pyhR"><path fill="currentColor" d="M12,9c1.65,0,3,1.35,3,3s-1.35,3-3,3s-3-1.35-3-3S10.35,9,12,9 M12,7c-2.76,0-5,2.24-5,5s2.24,5,5,5s5-2.24,5-5 S14.76,7,12,7L12,7z M2,13l2,0c0.55,0,1-0.45,1-1s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S1.45,13,2,13z M20,13l2,0c0.55,0,1-0.45,1-1 s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S19.45,13,20,13z M11,2v2c0,0.55,0.45,1,1,1s1-0.45,1-1V2c0-0.55-0.45-1-1-1S11,1.45,11,2z M11,20v2c0,0.55,0.45,1,1,1s1-0.45,1-1v-2c0-0.55-0.45-1-1-1C11.45,19,11,19.45,11,20z M5.99,4.58c-0.39-0.39-1.03-0.39-1.41,0 c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0s0.39-1.03,0-1.41L5.99,4.58z M18.36,16.95 c-0.39-0.39-1.03-0.39-1.41,0c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0c0.39-0.39,0.39-1.03,0-1.41 L18.36,16.95z M19.42,5.99c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06c-0.39,0.39-0.39,1.03,0,1.41 s1.03,0.39,1.41,0L19.42,5.99z M7.05,18.36c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06 c-0.39,0.39-0.39,1.03,0,1.41s1.03,0.39,1.41,0L7.05,18.36z"></path></svg><svg viewBox="0 0 24 24" width="24" height="24" aria-hidden="true" class="toggleIcon_g3eP darkToggleIcon_wfgR"><path fill="currentColor" d="M9.37,5.51C9.19,6.15,9.1,6.82,9.1,7.5c0,4.08,3.32,7.4,7.4,7.4c0.68,0,1.35-0.09,1.99-0.27C17.45,17.19,14.93,19,12,19 c-3.86,0-7-3.14-7-7C5,9.07,6.81,6.55,9.37,5.51z M12,3c-4.97,0-9,4.03-9,9s4.03,9,9,9s9-4.03,9-9c0-0.46-0.04-0.92-0.1-1.36 c-0.98,1.37-2.58,2.26-4.4,2.26c-2.98,0-5.4-2.42-5.4-5.4c0-1.81,0.89-3.42,2.26-4.4C12.92,3.04,12.46,3,12,3L12,3z"></path></svg><svg viewBox="0 0 24 24" width="24" height="24" aria-hidden="true" class="toggleIcon_g3eP systemToggleIcon_QzmC"><path fill="currentColor" d="m12 21c4.971 0 9-4.029 9-9s-4.029-9-9-9-9 4.029-9 9 4.029 9 9 9zm4.95-13.95c1.313 1.313 2.05 3.093 2.05 4.95s-0.738 3.637-2.05 4.95c-1.313 1.313-3.093 2.05-4.95 2.05v-14c1.857 0 3.637 0.737 4.95 2.05z"></path></svg></button></div><div class="navbarSearchContainer_Bca1"><div class="navbar__search"><span aria-label="expand searchbar" role="button" class="search-icon" tabindex="0"></span><input id="search_input_react" type="search" placeholder="Loading..." aria-label="Search" class="navbar__search-input search-bar" disabled=""></div></div></div></div><div role="presentation" class="navbar-sidebar__backdrop"></div></nav><div id="__docusaurus_skipToContent_fallback" class="theme-layout-main main-wrapper mainWrapper_z2l0"><main class="container margin-vert--xl"><div class="row"><div class="col col--6 col--offset-3"><h1 class="hero__title">Page Not Found</h1><p>We could not find what you were looking for.</p><p>Please contact the owner of the site that linked you to the original URL and let them know their link is broken.</p></div></div></main></div><footer class="theme-layout-footer footer footer--dark"><div class="container container-fluid"><div class="row footer__links"><div class="theme-layout-footer-column col footer__col"><div class="footer__title">Solace Agent Mesh</div><ul class="footer__items clean-list"><li class="footer__item"><a class="footer__link-item" href="/solace-agent-mesh/docs/documentation/getting-started/introduction">Documentation</a></li><li class="footer__item"><a href="https://github.com/SolaceLabs/solace-agent-mesh/" target="_blank" rel="noopener noreferrer" class="footer__link-item">GitHub<svg width="13.5" height="13.5" aria-hidden="true" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a></li><li class="footer__item"><a href="https://github.com/SolaceLabs/solace-agent-mesh-core-plugins/" target="_blank" rel="noopener noreferrer" class="footer__link-item">Official Plugins<svg width="13.5" height="13.5" aria-hidden="true" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a></li></ul></div><div class="theme-layout-footer-column col footer__col"><div class="footer__title">Company</div><ul class="footer__items clean-list"><li class="footer__item"><a href="https://solace.com/products/" target="_blank" rel="noopener noreferrer" class="footer__link-item">Products<svg width="13.5" height="13.5" aria-hidden="true" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a></li><li class="footer__item"><a href="https://solace.com/contact/" target="_blank" rel="noopener noreferrer" class="footer__link-item">Contact<svg width="13.5" height="13.5" aria-hidden="true" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a></li><li class="footer__item"><a href="https://solace.com/support/" target="_blank" rel="noopener noreferrer" class="footer__link-item">Support<svg width="13.5" height="13.5" aria-hidden="true" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a></li><li class="footer__item"><a href="https://solace.com/legal/" target="_blank" rel="noopener noreferrer" class="footer__link-item">Privacy and Legal<svg width="13.5" height="13.5" aria-hidden="true" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a></li></ul></div><div class="theme-layout-footer-column col footer__col"><div class="footer__title">Community</div><ul class="footer__items clean-list"><li class="footer__item"><a href="https://www.linkedin.com/company/solacedotcom/" target="_blank" rel="noopener noreferrer" class="footer__link-item">LinkedIn<svg width="13.5" height="13.5" aria-hidden="true" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a></li><li class="footer__item"><a href="https://github.com/SolaceLabs" target="_blank" rel="noopener noreferrer" class="footer__link-item">GitHub<svg width="13.5" height="13.5" aria-hidden="true" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a></li><li class="footer__item"><a href="https://www.youtube.com/SolaceSystems" target="_blank" rel="noopener noreferrer" class="footer__link-item">YouTube<svg width="13.5" height="13.5" aria-hidden="true" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a></li><li class="footer__item"><a href="https://twitter.com/solacedotcom" target="_blank" rel="noopener noreferrer" class="footer__link-item">X<svg width="13.5" height="13.5" aria-hidden="true" class="iconExternalLink_nPIU"><use href="#theme-svg-external-link"></use></svg></a></li></ul></div></div><div class="footer__bottom text--center"><div class="margin-bottom--sm"><img src="/solace-agent-mesh/img/solace-logo.png" alt="Solace Logo" class="footer__logo themedComponent_mlkZ themedComponent--light_NVdE" width="10%" height="10%"><img src="/solace-agent-mesh/img/solace-logo.png" alt="Solace Logo" class="footer__logo themedComponent_mlkZ themedComponent--dark_xIcU" width="10%" height="10%"></div><div class="footer__copyright">Solace Agent Mesh. Copyright © 2025 Solace. Version: 1.0.2</div></div></div></footer></div>
15
15
  </body>
16
16
  </html>