solace-agent-mesh 1.3.2__py3-none-any.whl → 1.4.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

Files changed (136) hide show
  1. solace_agent_mesh/agent/adk/artifacts/filesystem_artifact_service.py +16 -8
  2. solace_agent_mesh/agent/adk/setup.py +183 -8
  3. solace_agent_mesh/agent/sac/app.py +337 -622
  4. solace_agent_mesh/agent/sac/component.py +47 -1
  5. solace_agent_mesh/agent/tools/dynamic_tool.py +36 -5
  6. solace_agent_mesh/agent/tools/tool_config_types.py +58 -0
  7. solace_agent_mesh/assets/docs/404.html +3 -3
  8. solace_agent_mesh/assets/docs/assets/js/0e682baa.da822665.js +1 -0
  9. solace_agent_mesh/assets/docs/assets/js/1023fc19.8a8a9309.js +1 -0
  10. solace_agent_mesh/assets/docs/assets/js/1523c6b4.2645ef68.js +1 -0
  11. solace_agent_mesh/assets/docs/assets/js/1c6e87d2.43771adc.js +1 -0
  12. solace_agent_mesh/assets/docs/assets/js/2a9cab12.2afaee76.js +1 -0
  13. solace_agent_mesh/assets/docs/assets/js/332e10b5.f7629851.js +1 -0
  14. solace_agent_mesh/assets/docs/assets/js/3d406171.5560fdf9.js +1 -0
  15. solace_agent_mesh/assets/docs/assets/js/42b3f8d8.508ae8db.js +1 -0
  16. solace_agent_mesh/assets/docs/assets/js/442a8107.b5c2532a.js +1 -0
  17. solace_agent_mesh/assets/docs/assets/js/483cef9a.8d318c2f.js +1 -0
  18. solace_agent_mesh/assets/docs/assets/js/55f47984.bcd00a86.js +1 -0
  19. solace_agent_mesh/assets/docs/assets/js/5b4258a4.dff11eca.js +1 -0
  20. solace_agent_mesh/assets/docs/assets/js/664b740a.ba305a89.js +1 -0
  21. solace_agent_mesh/assets/docs/assets/js/75384d09.abdf9cf9.js +1 -0
  22. solace_agent_mesh/assets/docs/assets/js/768e31b0.9abcdc48.js +1 -0
  23. solace_agent_mesh/assets/docs/assets/js/945fb41e.abf2be91.js +1 -0
  24. solace_agent_mesh/assets/docs/assets/js/9a09e75d.92de8cf5.js +1 -0
  25. solace_agent_mesh/assets/docs/assets/js/9eff14a2.d62aad71.js +1 -0
  26. solace_agent_mesh/assets/docs/assets/js/a3a92b25.1d029b81.js +1 -0
  27. solace_agent_mesh/assets/docs/assets/js/{aba87c2f.071e2d94.js → aba87c2f.4ddf32f2.js} +1 -1
  28. solace_agent_mesh/assets/docs/assets/js/ae0e903d.abca774a.js +1 -0
  29. solace_agent_mesh/assets/docs/assets/js/ae4415af.24cdc514.js +1 -0
  30. solace_agent_mesh/assets/docs/assets/js/bac0be12.27ee2c26.js +1 -0
  31. solace_agent_mesh/assets/docs/assets/js/c2c06897.87cb1f47.js +1 -0
  32. solace_agent_mesh/assets/docs/assets/js/c835a94d.ce21f0bf.js +1 -0
  33. solace_agent_mesh/assets/docs/assets/js/cc969b05.feef7dcc.js +1 -0
  34. solace_agent_mesh/assets/docs/assets/js/cd3d4052.a19e7d78.js +1 -0
  35. solace_agent_mesh/assets/docs/assets/js/{cee5d587.f5b73ca1.js → cee5d587.f1e1ca86.js} +1 -1
  36. solace_agent_mesh/assets/docs/assets/js/f284c35a.cad4dbf2.js +1 -0
  37. solace_agent_mesh/assets/docs/assets/js/f897a61a.bc634a3e.js +1 -0
  38. solace_agent_mesh/assets/docs/assets/js/{main.4adc477a.js → main.1de3da6a.js} +2 -2
  39. solace_agent_mesh/assets/docs/assets/js/runtime~main.3188e049.js +1 -0
  40. solace_agent_mesh/assets/docs/docs/documentation/Enterprise/installation/index.html +4 -4
  41. solace_agent_mesh/assets/docs/docs/documentation/Enterprise/single-sign-on/index.html +5 -5
  42. solace_agent_mesh/assets/docs/docs/documentation/Migrations/A2A Upgrade To 0.3.0/a2a-gateway-upgrade-to-0.3.0/index.html +6 -6
  43. solace_agent_mesh/assets/docs/docs/documentation/Migrations/A2A Upgrade To 0.3.0/a2a-technical-migration-map/index.html +6 -6
  44. solace_agent_mesh/assets/docs/docs/documentation/concepts/agents/index.html +6 -6
  45. solace_agent_mesh/assets/docs/docs/documentation/concepts/architecture/index.html +3 -3
  46. solace_agent_mesh/assets/docs/docs/documentation/concepts/cli/index.html +18 -18
  47. solace_agent_mesh/assets/docs/docs/documentation/concepts/gateways/index.html +3 -3
  48. solace_agent_mesh/assets/docs/docs/documentation/concepts/orchestrator/index.html +3 -3
  49. solace_agent_mesh/assets/docs/docs/documentation/concepts/plugins/index.html +10 -10
  50. solace_agent_mesh/assets/docs/docs/documentation/deployment/debugging/index.html +4 -4
  51. solace_agent_mesh/assets/docs/docs/documentation/deployment/deploy/index.html +3 -3
  52. solace_agent_mesh/assets/docs/docs/documentation/deployment/observability/index.html +3 -3
  53. solace_agent_mesh/assets/docs/docs/documentation/getting-started/component-overview/index.html +7 -7
  54. solace_agent_mesh/assets/docs/docs/documentation/getting-started/configurations/index.html +3 -3
  55. solace_agent_mesh/assets/docs/docs/documentation/getting-started/installation/index.html +9 -9
  56. solace_agent_mesh/assets/docs/docs/documentation/getting-started/introduction/index.html +6 -6
  57. solace_agent_mesh/assets/docs/docs/documentation/getting-started/quick-start/index.html +7 -7
  58. solace_agent_mesh/assets/docs/docs/documentation/tutorials/bedrock-agents/index.html +23 -23
  59. solace_agent_mesh/assets/docs/docs/documentation/tutorials/custom-agent/index.html +5 -5
  60. solace_agent_mesh/assets/docs/docs/documentation/tutorials/event-mesh-gateway/index.html +5 -5
  61. solace_agent_mesh/assets/docs/docs/documentation/tutorials/mcp-integration/index.html +4 -4
  62. solace_agent_mesh/assets/docs/docs/documentation/tutorials/mongodb-integration/index.html +9 -9
  63. solace_agent_mesh/assets/docs/docs/documentation/tutorials/rag-integration/index.html +10 -10
  64. solace_agent_mesh/assets/docs/docs/documentation/tutorials/rest-gateway/index.html +8 -8
  65. solace_agent_mesh/assets/docs/docs/documentation/tutorials/slack-integration/index.html +6 -6
  66. solace_agent_mesh/assets/docs/docs/documentation/tutorials/sql-database/index.html +9 -9
  67. solace_agent_mesh/assets/docs/docs/documentation/user-guide/builtin-tools/artifact-management/index.html +3 -3
  68. solace_agent_mesh/assets/docs/docs/documentation/user-guide/builtin-tools/audio-tools/index.html +5 -5
  69. solace_agent_mesh/assets/docs/docs/documentation/user-guide/builtin-tools/data-analysis-tools/index.html +5 -5
  70. solace_agent_mesh/assets/docs/docs/documentation/user-guide/builtin-tools/embeds/index.html +3 -3
  71. solace_agent_mesh/assets/docs/docs/documentation/user-guide/builtin-tools/index.html +5 -5
  72. solace_agent_mesh/assets/docs/docs/documentation/user-guide/create-agents/index.html +19 -19
  73. solace_agent_mesh/assets/docs/docs/documentation/user-guide/create-gateways/index.html +7 -7
  74. solace_agent_mesh/assets/docs/docs/documentation/user-guide/creating-python-tools/index.html +73 -8
  75. solace_agent_mesh/assets/docs/docs/documentation/user-guide/creating-service-providers/index.html +10 -10
  76. solace_agent_mesh/assets/docs/docs/documentation/user-guide/solace-ai-connector/index.html +3 -3
  77. solace_agent_mesh/assets/docs/docs/documentation/user-guide/structure/index.html +4 -4
  78. solace_agent_mesh/assets/docs/lunr-index-1757991496554.json +1 -0
  79. solace_agent_mesh/assets/docs/lunr-index.json +1 -1
  80. solace_agent_mesh/assets/docs/search-doc-1757991496554.json +1 -0
  81. solace_agent_mesh/assets/docs/search-doc.json +1 -1
  82. solace_agent_mesh/cli/__init__.py +1 -1
  83. solace_agent_mesh/cli/commands/run_cmd.py +4 -7
  84. solace_agent_mesh/client/webui/frontend/static/assets/{authCallback-CAX9u8a7.js → authCallback-j1LW-wlq.js} +1 -1
  85. solace_agent_mesh/client/webui/frontend/static/assets/{client-DXU9SPI5.js → client-B9p_nFNA.js} +1 -1
  86. solace_agent_mesh/client/webui/frontend/static/assets/main-B9s_V9tJ.css +1 -0
  87. solace_agent_mesh/client/webui/frontend/static/assets/main-Dq4AJNvn.js +339 -0
  88. solace_agent_mesh/client/webui/frontend/static/assets/{vendor-B0BEKoAR.js → vendor-CS5YMf8a.js} +74 -69
  89. solace_agent_mesh/client/webui/frontend/static/auth-callback.html +3 -3
  90. solace_agent_mesh/client/webui/frontend/static/index.html +4 -4
  91. solace_agent_mesh/common/utils/pydantic_utils.py +56 -0
  92. solace_agent_mesh/config_portal/backend/plugin_catalog/registry_manager.py +6 -4
  93. solace_agent_mesh/gateway/base/app.py +58 -120
  94. solace_agent_mesh/gateway/http_sse/app.py +99 -150
  95. solace_agent_mesh/gateway/http_sse/component.py +57 -30
  96. solace_agent_mesh/gateway/http_sse/sse_event_buffer.py +87 -0
  97. solace_agent_mesh/gateway/http_sse/sse_manager.py +44 -23
  98. {solace_agent_mesh-1.3.2.dist-info → solace_agent_mesh-1.4.0.dist-info}/METADATA +1 -1
  99. {solace_agent_mesh-1.3.2.dist-info → solace_agent_mesh-1.4.0.dist-info}/RECORD +103 -100
  100. solace_agent_mesh/assets/docs/assets/js/0e682baa.b3bbde9a.js +0 -1
  101. solace_agent_mesh/assets/docs/assets/js/1023fc19.364235d5.js +0 -1
  102. solace_agent_mesh/assets/docs/assets/js/1523c6b4.1b0ec6f9.js +0 -1
  103. solace_agent_mesh/assets/docs/assets/js/1c6e87d2.a8c5ce5a.js +0 -1
  104. solace_agent_mesh/assets/docs/assets/js/2a9cab12.8909df92.js +0 -1
  105. solace_agent_mesh/assets/docs/assets/js/332e10b5.7a103f42.js +0 -1
  106. solace_agent_mesh/assets/docs/assets/js/3d406171.0b9eeed1.js +0 -1
  107. solace_agent_mesh/assets/docs/assets/js/42b3f8d8.d97b8e94.js +0 -1
  108. solace_agent_mesh/assets/docs/assets/js/442a8107.b3159bb2.js +0 -1
  109. solace_agent_mesh/assets/docs/assets/js/483cef9a.03d5dceb.js +0 -1
  110. solace_agent_mesh/assets/docs/assets/js/55f47984.cf3781c4.js +0 -1
  111. solace_agent_mesh/assets/docs/assets/js/5b4258a4.0d080cd9.js +0 -1
  112. solace_agent_mesh/assets/docs/assets/js/664b740a.1b744a32.js +0 -1
  113. solace_agent_mesh/assets/docs/assets/js/75384d09.c193a8f0.js +0 -1
  114. solace_agent_mesh/assets/docs/assets/js/768e31b0.8b51cd70.js +0 -1
  115. solace_agent_mesh/assets/docs/assets/js/945fb41e.c63791d1.js +0 -1
  116. solace_agent_mesh/assets/docs/assets/js/9a09e75d.d6607c56.js +0 -1
  117. solace_agent_mesh/assets/docs/assets/js/9eff14a2.472b0310.js +0 -1
  118. solace_agent_mesh/assets/docs/assets/js/a3a92b25.4b7fa6a2.js +0 -1
  119. solace_agent_mesh/assets/docs/assets/js/ae0e903d.4d8dda10.js +0 -1
  120. solace_agent_mesh/assets/docs/assets/js/ae4415af.7a2f0bbf.js +0 -1
  121. solace_agent_mesh/assets/docs/assets/js/bac0be12.f50d9bac.js +0 -1
  122. solace_agent_mesh/assets/docs/assets/js/c2c06897.587b4af5.js +0 -1
  123. solace_agent_mesh/assets/docs/assets/js/c835a94d.146e3186.js +0 -1
  124. solace_agent_mesh/assets/docs/assets/js/cc969b05.bd3e0d6c.js +0 -1
  125. solace_agent_mesh/assets/docs/assets/js/cd3d4052.b6535013.js +0 -1
  126. solace_agent_mesh/assets/docs/assets/js/f284c35a.7334119c.js +0 -1
  127. solace_agent_mesh/assets/docs/assets/js/f897a61a.0aa29dbb.js +0 -1
  128. solace_agent_mesh/assets/docs/assets/js/runtime~main.cf0229ea.js +0 -1
  129. solace_agent_mesh/assets/docs/lunr-index-1757704179464.json +0 -1
  130. solace_agent_mesh/assets/docs/search-doc-1757704179464.json +0 -1
  131. solace_agent_mesh/client/webui/frontend/static/assets/main-C03yrETa.css +0 -1
  132. solace_agent_mesh/client/webui/frontend/static/assets/main-DjoMeldu.js +0 -339
  133. /solace_agent_mesh/assets/docs/assets/js/{main.4adc477a.js.LICENSE.txt → main.1de3da6a.js.LICENSE.txt} +0 -0
  134. {solace_agent_mesh-1.3.2.dist-info → solace_agent_mesh-1.4.0.dist-info}/WHEEL +0 -0
  135. {solace_agent_mesh-1.3.2.dist-info → solace_agent_mesh-1.4.0.dist-info}/entry_points.txt +0 -0
  136. {solace_agent_mesh-1.3.2.dist-info → solace_agent_mesh-1.4.0.dist-info}/licenses/LICENSE +0 -0
@@ -1 +0,0 @@
1
- "use strict";(self.webpackChunksolace_agenitc_mesh_docs=self.webpackChunksolace_agenitc_mesh_docs||[]).push([[5627],{5232:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>o,default:()=>_,frontMatter:()=>r,metadata:()=>a,toc:()=>c});const a=JSON.parse('{"id":"documentation/user-guide/create-gateways","title":"Create Gateways","description":"Gateways in Solace Agent Mesh (SAM) serve as bridges between external systems and the A2A (Agent-to-Agent) ecosystem. They enable your agents to receive information from and send responses to diverse external platforms like chat systems, web applications, IoT devices, APIs, and file systems.","source":"@site/docs/documentation/user-guide/create-gateways.md","sourceDirName":"documentation/user-guide","slug":"/documentation/user-guide/create-gateways","permalink":"/solace-agent-mesh/docs/documentation/user-guide/create-gateways","draft":false,"unlisted":false,"editUrl":"https://github.com/SolaceLabs/solace-agent-mesh/edit/main/docs/docs/documentation/user-guide/create-gateways.md","tags":[],"version":"current","sidebarPosition":40,"frontMatter":{"title":"Create Gateways","sidebar_position":40},"sidebar":"docSidebar","previous":{"title":"Creating Python Tools","permalink":"/solace-agent-mesh/docs/documentation/user-guide/creating-python-tools"},"next":{"title":"Creating Service Providers","permalink":"/solace-agent-mesh/docs/documentation/user-guide/creating-service-providers"}}');var i=t(4848),s=t(8453);const r={title:"Create Gateways",sidebar_position:40},o="Create Gateways",l={},c=[{value:"What Are Gateways?",id:"what-are-gateways",level:2},{value:"Quick Start: Creating Your First Gateway",id:"quick-start-creating-your-first-gateway",level:2},{value:"CLI Options",id:"cli-options",level:3},{value:"Gateway Architecture",id:"gateway-architecture",level:2},{value:"Gateway App",id:"gateway-app",level:3},{value:"Gateway Component",id:"gateway-component",level:3},{value:"Step-by-Step Tutorial",id:"step-by-step-tutorial",level:2},{value:"Step 1: Generate the Gateway Structure",id:"step-1-generate-the-gateway-structure",level:3},{value:"Step 2: Define Configuration Schema",id:"step-2-define-configuration-schema",level:3},{value:"Step 3: Implement Core Logic",id:"step-3-implement-core-logic",level:3},{value:"Step 4: Configure the Gateway",id:"step-4-configure-the-gateway",level:3},{value:"Step 5: Install Dependencies",id:"step-5-install-dependencies",level:3},{value:"Step 6: Run Your Gateway",id:"step-6-run-your-gateway",level:3},{value:"Advanced Gateway Patterns",id:"advanced-gateway-patterns",level:2},{value:"Authentication and Authorization",id:"authentication-and-authorization",level:3},{value:"File Handling with Artifacts",id:"file-handling-with-artifacts",level:3},{value:"Streaming Responses",id:"streaming-responses",level:3},{value:"Error Handling and Retry Logic",id:"error-handling-and-retry-logic",level:3},{value:"Best Practices",id:"best-practices",level:2},{value:"1. Configuration Management",id:"1-configuration-management",level:3},{value:"2. Error Handling",id:"2-error-handling",level:3},{value:"3. Security",id:"3-security",level:3},{value:"4. Performance",id:"4-performance",level:3},{value:"5. Monitoring and Logging",id:"5-monitoring-and-logging",level:3},{value:"Common Gateway Patterns",id:"common-gateway-patterns",level:2},{value:"HTTP/REST API Gateway",id:"httprest-api-gateway",level:3},{value:"WebSocket Gateway",id:"websocket-gateway",level:3},{value:"Message Queue Gateway",id:"message-queue-gateway",level:3},{value:"Packaging as a Plugin",id:"packaging-as-a-plugin",level:2},{value:"1. Create Plugin Structure",id:"1-create-plugin-structure",level:3},{value:"2. Configure <code>pyproject.toml</code>",id:"2-configure-pyprojecttoml",level:3},{value:"3. Build and Install",id:"3-build-and-install",level:3},{value:"Troubleshooting",id:"troubleshooting",level:2},{value:"Common Issues",id:"common-issues",level:3},{value:"Gateway Fails to Start",id:"gateway-fails-to-start",level:4},{value:"Tasks Not Reaching Agents",id:"tasks-not-reaching-agents",level:4},{value:"Authentication Failures",id:"authentication-failures",level:4},{value:"File/Artifact Issues",id:"fileartifact-issues",level:4},{value:"Debugging Tips",id:"debugging-tips",level:3}];function d(e){const n={admonition:"admonition",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,s.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.header,{children:(0,i.jsx)(n.h1,{id:"create-gateways",children:"Create Gateways"})}),"\n",(0,i.jsx)(n.p,{children:"Gateways in Solace Agent Mesh (SAM) serve as bridges between external systems and the A2A (Agent-to-Agent) ecosystem. They enable your agents to receive information from and send responses to diverse external platforms like chat systems, web applications, IoT devices, APIs, and file systems."}),"\n",(0,i.jsx)(n.p,{children:"This guide walks you through the steps of creating custom gateways, from basic concepts to advanced implementations."}),"\n",(0,i.jsx)(n.h2,{id:"what-are-gateways",children:"What Are Gateways?"}),"\n",(0,i.jsx)(n.p,{children:"A gateway acts as a translator and coordinator that:"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Receives"})," events, messages, or data from external systems"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Authenticates"})," and authorizes external interactions"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Translates"})," external data into standardized A2A ",(0,i.jsx)(n.code,{children:"Task"})," format"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Submits"})," tasks to target A2A agents for processing"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Receives"})," responses and status updates from agents"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Translates"})," A2A responses back to external system format"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Sends"})," results back to the originating external system"]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"quick-start-creating-your-first-gateway",children:"Quick Start: Creating Your First Gateway"}),"\n",(0,i.jsxs)(n.p,{children:["You can create a gateway directly using the SAM CLI ",(0,i.jsx)(n.code,{children:"sam add gateway"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"sam add gateway my-custom-gateway\n"})}),"\n",(0,i.jsx)(n.p,{children:"This command:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["Launches an interactive setup (or use ",(0,i.jsx)(n.code,{children:"--gui"})," for browser-based configuration)"]}),"\n",(0,i.jsx)(n.li,{children:"Generates the necessary files and configuration"}),"\n",(0,i.jsx)(n.li,{children:"Sets up the basic gateway structure"}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"cli-options",children:"CLI Options"}),"\n",(0,i.jsx)(n.p,{children:"You can customize the gateway creation with these options:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:'sam add gateway my-gateway \\\n --namespace "myorg/dev" \\\n --gateway-id "my-custom-gw-id" \\\n --artifact-service-type "filesystem" \\\n --artifact-service-base-path "var/data/my-gateway-artifacts" \\\n --system-purpose "This gateway processes external data feeds" \\\n --response-format "Agents should respond with structured JSON"\n'})}),"\n",(0,i.jsx)(n.p,{children:"For a complete list of options, run:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"sam add gateway --help\n"})}),"\n",(0,i.jsx)(n.h2,{id:"gateway-architecture",children:"Gateway Architecture"}),"\n",(0,i.jsx)(n.p,{children:"Every SAM gateway consists of two main components:"}),"\n",(0,i.jsx)(n.h3,{id:"gateway-app",children:"Gateway App"}),"\n",(0,i.jsxs)(n.p,{children:["Gateway App (",(0,i.jsx)(n.code,{children:"app.py"}),"):"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Defines configuration schema"}),"\n",(0,i.jsx)(n.li,{children:"Manages gateway-level settings"}),"\n",(0,i.jsx)(n.li,{children:"Links to the gateway component"}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"gateway-component",children:"Gateway Component"}),"\n",(0,i.jsxs)(n.p,{children:["Gateway Component (",(0,i.jsx)(n.code,{children:"component.py"}),"):"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Contains the core business logic"}),"\n",(0,i.jsx)(n.li,{children:"Handles external system integration"}),"\n",(0,i.jsx)(n.li,{children:"Implements required abstract methods"}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"step-by-step-tutorial",children:"Step-by-Step Tutorial"}),"\n",(0,i.jsxs)(n.p,{children:["Let's create a practical example, ",(0,i.jsx)(n.strong,{children:"Directory Monitor Gateway"}),", a gateway that monitors a directory for new files and sends them to agents for processing."]}),"\n",(0,i.jsxs)(n.p,{children:["You can create a gateway using either ",(0,i.jsx)(n.code,{children:"sam add gateway <your_gateway_name>"})," command directly or ",(0,i.jsx)(n.code,{children:"sam plugin create <your_gateway_plugin_name> --type gateway"})," command as gateway plugin."]}),"\n",(0,i.jsxs)(n.admonition,{title:"Gateway as plugin",type:"tip",children:[(0,i.jsx)(n.p,{children:"Gateways can also be implemented as plugins. This allows you to easily package your gateway logic and reuse it across different projects."}),(0,i.jsxs)(n.p,{children:["To create a plugin of type gateway, use the ",(0,i.jsx)(n.code,{children:"sam plugin create <your_gateway_plugin_name> --type gateway"})," command."]}),(0,i.jsx)(n.p,{children:"For a complete list of options, run:"}),(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"sam plugin create --help\n"})}),(0,i.jsxs)(n.p,{children:["To create a gateway instance based on a plugin, use the ",(0,i.jsx)(n.code,{children:"sam plugin add <your_gateway_name> --plugin <your_gateway_plugin>"})," command."]}),(0,i.jsx)(n.p,{children:"For a complete list of options, run:"}),(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"sam plugin add --help\n"})}),(0,i.jsx)(n.p,{children:"Although the specific directory structure may differ from standalone gateways, the core concepts remain the same. The core files remain the same: app.py, component.py, and the YAML configuration file."})]}),"\n",(0,i.jsx)(n.h3,{id:"step-1-generate-the-gateway-structure",children:"Step 1: Generate the Gateway Structure"}),"\n",(0,i.jsxs)(n.p,{children:["This tutorial shows you how to create a new gateway with the ",(0,i.jsx)(n.code,{children:"sam add gateway"})," command."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"sam add gateway dir-monitor\n"})}),"\n",(0,i.jsx)(n.p,{children:"This creates:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"configs/gateways/dir_monitor_config.yaml"})," - Configuration file"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"src/dir_monitor/app.py"})," - Gateway app class"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.code,{children:"src/dir_monitor/component.py"})," - Gateway component class"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"step-2-define-configuration-schema",children:"Step 2: Define Configuration Schema"}),"\n",(0,i.jsxs)(n.p,{children:["Define Configuration Schema (",(0,i.jsx)(n.code,{children:"app.py"}),")"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-python",children:'# src/dir_monitor/app.py\nfrom typing import Any, Dict, List, Type\nfrom solace_ai_connector.common.log import log\nfrom solace_agent_mesh.gateway.base.app import BaseGatewayApp\nfrom solace_agent_mesh.gateway.base.component import BaseGatewayComponent\nfrom .component import DirMonitorGatewayComponent\n\n# Module info required by SAC\ninfo = {\n "class_name": "DirMonitorGatewayApp",\n "description": "Custom App class for the A2A DirMonitor Gateway.",\n}\n\nclass DirMonitorGatewayApp(BaseGatewayApp):\n """\n Directory Monitor Gateway App\n Extends BaseGatewayApp with directory monitoring specific configuration.\n """\n\n # Define gateway-specific configuration parameters\n SPECIFIC_APP_SCHEMA_PARAMS: List[Dict[str, Any]] = [\n {\n "name": "directory_path",\n "required": True,\n "type": "string",\n "description": "The directory path to monitor for changes.",\n },\n {\n "name": "target_agent_name",\n "required": False,\n "type": "string",\n "default": "OrchestratorAgent",\n "description": "The A2A agent to send tasks to.",\n },\n {\n "name": "default_user_identity",\n "required": False,\n "type": "string",\n "default": "dir_monitor_user",\n "description": "Default user identity for A2A tasks.",\n },\n {\n "name": "error_directory_path",\n "required": True,\n "type": "string",\n "description": "Directory to move files if processing fails.",\n },\n ]\n\n def __init__(self, app_info: Dict[str, Any], **kwargs):\n log_prefix = app_info.get("name", "DirMonitorGatewayApp")\n log.info("[%s] Initializing Directory Monitor Gateway App...", log_prefix)\n super().__init__(app_info=app_info, **kwargs)\n log.info("[%s] Directory Monitor Gateway App initialized.", self.name)\n\n def _get_gateway_component_class(self) -> Type[BaseGatewayComponent]:\n """Returns the gateway component class for this app."""\n return DirMonitorGatewayComponent\n'})}),"\n",(0,i.jsx)(n.h3,{id:"step-3-implement-core-logic",children:"Step 3: Implement Core Logic"}),"\n",(0,i.jsxs)(n.p,{children:["Implement Core Logic (",(0,i.jsx)(n.code,{children:"component.py"}),")"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-python",children:'# src/dir_monitor/component.py\nimport asyncio\nimport os\nimport shutil\nimport mimetypes\nimport threading\nfrom typing import Any, Dict, List, Optional, Tuple, Union\nfrom datetime import datetime, timezone\n\nfrom solace_ai_connector.common.log import log\n\n# Import watchdog for file system monitoring\ntry:\n from watchdog.observers import Observer\n from watchdog.events import FileSystemEventHandler\n WATCHDOG_AVAILABLE = True\nexcept ImportError:\n WATCHDOG_AVAILABLE = False\n Observer = None\n FileSystemEventHandler = None\n\nfrom solace_agent_mesh.gateway.base.component import BaseGatewayComponent\nfrom solace_agent_mesh.common.types import (\n Part as A2APart,\n TextPart,\n FilePart,\n Task,\n TaskStatusUpdateEvent,\n TaskArtifactUpdateEvent,\n JSONRPCError,\n FileContent,\n)\nfrom solace_agent_mesh.agent.utils.artifact_helpers import save_artifact_with_metadata\n\n# Component info\ninfo = {\n "class_name": "DirMonitorGatewayComponent",\n "description": "Monitors directories for new files and processes them via A2A agents.",\n}\n\nclass DirMonitorGatewayComponent(BaseGatewayComponent):\n """\n Directory Monitor Gateway Component\n Watches a directory and creates A2A tasks for new files.\n """\n\n def __init__(self, **kwargs: Any):\n super().__init__(**kwargs)\n log.info("%s Initializing Directory Monitor Gateway Component...", self.log_identifier)\n\n # Check if watchdog is available\n if not WATCHDOG_AVAILABLE:\n log.error("%s Watchdog library not found. Install with: pip install watchdog", \n self.log_identifier)\n raise ImportError("Watchdog library required for directory monitoring")\n\n # Load configuration\n try:\n self.directory_path = self.get_config("directory_path")\n self.target_agent_name = self.get_config("target_agent_name", "OrchestratorAgent")\n self.default_user_identity_id = self.get_config("default_user_identity", "dir_monitor_user")\n self.error_directory_path = self.get_config("error_directory_path")\n\n # Validate directories\n if not os.path.isdir(self.directory_path):\n raise ValueError(f"Monitor directory not found: {self.directory_path}")\n \n os.makedirs(self.error_directory_path, exist_ok=True)\n log.info("%s Monitoring: %s, Error dir: %s", \n self.log_identifier, self.directory_path, self.error_directory_path)\n\n except Exception as e:\n log.error("%s Configuration error: %s", self.log_identifier, e)\n raise\n\n # Initialize monitoring components\n self.observer: Optional[Observer] = None\n self.watchdog_thread: Optional[threading.Thread] = None\n\n log.info("%s Directory Monitor Gateway Component initialized.", self.log_identifier)\n\n class DirWatchEventHandler(FileSystemEventHandler):\n """Handles file system events from Watchdog."""\n \n def __init__(self, component_ref: \'DirMonitorGatewayComponent\'):\n super().__init__()\n self.component_ref = component_ref\n self.log_identifier = f"{component_ref.log_identifier}[FileHandler]"\n\n def on_created(self, event):\n if event.is_directory:\n return\n\n file_path = event.src_path\n log.info("%s New file detected: %s", self.log_identifier, file_path)\n\n # Bridge to async loop\n if self.component_ref.async_loop and self.component_ref.async_loop.is_running():\n asyncio.run_coroutine_threadsafe(\n self.component_ref._process_new_file(file_path),\n self.component_ref.async_loop\n )\n else:\n log.error("%s Async loop not available for file: %s", \n self.log_identifier, file_path)\n\n def generate_uuid(self) -> str:\n """Generate a unique identifier."""\n import uuid\n return str(uuid.uuid4())\n\n def _start_listener(self) -> None:\n """Start the directory monitoring listener."""\n log_id_prefix = f"{self.log_identifier}[StartListener]"\n log.info("%s Starting directory monitor for: %s", log_id_prefix, self.directory_path)\n\n if not WATCHDOG_AVAILABLE:\n log.error("%s Watchdog not available", log_id_prefix)\n self.stop_signal.set()\n return\n\n # Set up file system observer\n self.observer = Observer()\n event_handler = self.DirWatchEventHandler(self)\n self.observer.schedule(event_handler, self.directory_path, recursive=False)\n\n # Start observer in separate thread\n self.watchdog_thread = threading.Thread(\n target=self._run_observer,\n name=f"{self.name}_WatchdogThread",\n daemon=True\n )\n self.watchdog_thread.start()\n log.info("%s Directory monitor started", log_id_prefix)\n\n def _run_observer(self):\n """Run the watchdog observer."""\n if not self.observer:\n return\n \n log_id_prefix = f"{self.log_identifier}[Observer]"\n try:\n log.info("%s Starting file system observer...", log_id_prefix)\n self.observer.start()\n \n # Wait for stop signal\n while not self.stop_signal.is_set() and self.observer.is_alive():\n self.stop_signal.wait(timeout=1)\n \n log.info("%s Observer loop exiting", log_id_prefix)\n except Exception as e:\n log.exception("%s Observer error: %s", log_id_prefix, e)\n self.stop_signal.set()\n finally:\n if self.observer.is_alive():\n self.observer.stop()\n self.observer.join()\n log.info("%s Observer stopped", log_id_prefix)\n\n def _stop_listener(self) -> None:\n """Stop the directory monitoring listener."""\n log_id_prefix = f"{self.log_identifier}[StopListener]"\n log.info("%s Stopping directory monitor...", log_id_prefix)\n \n if self.observer and self.observer.is_alive():\n log.info("%s Stopping observer...", log_id_prefix)\n self.observer.stop()\n \n if self.watchdog_thread and self.watchdog_thread.is_alive():\n log.info("%s Joining observer thread...", log_id_prefix)\n self.watchdog_thread.join(timeout=5)\n if self.watchdog_thread.is_alive():\n log.warning("%s Observer thread did not join cleanly", log_id_prefix)\n \n log.info("%s Directory monitor stopped", log_id_prefix)\n\n async def _process_new_file(self, file_path: str):\n """Process a newly detected file."""\n log_id_prefix = f"{self.log_identifier}[ProcessFile:{os.path.basename(file_path)}]"\n log.info("%s Processing new file: %s", log_id_prefix, file_path)\n \n error_context = {\n "file_path": file_path,\n "a2a_session_id": f"dir_monitor-error-{self.generate_uuid()}"\n }\n\n try:\n # Step 1: Authenticate and enrich user\n user_identity_profile = await self.authenticate_and_enrich_user(file_path)\n if not user_identity_profile:\n log.error("%s Authentication failed for file: %s", log_id_prefix, file_path)\n error_obj = JSONRPCError(code=-32001, message="Authentication failed")\n await self._send_error_to_external(error_context, error_obj)\n return\n\n # Step 2: Translate external input to A2A format\n target_agent_name, a2a_parts, external_request_context = await self._translate_external_input(\n file_path, user_identity_profile\n )\n\n if not target_agent_name or not a2a_parts:\n log.error("%s Failed to translate file to A2A task: %s", log_id_prefix, file_path)\n error_obj = JSONRPCError(code=-32002, message="Failed to translate file to A2A task")\n final_error_context = {**error_context, **external_request_context}\n await self._send_error_to_external(final_error_context, error_obj)\n return\n\n # Step 3: Submit A2A task\n log.info("%s Submitting A2A task for file: %s to agent: %s", \n log_id_prefix, file_path, target_agent_name)\n await self.submit_a2a_task(\n target_agent_name=target_agent_name,\n a2a_parts=a2a_parts,\n external_request_context=external_request_context,\n user_identity=user_identity_profile\n )\n log.info("%s A2A task submitted for file: %s", log_id_prefix, file_path)\n\n except FileNotFoundError:\n log.error("%s File not found during processing: %s", log_id_prefix, file_path)\n except Exception as e:\n log.exception("%s Unexpected error processing file %s: %s", log_id_prefix, file_path, e)\n error_obj = JSONRPCError(code=-32000, message=f"Unexpected error: {e}")\n await self._send_error_to_external(error_context, error_obj)\n\n async def _extract_initial_claims(self, external_event_data: Any) -> Optional[Dict[str, Any]]:\n """Extract user identity claims from file event."""\n file_path = str(external_event_data)\n log_id_prefix = f"{self.log_identifier}[ExtractClaims:{os.path.basename(file_path)}]"\n \n claims = {\n "id": self.default_user_identity_id,\n "source": "dir_monitor",\n "file_path": file_path\n }\n log.debug("%s Extracted claims for file %s: %s", log_id_prefix, file_path, claims)\n return claims\n\n async def _translate_external_input(\n self, external_event_data: Any, authenticated_user_identity: Dict[str, Any]\n ) -> Tuple[Optional[str], List[A2APart], Dict[str, Any]]:\n """Translate file event to A2A task format."""\n file_path = str(external_event_data)\n log_id_prefix = f"{self.log_identifier}[TranslateInput:{os.path.basename(file_path)}]"\n\n user_id_for_a2a = authenticated_user_identity.get("id", self.default_user_identity_id)\n a2a_session_id = f"dir_monitor-session-{self.generate_uuid()}"\n \n # Prepare external request context\n external_request_context: Dict[str, Any] = {\n "file_path": file_path,\n "user_id_for_a2a": user_id_for_a2a,\n "app_name_for_artifacts": self.gateway_id,\n "user_id_for_artifacts": user_id_for_a2a,\n "a2a_session_id": a2a_session_id,\n }\n a2a_parts: List[A2APart] = []\n\n try:\n # Check if file exists\n if not os.path.exists(file_path):\n log.error("%s File does not exist: %s", log_id_prefix, file_path)\n raise FileNotFoundError(f"File not found: {file_path}")\n\n # Read file content\n with open(file_path, "rb") as f:\n content_bytes = f.read()\n \n # Determine MIME type\n mime_type, _ = mimetypes.guess_type(file_path)\n if mime_type is None:\n mime_type = "application/octet-stream"\n\n # Save file as artifact\n if not self.shared_artifact_service:\n log.error("%s Artifact service not available for file: %s", \n log_id_prefix, os.path.basename(file_path))\n return None, [], external_request_context\n\n artifact_metadata = {\n "source": "dir_monitor_gateway",\n "original_filename": os.path.basename(file_path),\n "detected_mime_type": mime_type,\n "processing_timestamp_utc": datetime.now(timezone.utc).isoformat(),\n }\n\n log.debug("%s Saving artifact for file: %s", log_id_prefix, file_path)\n save_result = await save_artifact_with_metadata(\n artifact_service=self.shared_artifact_service,\n app_name=self.gateway_id,\n user_id=str(user_id_for_a2a),\n session_id=a2a_session_id,\n filename=os.path.basename(file_path),\n content_bytes=content_bytes,\n mime_type=mime_type,\n metadata_dict=artifact_metadata,\n timestamp=datetime.now(timezone.utc),\n )\n\n if save_result["status"] not in ["success", "partial_success"]:\n log.error("%s Failed to save file as artifact: %s", \n log_id_prefix, save_result.get("message"))\n return None, [], external_request_context\n\n # Create artifact URI\n data_version = save_result.get("data_version", 0)\n artifact_uri = f"artifact://{self.gateway_id}/{str(user_id_for_a2a)}/{a2a_session_id}/{os.path.basename(file_path)}?version={data_version}"\n \n log.info("%s Saved file as artifact: %s", log_id_prefix, artifact_uri)\n\n # Create A2A parts\n file_content_obj = FileContent(\n name=os.path.basename(file_path),\n uri=artifact_uri,\n mimeType=mime_type\n )\n a2a_parts.append(FilePart(file=file_content_obj))\n a2a_parts.append(TextPart(\n text=f"Please analyze and summarize the content of: {os.path.basename(file_path)}"\n ))\n\n log.info("%s Successfully translated file %s into A2A parts", log_id_prefix, file_path)\n return self.target_agent_name, a2a_parts, external_request_context\n\n except Exception as e:\n log.exception("%s Error translating file %s: %s", log_id_prefix, file_path, e)\n return None, [], external_request_context\n\n async def _send_final_response_to_external(\n self, external_request_context: Dict[str, Any], task_data: Task\n ) -> None:\n """Handle final response from A2A agent."""\n log_id_prefix = f"{self.log_identifier}[SendFinalResponse]"\n file_path = external_request_context.get("file_path", "Unknown file")\n task_id = task_data.id\n\n # Extract summary from response\n summary_text = "Summary not available."\n if task_data.status and task_data.status.message and task_data.status.message.parts:\n for part in task_data.status.message.parts:\n if isinstance(part, TextPart):\n summary_text = part.text\n break\n \n log.info("%s Task %s completed for file \'%s\'. Status: %s", \n log_id_prefix, task_id, os.path.basename(file_path), \n task_data.status.state if task_data.status else "Unknown")\n log.info("%s Summary: %s", log_id_prefix, summary_text[:200] + "..." if len(summary_text) > 200 else summary_text)\n\n async def _send_error_to_external(\n self, external_request_context: Dict[str, Any], error_data: JSONRPCError\n ) -> None:\n """Handle errors by moving files to error directory."""\n log_id_prefix = f"{self.log_identifier}[SendError]"\n file_path = external_request_context.get("file_path")\n \n log.error("%s A2A Error for file \'%s\'. Code: %s, Message: %s",\n log_id_prefix, \n os.path.basename(file_path) if file_path else "Unknown file",\n error_data.code, error_data.message)\n\n # Move problematic file to error directory\n if file_path and os.path.exists(file_path):\n try:\n os.makedirs(self.error_directory_path, exist_ok=True)\n base_name = os.path.basename(file_path)\n error_file_path = os.path.join(self.error_directory_path, base_name)\n \n # Handle filename conflicts\n counter = 0\n while os.path.exists(error_file_path):\n counter += 1\n name, ext = os.path.splitext(base_name)\n error_file_path = os.path.join(self.error_directory_path, f"{name}_error_{counter}{ext}")\n\n shutil.move(file_path, error_file_path)\n log.info("%s Moved problematic file %s to %s", log_id_prefix, file_path, error_file_path)\n except Exception as e:\n log.exception("%s Failed to move file %s to error directory: %s",\n log_id_prefix, file_path, e)\n\n async def _send_update_to_external(\n self,\n external_request_context: Dict[str, Any],\n event_data: Union[TaskStatusUpdateEvent, TaskArtifactUpdateEvent],\n is_final_chunk_of_update: bool,\n ) -> None:\n """Handle intermediate updates (optional for this gateway)."""\n log_id_prefix = f"{self.log_identifier}[SendUpdate]"\n task_id = event_data.id\n file_path = external_request_context.get("file_path", "Unknown file")\n \n log.debug("%s Received update for task %s (file %s). Updates not processed by this gateway.",\n log_id_prefix, task_id, os.path.basename(file_path))\n\n def cleanup(self):\n """Clean up resources."""\n log.info("%s Cleaning up Directory Monitor Gateway Component...", self.log_identifier)\n super().cleanup()\n log.info("%s Directory Monitor Gateway Component cleanup finished.", self.log_identifier)\n'})}),"\n",(0,i.jsx)(n.h3,{id:"step-4-configure-the-gateway",children:"Step 4: Configure the Gateway"}),"\n",(0,i.jsxs)(n.p,{children:["Configure the Gateway (",(0,i.jsx)(n.code,{children:"dir_monitor_config.yaml"}),")"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-yaml",children:'# configs/gateways/dir_monitor_config.yaml\nlog:\n stdout_log_level: INFO\n log_file_level: DEBUG\n log_file: "dir_monitor_gateway.log"\n\n!include ../shared_config.yaml\n\napps:\n - name: dir_monitor_gateway_app\n app_base_path: .\n app_module: src.dir_monitor.app\n\n broker:\n <<: *broker_connection\n\n app_config:\n namespace: ${NAMESPACE}\n gateway_id: dir-monitor-gateway\n \n # Artifact service configuration\n artifact_service: *default_artifact_service\n\n # Authorization service\n authorization_service:\n type: "none"\n\n # System purpose for A2A context\n system_purpose: >\n This system monitors directories for new files and processes them automatically.\n Analyze and summarize file contents. Always provide useful insights about the files.\n Your external name is Directory Monitor Agent.\n\n response_format: >\n Responses should be clear, concise, and professionally formatted.\n Provide structured analysis of file contents in Markdown format.\n\n # Gateway-specific configuration\n directory_path: /path/to/monitor/directory\n error_directory_path: /path/to/error/directory\n target_agent_name: "OrchestratorAgent"\n default_user_identity: "dir_monitor_system"\n'})}),"\n",(0,i.jsx)(n.h3,{id:"step-5-install-dependencies",children:"Step 5: Install Dependencies"}),"\n",(0,i.jsx)(n.p,{children:"Add required dependencies to your project:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"pip install watchdog\n"})}),"\n",(0,i.jsx)(n.h3,{id:"step-6-run-your-gateway",children:"Step 6: Run Your Gateway"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"sam run configs/gateways/dir_monitor_config.yaml\n"})}),"\n",(0,i.jsx)(n.h2,{id:"advanced-gateway-patterns",children:"Advanced Gateway Patterns"}),"\n",(0,i.jsx)(n.h3,{id:"authentication-and-authorization",children:"Authentication and Authorization"}),"\n",(0,i.jsx)(n.p,{children:"Gateways can implement sophisticated authentication:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-python",children:'async def _extract_initial_claims(self, external_event_data: Any) -> Optional[Dict[str, Any]]:\n """Extract user claims with API key validation."""\n request = external_event_data.get("request")\n \n # Validate API key\n api_key = request.headers.get("X-API-Key")\n if not api_key or not self._validate_api_key(api_key):\n return None\n \n # Extract user information\n user_id = request.headers.get("X-User-ID", "anonymous")\n \n return {\n "id": user_id,\n "source": "api_gateway",\n "api_key_hash": hashlib.sha256(api_key.encode()).hexdigest()[:8],\n "roles": self._get_user_roles(user_id)\n }\n'})}),"\n",(0,i.jsx)(n.h3,{id:"file-handling-with-artifacts",children:"File Handling with Artifacts"}),"\n",(0,i.jsx)(n.p,{children:"For gateways that handle files:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-python",children:'async def _save_file_as_artifact(self, file_content: bytes, filename: str, \n mime_type: str, session_id: str) -> Optional[str]:\n """Save file content as artifact and return URI."""\n if not self.shared_artifact_service:\n return None\n \n try:\n save_result = await save_artifact_with_metadata(\n artifact_service=self.shared_artifact_service,\n app_name=self.gateway_id,\n user_id="system",\n session_id=session_id,\n filename=filename,\n content_bytes=file_content,\n mime_type=mime_type,\n metadata_dict={\n "source": "my_gateway",\n "upload_timestamp": datetime.now(timezone.utc).isoformat()\n },\n timestamp=datetime.now(timezone.utc)\n )\n \n if save_result["status"] in ["success", "partial_success"]:\n version = save_result.get("data_version", 0)\n return f"artifact://{self.gateway_id}/system/{session_id}/{filename}?version={version}"\n \n except Exception as e:\n log.error("Failed to save artifact: %s", e)\n \n return None\n'})}),"\n",(0,i.jsx)(n.h3,{id:"streaming-responses",children:"Streaming Responses"}),"\n",(0,i.jsx)(n.p,{children:"Handle streaming responses from agents:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-python",children:'async def _send_update_to_external(\n self, external_request_context: Dict[str, Any],\n event_data: Union[TaskStatusUpdateEvent, TaskArtifactUpdateEvent],\n is_final_chunk_of_update: bool\n) -> None:\n """Send streaming updates to external system."""\n if isinstance(event_data, TaskStatusUpdateEvent):\n if event_data.status and event_data.status.message:\n for part in event_data.status.message.parts:\n if isinstance(part, TextPart):\n # Send partial text to external system\n await self._send_partial_response(\n external_request_context,\n part.text,\n is_final=is_final_chunk_of_update\n )\n'})}),"\n",(0,i.jsx)(n.h3,{id:"error-handling-and-retry-logic",children:"Error Handling and Retry Logic"}),"\n",(0,i.jsx)(n.p,{children:"Implement robust error handling:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-python",children:'async def _process_with_retry(self, data: Any, max_retries: int = 3):\n """Process data with retry logic."""\n for attempt in range(max_retries):\n try:\n return await self._process_data(data)\n except TemporaryError as e:\n if attempt < max_retries - 1:\n wait_time = 2 ** attempt # Exponential backoff\n log.warning("Attempt %d failed, retrying in %ds: %s", \n attempt + 1, wait_time, e)\n await asyncio.sleep(wait_time)\n else:\n raise\n except PermanentError:\n # Don\'t retry permanent errors\n raise\n'})}),"\n",(0,i.jsx)(n.h2,{id:"best-practices",children:"Best Practices"}),"\n",(0,i.jsx)(n.h3,{id:"1-configuration-management",children:"1. Configuration Management"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Use environment variables for sensitive data"}),"\n",(0,i.jsx)(n.li,{children:"Provide sensible defaults"}),"\n",(0,i.jsx)(n.li,{children:"Validate configuration at startup"}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"2-error-handling",children:"2. Error Handling"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Implement comprehensive error handling"}),"\n",(0,i.jsx)(n.li,{children:"Use appropriate HTTP status codes"}),"\n",(0,i.jsx)(n.li,{children:"Log errors with sufficient context"}),"\n",(0,i.jsx)(n.li,{children:"Provide meaningful error messages"}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"3-security",children:"3. Security"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Validate all external inputs"}),"\n",(0,i.jsx)(n.li,{children:"Use secure authentication methods"}),"\n",(0,i.jsx)(n.li,{children:"Implement rate limiting where appropriate"}),"\n",(0,i.jsx)(n.li,{children:"Store secrets securely (use environment variables)"}),"\n",(0,i.jsx)(n.li,{children:"Follow principle of least privilege"}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"4-performance",children:"4. Performance"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Use async/await for I/O operations"}),"\n",(0,i.jsx)(n.li,{children:"Implement connection pooling for external APIs"}),"\n",(0,i.jsx)(n.li,{children:"Monitor resource usage"}),"\n",(0,i.jsx)(n.li,{children:"Handle backpressure appropriately"}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"5-monitoring-and-logging",children:"5. Monitoring and Logging"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Use structured logging"}),"\n",(0,i.jsx)(n.li,{children:"Include correlation IDs"}),"\n",(0,i.jsx)(n.li,{children:"Monitor key metrics (latency, error rates, throughput)"}),"\n",(0,i.jsx)(n.li,{children:"Set up health checks"}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"common-gateway-patterns",children:"Common Gateway Patterns"}),"\n",(0,i.jsx)(n.h3,{id:"httprest-api-gateway",children:"HTTP/REST API Gateway"}),"\n",(0,i.jsx)(n.p,{children:"For HTTP-based integrations:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-python",children:'from fastapi import FastAPI, HTTPException, Depends\nfrom fastapi.security import HTTPBearer\n\nclass HTTPAPIGatewayComponent(BaseGatewayComponent):\n def __init__(self, **kwargs):\n super().__init__(**kwargs)\n self.app = FastAPI()\n self.security = HTTPBearer()\n self._setup_routes()\n \n def _setup_routes(self):\n @self.app.post("/webhook/{endpoint_id}")\n async def webhook_handler(endpoint_id: str, request: Request,\n token: str = Depends(self.security)):\n # Authenticate request\n user_identity = await self.authenticate_and_enrich_user({\n "token": token,\n "endpoint_id": endpoint_id,\n "request": request\n })\n \n if not user_identity:\n raise HTTPException(status_code=401, detail="Unauthorized")\n \n # Process webhook\n body = await request.json()\n target_agent, parts, context = await self._translate_external_input(\n body, user_identity\n )\n \n task_id = await self.submit_a2a_task(\n target_agent_name=target_agent,\n a2a_parts=parts,\n external_request_context=context,\n user_identity=user_identity\n )\n \n return {"task_id": task_id, "status": "accepted"}\n'})}),"\n",(0,i.jsx)(n.h3,{id:"websocket-gateway",children:"WebSocket Gateway"}),"\n",(0,i.jsx)(n.p,{children:"For real-time bidirectional communication:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-python",children:'import websockets\nimport json\n\nclass WebSocketGatewayComponent(BaseGatewayComponent):\n def __init__(self, **kwargs):\n super().__init__(**kwargs)\n self.connections = {}\n \n async def _start_listener(self):\n """Start WebSocket server."""\n self.server = await websockets.serve(\n self.handle_websocket,\n self.get_config("websocket_host", "localhost"),\n self.get_config("websocket_port", 8765)\n )\n log.info("%s WebSocket server started", self.log_identifier)\n \n async def handle_websocket(self, websocket, path):\n """Handle WebSocket connections."""\n connection_id = self.generate_uuid()\n self.connections[connection_id] = websocket\n \n try:\n async for message in websocket:\n data = json.loads(message)\n await self.process_websocket_message(connection_id, data)\n except websockets.exceptions.ConnectionClosed:\n log.info("%s WebSocket connection closed: %s", self.log_identifier, connection_id)\n finally:\n self.connections.pop(connection_id, None)\n \n async def process_websocket_message(self, connection_id: str, data: dict):\n """Process incoming WebSocket message."""\n user_identity = await self.authenticate_and_enrich_user({\n "connection_id": connection_id,\n "data": data\n })\n \n if user_identity:\n target_agent, parts, context = await self._translate_external_input(\n data, user_identity\n )\n context["connection_id"] = connection_id\n \n await self.submit_a2a_task(\n target_agent_name=target_agent,\n a2a_parts=parts,\n external_request_context=context,\n user_identity=user_identity\n )\n \n async def _send_final_response_to_external(self, context: Dict[str, Any], task_data: Task):\n """Send response back via WebSocket."""\n connection_id = context.get("connection_id")\n websocket = self.connections.get(connection_id)\n \n if websocket:\n response = {\n "task_id": task_data.id,\n "status": task_data.status.state.value if task_data.status else "unknown",\n "result": self._extract_text_from_task(task_data)\n }\n await websocket.send(json.dumps(response))\n'})}),"\n",(0,i.jsx)(n.h3,{id:"message-queue-gateway",children:"Message Queue Gateway"}),"\n",(0,i.jsx)(n.p,{children:"For integration with message queues:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-python",children:'import asyncio\nimport aio_pika\n\nclass MessageQueueGatewayComponent(BaseGatewayComponent):\n def __init__(self, **kwargs):\n super().__init__(**kwargs)\n self.connection = None\n self.channel = None\n \n async def _start_listener(self):\n """Connect to message queue and start consuming."""\n connection_url = self.get_config("rabbitmq_url")\n queue_name = self.get_config("input_queue_name")\n \n self.connection = await aio_pika.connect_robust(connection_url)\n self.channel = await self.connection.channel()\n \n queue = await self.channel.declare_queue(queue_name, durable=True)\n await queue.consume(self.process_message)\n \n log.info("%s Started consuming from queue: %s", self.log_identifier, queue_name)\n \n async def process_message(self, message: aio_pika.IncomingMessage):\n """Process incoming queue message."""\n async with message.process():\n try:\n data = json.loads(message.body.decode())\n \n user_identity = await self.authenticate_and_enrich_user(data)\n if not user_identity:\n log.warning("%s Authentication failed for message", self.log_identifier)\n return\n \n target_agent, parts, context = await self._translate_external_input(\n data, user_identity\n )\n context["message_id"] = message.message_id\n context["reply_to"] = message.reply_to\n \n await self.submit_a2a_task(\n target_agent_name=target_agent,\n a2a_parts=parts,\n external_request_context=context,\n user_identity=user_identity\n )\n \n except Exception as e:\n log.exception("%s Error processing message: %s", self.log_identifier, e)\n \n async def _send_final_response_to_external(self, context: Dict[str, Any], task_data: Task):\n """Send response back to reply queue."""\n reply_to = context.get("reply_to")\n if reply_to and self.channel:\n response = {\n "task_id": task_data.id,\n "status": task_data.status.state.value if task_data.status else "unknown",\n "result": self._extract_text_from_task(task_data)\n }\n \n await self.channel.default_exchange.publish(\n aio_pika.Message(json.dumps(response).encode()),\n routing_key=reply_to\n )\n'})}),"\n",(0,i.jsx)(n.h2,{id:"packaging-as-a-plugin",children:"Packaging as a Plugin"}),"\n",(0,i.jsx)(n.p,{children:"For distribution and reusability, package your gateway as a plugin:"}),"\n",(0,i.jsx)(n.h3,{id:"1-create-plugin-structure",children:"1. Create Plugin Structure"}),"\n",(0,i.jsxs)(n.p,{children:["The following structure is created when running the ",(0,i.jsx)(n.code,{children:"sam plugin create my-gateway-plugin --type gateway"})," command:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"my-gateway-plugin/\n\u251c\u2500\u2500 pyproject.toml\n\u251c\u2500\u2500 README.md\n\u251c\u2500\u2500 src/\n\u2502 \u2514\u2500\u2500 sam_my_gateway/\n\u2502 \u251c\u2500\u2500 __init__.py\n\u2502 \u251c\u2500\u2500 app.py\n\u2502 \u251c\u2500\u2500 component.py\n\u251c\u2500\u2500 config.yaml\n\u2514\u2500\u2500 examples/\n \u2514\u2500\u2500 my_gateway_example.yaml\n"})}),"\n",(0,i.jsxs)(n.h3,{id:"2-configure-pyprojecttoml",children:["2. Configure ",(0,i.jsx)(n.code,{children:"pyproject.toml"})]}),"\n",(0,i.jsxs)(n.p,{children:["Update the ",(0,i.jsx)(n.code,{children:"pyproject.toml"})," file to include your gateway dependencies:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-toml",children:'...\ndependencies = [\n "watchdog>=3.0.0", # Add your specific dependencies\n]\n...\n'})}),"\n",(0,i.jsx)(n.h3,{id:"3-build-and-install",children:"3. Build and Install"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"# Build the plugin\nsam plugin build\n\n# Install plugin from local wheel file\nsam plugin add my-gateway --plugin dist/sam_my_gateway-0.1.0-py3-none-any.whl\n"})}),"\n",(0,i.jsx)(n.h2,{id:"troubleshooting",children:"Troubleshooting"}),"\n",(0,i.jsx)(n.h3,{id:"common-issues",children:"Common Issues"}),"\n",(0,i.jsx)(n.h4,{id:"gateway-fails-to-start",children:"Gateway Fails to Start"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Check configuration schema validation"}),"\n",(0,i.jsx)(n.li,{children:"Verify all required parameters are provided"}),"\n",(0,i.jsx)(n.li,{children:"Ensure external dependencies are installed"}),"\n"]}),"\n",(0,i.jsx)(n.h4,{id:"tasks-not-reaching-agents",children:"Tasks Not Reaching Agents"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Verify namespace configuration matches agents"}),"\n",(0,i.jsx)(n.li,{children:"Check Solace broker connectivity"}),"\n",(0,i.jsx)(n.li,{children:"Confirm agent names are correct"}),"\n"]}),"\n",(0,i.jsx)(n.h4,{id:"authentication-failures",children:"Authentication Failures"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Validate user identity extraction logic"}),"\n",(0,i.jsx)(n.li,{children:"Check authorization service configuration"}),"\n",(0,i.jsx)(n.li,{children:"Verify claims format matches expectations"}),"\n"]}),"\n",(0,i.jsx)(n.h4,{id:"fileartifact-issues",children:"File/Artifact Issues"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Ensure artifact service is properly configured"}),"\n",(0,i.jsx)(n.li,{children:"Check file permissions and paths"}),"\n",(0,i.jsx)(n.li,{children:"Verify artifact URI construction"}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"debugging-tips",children:"Debugging Tips"}),"\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:"Enable Debug Logging"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-yaml",children:"log:\n stdout_log_level: DEBUG\n log_file_level: DEBUG\n"})}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Use Test Agents"}),":\nCreate simple echo agents for testing gateway integration"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Monitor Solace Topics"}),":\nUse Solace monitoring tools to trace message flow"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Add Correlation IDs"}),":\nInclude unique identifiers in logs for request tracing"]}),"\n"]}),"\n"]})]})}function _(e={}){const{wrapper:n}={...(0,s.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:()=>r,x:()=>o});var a=t(6540);const i={},s=a.createContext(i);function r(e){const n=a.useContext(s);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(i):e.components||i:r(e.components),a.createElement(s.Provider,{value:n},e.children)}}}]);
@@ -1 +0,0 @@
1
- "use strict";(self.webpackChunksolace_agenitc_mesh_docs=self.webpackChunksolace_agenitc_mesh_docs||[]).push([[7132],{8097:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>r,default:()=>h,frontMatter:()=>o,metadata:()=>a,toc:()=>l});const a=JSON.parse('{"id":"documentation/tutorials/rest-gateway","title":"REST Gateway","description":"Solace Agent Mesh (SAM) REST API Gateway provides a standard, robust, and secure HTTP-based entry point for programmatic and system-to-system integrations. It allows external clients to submit tasks to SAM agents, manage files, and discover agent capabilities using a familiar RESTful interface.","source":"@site/docs/documentation/tutorials/rest-gateway.md","sourceDirName":"documentation/tutorials","slug":"/documentation/tutorials/rest-gateway","permalink":"/solace-agent-mesh/docs/documentation/tutorials/rest-gateway","draft":false,"unlisted":false,"editUrl":"https://github.com/SolaceLabs/solace-agent-mesh/edit/main/docs/docs/documentation/tutorials/rest-gateway.md","tags":[],"version":"current","sidebarPosition":15,"frontMatter":{"title":"REST Gateway","sidebar_position":15},"sidebar":"docSidebar","previous":{"title":"MCP Integration","permalink":"/solace-agent-mesh/docs/documentation/tutorials/mcp-integration"},"next":{"title":"Event Mesh Gateway","permalink":"/solace-agent-mesh/docs/documentation/tutorials/event-mesh-gateway"}}');var s=t(4848),i=t(8453);const o={title:"REST Gateway",sidebar_position:15},r=void 0,c={},l=[{value:"Key Features",id:"key-features",level:2},{value:"Setting Up the Environment",id:"setting-up-the-environment",level:2},{value:"Adding the REST Gateway Plugin",id:"adding-the-rest-gateway-plugin",level:2},{value:"Configuring the REST Gateway",id:"configuring-the-rest-gateway",level:3},{value:"Running the REST Gateway",id:"running-the-rest-gateway",level:2},{value:"Sending a Request via REST API",id:"sending-a-request-via-rest-api",level:2},{value:"Modern API (v2) - Asynchronous",id:"modern-api-v2---asynchronous",level:3},{value:"Legacy API (v1) - Synchronous",id:"legacy-api-v1---synchronous",level:3}];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,i.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.p,{children:"Solace Agent Mesh (SAM) REST API Gateway provides a standard, robust, and secure HTTP-based entry point for programmatic and system-to-system integrations. It allows external clients to submit tasks to SAM agents, manage files, and discover agent capabilities using a familiar RESTful interface."}),"\n",(0,s.jsx)(n.p,{children:"The gateway is designed to be highly configurable and supports two distinct operational modes to cater to both modern, asynchronous workflows and legacy, synchronous systems."}),"\n",(0,s.jsx)(n.h2,{id:"key-features",children:"Key Features"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Dual API Versions"}),": Supports both a modern asynchronous API (v2) and a deprecated synchronous API (v1) for backward compatibility."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Asynchronous by Default"}),': The v2 API uses a "202 Accepted + Poll" pattern, ideal for long-running agent tasks.']}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Delegated Authentication"}),": Integrates with an external authentication service via bearer tokens for secure access."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"File Handling"}),": Supports file uploads for tasks and provides download URLs for generated artifacts."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Dynamic Configuration"}),": All gateway behaviors, including server settings and authentication, are configured via the main SAM Host YAML file."]}),"\n"]}),"\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/getting-started/installation",children:"install Solace Agent Mesh and the SAM CLI"}),", and then ",(0,s.jsx)(n.a,{href:"/solace-agent-mesh/docs/documentation/getting-started/quick-start",children:"create a new Solace Agent Mesh project"}),"."]}),"\n",(0,s.jsx)(n.h2,{id:"adding-the-rest-gateway-plugin",children:"Adding the REST Gateway Plugin"}),"\n",(0,s.jsx)(n.p,{children:"Once you have your project set up, add the REST Gateway plugin:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-sh",children:"sam plugin add my-http-rest --plugin sam-rest-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:"my-http-rest"}),"."]}),"\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-rest-gateway"})," plugin"]}),"\n",(0,s.jsxs)(n.li,{children:["Creates a new gateway configuration named ",(0,s.jsx)(n.code,{children:"my-http-rest"})," in your ",(0,s.jsx)(n.code,{children:"configs/gateways/"})," directory"]}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"configuring-the-rest-gateway",children:"Configuring the REST Gateway"}),"\n",(0,s.jsxs)(n.p,{children:["For further configuration, you can edit the ",(0,s.jsx)(n.code,{children:"configs/gateways/my-http-rest.yaml"})," file. This file contains the gateway configuration that can be customized for your use case."]}),"\n",(0,s.jsxs)(n.admonition,{title:"Using local Solace PubSub+ Broker container",type:"info",children:[(0,s.jsxs)(n.p,{children:["Solace PubSub+ Broker container uses port 8080. You need to edit the ",(0,s.jsx)(n.code,{children:"rest_api_server_port"})," field and ",(0,s.jsx)(n.code,{children:"external_auth_service_url"})," field in the ",(0,s.jsx)(n.code,{children:"configs/gateways/my-http-rest.yaml"})," file to a free port other than 8080 (for example: 8081)."]}),(0,s.jsxs)(n.p,{children:["You can edit the YAML file directly or add environment variables ",(0,s.jsx)(n.code,{children:"REST_API_PORT=8081"})," and ",(0,s.jsx)(n.code,{children:"EXTERNAL_AUTH_SERVICE_URL=http://localhost:8081"}),"."]}),(0,s.jsx)(n.p,{children:"Make sure you change the REST API gateway to your new port in the following request examples."})]}),"\n",(0,s.jsx)(n.h2,{id:"running-the-rest-gateway",children:"Running the REST Gateway"}),"\n",(0,s.jsx)(n.p,{children:"To run the REST Gateway, use the following command:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-sh",children:"sam run configs/gateways/my-http-rest.yaml\n"})}),"\n",(0,s.jsx)(n.h2,{id:"sending-a-request-via-rest-api",children:"Sending a Request via REST API"}),"\n",(0,s.jsxs)(n.p,{children:["You can also interact with SAM via the ",(0,s.jsx)(n.strong,{children:"REST API"}),"."]}),"\n",(0,s.jsxs)(n.p,{children:["The REST API gateway runs on ",(0,s.jsx)(n.code,{children:"http://localhost:8080"})," by default. You can use either the legacy v1 API or the modern async v2 API."]}),"\n",(0,s.jsx)(n.h3,{id:"modern-api-v2---asynchronous",children:"Modern API (v2) - Asynchronous"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-sh",children:"# Submit task\ncurl --location 'http://localhost:8080/api/v2/tasks' \\\n--header 'Authorization: Bearer token' \\\n--form 'agent_name=\"OrchestratorAgent\"' \\\n--form 'prompt=\"Hi\\!\"'\n\n# Poll for result using returned task ID\ncurl --location 'http://localhost:8080/api/v2/tasks/{taskId}' \\\n--header 'Authorization: Bearer token'\n"})}),"\n",(0,s.jsx)(n.admonition,{type:"warning",children:(0,s.jsxs)(n.p,{children:["It might take a while for the system to respond. See the ",(0,s.jsx)(n.a,{href:"/solace-agent-mesh/docs/documentation/deployment/observability",children:"observability"})," page for more information about monitoring the system while it processes the request."]})}),"\n",(0,s.jsx)(n.p,{children:"Sample output:"}),"\n",(0,s.jsxs)(n.p,{children:["From ",(0,s.jsx)(n.code,{children:"api/v2/tasks"})]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-json",children:'{\n "taskId":"task-6a0e682f4f6c4927a5997e4fd06eea83"\n}\n'})}),"\n",(0,s.jsxs)(n.p,{children:["From ",(0,s.jsx)(n.code,{children:"api/v2/tasks/{taskId}"})]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-json",children:'{\n "id": "task-6a0e682f4f6c4927a5997e4fd06eea83",\n "sessionId": "rest-session-4df0c24fcecc45fcb69692db9876bc5c",\n "status": {\n "state": "completed",\n "message": {\n "role": "agent",\n "parts": [{ "type": "text", "text": "Outdoor Activities in London: Spring Edition. Today\'s Perfect Activities (13\xb0C, Light Cloud): - Royal Parks Exploration : Hyde Park and Kensington Gardens..." }]\n },\n "timestamp": "2025-07-03T16:54:15.273085"\n },\n "artifacts": [],\n "metadata": { "agent_name": "OrchestratorAgent" }\n}\n'})}),"\n",(0,s.jsx)(n.h3,{id:"legacy-api-v1---synchronous",children:"Legacy API (v1) - Synchronous"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-sh",children:"curl --location 'http://localhost:8080/api/v1/invoke' \\\n--header 'Authorization: Bearer None' \\\n--form 'prompt=\"Suggest some good outdoor activities in London given the season and current weather conditions.\"' \\\n--form 'agent_name=\"OrchestratorAgent\"' \\\n--form 'stream=\"false\"'\n"})}),"\n",(0,s.jsx)(n.p,{children:"Sample output:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-json",children:'{\n "id": "task-9f7d5f465f5a4f1ca799e8e5ecb35a43",\n "sessionId": "rest-session-36b36eeb69b04da7b67708f90e5512dc",\n "status": {\n "state": "completed",\n "message": {\n "role": "agent",\n "parts": [\n { "type": "text", "text": "Outdoor Activities in London: Spring Edition. Today\'s Perfect Activities (13\xb0C, Light Cloud): - Royal Parks Exploration : Hyde Park and Kensington Gardens..." }\n ]\n },\n "timestamp": "2025-07-03T16:59:37.486480"\n },\n "artifacts": [],\n "metadata": { "agent_name": "OrchestratorAgent" }\n}\n'})})]})}function h(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>o,x:()=>r});var a=t(6540);const s={},i=a.createContext(s);function o(e){const n=a.useContext(i);return a.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(s):e.components||s:o(e.components),a.createElement(i.Provider,{value:n},e.children)}}}]);
@@ -1 +0,0 @@
1
- "use strict";(self.webpackChunksolace_agenitc_mesh_docs=self.webpackChunksolace_agenitc_mesh_docs||[]).push([[1257],{6060:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>o,default:()=>h,frontMatter:()=>i,metadata:()=>a,toc:()=>c});const a=JSON.parse('{"id":"documentation/Migrations/A2A Upgrade To 0.3.0/a2a-gateway-upgrade-to-0.3.0","title":"SAM Gateway Migration Guide: Upgrading to the A2A SDK","description":"This guide is for developers who have built or are maintaining a custom Solace Agent Mesh (SAM) gateway. A recent architectural update has aligned SAM with the official Agent-to-Agent (A2A) protocol","source":"@site/docs/documentation/Migrations/A2A Upgrade To 0.3.0/a2a-gateway-upgrade-to-0.3.0.md","sourceDirName":"documentation/Migrations/A2A Upgrade To 0.3.0","slug":"/documentation/Migrations/A2A Upgrade To 0.3.0/a2a-gateway-upgrade-to-0.3.0","permalink":"/solace-agent-mesh/docs/documentation/Migrations/A2A Upgrade To 0.3.0/a2a-gateway-upgrade-to-0.3.0","draft":false,"unlisted":false,"editUrl":"https://github.com/SolaceLabs/solace-agent-mesh/edit/main/docs/docs/documentation/Migrations/A2A Upgrade To 0.3.0/a2a-gateway-upgrade-to-0.3.0.md","tags":[],"version":"current","frontMatter":{},"sidebar":"docSidebar","previous":{"title":"RAG Integration","permalink":"/solace-agent-mesh/docs/documentation/tutorials/rag-integration"},"next":{"title":"A2A Technical Migration Map","permalink":"/solace-agent-mesh/docs/documentation/Migrations/A2A Upgrade To 0.3.0/a2a-technical-migration-map"}}');var s=n(4848),r=n(8453);const i={},o="SAM Gateway Migration Guide: Upgrading to the A2A SDK",l={},c=[{value:"1. Why the Change?",id:"1-why-the-change",level:2},{value:"2. Core Conceptual Changes",id:"2-core-conceptual-changes",level:2},{value:"The <code>a2a</code> Helper Layer: The New Best Practice",id:"the-a2a-helper-layer-the-new-best-practice",level:3},{value:"Type System Migration",id:"type-system-migration",level:3},{value:"Accessing Object Properties",id:"accessing-object-properties",level:3},{value:"Changes to <code>BaseGatewayComponent</code>",id:"changes-to-basegatewaycomponent",level:3},{value:"3. Practical Migration Checklist",id:"3-practical-migration-checklist",level:2},{value:"4. Code Examples: Before &amp; After",id:"4-code-examples-before--after",level:2},{value:"Example 1: Translating External Input",id:"example-1-translating-external-input",level:3},{value:"Example 2: Sending a Final Response",id:"example-2-sending-a-final-response",level:3}];function d(e){const t={br:"br",code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",li:"li",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},{Details:n}=t;return n||function(e,t){throw new Error("Expected "+(t?"component":"object")+" `"+e+"` to be defined: you likely forgot to import, pass, or provide it.")}("Details",!0),(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.header,{children:(0,s.jsx)(t.h1,{id:"sam-gateway-migration-guide-upgrading-to-the-a2a-sdk",children:"SAM Gateway Migration Guide: Upgrading to the A2A SDK"})}),"\n",(0,s.jsxs)(t.p,{children:["This guide is for developers who have built or are maintaining a custom Solace Agent Mesh (SAM) gateway. A recent architectural update has aligned SAM with the official Agent-to-Agent (A2A) protocol",(0,s.jsx)(t.br,{}),"\n","specification by adopting the ",(0,s.jsx)(t.code,{children:"a2a-sdk"}),". This migration requires some changes to your gateway code to ensure compatibility."]}),"\n",(0,s.jsx)(t.p,{children:"This document provides a high-level overview of the conceptual changes and a practical checklist to guide you through the upgrade process."}),"\n",(0,s.jsx)(t.h2,{id:"1-why-the-change",children:"1. Why the Change?"}),"\n",(0,s.jsxs)(t.p,{children:["The migration from our legacy A2A implementation to the official ",(0,s.jsx)(t.code,{children:"a2a-sdk"})," is a foundational improvement with several key benefits:"]}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Protocol Compliance:"})," Ensures your gateway is fully interoperable with any A2A-compliant agent or system."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Standardization:"})," Replaces bespoke code with a community-supported standard, reducing technical debt."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Improved Maintainability:"})," Insulates your gateway from future A2A specification changes. The ",(0,s.jsx)(t.code,{children:"a2a-sdk"})," will be updated, not your core logic."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Future-Proofing:"})," Positions your gateway to easily adopt new features as the A2A protocol evolves."]}),"\n"]}),"\n",(0,s.jsx)(t.h2,{id:"2-core-conceptual-changes",children:"2. Core Conceptual Changes"}),"\n",(0,s.jsx)(t.p,{children:"The upgrade introduces a few key changes in how you interact with A2A objects."}),"\n",(0,s.jsxs)(t.h3,{id:"the-a2a-helper-layer-the-new-best-practice",children:["The ",(0,s.jsx)(t.code,{children:"a2a"})," Helper Layer: The New Best Practice"]}),"\n",(0,s.jsxs)(t.p,{children:["The most significant change is the introduction of a new abstraction layer located at ",(0,s.jsx)(t.code,{children:"solace_agent_mesh.common.a2a"}),"."]}),"\n",(0,s.jsxs)(t.p,{children:["You should ",(0,s.jsxs)(t.strong,{children:["no longer instantiate ",(0,s.jsx)(t.code,{children:"a2a.types"})," models directly"]})," or access their properties by hand. Instead, use the provided helper functions. This layer is designed to simplify development and",(0,s.jsx)(t.br,{}),"\n","protect your code from future SDK changes."]}),"\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.strong,{children:"Example:"})}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-python",children:'# BEFORE: Direct instantiation and property access \nfrom solace_agent_mesh.common.types import TextPart, Task \nmy_part = TextPart(text="Hello") \ntask_id = my_task.id \n \n# AFTER: Using the a2a helper layer \nfrom solace_agent_mesh.common import a2a \nmy_part = a2a.create_text_part(text="Hello") \ntask_id = a2a.get_task_id(my_task) \n'})}),"\n",(0,s.jsx)(t.h3,{id:"type-system-migration",children:"Type System Migration"}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:["The legacy types in ",(0,s.jsx)(t.code,{children:"solace_agent_mesh.common.types"})," (like ",(0,s.jsx)(t.code,{children:"A2APart"}),", ",(0,s.jsx)(t.code,{children:"FileContent"}),") are deprecated."]}),"\n",(0,s.jsxs)(t.li,{children:["All A2A models now come from the ",(0,s.jsx)(t.code,{children:"a2a.types"})," library."]}),"\n",(0,s.jsxs)(t.li,{children:["The type hint for a list of message parts has changed from ",(0,s.jsx)(t.code,{children:"List[A2APart]"})," to ",(0,s.jsx)(t.code,{children:"List[ContentPart]"}),". ",(0,s.jsx)(t.code,{children:"ContentPart"})," is a simple alias for the union of ",(0,s.jsx)(t.code,{children:"TextPart"}),", ",(0,s.jsx)(t.code,{children:"DataPart"}),", and ",(0,s.jsx)(t.code,{children:"FilePart"}),"."]}),"\n"]}),"\n",(0,s.jsx)(t.h3,{id:"accessing-object-properties",children:"Accessing Object Properties"}),"\n",(0,s.jsxs)(t.p,{children:["Field names on many A2A objects have changed. Always use the ",(0,s.jsx)(t.code,{children:"a2a"})," helper functions for safe and future-proof access."]}),"\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:"Action"}),(0,s.jsx)(t.th,{style:{textAlign:"left"},children:"Old Pattern"}),(0,s.jsx)(t.th,{style:{textAlign:"left"},children:"New Pattern (Recommended)"})]})}),(0,s.jsxs)(t.tbody,{children:[(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"left"},children:"Get Task ID"}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"task.id"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"a2a.get_task_id(task)"})})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"left"},children:"Get Task Status"}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"task.status.state"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"a2a.get_task_status(task)"})})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"left"},children:"Get Event's Task ID"}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"event.id"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"event.task_id"})})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"left"},children:"Get Message Parts"}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"message.parts"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"a2a.get_parts_from_message(message)"})})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"left"},children:"Get Error Message"}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"error.message"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"a2a.get_error_message(error)"})})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"left"},children:"Get Error Code"}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"error.code"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"a2a.get_error_code(error)"})})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"left"},children:"Get Error Data"}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"error.data"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"a2a.get_error_data(error)"})})]})]})]}),"\n",(0,s.jsxs)(t.h3,{id:"changes-to-basegatewaycomponent",children:["Changes to ",(0,s.jsx)(t.code,{children:"BaseGatewayComponent"})]}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"BaseGatewayComponent"})," has been significantly improved. It now handles more of the A2A protocol complexity, simplifying gateway implementations."]}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Artifact Handling:"})," The base class can now automatically handle artifact URIs, converting them to embedded bytes before sending them to your gateway's ",(0,s.jsx)(t.code,{children:"_send_..."})," methods. This is controlled by",(0,s.jsx)(t.br,{}),"\n","the ",(0,s.jsx)(t.code,{children:"resolve_artifact_uris_in_gateway"})," parameter in the constructor."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Message Publishing:"})," The base class now manages the details of preparing and publishing the A2A request message in ",(0,s.jsx)(t.code,{children:"submit_a2a_task"}),"."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Asynchronous Model:"})," The underlying threading model has been removed in favor of a more direct ",(0,s.jsx)(t.code,{children:"asyncio"})," implementation, simplifying the component lifecycle."]}),"\n"]}),"\n",(0,s.jsxs)(t.p,{children:["It is highly recommended to review the latest ",(0,s.jsx)(t.code,{children:"BaseGatewayComponent"})," and re-base your custom gateway on it to inherit these benefits and reduce boilerplate code."]}),"\n",(0,s.jsx)(t.h2,{id:"3-practical-migration-checklist",children:"3. Practical Migration Checklist"}),"\n",(0,s.jsx)(t.p,{children:"Follow these steps to update your gateway code."}),"\n",(0,s.jsxs)(t.ol,{children:["\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.strong,{children:"Update Imports:"})}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:["Remove imports from ",(0,s.jsx)(t.code,{children:"solace_agent_mesh.common.types"}),"."]}),"\n",(0,s.jsxs)(t.li,{children:["Add imports from ",(0,s.jsx)(t.code,{children:"a2a.types"})," for specific models if needed."]}),"\n",(0,s.jsxs)(t.li,{children:["Add ",(0,s.jsx)(t.code,{children:"from solace_agent_mesh.common import a2a"}),"."]}),"\n",(0,s.jsxs)(t.li,{children:["Add ",(0,s.jsx)(t.code,{children:"from solace_agent_mesh.common.a2a import ContentPart"}),"."]}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.strong,{children:"Update Type Hints:"})}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:["Find all instances of ",(0,s.jsx)(t.code,{children:"List[A2APart]"})," and change them to ",(0,s.jsx)(t.code,{children:"List[ContentPart]"}),"."]}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.strong,{children:"Refactor Object Creation:"})}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:["Replace direct model instantiation like ",(0,s.jsx)(t.code,{children:"TextPart(...)"})," or ",(0,s.jsx)(t.code,{children:"FilePart(...)"})," with their corresponding helper functions: ",(0,s.jsx)(t.code,{children:"a2a.create_text_part(...)"}),", ",(0,s.jsx)(t.code,{children:"a2a.create_file_part_from_uri(...)"}),", etc."]}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.strong,{children:"Refactor Property Access:"})}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:["Replace direct property access (",(0,s.jsx)(t.code,{children:"task.id"}),", ",(0,s.jsx)(t.code,{children:"error.message"}),") with calls to the ",(0,s.jsx)(t.code,{children:"a2a"})," helper functions (",(0,s.jsx)(t.code,{children:"a2a.get_task_id(task)"}),", ",(0,s.jsx)(t.code,{children:"a2a.get_error_message(error)"}),")."]}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.strong,{children:"Review Base Class Integration:"})}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:["If you have a custom gateway, compare it against the latest ",(0,s.jsx)(t.code,{children:"BaseGatewayComponent"}),". Consider refactoring to delegate more responsibility (like artifact handling and message submission) to the",(0,s.jsx)(t.br,{}),"\n","base class."]}),"\n"]}),"\n"]}),"\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.strong,{children:"Test Thoroughly:"})}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsx)(t.li,{children:"Once refactored, run your integration tests to ensure the gateway correctly translates inputs and processes outputs in the new format."}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(t.h2,{id:"4-code-examples-before--after",children:"4. Code Examples: Before & After"}),"\n",(0,s.jsx)(t.p,{children:"Here are some common patterns you will encounter during the migration."}),"\n",(0,s.jsx)(t.h3,{id:"example-1-translating-external-input",children:"Example 1: Translating External Input"}),"\n",(0,s.jsx)(t.p,{children:"This example shows how to create A2A parts from an external event."}),"\n",(0,s.jsxs)(n,{children:[(0,s.jsx)("summary",{children:(0,s.jsx)("strong",{children:"_translate_external_input"})}),(0,s.jsx)(t.p,{children:(0,s.jsx)(t.strong,{children:"Before:"})}),(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-python",children:'from solace_agent_mesh.common.types import Part as A2APart, TextPart, FilePart, FileContent \n \nasync def _translate_external_input(self, external_event: Any) -> Tuple[str, List[A2APart], Dict[str, Any]]: \n # ... \n a2a_parts: List[A2APart] = [] \n \n # Create a file part with a URI \n uri = "artifact://..." \n a2a_parts.append( \n FilePart( \n file=FileContent(name="report.pdf", uri=uri) \n ) \n ) \n \n # Create a text part \n prompt = "Summarize the attached file." \n a2a_parts.append(TextPart(text=prompt)) \n \n return "summary_agent", a2a_parts, {} \n'})}),(0,s.jsx)(t.p,{children:(0,s.jsx)(t.strong,{children:"After:"})}),(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-python",children:'from solace_agent_mesh.common import a2a \nfrom solace_agent_mesh.common.a2a import ContentPart \n \nasync def _translate_external_input(self, external_event: Any) -> Tuple[str, List[ContentPart], Dict[str, Any]]: \n # ... \n a2a_parts: List[ContentPart] = [] \n \n # Create a file part with a URI using the helper \n uri = "artifact://..." \n file_part = a2a.create_file_part_from_uri(uri=uri, name="report.pdf") \n a2a_parts.append(file_part) \n \n # Create a text part using the helper \n prompt = "Summarize the attached file." \n text_part = a2a.create_text_part(text=prompt) \n a2a_parts.append(text_part) \n \n return "summary_agent", a2a_parts, {} \n'})})]}),"\n",(0,s.jsx)(t.h3,{id:"example-2-sending-a-final-response",children:"Example 2: Sending a Final Response"}),"\n",(0,s.jsxs)(t.p,{children:["This example shows how to process a final ",(0,s.jsx)(t.code,{children:"Task"})," object."]}),"\n",(0,s.jsxs)(n,{children:[(0,s.jsx)("summary",{children:(0,s.jsx)("strong",{children:"_send_final_response_to_external"})}),(0,s.jsx)(t.p,{children:(0,s.jsx)(t.strong,{children:"Before:"})}),(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-python",children:'from solace_agent_mesh.common.types import Task, TaskState, TextPart \n \nasync def _send_final_response_to_external(self, context: Dict, task_data: Task) -> None: \n task_id = task_data.id \n final_status_text = ":checkered_flag: Task complete." \n \n if task_data.status.state == TaskState.FAILED: \n error_message_text = "" \n if task_data.status.message and task_data.status.message.parts: \n for part in task_data.status.message.parts: \n if isinstance(part, TextPart): \n error_message_text = part.text \n break \n final_status_text = f":x: Error: Task failed. {error_message_text}".strip() \n \n # ... use final_status_text and task_id \n'})}),(0,s.jsx)(t.p,{children:(0,s.jsx)(t.strong,{children:"After:"})}),(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-python",children:'from solace_agent_mesh.common import a2a \nfrom a2a.types import Task, TaskState \n \nasync def _send_final_response_to_external(self, context: Dict, task_data: Task) -> None: \n # Use helpers to safely access properties \n task_id = a2a.get_task_id(task_data) \n task_status = a2a.get_task_status(task_data) \n \n final_status_text = ":checkered_flag: Task complete." \n \n if task_status == TaskState.failed: \n error_message_text = "" \n if task_data.status and task_data.status.message: \n # Use helper to extract all text from the message \n error_message_text = a2a.get_text_from_message(task_data.status.message) \n final_status_text = f":x: Error: Task failed. {error_message_text}".strip() \n \n # ... use final_status_text and task_id \n'})})]})]})}function h(e={}){const{wrapper:t}={...(0,r.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>i,x:()=>o});var a=n(6540);const s={},r=a.createContext(s);function i(e){const t=a.useContext(r);return a.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:i(e.components),a.createElement(r.Provider,{value:t},e.children)}}}]);
@@ -1 +0,0 @@
1
- "use strict";(self.webpackChunksolace_agenitc_mesh_docs=self.webpackChunksolace_agenitc_mesh_docs||[]).push([[8055],{5343:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>s,default:()=>h,frontMatter:()=>o,metadata:()=>i,toc:()=>c});const i=JSON.parse('{"id":"documentation/tutorials/rag-integration","title":"RAG Integration","description":"This tutorial guides you through setting up and configuring Solace Agent Mesh (SAM) Retrieval Augmented Generation (RAG) plugin. The RAG plugin enables your agents to answer questions by retrieving information from a knowledge base of your documents.","source":"@site/docs/documentation/tutorials/rag-integration.md","sourceDirName":"documentation/tutorials","slug":"/documentation/tutorials/rag-integration","permalink":"/solace-agent-mesh/docs/documentation/tutorials/rag-integration","draft":false,"unlisted":false,"editUrl":"https://github.com/SolaceLabs/solace-agent-mesh/edit/main/docs/docs/documentation/tutorials/rag-integration.md","tags":[],"version":"current","sidebarPosition":70,"frontMatter":{"title":"RAG Integration","sidebar_position":70,"toc_max_heading_level":4},"sidebar":"docSidebar","previous":{"title":"Slack Integration","permalink":"/solace-agent-mesh/docs/documentation/tutorials/slack-integration"},"next":{"title":"SAM Gateway Migration Guide: Upgrading to the A2A SDK","permalink":"/solace-agent-mesh/docs/documentation/Migrations/A2A Upgrade To 0.3.0/a2a-gateway-upgrade-to-0.3.0"}}');var a=t(4848),r=t(8453);const o={title:"RAG Integration",sidebar_position:70,toc_max_heading_level:4},s="RAG Integration",l={},c=[{value:"What is SAM RAG?",id:"what-is-sam-rag",level:2},{value:"Prerequisites",id:"prerequisites",level:2},{value:"Adding the RAG Plugin",id:"adding-the-rag-plugin",level:2},{value:"Configuring the RAG Agent",id:"configuring-the-rag-agent",level:2},{value:"Shared Configuration",id:"shared-configuration",level:3},{value:"RAG Pipeline Configuration",id:"rag-pipeline-configuration",level:3},{value:"1. Scanner Configuration",id:"1-scanner-configuration",level:4},{value:"2. Preprocessor Configuration",id:"2-preprocessor-configuration",level:4},{value:"3. Splitter Configuration",id:"3-splitter-configuration",level:4},{value:"4. Embedding Configuration",id:"4-embedding-configuration",level:4},{value:"5. Vector Database Configuration",id:"5-vector-database-configuration",level:4},{value:"6. LLM Configuration",id:"6-llm-configuration",level:4},{value:"7. Retrieval Configuration",id:"7-retrieval-configuration",level:4},{value:"Environment Variables",id:"environment-variables",level:3},{value:"Running the RAG Agent",id:"running-the-rag-agent",level:2},{value:"Testing the RAG Agent",id:"testing-the-rag-agent",level:2},{value:"Ingesting Documents",id:"ingesting-documents",level:3},{value:"Option 1: Automatic Scanning (Batch Ingestion)",id:"option-1-automatic-scanning-batch-ingestion",level:4},{value:"Option 2: Manual Upload via Gateway",id:"option-2-manual-upload-via-gateway",level:4},{value:"Querying the Knowledge Base",id:"querying-the-knowledge-base",level:3},{value:"Troubleshooting",id:"troubleshooting",level:2}];function d(e){const n={a:"a",blockquote:"blockquote",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,r.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.header,{children:(0,a.jsx)(n.h1,{id:"rag-integration",children:"RAG Integration"})}),"\n",(0,a.jsx)(n.p,{children:"This tutorial guides you through setting up and configuring Solace Agent Mesh (SAM) Retrieval Augmented Generation (RAG) plugin. The RAG plugin enables your agents to answer questions by retrieving information from a knowledge base of your documents."}),"\n",(0,a.jsx)(n.h2,{id:"what-is-sam-rag",children:"What is SAM RAG?"}),"\n",(0,a.jsx)(n.p,{children:"The SAM RAG plugin enhances your agents with the ability to perform retrieval-augmented generation. This means the agent can:"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.strong,{children:"Scan"})," documents from various sources (local filesystem, Google Drive, etc.)."]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.strong,{children:"Preprocess"})," and ",(0,a.jsx)(n.strong,{children:"split"})," the text into manageable chunks."]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.strong,{children:"Embed"})," these chunks into vectors and store them in a vector database."]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.strong,{children:"Retrieve"})," relevant chunks of text based on a user's query."]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.strong,{children:"Generate"})," an answer using a large language model (LLM) augmented with the retrieved information."]}),"\n"]}),"\n",(0,a.jsx)(n.p,{children:"This allows you to build agents that can answer questions about your own private data."}),"\n",(0,a.jsx)(n.h2,{id:"prerequisites",children:"Prerequisites"}),"\n",(0,a.jsx)(n.p,{children:"Before you begin, ensure you have:"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.a,{href:"/solace-agent-mesh/docs/documentation/getting-started/installation",children:"Installed Solace Agent Mesh and the SAM CLI"}),"."]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.a,{href:"/solace-agent-mesh/docs/documentation/getting-started/quick-start",children:"Created a new Solace Agent Mesh project"}),"."]}),"\n",(0,a.jsx)(n.li,{children:"Access to a vector database (for example, Qdrant, Chroma, and Pinecone)."}),"\n",(0,a.jsx)(n.li,{children:"Access to an LLM for generation and an embedding model."}),"\n",(0,a.jsx)(n.li,{children:"A directory with some documents for the agent to ingest."}),"\n"]}),"\n",(0,a.jsx)(n.h2,{id:"adding-the-rag-plugin",children:"Adding the RAG Plugin"}),"\n",(0,a.jsx)(n.p,{children:"To add the RAG plugin to your SAM project, run the following command:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sh",children:"sam plugin add my-rag-agent --plugin sam-rag\n"})}),"\n",(0,a.jsxs)(n.p,{children:["Replace ",(0,a.jsx)(n.code,{children:"my-rag-agent"})," with your preferred agent name. This command:"]}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:["Installs the ",(0,a.jsx)(n.code,{children:"sam-rag"})," plugin."]}),"\n",(0,a.jsxs)(n.li,{children:["Creates a new agent configuration file at ",(0,a.jsx)(n.code,{children:"configs/agents/my-rag-agent.yaml"}),"."]}),"\n"]}),"\n",(0,a.jsx)(n.h2,{id:"configuring-the-rag-agent",children:"Configuring the RAG Agent"}),"\n",(0,a.jsxs)(n.p,{children:["The RAG agent requires a detailed configuration. Open ",(0,a.jsx)(n.code,{children:"configs/agents/my-rag-agent.yaml"})," to configure the following sections:"]}),"\n",(0,a.jsx)(n.h3,{id:"shared-configuration",children:"Shared Configuration"}),"\n",(0,a.jsxs)(n.p,{children:["Like other agents, the RAG agent needs a connection to the Solace broker and a configured LLM. This is typically done in a ",(0,a.jsx)(n.code,{children:"shared_config.yaml"})," file."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-yaml",children:"# configs/shared_config.yaml\nshared_config:\n - broker_connection: &broker_connection\n dev_mode: ${SOLACE_DEV_MODE, false}\n broker_url: ${SOLACE_BROKER_URL, ws://localhost:8080}\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\n - models:\n general: &general_model\n model: ${LLM_SERVICE_GENERAL_MODEL_NAME}\n api_base: ${LLM_SERVICE_ENDPOINT}\n api_key: ${LLM_SERVICE_API_KEY}\n"})}),"\n",(0,a.jsx)(n.h3,{id:"rag-pipeline-configuration",children:"RAG Pipeline Configuration"}),"\n",(0,a.jsxs)(n.p,{children:["The RAG pipeline has several stages, each with its own configuration block within the ",(0,a.jsx)(n.code,{children:"app_config"})," section of your ",(0,a.jsx)(n.code,{children:"my-rag-agent.yaml"})," file."]}),"\n",(0,a.jsx)(n.h4,{id:"1-scanner-configuration",children:"1. Scanner Configuration"}),"\n",(0,a.jsx)(n.p,{children:"The scanner discovers documents to be ingested. You can configure it to scan a local filesystem or cloud sources."}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.strong,{children:"Local Filesystem Example:"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-yaml",children:'scanner:\n batch: true\n use_memory_storage: true\n source:\n type: filesystem\n directories:\n - "/path/to/your/documents" # Important: Replace with your actual document directory path\n filters:\n file_formats:\n - ".txt"\n - ".pdf"\n - ".md"\n'})}),"\n",(0,a.jsxs)(n.p,{children:[(0,a.jsx)(n.strong,{children:"Multi-Cloud Source Example:"}),"\nYou can also configure multiple sources, including Google Drive, OneDrive, and S3."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-yaml",children:'scanner:\n batch: true\n use_memory_storage: true\n sources:\n - type: filesystem\n directories: ["${LOCAL_DOCUMENTS_PATH}"]\n - type: google_drive\n credentials_path: "${GOOGLE_DRIVE_CREDENTIALS_PATH}"\n folders:\n - folder_id: "${GOOGLE_DRIVE_FOLDER_ID_1}"\n name: "Documents"\n recursive: true\n'})}),"\n",(0,a.jsx)(n.h4,{id:"2-preprocessor-configuration",children:"2. Preprocessor Configuration"}),"\n",(0,a.jsx)(n.p,{children:"The preprocessor cleans the text extracted from documents."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-yaml",children:"preprocessor:\n default_preprocessor:\n type: enhanced\n params:\n lowercase: true\n normalize_whitespace: true\n remove_urls: true\n preprocessors:\n pdf: \n type: document\n params:\n lowercase: true\n normalize_whitespace: true\n remove_non_ascii: true\n remove_urls: true\n"})}),"\n",(0,a.jsx)(n.h4,{id:"3-splitter-configuration",children:"3. Splitter Configuration"}),"\n",(0,a.jsx)(n.p,{children:"The splitter breaks down large documents into smaller chunks. Different splitters are available for different file types."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-yaml",children:"splitter:\n default_splitter:\n type: recursive_character\n params:\n chunk_size: 2048\n chunk_overlap: 400\n splitters:\n markdown:\n type: markdown\n params:\n chunk_size: 2048\n chunk_overlap: 400\n pdf:\n type: token\n params:\n chunk_size: 500\n chunk_overlap: 100\n"})}),"\n",(0,a.jsx)(n.h4,{id:"4-embedding-configuration",children:"4. Embedding Configuration"}),"\n",(0,a.jsx)(n.p,{children:"This section defines the model used to create vector embeddings from the text chunks."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-yaml",children:'embedding:\n embedder_type: "openai"\n embedder_params:\n model: "${OPENAI_EMBEDDING_MODEL}"\n api_key: "${OPENAI_API_KEY}"\n api_base: "${OPENAI_API_ENDPOINT}"\n normalize_embeddings: true\n'})}),"\n",(0,a.jsx)(n.h4,{id:"5-vector-database-configuration",children:"5. Vector Database Configuration"}),"\n",(0,a.jsx)(n.p,{children:"Configure the connection to your vector database where the embeddings are stored."}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.strong,{children:"Qdrant Example:"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-yaml",children:'vector_db:\n db_type: "qdrant"\n db_params:\n url: "${QDRANT_URL}"\n api_key: "${QDRANT_API_KEY}"\n collection_name: "${QDRANT_COLLECTION}"\n embedding_dimension: ${QDRANT_EMBEDDING_DIMENSION}\n'})}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.strong,{children:"Chroma Example:"})}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-yaml",children:'vector_db:\n db_type: "chroma"\n db_params:\n host: "${CHROMA_HOST}"\n port: "${CHROMA_PORT}"\n collection_name: "${CHROMA_COLLECTION}"\n'})}),"\n",(0,a.jsx)(n.h4,{id:"6-llm-configuration",children:"6. LLM Configuration"}),"\n",(0,a.jsx)(n.p,{children:"Configure the LLM that is used to generate answers based on the retrieved context."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-yaml",children:'llm:\n load_balancer:\n - model_name: "gpt-4o"\n litellm_params:\n model: "openai/${OPENAI_MODEL_NAME}"\n api_key: "${OPENAI_API_KEY}"\n api_base: "${OPENAI_API_ENDPOINT}"\n'})}),"\n",(0,a.jsx)(n.h4,{id:"7-retrieval-configuration",children:"7. Retrieval Configuration"}),"\n",(0,a.jsx)(n.p,{children:"This defines how many document chunks are retrieved to answer a query."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-yaml",children:"retrieval:\n top_k: 7\n"})}),"\n",(0,a.jsx)(n.h3,{id:"environment-variables",children:"Environment Variables"}),"\n",(0,a.jsxs)(n.p,{children:["The RAG agent relies heavily on environment variables. Here are some of the most important ones you'll need to set in your ",(0,a.jsx)(n.code,{children:".env"})," file:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:'# Solace Connection\nSOLACE_BROKER_URL=ws://localhost:8080\nSOLACE_BROKER_VPN=default\nSOLACE_BROKER_USERNAME=default\nSOLACE_BROKER_PASSWORD=default\nNAMESPACE=my-org/dev\n\n# LLM and Embedding Models\nOPENAI_API_KEY="your-openai-api-key"\nOPENAI_API_ENDPOINT="your-openai-api-endpoint"\nOPENAI_MODEL_NAME="model name. E.g., gpt-4o"\nOPENAI_EMBEDDING_MODEL="embedding model name. E.g., text-embedding-3-small"\n\n# Vector Database (Qdrant example)\nQDRANT_URL="Qdrant url"\nQDRANT_API_KEY="API key"\nQDRANT_COLLECTION="my-rag-collection"\nQDRANT_EMBEDDING_DIMENSION=1536 # Depends on your embedding model\n\n# Scanner\nLOCAL_DOCUMENTS_PATH="./my_documents" # Relative path to your documents folder\n'})}),"\n",(0,a.jsxs)(n.p,{children:["Create a directory named ",(0,a.jsx)(n.code,{children:"my_documents"})," in your project root and place some text or markdown files inside it."]}),"\n",(0,a.jsx)(n.h2,{id:"running-the-rag-agent",children:"Running the RAG Agent"}),"\n",(0,a.jsx)(n.p,{children:"Once you have configured your agent and set the environment variables, you can run it:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sh",children:"sam run configs/agents/my-rag-agent.yaml\n"})}),"\n",(0,a.jsx)(n.p,{children:"When the agent starts, it begins scanning the documents in the configured source, processing and ingesting them into your vector database. This process may take some time, depending on the number and size of your documents."}),"\n",(0,a.jsx)(n.h2,{id:"testing-the-rag-agent",children:"Testing the RAG Agent"}),"\n",(0,a.jsx)(n.p,{children:"Once your agent is running, you can test its retrieval capabilities and ingest new documents."}),"\n",(0,a.jsx)(n.h3,{id:"ingesting-documents",children:"Ingesting Documents"}),"\n",(0,a.jsx)(n.p,{children:"There are two primary ways to ingest documents into your RAG agent's knowledge base:"}),"\n",(0,a.jsx)(n.h4,{id:"option-1-automatic-scanning-batch-ingestion",children:"Option 1: Automatic Scanning (Batch Ingestion)"}),"\n",(0,a.jsxs)(n.p,{children:["This method uses the configured ",(0,a.jsx)(n.code,{children:"scanner"})," component. The agent automatically ingests documents from the directories specified in your configuration upon startup."]}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.strong,{children:"Step 1: Create a Document"})}),"\n",(0,a.jsxs)(n.p,{children:["First, create a simple text file named ",(0,a.jsx)(n.code,{children:"sam_features.txt"})," and add some content to it. For example:"]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-text",children:"Solace Agent Mesh (SAM) is a powerful framework for building AI agents.\nKey features of SAM include:\n- A flexible plugin architecture.\n- Integration with various LLMs and vector databases.\n- Scalable gateways for different communication protocols.\n- An event-driven design based on Solace PubSub+.\n"})}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.strong,{children:"Step 2: Place the Document in the Scanned Directory"})}),"\n",(0,a.jsxs)(n.p,{children:['In the "Environment Variables" section, we configured ',(0,a.jsx)(n.code,{children:"LOCAL_DOCUMENTS_PATH"})," to point to a directory (e.g., ",(0,a.jsx)(n.code,{children:"./my_documents"}),")."]}),"\n",(0,a.jsxs)(n.p,{children:["Create this directory in your project's root folder if you haven't already, and move your ",(0,a.jsx)(n.code,{children:"sam_features.txt"})," file into it."]}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sh",children:"mkdir -p my_documents\nmv sam_features.txt my_documents/\n"})}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.strong,{children:"Step 3: Run the Agent to Trigger Ingestion"})}),"\n",(0,a.jsx)(n.p,{children:"If your agent is already running, you'll need to restart it to trigger the batch scan. If it's not running, start it now:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-sh",children:"sam run configs/agents/my-rag-agent.yaml\n"})}),"\n",(0,a.jsx)(n.p,{children:"You will see logs indicating that the file is being processed. Once the agent is running and the initial scan is complete, the document is successfully ingested and ready for retrieval."}),"\n",(0,a.jsx)(n.h4,{id:"option-2-manual-upload-via-gateway",children:"Option 2: Manual Upload via Gateway"}),"\n",(0,a.jsx)(n.p,{children:"You can also ingest documents dynamically by uploading them directly through a gateway, like the Web UI. This is useful for adding single documents without restarting the agent. The RAG agent exposes a tool for this purpose."}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.strong,{children:"Step 1: Start the RAG Agent and Web UI"})}),"\n",(0,a.jsx)(n.p,{children:"Ensure both your RAG agent and the Web UI gateway are running."}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.strong,{children:"Step 2: Upload a Document in the Web UI"})}),"\n",(0,a.jsxs)(n.ol,{children:["\n",(0,a.jsxs)(n.li,{children:["Open the Web UI (usually at ",(0,a.jsx)(n.a,{href:"http://localhost:8000",children:"http://localhost:8000"}),", or check your gateway configuration for the correct URL) and start a chat with your RAG agent."]}),"\n",(0,a.jsx)(n.li,{children:"Use the file attachment button to select a document from your local machine."}),"\n",(0,a.jsxs)(n.li,{children:["Send a prompt along with the file, instructing the agent to ingest it. For example:","\n",(0,a.jsxs)(n.blockquote,{children:["\n",(0,a.jsx)(n.p,{children:'"Please ingest the attached document into your knowledge base."'}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,a.jsxs)(n.p,{children:["The RAG agent uses its ",(0,a.jsx)(n.code,{children:"built-in"})," ingest_document tool to process the file you uploaded. The file goes through the same preprocessing, splitting, and embedding pipeline as the documents from the automatic scan."]}),"\n",(0,a.jsx)(n.p,{children:(0,a.jsx)(n.strong,{children:"Step 3: Confirm Ingestion"})}),"\n",(0,a.jsx)(n.p,{children:"After the agent confirms that the document has been ingested, you can immediately ask questions about its content."}),"\n",(0,a.jsx)(n.h3,{id:"querying-the-knowledge-base",children:"Querying the Knowledge Base"}),"\n",(0,a.jsx)(n.p,{children:"You can interact with your RAG agent through any gateway, such as the Web UI gateway."}),"\n",(0,a.jsxs)(n.ol,{children:["\n",(0,a.jsx)(n.li,{children:"Make sure you have a Web UI gateway running (or add one to your project)."}),"\n",(0,a.jsxs)(n.li,{children:["Open the Web UI (usually at ",(0,a.jsx)(n.code,{children:"http://localhost:8000"}),")."]}),"\n",(0,a.jsxs)(n.li,{children:["Start a conversation with ",(0,a.jsx)(n.code,{children:"my-rag-agent"}),"."]}),"\n",(0,a.jsx)(n.li,{children:"Ask a question related to the content of the documents you provided during the initial scan."}),"\n"]}),"\n",(0,a.jsx)(n.p,{children:"For example, if you have a document about product features, you could ask:"}),"\n",(0,a.jsxs)(n.blockquote,{children:["\n",(0,a.jsx)(n.p,{children:'"What are the key features of Product X?"'}),"\n"]}),"\n",(0,a.jsx)(n.p,{children:"The agent searches its knowledge base, finds the relevant information, and generates an answer based on the content of your documents."}),"\n",(0,a.jsx)(n.h2,{id:"troubleshooting",children:"Troubleshooting"}),"\n",(0,a.jsxs)(n.ul,{children:["\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.strong,{children:"Connection Errors"}),": Double-check all your URLs, API keys, and credentials for your LLM and vector database."]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.strong,{children:"Ingestion Issues"}),": Check the agent logs for errors during the scanning, preprocessing, or embedding stages. Ensure the file formats are supported and the paths are correct."]}),"\n",(0,a.jsxs)(n.li,{children:[(0,a.jsx)(n.strong,{children:"No Answers"}),": If the agent can't answer, it might be because the information is not in the documents, or the ",(0,a.jsx)(n.code,{children:"top_k"})," retrieval setting is too low."]}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,r.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:()=>o,x:()=>s});var i=t(6540);const a={},r=i.createContext(a);function o(e){const n=i.useContext(r);return i.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(a):e.components||a:o(e.components),i.createElement(r.Provider,{value:n},e.children)}}}]);
@@ -1 +0,0 @@
1
- "use strict";(self.webpackChunksolace_agenitc_mesh_docs=self.webpackChunksolace_agenitc_mesh_docs||[]).push([[1095],{6871:(e,n,i)=>{i.r(n),i.d(n,{assets:()=>a,contentTitle:()=>r,default:()=>h,frontMatter:()=>s,metadata:()=>o,toc:()=>d});const o=JSON.parse('{"id":"documentation/user-guide/builtin-tools/builtin-tools","title":"Configuring Built-in Tools","description":"This guide provides instructions for enabling and configuring the built-in tools provided by Solace Agent Mesh (SAM) framework.","source":"@site/docs/documentation/user-guide/builtin-tools/builtin-tools.md","sourceDirName":"documentation/user-guide/builtin-tools","slug":"/documentation/user-guide/builtin-tools/","permalink":"/solace-agent-mesh/docs/documentation/user-guide/builtin-tools/","draft":false,"unlisted":false,"editUrl":"https://github.com/SolaceLabs/solace-agent-mesh/edit/main/docs/docs/documentation/user-guide/builtin-tools/builtin-tools.md","tags":[],"version":"current","sidebarPosition":60,"frontMatter":{"title":"Configuring Built-in Tools","sidebar_position":60},"sidebar":"docSidebar","previous":{"title":"Creating Service Providers","permalink":"/solace-agent-mesh/docs/documentation/user-guide/creating-service-providers"},"next":{"title":"Artifact Management Tools","permalink":"/solace-agent-mesh/docs/documentation/user-guide/builtin-tools/artifact-management"}}');var l=i(4848),t=i(8453);const s={title:"Configuring Built-in Tools",sidebar_position:60},r="Configuring Built-in Tools",a={},d=[{value:"Overview",id:"overview",level:2},{value:"Configuration Methods",id:"configuration-methods",level:2},{value:"Method 1: Enabling Tool Groups (Recommended)",id:"method-1-enabling-tool-groups-recommended",level:3},{value:"Method 2: Enabling Individual Tools",id:"method-2-enabling-individual-tools",level:3},{value:"Available Tool Groups and Tools",id:"available-tool-groups-and-tools",level:2},{value:"Artifact Management",id:"artifact-management",level:3},{value:"Data Analysis",id:"data-analysis",level:3},{value:"Web",id:"web",level:3},{value:"Audio",id:"audio",level:3},{value:"Image",id:"image",level:3},{value:"General",id:"general",level:3},{value:"Complete Configuration Example",id:"complete-configuration-example",level:2}];function c(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,t.R)(),...e.components};return(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)(n.header,{children:(0,l.jsx)(n.h1,{id:"configuring-built-in-tools",children:"Configuring Built-in Tools"})}),"\n",(0,l.jsx)(n.p,{children:"This guide provides instructions for enabling and configuring the built-in tools provided by Solace Agent Mesh (SAM) framework."}),"\n",(0,l.jsx)(n.h2,{id:"overview",children:"Overview"}),"\n",(0,l.jsx)(n.p,{children:"Built-in tools are pre-packaged functionalities that can be granted to agents without requiring custom Python code. These tools address common operations such as file management, data analysis, web requests, and multi-modal generation."}),"\n",(0,l.jsxs)(n.p,{children:["The Solace Agent Mesh framework manages these tools through a central ",(0,l.jsx)(n.code,{children:"tool_registry"}),", which is responsible for loading the tools, generating instructional prompts for the Large Language Model (LLM), and handling their execution in a consistent manner."]}),"\n",(0,l.jsx)(n.h2,{id:"configuration-methods",children:"Configuration Methods"}),"\n",(0,l.jsxs)(n.p,{children:["Tool configuration is managed within the ",(0,l.jsx)(n.code,{children:"tools"})," list in an agent's ",(0,l.jsx)(n.code,{children:"app_config"})," block in the corresponding YAML configuration file."]}),"\n",(0,l.jsx)(n.h3,{id:"method-1-enabling-tool-groups-recommended",children:"Method 1: Enabling Tool Groups (Recommended)"}),"\n",(0,l.jsx)(n.p,{children:"For efficient configuration, built-in tools are organized into logical groups. An entire group of related tools can be enabled with a single entry. This is the recommended approach for standard functionalities."}),"\n",(0,l.jsxs)(n.ul,{children:["\n",(0,l.jsxs)(n.li,{children:[(0,l.jsx)(n.strong,{children:(0,l.jsx)(n.code,{children:"tool_type"})}),": ",(0,l.jsx)(n.code,{children:"builtin-group"})]}),"\n",(0,l.jsxs)(n.li,{children:[(0,l.jsx)(n.strong,{children:(0,l.jsx)(n.code,{children:"group_name"})}),": The unique identifier for the tool category."]}),"\n"]}),"\n",(0,l.jsx)(n.p,{children:(0,l.jsx)(n.strong,{children:"Example:"})}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-yaml",children:'# In your agent\'s app_config:\ntools:\n - tool_type: builtin-group\n group_name: "artifact_management"\n - tool_type: builtin-group\n group_name: "data_analysis"\n'})}),"\n",(0,l.jsx)(n.h3,{id:"method-2-enabling-individual-tools",children:"Method 2: Enabling Individual Tools"}),"\n",(0,l.jsx)(n.p,{children:"For more granular control over an agent's capabilities, specific tools can be enabled individually."}),"\n",(0,l.jsxs)(n.ul,{children:["\n",(0,l.jsxs)(n.li,{children:[(0,l.jsx)(n.strong,{children:(0,l.jsx)(n.code,{children:"tool_type"})}),": ",(0,l.jsx)(n.code,{children:"builtin"})]}),"\n",(0,l.jsxs)(n.li,{children:[(0,l.jsx)(n.strong,{children:(0,l.jsx)(n.code,{children:"tool_name"})}),": The unique, registered name of the tool."]}),"\n"]}),"\n",(0,l.jsx)(n.p,{children:(0,l.jsx)(n.strong,{children:"Example:"})}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-yaml",children:'# In your agent\'s app_config:\ntools:\n - tool_type: builtin\n tool_name: "web_request"\n - tool_type: builtin\n tool_name: "time_delay"\n'})}),"\n",(0,l.jsx)(n.admonition,{title:"Note",type:"info",children:(0,l.jsx)(n.p,{children:"The Solace Agent Mesh framework automatically handles duplicate tool registrations. If a tool group is enabled and a tool from that group is also listed individually, the tool is only loaded once."})}),"\n",(0,l.jsx)(n.h2,{id:"available-tool-groups-and-tools",children:"Available Tool Groups and Tools"}),"\n",(0,l.jsx)(n.p,{children:"The following sections detail the available tool groups and the individual tools they contain."}),"\n",(0,l.jsx)(n.h3,{id:"artifact-management",children:"Artifact Management"}),"\n",(0,l.jsxs)(n.p,{children:[(0,l.jsx)(n.strong,{children:"Group Name"}),": ",(0,l.jsx)(n.code,{children:"artifact_management"})]}),"\n",(0,l.jsxs)(n.p,{children:[(0,l.jsx)(n.strong,{children:"Description"}),": Tools for creating, loading, and managing file artifacts."]}),"\n",(0,l.jsxs)(n.p,{children:[(0,l.jsx)(n.strong,{children:"Individual Tools"}),":"]}),"\n",(0,l.jsxs)(n.ul,{children:["\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.code,{children:"create_artifact"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.code,{children:"append_to_artifact"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.code,{children:"list_artifacts"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.code,{children:"load_artifact"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.code,{children:"signal_artifact_for_return"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.code,{children:"apply_embed_and_create_artifact"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.code,{children:"extract_content_from_artifact"})}),"\n"]}),"\n",(0,l.jsx)(n.admonition,{type:"info",children:(0,l.jsxs)(n.p,{children:["For a more in-depth guide on using artifact management tools, refer to the ",(0,l.jsx)(n.a,{href:"/solace-agent-mesh/docs/documentation/user-guide/builtin-tools/artifact-management",children:"Artifact Management"})," documentation."]})}),"\n",(0,l.jsx)(n.h3,{id:"data-analysis",children:"Data Analysis"}),"\n",(0,l.jsxs)(n.p,{children:[(0,l.jsx)(n.strong,{children:"Group Name"}),": ",(0,l.jsx)(n.code,{children:"data_analysis"})]}),"\n",(0,l.jsxs)(n.p,{children:[(0,l.jsx)(n.strong,{children:"Description"}),": Tools for querying, transforming, and visualizing data."]}),"\n",(0,l.jsxs)(n.p,{children:[(0,l.jsx)(n.strong,{children:"Individual Tools"}),":"]}),"\n",(0,l.jsxs)(n.ul,{children:["\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.code,{children:"query_data_with_sql"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.code,{children:"create_sqlite_db"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.code,{children:"transform_data_with_jq"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.code,{children:"create_chart_from_plotly_config"})}),"\n"]}),"\n",(0,l.jsx)(n.admonition,{type:"info",children:(0,l.jsxs)(n.p,{children:["For a more in-depth guide on using Data Analysis tools, refer to the ",(0,l.jsx)(n.a,{href:"/solace-agent-mesh/docs/documentation/user-guide/builtin-tools/data-analysis-tools",children:"Data Analysis Tools"})," documentation."]})}),"\n",(0,l.jsx)(n.h3,{id:"web",children:"Web"}),"\n",(0,l.jsxs)(n.p,{children:[(0,l.jsx)(n.strong,{children:"Group Name"}),": ",(0,l.jsx)(n.code,{children:"web"})]}),"\n",(0,l.jsxs)(n.p,{children:[(0,l.jsx)(n.strong,{children:"Description"}),": Tools for interacting with web resources."]}),"\n",(0,l.jsxs)(n.p,{children:[(0,l.jsx)(n.strong,{children:"Individual Tools"}),":"]}),"\n",(0,l.jsxs)(n.ul,{children:["\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.code,{children:"web_request"})}),"\n"]}),"\n",(0,l.jsx)(n.h3,{id:"audio",children:"Audio"}),"\n",(0,l.jsxs)(n.p,{children:[(0,l.jsx)(n.strong,{children:"Group Name"}),": ",(0,l.jsx)(n.code,{children:"audio"})]}),"\n",(0,l.jsxs)(n.p,{children:[(0,l.jsx)(n.strong,{children:"Description"}),": Tools for generating and transcribing audio content."]}),"\n",(0,l.jsxs)(n.p,{children:[(0,l.jsx)(n.strong,{children:"Individual Tools"}),":"]}),"\n",(0,l.jsxs)(n.ul,{children:["\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.code,{children:"text_to_speech"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.code,{children:"multi_speaker_text_to_speech"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.code,{children:"transcribe_audio"})}),"\n"]}),"\n",(0,l.jsx)(n.h3,{id:"image",children:"Image"}),"\n",(0,l.jsxs)(n.p,{children:[(0,l.jsx)(n.strong,{children:"Group Name"}),": ",(0,l.jsx)(n.code,{children:"image"})]}),"\n",(0,l.jsxs)(n.p,{children:[(0,l.jsx)(n.strong,{children:"Description"}),": Tools for generating and analyzing images."]}),"\n",(0,l.jsxs)(n.p,{children:[(0,l.jsx)(n.strong,{children:"Individual Tools"}),":"]}),"\n",(0,l.jsxs)(n.ul,{children:["\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.code,{children:"create_image_from_description"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.code,{children:"describe_image"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.code,{children:"edit_image_with_gemini"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.code,{children:"describe_audio"})}),"\n"]}),"\n",(0,l.jsx)(n.h3,{id:"general",children:"General"}),"\n",(0,l.jsxs)(n.p,{children:[(0,l.jsx)(n.strong,{children:"Group Name"}),": ",(0,l.jsx)(n.code,{children:"general"})]}),"\n",(0,l.jsxs)(n.p,{children:[(0,l.jsx)(n.strong,{children:"Description"}),": General-purpose utility tools."]}),"\n",(0,l.jsxs)(n.p,{children:[(0,l.jsx)(n.strong,{children:"Individual Tools"}),":"]}),"\n",(0,l.jsxs)(n.ul,{children:["\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.code,{children:"convert_file_to_markdown"})}),"\n",(0,l.jsx)(n.li,{children:(0,l.jsx)(n.code,{children:"mermaid_diagram_generator"})}),"\n"]}),"\n",(0,l.jsx)(n.h2,{id:"complete-configuration-example",children:"Complete Configuration Example"}),"\n",(0,l.jsxs)(n.p,{children:["Below is a comprehensive example of a well-formed ",(0,l.jsx)(n.code,{children:"app_config"})," that uses the unified method to enable a mix of tool groups and individual tools."]}),"\n",(0,l.jsx)(n.pre,{children:(0,l.jsx)(n.code,{className:"language-yaml",children:'# In your agent\'s YAML file:\napp_config:\n namespace: "myorg/dev"\n agent_name: "DataAndWebAgent"\n model: "gemini-1.5-pro"\n instruction: "You are an agent that can analyze data and browse the web."\n\n # --- Unified Tool Configuration ---\n tools:\n # Enable a group of tools\n - tool_type: builtin-group\n group_name: "data_analysis"\n\n # Enable another group\n - tool_type: builtin-group\n group_name: "artifact_management"\n\n # Enable a single, specific tool\n - tool_type: builtin\n tool_name: "web_request"\n\n # Enable a custom Python tool\n - tool_type: python\n component_module: "my_company.tools.custom_calculators"\n function_name: "calculate_roi"\n\n # ... other service configurations (session_service, artifact_service, etc.)\n'})})]})}function h(e={}){const{wrapper:n}={...(0,t.R)(),...e.components};return n?(0,l.jsx)(n,{...e,children:(0,l.jsx)(c,{...e})}):c(e)}},8453:(e,n,i)=>{i.d(n,{R:()=>s,x:()=>r});var o=i(6540);const l={},t=o.createContext(l);function s(e){const n=o.useContext(t);return o.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(l):e.components||l:s(e.components),o.createElement(t.Provider,{value:n},e.children)}}}]);
@@ -1 +0,0 @@
1
- "use strict";(self.webpackChunksolace_agenitc_mesh_docs=self.webpackChunksolace_agenitc_mesh_docs||[]).push([[1721],{3878:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>o,default:()=>h,frontMatter:()=>a,metadata:()=>s,toc:()=>c});const s=JSON.parse('{"id":"documentation/getting-started/introduction","title":"Introduction","description":"Solace Agent Mesh","source":"@site/docs/documentation/getting-started/introduction.md","sourceDirName":"documentation/getting-started","slug":"/documentation/getting-started/introduction","permalink":"/solace-agent-mesh/docs/documentation/getting-started/introduction","draft":false,"unlisted":false,"editUrl":"https://github.com/SolaceLabs/solace-agent-mesh/edit/main/docs/docs/documentation/getting-started/introduction.md","tags":[],"version":"current","sidebarPosition":10,"frontMatter":{"title":"Introduction","sidebar_position":10},"sidebar":"docSidebar","next":{"title":"Installation","permalink":"/solace-agent-mesh/docs/documentation/getting-started/installation"}}');var i=t(4848),r=t(8453);const a={title:"Introduction",sidebar_position:10},o=void 0,l={},c=[{value:"Solace Agent Mesh",id:"solace-agent-mesh",level:2},{value:"What Problems Does the Mesh Solve?",id:"what-problems-does-the-mesh-solve",level:3},{value:"Why Choose Solace Agent Mesh?",id:"why-choose-solace-agent-mesh",level:3},{value:"Real-World Applications",id:"real-world-applications",level:2},{value:"Evolution Through Usage",id:"evolution-through-usage",level:3},{value:"For Developers",id:"for-developers",level:2},{value:"Getting Started",id:"getting-started",level:2}];function d(e){const n={a:"a",br:"br",h2:"h2",h3:"h3",img:"img",li:"li",p:"p",strong:"strong",ul:"ul",...(0,r.R)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h2,{id:"solace-agent-mesh",children:"Solace Agent Mesh"}),"\n",(0,i.jsx)(n.p,{children:"Modern AI development faces a fundamental challenge: while powerful AI models are readily available, the real complexity lies in connecting them to the data and systems where they can provide value. Data exists in isolated silos - spread across databases, SaaS platforms, APIs, and legacy systems - making it difficult to build AI applications that can work across these boundaries."}),"\n",(0,i.jsx)(n.p,{children:'Solace Agent Mesh (SAM) is an open-source framework that tackles this challenge head-on by integrating the Google Agent Development Kit (ADK) with the Solace AI Connector (SAC) to provide a "Universal A2A Agent Host" that enables scalable, distributed AI agent communication through Solace PubSub+. Whether you\'re an AI enthusiast experimenting with new models, or an enterprise developer building production systems, SAM gives you the tools to:'}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"connect AI agents to real-world data sources and systems through a standardized A2A (Agent-to-Agent) protocol"}),"\n",(0,i.jsx)(n.li,{children:"add gateways to provide event-based integrations or interactive UI connections"}),"\n",(0,i.jsx)(n.li,{children:"monitor and debug AI interactions in real-time through comprehensive observability"}),"\n",(0,i.jsx)(n.li,{children:"deploy solutions that scale from prototype to production with enterprise-grade reliability"}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Rather than trying to be a monolithic AI platform, SAM focuses on being an excellent integration layer built on proven event-driven architecture. It brings together specialized agents - whether they're using local databases, accessing cloud APIs, or interfacing with enterprise systems - and helps them collaborate through standardized A2A communication to solve complex problems."}),"\n",(0,i.jsx)(n.p,{children:"Built on event-driven architecture technology from Solace with Google ADK integration, SAM provides the robust foundation needed for both experimental and production deployments."}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"Solace Agent Mesh Overview",src:t(1351).A+"",width:"2558",height:"1788"})}),"\n",(0,i.jsx)(n.h3,{id:"what-problems-does-the-mesh-solve",children:"What Problems Does the Mesh Solve?"}),"\n",(0,i.jsx)(n.p,{children:"Solace Agent Mesh tackles the hardest challenges in building collaborative AI systems: agent coordination, system integration, and extensibility at scale. This section reveals the key problems it solves and shows how organizations are using it today."}),"\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:"Event-Driven Architecture at the Core:"}),(0,i.jsx)(n.br,{}),"\n","The beating heart of Solace Agent Mesh is its event mesh\u2014a neural network for your AI components. This architecture creates a fluid, asynchronous communication layer where messages flow naturally between agents, gateways, and external systems. By decoupling senders from receivers, the mesh dramatically simplifies agent interactions, ensures message delivery even during component failures, and lets you add, remove, or restart components on the fly without disrupting workflows."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Breaking Down AI Silos:"}),(0,i.jsx)(n.br,{}),"\n","Specialized agents operate independently yet collaborate effortlessly\u2014like expert teammates rather than isolated tools."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Orchestrating Complex Workflows:"}),(0,i.jsx)(n.br,{}),"\n","Create sophisticated multi-agent processes where tasks flow naturally between specialists, executing in sequence or parallel based on dynamic needs."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Speaking a Common Language:"}),(0,i.jsx)(n.br,{}),"\n","The A2A protocol creates a universal communication standard, ensuring all agents and gateways understand each other regardless of their internal implementation."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Unifying AI Capabilities:"}),(0,i.jsx)(n.br,{}),"\n","Blend diverse AI models, custom tools (Python functions, MCP tools), and enterprise data sources into a cohesive ecosystem."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Connecting to Your World:"}),(0,i.jsx)(n.br,{}),"\n","Purpose-built gateways bridge the gap between the agent mesh and your existing systems\u2014web interfaces, Slack workspaces, APIs, and event streams."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Handling the Unpredictable:"}),(0,i.jsx)(n.br,{}),"\n","The event-driven backbone gracefully manages long-running tasks and asynchronous patterns that are inherent in AI agent interactions."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Adding Agents to Increase Capabilities"}),":\nEach new agent adds more capabilities to the system. Adding a new agent is not additive\u2014it is exponential. With each agent being able to enhance all other agents as they collaborate for more and more complex tasks."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Adding Gateways to Increase the Supported Use Cases"}),":\nEach new gateway opens up new use cases for the system. A new gateway can provide a new interface to the system, with a different system purpose and response rules."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Enterprise-Ready"}),":\nEngineered from the ground up for production deployment, this solution leverages expertise from Solace in building mission-critical distributed systems."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"why-choose-solace-agent-mesh",children:"Why Choose Solace Agent Mesh?"}),"\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:"Enterprise-Grade Performance:"}),(0,i.jsx)(n.br,{}),"\n","Built on Solace PubSub+ Event Broker, the mesh delivers high-throughput, fault-tolerant messaging that scales with your needs."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Plug-and-Play Extensibility:"}),(0,i.jsx)(n.br,{}),"\n","The event-driven architecture makes adding new capabilities remarkably simple. Deploy a new agent, and it instantly publishes its capabilities to the mesh. Other components discover it automatically\u2014no manual configuration, no downtime, no integration headaches."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Modular by Design:"}),(0,i.jsx)(n.br,{}),"\n","Every component\u2014agents, gateways, tools\u2014is a self-contained module you can reuse, replace, or enhance independently."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Configuration-Driven:"}),(0,i.jsx)(n.br,{}),"\n","YAML-based configuration gives you precise control over agent behavior, service integrations, and security settings without code changes."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Security-First Approach:"}),(0,i.jsx)(n.br,{}),"\n","The built-in authorization framework provides fine-grained access control over agents and tools based on user roles and scopes."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Resilient by Nature:"}),(0,i.jsx)(n.br,{}),"\n","Event-driven design creates responsive, self-healing interactions that recover gracefully from disruptions."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"real-world-applications",children:"Real-World Applications"}),"\n",(0,i.jsx)(n.p,{children:"Organizations are using Solace Agent Mesh in diverse scenarios:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Intelligent Enterprise Automation:"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Customer service systems that route inquiries to specialized agents based on intent and context."}),"\n",(0,i.jsx)(n.li,{children:"Data processing pipelines where specialized agents transform, analyze, and enrich information from multiple sources."}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"AI Task Specialization:"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Image analysis workflows where one agent processes visual data and delegates text generation to a language specialist."}),"\n",(0,i.jsx)(n.li,{children:"Document processing systems that extract text, summarize content, and translate results\u2014each step handled by the perfect specialist."}),"\n"]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Human-AI Collaboration:"}),(0,i.jsx)(n.br,{}),"\n","Agents that perform complex tasks while keeping humans in the loop for approvals, clarifications, or expert guidance via web or chat interfaces."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Multi-Agent Research:"}),(0,i.jsx)(n.br,{}),"\n","A production-ready platform for exploring agent collaboration patterns, delegation strategies, and distributed AI problem-solving."]}),"\n"]}),"\n",(0,i.jsxs)(n.li,{children:["\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Data-Driven Intelligence:"}),(0,i.jsx)(n.br,{}),"\n","Agents that query databases, transform results, and generate visualizations based on natural language requests or system events."]}),"\n"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"evolution-through-usage",children:"Evolution Through Usage"}),"\n",(0,i.jsx)(n.p,{children:"Solace Agent Mesh grows with your needs. For example, at Solace we started with basic agents and have continuously expanded the system's capabilities:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Added specialized agents for JIRA and Confluence integration"}),"\n",(0,i.jsx)(n.li,{children:"Implemented multiple interface options including browser-based user interfaces and REST API gateways"}),"\n",(0,i.jsx)(n.li,{children:"Integrated with various AI models and data sources"}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"for-developers",children:"For Developers"}),"\n",(0,i.jsx)(n.p,{children:"Solace Agent Mesh is an agentic framework that provides several key technical advantages:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Complete Observability"}),": Because all communication flows through the event broker, you can monitor and debug the entire system in real-time"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Flexible Integration"}),": Built-in support for common enterprise systems and AI frameworks"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Plugin Architecture"}),": Easily extend the system with custom agents and gateways"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Developer Tools"}),": Comprehensive CLI and debugging utilities"]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"getting-started",children:"Getting Started"}),"\n",(0,i.jsx)(n.p,{children:"Whether you're building a proof-of-concept or planning a production deployment, Solace Agent Mesh provides the foundation you need. For more information, see:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.a,{href:"/solace-agent-mesh/docs/documentation/getting-started/installation",children:"Installation"}),": For installing and setting up Solace Agent Mesh."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.a,{href:"/solace-agent-mesh/docs/documentation/getting-started/quick-start",children:"Quick Start"}),": For creating a project, build, and run Solace Agent Mesh."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.a,{href:"/solace-agent-mesh/docs/documentation/getting-started/component-overview",children:"Components Overview"}),": Understand the parts of Solace Agent Mesh."]}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(d,{...e})}):d(e)}},1351:(e,n,t)=>{t.d(n,{A:()=>s});const s=t.p+"assets/images/Solace_AI_Framework_With_Broker-85f0a306a9bcdd20b390b7a949f6d862.png"},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)}}}]);
@@ -1 +0,0 @@
1
- "use strict";(self.webpackChunksolace_agenitc_mesh_docs=self.webpackChunksolace_agenitc_mesh_docs||[]).push([[6719],{1786:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>a,default:()=>h,frontMatter:()=>i,metadata:()=>o,toc:()=>c});const o=JSON.parse('{"id":"documentation/user-guide/creating-python-tools","title":"Creating Python Tools","description":"Solace Agent Mesh (SAM) provides a powerful and unified system for creating custom agent tools using Python. This is the primary way to extend an agent\'s capabilities with your own business logic, integrate with proprietary APIs, or perform specialized data processing.","source":"@site/docs/documentation/user-guide/creating-python-tools.md","sourceDirName":"documentation/user-guide","slug":"/documentation/user-guide/creating-python-tools","permalink":"/solace-agent-mesh/docs/documentation/user-guide/creating-python-tools","draft":false,"unlisted":false,"editUrl":"https://github.com/SolaceLabs/solace-agent-mesh/edit/main/docs/docs/documentation/user-guide/creating-python-tools.md","tags":[],"version":"current","sidebarPosition":35,"frontMatter":{"title":"Creating Python Tools","sidebar_position":35},"sidebar":"docSidebar","previous":{"title":"Create Agents","permalink":"/solace-agent-mesh/docs/documentation/user-guide/create-agents"},"next":{"title":"Create Gateways","permalink":"/solace-agent-mesh/docs/documentation/user-guide/create-gateways"}}');var s=t(4848),r=t(8453);const i={title:"Creating Python Tools",sidebar_position:35},a="Creating Python Tools",l={},c=[{value:"Tool Creation Patterns",id:"tool-creation-patterns",level:2},{value:"Pattern 1: Simple Function-Based Tools",id:"pattern-1-simple-function-based-tools",level:2},{value:"Step 1: Write the Tool Function",id:"step-1-write-the-tool-function",level:3},{value:"Step 2: Configure the Tool",id:"step-2-configure-the-tool",level:3},{value:"Pattern 2: Advanced Single-Class Tools",id:"pattern-2-advanced-single-class-tools",level:2},{value:"Step 1: Create the <code>DynamicTool</code> Class",id:"step-1-create-the-dynamictool-class",level:3},{value:"Step 2: Configure the Tool",id:"step-2-configure-the-tool-1",level:3},{value:"Pattern 3: The Tool Provider Factory",id:"pattern-3-the-tool-provider-factory",level:2},{value:"Step 1: Create the Provider and Tools",id:"step-1-create-the-provider-and-tools",level:3},{value:"Step 2: Configure the Provider",id:"step-2-configure-the-provider",level:3}];function d(e){const n={code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",hr:"hr",li:"li",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,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.header,{children:(0,s.jsx)(n.h1,{id:"creating-python-tools",children:"Creating Python Tools"})}),"\n",(0,s.jsx)(n.p,{children:"Solace Agent Mesh (SAM) provides a powerful and unified system for creating custom agent tools using Python. This is the primary way to extend an agent's capabilities with your own business logic, integrate with proprietary APIs, or perform specialized data processing."}),"\n",(0,s.jsxs)(n.p,{children:["This guide covers the different patterns for creating custom tools, all of which are configured using the versatile ",(0,s.jsx)(n.code,{children:"tool_type: python"}),"."]}),"\n",(0,s.jsx)(n.h2,{id:"tool-creation-patterns",children:"Tool Creation Patterns"}),"\n",(0,s.jsx)(n.p,{children:"There are three primary patterns for creating Python tools, ranging from simple to advanced. You can choose the best pattern for your needs, and even mix and match them within the same project."}),"\n",(0,s.jsxs)(n.table,{children:[(0,s.jsx)(n.thead,{children:(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.th,{children:"Pattern"}),(0,s.jsx)(n.th,{children:"Best For"}),(0,s.jsx)(n.th,{children:"Key Feature"})]})}),(0,s.jsxs)(n.tbody,{children:[(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsx)(n.strong,{children:"Function-Based"})}),(0,s.jsx)(n.td,{children:"Simple, self-contained tools with static inputs."}),(0,s.jsx)(n.td,{children:"Quick and easy; uses function signature."})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsxs)(n.strong,{children:["Single ",(0,s.jsx)(n.code,{children:"DynamicTool"})," Class"]})}),(0,s.jsx)(n.td,{children:"Tools that require complex logic or a programmatically defined interface."}),(0,s.jsx)(n.td,{children:"Full control over the tool's definition."})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{children:(0,s.jsxs)(n.strong,{children:[(0,s.jsx)(n.code,{children:"DynamicToolProvider"})," Class"]})}),(0,s.jsx)(n.td,{children:"Generating multiple related tools from a single, configurable source."}),(0,s.jsx)(n.td,{children:"Maximum scalability and code reuse."})]})]})]}),"\n",(0,s.jsxs)(n.p,{children:["All three patterns are configured in your agent's YAML file under the ",(0,s.jsx)(n.code,{children:"tools"})," list with ",(0,s.jsx)(n.code,{children:"tool_type: python"}),"."]}),"\n",(0,s.jsx)(n.hr,{}),"\n",(0,s.jsx)(n.h2,{id:"pattern-1-simple-function-based-tools",children:"Pattern 1: Simple Function-Based Tools"}),"\n",(0,s.jsxs)(n.p,{children:["This is the most straightforward way to create a custom tool. You define a standard Python ",(0,s.jsx)(n.code,{children:"async"})," function, and SAM automatically introspects its signature and docstring to create the tool definition for the LLM."]}),"\n",(0,s.jsx)(n.h3,{id:"step-1-write-the-tool-function",children:"Step 1: Write the Tool Function"}),"\n",(0,s.jsxs)(n.p,{children:["Create a Python file (e.g., ",(0,s.jsx)(n.code,{children:"src/my_agent/tools.py"}),") and define your tool."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-python",children:'# src/my_agent/tools.py\nfrom typing import Any, Dict, Optional\nfrom google.adk.tools import ToolContext\n\nasync def greet_user(\n name: str,\n tool_context: Optional[ToolContext] = None,\n tool_config: Optional[Dict[str, Any]] = None\n) -> Dict[str, Any]:\n """\n Greets a user with a personalized message.\n\n Args:\n name: The name of the person to greet.\n\n Returns:\n A dictionary with the greeting message.\n """\n greeting_prefix = "Hello"\n if tool_config:\n greeting_prefix = tool_config.get("greeting_prefix", "Hello")\n\n greeting_message = f"{greeting_prefix}, {name}! Welcome to Solace Agent Mesh!"\n\n return {\n "status": "success",\n "message": greeting_message\n }\n'})}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"Key Requirements:"})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["The function must be ",(0,s.jsx)(n.code,{children:"async def"}),"."]}),"\n",(0,s.jsxs)(n.li,{children:["The function's docstring is used as the tool's ",(0,s.jsx)(n.code,{children:"description"})," for the LLM."]}),"\n",(0,s.jsxs)(n.li,{children:["Type hints (",(0,s.jsx)(n.code,{children:"str"}),", ",(0,s.jsx)(n.code,{children:"int"}),", ",(0,s.jsx)(n.code,{children:"bool"}),") are used to generate the parameter schema."]}),"\n",(0,s.jsxs)(n.li,{children:["The function should accept ",(0,s.jsx)(n.code,{children:"tool_context"})," and ",(0,s.jsx)(n.code,{children:"tool_config"})," as optional keyword arguments to receive framework context and YAML configuration."]}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"step-2-configure-the-tool",children:"Step 2: Configure the Tool"}),"\n",(0,s.jsxs)(n.p,{children:["In your agent's YAML configuration, add a ",(0,s.jsx)(n.code,{children:"tool_type: python"})," block and point it to your function."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:'# In your agent\'s app_config:\ntools:\n - tool_type: python\n component_module: "my_agent.tools"\n function_name: "greet_user"\n tool_config:\n greeting_prefix: "Greetings"\n'})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"component_module"}),": The Python module path to your tools file."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"function_name"}),": The exact name of the function to load."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.code,{children:"tool_config"}),": An optional dictionary passed to your tool at runtime."]}),"\n"]}),"\n",(0,s.jsx)(n.hr,{}),"\n",(0,s.jsx)(n.h2,{id:"pattern-2-advanced-single-class-tools",children:"Pattern 2: Advanced Single-Class Tools"}),"\n",(0,s.jsxs)(n.p,{children:["For tools that require more complex logic\u2014such as defining their interface programmatically based on configuration\u2014you can use a class that inherits from ",(0,s.jsx)(n.code,{children:"DynamicTool"}),"."]}),"\n",(0,s.jsxs)(n.h3,{id:"step-1-create-the-dynamictool-class",children:["Step 1: Create the ",(0,s.jsx)(n.code,{children:"DynamicTool"})," Class"]}),"\n",(0,s.jsxs)(n.p,{children:["Instead of a function, define a class that implements the ",(0,s.jsx)(n.code,{children:"DynamicTool"})," abstract base class."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-python",children:'# src/my_agent/tools.py\nfrom typing import Optional, Dict, Any\nfrom google.genai import types as adk_types\nfrom solace_agent_mesh.agent.tools.dynamic_tool import DynamicTool\n\nclass WeatherTool(DynamicTool):\n """A dynamic tool that fetches current weather information."""\n\n @property\n def tool_name(self) -> str:\n return "get_current_weather"\n\n @property\n def tool_description(self) -> str:\n return "Get the current weather for a specified location."\n\n @property\n def parameters_schema(self) -> adk_types.Schema:\n # Programmatically define the tool\'s parameters\n return adk_types.Schema(\n type=adk_types.Type.OBJECT,\n properties={\n "location": adk_types.Schema(type=adk_types.Type.STRING, description="The city and state/country."),\n "units": adk_types.Schema(type=adk_types.Type.STRING, enum=["celsius", "fahrenheit"], nullable=True),\n },\n required=["location"],\n )\n\n async def _run_async_impl(self, args: Dict[str, Any], **kwargs) -> Dict[str, Any]:\n location = args["location"]\n # Access config via self.tool_config\n api_key = self.tool_config.get("api_key")\n if not api_key:\n return {"status": "error", "message": "API key not configured"}\n # ... implementation to call weather API ...\n return {"status": "success", "weather": "Sunny"}\n'})}),"\n",(0,s.jsx)(n.h3,{id:"step-2-configure-the-tool-1",children:"Step 2: Configure the Tool"}),"\n",(0,s.jsxs)(n.p,{children:["The YAML configuration is very similar. You can either specify the ",(0,s.jsx)(n.code,{children:"class_name"})," or let SAM auto-discover it if it's the only ",(0,s.jsx)(n.code,{children:"DynamicTool"})," in the module."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"# In your agent's app_config:\ntools:\n - tool_type: python\n component_module: \"my_agent.tools\"\n # class_name: WeatherTool # Optional if it's the only one\n tool_config:\n api_key: ${WEATHER_API_KEY}\n"})}),"\n",(0,s.jsx)(n.hr,{}),"\n",(0,s.jsx)(n.h2,{id:"pattern-3-the-tool-provider-factory",children:"Pattern 3: The Tool Provider Factory"}),"\n",(0,s.jsx)(n.p,{children:"This is the most powerful pattern, designed for generating multiple, related tools from a single module and configuration block. It's perfect for creating toolsets based on external schemas, database tables, or other dynamic sources."}),"\n",(0,s.jsx)(n.h3,{id:"step-1-create-the-provider-and-tools",children:"Step 1: Create the Provider and Tools"}),"\n",(0,s.jsxs)(n.p,{children:["In your tools module, you define your ",(0,s.jsx)(n.code,{children:"DynamicTool"})," classes as before, but you also create a ",(0,s.jsx)(n.strong,{children:"provider"})," class that inherits from ",(0,s.jsx)(n.code,{children:"DynamicToolProvider"}),". This provider acts as a factory."]}),"\n",(0,s.jsxs)(n.p,{children:["You can also use the ",(0,s.jsx)(n.code,{children:"@register_tool"})," decorator on simple functions to have them automatically included by the provider."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-python",children:'# src/my_agent/database_tools.py\nfrom typing import Optional, Dict, Any, List\nfrom google.genai import types as adk_types\nfrom solace_agent_mesh.agent.tools.dynamic_tool import DynamicTool, DynamicToolProvider\n\n# --- Tool Implementations ---\nclass DatabaseQueryTool(DynamicTool):\n # ... (implementation as in previous examples) ...\n pass\n\nclass DatabaseSchemaTool(DynamicTool):\n # ... (implementation as in previous examples) ...\n pass\n\n# --- Tool Provider Implementation ---\nclass DatabaseToolProvider(DynamicToolProvider):\n """A factory that creates all database-related tools."""\n\n # Use a decorator for a simple, function-based tool\n\n def create_tools(self, tool_config: Optional[dict] = None) -> List[DynamicTool]:\n """\n Generates a list of all database tools, passing the shared\n configuration to each one.\n """\n # 1. Create tools from any decorated functions in this module\n tools = self._create_tools_from_decorators(tool_config)\n\n # 2. Programmatically create and add more complex tools\n if tool_config and tool_config.get("connection_string"):\n tools.append(DatabaseQueryTool(tool_config=tool_config))\n tools.append(DatabaseSchemaTool(tool_config=tool_config))\n\n return tools\n\n# NOTE that you must use the decorator outside of any class with the provider\'s class name.\n@DatabaseToolProvider.register_tool\nasync def get_database_server_version(tool_config: dict, **kwargs) -> dict:\n """Returns the version of the connected PostgreSQL server."""\n # ... implementation ...\n return {"version": "PostgreSQL 15.3"}\n\n'})}),"\n",(0,s.jsx)(n.h3,{id:"step-2-configure-the-provider",children:"Step 2: Configure the Provider"}),"\n",(0,s.jsxs)(n.p,{children:["You only need a single YAML block. SAM will automatically detect the ",(0,s.jsx)(n.code,{children:"DynamicToolProvider"})," and use it to load all the tools it generates."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:'# In your agent\'s app_config:\ntools:\n # This single block loads get_database_server_version,\n # execute_database_query, and get_database_schema.\n - tool_type: python\n component_module: "my_agent.database_tools"\n tool_config:\n connection_string: ${DB_CONNECTION_STRING}\n max_rows: 1000\n'})}),"\n",(0,s.jsx)(n.p,{children:"This approach is incredibly scalable, as one configuration entry can bootstrap an entire suite of dynamically generated tools."})]})}function h(e={}){const{wrapper:n}={...(0,r.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>i,x:()=>a});var o=t(6540);const s={},r=o.createContext(s);function i(e){const n=o.useContext(r);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:i(e.components),o.createElement(r.Provider,{value:n},e.children)}}}]);
@@ -1 +0,0 @@
1
- "use strict";(self.webpackChunksolace_agenitc_mesh_docs=self.webpackChunksolace_agenitc_mesh_docs||[]).push([[9639],{2888:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>r,contentTitle:()=>l,default:()=>h,frontMatter:()=>o,metadata:()=>a,toc:()=>c});const a=JSON.parse('{"id":"documentation/tutorials/slack-integration","title":"Slack Integration","description":"This tutorial integrates a Slack interface into Solace Agent Mesh, enabling interaction with the system directly from your Slack workspace and channels.","source":"@site/docs/documentation/tutorials/slack-integration.md","sourceDirName":"documentation/tutorials","slug":"/documentation/tutorials/slack-integration","permalink":"/solace-agent-mesh/docs/documentation/tutorials/slack-integration","draft":false,"unlisted":false,"editUrl":"https://github.com/SolaceLabs/solace-agent-mesh/edit/main/docs/docs/documentation/tutorials/slack-integration.md","tags":[],"version":"current","sidebarPosition":60,"frontMatter":{"title":"Slack Integration","sidebar_position":60},"sidebar":"docSidebar","previous":{"title":"MongoDB Integration","permalink":"/solace-agent-mesh/docs/documentation/tutorials/mongodb-integration"},"next":{"title":"RAG Integration","permalink":"/solace-agent-mesh/docs/documentation/tutorials/rag-integration"}}');var s=t(4848),i=t(8453);const o={title:"Slack Integration",sidebar_position:60},l="Slack Integration",r={},c=[{value:"Setting Up the Environment",id:"setting-up-the-environment",level:2},{value:"Creating the Slack App",id:"creating-the-slack-app",level:2},{value:"App-Level Tokens",id:"app-level-tokens",level:3},{value:"Installing the App in Your Slack Workspace",id:"installing-the-app-in-your-slack-workspace",level:3},{value:"Installing the Slack Gateway",id:"installing-the-slack-gateway",level:2},{value:"Running the Slack Gateway",id:"running-the-slack-gateway",level:2},{value:"Testing the Installation",id:"testing-the-installation",level:2}];function d(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",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:"slack-integration",children:"Slack Integration"})}),"\n",(0,s.jsx)(n.p,{children:"This tutorial integrates a Slack interface into Solace Agent Mesh, enabling interaction with the system directly from your Slack workspace and channels."}),"\n",(0,s.jsx)(n.admonition,{title:"Learn about gateways",type:"info",children:(0,s.jsxs)(n.p,{children:["Read about ",(0,s.jsx)(n.a,{href:"/solace-agent-mesh/docs/documentation/concepts/gateways",children:"Gateways"})," before you start this tutorial."]})}),"\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/getting-started/installation",children:"install Solace Agent Mesh and Solace Mesh Agent (SAM) CLI"}),", and then ",(0,s.jsx)(n.a,{href:"/solace-agent-mesh/docs/documentation/getting-started/quick-start",children:"create a new Solace Agent Mesh project"})," or ",(0,s.jsx)(n.a,{href:"/solace-agent-mesh/docs/documentation/concepts/plugins#create-a-plugin",children:"create a new gateway plugin"}),"."]}),"\n",(0,s.jsx)(n.h2,{id:"creating-the-slack-app",children:"Creating the Slack App"}),"\n",(0,s.jsxs)(n.p,{children:["Next, create a ",(0,s.jsx)(n.a,{href:"https://api.slack.com/apps",children:"Slack Application"})," in your workspace."]}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["Go to the ",(0,s.jsx)(n.a,{href:"https://api.slack.com/apps",children:"Slack Application"})," website."]}),"\n",(0,s.jsxs)(n.li,{children:["Select ",(0,s.jsx)(n.strong,{children:"Your Apps"})," and click ",(0,s.jsx)(n.strong,{children:"Create New App"}),"."]}),"\n",(0,s.jsxs)(n.li,{children:["Choose ",(0,s.jsx)(n.strong,{children:"From a manifest"})," and apply the following configuration.","\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"You can customize the name and description, but keep the rest of the configuration and settings unchanged."}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:"display_information:\n name: solace-agent-mesh-bot\n description: An app to integrate with Solace Agent Mesh\nfeatures:\n app_home:\n home_tab_enabled: false\n messages_tab_enabled: true\n messages_tab_read_only_enabled: false\n bot_user:\n display_name: Solace Agent Mesh\n always_online: false\noauth_config:\n scopes:\n bot:\n - app_mentions:read\n - bookmarks:read\n - channels:history\n - channels:join\n - channels:manage\n - channels:read\n - chat:write\n - chat:write.customize\n - chat:write.public\n - files:read\n - files:write\n - groups:history\n - groups:read\n - groups:write\n - im:history\n - im:read\n - im:write\n - links:read\n - links:write\n - mpim:history\n - mpim:read\n - mpim:write\n - pins:read\n - pins:write\n - reactions:read\n - reactions:write\n - reminders:read\n - reminders:write\n - team:read\n - usergroups:read\n - usergroups:write\n - users.profile:read\n - users:read.email\n - users:read\n - users:write\n - conversations.connect:read\n - conversations.connect:write\n - incoming-webhook\nsettings:\n event_subscriptions:\n bot_events:\n - app_mention\n - message.groups\n - message.im\n interactivity:\n is_enabled: true\n org_deploy_enabled: false\n socket_mode_enabled: true\n token_rotation_enabled: false\n"})}),"\n",(0,s.jsxs)(n.p,{children:["Then select ",(0,s.jsx)(n.code,{children:"Create"})," to create your new App."]}),"\n",(0,s.jsx)(n.h3,{id:"app-level-tokens",children:"App-Level Tokens"}),"\n",(0,s.jsxs)(n.p,{children:["In your created App, select ",(0,s.jsx)(n.code,{children:"Basic Information"})," under ",(0,s.jsx)(n.code,{children:"Settings"}),". Scroll down to ",(0,s.jsx)(n.code,{children:"App-Level Tokens"})," and click ",(0,s.jsx)(n.code,{children:"Generate Token and Scopes"}),"."]}),"\n",(0,s.jsxs)(n.p,{children:["Provide your token a name, add all available scopes, and then click ",(0,s.jsx)(n.code,{children:"Generate"}),"."]}),"\n",(0,s.jsxs)(n.p,{children:["Make note of the resulting application token (beginning with ",(0,s.jsx)(n.code,{children:"xapp-"}),") - you need it in a future step."]}),"\n",(0,s.jsx)(n.h3,{id:"installing-the-app-in-your-slack-workspace",children:"Installing the App in Your Slack Workspace"}),"\n",(0,s.jsxs)(n.p,{children:["Next, select ",(0,s.jsx)(n.strong,{children:"Install App"})," under ",(0,s.jsx)(n.strong,{children:"Settings"})," and follow the installation flow to install the App in your workspace."]}),"\n",(0,s.jsxs)(n.p,{children:["After installation, the bot token (beginning with ",(0,s.jsx)(n.code,{children:"xoxb-"}),") is visible. Make note of this token."]}),"\n",(0,s.jsx)(n.h2,{id:"installing-the-slack-gateway",children:"Installing the Slack Gateway"}),"\n",(0,s.jsx)(n.p,{children:"After configuring your Slack App, the next step is to add the Slack gateway to Solace Agent Mesh."}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Add the gateway plugin using Solace Agent Mesh (SAM) CLI:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-sh",children:"sam plugin add slack-bot --plugin sam-slack\n"})}),"\n",(0,s.jsxs)(n.p,{children:["You can change ",(0,s.jsx)(n.code,{children:"slack-bot"})," to any name you prefer for your gateway."]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"Configure the required environment variables:"}),"\n",(0,s.jsxs)(n.p,{children:["The Slack interface requires two authentication tokens. Add these to your ",(0,s.jsx)(n.code,{children:".env"})," file in the project root directory using the tokens generated during Slack App setup:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-env",children:"SLACK_BOT_TOKEN=xoxb-xxxxxxxxxx\nSLACK_APP_TOKEN=xapp-xxxxxxxxxx\n"})}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.admonition,{type:"tip",children:(0,s.jsxs)(n.p,{children:["You can further customize the Slack gateway by updating the ",(0,s.jsx)(n.code,{children:"configs/gateways/slack-bot.yaml"})," file. This file contains the configuration for the Slack gateway, including the initial status message, the gateway system purpose, and response format."]})}),"\n",(0,s.jsx)(n.h2,{id:"running-the-slack-gateway",children:"Running the Slack Gateway"}),"\n",(0,s.jsx)(n.p,{children:"Launch the Slack gateway with:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-sh",children:"sam run configs/gateways/slack-bot.yaml\n"})}),"\n",(0,s.jsxs)(n.p,{children:["For detailed information about available SAM CLI commands, see ",(0,s.jsx)(n.a,{href:"/solace-agent-mesh/docs/documentation/concepts/cli",children:"the Solace Agent Mesh CLI"}),"."]}),"\n",(0,s.jsx)(n.h2,{id:"testing-the-installation",children:"Testing the Installation"}),"\n",(0,s.jsx)(n.p,{children:"To test your installation:"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsx)(n.li,{children:"Open your Slack workspace in the desktop app or browser."}),"\n",(0,s.jsxs)(n.li,{children:["Find and click on the ",(0,s.jsx)(n.strong,{children:"Solace Agent Mesh"})," app under the ",(0,s.jsx)(n.strong,{children:"Apps"})," section."]}),"\n",(0,s.jsxs)(n.li,{children:["Send a test message by typing ",(0,s.jsx)(n.code,{children:"hello"})," and click ",(0,s.jsx)(n.strong,{children:"Enter"}),"."]}),"\n",(0,s.jsxs)(n.li,{children:["You should see:","\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:'A "Chatbot is thinking..." status message'}),"\n",(0,s.jsx)(n.li,{children:"A response from the chatbot within a few seconds"}),"\n"]}),"\n"]}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>o,x:()=>l});var a=t(6540);const s={},i=a.createContext(s);function o(e){const n=a.useContext(i);return a.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(s):e.components||s:o(e.components),a.createElement(i.Provider,{value:n},e.children)}}}]);
@@ -1 +0,0 @@
1
- "use strict";(self.webpackChunksolace_agenitc_mesh_docs=self.webpackChunksolace_agenitc_mesh_docs||[]).push([[6634],{1893:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>a,default:()=>h,frontMatter:()=>r,metadata:()=>o,toc:()=>l});const o=JSON.parse('{"id":"documentation/getting-started/component-overview","title":"Component Overview","description":"Solace Agent Mesh (SAM) is built on event-driven architecture principles using the A2A (Agent-to-Agent) protocol, with all components communicating through a standardized protocol over Solace PubSub+. This architectural choice enables loose coupling between components, making the system highly flexible and scalable.","source":"@site/docs/documentation/getting-started/component-overview.md","sourceDirName":"documentation/getting-started","slug":"/documentation/getting-started/component-overview","permalink":"/solace-agent-mesh/docs/documentation/getting-started/component-overview","draft":false,"unlisted":false,"editUrl":"https://github.com/SolaceLabs/solace-agent-mesh/edit/main/docs/docs/documentation/getting-started/component-overview.md","tags":[],"version":"current","sidebarPosition":40,"frontMatter":{"title":"Component Overview","sidebar_position":40},"sidebar":"docSidebar","previous":{"title":"Quick Start","permalink":"/solace-agent-mesh/docs/documentation/getting-started/quick-start"},"next":{"title":"Configurations","permalink":"/solace-agent-mesh/docs/documentation/getting-started/configurations"}}');var s=n(4848),i=n(8453);const r={title:"Component Overview",sidebar_position:40},a="Component Overview",c={},l=[];function d(e){const t={a:"a",h1:"h1",header:"header",li:"li",ol:"ol",p:"p",strong:"strong",...(0,i.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.header,{children:(0,s.jsx)(t.h1,{id:"component-overview",children:"Component Overview"})}),"\n",(0,s.jsx)(t.p,{children:"Solace Agent Mesh (SAM) is built on event-driven architecture principles using the A2A (Agent-to-Agent) protocol, with all components communicating through a standardized protocol over Solace PubSub+. This architectural choice enables loose coupling between components, making the system highly flexible and scalable."}),"\n",(0,s.jsx)(t.p,{children:'SAM integrates the Google Agent Development Kit (ADK) with a Solace event mesh to provide a "Universal A2A Agent Host" that enables distributed AI agent communication. Each component is designed to perform specific roles while working together seamlessly through the A2A protocol.'}),"\n",(0,s.jsx)(t.p,{children:"The key components that make up SAM are:"}),"\n",(0,s.jsxs)(t.ol,{children:["\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.strong,{children:"PubSub+ Event Broker or Event Mesh"}),": The central nervous system of the framework, facilitating A2A protocol communication between all components. ",(0,s.jsx)(t.a,{href:"https://solace.com/products/event-broker/",children:"more \ud83d\udd17"})]}),"\n"]}),"\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.strong,{children:"A2A Protocol & Agent Registry"}),": The standardized communication protocol that enables agent discovery, task delegation, and peer-to-peer communication."]}),"\n"]}),"\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.strong,{children:"Orchestrator"}),": A specialized agent responsible for breaking down requests into tasks and managing the overall workflow. ",(0,s.jsx)(t.a,{href:"/solace-agent-mesh/docs/documentation/concepts/orchestrator",children:"more \ud83d\udd17"})]}),"\n"]}),"\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.strong,{children:"Gateways"}),": The entry and exit points for the system, providing various interfaces (REST, HTTP SSE, webhooks, event mesh) that translate external requests into A2A protocol messages. ",(0,s.jsx)(t.a,{href:"/solace-agent-mesh/docs/documentation/concepts/gateways",children:"more \ud83d\udd17"})]}),"\n"]}),"\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.strong,{children:"Agents"}),": ADK-powered processing units that communicate through the A2A protocol, each bringing specialized capabilities and tools. ",(0,s.jsx)(t.a,{href:"/solace-agent-mesh/docs/documentation/concepts/agents",children:"more \ud83d\udd17"})]}),"\n"]}),"\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.strong,{children:"ADK Runtime"}),": The Google Agent Development Kit provides the core intelligence layer with tool execution, session management, and artifact handling capabilities."]}),"\n"]}),"\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.strong,{children:"Built-in Tools"}),": Comprehensive tool ecosystem including artifact management, data analysis, web tools, and peer agent delegation capabilities."]}),"\n"]}),"\n",(0,s.jsxs)(t.li,{children:["\n",(0,s.jsxs)(t.p,{children:[(0,s.jsx)(t.strong,{children:"Real-time Monitoring and Debugging Component"}),": Enables real-time monitoring of system activities and provides interactive debugging capabilities for administrators. ",(0,s.jsx)(t.a,{href:"/solace-agent-mesh/docs/documentation/deployment/observability",children:"more \ud83d\udd17"})]}),"\n"]}),"\n"]})]})}function h(e={}){const{wrapper:t}={...(0,i.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>r,x:()=>a});var o=n(6540);const s={},i=o.createContext(s);function r(e){const t=o.useContext(i);return o.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function a(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),o.createElement(i.Provider,{value:t},e.children)}}}]);
@@ -1 +0,0 @@
1
- "use strict";(self.webpackChunksolace_agenitc_mesh_docs=self.webpackChunksolace_agenitc_mesh_docs||[]).push([[3486],{3782:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>r,default:()=>E,frontMatter:()=>i,metadata:()=>s,toc:()=>l});const s=JSON.parse('{"id":"documentation/Enterprise/installation","title":"Installation","description":"Prepare the Enterprise Image","source":"@site/docs/documentation/Enterprise/installation.md","sourceDirName":"documentation/Enterprise","slug":"/documentation/Enterprise/installation","permalink":"/solace-agent-mesh/docs/documentation/Enterprise/installation","draft":false,"unlisted":false,"editUrl":"https://github.com/SolaceLabs/solace-agent-mesh/edit/main/docs/docs/documentation/Enterprise/installation.md","tags":[],"version":"current","sidebarPosition":5,"frontMatter":{"title":"Installation","sidebar_position":5},"sidebar":"docSidebar","previous":{"title":"A2A Technical Migration Map","permalink":"/solace-agent-mesh/docs/documentation/Migrations/A2A Upgrade To 0.3.0/a2a-technical-migration-map"},"next":{"title":"SSO","permalink":"/solace-agent-mesh/docs/documentation/Enterprise/single-sign-on"}}');var a=t(4848),o=t(8453);const i={title:"Installation",sidebar_position:5},r=void 0,c={},l=[{value:"Prepare the Enterprise Image",id:"prepare-the-enterprise-image",level:2},{value:"Running SAM Enterprise",id:"running-sam-enterprise",level:2},{value:"Development Use Case",id:"development-use-case",level:3},{value:"Production Use Case",id:"production-use-case",level:3}];function d(e){const n={a:"a",admonition:"admonition",code:"code",h2:"h2",h3:"h3",p:"p",pre:"pre",...(0,o.R)(),...e.components};return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(n.h2,{id:"prepare-the-enterprise-image",children:"Prepare the Enterprise Image"}),"\n",(0,a.jsxs)(n.p,{children:["Download the latest enterprise docker image tarball from the ",(0,a.jsx)(n.a,{href:"https://products.solace.com/",children:"Solace Product Portal"}),"."]}),"\n",(0,a.jsx)(n.p,{children:"Load the image using Docker with the following command."}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"docker load -i solace-agent-mesh-enterprise-<tag>.tar\n"})}),"\n",(0,a.jsx)(n.p,{children:"Once loaded, you can verify the image locally using the following command:"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:"docker images\n"})}),"\n",(0,a.jsx)(n.h2,{id:"running-sam-enterprise",children:"Running SAM Enterprise"}),"\n",(0,a.jsx)(n.p,{children:"Here are two examples of Docker run commands for both a development use case as well as a production use case:"}),"\n",(0,a.jsx)(n.admonition,{type:"tip",children:(0,a.jsxs)(n.p,{children:["You may need to include ",(0,a.jsx)(n.code,{children:"--platform linux/amd64"})," depending on the host machine you\u2019re using."]})}),"\n",(0,a.jsx)(n.h3,{id:"development-use-case",children:"Development Use Case"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:'docker run -itd -p 8000:8000 \\\n -e LLM_SERVICE_API_KEY="<YOUR_LLM_TOKEN>" \\\n -e LLM_SERVICE_ENDPOINT="<YOUR_LLM_SERVICE_ENDPOINT>" \\\n -e LLM_SERVICE_PLANNING_MODEL_NAME="<YOUR_MODEL_NAME>" \\\n -e LLM_SERVICE_GENERAL_MODEL_NAME="<YOUR_MODEL_NAME>" \\\n -e NAMESPACE="<YOUR_NAMESPACE>" \\\n -e SOLACE_DEV_MODE="true" \\\n --name sam-ent-dev \\\nsolace-agent-mesh-enterprise:<tag>\n'})}),"\n",(0,a.jsx)(n.h3,{id:"production-use-case",children:"Production Use Case"}),"\n",(0,a.jsx)(n.pre,{children:(0,a.jsx)(n.code,{className:"language-bash",children:'docker run -itd -p 8000:8000 \\\n -e LLM_SERVICE_API_KEY="<YOUR_LLM_TOKEN>" \\\n -e LLM_SERVICE_ENDPOINT="<YOUR_LLM_SERVICE_ENDPOINT>" \\\n -e LLM_SERVICE_PLANNING_MODEL_NAME="<YOUR_MODEL_NAME>" \\\n -e LLM_SERVICE_GENERAL_MODEL_NAME="<YOUR_MODEL_NAME>" \\\n -e NAMESPACE="<YOUR_NAMESPACE>" \\\n -e SOLACE_DEV_MODE="false" \\\n -e SOLACE_BROKER_URL="<YOUR_BROKER_URL>" \\\n -e SOLACE_BROKER_VPN="<YOUR_BROKER_VPN>" \\\n -e SOLACE_BROKER_USERNAME="<YOUR_BROKER_USERNAME>" \\\n -e SOLACE_BROKER_PASSWORD="<YOUR_BROKER_PASSWORD>" \\\n --name sam-ent-prod \\\nsolace-agent-mesh-enterprise:<tag>\n'})}),"\n",(0,a.jsxs)(n.p,{children:["You can then access SAM Enterprise UI through ",(0,a.jsx)(n.a,{href:"http://localhost:8000",children:"http://localhost:8000"})]})]})}function E(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:()=>r});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 r(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)}}}]);