solace-agent-mesh 1.5.0__py3-none-any.whl → 1.6.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.
- solace_agent_mesh/agent/adk/callbacks.py +14 -17
- solace_agent_mesh/agent/adk/embed_resolving_mcp_toolset.py +3 -1
- solace_agent_mesh/agent/adk/intelligent_mcp_callbacks.py +2 -1
- solace_agent_mesh/agent/adk/mcp_content_processor.py +2 -1
- solace_agent_mesh/agent/adk/models/lite_llm.py +123 -8
- solace_agent_mesh/agent/adk/models/oauth2_token_manager.py +245 -0
- solace_agent_mesh/agent/adk/runner.py +3 -1
- solace_agent_mesh/agent/adk/services.py +4 -1
- solace_agent_mesh/agent/adk/setup.py +3 -1
- solace_agent_mesh/agent/adk/tool_wrapper.py +2 -2
- solace_agent_mesh/agent/protocol/event_handlers.py +42 -2
- solace_agent_mesh/agent/proxies/__init__.py +0 -0
- solace_agent_mesh/agent/proxies/a2a/__init__.py +3 -0
- solace_agent_mesh/agent/proxies/a2a/app.py +55 -0
- solace_agent_mesh/agent/proxies/a2a/component.py +1115 -0
- solace_agent_mesh/agent/proxies/a2a/config.py +140 -0
- solace_agent_mesh/agent/proxies/a2a/oauth_token_cache.py +104 -0
- solace_agent_mesh/agent/proxies/base/__init__.py +3 -0
- solace_agent_mesh/agent/proxies/base/app.py +99 -0
- solace_agent_mesh/agent/proxies/base/component.py +619 -0
- solace_agent_mesh/agent/proxies/base/config.py +85 -0
- solace_agent_mesh/agent/proxies/base/proxy_task_context.py +17 -0
- solace_agent_mesh/agent/sac/app.py +12 -4
- solace_agent_mesh/agent/sac/component.py +164 -9
- solace_agent_mesh/agent/tools/audio_tools.py +127 -9
- solace_agent_mesh/agent/tools/builtin_artifact_tools.py +3 -1
- solace_agent_mesh/agent/tools/builtin_data_analysis_tools.py +3 -1
- solace_agent_mesh/agent/tools/dynamic_tool.py +2 -1
- solace_agent_mesh/agent/tools/general_agent_tools.py +2 -1
- solace_agent_mesh/agent/tools/image_tools.py +2 -1
- solace_agent_mesh/agent/tools/peer_agent_tool.py +2 -1
- solace_agent_mesh/agent/tools/registry.py +3 -1
- solace_agent_mesh/agent/tools/test_tools.py +2 -1
- solace_agent_mesh/agent/tools/web_tools.py +12 -6
- solace_agent_mesh/agent/utils/artifact_helpers.py +144 -4
- solace_agent_mesh/agent/utils/config_parser.py +3 -1
- solace_agent_mesh/assets/docs/404.html +3 -3
- solace_agent_mesh/assets/docs/assets/js/{b7006a3a.73a79653.js → 032c2d61.f3d37824.js} +1 -1
- solace_agent_mesh/assets/docs/assets/js/0bcf40b7.c019ad46.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/15ba94aa.932dd2db.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/2131ec11.5c7a1f6e.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/{2334.622a6395.js → 2334.1cf50a20.js} +1 -1
- solace_agent_mesh/assets/docs/assets/js/240a0364.7eac6021.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/2e32b5e0.33f5d75b.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/341393d4.0fac2613.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/{3624.b524e433.js → 3624.0eaa1fd0.js} +1 -1
- solace_agent_mesh/assets/docs/assets/js/3a6c6137.f5940cfa.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/3ac1795d.76654dd9.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/3ff0015d.2be20244.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/509e993c.4c7a1a6d.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/547e15cc.2cbb060a.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/55b7b518.f2b1d1ba.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/5c2bd65f.eda4bcb2.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/6063ff4c.ef84f702.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/631738c7.a8b1ef8b.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/6a520c9d.ba015d81.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/6ad8f0bd.f4b15f3b.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/6d84eae0.4a5fbf39.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/6fdfefc7.99de744e.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/71da7b71.38583438.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/722f809d.965da774.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/742f027b.46c07808.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/77cf947d.48cb18a2.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/8024126c.56e59919.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/81a99df0.07034dd9.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/82fbfb93.139a1a1f.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/{8591.d7c16be6.js → 8591.5d015485.js} +2 -2
- solace_agent_mesh/assets/docs/assets/js/{8731.49e930c2.js → 8731.6c1dbf0c.js} +1 -1
- solace_agent_mesh/assets/docs/assets/js/924ffdeb.8095e148.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/945fb41e.6f4cdffd.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/94e8668d.b5ddb7a1.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/9bb13469.dd1c9b54.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/9e9d0a82.570c057b.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/ab9708a8.3e6dd091.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/ad71b5ed.af3ecfd1.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/c198a0dc.8f31f867.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/c93cbaa0.eaff365e.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/ceb2a7a6.5d92d7d0.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/da0b5bad.d08a9466.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/db924877.e98d12a1.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/dd817ffc.0aa9630a.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/dd81e2b8.d590bc9e.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/de5f4c65.e8241890.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/de915948.27d6b065.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/e3d9abda.2b916f9e.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/e6f9706b.e74a984d.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/e92d0134.cf6d6522.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/f284c35a.42f59cdd.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/ff4d71f2.15b02f97.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/main.20feee82.js +2 -0
- solace_agent_mesh/assets/docs/assets/js/runtime~main.0d198646.js +1 -0
- solace_agent_mesh/assets/docs/docs/documentation/components/agents/index.html +154 -0
- solace_agent_mesh/assets/docs/docs/documentation/{user-guide → components}/builtin-tools/artifact-management/index.html +7 -7
- solace_agent_mesh/assets/docs/docs/documentation/{user-guide → components}/builtin-tools/audio-tools/index.html +7 -7
- solace_agent_mesh/assets/docs/docs/documentation/{user-guide → components}/builtin-tools/data-analysis-tools/index.html +8 -8
- solace_agent_mesh/assets/docs/docs/documentation/{user-guide → components}/builtin-tools/embeds/index.html +6 -6
- solace_agent_mesh/assets/docs/docs/documentation/{user-guide → components}/builtin-tools/index.html +11 -11
- solace_agent_mesh/assets/docs/docs/documentation/{concepts → components}/cli/index.html +25 -25
- solace_agent_mesh/assets/docs/docs/documentation/components/gateways/index.html +91 -0
- solace_agent_mesh/assets/docs/docs/documentation/components/index.html +29 -0
- solace_agent_mesh/assets/docs/docs/documentation/components/orchestrator/index.html +55 -0
- solace_agent_mesh/assets/docs/docs/documentation/components/plugins/index.html +110 -0
- solace_agent_mesh/assets/docs/docs/documentation/components/proxies/index.html +262 -0
- solace_agent_mesh/assets/docs/docs/documentation/deploying/debugging/index.html +104 -0
- solace_agent_mesh/assets/docs/docs/documentation/deploying/deployment-options/index.html +85 -0
- solace_agent_mesh/assets/docs/docs/documentation/deploying/index.html +25 -0
- solace_agent_mesh/assets/docs/docs/documentation/deploying/observability/index.html +59 -0
- solace_agent_mesh/assets/docs/docs/documentation/{user-guide → developing}/create-agents/index.html +113 -152
- solace_agent_mesh/assets/docs/docs/documentation/{user-guide → developing}/create-gateways/index.html +10 -10
- solace_agent_mesh/assets/docs/docs/documentation/{user-guide → developing}/creating-python-tools/index.html +12 -12
- solace_agent_mesh/assets/docs/docs/documentation/developing/creating-service-providers/index.html +54 -0
- solace_agent_mesh/assets/docs/docs/documentation/developing/evaluations/index.html +135 -0
- solace_agent_mesh/assets/docs/docs/documentation/developing/index.html +34 -0
- solace_agent_mesh/assets/docs/docs/documentation/developing/structure/index.html +55 -0
- solace_agent_mesh/assets/docs/docs/documentation/{tutorials → developing/tutorials}/bedrock-agents/index.html +25 -25
- solace_agent_mesh/assets/docs/docs/documentation/{tutorials → developing/tutorials}/custom-agent/index.html +13 -13
- solace_agent_mesh/assets/docs/docs/documentation/{tutorials → developing/tutorials}/event-mesh-gateway/index.html +12 -12
- solace_agent_mesh/assets/docs/docs/documentation/{tutorials → developing/tutorials}/mcp-integration/index.html +10 -10
- solace_agent_mesh/assets/docs/docs/documentation/{tutorials → developing/tutorials}/mongodb-integration/index.html +13 -13
- solace_agent_mesh/assets/docs/docs/documentation/{tutorials → developing/tutorials}/rag-integration/index.html +13 -13
- solace_agent_mesh/assets/docs/docs/documentation/{tutorials → developing/tutorials}/rest-gateway/index.html +10 -10
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/slack-integration/index.html +72 -0
- solace_agent_mesh/assets/docs/docs/documentation/{tutorials → developing/tutorials}/sql-database/index.html +14 -14
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/index.html +33 -0
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/installation/index.html +83 -0
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/rbac-setup-guide/index.html +222 -0
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/single-sign-on/index.html +161 -0
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/architecture/index.html +75 -0
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/index.html +53 -0
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/introduction/index.html +35 -100
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/try-agent-mesh/index.html +41 -0
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/configurations/index.html +81 -0
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/index.html +25 -0
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/installation/index.html +76 -0
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/large_language_models/index.html +160 -0
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/run-project/index.html +142 -0
- solace_agent_mesh/assets/docs/docs/documentation/migrations/a2a-upgrade/a2a-gateway-upgrade-to-0.3.0/index.html +100 -0
- solace_agent_mesh/assets/docs/docs/documentation/{Migrations/A2A Upgrade To 0.3.0/a2a-technical-migration-map/index.html → migrations/a2a-upgrade/a2a-technical-migration-map/index.html} +10 -11
- solace_agent_mesh/assets/docs/img/solace-logo.png +0 -0
- solace_agent_mesh/assets/docs/lunr-index-1761165361160.json +1 -0
- solace_agent_mesh/assets/docs/lunr-index.json +1 -1
- solace_agent_mesh/assets/docs/search-doc-1761165361160.json +1 -0
- solace_agent_mesh/assets/docs/search-doc.json +1 -1
- solace_agent_mesh/assets/docs/sitemap.xml +1 -1
- solace_agent_mesh/cli/__init__.py +1 -1
- solace_agent_mesh/cli/commands/add_cmd/agent_cmd.py +2 -69
- solace_agent_mesh/cli/commands/eval_cmd.py +11 -49
- solace_agent_mesh/cli/commands/init_cmd/__init__.py +0 -5
- solace_agent_mesh/cli/commands/init_cmd/env_step.py +10 -12
- solace_agent_mesh/cli/commands/init_cmd/orchestrator_step.py +9 -61
- solace_agent_mesh/cli/commands/init_cmd/webui_gateway_step.py +9 -49
- solace_agent_mesh/cli/commands/plugin_cmd/add_cmd.py +1 -2
- solace_agent_mesh/client/webui/frontend/static/assets/{authCallback-DwrxZE0E.js → authCallback-BTf6dqwp.js} +1 -1
- solace_agent_mesh/client/webui/frontend/static/assets/{client-DarGQzyw.js → client-CaY59VuC.js} +1 -1
- solace_agent_mesh/client/webui/frontend/static/assets/main-BGTaW0uv.js +342 -0
- solace_agent_mesh/client/webui/frontend/static/assets/main-DHJKSW1S.css +1 -0
- solace_agent_mesh/client/webui/frontend/static/assets/{vendor-BKIeiHj_.js → vendor-BEmvJSYz.js} +1 -1
- solace_agent_mesh/client/webui/frontend/static/auth-callback.html +3 -3
- solace_agent_mesh/client/webui/frontend/static/index.html +4 -4
- solace_agent_mesh/common/a2a/__init__.py +24 -0
- solace_agent_mesh/common/a2a/artifact.py +41 -1
- solace_agent_mesh/common/a2a/events.py +29 -0
- solace_agent_mesh/common/a2a/message.py +68 -0
- solace_agent_mesh/common/a2a/protocol.py +76 -3
- solace_agent_mesh/common/a2a/translation.py +3 -1
- solace_agent_mesh/common/agent_registry.py +83 -3
- solace_agent_mesh/common/constants.py +3 -1
- solace_agent_mesh/common/middleware/config_resolver.py +3 -1
- solace_agent_mesh/common/middleware/registry.py +3 -1
- solace_agent_mesh/common/sac/sam_component_base.py +2 -1
- solace_agent_mesh/common/sam_events/event_service.py +3 -2
- solace_agent_mesh/common/services/employee_service.py +3 -1
- solace_agent_mesh/common/services/identity_service.py +2 -1
- solace_agent_mesh/common/services/providers/local_file_identity_service.py +2 -1
- solace_agent_mesh/common/utils/artifact_utils.py +3 -1
- solace_agent_mesh/common/utils/asyncio_macos_fix.py +3 -1
- solace_agent_mesh/common/utils/embeds/converter.py +3 -1
- solace_agent_mesh/common/utils/embeds/evaluators.py +2 -1
- solace_agent_mesh/common/utils/embeds/modifiers.py +3 -2
- solace_agent_mesh/common/utils/embeds/resolver.py +2 -1
- solace_agent_mesh/common/utils/initializer.py +3 -1
- solace_agent_mesh/common/utils/message_utils.py +2 -1
- solace_agent_mesh/common/utils/push_notification_auth.py +3 -2
- solace_agent_mesh/common/utils/pydantic_utils.py +12 -0
- solace_agent_mesh/config_portal/backend/common.py +1 -1
- solace_agent_mesh/config_portal/frontend/static/client/assets/_index-ByU1X1HD.js +98 -0
- solace_agent_mesh/config_portal/frontend/static/client/assets/{manifest-44d62be6.js → manifest-61038fc6.js} +1 -1
- solace_agent_mesh/config_portal/frontend/static/client/index.html +1 -1
- solace_agent_mesh/core_a2a/service.py +2 -2
- solace_agent_mesh/evaluation/evaluator.py +128 -104
- solace_agent_mesh/evaluation/message_organizer.py +116 -110
- solace_agent_mesh/evaluation/report_data_processor.py +84 -86
- solace_agent_mesh/evaluation/report_generator.py +73 -79
- solace_agent_mesh/evaluation/run.py +421 -235
- solace_agent_mesh/evaluation/shared/__init__.py +92 -0
- solace_agent_mesh/evaluation/shared/constants.py +47 -0
- solace_agent_mesh/evaluation/shared/exceptions.py +50 -0
- solace_agent_mesh/evaluation/shared/helpers.py +35 -0
- solace_agent_mesh/evaluation/shared/test_case_loader.py +167 -0
- solace_agent_mesh/evaluation/shared/test_suite_loader.py +280 -0
- solace_agent_mesh/evaluation/subscriber.py +111 -232
- solace_agent_mesh/evaluation/summary_builder.py +227 -117
- solace_agent_mesh/gateway/base/app.py +3 -2
- solace_agent_mesh/gateway/base/component.py +11 -2
- solace_agent_mesh/gateway/base/task_context.py +2 -1
- solace_agent_mesh/gateway/http_sse/alembic/versions/20251015_add_session_performance_indexes.py +70 -0
- solace_agent_mesh/gateway/http_sse/app.py +2 -1
- solace_agent_mesh/gateway/http_sse/component.py +102 -3
- solace_agent_mesh/gateway/http_sse/components/task_logger_forwarder.py +3 -2
- solace_agent_mesh/gateway/http_sse/components/visualization_forwarder_component.py +3 -1
- solace_agent_mesh/gateway/http_sse/dependencies.py +7 -5
- solace_agent_mesh/gateway/http_sse/main.py +5 -2
- solace_agent_mesh/gateway/http_sse/repository/chat_task_repository.py +12 -13
- solace_agent_mesh/gateway/http_sse/repository/feedback_repository.py +15 -18
- solace_agent_mesh/gateway/http_sse/repository/interfaces.py +25 -18
- solace_agent_mesh/gateway/http_sse/repository/session_repository.py +30 -26
- solace_agent_mesh/gateway/http_sse/repository/task_repository.py +35 -44
- solace_agent_mesh/gateway/http_sse/routers/agent_cards.py +7 -5
- solace_agent_mesh/gateway/http_sse/routers/artifacts.py +97 -205
- solace_agent_mesh/gateway/http_sse/routers/auth.py +3 -1
- solace_agent_mesh/gateway/http_sse/routers/config.py +3 -2
- solace_agent_mesh/gateway/http_sse/routers/dto/responses/session_responses.py +4 -3
- solace_agent_mesh/gateway/http_sse/routers/people.py +3 -1
- solace_agent_mesh/gateway/http_sse/routers/sessions.py +5 -3
- solace_agent_mesh/gateway/http_sse/routers/sse.py +3 -2
- solace_agent_mesh/gateway/http_sse/routers/tasks.py +35 -42
- solace_agent_mesh/gateway/http_sse/routers/users.py +3 -1
- solace_agent_mesh/gateway/http_sse/routers/visualization.py +19 -12
- solace_agent_mesh/gateway/http_sse/services/agent_card_service.py +3 -1
- solace_agent_mesh/gateway/http_sse/services/data_retention_service.py +6 -5
- solace_agent_mesh/gateway/http_sse/services/feedback_service.py +53 -44
- solace_agent_mesh/gateway/http_sse/services/people_service.py +2 -2
- solace_agent_mesh/gateway/http_sse/services/session_service.py +23 -21
- solace_agent_mesh/gateway/http_sse/services/task_logger_service.py +10 -9
- solace_agent_mesh/gateway/http_sse/services/task_service.py +3 -2
- solace_agent_mesh/gateway/http_sse/session_manager.py +2 -1
- solace_agent_mesh/gateway/http_sse/shared/base_repository.py +45 -71
- solace_agent_mesh/gateway/http_sse/shared/types.py +0 -18
- solace_agent_mesh/gateway/http_sse/sse_event_buffer.py +2 -1
- solace_agent_mesh/gateway/http_sse/sse_manager.py +2 -2
- solace_agent_mesh/templates/gateway_app_template.py +4 -2
- solace_agent_mesh/templates/gateway_component_template.py +3 -1
- solace_agent_mesh/templates/gateway_config_template.yaml +0 -5
- solace_agent_mesh/templates/logging_config_template.ini +27 -46
- solace_agent_mesh/templates/plugin_gateway_config_template.yaml +0 -3
- solace_agent_mesh/templates/plugin_tools_template.py +2 -2
- solace_agent_mesh/templates/shared_config.yaml +40 -0
- {solace_agent_mesh-1.5.0.dist-info → solace_agent_mesh-1.6.0.dist-info}/METADATA +47 -21
- {solace_agent_mesh-1.5.0.dist-info → solace_agent_mesh-1.6.0.dist-info}/RECORD +254 -225
- solace_agent_mesh/assets/docs/assets/images/sac-flows-80d5b603c6aafd33e87945680ce0abf3.png +0 -0
- solace_agent_mesh/assets/docs/assets/images/sac_parts_of_a_component-cb3d0424b1d0c17734c5435cca6b4082.png +0 -0
- solace_agent_mesh/assets/docs/assets/js/04989206.a248f00c.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/0e682baa.d54b8668.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/1023fc19.8a8a9309.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/1523c6b4.2645ef68.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/166ab619.e27886d9.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/1c6e87d2.e056b7e0.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/21ceee5f.3bf39250.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/2a9cab12.2afaee76.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/332e10b5.f7629851.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/3d406171.5560fdf9.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/42b3f8d8.508ae8db.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/442a8107.b5c2532a.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/453a82a6.3c6bb61d.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/483cef9a.bf9398af.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/4c2787c2.c1290a40.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/55f47984.bcd00a86.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/5b4258a4.fdfd2325.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/664b740a.ba305a89.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/75384d09.c19e8b51.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/768e31b0.9abcdc48.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/85387663.be2bc838.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/945fb41e.16e00776.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/9a09e75d.92de8cf5.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/9eff14a2.d62aad71.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/a12a4955.25fbed32.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/a3a92b25.af35e313.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/aba87c2f.4ddf32f2.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/ae0e903d.5fe5203f.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/ae4415af.16cc58d3.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/bac0be12.17de4316.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/c2c06897.87cb1f47.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/c835a94d.ce21f0bf.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/cc969b05.feef7dcc.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/cd3d4052.a19e7d78.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/ced92a13.fb92e7ca.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/cee5d587.47904f5e.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/d6a81ee7.829198f1.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/f284c35a.ed8dd236.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/f897a61a.126663fe.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/fbfa3e75.e144b16c.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/main.0c149855.js +0 -2
- solace_agent_mesh/assets/docs/assets/js/runtime~main.c66557e4.js +0 -1
- solace_agent_mesh/assets/docs/docs/documentation/Enterprise/installation/index.html +0 -46
- solace_agent_mesh/assets/docs/docs/documentation/Enterprise/rbac-setup-guilde/index.html +0 -201
- solace_agent_mesh/assets/docs/docs/documentation/Enterprise/single-sign-on/index.html +0 -29
- solace_agent_mesh/assets/docs/docs/documentation/Migrations/A2A Upgrade To 0.3.0/a2a-gateway-upgrade-to-0.3.0/index.html +0 -105
- solace_agent_mesh/assets/docs/docs/documentation/concepts/agents/index.html +0 -144
- solace_agent_mesh/assets/docs/docs/documentation/concepts/architecture/index.html +0 -91
- solace_agent_mesh/assets/docs/docs/documentation/concepts/gateways/index.html +0 -91
- solace_agent_mesh/assets/docs/docs/documentation/concepts/orchestrator/index.html +0 -55
- solace_agent_mesh/assets/docs/docs/documentation/concepts/plugins/index.html +0 -111
- solace_agent_mesh/assets/docs/docs/documentation/deployment/debugging/index.html +0 -77
- solace_agent_mesh/assets/docs/docs/documentation/deployment/deploy/index.html +0 -48
- solace_agent_mesh/assets/docs/docs/documentation/deployment/observability/index.html +0 -54
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/component-overview/index.html +0 -45
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/configurations/index.html +0 -74
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/configurations/litellm_models/index.html +0 -49
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/installation/index.html +0 -76
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/quick-start/index.html +0 -73
- solace_agent_mesh/assets/docs/docs/documentation/tutorials/slack-integration/index.html +0 -72
- solace_agent_mesh/assets/docs/docs/documentation/user-guide/creating-service-providers/index.html +0 -54
- solace_agent_mesh/assets/docs/docs/documentation/user-guide/solace-ai-connector/index.html +0 -69
- solace_agent_mesh/assets/docs/docs/documentation/user-guide/structure/index.html +0 -59
- solace_agent_mesh/assets/docs/lunr-index-1760032255022.json +0 -1
- solace_agent_mesh/assets/docs/search-doc-1760032255022.json +0 -1
- solace_agent_mesh/client/webui/frontend/static/assets/main-CZbpmwfA.css +0 -1
- solace_agent_mesh/client/webui/frontend/static/assets/main-C__uuUkB.js +0 -339
- solace_agent_mesh/config_portal/frontend/static/client/assets/_index-BNuqpWDc.js +0 -98
- solace_agent_mesh/evaluation/config_loader.py +0 -657
- solace_agent_mesh/evaluation/test_case_loader.py +0 -714
- /solace_agent_mesh/assets/docs/assets/js/{8591.d7c16be6.js.LICENSE.txt → 8591.5d015485.js.LICENSE.txt} +0 -0
- /solace_agent_mesh/assets/docs/assets/js/{main.0c149855.js.LICENSE.txt → main.20feee82.js.LICENSE.txt} +0 -0
- {solace_agent_mesh-1.5.0.dist-info → solace_agent_mesh-1.6.0.dist-info}/WHEEL +0 -0
- {solace_agent_mesh-1.5.0.dist-info → solace_agent_mesh-1.6.0.dist-info}/entry_points.txt +0 -0
- {solace_agent_mesh-1.5.0.dist-info → solace_agent_mesh-1.6.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";(self.webpackChunksolace_agenitc_mesh_docs=self.webpackChunksolace_agenitc_mesh_docs||[]).push([[3974],{6145:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>r,contentTitle:()=>a,default:()=>g,frontMatter:()=>l,metadata:()=>o,toc:()=>c});const o=JSON.parse('{"id":"documentation/user-guide/create-agents","title":"Create Agents","description":"Introduction","source":"@site/docs/documentation/user-guide/create-agents.md","sourceDirName":"documentation/user-guide","slug":"/documentation/user-guide/create-agents","permalink":"/solace-agent-mesh/docs/documentation/user-guide/create-agents","draft":false,"unlisted":false,"editUrl":"https://github.com/SolaceLabs/solace-agent-mesh/edit/main/docs/docs/documentation/user-guide/create-agents.md","tags":[],"version":"current","sidebarPosition":30,"frontMatter":{"title":"Create Agents","sidebar_position":30},"sidebar":"docSidebar","previous":{"title":"Structure","permalink":"/solace-agent-mesh/docs/documentation/user-guide/structure"},"next":{"title":"Creating Python Tools","permalink":"/solace-agent-mesh/docs/documentation/user-guide/creating-python-tools"}}');var i=t(4848),s=t(8453);const l={title:"Create Agents",sidebar_position:30},a="Creating Agents",r={},c=[{value:"Introduction",id:"introduction",level:2},{value:"Quick Start: Creating Your First Agent",id:"quick-start-creating-your-first-agent",level:2},{value:"CLI Options",id:"cli-options",level:3},{value:"Core Concepts",id:"core-concepts",level:2},{value:"Tools",id:"tools",level:3},{value:"Configuration File",id:"configuration-file",level:3},{value:"Tool Configuration",id:"tool-configuration",level:3},{value:"ToolContext",id:"toolcontext",level:3},{value:"Lifecycle Functions",id:"lifecycle-functions",level:3},{value:"Creating an Agent Plugin: Step-by-Step",id:"creating-an-agent-plugin-step-by-step",level:2},{value:"Step 1: Initialize your Agent",id:"step-1-initialize-your-agent",level:3},{value:"Step 2: The Tool Function",id:"step-2-the-tool-function",level:3},{value:"Step 3: The Agent Configuration",id:"step-3-the-agent-configuration",level:3},{value:"Step 4: The Lifecycle Function",id:"step-4-the-lifecycle-function",level:3},{value:"Advanced Concepts",id:"advanced-concepts",level:2},{value:"Working with Artifacts",id:"working-with-artifacts",level:3},{value:"Using Multiple Tool Configurations",id:"using-multiple-tool-configurations",level:3},{value:"Running Your Agent",id:"running-your-agent",level:2},{value:"Architecture Overview",id:"architecture-overview",level:2},{value:"Best Practices",id:"best-practices",level:2},{value:"Tool Design",id:"tool-design",level:3},{value:"Configuration",id:"configuration",level:3},{value:"Testing",id:"testing",level:3}];function d(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",header:"header",li:"li",mermaid:"mermaid",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:"creating-agents",children:"Creating Agents"})}),"\n",(0,i.jsx)(n.h2,{id:"introduction",children:"Introduction"}),"\n",(0,i.jsx)(n.admonition,{type:"tip",children:(0,i.jsxs)(n.p,{children:["For a more comprehensive tutorial example, see the ",(0,i.jsx)(n.a,{href:"/solace-agent-mesh/docs/documentation/tutorials/custom-agent",children:"Build Your Own Agent"})," guide.\nThis page provides an in-depth theoretical overview of creating agents in Solace Agent Mesh."]})}),"\n",(0,i.jsxs)(n.p,{children:["Solace Agent Mesh is a powerful platform that enables you to create intelligent agents that can communicate with each other and perform complex tasks. At its core, Solace Agent Mesh uses a ",(0,i.jsx)(n.strong,{children:"tool-based architecture"})," where LLM-powered agents are equipped with specific capabilities (tools) that they can use to accomplish user requests."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsxs)(n.strong,{children:["Before continuing with this tutorial, make sure you are familiar with the basic ",(0,i.jsx)(n.a,{href:"/solace-agent-mesh/docs/documentation/concepts/agents",children:"agent concept"}),"."]})}),"\n",(0,i.jsx)(n.p,{children:"This tutorial guides you through creating your first Solace Agent Mesh agent from scratch. You will learn how to:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Define tools as Python functions"}),"\n",(0,i.jsx)(n.li,{children:"Configure an agent using YAML"}),"\n",(0,i.jsx)(n.li,{children:"Set up agent lifecycle functions"}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:'By the end of this tutorial, you should have a working "Hello World" agent that demonstrates the fundamental concepts of Solace Agent Mesh agent development.'}),"\n",(0,i.jsx)(n.h2,{id:"quick-start-creating-your-first-agent",children:"Quick Start: Creating Your First Agent"}),"\n",(0,i.jsxs)(n.p,{children:["You can create an agent directly using the Solace Agent Mesh CLI ",(0,i.jsx)(n.code,{children:"sam add agent"}),":"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"sam add agent my-first-agent\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 agent structure"}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"Note that create agent as plugin is preferred over create agent directly."}),"\n",(0,i.jsx)(n.h3,{id:"cli-options",children:"CLI Options"}),"\n",(0,i.jsx)(n.p,{children:"You can customize the agent creation with provided CLI options."}),"\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 agent --help\n"})}),"\n",(0,i.jsx)(n.h2,{id:"core-concepts",children:"Core Concepts"}),"\n",(0,i.jsx)(n.p,{children:"Before diving into the implementation, it is important to understand the key concepts that make Solace Agent Mesh agents work:"}),"\n",(0,i.jsx)(n.h3,{id:"tools",children:"Tools"}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.strong,{children:"Tools are the fundamental building blocks of Solace Agent Mesh agents."})," Each tool is implemented as a Python function that performs a specific task. Tools can:"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Process text and data"}),"\n",(0,i.jsx)(n.li,{children:"Interact with external APIs"}),"\n",(0,i.jsx)(n.li,{children:"Create and manipulate files"}),"\n",(0,i.jsx)(n.li,{children:"Communicate with other agents"}),"\n",(0,i.jsx)(n.li,{children:"Access databases and services"}),"\n"]}),"\n",(0,i.jsx)(n.p,{children:"The LLM (Large Language Model) orchestrating your agent decides which tools to use based on the user's request and the tool descriptions you provide."}),"\n",(0,i.jsx)(n.admonition,{type:"tip",children:(0,i.jsxs)(n.p,{children:["Solace Agent Mesh provides a set of ",(0,i.jsx)(n.a,{href:"/solace-agent-mesh/docs/documentation/user-guide/builtin-tools/",children:"built-in tools"})," plus support for ",(0,i.jsx)(n.a,{href:"/solace-agent-mesh/docs/documentation/tutorials/mcp-integration",children:"model context protocol (MCP)"})," servers, which can be configured in the tools list of your agent configuration."]})}),"\n",(0,i.jsx)(n.h3,{id:"configuration-file",children:"Configuration File"}),"\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.code,{children:"config.yaml"})," (for plugin template) or ",(0,i.jsx)(n.code,{children:"agent-name.yaml"})," (for agent instances) file is the blueprint of your agent. It defines:"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Agent identity"}),": Name, description, and capabilities"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Model configuration"}),": Which LLM to use"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Tools list"}),": Defines which tools the agent can access and how they're configured"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Lifecycle functions"}),": Setup and cleanup procedures"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Framework services"}),": Session management, artifact storage, and so on."]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.a,{href:"/solace-agent-mesh/docs/documentation/concepts/agents#agent-card",children:"Agent card"})}),": Metadata describing the agent capabilities, skills and its visibility in the system"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"tool-configuration",children:"Tool Configuration"}),"\n",(0,i.jsxs)(n.p,{children:["Within the ",(0,i.jsx)(n.code,{children:"tools"})," list in your YAML config, each tool can have its own ",(0,i.jsx)(n.code,{children:"tool_config"})," section. This allows you to:"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"Configure the same tool function for different purposes"}),"\n",(0,i.jsx)(n.li,{children:"Pass specific parameters to tool instances"}),"\n",(0,i.jsx)(n.li,{children:"Customize tool behavior per agent"}),"\n"]}),"\n",(0,i.jsxs)(n.admonition,{type:"info",children:[(0,i.jsxs)(n.p,{children:['For tools of type "python", you can also use the ',(0,i.jsx)(n.code,{children:"tool_name"})," and ",(0,i.jsx)(n.code,{children:"tool_description"})," to overwrite the function name and description in the tool docstring."]}),(0,i.jsx)(n.p,{children:"This is useful when using a generic tool function for multiple purposes, allowing you to provide a more descriptive name and description for each instance."})]}),"\n",(0,i.jsx)(n.h3,{id:"toolcontext",children:"ToolContext"}),"\n",(0,i.jsxs)(n.p,{children:["The ",(0,i.jsx)(n.code,{children:"ToolContext"})," object (passed as one of the arguments to your tool function) provides your tools with access to Solace Agent Mesh core services:"]}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Logging"}),": Structured logging for debugging and monitoring"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Artifact Service"}),": File storage and retrieval"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Session Information"}),": Current user and session context"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Agent State"}),": Shared data between tool calls"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"lifecycle-functions",children:"Lifecycle Functions"}),"\n",(0,i.jsx)(n.p,{children:"Lifecycle functions allow you to manage resources that should persist for the agent's lifetime:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"agent_init_function"})}),": Runs when the agent starts (for example, database connections)"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"agent_cleanup_function"})}),": Runs when the agent shuts down (for example, closing connections)"]}),"\n"]}),"\n",(0,i.jsx)(n.admonition,{type:"note",children:(0,i.jsx)(n.p,{children:"Lifecycle functions are optional but recommended for managing resources effectively."})}),"\n",(0,i.jsx)(n.h2,{id:"creating-an-agent-plugin-step-by-step",children:"Creating an Agent Plugin: Step-by-Step"}),"\n",(0,i.jsx)(n.p,{children:"Create a simple agent that can greet users and demonstrate the core concepts."}),"\n",(0,i.jsxs)(n.p,{children:["You can create an agent either by using the ",(0,i.jsx)(n.code,{children:"sam add agent"})," command or by creating a new plugin of type agent, ",(0,i.jsx)(n.code,{children:"sam plugin create my-hello-agent --type agent"}),"."]}),"\n",(0,i.jsx)(n.admonition,{type:"tip",children:(0,i.jsxs)(n.p,{children:["For information and recommendations about these options, see ",(0,i.jsx)(n.a,{href:"/solace-agent-mesh/docs/documentation/concepts/plugins#agent-or-plugin-which-to-use",children:(0,i.jsx)(n.code,{children:"Agent or Plugin: Which To use?"})}),"."]})}),"\n",(0,i.jsx)(n.h3,{id:"step-1-initialize-your-agent",children:"Step 1: Initialize your Agent"}),"\n",(0,i.jsxs)(n.p,{children:["In this tutorial, you create a new agent by creating a new plugin of type agent.\nFor an example of custom agents, see ",(0,i.jsx)(n.a,{href:"/solace-agent-mesh/docs/documentation/tutorials/custom-agent",children:"Build Your Own Agent"})," guide."]}),"\n",(0,i.jsx)(n.p,{children:"Although the directory structure for plugins is slightly different than the one for agents, both require a YAML configuration file, and a python module with the tools and lifecycle functions you want."}),"\n",(0,i.jsx)(n.p,{children:"To create a new agent plugin, run the following command:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"sam plugin create my-hello-agent --type agent\n"})}),"\n",(0,i.jsx)(n.p,{children:"And follow the prompts to set up your agent. The prompts create a new directory structure for your agent."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"my-hello-agent/\n\u251c\u2500\u2500 src/\n\u2502 \u2514\u2500\u2500 my_hello_agent/\n\u2502 \u251c\u2500\u2500 __init__.py\n\u2502 \u251c\u2500\u2500 tools.py\n\u2502 \u2514\u2500\u2500 lifecycle.py # This file won't be automatically created\n\u251c\u2500\u2500 config.yaml\n\u251c\u2500\u2500 pyproject.toml\n\u2514\u2500\u2500 README.md\n"})}),"\n",(0,i.jsx)(n.mermaid,{value:"graph TD\n A[my-hello-agent/] --\x3e B[src/]\n A --\x3e C[config.yaml]\n A --\x3e D[pyproject.toml]\n A --\x3e E[README.md]\n \n B --\x3e F[my_hello_agent/]\n F --\x3e G[__init__.py]\n F --\x3e H[tools.py]\n F --\x3e I[lifecycle.py]\n \n style C fill:#b60000,stroke:#333,stroke-width:2px\n style H fill:#b60000,stroke:#333,stroke-width:2px\n style I fill:#007000,stroke:#333,stroke-width:2px"}),"\n",(0,i.jsx)(n.h3,{id:"step-2-the-tool-function",children:"Step 2: The Tool Function"}),"\n",(0,i.jsx)(n.p,{children:"Create your first tool function:\nThe following arguments are provided by the framework:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"tool_context: Solace Agent Mesh framework context"}),"\n",(0,i.jsx)(n.li,{children:"tool_config: Tool-specific configuration (from config.yaml)"}),"\n"]}),"\n",(0,i.jsxs)(n.p,{children:["For a complete guide on creating python tools, see our ",(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.a,{href:"/solace-agent-mesh/docs/documentation/user-guide/creating-python-tools",children:"Creating Python Tools"})})," documentation."]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-python",children:'# src/my_hello_agent/tools.py\n"""\nTools for the Hello World agent.\n"""\n\nfrom typing import Any, Dict, Optional\nfrom google.adk.tools import ToolContext\nfrom solace_ai_connector.common.log import log\n\n\nasync def hello_tool(\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 log_identifier = "[HelloTool]"\n log.info(f"{log_identifier} Greeting user: {name}")\n \n # Get configuration from tool_config\n greeting_prefix = "Hello"\n if tool_config:\n greeting_prefix = tool_config.get("greeting_prefix", "Hello")\n \n # Create the greeting message\n greeting_message = f"{greeting_prefix}, {name}! Welcome to Solace Agent Mesh!"\n \n log.info(f"{log_identifier} Generated greeting: {greeting_message}")\n \n return {\n "status": "success",\n "message": greeting_message,\n "greeted_name": name\n }\n\n\nasync def farewell_tool(\n name: str,\n tool_context: Optional[ToolContext] = None,\n tool_config: Optional[Dict[str, Any]] = None\n) -> Dict[str, Any]:\n """\n Says goodbye to a user.\n \n Args:\n name: The name of the person to say goodbye to\n \n Returns:\n A dictionary with the farewell message\n """\n log_identifier = "[FarewellTool]"\n log.info(f"{log_identifier} Saying goodbye to user: {name}")\n \n # Get configuration from tool_config\n farewell_prefix = "Goodbye"\n if tool_config:\n farewell_prefix = tool_config.get("farewell_prefix", "Goodbye")\n \n # Create the farewell message\n farewell_message = f"{farewell_prefix}, {name}! Thanks for using Solace Agent Mesh!"\n \n log.info(f"{log_identifier} Generated farewell: {farewell_message}")\n \n return {\n "status": "success",\n "message": farewell_message,\n "farewell_name": name\n }\n'})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Key Points:"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Function Signature"}),": All tool functions should be ",(0,i.jsx)(n.code,{children:"async"})," and accept ",(0,i.jsx)(n.code,{children:"tool_context"})," and ",(0,i.jsx)(n.code,{children:"tool_config"})," parameters"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Return Format"}),": Return a dictionary with at least a ",(0,i.jsx)(n.code,{children:"status"})," field"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Logging"}),": Use the Solace Agent Mesh logger for consistent logging"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Configuration"}),": Access tool-specific config via the ",(0,i.jsx)(n.code,{children:"tool_config"})," parameter"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"step-3-the-agent-configuration",children:"Step 3: The Agent Configuration"}),"\n",(0,i.jsx)(n.p,{children:"Create the main configuration file for your agent:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-yaml",children:'# File: config.yaml (at root of project directory)\n# ... (additional services and configurations)\n\napps:\n - name: my-hello-agent\n app_module: solace_agent_mesh.agent.sac.app \n broker:\n # Can be found in configs/shared_config.yaml after running sam init\n <<: *broker_connection\n \n # Agent-specific configuration\n app_config:\n # Basic agent identity\n namespace: ${NAMESPACE} \n supports_streaming: true \n agent_name: "HelloAgent"\n display_name: "Hello World Agent"\n \n # LLM model configuration\n model: *general_model \n \n # Agent instructions (system prompt)\n instruction: |\n You are a friendly Hello World agent. Your purpose is to greet users and \n demonstrate the capabilities of Solace Agent Mesh. You can:\n \n 1. Greet users with personalized messages using the hello_tool\n 2. Say goodbye to users using the farewell_tool\n \n Always be polite and helpful. When greeting someone, ask for their name \n if they haven\'t provided it.\n \n # Lifecycle functions\n agent_init_function:\n module: "my_hello_agent.lifecycle" # This should point to your lifecycle python module\n name: "initialize_hello_agent"\n base_path: .\n config:\n startup_message: "Hello Agent is starting up!"\n log_level: "INFO"\n \n agent_cleanup_function:\n module: "my_hello_agent.lifecycle"\n base_path: .\n name: "cleanup_hello_agent"\n \n # Tools configuration\n tools:\n # Hello tool with custom greeting\n - tool_type: python\n component_module: "my_hello_agent.tools"\n component_base_path: .\n function_name: "hello_tool"\n tool_name: "greet_user" # Renaming the tool, must use this name in the agent card\n tool_config:\n greeting_prefix: "Hello there"\n \n # Farewell tool with custom farewell\n - tool_type: python\n component_module: "my_hello_agent.tools"\n component_base_path: .\n function_name: "farewell_tool"\n tool_name: "say_goodbye"\n tool_config:\n farewell_prefix: "See you later"\n \n # Built-in artifact tools for file operations\n - tool_type: builtin-group\n group_name: "artifact_management"\n \n # Agent card (describes the agent\'s capabilities)\n agent_card:\n description: "A friendly Hello World agent that demonstrates Solace Agent Mesh capabilities"\n defaultInputModes: ["text"]\n defaultOutputModes: ["text"]\n skills:\n - id: "greet_user"\n name: "Greet User"\n description: "Greets users with personalized messages"\n - id: "say_goodbye"\n name: "Say Goodbye"\n description: "Says goodbye to users"\n - id: "file_operations"\n name: "File Operations"\n description: "Create, read, and manage files and artifacts"\n \n # Session and artifact services\n session_service: *default_session_service\n artifact_service: *default_artifact_service\n# ... (additional services and configurations)\n'})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Key Sections Explained:"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"namespace"})}),": Unique identifier for your agent in the mesh"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"model"})}),": LLM configuration (can be a string or detailed config)"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"instruction"})}),": The system prompt that defines your agent's behavior"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"tools"})}),": List of tools your agent can use, with their configurations"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:(0,i.jsx)(n.code,{children:"agent_card"})}),": Metadata describing your agent's capabilities"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"step-4-the-lifecycle-function",children:"Step 4: The Lifecycle Function"}),"\n",(0,i.jsx)(n.p,{children:"Lifecycle functions are completely optional but useful for managing resources. They run when the agent starts and stops."}),"\n",(0,i.jsx)(n.p,{children:"The lifecycle file is not automatically created, so you need to create it manually:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"touch src/my_hello_agent/lifecycle.py\n"})}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-python",children:'# src/my_hello_agent/lifecycle.py\n"""\nLifecycle functions for the Hello World agent.\n"""\n\nfrom typing import Any, Dict\nfrom pydantic import BaseModel, Field\nfrom solace_ai_connector.common.log import log\n\n\nclass HelloAgentInitConfig(BaseModel):\n """\n Configuration model for the Hello Agent initialization.\n """\n startup_message: str = Field(description="Message to log on startup")\n log_level: str = Field(default="INFO", description="Logging level for the agent")\n\n\ndef initialize_hello_agent(host_component: Any, init_config: HelloAgentInitConfig):\n """\n Initializes the Hello World agent.\n \n Args:\n host_component: The agent host component\n init_config: Validated initialization configuration\n """\n log_identifier = f"[{host_component.agent_name}:init]"\n log.info(f"{log_identifier} Starting Hello Agent initialization...")\n \n # Log the startup message from config\n log.info(f"{log_identifier} {init_config.startup_message}")\n \n # You could initialize shared resources here, such as:\n # - Database connections\n # - API clients\n # - Caches or shared data structures\n \n # Store any shared state in the agent\n host_component.set_agent_specific_state("initialized_at", "2024-01-01T00:00:00Z")\n host_component.set_agent_specific_state("greeting_count", 0)\n \n log.info(f"{log_identifier} Hello Agent initialization completed successfully")\n\n\ndef cleanup_hello_agent(host_component: Any):\n """\n Cleans up resources when the Hello World agent shuts down.\n \n Args:\n host_component: The agent host component\n """\n log_identifier = f"[{host_component.agent_name}:cleanup]"\n log.info(f"{log_identifier} Starting Hello Agent cleanup...")\n \n # Retrieve any shared state\n greeting_count = host_component.get_agent_specific_state("greeting_count", 0)\n log.info(f"{log_identifier} Agent processed {greeting_count} greetings during its lifetime")\n \n # Clean up resources here, such as:\n # - Closing database connections\n # - Shutting down background tasks\n # - Saving final state\n \n log.info(f"{log_identifier} Hello Agent cleanup completed")\n'})}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.strong,{children:"Key Points:"})}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Pydantic Models"}),": Use Pydantic for configuration validation"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Shared State"}),": Store data that persists across tool calls"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Resource Management"}),": Initialize connections in ",(0,i.jsx)(n.code,{children:"init"}),", clean up in ",(0,i.jsx)(n.code,{children:"cleanup"})]}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"advanced-concepts",children:"Advanced Concepts"}),"\n",(0,i.jsx)(n.h3,{id:"working-with-artifacts",children:"Working with Artifacts"}),"\n",(0,i.jsx)(n.p,{children:"You can enhance our hello tool to save greetings to a file using Solace Agent Mesh's artifact service:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-python",children:'\nfrom datetime import datetime\nfrom solace_agent_mesh.agent.utils.artifact_helpers import save_artifact_with_metadata\n\nasync def hello_tool_with_artifact(\n name: str,\n save_to_file: bool = False,\n tool_context: Optional[ToolContext] = None,\n tool_config: Optional[Dict[str, Any]] = None\n) -> Dict[str, Any]:\n """\n Greets a user and optionally saves the greeting to a file.\n """\n log_identifier = "[HelloToolWithArtifact]"\n \n # Generate greeting (same as before)\n greeting_prefix = tool_config.get("greeting_prefix", "Hello") if tool_config else "Hello"\n greeting_message = f"{greeting_prefix}, {name}! Welcome to Solace Agent Mesh!"\n \n result = {\n "status": "success",\n "message": greeting_message,\n "greeted_name": name\n }\n \n # Save to artifact if requested\n if save_to_file and tool_context:\n try:\n # Prepare content\n timestamp = datetime.now(timezone.utc)\n filename = f"greeting_{name}_{timestamp}.txt"\n content = f"Greeting: {greeting_message}\\nTimestamp: {timestamp}\\n"\n \n # Save artifact\n artifact_service = tool_context._invocation_context.artifact_service\n await save_artifact_with_metadata(\n artifact_service=artifact_service,\n app_name=tool_context._invocation_context.app_name,\n user_id=tool_context._invocation_context.user_id,\n session_id=tool_context._invocation_context.session.id,\n filename=filename,\n content_bytes=content.encode(\'utf-8\'),\n mime_type="application/json",\n metadata_dict={\n "description": "Greeting message",\n "source": "Greeting Agent",\n },\n timestamp=timestamp\n )\n \n result["artifact_saved"] = filename\n log.info(f"{log_identifier} Saved greeting to artifact: {filename}")\n \n except Exception as e:\n log.error(f"{log_identifier} Failed to save artifact: {e}")\n result["artifact_error"] = str(e)\n \n return result\n'})}),"\n",(0,i.jsx)(n.h3,{id:"using-multiple-tool-configurations",children:"Using Multiple Tool Configurations"}),"\n",(0,i.jsx)(n.p,{children:"You can configure the same tool function multiple times with different settings:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-yaml",children:'tools:\n # Formal greeting\n - tool_type: python\n component_module: "my_hello_agent.tools"\n function_name: "hello_tool"\n tool_name: "formal_greeting"\n tool_config:\n greeting_prefix: "Good day"\n \n # Casual greeting\n - tool_type: python\n component_module: "my_hello_agent.tools"\n function_name: "hello_tool"\n tool_name: "casual_greeting"\n tool_config:\n greeting_prefix: "Hey there"\n \n # Enthusiastic greeting\n - tool_type: python\n component_module: "my_hello_agent.tools"\n function_name: "hello_tool"\n tool_name: "enthusiastic_greeting"\n tool_config:\n greeting_prefix: "Hello and welcome"\n'})}),"\n",(0,i.jsx)(n.p,{children:"This gives your agent multiple greeting styles to choose from based on the context."}),"\n",(0,i.jsx)(n.h2,{id:"running-your-agent",children:"Running Your Agent"}),"\n",(0,i.jsx)(n.p,{children:"To run a plugin agent, you first need to package and install it as a plugin."}),"\n",(0,i.jsxs)(n.admonition,{title:"Quick Debug",type:"tip",children:[(0,i.jsxs)(n.p,{children:["For debugging or isolated development testing, you can run your agent from the ",(0,i.jsx)(n.code,{children:"src"})," directory directly using the Solace Agent Mesh CLI."]}),(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"cd src\nsam run ../config.yaml\n"})}),(0,i.jsx)(n.p,{children:"Changing to the src directory allows the module path to be set correctly so that Solace Agent Mesh can find your functions without your having to install them in your python environment as a plugin package."})]}),"\n",(0,i.jsxs)(n.p,{children:["To properly instantiate your plugin agent, first build the plugin.\nThe following command will produce a python wheel file under ",(0,i.jsx)(n.code,{children:"dist"})," directory:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-bash",children:"sam plugin build\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Check into ",(0,i.jsx)(n.a,{href:"/solace-agent-mesh/docs/documentation/getting-started/quick-start#create-a-project",children:"your Solace Agent Mesh project directory"}),", and add the plugin wheel with a given name:"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"sam plugin add my-first-weather-agent --plugin PATH/TO/weather-agent/dist/weather-agent.whl\n"})}),"\n",(0,i.jsx)(n.admonition,{type:"note",children:(0,i.jsxs)(n.p,{children:["Using the ",(0,i.jsx)(n.code,{children:"sam plugin add"})," command installs your plugin as a python dependency into your python environment.\nThis also means changing the source code without reinstalling the plugin will not reflect the changes."]})}),"\n",(0,i.jsx)(n.p,{children:"Now, you can run the complete Solace Agent Mesh application along with your newly added agent:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{children:"sam run\n"})}),"\n",(0,i.jsxs)(n.p,{children:["Alternatively, only run the newly added agent using ",(0,i.jsx)(n.code,{children:"sam run configs/agents/my-first-weather-agent.yaml"})]}),"\n",(0,i.jsx)(n.h2,{id:"architecture-overview",children:"Architecture Overview"}),"\n",(0,i.jsx)(n.p,{children:"Here is how all the pieces fit together:"}),"\n",(0,i.jsx)(n.mermaid,{value:"graph TD\n subgraph Agent Configuration\n direction LR\n A[config.yaml] --\x3e|Defines| B(Agent Properties);\n A --\x3e|Lists & Configures| C(Tools);\n end\n\n subgraph Agent Host\n direction TB\n D[SAM Host] --\x3e|Loads| A;\n D --\x3e|Instantiates| E[Agent];\n E --\x3e|Initializes with| F[Lifecycle Functions];\n end\n\n subgraph Tool Implementation\n direction LR\n G[Python Module tools.py] --\x3e|Contains| H[Tool Functions];\n end\n\n subgraph Execution Flow\n direction TB\n I[User Request] --\x3e J[LLM Orchestrator];\n J --\x3e|Selects Tool| K{ADKToolWrapper};\n K --\x3e|Calls| H;\n H --\x3e|Accesses| L[ToolContext];\n H --\x3e|Uses| M[tool_config];\n H --\x3e|Returns Result| J;\n end\n\n C --\x3e|Wrapped by| K;\n\n style A fill:#b60000,stroke:#faa,stroke-width:2px\n style H fill:#b60000,stroke:#faa,stroke-width:2px\n style F fill:#007000,stroke:#faa,stroke-width:2px"}),"\n",(0,i.jsx)(n.h2,{id:"best-practices",children:"Best Practices"}),"\n",(0,i.jsx)(n.h3,{id:"tool-design",children:"Tool Design"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Single Responsibility"}),": Each tool should do one thing well"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Clear Documentation"}),": Write detailed docstrings for your tools"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Error Handling"}),": Always return structured error responses"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Logging"}),": Use consistent logging for debugging and monitoring"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"configuration",children:"Configuration"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Environment Variables"}),": Use environment variables for sensitive data"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Validation"}),": Use Pydantic models for configuration validation"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Documentation"}),": Comment your configuration files thoroughly"]}),"\n"]}),"\n",(0,i.jsx)(n.h3,{id:"testing",children:"Testing"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Unit Tests"}),": Test your tool functions independently"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Integration Tests"}),": Test your agent with real Solace Agent Mesh infrastructure"]}),"\n",(0,i.jsxs)(n.li,{children:[(0,i.jsx)(n.strong,{children:"Mock Dependencies"}),": Mock external services for reliable testing"]}),"\n"]})]})}function g(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:()=>l,x:()=>a});var o=t(6540);const i={},s=o.createContext(i);function l(e){const n=o.useContext(s);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(i):e.components||i:l(e.components),o.createElement(s.Provider,{value:n},e.children)}}}]);
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";(self.webpackChunksolace_agenitc_mesh_docs=self.webpackChunksolace_agenitc_mesh_docs||[]).push([[1442],{8376:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>r,contentTitle:()=>o,default:()=>h,frontMatter:()=>a,metadata:()=>i,toc:()=>c});const i=JSON.parse('{"id":"documentation/concepts/plugins","title":"Plugins","description":"Plugins","source":"@site/docs/documentation/concepts/plugins.md","sourceDirName":"documentation/concepts","slug":"/documentation/concepts/plugins","permalink":"/solace-agent-mesh/docs/documentation/concepts/plugins","draft":false,"unlisted":false,"editUrl":"https://github.com/SolaceLabs/solace-agent-mesh/edit/main/docs/docs/documentation/concepts/plugins.md","tags":[],"version":"current","sidebarPosition":60,"frontMatter":{"title":"Plugins","sidebar_position":60},"sidebar":"docSidebar","previous":{"title":"Orchestrator","permalink":"/solace-agent-mesh/docs/documentation/concepts/orchestrator"},"next":{"title":"Solace AI Event Connector","permalink":"/solace-agent-mesh/docs/documentation/user-guide/solace-ai-connector"}}');var s=t(4848),l=t(8453);const a={title:"Plugins",sidebar_position:60},o=void 0,r={},c=[{value:"Plugins",id:"plugins",level:2},{value:"Official Core Plugins",id:"official-core-plugins",level:3},{value:"Create a Plugin",id:"create-a-plugin",level:2},{value:"Build the Plugin",id:"build-the-plugin",level:3},{value:"Share the Plugin",id:"share-the-plugin",level:3},{value:"Use a Plugin",id:"use-a-plugin",level:2},{value:"Plugin Catalog Dashboard",id:"plugin-catalog-dashboard",level:2},{value:"Agent or Plugin: Which To Use?",id:"agent-or-plugin-which-to-use",level:2},{value:"When To Use a Standalone Agent",id:"when-to-use-a-standalone-agent",level:3},{value:"When To Use an Agent Plugin",id:"when-to-use-an-agent-plugin",level:3},{value:"Recommendation",id:"recommendation",level:3}];function d(e){const n={a:"a",admonition:"admonition",code:"code",h2:"h2",h3:"h3",li:"li",p:"p",pre:"pre",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,l.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h2,{id:"plugins",children:"Plugins"}),"\n",(0,s.jsx)(n.p,{children:"Plugins provide a mechanism to extend the functionality of Solace Agent Mesh in a modular, shareable, and reusable way. The current plugin ecosystem includes agents, gateways, and specialized integrations."}),"\n",(0,s.jsx)(n.admonition,{title:"In one sentence",type:"tip",children:(0,s.jsx)(n.p,{children:"Plugins are modular Python packages that extend Solace Agent Mesh's capabilities through agents, gateways, and specialized integrations."})}),"\n",(0,s.jsxs)(n.p,{children:["Plugins are packaged as Python modules that can be installed using various package managers (",(0,s.jsx)(n.code,{children:"pip"}),", ",(0,s.jsx)(n.code,{children:"uv"}),", ",(0,s.jsx)(n.code,{children:"poetry"}),", ",(0,s.jsx)(n.code,{children:"conda"}),"). They integrate seamlessly with the A2A protocol and can provide:"]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Agent Plugins"}),": Specialized agents with domain-specific capabilities"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Gateway Plugins"}),": New interface types for external system integration"]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Custom Plugins"}),": Custom integrations such as HR providers."]}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"All plugin interactions (create, build, add) are managed through the Solace Agent Mesh CLI."}),"\n",(0,s.jsx)(n.admonition,{type:"info",children:(0,s.jsxs)(n.p,{children:["Run ",(0,s.jsx)(n.code,{children:"sam plugin --help"})," to see the list of available commands for plugins."]})}),"\n",(0,s.jsx)(n.h3,{id:"official-core-plugins",children:"Official Core Plugins"}),"\n",(0,s.jsxs)(n.p,{children:["Solace Agent Mesh comes with a set of official core plugins that can be used to extend the functionality of the system. You can find the repository of the official core plugins ",(0,s.jsx)(n.a,{href:"https://github.com/SolaceLabs/solace-agent-mesh-core-plugins",children:"here \ud83d\udd17"}),"."]}),"\n",(0,s.jsxs)(n.p,{children:["For more information about how to use the official core plugins, see ",(0,s.jsx)(n.a,{href:"#use-a-plugin",children:"Use Plugins"}),"."]}),"\n",(0,s.jsx)(n.h2,{id:"create-a-plugin",children:"Create a Plugin"}),"\n",(0,s.jsxs)(n.p,{children:["To get started, ",(0,s.jsx)(n.a,{href:"/solace-agent-mesh/docs/documentation/getting-started/installation",children:"install the Solace Agent Mesh CLI"})," and run the following command:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"solace-agent-mesh plugin create <plugin-name>\n"})}),"\n",(0,s.jsx)(n.p,{children:"Follow the prompts to create a new plugin. A plugin can be one of the following types:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Agent Plugin"}),": Contains custom agents that can be used in a Solace Agent Mesh project."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Gateway Plugin"}),": Contains custom gateways that can be used in a Solace Agent Mesh project."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Custom Plugin"}),": Contains custom integrations such as HR providers or other specialized functionality."]}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"Solace Agent Mesh CLI creates a directory with the provided name and the following structure:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:"plugin-name/\n\u251c\u2500 config.yaml\n\u251c\u2500 src/\n\u2502 \u251c\u2500 __init__.py\n\u2502 \u251c\u2500 [...Other type specific python files]\n\u251c\u2500 .gitignore\n\u251c\u2500 pyproject.toml\n\u251c\u2500 README.md\n"})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["The ",(0,s.jsx)(n.code,{children:"src"})," directory contains the python source code."]}),"\n",(0,s.jsxs)(n.li,{children:["The ",(0,s.jsx)(n.code,{children:"config.yaml"})," file holds the configuration for the plugin, and how to be used in a Solace Agent Mesh application."]}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"Once the plugin is created, you can start customizing the config.yaml or the python files."}),"\n",(0,s.jsx)(n.h3,{id:"build-the-plugin",children:"Build the Plugin"}),"\n",(0,s.jsxs)(n.p,{children:["Building the plugin creates a Python wheel package that can be installed using ",(0,s.jsx)(n.code,{children:"pip"})," or other package managers."]}),"\n",(0,s.jsxs)(n.p,{children:["Python ",(0,s.jsx)(n.code,{children:"build"})," package must be installed already since ",(0,s.jsx)(n.code,{children:"sam plugin build"})," command uses ",(0,s.jsx)(n.code,{children:"build"})," package, if not, run ",(0,s.jsx)(n.code,{children:"pip install build"}),"."]}),"\n",(0,s.jsx)(n.p,{children:"To build the plugin, run the following Solace Agent Mesh CLI command:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"solace-agent-mesh plugin build\n"})}),"\n",(0,s.jsxs)(n.p,{children:["The plugin uses the standard ",(0,s.jsx)(n.code,{children:"pyproject.toml"})," file to build the package."]}),"\n",(0,s.jsx)(n.h3,{id:"share-the-plugin",children:"Share the Plugin"}),"\n",(0,s.jsxs)(n.p,{children:["To share the plugin, you can upload the wheel package to a package repository or share the wheel package directly, or any other valid way to share a ",(0,s.jsx)(n.code,{children:"pyproject"})," project."]}),"\n",(0,s.jsx)(n.h2,{id:"use-a-plugin",children:"Use a Plugin"}),"\n",(0,s.jsxs)(n.p,{children:["To use a plugin in your project, use the ",(0,s.jsx)(n.code,{children:"plugin add"})," command, which performs two steps under-the-hood:"]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["Locates the plugin or installs the plugin package using a Python package manager (like ",(0,s.jsx)(n.code,{children:"pip"})," or ",(0,s.jsx)(n.code,{children:"uv"}),")"]}),"\n",(0,s.jsx)(n.li,{children:"Creates a component instance based on the plugin"}),"\n"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"solace-agent-mesh plugin add <COMPONENT_NAME> --plugin <PLUGIN_NAME>\n"})}),"\n",(0,s.jsx)(n.p,{children:"where:"}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"<COMPONENT_NAME>"})," is the name you choose for the component instance in your project."]}),"\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.code,{children:"<PLUGIN_NAME>"}),", you can use:"]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["Name of the plugin as published to a package manager like ",(0,s.jsx)(n.code,{children:"pypi"}),", for example ",(0,s.jsx)(n.code,{children:"my-plugin"})]}),"\n",(0,s.jsx)(n.li,{children:"Name of the plugin that has been already installed into your Python environment."}),"\n",(0,s.jsxs)(n.li,{children:["A local path to the plugin directory, for example ",(0,s.jsx)(n.code,{children:"./my-plugin"})]}),"\n",(0,s.jsxs)(n.li,{children:["A path to a wheel package, for example ",(0,s.jsx)(n.code,{children:"./my-plugin/dist/my_plugin-0.1.0-py3-none-any.whl"})]}),"\n",(0,s.jsxs)(n.li,{children:["A URL to a git repository, for example ",(0,s.jsx)(n.code,{children:"git+https://github.com/<USERNAME>/<REPOSITORY>"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["If the plugin is in a subdirectory of the repository, you can specify the subdirectory using the ",(0,s.jsx)(n.code,{children:"git+https://github.com/<USERNAME>/<REPOSITORY>#subdirectory=<PLUGIN_NAME>"})," syntax."]}),"\n"]}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"The CLI handles both steps automatically, or you can manage the plugin installation yourself using your preferred Python package manager."}),"\n",(0,s.jsxs)(n.admonition,{type:"tip",children:[(0,s.jsxs)(n.p,{children:["You can also customize the python package manager command used to install the plugin by setting the ",(0,s.jsx)(n.code,{children:"SAM_PLUGIN_INSTALL_COMMAND"})," environment variable or passing the ",(0,s.jsx)(n.code,{children:"--install-command"})," option to the ",(0,s.jsx)(n.code,{children:"plugin add"})," command.\nFor example, to use ",(0,s.jsx)(n.code,{children:"uv"})," as the package manager, you can run:"]}),(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:'export SAM_PLUGIN_INSTALL_COMMAND="uv pip install {package}"\n'})}),(0,s.jsx)(n.p,{children:"or"}),(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:'solace-agent-mesh plugin add <COMPONENT_NAME> --plugin <PLUGIN_NAME> --install-command "uv pip install {package}"\n'})})]}),"\n",(0,s.jsxs)(n.p,{children:["This command adds the plugin instance configuration to your ",(0,s.jsx)(n.code,{children:"configs"})," directory."]}),"\n",(0,s.jsx)(n.p,{children:"Depending on the plugin, you may need to update the newly added plugin configuration file. Follow the instructions provided by the plugin author for any specific configurations."}),"\n",(0,s.jsx)(n.h2,{id:"plugin-catalog-dashboard",children:"Plugin Catalog Dashboard"}),"\n",(0,s.jsxs)(n.p,{children:["You can manage available plugins with the ",(0,s.jsx)(n.code,{children:"plugin catalog"})," command, which launches a user-friendly interface."]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"solace-agent-mesh plugin catalog\n"})}),"\n",(0,s.jsx)(n.h2,{id:"agent-or-plugin-which-to-use",children:"Agent or Plugin: Which To Use?"}),"\n",(0,s.jsx)(n.p,{children:"In simple terms, plugins of type agent are just packaged agents. However, there are distinct advantages to each approach, and choosing the right one depends on your use case."}),"\n",(0,s.jsx)(n.p,{children:"Here\u2019s a detailed comparison to help you decide."}),"\n",(0,s.jsxs)(n.table,{children:[(0,s.jsx)(n.thead,{children:(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.th,{style:{textAlign:"left"},children:"Feature"}),(0,s.jsxs)(n.th,{style:{textAlign:"left"},children:["Standalone Agent (",(0,s.jsx)(n.code,{children:"sam add agent"}),")"]}),(0,s.jsxs)(n.th,{style:{textAlign:"left"},children:["Agent Plugin (",(0,s.jsx)(n.code,{children:"sam plugin create"}),")"]})]})}),(0,s.jsxs)(n.tbody,{children:[(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{style:{textAlign:"left"},children:(0,s.jsx)(n.strong,{children:"Creation"})}),(0,s.jsx)(n.td,{style:{textAlign:"left"},children:"A single command creates a configuration file in your project."}),(0,s.jsx)(n.td,{style:{textAlign:"left"},children:"Creates a complete, standard Python project structure."})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{style:{textAlign:"left"},children:(0,s.jsx)(n.strong,{children:"Structure"})}),(0,s.jsx)(n.td,{style:{textAlign:"left"},children:"Consists of a YAML configuration file and associated Python tool files within a Solace Agent Mesh project."}),(0,s.jsxs)(n.td,{style:{textAlign:"left"},children:["A self-contained Python package with ",(0,s.jsx)(n.code,{children:"pyproject.toml"}),", a ",(0,s.jsx)(n.code,{children:"src"})," directory, and configuration templates."]})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{style:{textAlign:"left"},children:(0,s.jsx)(n.strong,{children:"Packaging"})}),(0,s.jsx)(n.td,{style:{textAlign:"left"},children:"Not packaged. It exists as a component within a larger Solace Agent Mesh project."}),(0,s.jsxs)(n.td,{style:{textAlign:"left"},children:["Packaged into a standard Python wheel (",(0,s.jsx)(n.code,{children:".whl"}),") file using ",(0,s.jsx)(n.code,{children:"sam plugin build"}),"."]})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{style:{textAlign:"left"},children:(0,s.jsx)(n.strong,{children:"Distribution"})}),(0,s.jsx)(n.td,{style:{textAlign:"left"},children:"Shared by copying files or sharing the entire project."}),(0,s.jsx)(n.td,{style:{textAlign:"left"},children:"Easily distributed as a wheel file, via a Git repository, or published to a package index like PyPI."})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{style:{textAlign:"left"},children:(0,s.jsx)(n.strong,{children:"Reusability"})}),(0,s.jsx)(n.td,{style:{textAlign:"left"},children:"Primarily for use within the project where it was created."}),(0,s.jsx)(n.td,{style:{textAlign:"left"},children:"Designed for high reusability across different projects, teams, and communities."})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{style:{textAlign:"left"},children:(0,s.jsx)(n.strong,{children:"Installation"})}),(0,s.jsx)(n.td,{style:{textAlign:"left"},children:"No installation needed. The agent is configured and run as part of the main project."}),(0,s.jsxs)(n.td,{style:{textAlign:"left"},children:["Installed into the Python environment using ",(0,s.jsx)(n.code,{children:"sam plugin add"}),", which handles the package installation."]})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{style:{textAlign:"left"},children:(0,s.jsx)(n.strong,{children:"Versioning"})}),(0,s.jsx)(n.td,{style:{textAlign:"left"},children:"Versioned along with the main project."}),(0,s.jsxs)(n.td,{style:{textAlign:"left"},children:["Can be versioned independently according to Python packaging standards (e.g., ",(0,s.jsx)(n.code,{children:"v0.1.0"}),", ",(0,s.jsx)(n.code,{children:"v0.2.0"}),")."]})]}),(0,s.jsxs)(n.tr,{children:[(0,s.jsx)(n.td,{style:{textAlign:"left"},children:(0,s.jsx)(n.strong,{children:"Development"})}),(0,s.jsx)(n.td,{style:{textAlign:"left"},children:"Simple and direct. Edit files and run. Ideal for rapid prototyping."}),(0,s.jsx)(n.td,{style:{textAlign:"left"},children:"Involves a build/install cycle. Better for structured, long-term development."})]})]})]}),"\n",(0,s.jsx)(n.h3,{id:"when-to-use-a-standalone-agent",children:"When To Use a Standalone Agent"}),"\n",(0,s.jsx)(n.p,{children:"Create a standalone agent when:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"You need to quickly test an idea or build a proof-of-concept."}),"\n",(0,s.jsx)(n.li,{children:"The agent is tightly coupled to a single project and is not intended for reuse."}),"\n",(0,s.jsx)(n.li,{children:"You want the most straightforward path to adding a simple agent without the overhead of a full package structure."}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"when-to-use-an-agent-plugin",children:"When To Use an Agent Plugin"}),"\n",(0,s.jsx)(n.p,{children:"Create an agent as a plugin when:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"You plan to use the same agent in multiple projects."}),"\n",(0,s.jsx)(n.li,{children:"You want to share your agent with other developers, teams, or the open-source community."}),"\n",(0,s.jsx)(n.li,{children:"You are building a robust, production-ready agent that benefits from a formal package structure, dependency management, and versioning."}),"\n",(0,s.jsx)(n.li,{children:"You are building a collection of standardized agents for your organization."}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"recommendation",children:"Recommendation"}),"\n",(0,s.jsx)(n.p,{children:"The choice of how to build your agent depends on your goals and the requirements of your project:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"Standalone Agents"})," should be viewed as tactical tools for rapid, isolated prototyping. They serve immediate, project-specific needs but do not contribute to a scalable, long-term asset library."]}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsxs)(n.p,{children:[(0,s.jsx)(n.strong,{children:"Agent Plugins"})," are the foundation for building a robust, governable, and reusable AI ecosystem. This model treats AI capabilities as enterprise assets, promoting standardization, reducing redundant development costs, and accelerating innovation across the organization. For any capability intended for broader use or long-term value, the plugin framework is the mandated path to maximize return on investment and ensure architectural integrity."]}),"\n"]}),"\n"]})]})}function h(e={}){const{wrapper:n}={...(0,l.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:()=>a,x:()=>o});var i=t(6540);const s={},l=i.createContext(s);function a(e){const n=i.useContext(l);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:a(e.components),i.createElement(l.Provider,{value:n},e.children)}}}]);
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";(self.webpackChunksolace_agenitc_mesh_docs=self.webpackChunksolace_agenitc_mesh_docs||[]).push([[3861],{4854:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>d,contentTitle:()=>o,default:()=>h,frontMatter:()=>r,metadata:()=>i,toc:()=>c});const i=JSON.parse('{"id":"documentation/getting-started/configurations/configurations","title":"Configurations","description":"Shared Configurations","source":"@site/docs/documentation/getting-started/configurations/configurations.md","sourceDirName":"documentation/getting-started/configurations","slug":"/documentation/getting-started/configurations/","permalink":"/solace-agent-mesh/docs/documentation/getting-started/configurations/","draft":false,"unlisted":false,"editUrl":"https://github.com/SolaceLabs/solace-agent-mesh/edit/main/docs/docs/documentation/getting-started/configurations/configurations.md","tags":[],"version":"current","sidebarPosition":10,"frontMatter":{"title":"Configurations","sidebar_position":10,"toc_max_heading_level":4},"sidebar":"docSidebar","previous":{"title":"Component Overview","permalink":"/solace-agent-mesh/docs/documentation/getting-started/component-overview"},"next":{"title":"LLM Models","permalink":"/solace-agent-mesh/docs/documentation/getting-started/configurations/litellm_models"}}');var s=n(4848),l=n(8453);const r={title:"Configurations",sidebar_position:10,toc_max_heading_level:4},o="Configurations",d={},c=[{value:"Shared Configurations",id:"shared-configurations",level:2},{value:"Using Shared Configurations",id:"using-shared-configurations",level:3},{value:"Managing Multiple Shared Configuration Files",id:"managing-multiple-shared-configuration-files",level:3},{value:"Parameters",id:"parameters",level:3},{value:"Example <code>shared_config.yaml</code>",id:"example-shared_configyaml",level:5},{value:"Broker Connection",id:"broker-connection",level:4},{value:"Models",id:"models",level:4},{value:"Model Configuration Structure",id:"model-configuration-structure",level:5},{value:"Pre-Defined Model Types",id:"pre-defined-model-types",level:5},{value:"Services",id:"services",level:4},{value:"Session Service",id:"session-service",level:5},{value:"Artifact Service",id:"artifact-service",level:5},{value:"Data Tools Config",id:"data-tools-config",level:5},{value:"System Logs",id:"system-logs",level:2}];function a(e){const t={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",h5:"h5",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,l.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.header,{children:(0,s.jsx)(t.h1,{id:"configurations",children:"Configurations"})}),"\n",(0,s.jsx)(t.h2,{id:"shared-configurations",children:"Shared Configurations"}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"shared_config.yaml"})," file is used to define configurations that can be shared across multiple agents or components in Solace Agent Mesh. This allows for centralized management of common settings like broker connections and language model configurations."]}),"\n",(0,s.jsx)(t.h3,{id:"using-shared-configurations",children:"Using Shared Configurations"}),"\n",(0,s.jsxs)(t.p,{children:["All agents and gateways require access to a ",(0,s.jsx)(t.code,{children:"shared_config"})," object. You can provide configuration in the following ways:"]}),"\n",(0,s.jsxs)(t.ol,{children:["\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Hard-coding values"}),": You can directly embed the ",(0,s.jsx)(t.code,{children:"shared_config"})," values within your agent or gateway YAML files."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsxs)(t.strong,{children:["Using ",(0,s.jsx)(t.code,{children:"!include"})]}),": For better project consistency and management, you can use the ",(0,s.jsx)(t.code,{children:"!include"})," directive to load a shared configuration file."]}),"\n"]}),"\n",(0,s.jsxs)(t.p,{children:["When a plugin is installed, it may come with hard-coded default values. It is a best practice to remove this section and use ",(0,s.jsx)(t.code,{children:"!include"})," to point to the centralized ",(0,s.jsx)(t.code,{children:"shared_config"})," file. This ensures that all components are using the same base configuration."]}),"\n",(0,s.jsx)(t.h3,{id:"managing-multiple-shared-configuration-files",children:"Managing Multiple Shared Configuration Files"}),"\n",(0,s.jsx)(t.p,{children:"You can use multiple shared configuration files to manage different environments or setups (e.g., for different cloud providers). You must follow these rules:"}),"\n",(0,s.jsxs)(t.ol,{children:["\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Filename"}),": The filename must always start with ",(0,s.jsx)(t.code,{children:"shared_config"})," (e.g., ",(0,s.jsx)(t.code,{children:"shared_config_aws.yaml"}),", ",(0,s.jsx)(t.code,{children:"shared_config_gcp.yaml"}),")."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:"Sub-directories"}),": You can organize these files into sub-directories (e.g., ",(0,s.jsx)(t.code,{children:"configs/agents/shared_config.yaml"}),"). When you do this, you must update the ",(0,s.jsx)(t.code,{children:"!include"})," path in your agent or gateway configurations to point to the correct location."]}),"\n"]}),"\n",(0,s.jsxs)(t.p,{children:["The file uses YAML anchors (",(0,s.jsx)(t.code,{children:"&anchor_name"}),") to create reusable configuration blocks, which can then be referenced in agent configuration files."]}),"\n",(0,s.jsx)(t.h3,{id:"parameters",children:"Parameters"}),"\n",(0,s.jsxs)(t.h5,{id:"example-shared_configyaml",children:["Example ",(0,s.jsx)(t.code,{children:"shared_config.yaml"})]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-yaml",children:"shared_config:\n - broker_connection: &broker_connection\n dev_mode: ${SOLACE_DEV_MODE, false}\n broker_url: ${SOLACE_BROKER_URL, ws://localhost:8008}\n broker_username: ${SOLACE_BROKER_USERNAME, default}\n broker_password: ${SOLACE_BROKER_PASSWORD, default}\n broker_vpn: ${SOLACE_BROKER_VPN, default}\n temporary_queue: ${USE_TEMPORARY_QUEUES, true}\n # Ensure high enough limits if many agents are running\n # max_connection_retries: -1 # Retry forever\n\n - models:\n planning: &planning_model\n # This dictionary structure tells ADK to use the LiteLlm wrapper.\n # 'model' uses the specific model identifier your endpoint expects.\n model: ${LLM_SERVICE_PLANNING_MODEL_NAME} # Use env var for model name\n # 'api_base' tells LiteLLM where to send the request.\n api_base: ${LLM_SERVICE_ENDPOINT} # Use env var for endpoint URL\n # 'api_key' provides authentication.\n api_key: ${LLM_SERVICE_API_KEY} # Use env var for API key\n # Enable parallel tool calls for planning model\n parallel_tool_calls: true \n # max_tokens: ${MAX_TOKENS, 16000} # Set a reasonable max token limit for planning\n # temperature: 0.1 # Lower temperature for more deterministic planning\n \n general: &general_model\n # This dictionary structure tells ADK to use the LiteLlm wrapper.\n # 'model' uses the specific model identifier your endpoint expects.\n model: ${LLM_SERVICE_GENERAL_MODEL_NAME} # Use env var for model name\n # 'api_base' tells LiteLLM where to send the request.\n api_base: ${LLM_SERVICE_ENDPOINT} # Use env var for endpoint URL\n # 'api_key' provides authentication.\n api_key: ${LLM_SERVICE_API_KEY} # Use env var for API key\n\n # ... (similar structure)\n\n - services:\n # Default session service configuration\n session_service: &default_session_service\n type: \"memory\"\n default_behavior: \"PERSISTENT\"\n \n # Default artifact service configuration\n artifact_service: &default_artifact_service\n type: \"filesystem\"\n base_path: \"/tmp/samv2\"\n artifact_scope: namespace\n \n # Default data tools configuration\n data_tools_config: &default_data_tools_config\n sqlite_memory_threshold_mb: 100\n max_result_preview_rows: 50\n max_result_preview_bytes: 4096\n"})}),"\n",(0,s.jsx)(t.h4,{id:"broker-connection",children:"Broker Connection"}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"broker_connection"})," section configures the connection to the Solace event broker. The connection parameters are described in the following table:"]}),"\n",(0,s.jsxs)(t.table,{children:[(0,s.jsx)(t.thead,{children:(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.th,{style:{textAlign:"left"},children:"Parameter"}),(0,s.jsx)(t.th,{style:{textAlign:"left"},children:"Environment Variable"}),(0,s.jsx)(t.th,{style:{textAlign:"left"},children:"Description"}),(0,s.jsx)(t.th,{style:{textAlign:"left"},children:"Default"})]})}),(0,s.jsxs)(t.tbody,{children:[(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"dev_mode"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"SOLACE_DEV_MODE"})}),(0,s.jsxs)(t.td,{style:{textAlign:"left"},children:["When set to ",(0,s.jsx)(t.code,{children:"true"}),", uses an in-memory broker for testing."]}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"false"})})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"broker_url"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"SOLACE_BROKER_URL"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:"The URL of the Solace broker."}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"ws://localhost:8008"})})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"broker_username"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"SOLACE_BROKER_USERNAME"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:"The username for authenticating with the broker."}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"default"})})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"broker_password"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"SOLACE_BROKER_PASSWORD"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:"The password for authenticating with the broker."}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"default"})})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"broker_vpn"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"SOLACE_BROKER_VPN"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:"The Message VPN to connect to on the broker."}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"default"})})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"temporary_queue"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"USE_TEMPORARY_QUEUES"})}),(0,s.jsxs)(t.td,{style:{textAlign:"left"},children:["Whether to use temporary queues for communication. If ",(0,s.jsx)(t.code,{children:"false"}),", a durable queue will be created."]}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"true"})})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"max_connection_retries"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"MAX_CONNECTION_RETRIES"})}),(0,s.jsxs)(t.td,{style:{textAlign:"left"},children:["The maximum number of times to retry connecting to the broker if the connection fails. A value of ",(0,s.jsx)(t.code,{children:"-1"})," means retry forever."]}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"-1"})})]})]})]}),"\n",(0,s.jsx)(t.admonition,{type:"tip",children:(0,s.jsxs)(t.p,{children:["If you need to configure multiple brokers, you can do so by adding additional entries under ",(0,s.jsx)(t.code,{children:"shared_config"})," with a unique name (For example, ",(0,s.jsx)(t.code,{children:"broker_connection_eu: &broker_connection_eu"})," or ",(0,s.jsx)(t.code,{children:"broker_connection_us: &broker_connection_us"}),") and then use the proper reference in your agent configurations. (Example: ",(0,s.jsx)(t.code,{children:"<<: *broker_connection_eu"}),")"]})}),"\n",(0,s.jsx)(t.h4,{id:"models",children:"Models"}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"models"})," section is used to configure the various Large Language Models (LLMs) and other generative models used by the agents. The configuration uses the ",(0,s.jsx)(t.a,{href:"https://litellm.ai/",children:"LiteLLM"})," library, which provides a standardized way to interact with ",(0,s.jsx)(t.a,{href:"https://docs.litellm.ai/docs/providers",children:"different model providers"}),"."]}),"\n",(0,s.jsx)(t.h5,{id:"model-configuration-structure",children:"Model Configuration Structure"}),"\n",(0,s.jsx)(t.p,{children:"The following table describes the parameters that tell the system how to interact with the model:"}),"\n",(0,s.jsxs)(t.table,{children:[(0,s.jsx)(t.thead,{children:(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.th,{style:{textAlign:"left"},children:"Parameter"}),(0,s.jsx)(t.th,{style:{textAlign:"left"},children:"Environment Variable"}),(0,s.jsx)(t.th,{style:{textAlign:"left"},children:"Description"})]})}),(0,s.jsxs)(t.tbody,{children:[(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"model"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"LLM_SERVICE_<MODEL_NAME>_MODEL_NAME"})}),(0,s.jsxs)(t.td,{style:{textAlign:"left"},children:["The specific model identifier that the endpoint expects in the format of ",(0,s.jsx)(t.code,{children:"provider/model"})," (e.g., ",(0,s.jsx)(t.code,{children:"openai/gpt-4"}),", ",(0,s.jsx)(t.code,{children:"anthropic/claude-3-opus-20240229"}),")."]})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"api_base"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"LLM_SERVICE_ENDPOINT"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:"The base URL of the LLM provider's API endpoint."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"api_key"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"LLM_SERVICE_API_KEY"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:"The API key for authenticating with the service."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"parallel_tool_calls"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"PARALLEL_TOOL_CALLS"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:"Enable parallel tool calls for the model."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"max_tokens"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"MAX_TOKENS"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:"Set a reasonable max token limit for the model."})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"temperature"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"TEMPERATURE"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:"Lower temperature for more deterministic planning."})]})]})]}),"\n",(0,s.jsx)(t.p,{children:"Alternatively, you can use Gemini models directly through Google Studio AI or Vertex AI:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-yaml",children:"model: gemini-2.5-pro\n"})}),"\n",(0,s.jsxs)(t.p,{children:["See the ",(0,s.jsx)(t.a,{href:"https://google.github.io/adk-docs/agents/models/#using-google-gemini-models",children:"documentation"})," for details on setting the environment for Gemini models."]}),"\n",(0,s.jsx)(t.h5,{id:"pre-defined-model-types",children:"Pre-Defined Model Types"}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"shared_config.yaml"})," example defines several models for different purposes. A pre-defined model serves as an alias for the model configuration. This alias allows you to refer to a configuration by its use case rather than its specific parameters."]}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:(0,s.jsx)(t.code,{children:"planning"})}),": Used by agents for planning and decision-making. It's configured for deterministic outputs (",(0,s.jsx)(t.code,{children:"temperature: 0.1"}),") and can use tools in parallel."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:(0,s.jsx)(t.code,{children:"general"})}),": A general-purpose model for various tasks."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:(0,s.jsx)(t.code,{children:"image_gen"})}),": A model for generating images."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:(0,s.jsx)(t.code,{children:"image_describe"})}),": A model for describing the content of images."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:(0,s.jsx)(t.code,{children:"audio_transcription"})}),": A model for transcribing audio files."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:(0,s.jsx)(t.code,{children:"report_gen"})}),": A model specialized for generating reports."]}),"\n",(0,s.jsxs)(t.li,{children:[(0,s.jsx)(t.strong,{children:(0,s.jsx)(t.code,{children:"multimodal"})}),": A simple string reference to a multimodal model (e.g., ",(0,s.jsx)(t.code,{children:'"gemini-1.5-flash-latest"'}),")."]}),"\n"]}),"\n",(0,s.jsxs)(t.p,{children:["You can define any number of models in this section and reference them in your agent configurations. ",(0,s.jsxs)(t.strong,{children:["By default, the system only uses the ",(0,s.jsx)(t.code,{children:"planning"})," and the ",(0,s.jsx)(t.code,{children:"general"})," models. No need to fill the other fields"]})]}),"\n",(0,s.jsx)(t.admonition,{type:"info",children:(0,s.jsxs)(t.p,{children:["For more information on configuring different LLM models and SSL/TLS settings, please refer to the ",(0,s.jsx)(t.a,{href:"/solace-agent-mesh/docs/documentation/getting-started/configurations/litellm_models",children:"LLM Models"})," documentation."]})}),"\n",(0,s.jsx)(t.h4,{id:"services",children:"Services"}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"services"})," section in ",(0,s.jsx)(t.code,{children:"shared_config.yaml"})," is used to configure various services that are available to agents."]}),"\n",(0,s.jsx)(t.h5,{id:"session-service",children:"Session Service"}),"\n",(0,s.jsx)(t.p,{children:"The parameters are described in the following table:"}),"\n",(0,s.jsxs)(t.table,{children:[(0,s.jsx)(t.thead,{children:(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.th,{style:{textAlign:"left"},children:"Parameter"}),(0,s.jsx)(t.th,{style:{textAlign:"left"},children:"Options"}),(0,s.jsx)(t.th,{style:{textAlign:"left"},children:"Description"}),(0,s.jsx)(t.th,{style:{textAlign:"left"},children:"Default"})]})}),(0,s.jsxs)(t.tbody,{children:[(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"type"})}),(0,s.jsxs)(t.td,{style:{textAlign:"left"},children:[(0,s.jsx)(t.code,{children:"memory"}),", ",(0,s.jsx)(t.code,{children:"sql"}),", ",(0,s.jsx)(t.code,{children:"vertex_rag"})]}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:"Configuration for ADK Session Service"}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"memory"})})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"default_behavior"})}),(0,s.jsxs)(t.td,{style:{textAlign:"left"},children:[(0,s.jsx)(t.code,{children:"PERSISTENT"}),", ",(0,s.jsx)(t.code,{children:"RUN_BASED"})]}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:"The default behavior of keeping the session history"}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"PERSISTENT"})})]})]})]}),"\n",(0,s.jsx)(t.admonition,{type:"tip",children:(0,s.jsxs)(t.p,{children:["Although the default session service type is ",(0,s.jsx)(t.code,{children:"memory"}),", both Orchestrator Agent and Web UI gateway use ",(0,s.jsx)(t.code,{children:"sql"})," as their session service to allow for persistent sessions."]})}),"\n",(0,s.jsx)(t.h5,{id:"artifact-service",children:"Artifact Service"}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"artifact_service"})," is responsible for managing artifacts, which are files or data generated by agents."]}),"\n",(0,s.jsxs)(t.table,{children:[(0,s.jsx)(t.thead,{children:(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.th,{style:{textAlign:"left"},children:"Parameter"}),(0,s.jsx)(t.th,{style:{textAlign:"left"},children:"Options"}),(0,s.jsx)(t.th,{style:{textAlign:"left"},children:"Description"}),(0,s.jsx)(t.th,{style:{textAlign:"left"},children:"Default"})]})}),(0,s.jsxs)(t.tbody,{children:[(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"type"})}),(0,s.jsxs)(t.td,{style:{textAlign:"left"},children:[(0,s.jsx)(t.code,{children:"memory"}),", ",(0,s.jsx)(t.code,{children:"gcs"}),", ",(0,s.jsx)(t.code,{children:"filesystem"})]}),(0,s.jsxs)(t.td,{style:{textAlign:"left"},children:["Service type for artifact storage. Use ",(0,s.jsx)(t.code,{children:"memory"})," for in-memory, ",(0,s.jsx)(t.code,{children:"gcs"})," for Google Cloud Storage, or ",(0,s.jsx)(t.code,{children:"filesystem"})," for local file storage."]}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"memory"})})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"base_path"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:"local path"}),(0,s.jsxs)(t.td,{style:{textAlign:"left"},children:["Base directory path for storing artifacts. Required only if ",(0,s.jsx)(t.code,{children:"type"})," is ",(0,s.jsx)(t.code,{children:"filesystem"}),"."]}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:"(none)"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"bucket_name"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:"bucket name"}),(0,s.jsxs)(t.td,{style:{textAlign:"left"},children:["Google Cloud Storage bucket name. Required only if ",(0,s.jsx)(t.code,{children:"type"})," is ",(0,s.jsx)(t.code,{children:"gcs"}),"."]}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:"(none)"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"artifact_scope"})}),(0,s.jsxs)(t.td,{style:{textAlign:"left"},children:[(0,s.jsx)(t.code,{children:"namespace"}),", ",(0,s.jsx)(t.code,{children:"app"})]}),(0,s.jsxs)(t.td,{style:{textAlign:"left"},children:["Scope for artifact sharing. ",(0,s.jsx)(t.code,{children:"namespace"}),": shared by all components in the namespace. ",(0,s.jsx)(t.code,{children:"app"}),": isolated by agent/gateway name. Must be consistent for all components in the same process."]}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"namespace"})})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"artifact_scope_value"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:"custom scope id"}),(0,s.jsxs)(t.td,{style:{textAlign:"left"},children:["Custom identifier for artifact scope. Required if ",(0,s.jsx)(t.code,{children:"artifact_scope"})," is set to a custom value."]}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:"(none)"})]})]})]}),"\n",(0,s.jsx)(t.h5,{id:"data-tools-config",children:"Data Tools Config"}),"\n",(0,s.jsxs)(t.p,{children:["The ",(0,s.jsx)(t.code,{children:"data_tools_config"})," section configures the behavior of data analysis tools."]}),"\n",(0,s.jsxs)(t.table,{children:[(0,s.jsx)(t.thead,{children:(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.th,{style:{textAlign:"left"},children:"Parameter"}),(0,s.jsx)(t.th,{style:{textAlign:"left"},children:"Type"}),(0,s.jsx)(t.th,{style:{textAlign:"left"},children:"Description"}),(0,s.jsx)(t.th,{style:{textAlign:"left"},children:"Default"})]})}),(0,s.jsxs)(t.tbody,{children:[(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"sqlite_memory_threshold_mb"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"integer"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:"The memory threshold in megabytes for using an in-memory SQLite database."}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"100"})})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"max_result_preview_rows"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"integer"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:"The maximum number of rows to show in a result preview."}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"50"})})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"max_result_preview_bytes"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"integer"})}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:"The maximum number of bytes to show in a result preview."}),(0,s.jsx)(t.td,{style:{textAlign:"left"},children:(0,s.jsx)(t.code,{children:"4096"})})]})]})]}),"\n",(0,s.jsx)(t.h2,{id:"system-logs",children:"System Logs"}),"\n",(0,s.jsxs)(t.p,{children:["For details on how to configure system logging, including log rotation and verbosity levels, please see the ",(0,s.jsx)(t.a,{href:"/solace-agent-mesh/docs/documentation/deployment/debugging#system-logs",children:"System Logs"})," section in the debugging documentation."]})]})}function h(e={}){const{wrapper:t}={...(0,l.R)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(a,{...e})}):a(e)}},8453:(e,t,n)=>{n.d(t,{R:()=>r,x:()=>o});var i=n(6540);const s={},l=i.createContext(s);function r(e){const t=i.useContext(l);return i.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function o(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:r(e.components),i.createElement(l.Provider,{value:t},e.children)}}}]);
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";(self.webpackChunksolace_agenitc_mesh_docs=self.webpackChunksolace_agenitc_mesh_docs||[]).push([[2274],{4700:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>r,default:()=>h,frontMatter:()=>i,metadata:()=>o,toc:()=>c});const o=JSON.parse('{"id":"documentation/Enterprise/single-sign-on","title":"SSO","description":"How to enable SSO","source":"@site/docs/documentation/Enterprise/single-sign-on.md","sourceDirName":"documentation/Enterprise","slug":"/documentation/Enterprise/single-sign-on","permalink":"/solace-agent-mesh/docs/documentation/Enterprise/single-sign-on","draft":false,"unlisted":false,"editUrl":"https://github.com/SolaceLabs/solace-agent-mesh/edit/main/docs/docs/documentation/Enterprise/single-sign-on.md","tags":[],"version":"current","sidebarPosition":10,"frontMatter":{"title":"SSO","sidebar_position":10},"sidebar":"docSidebar","previous":{"title":"RBAC Setup Guide","permalink":"/solace-agent-mesh/docs/documentation/Enterprise/rbac-setup-guilde"}}');var s=t(4848),a=t(8453);const i={title:"SSO",sidebar_position:10},r=void 0,l={},c=[{value:"How to enable SSO",id:"how-to-enable-sso",level:2},{value:"Running Solace Agent Mesh Enterprise with SSO enabled",id:"running-solace-agent-mesh-enterprise-with-sso-enabled",level:2}];function _(e){const n={a:"a",admonition:"admonition",code:"code",h2:"h2",p:"p",pre:"pre",strong:"strong",...(0,a.R)(),...e.components},{Details:t}=n;return t||function(e,n){throw new Error("Expected "+(n?"component":"object")+" `"+e+"` to be defined: you likely forgot to import, pass, or provide it.")}("Details",!0),(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h2,{id:"how-to-enable-sso",children:"How to enable SSO"}),"\n",(0,s.jsx)(n.p,{children:"Before running the Docker container, create two configuration files for SSO under the root directory in your Named Docker Volume. Use the content provided below for each file:"}),"\n",(0,s.jsxs)(t,{children:[(0,s.jsx)("summary",{children:"Configuration files for SSO"}),(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"oauth2_server.yaml"})}),(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:'---\n# Example gateway configuration with OAuth2 service integration\n# This shows how to configure a gateway to use the OAuth2 authentication service\n\nlog:\n stdout_log_level: INFO\n log_file_level: DEBUG\n log_file: oauth_server.log\n\n!include ../shared_config.yaml\n\nshared_config:\n # OAuth2 service configuration\n - oauth2_config: &oauth2_config\n enabled: true\n config_file: "configs/sso_vol/oauth2_config.yaml"\n host: ${OAUTH2_HOST, localhost}\n port: ${OAUTH2_PORT, 9000}\n ssl_cert: "" # Optional: path to SSL certificate\n ssl_key: "" # Optional: path to SSL private key\n\nflows:\n # Initialize OAuth2 service\n - name: oauth2_service\n components:\n - component_name: oauth2_auth_service\n component_module: solace_agent_mesh_enterprise.components.oauth2_component\n component_config:\n <<: *oauth2_config\n'})}),(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"oauth2_config.yaml"})}),(0,s.jsx)(n.p,{children:"In the oauth2_config.yaml file, uncomment the authentication provider you want to use.\nNote that the Azure provider is configured as the default option."}),(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:'---\n# OAuth2 Service Configuration\n# This file configures the OAuth2 authentication service that supports multiple providers\n# All providers now use the unified OIDC approach with automatic endpoint discovery\n\n# Enable or disable the OAuth2 service\nenabled: ${OAUTH2_ENABLED:false}\n\n# Development mode - enables insecure transport and relaxed token scope for local development\n# Set OAUTH2_DEV_MODE=true for local development (NEVER use in production!)\ndevelopment_mode: ${OAUTH2_DEV_MODE:false}\n\n# OAuth2 providers configuration\n# All providers now use the unified OIDCProvider with automatic endpoint discovery\nproviders:\n # Google OAuth2 provider\n # google:\n # # OIDC issuer URL - endpoints will be discovered automatically\n # issuer: "https://accounts.google.com"\n # client_id: ${GOOGLE_CLIENT_ID}\n # client_secret: ${GOOGLE_CLIENT_SECRET}\n # redirect_uri: ${GOOGLE_REDIRECT_URI:http://localhost:8080/callback}\n # scope: "openid email profile"\n\n # Azure/Microsoft OAuth2 provider\n azure:\n # Azure OIDC issuer URL includes tenant ID\n issuer: https://login.microsoftonline.com/${AZURE_TENANT_ID}/v2.0\n client_id: ${AZURE_CLIENT_ID}\n client_secret: ${AZURE_CLIENT_SECRET}\n redirect_uri: ${AZURE_REDIRECT_URI:http://localhost:8080/callback}\n scope: "openid email profile offline_access"\n\n # Auth0 OAuth2 provider\n # auth0:\n # # Auth0 issuer URL\n # issuer: ${AUTH0_ISSUER:https://your-domain.auth0.com/}\n # client_id: ${AUTH0_CLIENT_ID}\n # client_secret: ${AUTH0_CLIENT_SECRET}\n # redirect_uri: ${AUTH0_REDIRECT_URI:http://localhost:8080/callback}\n # scope: "openid email profile"\n # # Optional: Auth0 audience for API access\n # audience: ${AUTH0_AUDIENCE:}\n\n # # Okta OAuth2 provider (example)\n # okta:\n # issuer: ${OKTA_ISSUER:https://your-okta-domain.okta.com/oauth2/default}\n # client_id: ${OKTA_CLIENT_ID}\n # client_secret: ${OKTA_CLIENT_SECRET}\n # redirect_uri: ${OKTA_REDIRECT_URI:http://localhost:8080/callback}\n # scope: "openid email profile"\n\n # # Keycloak OAuth2 provider (example)\n # keycloak:\n # issuer: ${KEYCLOAK_ISSUER:https://your-keycloak.com/auth/realms/your-realm}\n # client_id: ${KEYCLOAK_CLIENT_ID}\n # client_secret: ${KEYCLOAK_CLIENT_SECRET}\n # redirect_uri: ${KEYCLOAK_REDIRECT_URI:http://localhost:8080/callback}\n # scope: "openid email profile"\n\n # # Generic OIDC provider (for any standard OIDC-compliant provider)\n # custom_oidc:\n # # Just provide the issuer URL and the service will discover all endpoints\n # issuer: ${CUSTOM_OIDC_ISSUER:https://your-provider.com}\n # client_id: ${CUSTOM_OIDC_CLIENT_ID}\n # client_secret: ${CUSTOM_OIDC_CLIENT_SECRET}\n # redirect_uri: ${CUSTOM_OIDC_REDIRECT_URI:http://localhost:8080/callback}\n # scope: "openid email profile"\n\n# Logging configuration\nlogging:\n level: ${OAUTH2_LOG_LEVEL:INFO}\n\n# Session configuration\nsession:\n # Session timeout in seconds (default: 1 hour)\n timeout: ${OAUTH2_SESSION_TIMEOUT:3600}\n\n# Security configuration\nsecurity:\n # CORS settings\n cors:\n enabled: ${OAUTH2_CORS_ENABLED:true}\n origins: ${OAUTH2_CORS_ORIGINS:*}\n\n # Rate limiting\n rate_limit:\n enabled: ${OAUTH2_RATE_LIMIT_ENABLED:true}\n requests_per_minute: ${OAUTH2_RATE_LIMIT_RPM:60}\n'})})]}),"\n",(0,s.jsx)(n.p,{children:"Update your WebUI Gateway to configure login as follows"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:'# Auth-related (placeholders, functionality depends on backend implementation)\nfrontend_auth_login_url: ${FRONTEND_AUTH_LOGIN_URL}\nfrontend_use_authorization: ${FRONTEND_USE_AUTHORIZATION}\nfrontend_redirect_url: ${FRONTEND_REDIRECT_URL, ""}\n\nexternal_auth_callback_uri: ${EXTERNAL_AUTH_CALLBACK}\nexternal_auth_service_url: ${EXTERNAL_AUTH_SERVICE_URL}\nexternal_auth_provider: ${EXTERNAL_AUTH_PROVIDER}\n'})}),"\n",(0,s.jsx)(n.p,{children:"Your final WebUI Gateway yaml configuration should look like this"}),"\n",(0,s.jsxs)(t,{children:[(0,s.jsx)("summary",{children:"WebUI Gateway SSO Enabled"}),(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"webUI.yaml"})}),(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:'log:\n stdout_log_level: INFO\n log_file_level: INFO\n log_file: webui_app.log\n\n\n!include ../shared_config.yaml\n\napps:\n - name: a2a_webui_app\n app_base_path: .\n app_module: solace_agent_mesh.gateway.http_sse.app\n\n broker:\n <<: *broker_connection\n\n app_config:\n namespace: ${NAMESPACE}\n session_secret_key: "${SESSION_SECRET_KEY}"\n\n artifact_service: *default_artifact_service\n session_service: \n type: "sql"\n database_url: ${WEB_UI_GATEWAY_DATABASE_URL, sqlite:///webui_gateway.db}\n default_behavior: "PERSISTENT"\n gateway_id: ${WEBUI_GATEWAY_ID}\n fastapi_host: ${FASTAPI_HOST}\n fastapi_port: ${FASTAPI_PORT}\n cors_allowed_origins: \n - "http://localhost:3000" \n - "http://127.0.0.1:3000"\n\n enable_embed_resolution: ${ENABLE_EMBED_RESOLUTION} # Enable late-stage resolution\n gateway_artifact_content_limit_bytes: ${GATEWAY_ARTIFACT_LIMIT_BYTES, 10000000} # Max size for late-stage embeds\n sse_max_queue_size: ${SSE_MAX_QUEUE_SIZE, 200} # Max size of SSE connection queues\n\n system_purpose: >\n The system is an AI Chatbot with agentic capabilities.\n It will use the agents available to provide information,\n reasoning and general assistance for the users in this system.\n **Always return useful artifacts and files that you create to the user.**\n Provide a status update before each tool call.\n Your external name is Agent Mesh.\n\n response_format: >\n Responses should be clear, concise, and professionally toned.\n Format responses to the user in Markdown using appropriate formatting.\n\n # --- Frontend Config Passthrough ---\n frontend_welcome_message: ${FRONTEND_WELCOME_MESSAGE}\n frontend_bot_name: ${FRONTEND_BOT_NAME}\n frontend_collect_feedback: ${FRONTEND_COLLECT_FEEDBACK}\n\n # Auth-related (placeholders, functionality depends on backend implementation)\n frontend_auth_login_url: ${FRONTEND_AUTH_LOGIN_URL}\n frontend_use_authorization: ${FRONTEND_USE_AUTHORIZATION}\n frontend_redirect_url: ${FRONTEND_REDIRECT_URL, ""}\n\n external_auth_callback_uri: ${EXTERNAL_AUTH_CALLBACK}\n external_auth_service_url: ${EXTERNAL_AUTH_SERVICE_URL}\n external_auth_provider: ${EXTERNAL_AUTH_PROVIDER}\n'})})]}),"\n",(0,s.jsx)(n.h2,{id:"running-solace-agent-mesh-enterprise-with-sso-enabled",children:"Running Solace Agent Mesh Enterprise with SSO enabled"}),"\n",(0,s.jsx)(n.p,{children:"Here is an example of Docker run command with Azure SSO provider for production use case:"}),"\n",(0,s.jsx)(n.admonition,{type:"tip",children:(0,s.jsxs)(n.p,{children:["You may need to include ",(0,s.jsx)(n.code,{children:"--platform linux/amd64"})," depending on the host machine you\u2019re using."]})}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:'docker run -itd -p 8000:8000 -p 9000:9000 \\\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 -e FASTAPI_HOST="0.0.0.0" \\\n -e FASTAPI_PORT="8000" \\\n -e AZURE_TENANT_ID="xxxxxxxxx-xxxxxx-xxxxxxxx-xxxxxxxxxx" \\\n -e AZURE_CLIENT_ID="xxxxxxxxx-xxxxxx-xxxxxxxx-xxxxxxxxxx" \\\n -e AZURE_CLIENT_SECRET="xxxxxxxxx-xxxxxx-xxxxxxxx-xxxxxxxxxx" \\\n -e OAUTH2_ENABLED="true" \\\n -e OAUTH2_LOG_LEVEL="DEBUG" \\\n -e OAUTH2_DEV_MODE="true" \\\n -e OAUTH2_HOST="0.0.0.0" \\\n -e OAUTH2_PORT="9000" \\\n -e FRONTEND_USE_AUTHORIZATION="true" \\\n -e FRONTEND_REDIRECT_URL="http://localhost:8000" \\\n -e FRONTEND_AUTH_LOGIN_URL="http://localhost:8000/api/v1/auth/login" \\\n -e EXTERNAL_AUTH_SERVICE_URL="http://localhost:9000" \\\n -e EXTERNAL_AUTH_PROVIDER="azure" \\\n -e EXTERNAL_AUTH_CALLBACK="http://localhost:8000/api/v1/auth/callback" \\\n -v <YOUR_NAMED_DOCKER_VOLUME>:/app/config/sso_vol/ \\\n --name sam-ent-prod-sso \\\nsolace-agent-mesh-enterprise:<tag> run config/sso_vol/oauth2_server.yaml config/webui_backend.yaml config/a2a_orchestrator.yaml config/a2a_agents.yaml\n'})}),"\n",(0,s.jsxs)(n.p,{children:["You can then access Solace Agent Mesh Enterprise UI through ",(0,s.jsx)(n.a,{href:"http://localhost:8000",children:"http://localhost:8000"})]}),"\n",(0,s.jsxs)(t,{children:[(0,s.jsx)("summary",{children:"Configuration Options"}),(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"Specify the hostname and port for the UI running in the docker container. The main UI runs on port 8000 by default. Using 0.0.0.0 as the host allows external access to the container."})}),(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:'-e FASTAPI_HOST="0.0.0.0" \\\n-e FASTAPI_PORT="8000" \\ \n'})}),(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"Enable single sign-on processing on the frontend."})}),(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:'-e FRONTEND_USE_AUTHORIZATION="true" \\\n'})}),(0,s.jsx)(n.p,{children:(0,s.jsxs)(n.strong,{children:["Specify the main URL of the UI. For instance, this could be ",(0,s.jsx)(n.a,{href:"https://www.example.com",children:"https://www.example.com"})]})}),(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:'-e FRONTEND_REDIRECT_URL="http://localhost:8000" \\\n'})}),(0,s.jsx)(n.p,{children:(0,s.jsxs)(n.strong,{children:["Set the login URL used by the main UI. For instance, this could be ",(0,s.jsx)(n.a,{href:"https://www.example.com/api/v1/auth/login",children:"https://www.example.com/api/v1/auth/login"})]})}),(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:'-e FRONTEND_AUTH_LOGIN_URL="http://localhost:8000/api/v1/auth/login" \\\n'})}),(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"Enable the OAUTH2 server and set the log level"})}),(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:'-e OAUTH2_ENABLED="true" \\\n-e OAUTH2_LOG_LEVEL="DEBUG" \\\n'})}),(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"Specify the hostname and port for the authorization server running in the docker container. Using 0.0.0.0 as the host allows external access to the container."})}),(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:'-e OAUTH2_HOST="0.0.0.0" \\\n-e OAUTH2_PORT="9000" \\\n'})}),(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"Specify whether the Oauth2 checks use dev mode. When dev mode is true the following environment variables are added to allow http access and relax the token scope. This MUST be set false in a production environment."})}),(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:'-e OAUTH2_DEV_MODE="true" \\\n'})}),(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:'OAUTHLIB_RELAX_TOKEN_SCOPE="1"\nOAUTHLIB_INSECURE_TRANSPORT="1"\n'})}),(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"Configure the environment variables for your chosen authentication provider. Refer to the oauth2_config.yaml file to identify the required variables. For example, with Azure set the following"})}),(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:'-e AZURE_TENANT_ID="xxxxxxxxx-xxxxxx-xxxxxxxx-xxxxxxxxxx" \\\n-e AZURE_CLIENT_ID="xxxxxxxxx-xxxxxx-xxxxxxxx-xxxxxxxxxx" \\\n-e AZURE_CLIENT_SECRET="xxxxxxxxx-xxxxxx-xxxxxxxx-xxxxxxxxxx" \\\n'})}),(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"Configure the authorization server's public URL (accessible from outside the Docker container) and specify the OAuth2 provider\u2019s name from oauth2_config.yaml (this example uses the azure profile):"})}),(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:'-e EXTERNAL_AUTH_SERVICE_URL="http://localhost:9000" \\\n-e EXTERNAL_AUTH_PROVIDER="azure" \\\n'})}),(0,s.jsx)(n.p,{children:(0,s.jsxs)(n.strong,{children:["Lastly, set the callback URL that your auth provider will use to redirect with the auth code. For instance, this could be ",(0,s.jsx)(n.a,{href:"https://www.example.com/api/v1/auth/callback",children:"https://www.example.com/api/v1/auth/callback"})]})}),(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:'-e EXTERNAL_AUTH_CALLBACK="http://localhost:8000/api/v1/auth/callback" \\\n'})}),(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"Note that both the main UI and authorization server ports must be mapped to the host machine, as shown in the Docker run command above:"})}),(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"-p 8000:8000 -p 9000:9000 \\\n"})}),(0,s.jsx)(n.p,{children:(0,s.jsx)(n.strong,{children:"The oauth 2 configuration files must be mounted inside the container:"})}),(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"-v <YOUR_NAMED_DOCKER_VOLUME>:/app/config/sso_vol/ \\\n"})})]})]})}function h(e={}){const{wrapper:n}={...(0,a.R)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(_,{...e})}):_(e)}},8453:(e,n,t)=>{t.d(n,{R:()=>i,x:()=>r});var o=t(6540);const s={},a=o.createContext(s);function i(e){const n=o.useContext(a);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(s):e.components||s:i(e.components),o.createElement(a.Provider,{value:n},e.children)}}}]);
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use strict";(self.webpackChunksolace_agenitc_mesh_docs=self.webpackChunksolace_agenitc_mesh_docs||[]).push([[7289],{3089:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>c,contentTitle:()=>i,default:()=>m,frontMatter:()=>a,metadata:()=>o,toc:()=>l});const o=JSON.parse('{"id":"documentation/deployment/deploy","title":"Deployment","description":"Development","source":"@site/docs/documentation/deployment/deploy.md","sourceDirName":"documentation/deployment","slug":"/documentation/deployment/deploy","permalink":"/solace-agent-mesh/docs/documentation/deployment/deploy","draft":false,"unlisted":false,"editUrl":"https://github.com/SolaceLabs/solace-agent-mesh/edit/main/docs/docs/documentation/deployment/deploy.md","tags":[],"version":"current","sidebarPosition":10,"frontMatter":{"title":"Deployment","sidebar_position":10},"sidebar":"docSidebar","previous":{"title":"Dynamic Embeds","permalink":"/solace-agent-mesh/docs/documentation/user-guide/builtin-tools/embeds"},"next":{"title":"Observability","permalink":"/solace-agent-mesh/docs/documentation/deployment/observability"}}');var s=t(4848),r=t(8453);const a={title:"Deployment",sidebar_position:10},i="Deployment",c={},l=[{value:"Development",id:"development",level:2},{value:"Production",id:"production",level:2},{value:"Docker Deployment",id:"docker-deployment",level:3},{value:"Kubernetes Deployment",id:"kubernetes-deployment",level:3},{value:"Splitting and Scaling",id:"splitting-and-scaling",level:3},{value:"Storage Considerations",id:"storage-considerations",level:3},{value:"Security Best Practices",id:"security-best-practices",level:3},{value:"Solace Event Broker Configuration",id:"solace-event-broker-configuration",level:3}];function d(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,r.R)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.header,{children:(0,s.jsx)(n.h1,{id:"deployment",children:"Deployment"})}),"\n",(0,s.jsx)(n.h2,{id:"development",children:"Development"}),"\n",(0,s.jsxs)(n.p,{children:["In a development environment, you can use Solace Agent Mesh CLI to run the project as a single application. By default, environment variables are loaded from your configuration file (typically a ",(0,s.jsx)(n.code,{children:".env"})," file at the project root):"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-bash",children:"sam run\n"})}),"\n",(0,s.jsx)(n.h2,{id:"production",children:"Production"}),"\n",(0,s.jsx)(n.p,{children:"For a production environment, use a containerized and reproducible setup. We recommend Docker or Kubernetes."}),"\n",(0,s.jsxs)(n.p,{children:["If your host system architecture is not ",(0,s.jsx)(n.code,{children:"linux/amd64"}),", add the ",(0,s.jsx)(n.code,{children:"--platform linux/amd64"})," flag when you run the container."]}),"\n",(0,s.jsx)(n.h3,{id:"docker-deployment",children:"Docker Deployment"}),"\n",(0,s.jsx)(n.p,{children:"Below is a sample Dockerfile for a Solace Agent Mesh project:"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-Dockerfile",children:'FROM solace/solace-agent-mesh:latest\nWORKDIR /app\n\n# Install Python dependencies\nCOPY ./requirements.txt /app/requirements.txt\nRUN python3.11 -m pip install --no-cache-dir -r /app/requirements.txt\n\n# Copy project files\nCOPY . /app\n\nCMD ["run", "--system-env"]\n\n# To run one specific component, use:\n# CMD ["run", "--system-env", "configs/agents/main_orchestrator.yaml"]\n\n'})}),"\n",(0,s.jsxs)(n.p,{children:["And the following ",(0,s.jsx)(n.code,{children:".dockerignore"})]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{children:".env\n*.log\ndist\n.git\n.vscode\n.DS_Store\n"})}),"\n",(0,s.jsx)(n.h3,{id:"kubernetes-deployment",children:"Kubernetes Deployment"}),"\n",(0,s.jsxs)(n.p,{children:["For scalable and highly available deployments, Kubernetes is recommended. Below is a minimal ",(0,s.jsx)(n.code,{children:"Deployment"})," configuration:"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-yaml",children:'apiVersion: apps/v1\nkind: Deployment\nmetadata:\n name: solace-agent-mesh\n labels:\n app: solace-agent-mesh\nspec:\n replicas: 1 # Adjust based on load\n selector:\n matchLabels:\n app: solace-agent-mesh\n template:\n metadata:\n labels:\n app: solace-agent-mesh\n spec:\n containers:\n - name: solace-agent-mesh\n image: your-registry/solace-agent-mesh:latest\n \n envFrom:\n - secretRef:\n name: solace-agent-mesh-secrets # Configure secrets in a Kubernetes Secret\n\n command: ["solace-agent-mesh", "run", "--system-env"]\n args:\n - "configs/main_orchestrator.yaml"\n - "configs/gateway/webui.yaml"\n # Add any other components you want to run here\n\n ports:\n - containerPort: 8000 # Adjust based on your service ports\n\n volumeMounts:\n - name: shared-storage\n mountPath: /tmp/solace-agent-mesh\n volumes:\n - name: shared-storage\n emptyDir: {}\n'})}),"\n",(0,s.jsx)(n.h3,{id:"splitting-and-scaling",children:"Splitting and Scaling"}),"\n",(0,s.jsx)(n.p,{children:"For a robust production setup, consider splitting components into separate containers. This practice enhances scalability and ensures that if one process crashes, the rest of the system remains unaffected. Upon restarting, the failed process rejoins the system."}),"\n",(0,s.jsx)(n.p,{children:"To adapt the setup:"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"Reuse the same Docker image."}),"\n",(0,s.jsx)(n.li,{children:"Adjust the startup command to run only the necessary components."}),"\n",(0,s.jsx)(n.li,{children:"Scale containers independently based on their resource needs."}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"storage-considerations",children:"Storage Considerations"}),"\n",(0,s.jsx)(n.admonition,{type:"warning",children:(0,s.jsx)(n.p,{children:"If using multiple containers, ensure all instances access the same storage with identical configurations."})}),"\n",(0,s.jsx)(n.h3,{id:"security-best-practices",children:"Security Best Practices"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Environment Variables"}),": Store secrets in a secure vault (for example, AWS Secrets Manager, HashiCorp Vault) rather than in ",(0,s.jsx)(n.code,{children:".env"})," files."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"TLS Encryption"}),": Ensure that communication between components and with the Solace event broker is encrypted using TLS."]}),"\n",(0,s.jsxs)(n.li,{children:[(0,s.jsx)(n.strong,{children:"Container Security"}),": Regularly update container images and use security scanning tools (for example, Trivy, Clair)."]}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"solace-event-broker-configuration",children:"Solace Event Broker Configuration"}),"\n",(0,s.jsxs)(n.p,{children:["For production environments, it's recommended to use a cloud-managed Solace event broker (or event broker service). For more information, see ",(0,s.jsx)(n.a,{href:"https://solace.com/products/event-broker/",children:"Solace Cloud"}),"."]})]})}function m(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:()=>a,x:()=>i});var o=t(6540);const s={},r=o.createContext(s);function a(e){const n=o.useContext(r);return o.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function i(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:a(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([[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 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 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 Solace Agent Mesh 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 Solace Agent Mesh 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 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 Solace Agent Mesh 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 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 Solace Agent Mesh 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 Solace Agent Mesh 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 Solace Agent Mesh 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 a local Solace Broker container",type:"info",children:[(0,s.jsxs)(n.p,{children:["The Solace 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 Solace Agent Mesh 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":"Solace Agent Mesh 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 gateway. A recent architectural update has aligned Solace Agent Mesh 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="Solace Agent Mesh 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 & 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:"solace-agent-mesh-gateway-migration-guide-upgrading-to-the-a2a-sdk",children:"Solace Agent Mesh 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 gateway. A recent architectural update has aligned Solace Agent Mesh 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)}}}]);
|