solace-agent-mesh 1.5.1__py3-none-any.whl → 1.6.1__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 (184) hide show
  1. solace_agent_mesh/agent/adk/callbacks.py +0 -5
  2. solace_agent_mesh/agent/adk/models/lite_llm.py +123 -8
  3. solace_agent_mesh/agent/adk/models/oauth2_token_manager.py +245 -0
  4. solace_agent_mesh/agent/protocol/event_handlers.py +213 -31
  5. solace_agent_mesh/agent/proxies/__init__.py +0 -0
  6. solace_agent_mesh/agent/proxies/a2a/__init__.py +3 -0
  7. solace_agent_mesh/agent/proxies/a2a/app.py +55 -0
  8. solace_agent_mesh/agent/proxies/a2a/component.py +1115 -0
  9. solace_agent_mesh/agent/proxies/a2a/config.py +140 -0
  10. solace_agent_mesh/agent/proxies/a2a/oauth_token_cache.py +104 -0
  11. solace_agent_mesh/agent/proxies/base/__init__.py +3 -0
  12. solace_agent_mesh/agent/proxies/base/app.py +99 -0
  13. solace_agent_mesh/agent/proxies/base/component.py +650 -0
  14. solace_agent_mesh/agent/proxies/base/config.py +85 -0
  15. solace_agent_mesh/agent/proxies/base/proxy_task_context.py +17 -0
  16. solace_agent_mesh/agent/sac/app.py +58 -5
  17. solace_agent_mesh/agent/sac/component.py +238 -75
  18. solace_agent_mesh/agent/sac/task_execution_context.py +46 -0
  19. solace_agent_mesh/agent/tools/audio_tools.py +125 -8
  20. solace_agent_mesh/agent/tools/web_tools.py +10 -5
  21. solace_agent_mesh/agent/utils/artifact_helpers.py +141 -3
  22. solace_agent_mesh/assets/docs/404.html +3 -3
  23. solace_agent_mesh/assets/docs/assets/js/5c2bd65f.eda4bcb2.js +1 -0
  24. solace_agent_mesh/assets/docs/assets/js/6ad8f0bd.f4b15f3b.js +1 -0
  25. solace_agent_mesh/assets/docs/assets/js/71da7b71.38583438.js +1 -0
  26. solace_agent_mesh/assets/docs/assets/js/77cf947d.48cb18a2.js +1 -0
  27. solace_agent_mesh/assets/docs/assets/js/924ffdeb.8095e148.js +1 -0
  28. solace_agent_mesh/assets/docs/assets/js/9e9d0a82.570c057b.js +1 -0
  29. solace_agent_mesh/assets/docs/assets/js/{ad71b5ed.60668e9e.js → ad71b5ed.af3ecfd1.js} +1 -1
  30. solace_agent_mesh/assets/docs/assets/js/ceb2a7a6.5d92d7d0.js +1 -0
  31. solace_agent_mesh/assets/docs/assets/js/{da0b5bad.9d369087.js → da0b5bad.d08a9466.js} +1 -1
  32. solace_agent_mesh/assets/docs/assets/js/db924877.e98d12a1.js +1 -0
  33. solace_agent_mesh/assets/docs/assets/js/de915948.27d6b065.js +1 -0
  34. solace_agent_mesh/assets/docs/assets/js/{e3d9abda.2b916f9e.js → e3d9abda.6b9493d0.js} +1 -1
  35. solace_agent_mesh/assets/docs/assets/js/e6f9706b.e74a984d.js +1 -0
  36. solace_agent_mesh/assets/docs/assets/js/f284c35a.42f59cdd.js +1 -0
  37. solace_agent_mesh/assets/docs/assets/js/ff4d71f2.15b02f97.js +1 -0
  38. solace_agent_mesh/assets/docs/assets/js/{main.bd3c34f3.js → main.b12eac43.js} +2 -2
  39. solace_agent_mesh/assets/docs/assets/js/runtime~main.e268214e.js +1 -0
  40. solace_agent_mesh/assets/docs/docs/documentation/components/agents/index.html +15 -4
  41. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/artifact-management/index.html +4 -4
  42. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/audio-tools/index.html +4 -4
  43. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/data-analysis-tools/index.html +4 -4
  44. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/embeds/index.html +4 -4
  45. solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/index.html +4 -4
  46. solace_agent_mesh/assets/docs/docs/documentation/components/cli/index.html +4 -4
  47. solace_agent_mesh/assets/docs/docs/documentation/components/gateways/index.html +4 -4
  48. solace_agent_mesh/assets/docs/docs/documentation/components/index.html +4 -4
  49. solace_agent_mesh/assets/docs/docs/documentation/components/orchestrator/index.html +4 -4
  50. solace_agent_mesh/assets/docs/docs/documentation/components/plugins/index.html +4 -4
  51. solace_agent_mesh/assets/docs/docs/documentation/components/proxies/index.html +262 -0
  52. solace_agent_mesh/assets/docs/docs/documentation/deploying/debugging/index.html +3 -3
  53. solace_agent_mesh/assets/docs/docs/documentation/deploying/deployment-options/index.html +31 -3
  54. solace_agent_mesh/assets/docs/docs/documentation/deploying/index.html +3 -3
  55. solace_agent_mesh/assets/docs/docs/documentation/deploying/observability/index.html +3 -3
  56. solace_agent_mesh/assets/docs/docs/documentation/developing/create-agents/index.html +4 -4
  57. solace_agent_mesh/assets/docs/docs/documentation/developing/create-gateways/index.html +5 -5
  58. solace_agent_mesh/assets/docs/docs/documentation/developing/creating-python-tools/index.html +4 -4
  59. solace_agent_mesh/assets/docs/docs/documentation/developing/creating-service-providers/index.html +4 -4
  60. solace_agent_mesh/assets/docs/docs/documentation/developing/evaluations/index.html +135 -0
  61. solace_agent_mesh/assets/docs/docs/documentation/developing/index.html +6 -4
  62. solace_agent_mesh/assets/docs/docs/documentation/developing/structure/index.html +4 -4
  63. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/bedrock-agents/index.html +4 -4
  64. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/custom-agent/index.html +4 -4
  65. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/event-mesh-gateway/index.html +5 -5
  66. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/mcp-integration/index.html +4 -4
  67. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/mongodb-integration/index.html +4 -4
  68. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/rag-integration/index.html +4 -4
  69. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/rest-gateway/index.html +4 -4
  70. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/slack-integration/index.html +4 -4
  71. solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/sql-database/index.html +4 -4
  72. solace_agent_mesh/assets/docs/docs/documentation/enterprise/index.html +3 -3
  73. solace_agent_mesh/assets/docs/docs/documentation/enterprise/installation/index.html +3 -3
  74. solace_agent_mesh/assets/docs/docs/documentation/enterprise/rbac-setup-guide/index.html +3 -3
  75. solace_agent_mesh/assets/docs/docs/documentation/enterprise/single-sign-on/index.html +3 -3
  76. solace_agent_mesh/assets/docs/docs/documentation/getting-started/architecture/index.html +3 -3
  77. solace_agent_mesh/assets/docs/docs/documentation/getting-started/index.html +3 -3
  78. solace_agent_mesh/assets/docs/docs/documentation/getting-started/introduction/index.html +3 -3
  79. solace_agent_mesh/assets/docs/docs/documentation/getting-started/try-agent-mesh/index.html +3 -3
  80. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/configurations/index.html +6 -5
  81. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/index.html +3 -3
  82. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/installation/index.html +3 -3
  83. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/large_language_models/index.html +100 -3
  84. solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/run-project/index.html +3 -3
  85. solace_agent_mesh/assets/docs/docs/documentation/migrations/a2a-upgrade/a2a-gateway-upgrade-to-0.3.0/index.html +3 -3
  86. solace_agent_mesh/assets/docs/docs/documentation/migrations/a2a-upgrade/a2a-technical-migration-map/index.html +3 -3
  87. solace_agent_mesh/assets/docs/lunr-index-1761248203150.json +1 -0
  88. solace_agent_mesh/assets/docs/lunr-index.json +1 -1
  89. solace_agent_mesh/assets/docs/search-doc-1761248203150.json +1 -0
  90. solace_agent_mesh/assets/docs/search-doc.json +1 -1
  91. solace_agent_mesh/assets/docs/sitemap.xml +1 -1
  92. solace_agent_mesh/cli/__init__.py +1 -1
  93. solace_agent_mesh/cli/commands/add_cmd/agent_cmd.py +2 -69
  94. solace_agent_mesh/cli/commands/eval_cmd.py +11 -49
  95. solace_agent_mesh/cli/commands/init_cmd/__init__.py +0 -5
  96. solace_agent_mesh/cli/commands/init_cmd/env_step.py +10 -12
  97. solace_agent_mesh/cli/commands/init_cmd/orchestrator_step.py +9 -61
  98. solace_agent_mesh/cli/commands/init_cmd/webui_gateway_step.py +9 -49
  99. solace_agent_mesh/cli/commands/plugin_cmd/add_cmd.py +1 -2
  100. solace_agent_mesh/client/webui/frontend/static/assets/{authCallback-DwrxZE0E.js → authCallback-BTf6dqwp.js} +1 -1
  101. solace_agent_mesh/client/webui/frontend/static/assets/{client-DarGQzyw.js → client-CaY59VuC.js} +1 -1
  102. solace_agent_mesh/client/webui/frontend/static/assets/main-B32noGmR.js +342 -0
  103. solace_agent_mesh/client/webui/frontend/static/assets/main-DHJKSW1S.css +1 -0
  104. solace_agent_mesh/client/webui/frontend/static/assets/{vendor-BKIeiHj_.js → vendor-BEmvJSYz.js} +1 -1
  105. solace_agent_mesh/client/webui/frontend/static/auth-callback.html +3 -3
  106. solace_agent_mesh/client/webui/frontend/static/index.html +4 -4
  107. solace_agent_mesh/common/a2a/__init__.py +24 -0
  108. solace_agent_mesh/common/a2a/artifact.py +39 -0
  109. solace_agent_mesh/common/a2a/events.py +29 -0
  110. solace_agent_mesh/common/a2a/message.py +68 -0
  111. solace_agent_mesh/common/a2a/protocol.py +151 -1
  112. solace_agent_mesh/common/agent_registry.py +83 -3
  113. solace_agent_mesh/common/constants.py +3 -1
  114. solace_agent_mesh/common/sac/sam_component_base.py +383 -4
  115. solace_agent_mesh/common/utils/pydantic_utils.py +12 -0
  116. solace_agent_mesh/config_portal/backend/common.py +1 -1
  117. solace_agent_mesh/config_portal/frontend/static/client/assets/_index-ByU1X1HD.js +98 -0
  118. solace_agent_mesh/config_portal/frontend/static/client/assets/{manifest-44d62be6.js → manifest-61038fc6.js} +1 -1
  119. solace_agent_mesh/config_portal/frontend/static/client/index.html +1 -1
  120. solace_agent_mesh/evaluation/evaluator.py +128 -104
  121. solace_agent_mesh/evaluation/message_organizer.py +116 -110
  122. solace_agent_mesh/evaluation/report_data_processor.py +84 -86
  123. solace_agent_mesh/evaluation/report_generator.py +73 -79
  124. solace_agent_mesh/evaluation/run.py +421 -235
  125. solace_agent_mesh/evaluation/shared/__init__.py +92 -0
  126. solace_agent_mesh/evaluation/shared/constants.py +47 -0
  127. solace_agent_mesh/evaluation/shared/exceptions.py +50 -0
  128. solace_agent_mesh/evaluation/shared/helpers.py +35 -0
  129. solace_agent_mesh/evaluation/shared/test_case_loader.py +167 -0
  130. solace_agent_mesh/evaluation/shared/test_suite_loader.py +280 -0
  131. solace_agent_mesh/evaluation/subscriber.py +111 -232
  132. solace_agent_mesh/evaluation/summary_builder.py +227 -117
  133. solace_agent_mesh/gateway/base/app.py +16 -1
  134. solace_agent_mesh/gateway/base/component.py +112 -39
  135. solace_agent_mesh/gateway/http_sse/alembic/versions/20251015_add_session_performance_indexes.py +70 -0
  136. solace_agent_mesh/gateway/http_sse/component.py +99 -3
  137. solace_agent_mesh/gateway/http_sse/dependencies.py +4 -4
  138. solace_agent_mesh/gateway/http_sse/main.py +1 -0
  139. solace_agent_mesh/gateway/http_sse/repository/chat_task_repository.py +12 -13
  140. solace_agent_mesh/gateway/http_sse/repository/feedback_repository.py +15 -18
  141. solace_agent_mesh/gateway/http_sse/repository/interfaces.py +25 -18
  142. solace_agent_mesh/gateway/http_sse/repository/session_repository.py +30 -26
  143. solace_agent_mesh/gateway/http_sse/repository/task_repository.py +35 -44
  144. solace_agent_mesh/gateway/http_sse/routers/agent_cards.py +4 -3
  145. solace_agent_mesh/gateway/http_sse/routers/artifacts.py +95 -203
  146. solace_agent_mesh/gateway/http_sse/routers/dto/responses/session_responses.py +4 -3
  147. solace_agent_mesh/gateway/http_sse/routers/sessions.py +2 -2
  148. solace_agent_mesh/gateway/http_sse/routers/tasks.py +33 -41
  149. solace_agent_mesh/gateway/http_sse/routers/users.py +47 -1
  150. solace_agent_mesh/gateway/http_sse/routers/visualization.py +17 -11
  151. solace_agent_mesh/gateway/http_sse/services/data_retention_service.py +4 -4
  152. solace_agent_mesh/gateway/http_sse/services/feedback_service.py +51 -43
  153. solace_agent_mesh/gateway/http_sse/services/session_service.py +20 -20
  154. solace_agent_mesh/gateway/http_sse/services/task_logger_service.py +8 -8
  155. solace_agent_mesh/gateway/http_sse/shared/base_repository.py +45 -71
  156. solace_agent_mesh/gateway/http_sse/shared/types.py +0 -18
  157. solace_agent_mesh/templates/gateway_config_template.yaml +0 -5
  158. solace_agent_mesh/templates/logging_config_template.ini +10 -6
  159. solace_agent_mesh/templates/plugin_gateway_config_template.yaml +0 -3
  160. solace_agent_mesh/templates/shared_config.yaml +40 -0
  161. {solace_agent_mesh-1.5.1.dist-info → solace_agent_mesh-1.6.1.dist-info}/METADATA +47 -21
  162. {solace_agent_mesh-1.5.1.dist-info → solace_agent_mesh-1.6.1.dist-info}/RECORD +166 -145
  163. solace_agent_mesh/assets/docs/assets/js/5c2bd65f.e49689dd.js +0 -1
  164. solace_agent_mesh/assets/docs/assets/js/6ad8f0bd.39d5851d.js +0 -1
  165. solace_agent_mesh/assets/docs/assets/js/71da7b71.804d6567.js +0 -1
  166. solace_agent_mesh/assets/docs/assets/js/77cf947d.64c9bd6c.js +0 -1
  167. solace_agent_mesh/assets/docs/assets/js/9e9d0a82.dd810042.js +0 -1
  168. solace_agent_mesh/assets/docs/assets/js/db924877.cbc66f02.js +0 -1
  169. solace_agent_mesh/assets/docs/assets/js/de915948.139b4b9c.js +0 -1
  170. solace_agent_mesh/assets/docs/assets/js/e6f9706b.582a78ca.js +0 -1
  171. solace_agent_mesh/assets/docs/assets/js/f284c35a.5766a13d.js +0 -1
  172. solace_agent_mesh/assets/docs/assets/js/ff4d71f2.9c0297a6.js +0 -1
  173. solace_agent_mesh/assets/docs/assets/js/runtime~main.18dc45dd.js +0 -1
  174. solace_agent_mesh/assets/docs/lunr-index-1760121512891.json +0 -1
  175. solace_agent_mesh/assets/docs/search-doc-1760121512891.json +0 -1
  176. solace_agent_mesh/client/webui/frontend/static/assets/main-2nd1gbaH.js +0 -339
  177. solace_agent_mesh/client/webui/frontend/static/assets/main-DoKXctCM.css +0 -1
  178. solace_agent_mesh/config_portal/frontend/static/client/assets/_index-BNuqpWDc.js +0 -98
  179. solace_agent_mesh/evaluation/config_loader.py +0 -657
  180. solace_agent_mesh/evaluation/test_case_loader.py +0 -714
  181. /solace_agent_mesh/assets/docs/assets/js/{main.bd3c34f3.js.LICENSE.txt → main.b12eac43.js.LICENSE.txt} +0 -0
  182. {solace_agent_mesh-1.5.1.dist-info → solace_agent_mesh-1.6.1.dist-info}/WHEEL +0 -0
  183. {solace_agent_mesh-1.5.1.dist-info → solace_agent_mesh-1.6.1.dist-info}/entry_points.txt +0 -0
  184. {solace_agent_mesh-1.5.1.dist-info → solace_agent_mesh-1.6.1.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1 @@
1
+ "use strict";(self.webpackChunksolace_agenitc_mesh_docs=self.webpackChunksolace_agenitc_mesh_docs||[]).push([[6084],{4795:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>s,default:()=>h,frontMatter:()=>i,metadata:()=>a,toc:()=>l});const a=JSON.parse('{"id":"documentation/developing/tutorials/custom-agent","title":"Build Your Own Agent","description":"This tutorial shows you how to build a sophisticated weather agent using the Agent Mesh framework. Learn how to integrate with external APIs, manage resources properly, and create production-ready agents.","source":"@site/docs/documentation/developing/tutorials/custom-agent.md","sourceDirName":"documentation/developing/tutorials","slug":"/documentation/developing/tutorials/custom-agent","permalink":"/solace-agent-mesh/docs/documentation/developing/tutorials/custom-agent","draft":false,"unlisted":false,"editUrl":"https://github.com/SolaceLabs/solace-agent-mesh/edit/main/docs/docs/documentation/developing/tutorials/custom-agent.md","tags":[],"version":"current","sidebarPosition":5,"frontMatter":{"title":"Build Your Own Agent","sidebar_position":5},"sidebar":"docSidebar","previous":{"title":"Evaluating Agents","permalink":"/solace-agent-mesh/docs/documentation/developing/evaluations"},"next":{"title":"MCP Integration","permalink":"/solace-agent-mesh/docs/documentation/developing/tutorials/mcp-integration"}}');var r=t(4848),o=t(8453);const i={title:"Build Your Own Agent",sidebar_position:5},s="Build Your Own Agent",c={},l=[{value:"Overview",id:"overview",level:2},{value:"Prerequisites",id:"prerequisites",level:2},{value:"Planning the Weather Agent",id:"planning-the-weather-agent",level:2},{value:"Step 1: Project Structure",id:"step-1-project-structure",level:2},{value:"Step 2: Weather Service Implementation",id:"step-2-weather-service-implementation",level:2},{value:"Step 3: Weather Tools Implementation",id:"step-3-weather-tools-implementation",level:2},{value:"Step 4: Lifecycle Functions",id:"step-4-lifecycle-functions",level:2},{value:"Step 5: Agent Configuration",id:"step-5-agent-configuration",level:2},{value:"Step 6: Environment Setup",id:"step-6-environment-setup",level:2},{value:"Step 7: Running the Agent",id:"step-7-running-the-agent",level:2},{value:"Step 8: Testing the Weather Agent",id:"step-8-testing-the-weather-agent",level:2},{value:"Key Features Demonstrated",id:"key-features-demonstrated",level:2},{value:"1. External API Integration",id:"1-external-api-integration",level:3},{value:"2. Resource Management",id:"2-resource-management",level:3},{value:"3. Configuration Management",id:"3-configuration-management",level:3},{value:"4. Error Handling",id:"4-error-handling",level:3},{value:"5. Artifact Management",id:"5-artifact-management",level:3}];function d(e){const n={a:"a",admonition:"admonition",blockquote:"blockquote",code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,o.R)(),...e.components},{Details:t}=n;return t||function(e,n){throw new Error("Expected "+(n?"component":"object")+" `"+e+"` to be defined: you likely forgot to import, pass, or provide it.")}("Details",!0),(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.header,{children:(0,r.jsx)(n.h1,{id:"build-your-own-agent",children:"Build Your Own Agent"})}),"\n",(0,r.jsx)(n.p,{children:"This tutorial shows you how to build a sophisticated weather agent using the Agent Mesh framework. Learn how to integrate with external APIs, manage resources properly, and create production-ready agents."}),"\n",(0,r.jsx)(n.h2,{id:"overview",children:"Overview"}),"\n",(0,r.jsx)(n.p,{children:"Our weather agent will demonstrate:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"External API integration (OpenWeatherMap)"}),"\n",(0,r.jsx)(n.li,{children:"Professional service layer architecture"}),"\n",(0,r.jsx)(n.li,{children:"Multiple sophisticated tools"}),"\n",(0,r.jsx)(n.li,{children:"Proper lifecycle management"}),"\n",(0,r.jsx)(n.li,{children:"Error handling and validation"}),"\n",(0,r.jsx)(n.li,{children:"Artifact creation and management"}),"\n"]}),"\n",(0,r.jsx)(n.h2,{id:"prerequisites",children:"Prerequisites"}),"\n",(0,r.jsx)(n.p,{children:"Before starting this tutorial, make sure you have:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["Read the ",(0,r.jsx)(n.a,{href:"/solace-agent-mesh/docs/documentation/developing/create-agents",children:"Create Agent"})," tutorial"]}),"\n",(0,r.jsxs)(n.li,{children:["An OpenWeatherMap API key (free at ",(0,r.jsx)(n.a,{href:"https://openweathermap.org/api",children:"openweathermap.org"}),")"]}),"\n",(0,r.jsx)(n.li,{children:"Basic understanding of Python async/await"}),"\n",(0,r.jsx)(n.li,{children:"Familiarity with HTTP APIs"}),"\n"]}),"\n",(0,r.jsx)(n.h2,{id:"planning-the-weather-agent",children:"Planning the Weather Agent"}),"\n",(0,r.jsx)(n.p,{children:"Our weather agent will have the following capabilities:"}),"\n",(0,r.jsxs)(n.ol,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.strong,{children:"Get Current Weather"}),": Fetch current weather conditions for a specified location"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.strong,{children:"Get Weather Forecast"}),": Retrieve a multi-day weather forecast"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.strong,{children:"Save Weather Reports"}),": Store weather data as artifacts"]}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"The agent will demonstrate:"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"External API integration"}),"\n",(0,r.jsx)(n.li,{children:"Error handling and validation"}),"\n",(0,r.jsx)(n.li,{children:"Configuration management"}),"\n",(0,r.jsx)(n.li,{children:"Artifact creation"}),"\n",(0,r.jsx)(n.li,{children:"Resource lifecycle management"}),"\n"]}),"\n",(0,r.jsx)(n.h2,{id:"step-1-project-structure",children:"Step 1: Project Structure"}),"\n",(0,r.jsx)(n.p,{children:"Run the following command to create a new custom agent:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"sam add agent --gui\n"})}),"\n",(0,r.jsxs)(n.admonition,{type:"tip",children:[(0,r.jsxs)(n.p,{children:["You can create an agent either by using the ",(0,r.jsx)(n.code,{children:"sam add agent"})," command or by creating a new plugin of type agent, ",(0,r.jsx)(n.code,{children:"sam plugin create my-hello-agent --type agent"}),"."]}),(0,r.jsxs)(n.p,{children:["For information and recommendations about these options, see ",(0,r.jsx)(n.a,{href:"/solace-agent-mesh/docs/documentation/components/plugins#agent-or-plugin-which-to-use",children:(0,r.jsx)(n.code,{children:"Agent or Plugin: Which To use?"})}),"."]}),(0,r.jsxs)(n.p,{children:["For an example of plugin agents, see the ",(0,r.jsx)(n.a,{href:"/solace-agent-mesh/docs/documentation/developing/create-agents#step-1-initialize-your-agent",children:"Create Agents"})," guide."]})]}),"\n",(0,r.jsx)(n.p,{children:'Follow the steps on the GUI to create a new agent named "Weather Agent". We can update the tools/skills section directly in the configuration file later.'}),"\n",(0,r.jsxs)(n.admonition,{title:"Important Notice",type:"warning",children:[(0,r.jsx)(n.p,{children:"This tutorial is intentionally comprehensive to demonstrate the full flexibility and advanced features available in Agent Mesh agents. For most straightforward use cases, you only need a simple Python function and a corresponding reference in your YAML configuration file."}),(0,r.jsxs)(t,{children:[(0,r.jsx)("summary",{children:"Simple Weather Agent Example"}),(0,r.jsxs)(n.p,{children:["After going through the add agent wizard from ",(0,r.jsx)(n.code,{children:"sam add agent --gui"}),", create the following file under ",(0,r.jsx)(n.code,{children:"src/weather_agent/tools.py"})," directory:"]}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-py",children:'# src/weather_agent/tools.py\nimport httpx\nfrom typing import Any, Dict, Optional\nfrom google.adk.tools import ToolContext\nfrom solace_ai_connector.common.log import log\n\n\nasync def get_current_weather(\n location: str,\n units: str = "metric",\n tool_context: Optional[ToolContext] = None,\n tool_config: Optional[Dict[str, Any]] = None\n) -> Dict[str, Any]:\n """\n Get current weather conditions for a specified location.\n \n Args:\n location: City name, state, and country (for example, "New York, NY, US")\n units: Temperature units - "metric" (Celsius), "imperial" (Fahrenheit), or "kelvin"\n """\n log.info("[GetCurrentWeather] Getting current weather for: %s", location)\n base_url = "https://api.openweathermap.org/data/2.5"\n api_key = tool_config.get("api_key") if tool_config else None\n\n url = f"{base_url}/weather"\n params = {\n "q": location,\n "appid": api_key,\n "units": units\n }\n\n try:\n # Fetch weather data\n async with httpx.AsyncClient() as client:\n response = await client.get(url, params=params)\n response.raise_for_status()\n weather_data = response.json()\n \n result = {\n "status": "success",\n "location": location,\n "units": units,\n "data": weather_data\n }\n return result\n \n except Exception as e:\n log.error(f"[GetCurrentWeather] Error getting weather: {e}")\n return {\n "status": "error",\n "message": f"Weather service error: {str(e)}"\n }\n\n\nasync def get_weather_forecast(\n location: str,\n days: int = 5,\n units: str = "metric",\n tool_context: Optional[ToolContext] = None,\n tool_config: Optional[Dict[str, Any]] = None\n) -> Dict[str, Any]:\n """\n Get weather forecast for a specified location.\n \n Args:\n location: City name, state, and country\n days: Number of days for forecast (1-5)\n units: Temperature units\n """\n log.info("[GetWeatherForecast] Getting %d-day forecast for: %s", days, location)\n base_url = "https://api.openweathermap.org/data/2.5"\n api_key = tool_config.get("api_key") if tool_config else None\n\n url = f"{base_url}/forecast"\n params = {\n "q": location,\n "appid": api_key,\n "units": units,\n "cnt": min(days * 8, 40) \n }\n\n try:\n # Fetch forecast data\n async with httpx.AsyncClient() as client:\n response = await client.get(url, params=params)\n response.raise_for_status()\n forecast_data = response.json()\n\n result = {\n "status": "success",\n "location": forecast_data["location"],\n "days": days,\n "units": units,\n "data": forecast_data\n }\n return result\n except Exception as e:\n log.error(f"[GetWeatherForecast] Error getting forecast: {e}")\n return {\n "status": "error",\n "message": f"Weather service error: {str(e)}"\n }\n\n'})}),(0,r.jsxs)(n.p,{children:["And update the weather agent config file's tool section under ",(0,r.jsx)(n.code,{children:"configs/agent/weather-agent.yaml"})," as follows:"]}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-yaml",children:' # Tools configuration\n tools:\n # Current weather tool\n - tool_type: python\n component_module: "src.weather_agent.tools"\n component_base_path: .\n function_name: "get_current_weather"\n tool_description: "Get current weather conditions for a specified location"\n tool_config:\n api_key: ${OPENWEATHER_API_KEY}\n\n # Weather forecast tool\n - tool_type: python\n component_module: "src.weather_agent.tools"\n function_name: "get_weather_forecast"\n component_base_path: .\n tool_description: "Get weather forecast for up to 5 days for a specified location"\n tool_config:\n api_key: ${OPENWEATHER_API_KEY}\n\n'})}),(0,r.jsxs)(n.p,{children:["For better discoverability, update the ",(0,r.jsx)(n.a,{href:"/solace-agent-mesh/docs/documentation/components/agents#agent-card",children:"agent card"})," section in the same YAML file as follows:"]}),(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-yaml",children:' # Agent card\n agent_card:\n description: "Professional weather agent providing current conditions, forecasts, and weather comparisons"\n defaultInputModes: ["text"]\n defaultOutputModes: ["text"]\n skills:\n - id: "get_current_weather"\n name: "Get Current Weather"\n description: "Retrieve current weather conditions for any location worldwide"\n - id: "get_weather_forecast"\n name: "Get Weather Forecast"\n description: "Provide detailed weather forecasts up to 5 days ahead"\n'})}),(0,r.jsxs)(n.p,{children:["To run the agent, you can continue following documentation from ",(0,r.jsx)(n.a,{href:"#step-6-environment-setup",children:"Step 6"})," of this tutorial."]})]}),(0,r.jsx)(n.p,{children:"Other concepts mentioned in this page such as lifecycle, services, artifacts are just to showcase more advanced patterns."})]}),"\n",(0,r.jsx)(n.p,{children:"Create the directory structure for the weather agent:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{children:"sam-project/\n\u251c\u2500\u2500 src/\n\u2502 \u2514\u2500\u2500 weather_agent/\n\u2502 \u251c\u2500\u2500 __init__.py\n\u2502 \u251c\u2500\u2500 tools.py\n\u2502 \u251c\u2500\u2500 lifecycle.py\n\u2502 \u2514\u2500\u2500 services/\n\u2502 \u251c\u2500\u2500 __init__.py\n\u2502 \u2514\u2500\u2500 weather_service.py\n\u251c\u2500\u2500 configs\n\u2502 \u2514\u2500\u2500 shared_config.yaml\n\u2502 \u2514\u2500\u2500 agents/\n\u2502 \u2514\u2500\u2500 weather_agent.yaml\n...\n"})}),"\n",(0,r.jsxs)(n.admonition,{type:"tip",children:[(0,r.jsxs)(n.p,{children:["In Agent Mesh, you can create an agent either by using the ",(0,r.jsx)(n.code,{children:"sam add agent"})," command or by creating a new plugin of type agent, ",(0,r.jsx)(n.code,{children:"sam plugin create your-agent --type agent"}),"."]}),(0,r.jsxs)(n.p,{children:["This tutorial uses the ",(0,r.jsx)(n.code,{children:"sam add agent"}),' command to create a new agent named "Weather Agent", for an example of creating a custom agent plugin, see the ',(0,r.jsx)(n.a,{href:"/solace-agent-mesh/docs/documentation/developing/create-agents",children:"Create Agents"})," tutorial."]})]}),"\n",(0,r.jsx)(n.h2,{id:"step-2-weather-service-implementation",children:"Step 2: Weather Service Implementation"}),"\n",(0,r.jsx)(n.p,{children:"First, create a service class to handle weather API interactions:"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.strong,{children:[(0,r.jsx)(n.code,{children:"src/weather_agent/services/weather_service.py"}),":"]})}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-python",children:'"""\nWeather service for interacting with external weather APIs.\n"""\n\nimport aiohttp\nfrom typing import Dict, Any, Optional, List\nfrom datetime import datetime, timezone\nfrom solace_ai_connector.common.log import log\n\n\nclass WeatherService:\n """Service for fetching weather data from external APIs."""\n \n def __init__(self, api_key: str, base_url: str = "https://api.openweathermap.org/data/2.5"):\n self.api_key = api_key\n self.base_url = base_url\n self.session: Optional[aiohttp.ClientSession] = None\n self.log_identifier = "[WeatherService]"\n \n async def _get_session(self) -> aiohttp.ClientSession:\n """Get or create an HTTP session."""\n if self.session is None or self.session.closed:\n self.session = aiohttp.ClientSession()\n return self.session\n \n async def close(self):\n """Close the HTTP session."""\n if self.session and not self.session.closed:\n await self.session.close()\n log.info(f"{self.log_identifier} HTTP session closed")\n \n async def get_current_weather(self, location: str, units: str = "metric") -> Dict[str, Any]:\n """\n Get current weather for a location.\n \n Args:\n location: City name, state code, and country code (for example, "London,UK")\n units: Temperature units (metric, imperial, kelvin)\n \n Returns:\n Dictionary containing current weather data\n """\n log.info(f"{self.log_identifier} Fetching current weather for: {location}")\n \n session = await self._get_session()\n url = f"{self.base_url}/weather"\n params = {\n "q": location,\n "appid": self.api_key,\n "units": units\n }\n \n try:\n async with session.get(url, params=params) as response:\n if response.status == 200:\n data = await response.json()\n log.info(f"{self.log_identifier} Successfully fetched weather for {location}")\n return self._format_current_weather(data)\n elif response.status == 404:\n raise ValueError(f"Location \'{location}\' not found")\n else:\n error_data = await response.json()\n raise Exception(f"Weather API error: {error_data.get(\'message\', \'Unknown error\')}")\n \n except aiohttp.ClientError as e:\n log.error(f"{self.log_identifier} Network error fetching weather: {e}")\n raise Exception(f"Network error: {str(e)}")\n \n async def get_weather_forecast(self, location: str, days: int = 5, units: str = "metric") -> Dict[str, Any]:\n """\n Get weather forecast for a location.\n \n Args:\n location: City name, state code, and country code\n days: Number of days for forecast (1-5)\n units: Temperature units\n \n Returns:\n Dictionary containing forecast data\n """\n log.info(f"{self.log_identifier} Fetching {days}-day forecast for: {location}")\n \n session = await self._get_session()\n url = f"{self.base_url}/forecast"\n params = {\n "q": location,\n "appid": self.api_key,\n "units": units,\n "cnt": min(days * 8, 40) # API returns 3-hour intervals, max 40 entries\n }\n \n try:\n async with session.get(url, params=params) as response:\n if response.status == 200:\n data = await response.json()\n log.info(f"{self.log_identifier} Successfully fetched forecast for {location}")\n return self._format_forecast_data(data, days)\n elif response.status == 404:\n raise ValueError(f"Location \'{location}\' not found")\n else:\n error_data = await response.json()\n raise Exception(f"Weather API error: {error_data.get(\'message\', \'Unknown error\')}")\n \n except aiohttp.ClientError as e:\n log.error(f"{self.log_identifier} Network error fetching forecast: {e}")\n raise Exception(f"Network error: {str(e)}")\n \n def _format_current_weather(self, data: Dict) -> Dict[str, Any]:\n """Format current weather data for consistent output."""\n return {\n "location": f"{data[\'name\']}, {data[\'sys\'][\'country\']}",\n "temperature": data[\'main\'][\'temp\'],\n "feels_like": data[\'main\'][\'feels_like\'],\n "humidity": data[\'main\'][\'humidity\'],\n "pressure": data[\'main\'][\'pressure\'],\n "description": data[\'weather\'][0][\'description\'].title(),\n "wind_speed": data.get(\'wind\', {}).get(\'speed\', 0),\n "wind_direction": data.get(\'wind\', {}).get(\'deg\', 0),\n "visibility": data.get(\'visibility\', 0) / 1000, # Convert to km\n "timestamp": datetime.fromtimestamp(data[\'dt\']).isoformat(),\n "sunrise": datetime.fromtimestamp(data[\'sys\'][\'sunrise\']).isoformat(),\n "sunset": datetime.fromtimestamp(data[\'sys\'][\'sunset\']).isoformat()\n }\n \n def _format_forecast_data(self, data: Dict, days: int) -> Dict[str, Any]:\n """Format forecast data for consistent output."""\n forecasts = []\n current_date = None\n daily_data = []\n \n for item in data[\'list\'][:days * 8]:\n forecast_date = datetime.fromtimestamp(item[\'dt\']).date()\n \n if current_date != forecast_date:\n if daily_data:\n forecasts.append(self._aggregate_daily_forecast(daily_data))\n current_date = forecast_date\n daily_data = []\n \n daily_data.append(item)\n \n # Add the last day\'s data\n if daily_data:\n forecasts.append(self._aggregate_daily_forecast(daily_data))\n \n return {\n "location": f"{data[\'city\'][\'name\']}, {data[\'city\'][\'country\']}",\n "forecasts": forecasts[:days]\n }\n \n def _aggregate_daily_forecast(self, daily_data: List[Dict]) -> Dict[str, Any]:\n """Aggregate 3-hour forecasts into daily summary."""\n if not daily_data:\n return {}\n \n # Get temperatures for min/max calculation\n temps = [item[\'main\'][\'temp\'] for item in daily_data]\n \n # Use the forecast closest to noon for general conditions\n noon_forecast = min(daily_data, key=lambda x: abs(\n datetime.fromtimestamp(x[\'dt\']).hour - 12\n ))\n \n return {\n "date": datetime.fromtimestamp(daily_data[0][\'dt\']).date().isoformat(),\n "temperature_min": min(temps),\n "temperature_max": max(temps),\n "description": noon_forecast[\'weather\'][0][\'description\'].title(),\n "humidity": noon_forecast[\'main\'][\'humidity\'],\n "wind_speed": noon_forecast.get(\'wind\', {}).get(\'speed\', 0),\n "precipitation_probability": noon_forecast.get(\'pop\', 0) * 100\n }\n'})}),"\n",(0,r.jsx)(n.h2,{id:"step-3-weather-tools-implementation",children:"Step 3: Weather Tools Implementation"}),"\n",(0,r.jsx)(n.p,{children:"Now create the tool functions:"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.strong,{children:[(0,r.jsx)(n.code,{children:"src/weather_agent/tools.py"}),":"]})}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-python",children:'"""\nWeather agent tools for fetching and processing weather data.\n"""\n\nimport json\nfrom typing import Any, Dict, Optional\nfrom datetime import datetime, timezone\nfrom google.adk.tools import ToolContext\nfrom solace_ai_connector.common.log import log\nfrom solace_agent_mesh.agent.utils.artifact_helpers import save_artifact_with_metadata\n\nasync def get_current_weather(\n location: str,\n units: str = "metric",\n save_to_file: bool = False,\n tool_context: Optional[ToolContext] = None,\n tool_config: Optional[Dict[str, Any]] = None\n) -> Dict[str, Any]:\n """\n Get current weather conditions for a specified location.\n \n Args:\n location: City name, state, and country (for example, "New York, NY, US")\n units: Temperature units - "metric" (Celsius), "imperial" (Fahrenheit), or "kelvin"\n save_to_file: Whether to save the weather report as an artifact\n \n Returns:\n Dictionary containing current weather information\n """\n log_identifier = "[GetCurrentWeather]"\n log.info(f"{log_identifier} Getting current weather for: {location}")\n \n if not tool_context:\n return {\n "status": "error",\n "message": "Tool context is required for weather operations"\n }\n \n try:\n # Get weather service from agent state\n host_component = getattr(tool_context._invocation_context, "agent", None)\n if host_component:\n host_component = getattr(host_component, "host_component", None)\n \n if not host_component:\n return {\n "status": "error",\n "message": "Could not access agent host component"\n }\n \n weather_service = host_component.get_agent_specific_state("weather_service")\n if not weather_service:\n return {\n "status": "error",\n "message": "Weather service not initialized"\n }\n \n # Fetch weather data\n weather_data = await weather_service.get_current_weather(location, units)\n \n # Create human-readable summary\n summary = _create_weather_summary(weather_data)\n \n result = {\n "status": "success",\n "location": weather_data["location"],\n "summary": summary,\n "data": weather_data\n }\n \n # Save to artifact if requested\n if save_to_file:\n artifact_result = await _save_weather_artifact(\n weather_data, f"current_weather_{location}", tool_context\n )\n result["artifact"] = artifact_result\n \n log.info(f"{log_identifier} Successfully retrieved weather for {location}")\n return result\n \n except ValueError as e:\n log.warning(f"{log_identifier} Invalid location: {e}")\n return {\n "status": "error",\n "message": f"Location error: {str(e)}"\n }\n except Exception as e:\n log.error(f"{log_identifier} Error getting weather: {e}")\n return {\n "status": "error",\n "message": f"Weather service error: {str(e)}"\n }\n\n\nasync def get_weather_forecast(\n location: str,\n days: int = 5,\n units: str = "metric",\n save_to_file: bool = False,\n tool_context: Optional[ToolContext] = None,\n tool_config: Optional[Dict[str, Any]] = None\n) -> Dict[str, Any]:\n """\n Get weather forecast for a specified location.\n \n Args:\n location: City name, state, and country\n days: Number of days for forecast (1-5)\n units: Temperature units\n save_to_file: Whether to save the forecast as an artifact\n \n Returns:\n Dictionary containing weather forecast information\n """\n log_identifier = "[GetWeatherForecast]"\n log.info(f"{log_identifier} Getting {days}-day forecast for: {location}")\n \n if not tool_context:\n return {\n "status": "error",\n "message": "Tool context is required for weather operations"\n }\n \n # Validate days parameter\n if not 1 <= days <= 5:\n return {\n "status": "error",\n "message": "Days must be between 1 and 5"\n }\n \n try:\n # Get weather service from agent state\n host_component = getattr(tool_context._invocation_context, "agent", None)\n if host_component:\n host_component = getattr(host_component, "host_component", None)\n \n if not host_component:\n return {\n "status": "error",\n "message": "Could not access agent host component"\n }\n \n weather_service = host_component.get_agent_specific_state("weather_service")\n if not weather_service:\n return {\n "status": "error",\n "message": "Weather service not initialized"\n }\n \n # Fetch forecast data\n forecast_data = await weather_service.get_weather_forecast(location, days, units)\n \n # Create human-readable summary\n summary = _create_forecast_summary(forecast_data)\n \n result = {\n "status": "success",\n "location": forecast_data["location"],\n "summary": summary,\n "data": forecast_data\n }\n \n # Save to artifact if requested\n if save_to_file:\n artifact_result = await _save_weather_artifact(\n forecast_data, f"forecast_{location}_{days}day", tool_context\n )\n result["artifact"] = artifact_result\n \n log.info(f"{log_identifier} Successfully retrieved forecast for {location}")\n return result\n \n except ValueError as e:\n log.warning(f"{log_identifier} Invalid location: {e}")\n return {\n "status": "error",\n "message": f"Location error: {str(e)}"\n }\n except Exception as e:\n log.error(f"{log_identifier} Error getting forecast: {e}")\n return {\n "status": "error",\n "message": f"Weather service error: {str(e)}"\n }\n\n\ndef _create_weather_summary(weather_data: Dict[str, Any]) -> str:\n """Create a human-readable weather summary."""\n temp_unit = "\xb0C" # Assuming metric units for summary\n \n summary = f"Current weather in {weather_data[\'location\']}:\\n"\n summary += f"\u2022 Temperature: {weather_data[\'temperature\']}{temp_unit} (feels like {weather_data[\'feels_like\']}{temp_unit})\\n"\n summary += f"\u2022 Conditions: {weather_data[\'description\']}\\n"\n summary += f"\u2022 Humidity: {weather_data[\'humidity\']}%\\n"\n summary += f"\u2022 Wind: {weather_data[\'wind_speed\']} m/s\\n"\n summary += f"\u2022 Visibility: {weather_data[\'visibility\']} km"\n \n return summary\n\n\ndef _create_forecast_summary(forecast_data: Dict[str, Any]) -> str:\n """Create a human-readable forecast summary."""\n summary = f"Weather forecast for {forecast_data[\'location\']}:\\n\\n"\n \n for forecast in forecast_data[\'forecasts\']:\n date = datetime.fromisoformat(forecast[\'date\']).strftime(\'%A, %B %d\')\n summary += f"\u2022 {date}: {forecast[\'description\']}\\n"\n summary += f" High: {forecast[\'temperature_max\']:.1f}\xb0C, Low: {forecast[\'temperature_min\']:.1f}\xb0C\\n"\n if forecast[\'precipitation_probability\'] > 0:\n summary += f" Precipitation: {forecast[\'precipitation_probability\']:.0f}% chance\\n"\n summary += "\\n"\n \n return summary.strip()\n\n\nasync def _save_weather_artifact(\n weather_data: Dict[str, Any],\n filename_base: str,\n tool_context: ToolContext\n) -> Dict[str, Any]:\n """Save weather data as an artifact."""\n try:\n # Prepare content\n content = json.dumps(weather_data, indent=2, default=str)\n timestamp = datetime.now(timezone.utc)\n filename = f"{filename_base}_{timestamp.strftime(\'%Y%m%d_%H%M%S\')}.json"\n \n # Save artifact\n artifact_service = tool_context._invocation_context.artifact_service\n result = await save_artifact_with_metadata(\n artifact_service=artifact_service,\n app_name=tool_context._invocation_context.app_name,\n user_id=tool_context._invocation_context.user_id,\n session_id=tool_context._invocation_context.session.id,\n filename=filename,\n content_bytes=content.encode(\'utf-8\'),\n mime_type="application/json",\n metadata_dict={\n "description": "Weather data report",\n "source": "Weather Agent"\n },\n timestamp=timestamp\n )\n \n return {\n "filename": filename,\n "status": result.get("status", "success")\n }\n \n except Exception as e:\n log.error(f"[WeatherArtifact] Error saving artifact: {e}")\n return {\n "status": "error",\n "message": f"Failed to save artifact: {str(e)}"\n }\n'})}),"\n",(0,r.jsx)(n.h2,{id:"step-4-lifecycle-functions",children:"Step 4: Lifecycle Functions"}),"\n",(0,r.jsx)(n.p,{children:"Create the lifecycle management:"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsxs)(n.strong,{children:[(0,r.jsx)(n.code,{children:"src/weather_agent/lifecycle.py"}),":"]})}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-python",children:'"""\nLifecycle functions for the Weather Agent.\n"""\n\nfrom typing import Any\nimport asyncio\nfrom pydantic import BaseModel, Field, SecretStr\nfrom solace_ai_connector.common.log import log\nfrom .services.weather_service import WeatherService\n\n\nclass WeatherAgentInitConfig(BaseModel):\n """\n Configuration model for Weather Agent initialization.\n """\n api_key: SecretStr = Field(description="OpenWeatherMap API key")\n base_url: str = Field(\n default="https://api.openweathermap.org/data/2.5",\n description="Weather API base URL"\n )\n startup_message: str = Field(\n default="Weather Agent is ready to provide weather information!",\n description="Message to log on startup"\n )\n\n\ndef initialize_weather_agent(host_component: Any, init_config: WeatherAgentInitConfig):\n """\n Initialize the Weather Agent with weather service.\n \n Args:\n host_component: The agent host component\n init_config: Validated initialization configuration\n """\n log_identifier = f"[{host_component.agent_name}:init]"\n log.info(f"{log_identifier} Starting Weather Agent initialization...")\n \n try:\n # Initialize weather service\n weather_service = WeatherService(\n api_key=init_config.api_key.get_secret_value(),\n base_url=init_config.base_url\n )\n \n # Store service in agent state\n host_component.set_agent_specific_state("weather_service", weather_service)\n \n # Log startup message\n log.info(f"{log_identifier} {init_config.startup_message}")\n \n # Store initialization metadata\n host_component.set_agent_specific_state("initialized_at", "2024-01-01T00:00:00Z")\n host_component.set_agent_specific_state("weather_requests_count", 0)\n \n log.info(f"{log_identifier} Weather Agent initialization completed successfully")\n \n except Exception as e:\n log.error(f"{log_identifier} Failed to initialize Weather Agent: {e}")\n raise\n\n\ndef cleanup_weather_agent(host_component: Any):\n """\n Clean up Weather Agent resources.\n \n Args:\n host_component: The agent host component\n """\n log_identifier = f"[{host_component.agent_name}:cleanup]"\n log.info(f"{log_identifier} Starting Weather Agent cleanup...")\n\n async def cleanup_async(host_component: Any):\n try:\n # Get and close weather service\n weather_service = host_component.get_agent_specific_state("weather_service")\n if weather_service:\n await weather_service.close()\n log.info(f"{log_identifier} Weather service closed successfully")\n \n # Log final statistics\n request_count = host_component.get_agent_specific_state("weather_requests_count", 0)\n log.info(f"{log_identifier} Agent processed {request_count} weather requests during its lifetime")\n \n log.info(f"{log_identifier} Weather Agent cleanup completed")\n \n except Exception as e:\n log.error(f"{log_identifier} Error during cleanup: {e}")\n \n # run cleanup in the event loop\n loop = asyncio.get_event_loop()\n loop.run_until_complete(cleanup_async(host_component))\n log.info(f"{log_identifier} Weather Agent cleanup completed successfully")\n'})}),"\n",(0,r.jsx)(n.h2,{id:"step-5-agent-configuration",children:"Step 5: Agent Configuration"}),"\n",(0,r.jsx)(n.p,{children:"Create the comprehensive YAML configuration:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-yaml",children:'# Weather Agent Configuration\nlog:\n stdout_log_level: INFO\n log_file_level: DEBUG\n log_file: weather-agent.log\n\n!include ../shared_config.yaml\n\napps:\n - name: weather-agent\n # Broker configuration\n app_module: solace_agent_mesh.agent.sac.app\n broker:\n <<: *broker_connection\n\n app_config:\n namespace: "${NAMESPACE}"\n agent_name: "WeatherAgent"\n display_name: "Weather Information Agent"\n supports_streaming: true\n \n # LLM model configuration\n model: *general_model\n \n # Agent instructions\n instruction: |\n You are a professional weather agent that provides accurate, up-to-date weather information.\n \n Your capabilities include:\n 1. Getting current weather conditions for any location worldwide\n 2. Providing detailed weather forecasts up to 5 days\n 3. Saving weather reports as files for future reference\n \n Guidelines:\n - Always specify the location clearly when providing weather information\n - Include relevant details like temperature, conditions, humidity, and wind\n - Offer to save weather reports when providing detailed information\n - Be helpful in suggesting appropriate clothing or activities based on weather\n - If a location is ambiguous, ask for clarification (city, state/province, country)\n \n When users ask about weather, use the appropriate tools to fetch real-time data.\n Present information in a clear, organized manner that\'s easy to understand.\n \n # Lifecycle functions\n agent_init_function:\n module: "src.weather_agent.lifecycle"\n name: "initialize_weather_agent"\n base_path: .\n config:\n api_key: ${OPENWEATHER_API_KEY}\n base_url: "https://api.openweathermap.org/data/2.5"\n startup_message: "Weather Agent is ready to provide weather information!"\n \n agent_cleanup_function:\n module: "src.weather_agent.lifecycle"\n base_path: .\n name: "cleanup_weather_agent"\n \n # Tools configuration\n tools:\n # Current weather tool\n - tool_type: python\n component_module: "src.weather_agent.tools"\n component_base_path: .\n function_name: "get_current_weather"\n tool_description: "Get current weather conditions for a specified location"\n \n # Weather forecast tool\n - tool_type: python\n component_module: "src.weather_agent.tools"\n component_base_path: .\n function_name: "get_weather_forecast"\n tool_description: "Get weather forecast for up to 5 days for a specified location"\n \n # Built-in artifact tools for file operations\n - tool_type: builtin-group\n group_name: "artifact_management"\n \n session_service: *default_session_service\n artifact_service: *default_artifact_service\n\n artifact_handling_mode: "reference"\n enable_embed_resolution: true\n enable_artifact_content_instruction: true\n # Agent card\n agent_card:\n description: "Professional weather agent providing current conditions, forecasts, and weather comparisons"\n defaultInputModes: ["text"]\n defaultOutputModes: ["text", "file"]\n skills:\n - id: "get_current_weather"\n name: "Get Current Weather"\n description: "Retrieve current weather conditions for any location worldwide"\n - id: "get_weather_forecast"\n name: "Get Weather Forecast"\n description: "Provide detailed weather forecasts up to 5 days ahead"\n \n agent_card_publishing:\n interval_seconds: 30\n\n agent_discovery:\n enabled: false\n\n inter_agent_communication:\n allow_list: []\n request_timeout_seconds: 30\n'})}),"\n",(0,r.jsxs)(n.p,{children:["For more details on agent cards, see the ",(0,r.jsx)(n.a,{href:"/solace-agent-mesh/docs/documentation/components/agents#agent-card",children:"Agent Card Concepts"})," documentation."]}),"\n",(0,r.jsx)(n.h2,{id:"step-6-environment-setup",children:"Step 6: Environment Setup"}),"\n",(0,r.jsx)(n.p,{children:"Before running your weather agent, you'll need to:"}),"\n",(0,r.jsxs)(n.ol,{children:["\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Get an OpenWeatherMap API key"}),":"]}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["Sign up at ",(0,r.jsx)(n.a,{href:"https://openweathermap.org/api",children:"OpenWeatherMap"})]}),"\n",(0,r.jsx)(n.li,{children:"Get your free API key"}),"\n"]}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.strong,{children:"Set environment variables"}),":"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:'export OPENWEATHER_API_KEY="your_api_key_here"\n# Other environment variables as needed\n'})}),"\n"]}),"\n"]}),"\n",(0,r.jsx)(n.h2,{id:"step-7-running-the-agent",children:"Step 7: Running the Agent"}),"\n",(0,r.jsxs)(n.p,{children:["To start the agent, it is preferred to build the plugin and then install it with your agent name. But for debugging or isolated development testing, you can run your agent from the ",(0,r.jsx)(n.code,{children:"src"})," directory directly using the Agent Mesh CLI."]}),"\n",(0,r.jsx)(n.p,{children:"Start your weather agent for development purposes run:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-bash",children:"sam run\n"})}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["To solely run the agent, use ",(0,r.jsx)(n.code,{children:"sam run configs/agents/weather_agent.yaml"})]}),"\n"]}),"\n",(0,r.jsx)(n.h2,{id:"step-8-testing-the-weather-agent",children:"Step 8: Testing the Weather Agent"}),"\n",(0,r.jsx)(n.p,{children:"You can test your weather agent with these example requests:"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Current Weather:"})}),"\n",(0,r.jsxs)(n.blockquote,{children:["\n",(0,r.jsx)(n.p,{children:'"What\'s the current weather in New York City?"'}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Weather Forecast:"})}),"\n",(0,r.jsxs)(n.blockquote,{children:["\n",(0,r.jsx)(n.p,{children:'"Can you give me a 5-day forecast for London, UK and save it to a file?"'}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.strong,{children:"Weather with File Save:"})}),"\n",(0,r.jsxs)(n.blockquote,{children:["\n",(0,r.jsx)(n.p,{children:'"Get the current weather for Tokyo, Japan and save the report"'}),"\n"]}),"\n",(0,r.jsx)(n.h2,{id:"key-features-demonstrated",children:"Key Features Demonstrated"}),"\n",(0,r.jsx)(n.h3,{id:"1-external-api-integration",children:"1. External API Integration"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Proper HTTP session management"}),"\n",(0,r.jsx)(n.li,{children:"Error handling for network issues"}),"\n",(0,r.jsx)(n.li,{children:"API response transformation"}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"2-resource-management",children:"2. Resource Management"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Lifecycle functions for initialization and cleanup"}),"\n",(0,r.jsx)(n.li,{children:"Shared service instances across tool calls"}),"\n",(0,r.jsx)(n.li,{children:"Proper resource disposal"}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"3-configuration-management",children:"3. Configuration Management"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Pydantic models for type-safe configuration"}),"\n",(0,r.jsx)(n.li,{children:"Environment variable integration"}),"\n",(0,r.jsx)(n.li,{children:"Flexible tool configuration"}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"4-error-handling",children:"4. Error Handling"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Comprehensive exception handling"}),"\n",(0,r.jsx)(n.li,{children:"User-friendly error messages"}),"\n",(0,r.jsx)(n.li,{children:"Logging for debugging"}),"\n"]}),"\n",(0,r.jsx)(n.h3,{id:"5-artifact-management",children:"5. Artifact Management"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsx)(n.li,{children:"Saving structured data as files"}),"\n",(0,r.jsx)(n.li,{children:"Metadata enrichment"}),"\n",(0,r.jsx)(n.li,{children:"File format handling"}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,o.R)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>i,x:()=>s});var a=t(6540);const r={},o=a.createContext(r);function i(e){const n=a.useContext(o);return a.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function s(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:i(e.components),a.createElement(o.Provider,{value:n},e.children)}}}]);
@@ -0,0 +1 @@
1
+ "use strict";(self.webpackChunksolace_agenitc_mesh_docs=self.webpackChunksolace_agenitc_mesh_docs||[]).push([[5525],{5822:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>d,contentTitle:()=>o,default:()=>h,frontMatter:()=>l,metadata:()=>i,toc:()=>c});const i=JSON.parse('{"id":"documentation/installing-and-configuring/configurations","title":"Configuring Agent Mesh","description":"The shared_config.yaml file is used to define configurations that can be shared across multiple agents or components in Agent Mesh. This centralized approach simplifies management of common configurations such as Solace event broker connections, language model settings, and service definitions.","source":"@site/docs/documentation/installing-and-configuring/configurations.md","sourceDirName":"documentation/installing-and-configuring","slug":"/documentation/installing-and-configuring/configurations","permalink":"/solace-agent-mesh/docs/documentation/installing-and-configuring/configurations","draft":false,"unlisted":false,"editUrl":"https://github.com/SolaceLabs/solace-agent-mesh/edit/main/docs/docs/documentation/installing-and-configuring/configurations.md","tags":[],"version":"current","sidebarPosition":330,"frontMatter":{"title":"Configuring Agent Mesh","sidebar_position":330,"toc_max_heading_level":4},"sidebar":"docSidebar","previous":{"title":"Creating and Running an Agent Mesh Project","permalink":"/solace-agent-mesh/docs/documentation/installing-and-configuring/run-project"},"next":{"title":"Configuring LLMs","permalink":"/solace-agent-mesh/docs/documentation/installing-and-configuring/large_language_models"}}');var s=n(4848),r=n(8453);const l={title:"Configuring Agent Mesh",sidebar_position:330,toc_max_heading_level:4},o=void 0,d={},c=[{value:"Understanding Shared Configuration",id:"understanding-shared-configuration",level:2},{value:"Managing Multiple Shared Configuration Files",id:"managing-multiple-shared-configuration-files",level:3},{value:"Configuration Structure",id:"configuration-structure",level:2},{value:"Event Broker Connection",id:"event-broker-connection",level:2},{value:"LLM Configuration",id:"llm-configuration",level:2},{value:"Model Configuration Parameters",id:"model-configuration-parameters",level:3},{value:"Predefined Model Types",id:"predefined-model-types",level:3},{value:"Service Configuration",id:"service-configuration",level:2},{value:"Session Service",id:"session-service",level:3},{value:"Artifact Service",id:"artifact-service",level:3},{value:"Data Tools Configuration",id:"data-tools-configuration",level:3},{value:"System Logging",id:"system-logging",level:2}];function a(e){const t={a:"a",admonition:"admonition",code:"code",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,r.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"shared_config.yaml"})," file is used to define configurations that can be shared across multiple agents or components in Agent Mesh. This centralized approach simplifies management of common configurations such as Solace event broker connections, language model settings, and service definitions."]}),"\n",(0,s.jsx)(t.h2,{id:"understanding-shared-configuration",children:"Understanding Shared Configuration"}),"\n",(0,s.jsxs)(t.p,{children:["All agents and gateways require access to a ",(0,s.jsx)(t.code,{children:"shared_config"})," object. You can provide configuration in the following ways:"]}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsx)(t.li,{children:"hard-coding configuration values directly within your agent or gateway YAML files. This method works for simple setups or quick prototyping, but it becomes unwieldy as your deployment grows."}),"\n",(0,s.jsxs)(t.li,{children:["using the ",(0,s.jsx)(t.code,{children:"!include"})," directive to reference a centralized configuration file. This approach promotes consistency and simplifies maintenance across your entire project."]}),"\n"]}),"\n",(0,s.jsxs)(t.p,{children:["When a plugin is installed, it may come with hard-coded default values. It is a best practice to remove this section and use ",(0,s.jsx)(t.code,{children:"!include"})," to point to the centralized ",(0,s.jsx)(t.code,{children:"shared_config"})," file. This ensures that all components are using the same base configuration."]}),"\n",(0,s.jsx)(t.h3,{id:"managing-multiple-shared-configuration-files",children:"Managing Multiple Shared Configuration Files"}),"\n",(0,s.jsx)(t.p,{children:"You can use multiple shared configuration files to manage different environments or setups (e.g., for different cloud providers), as follows:"}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsxs)(t.p,{children:["The filename must always begin with ",(0,s.jsx)(t.code,{children:"shared_config"}),", followed by any descriptive suffix that helps identify the configuration's purpose. Examples include ",(0,s.jsx)(t.code,{children:"shared_config_aws.yaml"})," for Amazon Web Services deployments or ",(0,s.jsx)(t.code,{children:"shared_config_production.yaml"})," for production environments. This naming convention ensures the system can locate and process these files correctly."]}),"\n"]}),"\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsxs)(t.p,{children:["You can organize configuration files into subdirectories to further improve project structure. For instance, you might place files in ",(0,s.jsx)(t.code,{children:"configs/agents/shared_config.yaml"})," or ",(0,s.jsx)(t.code,{children:"environments/dev/shared_config_dev.yaml"}),". When you use subdirectories, you must update the ",(0,s.jsx)(t.code,{children:"!include"})," path in your agent or gateway configurations to reflect the correct file location."]}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(t.p,{children:["The configuration file uses YAML anchors (",(0,s.jsx)(t.code,{children:"&anchor_name"}),") to create reusable configuration blocks, which can then be referenced in agent configuration files."]}),"\n",(0,s.jsx)(t.h2,{id:"configuration-structure",children:"Configuration Structure"}),"\n",(0,s.jsxs)(t.p,{children:["The following example shows the structure of the ",(0,s.jsx)(t.code,{children:"shared_config.yaml"})," configuration file:"]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-yaml",children:"shared_config:\n - broker_connection: &broker_connection\n dev_mode: ${SOLACE_DEV_MODE, false}\n broker_url: ${SOLACE_BROKER_URL, ws://localhost:8008}\n broker_username: ${SOLACE_BROKER_USERNAME, default}\n broker_password: ${SOLACE_BROKER_PASSWORD, default}\n broker_vpn: ${SOLACE_BROKER_VPN, default}\n temporary_queue: ${USE_TEMPORARY_QUEUES, true}\n # Ensure high enough limits if many agents are running\n # max_connection_retries: -1 # Retry forever\n\n - models:\n planning: &planning_model\n # This dictionary structure tells ADK to use the LiteLlm wrapper.\n # 'model' uses the specific model identifier your endpoint expects.\n model: ${LLM_SERVICE_PLANNING_MODEL_NAME} # Use env var for model name\n # 'api_base' tells LiteLLM where to send the request.\n api_base: ${LLM_SERVICE_ENDPOINT} # Use env var for endpoint URL\n # 'api_key' provides authentication.\n api_key: ${LLM_SERVICE_API_KEY} # Use env var for API key\n # Enable parallel tool calls for planning model\n parallel_tool_calls: true\n # Prompt Caching Strategy\n cache_strategy: \"5m\" # none, 5m, 1h\n # max_tokens: ${MAX_TOKENS, 16000} # Set a reasonable max token limit for planning\n # temperature: 0.1 # Lower temperature for more deterministic planning\n \n general: &general_model\n # This dictionary structure tells ADK to use the LiteLlm wrapper.\n # 'model' uses the specific model identifier your endpoint expects.\n model: ${LLM_SERVICE_GENERAL_MODEL_NAME} # Use env var for model name\n # 'api_base' tells LiteLLM where to send the request.\n api_base: ${LLM_SERVICE_ENDPOINT} # Use env var for endpoint URL\n # 'api_key' provides authentication.\n api_key: ${LLM_SERVICE_API_KEY} # Use env var for API key\n\n # ... (similar structure)\n\n - services:\n # Default session service configuration\n session_service: &default_session_service\n type: \"memory\"\n default_behavior: \"PERSISTENT\"\n \n # Default artifact service configuration\n artifact_service: &default_artifact_service\n type: \"filesystem\"\n base_path: \"/tmp/samv2\"\n artifact_scope: namespace\n \n # Default data tools configuration\n data_tools_config: &default_data_tools_config\n sqlite_memory_threshold_mb: 100\n max_result_preview_rows: 50\n max_result_preview_bytes: 4096\n"})}),"\n",(0,s.jsx)(t.h2,{id:"event-broker-connection",children:"Event Broker Connection"}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"broker_connection"})," section configures the connection to the Solace event broker. The connection parameters are described in the following table:"]}),"\n",(0,s.jsxs)(t.table,{children:[(0,s.jsx)(t.thead,{children:(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.th,{style:{textAlign:"left"},children:"Parameter"}),(0,s.jsx)(t.th,{style:{textAlign:"left"},children:"Environment Variable"}),(0,s.jsx)(t.th,{style:{textAlign:"left"},children:"Description"}),(0,s.jsx)(t.th,{style:{textAlign:"left"},children:"Default"})]})}),(0,s.jsxs)(t.tbody,{children:[(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"dev_mode"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"SOLACE_DEV_MODE"})}),(0,s.jsxs)(t.td,{style:{textAlign:"left"},children:["When set to ",(0,s.jsx)(t.code,{children:"true"}),", uses an in-memory broker for testing."]}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"false"})})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"broker_url"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"SOLACE_BROKER_URL"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:"The URL of the Solace event broker."}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"ws://localhost:8008"})})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"broker_username"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"SOLACE_BROKER_USERNAME"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:"The username for authenticating with the event broker."}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"default"})})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"broker_password"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"SOLACE_BROKER_PASSWORD"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:"The password for authenticating with the event broker."}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"default"})})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"broker_vpn"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"SOLACE_BROKER_VPN"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:"The Message VPN to connect to on the event broker."}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"default"})})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"temporary_queue"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"USE_TEMPORARY_QUEUES"})}),(0,s.jsxs)(t.td,{style:{textAlign:"left"},children:["Whether to use temporary queues for communication. If ",(0,s.jsx)(t.code,{children:"false"}),", a durable queue will be created."]}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"true"})})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"max_connection_retries"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"MAX_CONNECTION_RETRIES"})}),(0,s.jsxs)(t.td,{style:{textAlign:"left"},children:["The maximum number of times to retry connecting to the event broker if the connection fails. A value of ",(0,s.jsx)(t.code,{children:"-1"})," means retry forever."]}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"-1"})})]})]})]}),"\n",(0,s.jsx)(t.admonition,{type:"tip",children:(0,s.jsxs)(t.p,{children:["If you need to configure multiple brokers, you can do so by adding additional entries under ",(0,s.jsx)(t.code,{children:"shared_config"})," with a unique name (For example, ",(0,s.jsx)(t.code,{children:"broker_connection_eu: &broker_connection_eu"})," or ",(0,s.jsx)(t.code,{children:"broker_connection_us: &broker_connection_us"}),"). Reference these configurations in your agent files using the appropriate anchor, such as ",(0,s.jsx)(t.code,{children:"<<: *broker_connection_eu"}),"."]})}),"\n",(0,s.jsxs)(t.admonition,{type:"info",children:[(0,s.jsxs)(t.p,{children:["Setting the ",(0,s.jsx)(t.code,{children:"temporary_queue"})," parameter to ",(0,s.jsx)(t.code,{children:"true"})," (default) will use ",(0,s.jsx)(t.a,{href:"https://docs.solace.com/Messaging/Guaranteed-Msg/Endpoints.htm#temporary-endpoints",children:"temporary endpoints"})," for A2A communication. Temporary queues are automatically created and deleted by the broker, which simplifies management and reduces the need for manual cleanup. However, it does not allow for multiple client connections to the same queue, which may be a limitation in some scenarios where you're running multiple instances of the same agent or a new instance needs to be started while an old instance is still running."]}),(0,s.jsxs)(t.p,{children:["If you set ",(0,s.jsx)(t.code,{children:"temporary_queue"})," to ",(0,s.jsx)(t.code,{children:"false"}),", the system will create a durable queue for the client. Durable queues persist beyond the lifetime of the client connection, allowing multiple clients to connect to the same queue and ensuring that messages are not lost if the client disconnects. However, this requires manual management of the queues, including cleanup of unused queues."]}),(0,s.jsxs)(t.p,{children:["Check the ",(0,s.jsx)(t.a,{href:"/solace-agent-mesh/docs/documentation/deploying/deployment-options#setting-up-queue-templates",children:"Setting up Queue Templates"})," section for guidance on configuring queue templates to manage message TTL."]})]}),"\n",(0,s.jsx)(t.h2,{id:"llm-configuration",children:"LLM Configuration"}),"\n",(0,s.jsxs)(t.p,{children:["The models section configures the various Large Language Models and other generative models that power your agents' intelligence. This configuration leverages the ",(0,s.jsx)(t.a,{href:"https://litellm.ai/",children:"LiteLLM"})," library, which provides a standardized interface for interacting with ",(0,s.jsx)(t.a,{href:"https://docs.litellm.ai/docs/providers",children:"different model providers"}),", simplifying the process of switching between or combining multiple AI services."]}),"\n",(0,s.jsx)(t.h3,{id:"model-configuration-parameters",children:"Model Configuration Parameters"}),"\n",(0,s.jsxs)(t.p,{children:["Each model configuration requires specific parameters that tell the system how to communicate with the model provider. The model parameter specifies the exact model identifier in the format expected by your provider, such as ",(0,s.jsx)(t.code,{children:"openai/gpt-4"})," or ",(0,s.jsx)(t.code,{children:"anthropic/claude-3-opus-20240229"}),". The API base URL points to your provider's endpoint, but some providers use default endpoints that don't require explicit specification."]}),"\n",(0,s.jsx)(t.p,{children:"Authentication typically requires an API key, but some providers use alternative authentication mechanisms. Additional parameters control model behavior, such as enabling parallel tool calls for models that support this feature, setting maximum token limits to control response length and costs, and adjusting temperature values to influence response creativity versus determinism."}),"\n",(0,s.jsxs)(t.table,{children:[(0,s.jsx)(t.thead,{children:(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.th,{style:{textAlign:"left"},children:"Parameter"}),(0,s.jsx)(t.th,{style:{textAlign:"left"},children:"Environment Variable"}),(0,s.jsx)(t.th,{style:{textAlign:"left"},children:"Description"})]})}),(0,s.jsxs)(t.tbody,{children:[(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"model"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"LLM_SERVICE_<MODEL_NAME>_MODEL_NAME"})}),(0,s.jsxs)(t.td,{style:{textAlign:"left"},children:["The specific model identifier that the endpoint expects in the format of ",(0,s.jsx)(t.code,{children:"provider/model"})," (e.g., ",(0,s.jsx)(t.code,{children:"openai/gpt-4"}),", ",(0,s.jsx)(t.code,{children:"anthropic/claude-3-opus-20240229"}),")."]})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"api_base"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"LLM_SERVICE_ENDPOINT"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:"The base URL of the LLM provider's API endpoint."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"api_key"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"LLM_SERVICE_API_KEY"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:"The API key for authenticating with the service."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"parallel_tool_calls"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"}}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:"Enable parallel tool calls for the model."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"cache_strategy"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"}}),(0,s.jsxs)(t.td,{style:{textAlign:"left"},children:["Set the prompt caching strategy (one of: ",(0,s.jsx)(t.code,{children:"none"}),", ",(0,s.jsx)(t.code,{children:"5m"}),", ",(0,s.jsx)(t.code,{children:"1h"}),"). For more details check ",(0,s.jsx)(t.a,{href:"/solace-agent-mesh/docs/documentation/installing-and-configuring/large_language_models#prompt-caching",children:"LLM Configuration"})," page."]})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"max_tokens"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"MAX_TOKENS"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:"Set a reasonable max token limit for the model."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"temperature"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"TEMPERATURE"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:"Lower temperature for more deterministic planning."})]})]})]}),"\n",(0,s.jsx)(t.p,{children:"For Google's Gemini models, you can use a simplified configuration approach that references the model directly:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-yaml",children:"model: gemini-2.5-pro\n"})}),"\n",(0,s.jsxs)(t.p,{children:["For detailed information about configuring Gemini models and setting up the required environment variables, see the ",(0,s.jsx)(t.a,{href:"https://google.github.io/adk-docs/agents/models/#using-google-gemini-models",children:"Gemini model documentation"}),"."]}),"\n",(0,s.jsx)(t.h3,{id:"predefined-model-types",children:"Predefined Model Types"}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"shared_config.yaml"})," configuration file defines predefined model types that serve as aliases for specific use cases. These aliases allow you to reference models by their intended purpose rather than their technical specifications, making your agent configurations more readable and maintainable. The model types are as follows:"]}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.code,{children:"planning"}),": Used by agents for planning and decision-making. It's configured for deterministic outputs (",(0,s.jsx)(t.code,{children:"temperature: 0.1"}),") and can use tools in parallel."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.code,{children:"general"}),": A general-purpose model for various tasks."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.code,{children:"image_gen"}),": A model for generating images."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.code,{children:"image_describe"}),": A model for describing the content of images."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.code,{children:"audio_transcription"}),": A model for transcribing audio files."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.code,{children:"report_gen"}),": A model specialized for generating reports."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.code,{children:"multimodal"}),": A simple string reference to a multimodal model (e.g., ",(0,s.jsx)(t.code,{children:'"gemini-1.5-flash-latest"'}),")."]}),"\n"]}),"\n",(0,s.jsxs)(t.p,{children:["You can define any number of models in this section and reference them in your agent configurations. The system uses only the ",(0,s.jsx)(t.code,{children:"planning"})," and ",(0,s.jsx)(t.code,{children:"general"})," models by default; you don't need to configure the specialized models unless your agents specifically require those capabilities."]}),"\n",(0,s.jsxs)(t.p,{children:["For information about configuring different LLM providers and SSL/TLS security settings, see ",(0,s.jsx)(t.a,{href:"/solace-agent-mesh/docs/documentation/installing-and-configuring/large_language_models",children:"Configuring LLMs"}),"."]}),"\n",(0,s.jsx)(t.h2,{id:"service-configuration",children:"Service Configuration"}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"services"})," section in ",(0,s.jsx)(t.code,{children:"shared_config.yaml"})," is used to configure various services that are available to agents. These services handle concerns such as session persistence, artifact storage, and data processing optimization."]}),"\n",(0,s.jsx)(t.h3,{id:"session-service",children:"Session Service"}),"\n",(0,s.jsx)(t.p,{children:"The session service manages conversation history and context persistence across agent interactions. This service determines whether agents remember previous conversations and how long that memory persists."}),"\n",(0,s.jsxs)(t.table,{children:[(0,s.jsx)(t.thead,{children:(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.th,{style:{textAlign:"left"},children:"Parameter"}),(0,s.jsx)(t.th,{style:{textAlign:"left"},children:"Options"}),(0,s.jsx)(t.th,{style:{textAlign:"left"},children:"Description"}),(0,s.jsx)(t.th,{style:{textAlign:"left"},children:"Default"})]})}),(0,s.jsxs)(t.tbody,{children:[(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"type"})}),(0,s.jsxs)(t.td,{style:{textAlign:"left"},children:[(0,s.jsx)(t.code,{children:"memory"}),", ",(0,s.jsx)(t.code,{children:"sql"}),", ",(0,s.jsx)(t.code,{children:"vertex_rag"})]}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:"Configuration for ADK Session Service"}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"memory"})})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"default_behavior"})}),(0,s.jsxs)(t.td,{style:{textAlign:"left"},children:[(0,s.jsx)(t.code,{children:"PERSISTENT"}),", ",(0,s.jsx)(t.code,{children:"RUN_BASED"})]}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:"The default behavior of keeping the session history"}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"PERSISTENT"})})]})]})]}),"\n",(0,s.jsx)(t.admonition,{type:"tip",children:(0,s.jsxs)(t.p,{children:["Although the default session service type is ",(0,s.jsx)(t.code,{children:"memory"}),", both Orchestrator Agent and Web UI gateway use ",(0,s.jsx)(t.code,{children:"sql"})," as their session service to allow for persistent sessions."]})}),"\n",(0,s.jsx)(t.h3,{id:"artifact-service",children:"Artifact Service"}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"artifact_service"})," is responsible for managing artifacts, which are files or data generated by agents, such as generated documents, processed data files, and intermediate results."]}),"\n",(0,s.jsxs)(t.table,{children:[(0,s.jsx)(t.thead,{children:(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.th,{style:{textAlign:"left"},children:"Parameter"}),(0,s.jsx)(t.th,{style:{textAlign:"left"},children:"Options"}),(0,s.jsx)(t.th,{style:{textAlign:"left"},children:"Description"}),(0,s.jsx)(t.th,{style:{textAlign:"left"},children:"Default"})]})}),(0,s.jsxs)(t.tbody,{children:[(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"type"})}),(0,s.jsxs)(t.td,{style:{textAlign:"left"},children:[(0,s.jsx)(t.code,{children:"memory"}),", ",(0,s.jsx)(t.code,{children:"gcs"}),", ",(0,s.jsx)(t.code,{children:"filesystem"})]}),(0,s.jsxs)(t.td,{style:{textAlign:"left"},children:["Service type for artifact storage. Use ",(0,s.jsx)(t.code,{children:"memory"})," for in-memory, ",(0,s.jsx)(t.code,{children:"gcs"})," for Google Cloud Storage, or ",(0,s.jsx)(t.code,{children:"filesystem"})," for local file storage."]}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"memory"})})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"base_path"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:"local path"}),(0,s.jsxs)(t.td,{style:{textAlign:"left"},children:["Base directory path for storing artifacts. Required only if ",(0,s.jsx)(t.code,{children:"type"})," is ",(0,s.jsx)(t.code,{children:"filesystem"}),"."]}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:"(none)"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"bucket_name"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:"bucket name"}),(0,s.jsxs)(t.td,{style:{textAlign:"left"},children:["Google Cloud Storage bucket name. Required only if ",(0,s.jsx)(t.code,{children:"type"})," is ",(0,s.jsx)(t.code,{children:"gcs"}),"."]}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:"(none)"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"artifact_scope"})}),(0,s.jsxs)(t.td,{style:{textAlign:"left"},children:[(0,s.jsx)(t.code,{children:"namespace"}),", ",(0,s.jsx)(t.code,{children:"app"})]}),(0,s.jsxs)(t.td,{style:{textAlign:"left"},children:["Scope for artifact sharing. ",(0,s.jsx)(t.code,{children:"namespace"}),": shared by all components in the namespace. ",(0,s.jsx)(t.code,{children:"app"}),": isolated by agent/gateway name. Must be consistent for all components in the same process."]}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"namespace"})})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"artifact_scope_value"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:"custom scope id"}),(0,s.jsxs)(t.td,{style:{textAlign:"left"},children:["Custom identifier for artifact scope. Required if ",(0,s.jsx)(t.code,{children:"artifact_scope"})," is set to a custom value."]}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:"(none)"})]})]})]}),"\n",(0,s.jsx)(t.h3,{id:"data-tools-configuration",children:"Data Tools Configuration"}),"\n",(0,s.jsx)(t.p,{children:"The data tools configuration optimizes how agents handle data analysis and processing tasks. These settings balance performance, memory usage, and user experience when agents work with databases and large datasets."}),"\n",(0,s.jsx)(t.p,{children:"The SQLite memory threshold determines when the system switches from disk-based to memory-based database operations. Lower thresholds favor memory usage for better performance although consume more system RAM. Higher thresholds reduce memory pressure although may slow database operations."}),"\n",(0,s.jsx)(t.p,{children:"Result preview settings control how much data agents display when showing query results or data samples. These limits prevent overwhelming users with massive datasets while ensuring they see enough information to understand the results."}),"\n",(0,s.jsxs)(t.table,{children:[(0,s.jsx)(t.thead,{children:(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.th,{style:{textAlign:"left"},children:"Parameter"}),(0,s.jsx)(t.th,{style:{textAlign:"left"},children:"Type"}),(0,s.jsx)(t.th,{style:{textAlign:"left"},children:"Description"}),(0,s.jsx)(t.th,{style:{textAlign:"left"},children:"Default"})]})}),(0,s.jsxs)(t.tbody,{children:[(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"sqlite_memory_threshold_mb"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"integer"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:"The memory threshold in megabytes for using an in-memory SQLite database."}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"100"})})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"max_result_preview_rows"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"integer"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:"The maximum number of rows to show in a result preview."}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"50"})})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"max_result_preview_bytes"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"integer"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:"The maximum number of bytes to show in a result preview."}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"4096"})})]})]})]}),"\n",(0,s.jsx)(t.h2,{id:"system-logging",children:"System Logging"}),"\n",(0,s.jsx)(t.p,{children:"System logging configuration controls how Agent Mesh records operational information, errors, and debugging details. Proper logging configuration helps with troubleshooting, monitoring, and maintaining your agent deployments."}),"\n",(0,s.jsxs)(t.p,{children:["For information about configuring log rotation, verbosity levels, and log formatting options, see ",(0,s.jsx)(t.a,{href:"/solace-agent-mesh/docs/documentation/deploying/debugging#system-logs",children:"System Logs"}),"."]})]})}function h(e={}){const{wrapper:t}={...(0,r.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(a,{...e})}):a(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>l,x:()=>o});var i=n(6540);const s={},r=i.createContext(s);function l(e){const t=i.useContext(r);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:l(e.components),i.createElement(r.Provider,{value:t},e.children)}}}]);
@@ -0,0 +1 @@
1
+ "use strict";(self.webpackChunksolace_agenitc_mesh_docs=self.webpackChunksolace_agenitc_mesh_docs||[]).push([[6684],{2005:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>i,default:()=>h,frontMatter:()=>r,metadata:()=>s,toc:()=>l});const s=JSON.parse('{"id":"documentation/components/orchestrator","title":"Orchestrator","description":"The A2A (Agent-to-Agent) protocol is the communication backbone of Agent Mesh that enables distributed agent coordination and workflow management. Unlike traditional centralized orchestration, the A2A protocol enables agents to discover each other, delegate tasks, and collaborate directly through standardized message patterns.","source":"@site/docs/documentation/components/orchestrator.md","sourceDirName":"documentation/components","slug":"/documentation/components/orchestrator","permalink":"/solace-agent-mesh/docs/documentation/components/orchestrator","draft":false,"unlisted":false,"editUrl":"https://github.com/SolaceLabs/solace-agent-mesh/edit/main/docs/docs/documentation/components/orchestrator.md","tags":[],"version":"current","sidebarPosition":240,"frontMatter":{"title":"Orchestrator","sidebar_position":240},"sidebar":"docSidebar","previous":{"title":"Agents","permalink":"/solace-agent-mesh/docs/documentation/components/agents"},"next":{"title":"Proxies","permalink":"/solace-agent-mesh/docs/documentation/components/proxies"}}');var o=t(4848),a=t(8453);const r={title:"Orchestrator",sidebar_position:240},i="Orchestrator Agent",c={},l=[{value:"Key Functions",id:"key-functions",level:2}];function d(e){const n={admonition:"admonition",h1:"h1",h2:"h2",header:"header",li:"li",ol:"ol",p:"p",strong:"strong",ul:"ul",...(0,a.R)(),...e.components};return(0,o.jsxs)(o.Fragment,{children:[(0,o.jsx)(n.header,{children:(0,o.jsx)(n.h1,{id:"orchestrator-agent",children:"Orchestrator Agent"})}),"\n",(0,o.jsx)(n.p,{children:"The A2A (Agent-to-Agent) protocol is the communication backbone of Agent Mesh that enables distributed agent coordination and workflow management. Unlike traditional centralized orchestration, the A2A protocol enables agents to discover each other, delegate tasks, and collaborate directly through standardized message patterns."}),"\n",(0,o.jsxs)(n.p,{children:["The advantages of centralized orchestration such as task breakdown and management, centralized point of communication and session management are still achieved in Agent Mesh through a specialized agent called the ",(0,o.jsx)(n.strong,{children:"OrchestratorAgent"})," that acts as the central coordinator for complex workflows."]}),"\n",(0,o.jsx)(n.admonition,{title:"In one sentence",type:"tip",children:(0,o.jsx)(n.p,{children:"The OrchestratorAgent allows for a centralized workflow management in Agent Mesh by coordinating tasks and communication between agents."})}),"\n",(0,o.jsx)(n.p,{children:"The system is not limited to a single orchestrator agent, and multiple orchestrator agents can be deployed to handle different workflows or domains. This allows for flexibility and scalability in managing complex tasks."}),"\n",(0,o.jsx)(n.h2,{id:"key-functions",children:"Key Functions"}),"\n",(0,o.jsx)(n.p,{children:"The orchestrator agent provides the following key functions:"}),"\n",(0,o.jsxs)(n.ol,{children:["\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:[(0,o.jsx)(n.strong,{children:"Request Analysis and Action Planning"}),":"]}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:"Receives high-level goals or requests"}),"\n",(0,o.jsx)(n.li,{children:"Analyzes them in the context of available actions registered by agents in the system"}),"\n",(0,o.jsx)(n.li,{children:"Uses state-of-the-art generative AI techniques to plan a sequence of actions to fulfill the request"}),"\n"]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:[(0,o.jsx)(n.strong,{children:"Task Creation and Distribution"}),":"]}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:"Creates tasks based on the action plan"}),"\n",(0,o.jsx)(n.li,{children:"Distributes tasks to appropriate agents"}),"\n",(0,o.jsx)(n.li,{children:"Enables efficient parallel processing and optimal resource utilization"}),"\n"]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:[(0,o.jsx)(n.strong,{children:"Workflow Management"}),":"]}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:"Tracks outstanding tasks"}),"\n",(0,o.jsx)(n.li,{children:"Aggregates responses from various agents"}),"\n",(0,o.jsx)(n.li,{children:"Ensures all parts of a complex request are processed and combined coherently"}),"\n"]}),"\n"]}),"\n",(0,o.jsxs)(n.li,{children:["\n",(0,o.jsxs)(n.p,{children:[(0,o.jsx)(n.strong,{children:"Response Formatting"}),":"]}),"\n",(0,o.jsxs)(n.ul,{children:["\n",(0,o.jsx)(n.li,{children:"Formats aggregated responses suitable for the gateway"}),"\n",(0,o.jsx)(n.li,{children:"Ensures the final output meets the requirements of the specific use case or interface"}),"\n"]}),"\n"]}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,a.R)(),...e.components};return n?(0,o.jsx)(n,{...e,children:(0,o.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>r,x:()=>i});var s=t(6540);const o={},a=s.createContext(o);function r(e){const n=s.useContext(a);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function i(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:r(e.components),s.createElement(a.Provider,{value:n},e.children)}}}]);
@@ -0,0 +1 @@
1
+ "use strict";(self.webpackChunksolace_agenitc_mesh_docs=self.webpackChunksolace_agenitc_mesh_docs||[]).push([[8907],{3780:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>o,default:()=>d,frontMatter:()=>a,metadata:()=>s,toc:()=>c});const s=JSON.parse('{"id":"documentation/components/proxies","title":"Proxies","description":"Proxies act as protocol bridges that connect Agent Mesh to external A2A agents. By translating between A2A over Solace event mesh and A2A over HTTPS protocols, proxies enable agents within the mesh to delegate tasks to external agents and include them in collaborative workflows.","source":"@site/docs/documentation/components/proxies.md","sourceDirName":"documentation/components","slug":"/documentation/components/proxies","permalink":"/solace-agent-mesh/docs/documentation/components/proxies","draft":false,"unlisted":false,"editUrl":"https://github.com/SolaceLabs/solace-agent-mesh/edit/main/docs/docs/documentation/components/proxies.md","tags":[],"version":"current","sidebarPosition":250,"frontMatter":{"title":"Proxies","sidebar_position":250},"sidebar":"docSidebar","previous":{"title":"Orchestrator","permalink":"/solace-agent-mesh/docs/documentation/components/orchestrator"},"next":{"title":"Gateways","permalink":"/solace-agent-mesh/docs/documentation/components/gateways"}}');var i=t(4848),r=t(8453);const a={title:"Proxies",sidebar_position:250},o="Proxies",l={},c=[{value:"Key Functions",id:"key-functions",level:2},{value:"When to Use a Proxy",id:"when-to-use-a-proxy",level:2},{value:"Proxy vs. Native Agent",id:"proxy-vs-native-agent",level:3},{value:"Architecture Overview",id:"architecture-overview",level:2},{value:"Configuration",id:"configuration",level:2},{value:"Basic Configuration",id:"basic-configuration",level:3},{value:"Configuration Parameters",id:"configuration-parameters",level:3},{value:"Authentication Types",id:"authentication-types",level:2},{value:"Static Bearer Token",id:"static-bearer-token",level:3},{value:"Static API Key",id:"static-api-key",level:3},{value:"OAuth 2.0 Client Credentials",id:"oauth-20-client-credentials",level:3},{value:"Artifact Handling",id:"artifact-handling",level:2},{value:"Request Flow: Agent Mesh to External Agent",id:"request-flow-agent-mesh-to-external-agent",level:3},{value:"Response Flow: External Agent to Agent Mesh",id:"response-flow-external-agent-to-agent-mesh",level:3},{value:"Artifact Metadata",id:"artifact-metadata",level:3},{value:"Discovery and Health",id:"discovery-and-health",level:2},{value:"Initial Discovery",id:"initial-discovery",level:3},{value:"Periodic Refresh",id:"periodic-refresh",level:3},{value:"Agent Card Transformation",id:"agent-card-transformation",level:3},{value:"Task Lifecycle Management",id:"task-lifecycle-management",level:2},{value:"Task Initiation",id:"task-initiation",level:3},{value:"Task Cancellation",id:"task-cancellation",level:3},{value:"Task Completion",id:"task-completion",level:3},{value:"Error Handling and Retry Logic",id:"error-handling-and-retry-logic",level:2},{value:"OAuth 2.0 Automatic Retry",id:"oauth-20-automatic-retry",level:3},{value:"Connection Errors",id:"connection-errors",level:3},{value:"Error Responses",id:"error-responses",level:3},{value:"Creating a Proxy",id:"creating-a-proxy",level:2},{value:"Creating the Configuration File",id:"creating-the-configuration-file",level:3},{value:"Running the Proxy",id:"running-the-proxy",level:3},{value:"Multiple Proxy Configurations",id:"multiple-proxy-configurations",level:3},{value:"Advanced Configuration",id:"advanced-configuration",level:2},{value:"Per-Agent Timeout Override",id:"per-agent-timeout-override",level:3},{value:"Custom Artifact Service Scope",id:"custom-artifact-service-scope",level:3},{value:"Multiple Proxies",id:"multiple-proxies",level:3},{value:"Troubleshooting",id:"troubleshooting",level:2},{value:"Agent Not Discoverable",id:"agent-not-discoverable",level:3},{value:"Authentication Failures",id:"authentication-failures",level:3},{value:"Timeout Errors",id:"timeout-errors",level:3},{value:"Artifact Issues",id:"artifact-issues",level:3}];function h(e){const n={admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",li:"li",mermaid:"mermaid",ol:"ol",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,r.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.header,{children:(0,i.jsx)(n.h1,{id:"proxies",children:"Proxies"})}),"\n",(0,i.jsx)(n.p,{children:"Proxies act as protocol bridges that connect Agent Mesh to external A2A agents. By translating between A2A over Solace event mesh and A2A over HTTPS protocols, proxies enable agents within the mesh to delegate tasks to external agents and include them in collaborative workflows."}),"\n",(0,i.jsx)(n.p,{children:"A single proxy instance can manage multiple external agents, each with its own URL, authentication configuration, and timeout settings."}),"\n",(0,i.jsx)(n.admonition,{title:"In one sentence",type:"tip",children:(0,i.jsx)(n.p,{children:"Proxies are protocol bridges that connect multiple external A2A-over-HTTPS agents to the Solace event mesh, enabling hybrid agent architectures."})}),"\n",(0,i.jsx)(n.h2,{id:"key-functions",children:"Key Functions"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Protocol Translation"}),": Proxies translate between A2A over HTTPS and A2A over Solace event mesh, enabling external agents to communicate with agents on the mesh without modification."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Authentication Management"}),": Proxies handle authentication to downstream agents, supporting multiple authentication schemes including static bearer tokens, API keys, and OAuth 2.0 client credentials flow with automatic token refresh."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Agent Discovery"}),": Proxies fetch agent cards from external agents and publish them to the mesh discovery topic, making external agents discoverable to other agents in the system."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Artifact Handling"}),": Proxies manage artifact flow between the mesh and external agents, resolving artifact URIs to byte content before forwarding requests and saving returned artifacts to the mesh's artifact service."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Task Lifecycle Management"}),": Proxies track active tasks, handle cancellation requests, and ensure proper cleanup when tasks complete or fail."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Automatic Retry Logic"}),": For OAuth 2.0 authenticated agents, proxies automatically detect authentication failures (401 responses), refresh tokens, and retry requests without manual intervention."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"when-to-use-a-proxy",children:"When to Use a Proxy"}),"\n",(0,i.jsx)(n.p,{children:"Proxies are the right choice when you need:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Integration with Third-Party Agents"}),": Connect to external A2A agents provided by vendors or partners that run on their own infrastructure."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Hybrid Cloud Architectures"}),": Bridge agents running in different cloud environments or on-premises systems with your Solace mesh."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Legacy System Integration"}),": Connect existing A2A agents that cannot be modified to use Solace messaging directly."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Gradual Migration"}),": Incrementally migrate agents to the Solace mesh while maintaining compatibility with external systems."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Service Isolation"}),": Keep certain agents isolated on separate infrastructure while still enabling them to participate in collaborative workflows."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"proxy-vs-native-agent",children:"Proxy vs. Native Agent"}),"\n",(0,i.jsxs)(n.table,{children:[(0,i.jsx)(n.thead,{children:(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.th,{children:"Aspect"}),(0,i.jsx)(n.th,{children:"Proxy"}),(0,i.jsx)(n.th,{children:"Native Agent"})]})}),(0,i.jsxs)(n.tbody,{children:[(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:(0,i.jsx)(n.strong,{children:"Communication"})}),(0,i.jsx)(n.td,{children:"A2A over HTTPS to external agent"}),(0,i.jsx)(n.td,{children:"A2A over Solace event mesh directly"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:(0,i.jsx)(n.strong,{children:"Deployment"})}),(0,i.jsx)(n.td,{children:"External agent runs separately"}),(0,i.jsx)(n.td,{children:"Runs within Agent Mesh"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:(0,i.jsx)(n.strong,{children:"Authentication"})}),(0,i.jsx)(n.td,{children:"Proxy handles auth to external agent"}),(0,i.jsx)(n.td,{children:"Mesh-level authentication"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:(0,i.jsx)(n.strong,{children:"Latency"})}),(0,i.jsx)(n.td,{children:"Additional HTTP hop"}),(0,i.jsx)(n.td,{children:"Direct mesh communication"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:(0,i.jsx)(n.strong,{children:"Task Initiation"})}),(0,i.jsx)(n.td,{children:"Can only receive tasks from mesh agents"}),(0,i.jsx)(n.td,{children:"Can initiate tasks to any agent"})]}),(0,i.jsxs)(n.tr,{children:[(0,i.jsx)(n.td,{children:(0,i.jsx)(n.strong,{children:"Use Case"})}),(0,i.jsx)(n.td,{children:"External/third-party agents"}),(0,i.jsx)(n.td,{children:"Agents you control"})]})]})]}),"\n",(0,i.jsx)(n.h2,{id:"architecture-overview",children:"Architecture Overview"}),"\n",(0,i.jsx)(n.p,{children:"The proxy sits between the Solace event mesh and external A2A agents, performing bidirectional protocol translation:"}),"\n",(0,i.jsx)(n.mermaid,{value:"graph LR\n A[Agent Mesh<br/>A2A over Solace Event Mesh] <--\x3e|Solace Topics| B[Proxy Component]\n B <--\x3e|HTTPS| C[External Agent 1<br/>A2A over HTTPS]\n B <--\x3e|HTTPS| D[External Agent 2<br/>A2A over HTTPS]\n B <--\x3e|HTTPS| E[External Agent N<br/>A2A over HTTPS]\n \n style B fill:none,stroke:#00C895,stroke-width:2px\n style A fill:none,stroke:#333,stroke-width:2px\n style C fill:none,stroke:#333,stroke-width:2px\n style D fill:none,stroke:#333,stroke-width:2px\n style E fill:none,stroke:#333,stroke-width:2px"}),"\n",(0,i.jsx)(n.p,{children:"The proxy performs these operations:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Request Flow"}),": Receives A2A requests from Agent Mesh, resolves artifact URIs to byte content, forwards HTTPS requests to external agents, and streams responses back to Agent Mesh."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Response Flow"}),": Receives responses from external agents, saves artifacts to Agent Mesh's artifact service, replaces byte content with artifact URIs, and publishes responses to Agent Mesh topics."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Discovery Flow"}),": Periodically fetches agent cards from external agents, updates the local registry, and publishes cards to the Agent Mesh discovery topic."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"configuration",children:"Configuration"}),"\n",(0,i.jsx)(n.p,{children:"Proxies are configured through YAML files that specify the namespace, downstream agents, authentication, and service settings."}),"\n",(0,i.jsx)(n.h3,{id:"basic-configuration",children:"Basic Configuration"}),"\n",(0,i.jsxs)(n.p,{children:["A single proxy can manage multiple external agents. Each agent in the ",(0,i.jsx)(n.code,{children:"proxied_agents"})," list can have its own URL, authentication, and timeout configuration:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-yaml",children:'app:\n class_name: solace_agent_mesh.agent.proxies.a2a.app.A2AProxyApp\n name: my-a2a-proxy\n app_config:\n namespace: "myorg/production"\n proxied_agents:\n - name: "external-data-agent"\n url: "https://api.example.com/agent"\n request_timeout_seconds: 120\n - name: "external-analytics-agent"\n url: "https://analytics.example.com/agent"\n request_timeout_seconds: 180\n - name: "external-reporting-agent"\n url: "https://reports.example.com/agent"\n artifact_service:\n type: "filesystem"\n base_path: "/tmp/proxy-artifacts"\n discovery_interval_seconds: 60\n default_request_timeout_seconds: 300\n\nbroker:\n # Broker configuration inherited from environment or specified here\n'})}),"\n",(0,i.jsx)(n.h3,{id:"configuration-parameters",children:"Configuration Parameters"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"namespace"}),': The topic prefix for A2A communication (for example, "myorg/production").']}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"proxied_agents"}),": A list of external agents to proxy. Each agent can have its own URL, authentication, and timeout settings (see Authentication Types below)."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"artifact_service"}),": Configuration for storing artifacts. This is shared across all proxied agents. This is configured in the same manner as agents and gateways"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"discovery_interval_seconds"}),": How often to refresh agent cards from all external agents (default: 60)."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"default_request_timeout_seconds"}),": Default timeout for requests to external agents. Individual agents can override this (default: 300)."]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"authentication-types",children:"Authentication Types"}),"\n",(0,i.jsxs)(n.p,{children:["The proxy supports three authentication schemes for connecting to downstream agents. Each agent in the ",(0,i.jsx)(n.code,{children:"proxied_agents"})," list can use a different authentication type, allowing you to integrate agents with varying security requirements in a single proxy instance."]}),"\n",(0,i.jsx)(n.h3,{id:"static-bearer-token",children:"Static Bearer Token"}),"\n",(0,i.jsx)(n.p,{children:"Use static bearer tokens for agents that require a fixed authentication token."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-yaml",children:'proxied_agents:\n - name: "secure-agent"\n url: "https://api.example.com/agent"\n authentication:\n type: "static_bearer"\n token: "${AGENT_BEARER_TOKEN}" # Use environment variable\n'})}),"\n",(0,i.jsx)(n.h3,{id:"static-api-key",children:"Static API Key"}),"\n",(0,i.jsx)(n.p,{children:"Use static API keys for agents that require API key authentication."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-yaml",children:'proxied_agents:\n - name: "api-key-agent"\n url: "https://api.example.com/agent"\n authentication:\n type: "static_apikey"\n token: "${AGENT_API_KEY}"\n'})}),"\n",(0,i.jsx)(n.h3,{id:"oauth-20-client-credentials",children:"OAuth 2.0 Client Credentials"}),"\n",(0,i.jsx)(n.p,{children:"Use OAuth 2.0 client credentials flow for agents that require dynamic token acquisition. The proxy automatically handles token refresh and retry logic."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-yaml",children:'proxied_agents:\n - name: "oauth-agent"\n url: "https://api.example.com/agent"\n authentication:\n type: "oauth2_client_credentials"\n token_url: "https://auth.example.com/oauth/token"\n client_id: "${OAUTH_CLIENT_ID}"\n client_secret: "${OAUTH_CLIENT_SECRET}"\n scope: "agent.read agent.write" # Optional\n token_cache_duration_seconds: 3300 # Optional, default: 3300 (55 minutes)\n'})}),"\n",(0,i.jsx)(n.p,{children:"The proxy caches OAuth tokens and automatically refreshes them when they expire. If a request receives a 401 Unauthorized response, the proxy invalidates the cached token and retries the request once with a fresh token."}),"\n",(0,i.jsx)(n.admonition,{title:"Security Best Practice",type:"note",children:(0,i.jsx)(n.p,{children:"Always use environment variables for sensitive credentials. Never commit tokens or secrets directly in configuration files."})}),"\n",(0,i.jsx)(n.h2,{id:"artifact-handling",children:"Artifact Handling"}),"\n",(0,i.jsx)(n.p,{children:"The proxy manages artifact flow in both directions to ensure seamless integration between Agent Mesh and external agents."}),"\n",(0,i.jsx)(n.h3,{id:"request-flow-agent-mesh-to-external-agent",children:"Request Flow: Agent Mesh to External Agent"}),"\n",(0,i.jsx)(n.p,{children:"When it forwards requests to external agents, the proxy resolves artifact URIs to byte content using the following sequence of operations:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["The proxy receives an A2A request containing artifact references (for example, ",(0,i.jsx)(n.code,{children:"artifact://app/user/session/data.csv?version=1"}),")."]}),"\n",(0,i.jsx)(n.li,{children:"The proxy loads the artifact content from Agent Mesh's artifact service."}),"\n",(0,i.jsx)(n.li,{children:"The proxy replaces the URI with the actual byte content in the request."}),"\n",(0,i.jsx)(n.li,{children:"The proxy forwards the modified request to the external agent."}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"This process ensures that external agents receive complete artifact data without needing access to Agent Mesh's artifact service."}),"\n",(0,i.jsx)(n.h3,{id:"response-flow-external-agent-to-agent-mesh",children:"Response Flow: External Agent to Agent Mesh"}),"\n",(0,i.jsx)(n.p,{children:"When it receives responses from external agents, the proxy saves artifacts to Agent Mesh as follows:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsx)(n.li,{children:"The external agent returns artifacts with byte content in the response."}),"\n",(0,i.jsx)(n.li,{children:"The proxy saves each artifact to Agent Mesh's artifact service."}),"\n",(0,i.jsx)(n.li,{children:"The proxy replaces the byte content with an artifact URI."}),"\n",(0,i.jsx)(n.li,{children:"The proxy publishes the modified response to Agent Mesh."}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"This process ensures that artifacts are stored centrally and can be accessed by other agents in Agent Mesh."}),"\n",(0,i.jsx)(n.h3,{id:"artifact-metadata",children:"Artifact Metadata"}),"\n",(0,i.jsx)(n.p,{children:"The proxy automatically generates metadata for saved artifacts, including:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"proxied_from_artifact_id"}),": The original artifact ID from the external agent"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"description"}),": Extracted from the artifact or generated from context"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"produced_artifacts"}),": A manifest of all artifacts created during task execution"]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"discovery-and-health",children:"Discovery and Health"}),"\n",(0,i.jsx)(n.p,{children:"The proxy maintains agent discovery and health monitoring through periodic agent card fetching."}),"\n",(0,i.jsx)(n.h3,{id:"initial-discovery",children:"Initial Discovery"}),"\n",(0,i.jsx)(n.p,{children:"When the proxy starts, it performs synchronous discovery of all configured agents by:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["Fetching agent cards from each external agent's ",(0,i.jsx)(n.code,{children:"/.well-known/agent.json"})," endpoint."]}),"\n",(0,i.jsx)(n.li,{children:"Updating the local agent registry with agent capabilities."}),"\n",(0,i.jsx)(n.li,{children:"Publishing agent cards to the Agent Mesh discovery topic."}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"This process ensures that external agents are immediately discoverable when the proxy starts."}),"\n",(0,i.jsx)(n.h3,{id:"periodic-refresh",children:"Periodic Refresh"}),"\n",(0,i.jsxs)(n.p,{children:["The proxy periodically refreshes agent cards based on the configured ",(0,i.jsx)(n.code,{children:"discovery_interval_seconds"}),". When the configured interval elapses, the proxy fetches updated agent cards from external agents, updates the local registry with any changes, and then publishes the updated cards to Agent Mesh. This process ensures that Agent Mesh has current information about external agent capabilities and availability."]}),"\n",(0,i.jsx)(n.h3,{id:"agent-card-transformation",children:"Agent Card Transformation"}),"\n",(0,i.jsx)(n.p,{children:"The proxy transforms agent cards to make external agents appear as native Agent Mesh agents:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["The ",(0,i.jsx)(n.code,{children:"name"})," field is set to the configured alias (the name you specify in ",(0,i.jsx)(n.code,{children:"proxied_agents"}),")."]}),"\n",(0,i.jsxs)(n.li,{children:["The ",(0,i.jsx)(n.code,{children:"url"})," field is rewritten to use the Solace topic format (for example, ",(0,i.jsx)(n.code,{children:"solace:myorg/production/agent/external-data-agent"}),")."]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"These agent cards allow other agents to interact with external agents using the standard A2A protocol over Solace event mesh, without knowing they are proxied."}),"\n",(0,i.jsx)(n.h2,{id:"task-lifecycle-management",children:"Task Lifecycle Management"}),"\n",(0,i.jsx)(n.p,{children:"The proxy tracks active tasks and manages their lifecycle from initiation to completion."}),"\n",(0,i.jsx)(n.h3,{id:"task-initiation",children:"Task Initiation"}),"\n",(0,i.jsx)(n.p,{children:"When a request arrives from Agent Mesh, the proxy:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsx)(n.li,{children:"Creates a task context to track the task's state."}),"\n",(0,i.jsx)(n.li,{children:"Resolves inbound artifacts."}),"\n",(0,i.jsx)(n.li,{children:"Forwards the request to the external agent."}),"\n",(0,i.jsx)(n.li,{children:"Begins streaming responses back to Agent Mesh."}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"task-cancellation",children:"Task Cancellation"}),"\n",(0,i.jsx)(n.p,{children:"When a cancellation request arrives, the proxy:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsx)(n.li,{children:"Looks up the active task context."}),"\n",(0,i.jsx)(n.li,{children:"Forwards the cancellation request to the external agent."}),"\n",(0,i.jsx)(n.li,{children:"Publishes the cancellation response to Agent Mesh."}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"task-completion",children:"Task Completion"}),"\n",(0,i.jsx)(n.p,{children:"When a task completes, the proxy:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsx)(n.li,{children:"Processes any final artifacts."}),"\n",(0,i.jsx)(n.li,{children:"Publishes the final task response to Agent Mesh."}),"\n",(0,i.jsx)(n.li,{children:"Removes the task context from active tracking."}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"error-handling-and-retry-logic",children:"Error Handling and Retry Logic"}),"\n",(0,i.jsx)(n.p,{children:"The proxy implements robust error handling and automatic retry logic for authentication failures."}),"\n",(0,i.jsx)(n.h3,{id:"oauth-20-automatic-retry",children:"OAuth 2.0 Automatic Retry"}),"\n",(0,i.jsx)(n.p,{children:"When using OAuth 2.0 authentication, the proxy automatically handles token expiration using the following sequence:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsx)(n.li,{children:"A request receives a 401 Unauthorized response from the external agent."}),"\n",(0,i.jsx)(n.li,{children:"The proxy invalidates the cached token."}),"\n",(0,i.jsx)(n.li,{children:"The proxy removes all cached clients for the agent/session."}),"\n",(0,i.jsx)(n.li,{children:"The proxy fetches a fresh token from the OAuth provider."}),"\n",(0,i.jsx)(n.li,{children:"The proxy retries the request once with the new token."}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"This sequence ensures seamless operation even when tokens expire during long-running tasks."}),"\n",(0,i.jsx)(n.h3,{id:"connection-errors",children:"Connection Errors"}),"\n",(0,i.jsx)(n.p,{children:"The proxy provides clear error messages for connection failures:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Connection refused or agent unreachable"}),"\n",(0,i.jsx)(n.li,{children:"Timeout errors with configurable timeout values"}),"\n",(0,i.jsx)(n.li,{children:"JSON-RPC protocol errors from external agents"}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"error-responses",children:"Error Responses"}),"\n",(0,i.jsx)(n.p,{children:"When errors occur, the proxy publishes standard A2A error responses to Agent Mesh, including:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"InternalError"}),": For unexpected proxy errors"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"InvalidRequestError"}),": For malformed requests"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"TaskNotFoundError"}),": For cancellation requests on unknown tasks"]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"creating-a-proxy",children:"Creating a Proxy"}),"\n",(0,i.jsx)(n.p,{children:"Proxies are configured using standard YAML configuration files, similar to agents and gateways."}),"\n",(0,i.jsx)(n.h3,{id:"creating-the-configuration-file",children:"Creating the Configuration File"}),"\n",(0,i.jsxs)(n.p,{children:["Create a new YAML file in your ",(0,i.jsx)(n.code,{children:"configs"})," directory (for example, ",(0,i.jsx)(n.code,{children:"configs/my-proxy.yaml"}),"):"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-yaml",children:'log:\n stdout_log_level: INFO\n log_file_level: DEBUG\n log_file: my-proxy.log\n\n# Include shared configuration (broker connection, etc.)\n!include shared_config.yaml\n\napps:\n - name: my_a2a_proxy\n app_module: solace_agent_mesh.agent.proxies.a2a.app\n broker:\n <<: *broker_connection\n\n app_config:\n namespace: "${NAMESPACE}"\n \n artifact_service:\n type: "filesystem"\n base_path: "/tmp/proxy-artifacts"\n artifact_scope: "namespace"\n \n discovery_interval_seconds: 60\n default_request_timeout_seconds: 300\n \n proxied_agents:\n - name: "external-agent-1"\n url: "https://api.example.com/agent"\n request_timeout_seconds: 120\n authentication:\n type: "static_bearer"\n token: "${AGENT_TOKEN}"\n'})}),"\n",(0,i.jsxs)(n.p,{children:["You can use the example file at ",(0,i.jsx)(n.code,{children:"examples/a2a_proxy.yaml"})," as a template."]}),"\n",(0,i.jsx)(n.h3,{id:"running-the-proxy",children:"Running the Proxy"}),"\n",(0,i.jsx)(n.p,{children:"Run the proxy along with your other Agent Mesh components:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"sam run\n"})}),"\n",(0,i.jsx)(n.p,{children:"The proxy automatically subscribes to the appropriate Solace topics and begins proxying requests to external agents."}),"\n",(0,i.jsx)(n.h3,{id:"multiple-proxy-configurations",children:"Multiple Proxy Configurations"}),"\n",(0,i.jsx)(n.p,{children:"While a single proxy can manage multiple external agents, you may want to create separate proxy configurations to:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Organize agents by domain or team"}),"\n",(0,i.jsx)(n.li,{children:"Isolate agents with different security requirements"}),"\n",(0,i.jsx)(n.li,{children:"Distribute load across multiple proxy instances"}),"\n"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"configs/\n\u251c\u2500\u2500 data-agents-proxy.yaml # Proxies 3 data-related agents\n\u251c\u2500\u2500 analytics-agents-proxy.yaml # Proxies 2 analytics agents\n\u2514\u2500\u2500 third-party-agents-proxy.yaml # Proxies external vendor agents\n"})}),"\n",(0,i.jsx)(n.p,{children:"Run all proxies together:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"sam run\n"})}),"\n",(0,i.jsx)(n.p,{children:"Or run specific proxy configurations:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"sam run configs/data-agents-proxy.yaml\n"})}),"\n",(0,i.jsx)(n.h2,{id:"advanced-configuration",children:"Advanced Configuration"}),"\n",(0,i.jsx)(n.h3,{id:"per-agent-timeout-override",children:"Per-Agent Timeout Override"}),"\n",(0,i.jsx)(n.p,{children:"You can override the default timeout for specific agents:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-yaml",children:'proxied_agents:\n - name: "slow-agent"\n url: "https://slow.example.com/agent"\n request_timeout_seconds: 600 # 10 minutes\n'})}),"\n",(0,i.jsx)(n.h3,{id:"custom-artifact-service-scope",children:"Custom Artifact Service Scope"}),"\n",(0,i.jsx)(n.p,{children:"Configure artifact storage scope for the proxy:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-yaml",children:'artifact_service:\n type: "filesystem"\n base_path: "/data/proxy-artifacts"\n artifact_scope: "namespace" # Options: namespace, app, custom\n'})}),"\n",(0,i.jsx)(n.h3,{id:"multiple-proxies",children:"Multiple Proxies"}),"\n",(0,i.jsx)(n.p,{children:"You can run multiple proxy instances to distribute load or isolate different sets of external agents. Each proxy instance can manage multiple agents:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-yaml",children:'# data-agents-proxy.yaml\napp:\n name: data-agents-proxy\n app_config:\n proxied_agents:\n - name: "data-agent-1"\n url: "https://data1.example.com/agent"\n - name: "data-agent-2"\n url: "https://data2.example.com/agent"\n - name: "data-agent-3"\n url: "https://data3.example.com/agent"\n\n# analytics-agents-proxy.yaml\napp:\n name: analytics-agents-proxy\n app_config:\n proxied_agents:\n - name: "analytics-agent-1"\n url: "https://analytics1.example.com/agent"\n - name: "analytics-agent-2"\n url: "https://analytics2.example.com/agent"\n'})}),"\n",(0,i.jsx)(n.h2,{id:"troubleshooting",children:"Troubleshooting"}),"\n",(0,i.jsx)(n.h3,{id:"agent-not-discoverable",children:"Agent Not Discoverable"}),"\n",(0,i.jsx)(n.p,{children:"If an external agent does not appear in Agent Mesh:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsx)(n.li,{children:"Check that the agent's URL is accessible from the proxy."}),"\n",(0,i.jsxs)(n.li,{children:["Verify that the agent exposes ",(0,i.jsx)(n.code,{children:"/.well-known/agent.json"}),"."]}),"\n",(0,i.jsx)(n.li,{children:"Check the proxy logs for discovery errors."}),"\n",(0,i.jsxs)(n.li,{children:["Ensure that ",(0,i.jsx)(n.code,{children:"discovery_interval_seconds"})," is set appropriately and is more frequent than the ",(0,i.jsx)(n.code,{children:"health_check_ttl_seconds"})," that is set on the calling agents and gateways."]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"authentication-failures",children:"Authentication Failures"}),"\n",(0,i.jsx)(n.p,{children:"If requests fail with 401 errors:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsx)(n.li,{children:"Verify that the credentials are correctly set in environment variables."}),"\n",(0,i.jsxs)(n.li,{children:["For OAuth 2.0, check that ",(0,i.jsx)(n.code,{children:"token_url"}),", ",(0,i.jsx)(n.code,{children:"client_id"}),", and ",(0,i.jsx)(n.code,{children:"client_secret"})," are correct."]}),"\n",(0,i.jsx)(n.li,{children:"Ensure that the OAuth token URL uses HTTPS (required for security)."}),"\n",(0,i.jsx)(n.li,{children:"Check the proxy logs for token acquisition errors."}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"timeout-errors",children:"Timeout Errors"}),"\n",(0,i.jsx)(n.p,{children:"If requests timeout:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["Increase ",(0,i.jsx)(n.code,{children:"request_timeout_seconds"})," for slow agents."]}),"\n",(0,i.jsx)(n.li,{children:"Check the network connectivity between the proxy and the external agent."}),"\n",(0,i.jsx)(n.li,{children:"Verify that the external agent is responding within the timeout period."}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"artifact-issues",children:"Artifact Issues"}),"\n",(0,i.jsx)(n.p,{children:"If artifacts are not flowing correctly:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsx)(n.li,{children:"Verify that the artifact service is properly configured."}),"\n",(0,i.jsx)(n.li,{children:"Check that the proxy has write permissions to the artifact storage location."}),"\n",(0,i.jsx)(n.li,{children:"Ensure that the artifact URIs are correctly formatted."}),"\n",(0,i.jsx)(n.li,{children:"Check the proxy logs for artifact save/load errors."}),"\n"]})]})}function d(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(h,{...e})}):h(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>a,x:()=>o});var s=t(6540);const i={},r=s.createContext(i);function a(e){const n=s.useContext(r);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:a(e.components),s.createElement(r.Provider,{value:n},e.children)}}}]);
@@ -0,0 +1 @@
1
+ "use strict";(self.webpackChunksolace_agenitc_mesh_docs=self.webpackChunksolace_agenitc_mesh_docs||[]).push([[6993],{35:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>r,default:()=>h,frontMatter:()=>a,metadata:()=>s,toc:()=>c});const s=JSON.parse('{"id":"documentation/components/agents","title":"Agents","description":"Agents are specialized processing units within the Agent Mesh framework that are built around the Google Agent Development Kit (ADK) and provide the core intelligence layer. They:","source":"@site/docs/documentation/components/agents.md","sourceDirName":"documentation/components","slug":"/documentation/components/agents","permalink":"/solace-agent-mesh/docs/documentation/components/agents","draft":false,"unlisted":false,"editUrl":"https://github.com/SolaceLabs/solace-agent-mesh/edit/main/docs/docs/documentation/components/agents.md","tags":[],"version":"current","sidebarPosition":220,"frontMatter":{"title":"Agents","sidebar_position":220},"sidebar":"docSidebar","previous":{"title":"Components","permalink":"/solace-agent-mesh/docs/documentation/components/"},"next":{"title":"Orchestrator","permalink":"/solace-agent-mesh/docs/documentation/components/orchestrator"}}');var i=t(4848),o=t(8453);const a={title:"Agents",sidebar_position:220},r=void 0,l={},c=[{value:"Key Functions",id:"key-functions",level:2},{value:"Agent Design",id:"agent-design",level:2},{value:"The Agent Lifecycle",id:"the-agent-lifecycle",level:3},{value:"Potential Agent Examples",id:"potential-agent-examples",level:3},{value:"Tool Ecosystem",id:"tool-ecosystem",level:2},{value:"1. Built-in Tools",id:"1-built-in-tools",level:3},{value:"2. Custom Python Tools",id:"2-custom-python-tools",level:3},{value:"3. MCP (Model Context Protocol) Tools",id:"3-mcp-model-context-protocol-tools",level:3},{value:"Agent Card",id:"agent-card",level:2},{value:"Key Fields",id:"key-fields",level:3},{value:"Skills",id:"skills",level:3},{value:"Example Configuration",id:"example-configuration",level:3},{value:"User-Defined Agents",id:"user-defined-agents",level:2},{value:"Remote A2A Agents",id:"remote-a2a-agents",level:2},{value:"Agent Plugins",id:"agent-plugins",level:2}];function d(e){const n={a:"a",admonition:"admonition",code:"code",h2:"h2",h3:"h3",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,o.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.p,{children:"Agents are specialized processing units within the Agent Mesh framework that are built around the Google Agent Development Kit (ADK) and provide the core intelligence layer. They:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"perform specific tasks or provide domain-specific knowledge or capabilities"}),"\n",(0,i.jsx)(n.li,{children:"integrate with the ADK runtime for advanced AI capabilities including tool usage, memory management, and session handling"}),"\n",(0,i.jsx)(n.li,{children:"play a crucial role in the system's ability to handle a wide range of tasks and adapt to various domains"}),"\n"]}),"\n",(0,i.jsx)(n.admonition,{title:"In one sentence",type:"tip",children:(0,i.jsx)(n.p,{children:"Agents are intelligence units that communicate through the A2A protocol to provide system capabilities beyond basic orchestrator capabilities."})}),"\n",(0,i.jsx)(n.h2,{id:"key-functions",children:"Key Functions"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"ADK Integration"}),": Agents are built using the Google Agent Development Kit, providing advanced AI capabilities including tool usage, memory management, and artifact handling."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"AI-Enabled"}),": Agents come packaged with access to large language models (LLMs) and can utilize various tools."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Dynamic Discovery"}),": New agents can self-register/deregister and be discovered dynamically through broadcast messages without requiring changes to the running system."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Tool Ecosystem"}),": Agents have access to built-in tools for artifact management, data analysis, web scraping, and peer-to-peer delegation."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Session Management"}),": Agents support conversation continuity through ADK's session management capabilities."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Independence"}),": Agents are modularized and can be updated or replaced independently of other components."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"agent-design",children:"Agent Design"}),"\n",(0,i.jsx)(n.p,{children:"Agents in Agent Mesh are built around the Solace AI Connector (SAC) component with ADK. Agent Mesh agents are complete self-contained units that can carry out specific tasks or provide domain-specific knowledge or capabilities. Each agent is defined by a YAML configuration file."}),"\n",(0,i.jsx)(n.p,{children:"Each agent integrates with:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"ADK Runtime"}),": For AI model access, tool execution, and session management"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"A2A Protocol"}),": For standardized agent-to-agent communication"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Tool Registry"}),": Access to built-in and custom tools"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Artifact Service"}),": For file handling and management"]}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"For example, an agent configured with SQL database tools can execute queries, perform data analysis, and generate visualizations through the integrated tool ecosystem, all while maintaining conversation context through its session management."}),"\n",(0,i.jsx)(n.h3,{id:"the-agent-lifecycle",children:"The Agent Lifecycle"}),"\n",(0,i.jsx)(n.p,{children:"Agents in Agent Mesh follow the A2A protocol lifecycle and interact with the agent registry:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Discovery"}),": Agents start broadcasting discovery messages on startup to announce their availability and capabilities to the agent mesh."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Active"}),": The agent listens for A2A protocol messages on its designated topics and processes incoming tasks through the ADK runtime."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Execution"}),": The agent works on a task. They can also delegate tasks to other agents through the peer-to-peer A2A communication protocol."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Cleanup"}),": When shutting down, agents perform session cleanup and deregister from the agent mesh."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"potential-agent-examples",children:"Potential Agent Examples"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"RAG (Retrieval Augmented Generation) Agent"}),": An agent that can retrieve information based on a natural language query using an embedding model and vector database, and then generate a response using a language model."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"External API Bridge"}),": An agent that acts as a bridge to external APIs, retrieving information from third-party services such as weather APIs or product information databases."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Internal System Lookup"}),": An agent that performs lookups in internal systems, such as a ticket management system or a customer relationship management (CRM) database."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Natural Language Processing Agent"}),": An agent that can perform tasks like sentiment analysis, named entity recognition, or language translation."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"tool-ecosystem",children:"Tool Ecosystem"}),"\n",(0,i.jsxs)(n.p,{children:["Agents perform tasks by using ",(0,i.jsx)(n.strong,{children:"tools"}),". A tool is a specific capability, like querying a database, calling an external API, or generating an image. The Agent Mesh framework provides a flexible and powerful tool ecosystem, allowing you to equip your agents with the right capabilities for any job."]}),"\n",(0,i.jsx)(n.p,{children:"There are three primary ways to add tools to an agent:"}),"\n",(0,i.jsx)(n.h3,{id:"1-built-in-tools",children:"1. Built-in Tools"}),"\n",(0,i.jsx)(n.p,{children:"Agent Mesh includes a rich library of pre-packaged tools for common tasks like data analysis, file management, and web requests. These are the easiest to use and can be enabled with just a few lines of configuration."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Use Case"}),": For standard, out-of-the-box functionality."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Learn More"}),": See the ",(0,i.jsx)(n.a,{href:"/solace-agent-mesh/docs/documentation/components/builtin-tools/",children:"Built-in Tools Reference"})," for a complete list and configuration details."]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"2-custom-python-tools",children:"2. Custom Python Tools"}),"\n",(0,i.jsx)(n.p,{children:"For unique business logic or specialized tasks, you can create your own tools using Python. This is the most powerful and flexible method, supporting everything from simple functions to advanced, class-based tool factories that can generate multiple tools programmatically."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Use Case"}),": For implementing custom logic, integrating with proprietary systems, or creating dynamically configured tools."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Learn More"}),": See the ",(0,i.jsx)(n.a,{href:"/solace-agent-mesh/docs/documentation/developing/creating-python-tools",children:"Creating Python Tools"})," guide for a complete walkthrough."]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"3-mcp-model-context-protocol-tools",children:"3. MCP (Model Context Protocol) Tools"}),"\n",(0,i.jsx)(n.p,{children:"For integrating with external, standalone tool servers that conform to the Model Context Protocol, you can configure an MCP tool. This allows agents to communicate with tools running in separate processes or on different machines."}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Use Case"}),": For integrating with existing MCP-compliant tool servers or language-agnostic tool development."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Learn More"}),": See the ",(0,i.jsx)(n.a,{href:"/solace-agent-mesh/docs/documentation/developing/tutorials/mcp-integration",children:"MCP Integration Tutorial"}),"."]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"agent-card",children:"Agent Card"}),"\n",(0,i.jsx)(n.p,{children:"The Agent Card is a public-facing profile that describes an agent's identity, capabilities, and how to interact with it. It functions like a digital business card, allowing other agents and clients within Agent Mesh to discover what an agent can do. This information is published by the agent and is crucial for dynamic discovery and interoperability."}),"\n",(0,i.jsxs)(n.p,{children:["The Agent Card is defined in the agent's YAML configuration file under the ",(0,i.jsx)(n.code,{children:"agent_card"})," section."]}),"\n",(0,i.jsx)(n.h3,{id:"key-fields",children:"Key Fields"}),"\n",(0,i.jsxs)(n.p,{children:["You can configure the following fields in the ",(0,i.jsx)(n.code,{children:"agent card"}),":"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"description"})}),": A summary of the agent's purpose and capabilities."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"defaultInputModes"})}),": A list of supported MIME types for input (e.g., ",(0,i.jsx)(n.code,{children:'["text/plain", "application/json", "file"]'}),")."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"defaultOutputModes"})}),": A list of supported MIME types for output."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"skills"})}),": A list of specific skills the agent possesses. Each skill corresponds to a capability, often backed by a tool."]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"skills",children:"Skills"}),"\n",(0,i.jsx)(n.p,{children:"A skill describes a specific function the agent can perform. It provides granular detail about the agent's abilities."}),"\n",(0,i.jsx)(n.p,{children:"Key attributes of a skill include:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"id"})}),": A unique identifier for the skill, which should match the ",(0,i.jsx)(n.code,{children:"tool_name"})," if the skill is directly mapped to a tool."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"name"})}),": A human-readable name for the skill."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"description"})}),": A clear explanation of what the skill does, which helps the LLM (and other agents) decide when to use it."]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"example-configuration",children:"Example Configuration"}),"\n",(0,i.jsxs)(n.p,{children:["Here is an example of an ",(0,i.jsx)(n.code,{children:"agent_card"}),' configuration for a "Mermaid Diagram Generator" agent:']}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-yaml",children:'# ... inside app_config ...\nagent_card:\n description: "An agent that generates PNG images from Mermaid diagram syntax."\n defaultInputModes: ["text"] # Expects Mermaid syntax as text\n defaultOutputModes: ["text", "file"] # Confirms with text, outputs file artifact\n skills:\n - id: "mermaid_diagram_generator"\n name: "Mermaid Diagram Generator"\n description: "Generates a PNG image from Mermaid diagram syntax. Input: mermaid_syntax (string), output_filename (string, optional)."\n'})}),"\n",(0,i.jsxs)(n.p,{children:['This card clearly communicates that the agent can take text (the Mermaid syntax) and produce a file (the PNG image), and it details the specific "mermaid_diagram_generator" skill it offers. For more details on creating agents and configuring their cards, see ',(0,i.jsx)(n.a,{href:"/solace-agent-mesh/docs/documentation/developing/create-agents",children:"Creating Custom Agents"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"user-defined-agents",children:"User-Defined Agents"}),"\n",(0,i.jsx)(n.p,{children:"Using the Agent Mesh CLI, you can create your own agents. Agents are configured through YAML files that specify:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Agent name and instructions"}),"\n",(0,i.jsx)(n.li,{children:"LLM model configuration"}),"\n",(0,i.jsx)(n.li,{children:"Available tools and capabilities"}),"\n",(0,i.jsx)(n.li,{children:"Artifact and session management settings"}),"\n",(0,i.jsx)(n.li,{children:"Discovery settings"}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"The following Agent Mesh CLI command creates an agent configuration:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-sh",children:"sam add agent my-agent [--gui]\n"})}),"\n",(0,i.jsxs)(n.p,{children:["For more information, see ",(0,i.jsx)(n.a,{href:"/solace-agent-mesh/docs/documentation/developing/create-agents",children:"Creating Custom Agents"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"remote-a2a-agents",children:"Remote A2A Agents"}),"\n",(0,i.jsx)(n.p,{children:"In addition to agents that run natively within Agent Mesh, you can integrate external agents that communicate using the A2A protocol over HTTPS. These remote agents run on separate infrastructure but can still participate in collaborative workflows with mesh agents."}),"\n",(0,i.jsx)(n.p,{children:"Remote A2A agents are useful when you need to:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Integrate third-party agents from vendors or partners"}),"\n",(0,i.jsx)(n.li,{children:"Connect agents running in different cloud environments or on-premises systems"}),"\n",(0,i.jsx)(n.li,{children:"Maintain service isolation while enabling collaboration"}),"\n",(0,i.jsx)(n.li,{children:"Gradually migrate existing A2A agents to the mesh"}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"To integrate external agents, you use a proxy component that acts as a protocol bridge between A2A over HTTPS and A2A over Solace event mesh. The proxy handles authentication, artifact flow, and discovery, making remote agents appear as native mesh agents to other components."}),"\n",(0,i.jsxs)(n.p,{children:["For detailed information on configuring and deploying proxies for remote agents, see ",(0,i.jsx)(n.a,{href:"/solace-agent-mesh/docs/documentation/components/proxies",children:"Proxies"}),"."]}),"\n",(0,i.jsx)(n.h2,{id:"agent-plugins",children:"Agent Plugins"}),"\n",(0,i.jsx)(n.p,{children:"You can also use agents built by the community or Solace directly in your app with little to no configuration."}),"\n",(0,i.jsxs)(n.p,{children:["For more information, see ",(0,i.jsx)(n.a,{href:"/solace-agent-mesh/docs/documentation/components/plugins#use-a-plugin",children:"Use a Plugin"}),"."]})]})}function h(e={}){const{wrapper:n}={...(0,o.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>a,x:()=>r});var s=t(6540);const i={},o=s.createContext(i);function a(e){const n=s.useContext(o);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function r(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:a(e.components),s.createElement(o.Provider,{value:n},e.children)}}}]);
@@ -1 +1 @@
1
- "use strict";(self.webpackChunksolace_agenitc_mesh_docs=self.webpackChunksolace_agenitc_mesh_docs||[]).push([[2516],{2948:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>o,default:()=>h,frontMatter:()=>r,metadata:()=>a,toc:()=>d});const a=JSON.parse('{"id":"documentation/developing/tutorials/event-mesh-gateway","title":"Event Mesh Gateway","description":"If you already have an event mesh in place, you can integrate Agent Mesh into it. This allows you to leverage existing infrastructure while introducing intelligence and automation through Agent Mesh.","source":"@site/docs/documentation/developing/tutorials/event-mesh-gateway.md","sourceDirName":"documentation/developing/tutorials","slug":"/documentation/developing/tutorials/event-mesh-gateway","permalink":"/solace-agent-mesh/docs/documentation/developing/tutorials/event-mesh-gateway","draft":false,"unlisted":false,"editUrl":"https://github.com/SolaceLabs/solace-agent-mesh/edit/main/docs/docs/documentation/developing/tutorials/event-mesh-gateway.md","tags":[],"version":"current","sidebarPosition":20,"frontMatter":{"title":"Event Mesh Gateway","sidebar_position":20},"sidebar":"docSidebar","previous":{"title":"REST Gateway","permalink":"/solace-agent-mesh/docs/documentation/developing/tutorials/rest-gateway"},"next":{"title":"Amazon Bedrock Agents","permalink":"/solace-agent-mesh/docs/documentation/developing/tutorials/bedrock-agents"}}');var s=t(4848),i=t(8453);const r={title:"Event Mesh Gateway",sidebar_position:20},o="Event Mesh Gateway",l={},d=[{value:"Benefits of Integrating with an Event Mesh",id:"benefits-of-integrating-with-an-event-mesh",level:2},{value:"Prerequisites",id:"prerequisites",level:2},{value:"Setting Up the Environment",id:"setting-up-the-environment",level:2},{value:"Adding the Event Mesh Gateway Plugin",id:"adding-the-event-mesh-gateway-plugin",level:2},{value:"Configuring the Event Mesh Gateway",id:"configuring-the-event-mesh-gateway",level:4},{value:"Environment Variables",id:"environment-variables",level:4},{value:"Gateway Configuration",id:"gateway-configuration",level:3},{value:"Event Handlers",id:"event-handlers",level:4},{value:"Output Handlers",id:"output-handlers",level:4},{value:"Complete Configuration Example",id:"complete-configuration-example",level:3},{value:"Running the Event Mesh Gateway",id:"running-the-event-mesh-gateway",level:2},{value:"Testing the Event Mesh Gateway",id:"testing-the-event-mesh-gateway",level:2},{value:"Using The Solace Broker Manager",id:"using-the-solace-broker-manager",level:3},{value:"Advanced Features",id:"advanced-features",level:2},{value:"Artifact Processing",id:"artifact-processing",level:3},{value:"Dynamic Agent Routing",id:"dynamic-agent-routing",level:3},{value:"Context Forwarding",id:"context-forwarding",level:3},{value:"Error Handling",id:"error-handling",level:3}];function c(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",header:"header",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,i.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.header,{children:(0,s.jsx)(n.h1,{id:"event-mesh-gateway",children:"Event Mesh Gateway"})}),"\n",(0,s.jsxs)(n.p,{children:["If you already have an ",(0,s.jsx)(n.a,{href:"https://solace.com/what-is-an-event-mesh/",children:"event mesh"})," in place, you can integrate Agent Mesh into it. This allows you to leverage existing infrastructure while introducing intelligence and automation through Agent Mesh."]}),"\n",(0,s.jsx)(n.h2,{id:"benefits-of-integrating-with-an-event-mesh",children:"Benefits of Integrating with an Event Mesh"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Seamless Communication"}),": Agent Mesh can subscribe to and publish events across the entire event mesh"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Event-Driven Automation"}),": Intelligent event processing based on patterns and AI-driven insights"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Scalability"}),": Agent Mesh can dynamically participate in large-scale event-driven systems"]}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"The Event Mesh Gateway connects Agent Mesh to your existing event mesh infrastructure. Through its asynchronous interfaces, applications within your event mesh can seamlessly access and utilize Agent Mesh capabilities."}),"\n",(0,s.jsx)(n.p,{children:"This tutorial shows you how to build an Event Mesh Gateway that automatically generates and adds concise summaries to Jira bug reports, making them easier to understand at a glance."}),"\n",(0,s.jsx)(n.h2,{id:"prerequisites",children:"Prerequisites"}),"\n",(0,s.jsx)(n.p,{children:"This tutorial assumes you have an existing Jira application integrated with your event mesh that:"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:['Publishes a "jira_created" event to topic ',(0,s.jsx)(n.code,{children:"jira/issue/created/<jira_id>"})," when a new Jira issue is created"]}),"\n",(0,s.jsxs)(n.li,{children:['Listens for "jira_update" events on topic ',(0,s.jsx)(n.code,{children:"jira/issue/update"})," to update existing issues"]}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"Create an Event Mesh Gateway that:"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsx)(n.li,{children:"Monitors for new Jira issues"}),"\n",(0,s.jsx)(n.li,{children:"Automatically generates a concise summary"}),"\n",(0,s.jsx)(n.li,{children:"Creates an event to update the original Jira issue with this summary"}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"This creates a streamlined workflow where bug reports are automatically enhanced with clear, AI-generated summaries."}),"\n",(0,s.jsx)(n.h2,{id:"setting-up-the-environment",children:"Setting Up the Environment"}),"\n",(0,s.jsxs)(n.p,{children:["First, you need to ",(0,s.jsx)(n.a,{href:"/solace-agent-mesh/docs/documentation/installing-and-configuring/installation",children:"install Agent Mesh and the Agent Mesh CLI"}),", and then ",(0,s.jsx)(n.a,{href:"/solace-agent-mesh/docs/documentation/installing-and-configuring/run-project",children:"create a new Agent Mesh project"}),"."]}),"\n",(0,s.jsxs)(n.p,{children:["For this tutorial, you need to create or use an existing ",(0,s.jsx)(n.a,{href:"https://solace.com/products/event-broker/",children:"Solace Event Broker"})," or ",(0,s.jsx)(n.a,{href:"https://solace.com/solutions/initiative/event-mesh/",children:"event mesh"})," created using Solace event brokers."]}),"\n",(0,s.jsx)(n.h2,{id:"adding-the-event-mesh-gateway-plugin",children:"Adding the Event Mesh Gateway Plugin"}),"\n",(0,s.jsx)(n.p,{children:"Once you have your project set up, add the Event Mesh Gateway plugin:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-sh",children:"sam plugin add jira-event-mesh --plugin sam-event-mesh-gateway\n"})}),"\n",(0,s.jsxs)(n.p,{children:["You can use any name for your agent, in this tutorial we use ",(0,s.jsx)(n.code,{children:"jira-event-mesh"}),"."]}),"\n",(0,s.jsx)(n.p,{children:"This command:"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["Installs the ",(0,s.jsx)(n.code,{children:"sam-event-mesh-gateway"})," plugin"]}),"\n",(0,s.jsxs)(n.li,{children:["Creates a new gateway configuration named ",(0,s.jsx)(n.code,{children:"jira-event-mesh"})," in your ",(0,s.jsx)(n.code,{children:"configs/gateways/"})," directory"]}),"\n"]}),"\n",(0,s.jsx)(n.h4,{id:"configuring-the-event-mesh-gateway",children:"Configuring the Event Mesh Gateway"}),"\n",(0,s.jsxs)(n.p,{children:["After adding the plugin, you can see a new configuration file in ",(0,s.jsx)(n.code,{children:"configs/gateways/jira-event-mesh.yaml"}),". This file contains the gateway configuration that needs to be customized for your Jira integration use case."]}),"\n",(0,s.jsx)(n.h4,{id:"environment-variables",children:"Environment Variables"}),"\n",(0,s.jsx)(n.p,{children:"First, set up the required environment variables for the data plane connection:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-sh",children:'# Data plane Solace broker connection (can be same or different from control plane)\nexport JIRA_EVENT_MESH_SOLACE_BROKER_URL="ws://localhost:8008"\nexport JIRA_EVENT_MESH_SOLACE_BROKER_VPN="default"\nexport JIRA_EVENT_MESH_SOLACE_BROKER_USERNAME="default"\nexport JIRA_EVENT_MESH_SOLACE_BROKER_PASSWORD="default"\n'})}),"\n",(0,s.jsx)(n.h3,{id:"gateway-configuration",children:"Gateway Configuration"}),"\n",(0,s.jsx)(n.p,{children:"The main configuration includes several key sections:"}),"\n",(0,s.jsx)(n.h4,{id:"event-handlers",children:"Event Handlers"}),"\n",(0,s.jsx)(n.p,{children:"Configure the event handler to listen for new Jira issues and generate summaries:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:'event_handlers:\n - name: "jira_issue_handler"\n subscriptions:\n - topic: "jira/issue/created/>"\n qos: 1\n input_expression: "template:Create a concise summary for the newly created Jira issue: Title: {{text://input.payload:title}}, Body: {{text://input.payload:body}}, ID: {{text://input.payload:id}}. Return a JSON object with fields \'id\', \'type\' (value should be \'summary\'), and \'summary\'."\n payload_encoding: "utf-8"\n payload_format: "json"\n target_agent_name: "OrchestratorAgent"\n on_success: "jira_summary_handler"\n on_error: "error_response_handler"\n forward_context:\n jira_id: "input.payload:id"\n correlation_id: "input.user_properties:correlation_id"\n'})}),"\n",(0,s.jsx)(n.h4,{id:"output-handlers",children:"Output Handlers"}),"\n",(0,s.jsx)(n.p,{children:"Configure output handlers to publish the summary back to the event mesh:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:'output_handlers:\n - name: "jira_summary_handler"\n topic_expression: "static:jira/issue/update"\n payload_expression: "task_response:text"\n payload_encoding: "utf-8"\n payload_format: "json"\n \n - name: "error_response_handler"\n topic_expression: "template:jira/issue/error/{{text://user_data.forward_context:jira_id}}"\n payload_expression: "task_response:a2a_task_response.error"\n payload_encoding: "utf-8"\n payload_format: "json"\n'})}),"\n",(0,s.jsx)(n.h3,{id:"complete-configuration-example",children:"Complete Configuration Example"}),"\n",(0,s.jsx)(n.p,{children:"Here is a complete configuration file based on the plugin template:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:'log:\n stdout_log_level: INFO\n log_file_level: DEBUG\n log_file: jira-event-mesh.log\n\n!include ../shared_config.yaml\n\napps:\n - name: jira-event-mesh-app\n app_module: sam_event_mesh_gateway.app\n broker:\n <<: *broker_connection\n\n app_config:\n namespace: ${NAMESPACE}\n gateway_id: "jira-event-mesh-gw-01"\n artifact_service: *default_artifact_service\n authorization_service:\n type: "none" # Or "default_rbac"\n default_user_identity: "anonymous_event_mesh_user" # If no identity from event\n\n\n\n # Data plane connection\n event_mesh_broker_config:\n broker_url: ${JIRA_EVENT_MESH_SOLACE_BROKER_URL}\n broker_vpn: ${JIRA_EVENT_MESH_SOLACE_BROKER_VPN}\n broker_username: ${JIRA_EVENT_MESH_SOLACE_BROKER_USERNAME}\n broker_password: ${JIRA_EVENT_MESH_SOLACE_BROKER_PASSWORD}\n\n event_handlers:\n - name: "jira_issue_handler"\n subscriptions:\n - topic: "jira/issue/created/>"\n qos: 1\n input_expression: "template:Create a concise summary for the newly created Jira issue: Title: {{text://input.payload:title}}, Body: {{text://input.payload:body}}, ID: {{text://input.payload:id}}. Return a JSON object with fields \'id\', \'type\' (value should be \'summary\'), and \'summary\'."\n payload_encoding: "utf-8"\n payload_format: "json"\n target_agent_name: "OrchestratorAgent"\n on_success: "jira_summary_handler"\n on_error: "error_response_handler"\n forward_context:\n jira_id: "input.payload:id"\n\n output_handlers:\n - name: "jira_summary_handler"\n topic_expression: "static:jira/issue/update"\n payload_expression: "task_response:text"\n payload_encoding: "utf-8"\n payload_format: "json"\n \n - name: "error_response_handler"\n topic_expression: "template:jira/issue/error/{{text://user_data.forward_context:jira_id}}"\n payload_expression: "task_response:a2a_task_response.error"\n payload_encoding: "utf-8"\n payload_format: "json"\n'})}),"\n",(0,s.jsx)(n.h2,{id:"running-the-event-mesh-gateway",children:"Running the Event Mesh Gateway"}),"\n",(0,s.jsx)(n.p,{children:"Now you can run the Event Mesh Gateway:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-sh",children:"sam run configs/gateways/jira-event-mesh.yaml\n"})}),"\n",(0,s.jsx)(n.p,{children:"The gateway:"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsx)(n.li,{children:"Connects to both the A2A control plane and the data plane event mesh"}),"\n",(0,s.jsx)(n.li,{children:"Subscribes to the configured topics on the data plane"}),"\n",(0,s.jsx)(n.li,{children:"Starts processing incoming events and routing them to agents"}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"testing-the-event-mesh-gateway",children:"Testing the Event Mesh Gateway"}),"\n",(0,s.jsx)(n.p,{children:"Now that the system is running, let's test the Event Mesh Gateway."}),"\n",(0,s.jsx)(n.h3,{id:"using-the-solace-broker-manager",children:"Using The Solace Broker Manager"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["Open the ",(0,s.jsx)(n.strong,{children:"Try Me!"})," tab of the ",(0,s.jsx)(n.a,{href:"https://docs.solace.com/Admin/Broker-Manager/PubSub-Manager-Overview.htm",children:"Solace Broker Manager"})]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["Connect both the ",(0,s.jsx)(n.strong,{children:"Publisher"})," and ",(0,s.jsx)(n.strong,{children:"Subscriber"})," panels by clicking their respective ",(0,s.jsx)(n.strong,{children:"Connect"})," buttons"]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"In the Subscriber panel:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["Enter ",(0,s.jsx)(n.code,{children:"jira/issue/update"})," in the ",(0,s.jsx)(n.code,{children:"Topic Subscriber"})," field"]}),"\n",(0,s.jsxs)(n.li,{children:["Click ",(0,s.jsx)(n.code,{children:"Subscribe"})]}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"In the Publisher panel:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["Use the topic ",(0,s.jsx)(n.code,{children:"jira/issue/created/JIRA-143321"})]}),"\n",(0,s.jsxs)(n.li,{children:["In the ",(0,s.jsx)(n.code,{children:"Message Content"})," field, enter:"]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-json",children:'{\n "id": "JIRA-143321",\n "title": "Exception when reading customer record",\n "body": "I got a DatabaseReadException when trying to get the data for customer ABC. The error indicated that the customer didn\'t exist, while they are our biggest customer!"\n}\n'})}),"\n",(0,s.jsxs)(n.ol,{start:"5",children:["\n",(0,s.jsxs)(n.li,{children:["Click ",(0,s.jsx)(n.strong,{children:"Publish"})]}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["After a few seconds, you can see a new message in the ",(0,s.jsx)(n.strong,{children:"Subscriber"})," messages with the topic ",(0,s.jsx)(n.code,{children:"jira/issue/update"})," and a body similar to:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-json",children:'{\n "id": "JIRA-143321",\n "type": "summary",\n "summary": "Database read error: Unable to retrieve record for key customer ABC despite confirmed existence"\n}\n'})}),"\n",(0,s.jsx)(n.h2,{id:"advanced-features",children:"Advanced Features"}),"\n",(0,s.jsx)(n.p,{children:"The Event Mesh Gateway supports several advanced features:"}),"\n",(0,s.jsx)(n.h3,{id:"artifact-processing",children:"Artifact Processing"}),"\n",(0,s.jsx)(n.p,{children:"You can configure the gateway to automatically create artifacts from incoming message payloads before sending them to agents. This is useful for processing files, images, or other binary data embedded in events."}),"\n",(0,s.jsx)(n.h3,{id:"dynamic-agent-routing",children:"Dynamic Agent Routing"}),"\n",(0,s.jsxs)(n.p,{children:["Instead of using a static ",(0,s.jsx)(n.code,{children:"target_agent_name"}),", you can use ",(0,s.jsx)(n.code,{children:"target_agent_name_expression"})," to dynamically determine which agent should process each event based on the message content."]}),"\n",(0,s.jsx)(n.h3,{id:"context-forwarding",children:"Context Forwarding"}),"\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"forward_context"})," configuration allows you to extract data from incoming messages and make it available when generating outgoing responses, enabling request-reply patterns and correlation tracking."]}),"\n",(0,s.jsx)(n.h3,{id:"error-handling",children:"Error Handling"}),"\n",(0,s.jsx)(n.p,{children:"Configure separate output handlers for success and error scenarios to ensure proper error reporting and system monitoring."})]})}function h(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(c,{...e})}):c(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>r,x:()=>o});var a=t(6540);const s={},i=a.createContext(s);function r(e){const n=a.useContext(i);return a.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),a.createElement(i.Provider,{value:n},e.children)}}}]);
1
+ "use strict";(self.webpackChunksolace_agenitc_mesh_docs=self.webpackChunksolace_agenitc_mesh_docs||[]).push([[2516],{2948:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>o,default:()=>h,frontMatter:()=>r,metadata:()=>a,toc:()=>d});const a=JSON.parse('{"id":"documentation/developing/tutorials/event-mesh-gateway","title":"Event Mesh Gateway","description":"If you already have an event mesh in place, you can integrate Agent Mesh into it. This allows you to leverage existing infrastructure while introducing intelligence and automation through Agent Mesh.","source":"@site/docs/documentation/developing/tutorials/event-mesh-gateway.md","sourceDirName":"documentation/developing/tutorials","slug":"/documentation/developing/tutorials/event-mesh-gateway","permalink":"/solace-agent-mesh/docs/documentation/developing/tutorials/event-mesh-gateway","draft":false,"unlisted":false,"editUrl":"https://github.com/SolaceLabs/solace-agent-mesh/edit/main/docs/docs/documentation/developing/tutorials/event-mesh-gateway.md","tags":[],"version":"current","sidebarPosition":20,"frontMatter":{"title":"Event Mesh Gateway","sidebar_position":20},"sidebar":"docSidebar","previous":{"title":"REST Gateway","permalink":"/solace-agent-mesh/docs/documentation/developing/tutorials/rest-gateway"},"next":{"title":"Amazon Bedrock Agents","permalink":"/solace-agent-mesh/docs/documentation/developing/tutorials/bedrock-agents"}}');var s=t(4848),i=t(8453);const r={title:"Event Mesh Gateway",sidebar_position:20},o="Event Mesh Gateway",l={},d=[{value:"Benefits of Integrating with an Event Mesh",id:"benefits-of-integrating-with-an-event-mesh",level:2},{value:"Prerequisites",id:"prerequisites",level:2},{value:"Setting Up the Environment",id:"setting-up-the-environment",level:2},{value:"Adding the Event Mesh Gateway Plugin",id:"adding-the-event-mesh-gateway-plugin",level:2},{value:"Configuring the Event Mesh Gateway",id:"configuring-the-event-mesh-gateway",level:4},{value:"Environment Variables",id:"environment-variables",level:4},{value:"Gateway Configuration",id:"gateway-configuration",level:3},{value:"Event Handlers",id:"event-handlers",level:4},{value:"Output Handlers",id:"output-handlers",level:4},{value:"Complete Configuration Example",id:"complete-configuration-example",level:3},{value:"Running the Event Mesh Gateway",id:"running-the-event-mesh-gateway",level:2},{value:"Testing the Event Mesh Gateway",id:"testing-the-event-mesh-gateway",level:2},{value:"Using The Solace Broker Manager",id:"using-the-solace-broker-manager",level:3},{value:"Advanced Features",id:"advanced-features",level:2},{value:"Artifact Processing",id:"artifact-processing",level:3},{value:"Dynamic Agent Routing",id:"dynamic-agent-routing",level:3},{value:"Context Forwarding",id:"context-forwarding",level:3},{value:"Error Handling",id:"error-handling",level:3}];function c(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",header:"header",li:"li",ol:"ol",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,i.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.header,{children:(0,s.jsx)(n.h1,{id:"event-mesh-gateway",children:"Event Mesh Gateway"})}),"\n",(0,s.jsxs)(n.p,{children:["If you already have an ",(0,s.jsx)(n.a,{href:"https://solace.com/what-is-an-event-mesh/",children:"event mesh"})," in place, you can integrate Agent Mesh into it. This allows you to leverage existing infrastructure while introducing intelligence and automation through Agent Mesh."]}),"\n",(0,s.jsx)(n.h2,{id:"benefits-of-integrating-with-an-event-mesh",children:"Benefits of Integrating with an Event Mesh"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Seamless Communication"}),": Agent Mesh can subscribe to and publish events across the entire event mesh"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Event-Driven Automation"}),": Intelligent event processing based on patterns and AI-driven insights"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Scalability"}),": Agent Mesh can dynamically participate in large-scale event-driven systems"]}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"The Event Mesh Gateway connects Agent Mesh to your existing event mesh infrastructure. Through its asynchronous interfaces, applications within your event mesh can seamlessly access and utilize Agent Mesh capabilities."}),"\n",(0,s.jsx)(n.p,{children:"This tutorial shows you how to build an Event Mesh Gateway that automatically generates and adds concise summaries to Jira bug reports, making them easier to understand at a glance."}),"\n",(0,s.jsx)(n.h2,{id:"prerequisites",children:"Prerequisites"}),"\n",(0,s.jsx)(n.p,{children:"This tutorial assumes you have an existing Jira application integrated with your event mesh that:"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:['Publishes a "jira_created" event to topic ',(0,s.jsx)(n.code,{children:"jira/issue/created/<jira_id>"})," when a new Jira issue is created"]}),"\n",(0,s.jsxs)(n.li,{children:['Listens for "jira_update" events on topic ',(0,s.jsx)(n.code,{children:"jira/issue/update"})," to update existing issues"]}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"Create an Event Mesh Gateway that:"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsx)(n.li,{children:"Monitors for new Jira issues"}),"\n",(0,s.jsx)(n.li,{children:"Automatically generates a concise summary"}),"\n",(0,s.jsx)(n.li,{children:"Creates an event to update the original Jira issue with this summary"}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"This creates a streamlined workflow where bug reports are automatically enhanced with clear, AI-generated summaries."}),"\n",(0,s.jsx)(n.h2,{id:"setting-up-the-environment",children:"Setting Up the Environment"}),"\n",(0,s.jsxs)(n.p,{children:["First, you need to ",(0,s.jsx)(n.a,{href:"/solace-agent-mesh/docs/documentation/installing-and-configuring/installation",children:"install Agent Mesh and the Agent Mesh CLI"}),", and then ",(0,s.jsx)(n.a,{href:"/solace-agent-mesh/docs/documentation/installing-and-configuring/run-project",children:"create a new Agent Mesh project"}),"."]}),"\n",(0,s.jsxs)(n.p,{children:["For this tutorial, you need to create or use an existing ",(0,s.jsx)(n.a,{href:"https://solace.com/products/event-broker/",children:"Solace Event Broker"})," or ",(0,s.jsx)(n.a,{href:"https://solace.com/solutions/initiative/event-mesh/",children:"event mesh"})," created using Solace event brokers."]}),"\n",(0,s.jsx)(n.h2,{id:"adding-the-event-mesh-gateway-plugin",children:"Adding the Event Mesh Gateway Plugin"}),"\n",(0,s.jsx)(n.p,{children:"Once you have your project set up, add the Event Mesh Gateway plugin:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-sh",children:"sam plugin add jira-event-mesh --plugin sam-event-mesh-gateway\n"})}),"\n",(0,s.jsxs)(n.p,{children:["You can use any name for your agent, in this tutorial we use ",(0,s.jsx)(n.code,{children:"jira-event-mesh"}),"."]}),"\n",(0,s.jsx)(n.p,{children:"This command:"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["Installs the ",(0,s.jsx)(n.code,{children:"sam-event-mesh-gateway"})," plugin"]}),"\n",(0,s.jsxs)(n.li,{children:["Creates a new gateway configuration named ",(0,s.jsx)(n.code,{children:"jira-event-mesh"})," in your ",(0,s.jsx)(n.code,{children:"configs/gateways/"})," directory"]}),"\n"]}),"\n",(0,s.jsx)(n.h4,{id:"configuring-the-event-mesh-gateway",children:"Configuring the Event Mesh Gateway"}),"\n",(0,s.jsxs)(n.p,{children:["After adding the plugin, you can see a new configuration file in ",(0,s.jsx)(n.code,{children:"configs/gateways/jira-event-mesh.yaml"}),". This file contains the gateway configuration that needs to be customized for your Jira integration use case."]}),"\n",(0,s.jsx)(n.h4,{id:"environment-variables",children:"Environment Variables"}),"\n",(0,s.jsx)(n.p,{children:"First, set up the required environment variables for the data plane connection:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-sh",children:'# Data plane Solace broker connection (can be same or different from control plane)\nexport JIRA_EVENT_MESH_SOLACE_BROKER_URL="ws://localhost:8008"\nexport JIRA_EVENT_MESH_SOLACE_BROKER_VPN="default"\nexport JIRA_EVENT_MESH_SOLACE_BROKER_USERNAME="default"\nexport JIRA_EVENT_MESH_SOLACE_BROKER_PASSWORD="default"\n'})}),"\n",(0,s.jsx)(n.h3,{id:"gateway-configuration",children:"Gateway Configuration"}),"\n",(0,s.jsx)(n.p,{children:"The main configuration includes several key sections:"}),"\n",(0,s.jsx)(n.h4,{id:"event-handlers",children:"Event Handlers"}),"\n",(0,s.jsx)(n.p,{children:"Configure the event handler to listen for new Jira issues and generate summaries:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:'event_handlers:\n - name: "jira_issue_handler"\n subscriptions:\n - topic: "jira/issue/created/>"\n qos: 1\n input_expression: "template:Create a concise summary for the newly created Jira issue: Title: {{text://input.payload:title}}, Body: {{text://input.payload:body}}, ID: {{text://input.payload:id}}. Return a JSON object with fields \'id\', \'type\' (value should be \'summary\'), and \'summary\'."\n payload_encoding: "utf-8"\n payload_format: "json"\n target_agent_name: "OrchestratorAgent"\n on_success: "jira_summary_handler"\n on_error: "error_response_handler"\n forward_context:\n jira_id: "input.payload:id"\n correlation_id: "input.user_properties:correlation_id"\n'})}),"\n",(0,s.jsx)(n.h4,{id:"output-handlers",children:"Output Handlers"}),"\n",(0,s.jsx)(n.p,{children:"Configure output handlers to publish the summary back to the event mesh:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:'output_handlers:\n - name: "jira_summary_handler"\n topic_expression: "static:jira/issue/update"\n payload_expression: "task_response:text"\n payload_encoding: "utf-8"\n payload_format: "json"\n \n - name: "error_response_handler"\n topic_expression: "template:jira/issue/error/{{text://user_data.forward_context:jira_id}}"\n payload_expression: "task_response:a2a_task_response.error"\n payload_encoding: "utf-8"\n payload_format: "json"\n'})}),"\n",(0,s.jsx)(n.h3,{id:"complete-configuration-example",children:"Complete Configuration Example"}),"\n",(0,s.jsx)(n.p,{children:"Here is a complete configuration file based on the plugin template:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:'log:\n stdout_log_level: INFO\n log_file_level: DEBUG\n log_file: jira-event-mesh.log\n\n!include ../shared_config.yaml\n\napps:\n - name: jira-event-mesh-app\n app_module: sam_event_mesh_gateway.app\n broker:\n <<: *broker_connection\n\n app_config:\n namespace: ${NAMESPACE}\n gateway_id: "jira-event-mesh-gw-01"\n artifact_service: *default_artifact_service\n default_user_identity: "anonymous_event_mesh_user" # If no identity from event\n\n\n\n # Data plane connection\n event_mesh_broker_config:\n broker_url: ${JIRA_EVENT_MESH_SOLACE_BROKER_URL}\n broker_vpn: ${JIRA_EVENT_MESH_SOLACE_BROKER_VPN}\n broker_username: ${JIRA_EVENT_MESH_SOLACE_BROKER_USERNAME}\n broker_password: ${JIRA_EVENT_MESH_SOLACE_BROKER_PASSWORD}\n\n event_handlers:\n - name: "jira_issue_handler"\n subscriptions:\n - topic: "jira/issue/created/>"\n qos: 1\n input_expression: "template:Create a concise summary for the newly created Jira issue: Title: {{text://input.payload:title}}, Body: {{text://input.payload:body}}, ID: {{text://input.payload:id}}. Return a JSON object with fields \'id\', \'type\' (value should be \'summary\'), and \'summary\'."\n payload_encoding: "utf-8"\n payload_format: "json"\n target_agent_name: "OrchestratorAgent"\n on_success: "jira_summary_handler"\n on_error: "error_response_handler"\n forward_context:\n jira_id: "input.payload:id"\n\n output_handlers:\n - name: "jira_summary_handler"\n topic_expression: "static:jira/issue/update"\n payload_expression: "task_response:text"\n payload_encoding: "utf-8"\n payload_format: "json"\n \n - name: "error_response_handler"\n topic_expression: "template:jira/issue/error/{{text://user_data.forward_context:jira_id}}"\n payload_expression: "task_response:a2a_task_response.error"\n payload_encoding: "utf-8"\n payload_format: "json"\n'})}),"\n",(0,s.jsx)(n.h2,{id:"running-the-event-mesh-gateway",children:"Running the Event Mesh Gateway"}),"\n",(0,s.jsx)(n.p,{children:"Now you can run the Event Mesh Gateway:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-sh",children:"sam run configs/gateways/jira-event-mesh.yaml\n"})}),"\n",(0,s.jsx)(n.p,{children:"The gateway:"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsx)(n.li,{children:"Connects to both the A2A control plane and the data plane event mesh"}),"\n",(0,s.jsx)(n.li,{children:"Subscribes to the configured topics on the data plane"}),"\n",(0,s.jsx)(n.li,{children:"Starts processing incoming events and routing them to agents"}),"\n"]}),"\n",(0,s.jsx)(n.h2,{id:"testing-the-event-mesh-gateway",children:"Testing the Event Mesh Gateway"}),"\n",(0,s.jsx)(n.p,{children:"Now that the system is running, let's test the Event Mesh Gateway."}),"\n",(0,s.jsx)(n.h3,{id:"using-the-solace-broker-manager",children:"Using The Solace Broker Manager"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["Open the ",(0,s.jsx)(n.strong,{children:"Try Me!"})," tab of the ",(0,s.jsx)(n.a,{href:"https://docs.solace.com/Admin/Broker-Manager/PubSub-Manager-Overview.htm",children:"Solace Broker Manager"})]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:["Connect both the ",(0,s.jsx)(n.strong,{children:"Publisher"})," and ",(0,s.jsx)(n.strong,{children:"Subscriber"})," panels by clicking their respective ",(0,s.jsx)(n.strong,{children:"Connect"})," buttons"]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"In the Subscriber panel:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["Enter ",(0,s.jsx)(n.code,{children:"jira/issue/update"})," in the ",(0,s.jsx)(n.code,{children:"Topic Subscriber"})," field"]}),"\n",(0,s.jsxs)(n.li,{children:["Click ",(0,s.jsx)(n.code,{children:"Subscribe"})]}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"In the Publisher panel:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["Use the topic ",(0,s.jsx)(n.code,{children:"jira/issue/created/JIRA-143321"})]}),"\n",(0,s.jsxs)(n.li,{children:["In the ",(0,s.jsx)(n.code,{children:"Message Content"})," field, enter:"]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-json",children:'{\n "id": "JIRA-143321",\n "title": "Exception when reading customer record",\n "body": "I got a DatabaseReadException when trying to get the data for customer ABC. The error indicated that the customer didn\'t exist, while they are our biggest customer!"\n}\n'})}),"\n",(0,s.jsxs)(n.ol,{start:"5",children:["\n",(0,s.jsxs)(n.li,{children:["Click ",(0,s.jsx)(n.strong,{children:"Publish"})]}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["After a few seconds, you can see a new message in the ",(0,s.jsx)(n.strong,{children:"Subscriber"})," messages with the topic ",(0,s.jsx)(n.code,{children:"jira/issue/update"})," and a body similar to:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-json",children:'{\n "id": "JIRA-143321",\n "type": "summary",\n "summary": "Database read error: Unable to retrieve record for key customer ABC despite confirmed existence"\n}\n'})}),"\n",(0,s.jsx)(n.h2,{id:"advanced-features",children:"Advanced Features"}),"\n",(0,s.jsx)(n.p,{children:"The Event Mesh Gateway supports several advanced features:"}),"\n",(0,s.jsx)(n.h3,{id:"artifact-processing",children:"Artifact Processing"}),"\n",(0,s.jsx)(n.p,{children:"You can configure the gateway to automatically create artifacts from incoming message payloads before sending them to agents. This is useful for processing files, images, or other binary data embedded in events."}),"\n",(0,s.jsx)(n.h3,{id:"dynamic-agent-routing",children:"Dynamic Agent Routing"}),"\n",(0,s.jsxs)(n.p,{children:["Instead of using a static ",(0,s.jsx)(n.code,{children:"target_agent_name"}),", you can use ",(0,s.jsx)(n.code,{children:"target_agent_name_expression"})," to dynamically determine which agent should process each event based on the message content."]}),"\n",(0,s.jsx)(n.h3,{id:"context-forwarding",children:"Context Forwarding"}),"\n",(0,s.jsxs)(n.p,{children:["The ",(0,s.jsx)(n.code,{children:"forward_context"})," configuration allows you to extract data from incoming messages and make it available when generating outgoing responses, enabling request-reply patterns and correlation tracking."]}),"\n",(0,s.jsx)(n.h3,{id:"error-handling",children:"Error Handling"}),"\n",(0,s.jsx)(n.p,{children:"Configure separate output handlers for success and error scenarios to ensure proper error reporting and system monitoring."})]})}function h(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(c,{...e})}):c(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>r,x:()=>o});var a=t(6540);const s={},i=a.createContext(s);function r(e){const n=a.useContext(i);return a.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),a.createElement(i.Provider,{value:n},e.children)}}}]);
@@ -0,0 +1 @@
1
+ "use strict";(self.webpackChunksolace_agenitc_mesh_docs=self.webpackChunksolace_agenitc_mesh_docs||[]).push([[3478],{2467:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>r,contentTitle:()=>l,default:()=>h,frontMatter:()=>i,metadata:()=>s,toc:()=>c});const s=JSON.parse('{"id":"documentation/developing/evaluations","title":"Evaluating Agents","description":"The framework includes an evaluation system that helps you test your agents\' behavior in a structured way. You can define test suites, run them against your agents, and generate detailed reports to analyze the results. When running evaluations locally, you can also benchmark different language models to see how they affect your agents\' responses.","source":"@site/docs/documentation/developing/evaluations.md","sourceDirName":"documentation/developing","slug":"/documentation/developing/evaluations","permalink":"/solace-agent-mesh/docs/documentation/developing/evaluations","draft":false,"unlisted":false,"editUrl":"https://github.com/SolaceLabs/solace-agent-mesh/edit/main/docs/docs/documentation/developing/evaluations.md","tags":[],"version":"current","sidebarPosition":450,"frontMatter":{"title":"Evaluating Agents","sidebar_position":450},"sidebar":"docSidebar","previous":{"title":"Creating Service Providers","permalink":"/solace-agent-mesh/docs/documentation/developing/creating-service-providers"},"next":{"title":"Build Your Own Agent","permalink":"/solace-agent-mesh/docs/documentation/developing/tutorials/custom-agent"}}');var a=t(4848),o=t(8453);const i={title:"Evaluating Agents",sidebar_position:450},l="Evaluating Agents",r={},c=[{value:"Creating a Test Case",id:"creating-a-test-case",level:2},{value:"Test Case Configuration",id:"test-case-configuration",level:3},{value:"Test Case Examples",id:"test-case-examples",level:3},{value:"Creating a Test Suite",id:"creating-a-test-suite",level:2},{value:"Local Evaluation",id:"local-evaluation",level:3},{value:"Local Test Suite Configuration",id:"local-test-suite-configuration",level:4},{value:"Example Local Test Suite",id:"example-local-test-suite",level:4},{value:"Remote Evaluation",id:"remote-evaluation",level:3},{value:"Remote Test Suite Configuration",id:"remote-test-suite-configuration",level:4},{value:"Example Remote Test Suite",id:"example-remote-test-suite",level:4},{value:"Evaluation Settings",id:"evaluation-settings",level:2},{value:"<code>tool_match</code>",id:"tool_match",level:3},{value:"<code>response_match</code>",id:"response_match",level:3},{value:"<code>llm_evaluator</code>",id:"llm_evaluator",level:3},{value:"Running Evaluations",id:"running-evaluations",level:2},{value:"Command",id:"command",level:3},{value:"Options",id:"options",level:3},{value:"Example",id:"example",level:3},{value:"Interpreting the Results",id:"interpreting-the-results",level:2},{value:"Results Directory",id:"results-directory",level:3},{value:"HTML Report",id:"html-report",level:3}];function d(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",header:"header",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,o.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.header,{children:(0,a.jsx)(n.h1,{id:"evaluating-agents",children:"Evaluating Agents"})}),"\n",(0,a.jsx)(n.p,{children:"The framework includes an evaluation system that helps you test your agents' behavior in a structured way. You can define test suites, run them against your agents, and generate detailed reports to analyze the results. When running evaluations locally, you can also benchmark different language models to see how they affect your agents' responses."}),"\n",(0,a.jsx)(n.p,{children:"At a high level, the evaluation process involves three main components:"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.strong,{children:"Test Case"}),": A ",(0,a.jsx)(n.code,{children:"JSON"})," file that defines a single, specific task for an agent to perform. It includes the initial prompt, any required files (artifacts), and the criteria for a successful outcome."]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.strong,{children:"Test Suite"}),": A ",(0,a.jsx)(n.code,{children:"JSON"})," file that groups one or more test cases into a single evaluation run. It also defines the environment for the evaluation, such as whether to run the agents locally or connect to a remote Agent Mesh."]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.strong,{children:"Evaluation Settings"}),": A configuration block within the test suite that specifies how to score the agent's performance. You can choose from several methods, from simple metric-based comparisons to more advanced evaluations using a language model."]}),"\n"]}),"\n",(0,a.jsx)(n.p,{children:"This document guides you through creating test cases, assembling them into test suites, and running evaluations to test your agents."}),"\n",(0,a.jsx)(n.h2,{id:"creating-a-test-case",children:"Creating a Test Case"}),"\n",(0,a.jsxs)(n.p,{children:["A test case is a ",(0,a.jsx)(n.code,{children:"JSON"})," file that defines a specific task for an agent to perform. It serves as the fundamental building block of an evaluation. You create a test case to represent a single interaction you want to test, such as asking a question, providing a file for processing, or requesting a specific action from an agent."]}),"\n",(0,a.jsx)(n.h3,{id:"test-case-configuration",children:"Test Case Configuration"}),"\n",(0,a.jsxs)(n.p,{children:["The following fields are available in the test case ",(0,a.jsx)(n.code,{children:"JSON"})," file."]}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"test_case_id"})," (Required): A unique identifier for the test case."]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"query"})," (Required): The initial prompt to be sent to the agent."]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"target_agent"})," (Required): The name of the agent to which the query should be sent."]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"category"})," (Optional): The category of the test case. Defaults to ",(0,a.jsx)(n.code,{children:"Other"}),"."]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"description"})," (Optional): A description of the test case."]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"artifacts"})," (Optional): A list of artifacts to be sent with the initial query. Each artifact has a ",(0,a.jsx)(n.code,{children:"type"})," and a ",(0,a.jsx)(n.code,{children:"path"}),"."]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"wait_time"})," (Optional): The maximum time in seconds to wait for a response from the agent. Defaults to ",(0,a.jsx)(n.code,{children:"60"}),"."]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"evaluation"})," (Optional): The evaluation criteria for the test case.","\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"expected_tools"})," (Optional): A list of tools that the agent is expected to use. Defaults to an empty list."]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"expected_response"})," (Optional): The expected final response from the agent. Defaults to an empty string."]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"criterion"})," (Optional): The criterion to be used by the ",(0,a.jsx)(n.code,{children:"llm_evaluator"}),". Defaults to an empty string."]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,a.jsx)(n.h3,{id:"test-case-examples",children:"Test Case Examples"}),"\n",(0,a.jsx)(n.p,{children:"Here is an example of a simple test case. It sends a greeting to an agent and checks for a standard response."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-json",children:'{\n "test_case_id": "hello_world",\n "category": "Content Generation",\n "description": "A simple test case to check the basic functionality of the system.",\n "query": "Hello, world!",\n "target_agent": "OrchestratorAgent",\n "wait_time": 30,\n "evaluation": {\n "expected_tools": [],\n "expected_response": "Hello! How can I help you today?",\n "criterion": "Evaluate if the agent provides a standard greeting."\n }\n}\n'})}),"\n",(0,a.jsxs)(n.p,{children:["This next example shows a more complex test case. It includes a ",(0,a.jsx)(n.code,{children:"CSV"})," file as an artifact and asks the agent to filter the data in the file."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-json",children:'{\n "test_case_id": "filter_csv_employees_by_age_and_country",\n "category": "Tool Usage",\n "description": "A test case to filter employees from a CSV file based on age and country.",\n "target_agent": "OrchestratorAgent",\n "query": "From the attached CSV, please list the names of all people who are older or equal to 30 and live in the USA.",\n "artifacts": [\n {\n "type": "file",\n "path": "artifacts/sample.csv"\n }\n ],\n "wait_time": 120,\n "evaluation": {\n "expected_tools": ["extract_content_from_artifact"],\n "expected_response": "The person who is 30 or older and lives in the USA is John Doe.",\n "criterion": "Evaluate if the agent correctly filters the CSV data."\n }\n}\n'})}),"\n",(0,a.jsx)(n.h2,{id:"creating-a-test-suite",children:"Creating a Test Suite"}),"\n",(0,a.jsxs)(n.p,{children:["The test suite is a ",(0,a.jsx)(n.code,{children:"JSON"})," file that defines the parameters of an evaluation run. You use it to group test cases and configure the environment in which they run."]}),"\n",(0,a.jsxs)(n.p,{children:["A common convention in the test suite configuration is to use keys ending with ",(0,a.jsx)(n.code,{children:"_VAR"}),". These keys indicate that the corresponding value is the name of an environment variable from which the framework should read the actual value. This practice helps you keep sensitive information\u2014like API keys and credentials\u2014out of your configuration files. This convention applies to the ",(0,a.jsx)(n.code,{children:"broker"})," object, the ",(0,a.jsx)(n.code,{children:"env"})," object within ",(0,a.jsx)(n.code,{children:"llm_models"}),", and the ",(0,a.jsx)(n.code,{children:"env"})," object within the ",(0,a.jsx)(n.code,{children:"llm_evaluator"})," in ",(0,a.jsx)(n.code,{children:"evaluation_settings"}),"."]}),"\n",(0,a.jsx)(n.p,{children:"You can run evaluations in two modes: local and remote. Both modes require a connection to a Solace event broker to function."}),"\n",(0,a.jsx)(n.h3,{id:"local-evaluation",children:"Local Evaluation"}),"\n",(0,a.jsx)(n.p,{children:"In a local evaluation, the evaluation framework brings up a local instance of Solace Agent Mesh (SAM) and runs the agents on your local machine. This mode is useful for development and testing because it allows you to iterate quickly on your agents and test cases. You can also use this mode to benchmark different language models against your agents to see how they perform."}),"\n",(0,a.jsxs)(n.p,{children:["To run a local evaluation, you need to install the ",(0,a.jsx)(n.code,{children:"sam-rest-gateway"})," plugin. This plugin allows the evaluation framework to communicate with the local SAM instance. You can install it with the following command:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:'pip install "sam-rest-gateway @ git+https://github.com/SolaceLabs/solace-agent-mesh-core-plugins#subdirectory=sam-rest-gateway"\n'})}),"\n",(0,a.jsx)(n.h4,{id:"local-test-suite-configuration",children:"Local Test Suite Configuration"}),"\n",(0,a.jsxs)(n.p,{children:["For a local evaluation, you must define the ",(0,a.jsx)(n.code,{children:"agents"}),", ",(0,a.jsx)(n.code,{children:"broker"}),", ",(0,a.jsx)(n.code,{children:"llm_models"}),", and ",(0,a.jsx)(n.code,{children:"test_cases"})," fields."]}),"\n",(0,a.jsxs)(n.p,{children:["The ",(0,a.jsx)(n.code,{children:"agents"})," field is a required list of paths to the agent configuration files. You must specify at least one agent."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-json",children:'"agents": [ "examples/agents/a2a_agents_example.yaml" ]\n'})}),"\n",(0,a.jsxs)(n.p,{children:["The ",(0,a.jsx)(n.code,{children:"broker"})," field is a required object containing the connection details for the Solace event broker."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-json",children:'"broker": {\n "SOLACE_BROKER_URL_VAR": "SOLACE_BROKER_URL",\n "SOLACE_BROKER_USERNAME_VAR": "SOLACE_BROKER_USERNAME",\n "SOLACE_BROKER_PASSWORD_VAR": "SOLACE_BROKER_PASSWORD",\n "SOLACE_BROKER_VPN_VAR": "SOLACE_BROKER_VPN"\n}\n'})}),"\n",(0,a.jsxs)(n.p,{children:["The ",(0,a.jsx)(n.code,{children:"llm_models"})," field is a required list of language models to use. You must specify at least one model. The ",(0,a.jsx)(n.code,{children:"env"})," object contains environment variables required by the model, such as the model name, endpoint, and API key."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-json",children:'"llm_models": [\n {\n "name": "gpt-4-1",\n "env": {\n "LLM_SERVICE_PLANNING_MODEL_NAME": "openai/azure-gpt-4-1",\n "LLM_SERVICE_ENDPOINT_VAR": "LLM_SERVICE_ENDPOINT",\n "LLM_SERVICE_API_KEY_VAR": "LLM_SERVICE_API_KEY"\n }\n },\n {\n "name": "gemini-1.5-pro",\n "env": {\n "LLM_SERVICE_PLANNING_MODEL_NAME": "google/gemini-1.5-pro-latest",\n "LLM_SERVICE_ENDPOINT_VAR": "LLM_SERVICE_ENDPOINT_GOOGLE",\n "LLM_SERVICE_API_KEY_VAR": "LLM_SERVICE_API_KEY_GOOGLE"\n }\n }\n]\n'})}),"\n",(0,a.jsxs)(n.p,{children:["The ",(0,a.jsx)(n.code,{children:"test_cases"})," field is a required list of paths to the test case ",(0,a.jsx)(n.code,{children:"JSON"})," files. You must specify at least one test case."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-json",children:'"test_cases": [ "tests/evaluation/test_cases/hello_world.test.json" ]\n'})}),"\n",(0,a.jsxs)(n.p,{children:["You can also provide optional settings for ",(0,a.jsx)(n.code,{children:"results_dir_name"}),", ",(0,a.jsx)(n.code,{children:"runs"}),", ",(0,a.jsx)(n.code,{children:"workers"}),", and ",(0,a.jsx)(n.code,{children:"evaluation_settings"}),"."]}),"\n",(0,a.jsxs)(n.p,{children:["The ",(0,a.jsx)(n.code,{children:"results_dir_name"})," field is an optional string that specifies the name of the directory for evaluation results. It defaults to ",(0,a.jsx)(n.code,{children:"tests"}),"."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-json",children:'"results_dir_name": "my-local-test-results"\n'})}),"\n",(0,a.jsxs)(n.p,{children:["The ",(0,a.jsx)(n.code,{children:"runs"})," field is an optional integer that specifies the number of times to run each test case. It defaults to ",(0,a.jsx)(n.code,{children:"1"}),"."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-json",children:'"runs": 3\n'})}),"\n",(0,a.jsxs)(n.p,{children:["The ",(0,a.jsx)(n.code,{children:"workers"})," field is an optional integer that specifies the number of parallel workers for running tests. It defaults to ",(0,a.jsx)(n.code,{children:"4"}),"."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-json",children:'"workers": 8\n'})}),"\n",(0,a.jsxs)(n.p,{children:["The ",(0,a.jsx)(n.code,{children:"evaluation_settings"})," field is an optional object that allows you to configure the evaluation. This object can contain ",(0,a.jsx)(n.code,{children:"tool_match"}),", ",(0,a.jsx)(n.code,{children:"response_match"}),", and ",(0,a.jsx)(n.code,{children:"llm_evaluator"})," settings."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-json",children:'"evaluation_settings": {\n "tool_match": {\n "enabled": true\n },\n "response_match": {\n "enabled": true\n },\n "llm_evaluator": {\n "enabled": true,\n "env": {\n "LLM_SERVICE_PLANNING_MODEL_NAME": "openai/gemini-2.5-pro",\n "LLM_SERVICE_ENDPOINT_VAR": "LLM_SERVICE_ENDPOINT",\n "LLM_SERVICE_API_KEY_VAR": "LLM_SERVICE_API_KEY"\n }\n }\n}\n'})}),"\n",(0,a.jsx)(n.h4,{id:"example-local-test-suite",children:"Example Local Test Suite"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-json",children:'{\n "agents": [\n "examples/agents/a2a_agents_example.yaml",\n "examples/agents/multimodal_example.yaml",\n "examples/agents/orchestrator_example.yaml"\n ],\n "broker": {\n "SOLACE_BROKER_URL_VAR": "SOLACE_BROKER_URL",\n "SOLACE_BROKER_USERNAME_VAR": "SOLACE_BROKER_USERNAME",\n "SOLACE_BROKER_PASSWORD_VAR": "SOLACE_BROKER_PASSWORD",\n "SOLACE_BROKER_VPN_VAR": "SOLACE_BROKER_VPN"\n },\n "llm_models": [\n {\n "name": "gpt-4-1",\n "env": {\n "LLM_SERVICE_PLANNING_MODEL_NAME": "openai/azure-gpt-4-1",\n "LLM_SERVICE_ENDPOINT_VAR": "LLM_SERVICE_ENDPOINT",\n "LLM_SERVICE_API_KEY_VAR": "LLM_SERVICE_API_KEY"\n }\n }\n ],\n "results_dir_name": "sam-local-eval-test",\n "runs": 3,\n "workers": 4,\n "test_cases": [\n "tests/evaluation/test_cases/filter_csv_employees_by_age_and_country.test.json",\n "tests/evaluation/test_cases/hello_world.test.json"\n ],\n "evaluation_settings": {\n "tool_match": {\n "enabled": true\n },\n "response_match": {\n "enabled": true\n },\n "llm_evaluator": {\n "enabled": true,\n "env": {\n "LLM_SERVICE_PLANNING_MODEL_NAME": "openai/gemini-2.5-pro",\n "LLM_SERVICE_ENDPOINT_VAR": "LLM_SERVICE_ENDPOINT",\n "LLM_SERVICE_API_KEY_VAR": "LLM_SERVICE_API_KEY"\n }\n }\n }\n}\n'})}),"\n",(0,a.jsx)(n.h3,{id:"remote-evaluation",children:"Remote Evaluation"}),"\n",(0,a.jsx)(n.p,{children:"In a remote evaluation, the evaluation framework sends requests to a remote Agent Mesh instance. This mode is useful for testing agents in a production-like environment where the agents are running on a separate server. The remote environment must have a REST gateway running to accept requests from the evaluation framework. You can also use an authentication token to communicate securely with the remote SAM instance."}),"\n",(0,a.jsx)(n.h4,{id:"remote-test-suite-configuration",children:"Remote Test Suite Configuration"}),"\n",(0,a.jsxs)(n.p,{children:["For a remote evaluation, you must define the ",(0,a.jsx)(n.code,{children:"broker"}),", ",(0,a.jsx)(n.code,{children:"remote"}),", and ",(0,a.jsx)(n.code,{children:"test_cases"})," fields."]}),"\n",(0,a.jsxs)(n.p,{children:["The ",(0,a.jsx)(n.code,{children:"broker"})," field is a required object with connection details for the Solace event broker."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-json",children:'"broker": {\n "SOLACE_BROKER_URL_VAR": "SOLACE_BROKER_URL",\n "SOLACE_BROKER_USERNAME_VAR": "SOLACE_BROKER_USERNAME",\n "SOLACE_BROKER_PASSWORD_VAR": "SOLACE_BROKER_PASSWORD",\n "SOLACE_BROKER_VPN_VAR": "SOLACE_BROKER_VPN"\n}\n'})}),"\n",(0,a.jsxs)(n.p,{children:["The ",(0,a.jsx)(n.code,{children:"remote"})," field is a required object containing the connection details for the remote Agent Mesh instance."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-json",children:'"remote": {\n "EVAL_REMOTE_URL_VAR": "EVAL_REMOTE_URL",\n "EVAL_AUTH_TOKEN_VAR": "EVAL_AUTH_TOKEN",\n "EVAL_NAMESPACE_VAR": "EVAL_NAMESPACE"\n}\n'})}),"\n",(0,a.jsxs)(n.p,{children:["The ",(0,a.jsx)(n.code,{children:"test_cases"})," field is a required list of paths to the test case ",(0,a.jsx)(n.code,{children:"JSON"})," files. You must specify at least one test case."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-json",children:'"test_cases": [ "tests/evaluation/test_cases/hello_world.test.json" ]\n'})}),"\n",(0,a.jsxs)(n.p,{children:["You can also provide optional settings for ",(0,a.jsx)(n.code,{children:"results_dir_name"}),", ",(0,a.jsx)(n.code,{children:"runs"}),", and ",(0,a.jsx)(n.code,{children:"evaluation_settings"}),"."]}),"\n",(0,a.jsxs)(n.p,{children:["The ",(0,a.jsx)(n.code,{children:"results_dir_name"})," field is an optional string that specifies the name of the directory for evaluation results. It defaults to ",(0,a.jsx)(n.code,{children:"tests"}),"."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-json",children:'"results_dir_name": "my-remote-test-results"\n'})}),"\n",(0,a.jsxs)(n.p,{children:["The ",(0,a.jsx)(n.code,{children:"runs"})," field is an optional integer that specifies the number of times to run each test case. It defaults to ",(0,a.jsx)(n.code,{children:"1"}),"."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-json",children:'"runs": 5\n'})}),"\n",(0,a.jsxs)(n.p,{children:["The ",(0,a.jsx)(n.code,{children:"evaluation_settings"})," field is an optional object that allows you to configure the evaluation."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-json",children:'"evaluation_settings": {\n "tool_match": {\n "enabled": true\n },\n "response_match": {\n "enabled": true\n }\n}\n'})}),"\n",(0,a.jsx)(n.h4,{id:"example-remote-test-suite",children:"Example Remote Test Suite"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-json",children:'{\n "broker": {\n "SOLACE_BROKER_URL_VAR": "SOLACE_BROKER_URL",\n "SOLACE_BROKER_USERNAME_VAR": "SOLACE_BROKER_USERNAME",\n "SOLACE_BROKER_PASSWORD_VAR": "SOLACE_BROKER_PASSWORD",\n "SOLACE_BROKER_VPN_VAR": "SOLACE_BROKER_VPN"\n },\n "remote": {\n "EVAL_REMOTE_URL_VAR": "EVAL_REMOTE_URL",\n "EVAL_AUTH_TOKEN_VAR": "EVAL_AUTH_TOKEN",\n "EVAL_NAMESPACE_VAR": "EVAL_NAMESPACE"\n },\n "results_dir_name": "sam-remote-eval-test",\n "runs": 1,\n "test_cases": [\n "tests/evaluation/test_cases/filter_csv_employees_by_age_and_country.test.json",\n "tests/evaluation/test_cases/hello_world.test.json"\n ],\n "evaluation_settings": {\n "tool_match": {\n "enabled": true\n },\n "response_match": {\n "enabled": true\n },\n "llm_evaluator": {\n "enabled": true,\n "env": {\n "LLM_SERVICE_PLANNING_MODEL_NAME": "openai/gemini-2.5-pro",\n "LLM_SERVICE_ENDPOINT_VAR": "LLM_SERVICE_ENDPOINT",\n "LLM_SERVICE_API_KEY_VAR": "LLM_SERVICE_API_KEY"\n }\n }\n }\n}\n'})}),"\n",(0,a.jsx)(n.h2,{id:"evaluation-settings",children:"Evaluation Settings"}),"\n",(0,a.jsxs)(n.p,{children:["The ",(0,a.jsx)(n.code,{children:"evaluation_settings"})," block in the test suite ",(0,a.jsx)(n.code,{children:"JSON"})," file allows you to configure how the evaluation is performed. Each enabled setting provides a score from 0 to 1, which contributes to the overall score for the test case."]}),"\n",(0,a.jsx)(n.h3,{id:"tool_match",children:(0,a.jsx)(n.code,{children:"tool_match"})}),"\n",(0,a.jsxs)(n.p,{children:["The ",(0,a.jsx)(n.code,{children:"tool_match"})," setting compares the tools the agent used with the ",(0,a.jsx)(n.code,{children:"expected_tools"})," defined in the test case. This is a simple, direct comparison and does not use a language model for the evaluation. It is most effective when the agent's expected behavior is straightforward and there is a clear, correct sequence of tools to be used. In more complex scenarios where multiple paths could lead to a successful outcome, this method may not be the best way to evaluate the agent's performance."]}),"\n",(0,a.jsx)(n.h3,{id:"response_match",children:(0,a.jsx)(n.code,{children:"response_match"})}),"\n",(0,a.jsxs)(n.p,{children:["The ",(0,a.jsx)(n.code,{children:"response_match"})," setting compares the agent's final response with the ",(0,a.jsx)(n.code,{children:"expected_response"})," from the test case. This comparison is based on the ROUGE metric, which evaluates the similarity between two responses by comparing their sequence of words. This method does not use a language model for the evaluation and does not work well with synonyms, so it is most effective when the expected answer is consistent. For more information about the ROUGE metric, see the ",(0,a.jsx)(n.a,{href:"https://pypi.org/project/rouge-metric/",children:"official documentation"}),"."]}),"\n",(0,a.jsx)(n.h3,{id:"llm_evaluator",children:(0,a.jsx)(n.code,{children:"llm_evaluator"})}),"\n",(0,a.jsxs)(n.p,{children:["The ",(0,a.jsx)(n.code,{children:"llm_evaluator"})," setting uses a language model to evaluate the entire lifecycle of a request within the agent mesh. This includes the initial prompt, all tool calls, delegation between agents, artifact inputs and outputs, and the final message output. The evaluation is based on a ",(0,a.jsx)(n.code,{children:"criterion"})," you provide in the test case, which defines what a successful outcome looks like. This is the most comprehensive evaluation method because it considers the full context of the request's execution."]}),"\n",(0,a.jsx)(n.h2,{id:"running-evaluations",children:"Running Evaluations"}),"\n",(0,a.jsxs)(n.p,{children:["After you create your test cases and test suite, you can run the evaluation from the command line using the ",(0,a.jsx)(n.code,{children:"sam eval"})," command."]}),"\n",(0,a.jsx)(n.h3,{id:"command",children:"Command"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"sam eval <PATH> [OPTIONS]\n"})}),"\n",(0,a.jsxs)(n.p,{children:["The command takes the path to the evaluation test suite ",(0,a.jsx)(n.code,{children:"JSON"})," file as a required argument."]}),"\n",(0,a.jsx)(n.h3,{id:"options",children:"Options"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"-v"}),", ",(0,a.jsx)(n.code,{children:"--verbose"}),": Enable verbose output to see detailed logs during the evaluation run."]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.code,{children:"-h"}),", ",(0,a.jsx)(n.code,{children:"--help"}),": Show a help message with information about the command and its options."]}),"\n"]}),"\n",(0,a.jsx)(n.h3,{id:"example",children:"Example"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"sam eval tests/evaluation/local_example.json --verbose\n"})}),"\n",(0,a.jsx)(n.h2,{id:"interpreting-the-results",children:"Interpreting the Results"}),"\n",(0,a.jsxs)(n.p,{children:["After an evaluation run is complete, the framework stores the results in a directory. The path to this directory is ",(0,a.jsx)(n.code,{children:"results/"})," followed by the ",(0,a.jsx)(n.code,{children:"results_dir_name"})," you specified in the test suite."]}),"\n",(0,a.jsx)(n.h3,{id:"results-directory",children:"Results Directory"}),"\n",(0,a.jsx)(n.p,{children:"The results directory has the following structure:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{children:"<results_dir_name>/\n\u251c\u2500\u2500 report.html\n\u251c\u2500\u2500 stats.json\n\u2514\u2500\u2500 <model_name>/\n \u251c\u2500\u2500 full_messages.json\n \u251c\u2500\u2500 results.json\n \u2514\u2500\u2500 <test_case_id>/\n \u2514\u2500\u2500 run_1/\n \u251c\u2500\u2500 messages.json\n \u251c\u2500\u2500 summary.json\n \u2514\u2500\u2500 test_case_info.json\n \u2514\u2500\u2500 run_2/\n \u251c\u2500\u2500 ...\n"})}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.strong,{children:(0,a.jsx)(n.code,{children:"report.html"})}),": An ",(0,a.jsx)(n.code,{children:"HTML"})," report that provides a comprehensive overview of the evaluation results. It includes a summary of the test runs, a breakdown of the results for each test case, and detailed logs for each test run. This report is the primary tool for analyzing the results of an evaluation."]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.strong,{children:(0,a.jsx)(n.code,{children:"stats.json"})}),": A ",(0,a.jsx)(n.code,{children:"JSON"})," file containing detailed statistics about the evaluation run, including scores for each evaluation metric."]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.strong,{children:(0,a.jsx)(n.code,{children:"<model_name>/"})}),": A directory for each language model tested (or a single ",(0,a.jsx)(n.code,{children:"remote"})," directory for remote evaluations).","\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.strong,{children:(0,a.jsx)(n.code,{children:"full_messages.json"})}),": A log of all messages exchanged during the evaluation for that model."]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.strong,{children:(0,a.jsx)(n.code,{children:"results.json"})}),": The raw evaluation results for each test case."]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.strong,{children:(0,a.jsx)(n.code,{children:"<test_case_id>/"})}),": A directory for each test case, containing a ",(0,a.jsx)(n.code,{children:"run_n"})," subdirectory for each run of the test case. These directories contain detailed logs and artifacts for each run."]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,a.jsx)(n.h3,{id:"html-report",children:"HTML Report"}),"\n",(0,a.jsxs)(n.p,{children:["The ",(0,a.jsx)(n.code,{children:"report.html"})," file provides a comprehensive overview of the evaluation results. It includes a summary of the test runs, a breakdown of the results for each test case, and detailed logs for each test run. This report is the primary tool for analyzing the results of an evaluation. You can open this file in a web browser to view the report."]})]})}function h(e={}){const{wrapper:n}={...(0,o.R)(),...e.components};return n?(0,a.jsx)(n,{...e,children:(0,a.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>i,x:()=>l});var s=t(6540);const a={},o=s.createContext(a);function i(e){const n=s.useContext(o);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(a):e.components||a:i(e.components),s.createElement(o.Provider,{value:n},e.children)}}}]);