legate 0.1.0
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.
- checksums.yaml +7 -0
- data/LICENSE +21 -0
- data/README.md +345 -0
- data/bin/legate +13 -0
- data/examples/00_quickstart.rb +51 -0
- data/examples/01_simple_agent.rb +105 -0
- data/examples/02_multi_tool_agent.rb +140 -0
- data/examples/03_custom_tool.rb +93 -0
- data/examples/04_agent_instructions.rb +84 -0
- data/examples/05_state_and_sessions.rb +91 -0
- data/examples/06_callbacks.rb +186 -0
- data/examples/07_async_jobs.rb +112 -0
- data/examples/08_loop_agent.rb +197 -0
- data/examples/09_sequential_workflow.rb +40 -0
- data/examples/10_parallel_workflow.rb +34 -0
- data/examples/11_agent_delegation.rb +24 -0
- data/examples/12_http_client_tool.rb +156 -0
- data/examples/13_authentication.rb +220 -0
- data/examples/14_mcp_client.rb +154 -0
- data/examples/15_mcp_server.rb +79 -0
- data/examples/16_webhooks.rb +91 -0
- data/examples/README_sequential_agents.md +164 -0
- data/examples/advanced/auth/cookie_auth_tool.rb +146 -0
- data/examples/advanced/auth/custom_auth_flows_example.rb +626 -0
- data/examples/advanced/auth/excon_middleware.rb +317 -0
- data/examples/advanced/auth/excon_middleware_auth.rb +399 -0
- data/examples/advanced/auth/fiber_auth_example.rb +281 -0
- data/examples/advanced/auth/fiber_oidc_example.rb +403 -0
- data/examples/advanced/auth/httpbin_bearer_tool.rb +159 -0
- data/examples/advanced/auth/oauth2_auth.rb +419 -0
- data/examples/advanced/auth/oidc_auth.rb +514 -0
- data/examples/advanced/auth/openweather_api.rb +251 -0
- data/examples/advanced/auth/openweather_tool.rb +153 -0
- data/examples/advanced/auth/query_param_middleware_test.rb +138 -0
- data/examples/advanced/auth/service_account.rb +135 -0
- data/examples/advanced/auth/test_with_httpbin.rb +202 -0
- data/examples/advanced/auth/token_lifecycle_example.rb +428 -0
- data/examples/advanced/callback_monitoring.rb +679 -0
- data/examples/advanced/mas/fixed_delegation_example.rb +191 -0
- data/examples/advanced/mas/loop_workflow.rb +28 -0
- data/examples/advanced/mas/mock_planner.rb +77 -0
- data/examples/advanced/mas/proper_delegation_example.rb +276 -0
- data/examples/advanced/mcp/legate_mcp_server_resource_example.rb +182 -0
- data/examples/advanced/mcp/mcp_resource_server_example.rb +309 -0
- data/examples/advanced/mcp/mcp_server_async.rb +76 -0
- data/examples/advanced/mcp/mcp_server_async_tools.rb +122 -0
- data/examples/advanced/mcp/mcp_server_legate_agent.rb +95 -0
- data/examples/advanced/mcp/mcp_server_rack.rb +89 -0
- data/examples/advanced/random_calculator.rb +104 -0
- data/examples/advanced/sleep_agent.rb +153 -0
- data/examples/advanced/webhooks/webhook_e2e_runner.rb +110 -0
- data/examples/advanced/webhooks/webhook_receiver_agent.rb +58 -0
- data/examples/advanced/workflows/task_refinement_loop_agent.rb +278 -0
- data/examples/advanced/workflows/travel_planner_auto_sequential.rb +444 -0
- data/examples/advanced/workflows/travel_planner_parallel.rb +656 -0
- data/examples/advanced/workflows/travel_planner_sequential.rb +512 -0
- data/examples/tools/oauth2_example.rb +136 -0
- data/examples/tools/sleepy_tool.rb +42 -0
- data/lib/legate/activity_log.rb +71 -0
- data/lib/legate/agent.rb +959 -0
- data/lib/legate/agent_code_generator.rb +185 -0
- data/lib/legate/agent_definition.rb +812 -0
- data/lib/legate/agentic/decision.rb +49 -0
- data/lib/legate/agentic/loop.rb +134 -0
- data/lib/legate/agentic.rb +5 -0
- data/lib/legate/agents/loop_agent.rb +248 -0
- data/lib/legate/agents/parallel_agent.rb +163 -0
- data/lib/legate/agents/sequential_agent.rb +190 -0
- data/lib/legate/agents.rb +14 -0
- data/lib/legate/auth/config.rb +148 -0
- data/lib/legate/auth/coordinator.rb +218 -0
- data/lib/legate/auth/coordinators/oauth2_coordinator.rb +99 -0
- data/lib/legate/auth/coordinators/oidc_coordinator.rb +68 -0
- data/lib/legate/auth/coordinators/service_account_coordinator.rb +122 -0
- data/lib/legate/auth/credential.rb +157 -0
- data/lib/legate/auth/encryption.rb +108 -0
- data/lib/legate/auth/error.rb +94 -0
- data/lib/legate/auth/exchanged_credential.rb +180 -0
- data/lib/legate/auth/excon_middleware.rb +285 -0
- data/lib/legate/auth/http_client_utils.rb +364 -0
- data/lib/legate/auth/manager.rb +531 -0
- data/lib/legate/auth/manager_store.rb +394 -0
- data/lib/legate/auth/middleware_factory.rb +290 -0
- data/lib/legate/auth/runner.rb +279 -0
- data/lib/legate/auth/scheme.rb +125 -0
- data/lib/legate/auth/schemes/api_key.rb +212 -0
- data/lib/legate/auth/schemes/google_service_account.rb +108 -0
- data/lib/legate/auth/schemes/http_bearer.rb +98 -0
- data/lib/legate/auth/schemes/oauth2.rb +396 -0
- data/lib/legate/auth/schemes/openid_connect.rb +346 -0
- data/lib/legate/auth/schemes/service_account.rb +388 -0
- data/lib/legate/auth/schemes.rb +40 -0
- data/lib/legate/auth/token_manager.rb +362 -0
- data/lib/legate/auth/token_store.rb +86 -0
- data/lib/legate/auth/tool_context_extension.rb +97 -0
- data/lib/legate/auth/tool_integration.rb +188 -0
- data/lib/legate/auth/url_guard.rb +81 -0
- data/lib/legate/auth.rb +453 -0
- data/lib/legate/callbacks/callback_context.rb +71 -0
- data/lib/legate/cli/agent_commands.rb +950 -0
- data/lib/legate/cli/auth_commands.rb +520 -0
- data/lib/legate/cli/base_command.rb +24 -0
- data/lib/legate/cli/deployment_commands.rb +934 -0
- data/lib/legate/cli/output_helper.rb +108 -0
- data/lib/legate/cli/session_commands.rb +138 -0
- data/lib/legate/cli/skaffold_commands.rb +223 -0
- data/lib/legate/cli/tool_commands.rb +261 -0
- data/lib/legate/cli/web_commands.rb +182 -0
- data/lib/legate/cli.rb +40 -0
- data/lib/legate/configuration/webhooks.rb +113 -0
- data/lib/legate/configuration.rb +39 -0
- data/lib/legate/definition_store.rb +23 -0
- data/lib/legate/errors.rb +118 -0
- data/lib/legate/event.rb +161 -0
- data/lib/legate/gemini_ai_beta_patch.rb +39 -0
- data/lib/legate/generators/agent_generator.rb +412 -0
- data/lib/legate/generators/code_validator.rb +48 -0
- data/lib/legate/generators/legate/install_generator.rb +35 -0
- data/lib/legate/generators/legate/templates/create_legate_tables.rb.tt +36 -0
- data/lib/legate/generators/legate/templates/initializer.rb +18 -0
- data/lib/legate/generators/runtime_tool_loader.rb +76 -0
- data/lib/legate/generators/tool_generator.rb +408 -0
- data/lib/legate/generators.rb +11 -0
- data/lib/legate/global_definition_registry.rb +506 -0
- data/lib/legate/global_tool_manager.rb +135 -0
- data/lib/legate/llm/adapter.rb +69 -0
- data/lib/legate/llm/gemini.rb +172 -0
- data/lib/legate/llm/ollama.rb +80 -0
- data/lib/legate/llm.rb +34 -0
- data/lib/legate/mcp/client.rb +320 -0
- data/lib/legate/mcp/connection/sse.rb +292 -0
- data/lib/legate/mcp/connection/stdio.rb +273 -0
- data/lib/legate/mcp/connection_manager.rb +103 -0
- data/lib/legate/mcp/server/legate_agent_adapter.rb +170 -0
- data/lib/legate/mcp/server/legate_direct_agent_adapter.rb +140 -0
- data/lib/legate/mcp/server/legate_tool_adapter.rb +119 -0
- data/lib/legate/mcp/tool_wrapper.rb +138 -0
- data/lib/legate/mcp/util/schema_converter.rb +134 -0
- data/lib/legate/mcp.rb +23 -0
- data/lib/legate/plan_executor.rb +375 -0
- data/lib/legate/planner.rb +839 -0
- data/lib/legate/rails/railtie.rb +43 -0
- data/lib/legate/rails.rb +9 -0
- data/lib/legate/redaction.rb +32 -0
- data/lib/legate/session.rb +299 -0
- data/lib/legate/session_service/active_record.rb +300 -0
- data/lib/legate/session_service/base.rb +68 -0
- data/lib/legate/session_service/event_broadcast.rb +74 -0
- data/lib/legate/session_service/in_memory.rb +188 -0
- data/lib/legate/tool/metadata_dsl.rb +122 -0
- data/lib/legate/tool.rb +276 -0
- data/lib/legate/tool_code_generator.rb +103 -0
- data/lib/legate/tool_context.rb +350 -0
- data/lib/legate/tool_loader.rb +39 -0
- data/lib/legate/tool_registry.rb +73 -0
- data/lib/legate/tool_result.rb +61 -0
- data/lib/legate/tools/agent_tool.rb +187 -0
- data/lib/legate/tools/base/http_client.rb +319 -0
- data/lib/legate/tools/base/safe_url.rb +56 -0
- data/lib/legate/tools/base_async_job_tool.rb +91 -0
- data/lib/legate/tools/calculator.rb +89 -0
- data/lib/legate/tools/cat_facts.rb +81 -0
- data/lib/legate/tools/check_job_status_tool.rb +48 -0
- data/lib/legate/tools/current_time_tool.rb +64 -0
- data/lib/legate/tools/echo.rb +43 -0
- data/lib/legate/tools/http_request_tool.rb +105 -0
- data/lib/legate/tools/random_number_tool.rb +64 -0
- data/lib/legate/tools/read_webpage_tool.rb +92 -0
- data/lib/legate/tools/sleepy_tool.rb +74 -0
- data/lib/legate/tools/webhook_tool.rb +146 -0
- data/lib/legate/version.rb +5 -0
- data/lib/legate/web/app.rb +984 -0
- data/lib/legate/web/public/css/main.css +4980 -0
- data/lib/legate/web/public/images/favicon-256.png +0 -0
- data/lib/legate/web/public/images/favicon-32.png +0 -0
- data/lib/legate/web/public/images/legate-logo-dark.png +0 -0
- data/lib/legate/web/public/images/legate-logo-light.png +0 -0
- data/lib/legate/web/public/js/legate.js +616 -0
- data/lib/legate/web/public/styles/main.scss +4402 -0
- data/lib/legate/web/routes/agent_authentication_routes.rb +530 -0
- data/lib/legate/web/routes/agent_definition_routes.rb +803 -0
- data/lib/legate/web/routes/agent_generator_routes.rb +80 -0
- data/lib/legate/web/routes/agent_interaction_routes.rb +734 -0
- data/lib/legate/web/routes/agent_runtime_routes.rb +323 -0
- data/lib/legate/web/routes/api_routes.rb +56 -0
- data/lib/legate/web/routes/authentication_routes.rb +1541 -0
- data/lib/legate/web/routes/core_routes.rb +111 -0
- data/lib/legate/web/routes/documentation_routes.rb +220 -0
- data/lib/legate/web/routes/tool_generator_routes.rb +81 -0
- data/lib/legate/web/routes/tools_ui_routes.rb +207 -0
- data/lib/legate/web/sass_compiler.rb +73 -0
- data/lib/legate/web/views/_active_session_info.slim +25 -0
- data/lib/legate/web/views/_activity_list.slim +55 -0
- data/lib/legate/web/views/_agent_card.slim +56 -0
- data/lib/legate/web/views/_agent_generator_modal.slim +382 -0
- data/lib/legate/web/views/_agent_status_controls.slim +71 -0
- data/lib/legate/web/views/_agent_tool_table.slim +74 -0
- data/lib/legate/web/views/_chat_message.slim +95 -0
- data/lib/legate/web/views/_display_agent_configuration.slim +26 -0
- data/lib/legate/web/views/_display_agent_description.slim +11 -0
- data/lib/legate/web/views/_display_agent_fallback.slim +15 -0
- data/lib/legate/web/views/_display_agent_hierarchy.slim +93 -0
- data/lib/legate/web/views/_display_agent_instruction.slim +17 -0
- data/lib/legate/web/views/_display_agent_mcp.slim +13 -0
- data/lib/legate/web/views/_display_agent_model.slim +17 -0
- data/lib/legate/web/views/_display_agent_name.slim +42 -0
- data/lib/legate/web/views/_display_agent_output_key.slim +26 -0
- data/lib/legate/web/views/_display_agent_type.slim +65 -0
- data/lib/legate/web/views/_edit_agent_configuration.slim +74 -0
- data/lib/legate/web/views/_edit_agent_description.slim +16 -0
- data/lib/legate/web/views/_edit_agent_fallback.slim +25 -0
- data/lib/legate/web/views/_edit_agent_hierarchy.slim +98 -0
- data/lib/legate/web/views/_edit_agent_instruction.slim +49 -0
- data/lib/legate/web/views/_edit_agent_mcp.slim +33 -0
- data/lib/legate/web/views/_edit_agent_model.slim +23 -0
- data/lib/legate/web/views/_edit_agent_output_key.slim +36 -0
- data/lib/legate/web/views/_edit_agent_tools.slim +40 -0
- data/lib/legate/web/views/_edit_agent_type.slim +67 -0
- data/lib/legate/web/views/_session_error.slim +4 -0
- data/lib/legate/web/views/_skeleton.slim +69 -0
- data/lib/legate/web/views/_tool_card.slim +9 -0
- data/lib/legate/web/views/_tool_generator_modal.slim +311 -0
- data/lib/legate/web/views/agent.slim +436 -0
- data/lib/legate/web/views/agent_auth.slim +562 -0
- data/lib/legate/web/views/agents.slim +369 -0
- data/lib/legate/web/views/auth.slim +112 -0
- data/lib/legate/web/views/auth_credential_detail.slim +327 -0
- data/lib/legate/web/views/auth_credentials.slim +261 -0
- data/lib/legate/web/views/auth_debug.slim +94 -0
- data/lib/legate/web/views/auth_mapping_detail.slim +151 -0
- data/lib/legate/web/views/auth_mapping_new.slim +123 -0
- data/lib/legate/web/views/auth_mappings.slim +120 -0
- data/lib/legate/web/views/auth_scheme_detail.slim +274 -0
- data/lib/legate/web/views/auth_schemes.slim +259 -0
- data/lib/legate/web/views/auth_test.slim +418 -0
- data/lib/legate/web/views/chat.slim +192 -0
- data/lib/legate/web/views/docs_index.slim +105 -0
- data/lib/legate/web/views/docs_show.slim +105 -0
- data/lib/legate/web/views/error_404.slim +5 -0
- data/lib/legate/web/views/index.slim +148 -0
- data/lib/legate/web/views/layout.slim +144 -0
- data/lib/legate/web/views/tool_detail.slim +87 -0
- data/lib/legate/web/views/tools.slim +50 -0
- data/lib/legate/web/webhook_listener.rb +367 -0
- data/lib/legate/web.rb +9 -0
- data/lib/legate.rb +220 -0
- data/public/docs/advanced/callbacks.md +828 -0
- data/public/docs/advanced/mcp_schema_conversion.md +59 -0
- data/public/docs/authentication/api_reference/config.md +210 -0
- data/public/docs/authentication/api_reference/credential.md +246 -0
- data/public/docs/authentication/api_reference/encryption.md +218 -0
- data/public/docs/authentication/api_reference/exchanged_credential.md +271 -0
- data/public/docs/authentication/api_reference/excon_middleware.md +175 -0
- data/public/docs/authentication/api_reference/index.md +30 -0
- data/public/docs/authentication/api_reference/scheme.md +250 -0
- data/public/docs/authentication/api_reference/schemes/api_key.md +175 -0
- data/public/docs/authentication/api_reference/schemes/google_service_account.md +221 -0
- data/public/docs/authentication/api_reference/schemes/http_bearer.md +169 -0
- data/public/docs/authentication/api_reference/schemes/oauth2.md +343 -0
- data/public/docs/authentication/api_reference/schemes/oidc.md +73 -0
- data/public/docs/authentication/api_reference/schemes/openid_connect.md +311 -0
- data/public/docs/authentication/api_reference/schemes/service_account.md +287 -0
- data/public/docs/authentication/api_reference/token_manager.md +221 -0
- data/public/docs/authentication/api_reference/token_store.md +146 -0
- data/public/docs/authentication/api_reference/tool_context_extension.md +166 -0
- data/public/docs/authentication/guides/api_key.md +190 -0
- data/public/docs/authentication/guides/bearer.md +172 -0
- data/public/docs/authentication/guides/configuration.md +255 -0
- data/public/docs/authentication/guides/custom_flow.md +523 -0
- data/public/docs/authentication/guides/index.md +24 -0
- data/public/docs/authentication/guides/migration.md +435 -0
- data/public/docs/authentication/guides/oauth2.md +252 -0
- data/public/docs/authentication/guides/oidc.md +241 -0
- data/public/docs/authentication/guides/overview.md +155 -0
- data/public/docs/authentication/guides/secure_storage.md +301 -0
- data/public/docs/authentication/guides/service_account.md +228 -0
- data/public/docs/authentication/guides/token_lifecycle.md +295 -0
- data/public/docs/authentication/guides/web_ui_integration.md +504 -0
- data/public/docs/authentication/index.md +58 -0
- data/public/docs/authentication/troubleshooting/credential_storage.md +550 -0
- data/public/docs/authentication/troubleshooting/environment_variables.md +540 -0
- data/public/docs/authentication/troubleshooting/index.md +11 -0
- data/public/docs/authentication/troubleshooting/oauth2_issues.md +220 -0
- data/public/docs/authentication/troubleshooting/oidc_issues.md +412 -0
- data/public/docs/authentication/troubleshooting/token_refresh.md +338 -0
- data/public/docs/cli/legate_cli_usage.md +363 -0
- data/public/docs/core_concepts/legate_agent_lifecycle.md +124 -0
- data/public/docs/core_concepts/legate_architecture_overview.md +110 -0
- data/public/docs/core_concepts/legate_configuration.md +116 -0
- data/public/docs/core_concepts/legate_definition_store.md +102 -0
- data/public/docs/core_concepts/legate_planner.md +94 -0
- data/public/docs/core_concepts/legate_session_service.md +104 -0
- data/public/docs/error_handling/legate_error_handling.md +122 -0
- data/public/docs/examples.md +199 -0
- data/public/docs/getting_started.md +111 -0
- data/public/docs/guides/agentic_agents.md +137 -0
- data/public/docs/guides/ai_code_generators.md +437 -0
- data/public/docs/guides/auto_loading.md +326 -0
- data/public/docs/guides/configuring_agent_webhooks.md +219 -0
- data/public/docs/guides/http_client_usage.md +264 -0
- data/public/docs/guides/llm_providers.md +137 -0
- data/public/docs/guides/mcp_client_integration.md +232 -0
- data/public/docs/guides/mcp_server_exposure.md +206 -0
- data/public/docs/guides/rails_integration.md +128 -0
- data/public/docs/guides/sending_outbound_webhooks.md +227 -0
- data/public/docs/guides/streaming.md +112 -0
- data/public/docs/guides/webhooks.md +288 -0
- data/public/docs/introduction.md +51 -0
- data/public/docs/multi_agent_systems/advanced_features.md +57 -0
- data/public/docs/multi_agent_systems/agent_delegation.md +190 -0
- data/public/docs/multi_agent_systems/agent_hierarchy.md +49 -0
- data/public/docs/multi_agent_systems/state_management.md +47 -0
- data/public/docs/multi_agent_systems/workflow_agents.md +72 -0
- data/public/docs/tools/legate_built_in_tools.md +332 -0
- data/public/docs/tools/legate_tools_and_registry.md +263 -0
- data/public/docs/web_ui/legate_web_ui.md +137 -0
- metadata +823 -0
|
@@ -0,0 +1,656 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# Example of a Parallel Travel Planning Process
|
|
5
|
+
# Run with: bundle exec ruby examples/advanced/workflows/travel_planner_parallel.rb
|
|
6
|
+
#
|
|
7
|
+
# This example demonstrates how to create a parallel agent pattern where multiple specialized
|
|
8
|
+
# agents are executed concurrently, with each agent handling a specific part of a travel planning task.
|
|
9
|
+
#
|
|
10
|
+
# Key components of this example:
|
|
11
|
+
# 1. Multiple specialized agents: destination_research, flight_search, accommodation_search,
|
|
12
|
+
# attractions_research, and weather_forecast
|
|
13
|
+
# 2. A parent parallel agent that orchestrates the concurrent execution of the specialized agents
|
|
14
|
+
# 3. Each agent has its own output_key to store its results in the shared session state
|
|
15
|
+
# 4. The ParallelAgent class automatically handles the execution and waits for all agents to complete
|
|
16
|
+
# 5. A final summary agent that compiles all the parallel results
|
|
17
|
+
#
|
|
18
|
+
# The architecture follows these principles:
|
|
19
|
+
# - Each agent is fully specialized for its task
|
|
20
|
+
# - Agents share the same session, allowing them to access each other's outputs
|
|
21
|
+
# - The parent-child relationship is explicitly established through the sub_agents parameter
|
|
22
|
+
# - The execution happens concurrently, significantly reducing the total time needed
|
|
23
|
+
|
|
24
|
+
require_relative '../../../lib/legate'
|
|
25
|
+
require_relative '../../../lib/legate/agents/parallel_agent' # Required for ParallelAgent
|
|
26
|
+
require_relative '../../../lib/legate/agents/sequential_agent' # Required for the final SequentialAgent
|
|
27
|
+
|
|
28
|
+
# Check if tty-spinner is installed
|
|
29
|
+
begin
|
|
30
|
+
require 'tty-spinner'
|
|
31
|
+
rescue LoadError
|
|
32
|
+
puts 'The tty-spinner gem is required for this example.'
|
|
33
|
+
puts 'Please install it with: gem install tty-spinner'
|
|
34
|
+
puts 'Or add it to your Gemfile and run: bundle install'
|
|
35
|
+
exit 1
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
# Clear any existing registrations to avoid conflicts
|
|
39
|
+
Legate::GlobalDefinitionRegistry.instance_variable_set(:@definitions, {})
|
|
40
|
+
|
|
41
|
+
puts '=== Travel Planner Parallel Process Example ==='
|
|
42
|
+
puts 'This example demonstrates multiple specialized agents running in parallel to plan a trip'
|
|
43
|
+
puts 'The ParallelAgent class automatically handles the concurrent execution of all agents.'
|
|
44
|
+
|
|
45
|
+
# Ensure the echo tool is registered - all agents will use this
|
|
46
|
+
Legate::GlobalToolManager.register_tool(Legate::Tools::Echo) unless Legate::GlobalToolManager.registered_tool_names.include?(:echo)
|
|
47
|
+
|
|
48
|
+
# Ensure delegate_task tool is registered for agent delegation
|
|
49
|
+
Legate::GlobalToolManager.register_tool(Legate::Tools::AgentTool) unless Legate::GlobalToolManager.registered_tool_names.include?(:delegate_task)
|
|
50
|
+
|
|
51
|
+
# ----- Define Specialized Parallel Agents -----
|
|
52
|
+
|
|
53
|
+
# 1. Destination Research Agent
|
|
54
|
+
destination_agent_def = Legate::AgentDefinition.new.define do |a|
|
|
55
|
+
a.name :destination_research
|
|
56
|
+
a.description 'Researches and suggests destination options based on user preferences'
|
|
57
|
+
a.instruction <<~INSTRUCTION
|
|
58
|
+
You are a destination research specialist. Your task is to analyze the user's preferences and suggest 2-3 suitable destinations.
|
|
59
|
+
|
|
60
|
+
First, think about what destinations would be appropriate based on the user's preferences. Then, use the 'echo' tool to output your response.
|
|
61
|
+
|
|
62
|
+
Your echo response should follow this EXACT format:
|
|
63
|
+
|
|
64
|
+
# DESTINATION RECOMMENDATIONS
|
|
65
|
+
|
|
66
|
+
Based on your preferences, here are the destinations I recommend:
|
|
67
|
+
|
|
68
|
+
## [Destination 1 Name]
|
|
69
|
+
- **Location**: [Region/Country]
|
|
70
|
+
- **Weather**: [Weather description for the time period]
|
|
71
|
+
- **Highlights**: [3-4 key attractions or experiences]
|
|
72
|
+
- **Best For**: [What makes this destination perfect for the user]
|
|
73
|
+
|
|
74
|
+
## [Destination 2 Name]
|
|
75
|
+
- **Location**: [Region/Country]
|
|
76
|
+
- **Weather**: [Weather description for the time period]
|
|
77
|
+
- **Highlights**: [3-4 key attractions or experiences]
|
|
78
|
+
- **Best For**: [What makes this destination perfect for the user]
|
|
79
|
+
|
|
80
|
+
## [Destination 3 Name] (optional)
|
|
81
|
+
- **Location**: [Region/Country]
|
|
82
|
+
- **Weather**: [Weather description for the time period]
|
|
83
|
+
- **Highlights**: [3-4 key attractions or experiences]
|
|
84
|
+
- **Best For**: [What makes this destination perfect for the user]
|
|
85
|
+
|
|
86
|
+
# RECOMMENDATION SUMMARY
|
|
87
|
+
[Brief explanation of why these destinations match the user's preferences]
|
|
88
|
+
INSTRUCTION
|
|
89
|
+
a.model_name 'gemini-3.5-flash'
|
|
90
|
+
a.output_key :destination_results
|
|
91
|
+
a.use_tool :echo
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
# 2. Flight Search Agent
|
|
95
|
+
flight_agent_def = Legate::AgentDefinition.new.define do |a|
|
|
96
|
+
a.name :flight_search
|
|
97
|
+
a.description 'Searches for flight options based on user preferences'
|
|
98
|
+
a.instruction <<~INSTRUCTION
|
|
99
|
+
You are a flight search specialist. Your task is to provide flight options based on the user's travel preferences.
|
|
100
|
+
|
|
101
|
+
First, analyze the user's request to understand their travel needs. Consider their preferences for timing, budget level, and potential destinations.
|
|
102
|
+
Then, use the 'echo' tool to output your response with simulated flight options.
|
|
103
|
+
|
|
104
|
+
Your echo response should follow this EXACT format:
|
|
105
|
+
|
|
106
|
+
# FLIGHT OPTIONS
|
|
107
|
+
|
|
108
|
+
Based on your travel preferences, here are some flight options:
|
|
109
|
+
|
|
110
|
+
## Option 1: [Origin] to [Destination]
|
|
111
|
+
- **Airline**: [Airline name]
|
|
112
|
+
- **Dates**: Depart [date] / Return [date]
|
|
113
|
+
- **Price**: $[amount] USD (round-trip)
|
|
114
|
+
- **Duration**: [hours] hrs each way
|
|
115
|
+
- **Stops**: [Direct/1 stop in X/etc.]
|
|
116
|
+
- **Notes**: [Any special notes about this option]
|
|
117
|
+
|
|
118
|
+
## Option 2: [Origin] to [Destination]
|
|
119
|
+
- **Airline**: [Airline name]
|
|
120
|
+
- **Dates**: Depart [date] / Return [date]
|
|
121
|
+
- **Price**: $[amount] USD (round-trip)
|
|
122
|
+
- **Duration**: [hours] hrs each way
|
|
123
|
+
- **Stops**: [Direct/1 stop in X/etc.]
|
|
124
|
+
- **Notes**: [Any special notes about this option]
|
|
125
|
+
|
|
126
|
+
## Option 3: [Origin] to [Destination] (optional)
|
|
127
|
+
- **Airline**: [Airline name]
|
|
128
|
+
- **Dates**: Depart [date] / Return [date]
|
|
129
|
+
- **Price**: $[amount] USD (round-trip)
|
|
130
|
+
- **Duration**: [hours] hrs each way
|
|
131
|
+
- **Stops**: [Direct/1 stop in X/etc.]
|
|
132
|
+
- **Notes**: [Any special notes about this option]
|
|
133
|
+
|
|
134
|
+
# FLIGHT SEARCH NOTES
|
|
135
|
+
- Prices are estimates and subject to change
|
|
136
|
+
- Consider booking within the next [timeframe] for best rates
|
|
137
|
+
- [Any other relevant booking tips]
|
|
138
|
+
INSTRUCTION
|
|
139
|
+
a.model_name 'gemini-3.5-flash'
|
|
140
|
+
a.output_key :flight_results
|
|
141
|
+
a.use_tool :echo
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
# 3. Accommodation Search Agent
|
|
145
|
+
accommodation_agent_def = Legate::AgentDefinition.new.define do |a|
|
|
146
|
+
a.name :accommodation_search
|
|
147
|
+
a.description 'Searches for accommodation options based on user preferences'
|
|
148
|
+
a.instruction <<~INSTRUCTION
|
|
149
|
+
You are an accommodation search specialist. Your task is to provide lodging options based on the user's travel preferences.
|
|
150
|
+
|
|
151
|
+
First, analyze the user's request to understand their accommodation needs. Consider their preferences for comfort level, budget, and potential destinations.
|
|
152
|
+
Then, use the 'echo' tool to output your response with simulated accommodation options.
|
|
153
|
+
|
|
154
|
+
Your echo response should follow this EXACT format:
|
|
155
|
+
|
|
156
|
+
# ACCOMMODATION OPTIONS
|
|
157
|
+
|
|
158
|
+
Based on your preferences, here are some accommodation recommendations:
|
|
159
|
+
|
|
160
|
+
## Option 1: [Accommodation Name]
|
|
161
|
+
- **Type**: [Hotel/Resort/Airbnb/etc.]
|
|
162
|
+
- **Location**: [Area/Neighborhood in destination]
|
|
163
|
+
- **Price Range**: $[amount]-$[amount] USD per night
|
|
164
|
+
- **Rating**: [4.5/5 stars, etc.]
|
|
165
|
+
- **Amenities**: [List of key amenities]
|
|
166
|
+
- **Highlights**: [What makes this place special]
|
|
167
|
+
|
|
168
|
+
## Option 2: [Accommodation Name]
|
|
169
|
+
- **Type**: [Hotel/Resort/Airbnb/etc.]
|
|
170
|
+
- **Location**: [Area/Neighborhood in destination]
|
|
171
|
+
- **Price Range**: $[amount]-$[amount] USD per night
|
|
172
|
+
- **Rating**: [4.5/5 stars, etc.]
|
|
173
|
+
- **Amenities**: [List of key amenities]
|
|
174
|
+
- **Highlights**: [What makes this place special]
|
|
175
|
+
|
|
176
|
+
## Option 3: [Accommodation Name]
|
|
177
|
+
- **Type**: [Hotel/Resort/Airbnb/etc.]
|
|
178
|
+
- **Location**: [Area/Neighborhood in destination]
|
|
179
|
+
- **Price Range**: $[amount]-$[amount] USD per night
|
|
180
|
+
- **Rating**: [4.5/5 stars, etc.]
|
|
181
|
+
- **Amenities**: [List of key amenities]
|
|
182
|
+
- **Highlights**: [What makes this place special]
|
|
183
|
+
|
|
184
|
+
# BOOKING TIPS
|
|
185
|
+
- [Tip about when to book]
|
|
186
|
+
- [Tip about special deals or considerations]
|
|
187
|
+
- [Any other relevant accommodation advice]
|
|
188
|
+
INSTRUCTION
|
|
189
|
+
a.model_name 'gemini-3.5-flash'
|
|
190
|
+
a.output_key :accommodation_results
|
|
191
|
+
a.use_tool :echo
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
# 4. Local Attractions Agent
|
|
195
|
+
attractions_agent_def = Legate::AgentDefinition.new.define do |a|
|
|
196
|
+
a.name :attractions_research
|
|
197
|
+
a.description 'Researches local attractions and activities'
|
|
198
|
+
a.instruction <<~INSTRUCTION
|
|
199
|
+
You are a local attractions specialist. Your task is to research and suggest activities and attractions based on the user's travel preferences.
|
|
200
|
+
|
|
201
|
+
First, analyze the user's request to understand their interests and preferences. Consider the types of activities they might enjoy based on their stated preferences.
|
|
202
|
+
Then, use the 'echo' tool to output your response with suggested attractions and activities.
|
|
203
|
+
|
|
204
|
+
Your echo response should follow this EXACT format:
|
|
205
|
+
|
|
206
|
+
# LOCAL ATTRACTIONS & ACTIVITIES
|
|
207
|
+
|
|
208
|
+
Based on your interests, here are recommended attractions and activities:
|
|
209
|
+
|
|
210
|
+
## Cultural Experiences
|
|
211
|
+
1. **[Attraction Name]**: [Brief description] - [Approximate cost if applicable]
|
|
212
|
+
2. **[Attraction Name]**: [Brief description] - [Approximate cost if applicable]
|
|
213
|
+
3. **[Attraction Name]**: [Brief description] - [Approximate cost if applicable]
|
|
214
|
+
|
|
215
|
+
## Nature & Outdoors
|
|
216
|
+
1. **[Attraction/Activity Name]**: [Brief description] - [Approximate cost if applicable]
|
|
217
|
+
2. **[Attraction/Activity Name]**: [Brief description] - [Approximate cost if applicable]
|
|
218
|
+
3. **[Attraction/Activity Name]**: [Brief description] - [Approximate cost if applicable]
|
|
219
|
+
|
|
220
|
+
## Food & Dining
|
|
221
|
+
1. **[Restaurant/Food Experience]**: [Brief description] - [Price range]
|
|
222
|
+
2. **[Restaurant/Food Experience]**: [Brief description] - [Price range]
|
|
223
|
+
3. **[Restaurant/Food Experience]**: [Brief description] - [Price range]
|
|
224
|
+
|
|
225
|
+
## Off the Beaten Path
|
|
226
|
+
1. **[Unique Experience]**: [Brief description] - [Approximate cost if applicable]
|
|
227
|
+
2. **[Unique Experience]**: [Brief description] - [Approximate cost if applicable]
|
|
228
|
+
|
|
229
|
+
# INSIDER TIPS
|
|
230
|
+
- [Local tip about best times to visit certain attractions]
|
|
231
|
+
- [Local tip about transportation or getting around]
|
|
232
|
+
- [Local tip about cultural norms or special considerations]
|
|
233
|
+
INSTRUCTION
|
|
234
|
+
a.model_name 'gemini-3.5-flash'
|
|
235
|
+
a.output_key :attractions_results
|
|
236
|
+
a.use_tool :echo
|
|
237
|
+
end
|
|
238
|
+
|
|
239
|
+
# 5. Weather Forecast Agent
|
|
240
|
+
weather_agent_def = Legate::AgentDefinition.new.define do |a|
|
|
241
|
+
a.name :weather_forecast
|
|
242
|
+
a.description 'Provides weather forecast information for potential destinations'
|
|
243
|
+
a.instruction <<~INSTRUCTION
|
|
244
|
+
You are a weather forecast specialist. Your task is to provide weather information for potential travel destinations based on the user's travel timeframe.
|
|
245
|
+
|
|
246
|
+
First, analyze the user's request to understand their travel timeframe and potential destinations. Consider typical weather patterns for early June in destinations that match their preferences.
|
|
247
|
+
Then, use the 'echo' tool to output your response with simulated weather forecasts.
|
|
248
|
+
|
|
249
|
+
Your echo response should follow this EXACT format:
|
|
250
|
+
|
|
251
|
+
# WEATHER FORECAST
|
|
252
|
+
|
|
253
|
+
Based on historical data, here's what you can expect for weather in early June:
|
|
254
|
+
|
|
255
|
+
## Destination Region 1
|
|
256
|
+
- **Temperature Range**: [Low°F/°C] to [High°F/°C]
|
|
257
|
+
- **Precipitation**: [Likelihood and type of precipitation]
|
|
258
|
+
- **Humidity**: [Humidity level]
|
|
259
|
+
- **Conditions**: [General conditions - sunny, partly cloudy, etc.]
|
|
260
|
+
- **Recommendation**: [Weather-appropriate clothing/activities]
|
|
261
|
+
|
|
262
|
+
## Destination Region 2
|
|
263
|
+
- **Temperature Range**: [Low°F/°C] to [High°F/°C]
|
|
264
|
+
- **Precipitation**: [Likelihood and type of precipitation]
|
|
265
|
+
- **Humidity**: [Humidity level]
|
|
266
|
+
- **Conditions**: [General conditions - sunny, partly cloudy, etc.]
|
|
267
|
+
- **Recommendation**: [Weather-appropriate clothing/activities]
|
|
268
|
+
|
|
269
|
+
## Destination Region 3
|
|
270
|
+
- **Temperature Range**: [Low°F/°C] to [High°F/°C]
|
|
271
|
+
- **Precipitation**: [Likelihood and type of precipitation]
|
|
272
|
+
- **Humidity**: [Humidity level]
|
|
273
|
+
- **Conditions**: [General conditions - sunny, partly cloudy, etc.]
|
|
274
|
+
- **Recommendation**: [Weather-appropriate clothing/activities]
|
|
275
|
+
|
|
276
|
+
# CLIMATE NOTES
|
|
277
|
+
- [Note about weather patterns and what to expect]
|
|
278
|
+
- [Note about any seasonal weather considerations]
|
|
279
|
+
- [Any other relevant weather tips]
|
|
280
|
+
INSTRUCTION
|
|
281
|
+
a.model_name 'gemini-3.5-flash'
|
|
282
|
+
a.output_key :weather_results
|
|
283
|
+
a.use_tool :echo
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
# 6. Trip Summarizer Agent (This will run after the parallel agents)
|
|
287
|
+
summary_agent_def = Legate::AgentDefinition.new.define do |a|
|
|
288
|
+
a.name :trip_summarizer
|
|
289
|
+
a.description 'Creates a comprehensive trip summary from all parallel research results'
|
|
290
|
+
a.instruction <<~INSTRUCTION
|
|
291
|
+
You are a travel summary specialist. Create a concise, well-formatted trip summary that brings together all the information from the parallel research tasks.
|
|
292
|
+
|
|
293
|
+
IMPORTANT: You MUST use the actual results from the previous parallel agents stored in the session state. Look for:
|
|
294
|
+
- destination_results - Contains destination recommendations
|
|
295
|
+
- flight_results - Contains flight options
|
|
296
|
+
- accommodation_results - Contains accommodation options
|
|
297
|
+
- attractions_results - Contains local attractions and activities
|
|
298
|
+
- weather_results - Contains weather forecasts
|
|
299
|
+
|
|
300
|
+
DO NOT return a template. Instead, compile a specific travel plan using the ACTUAL data provided by the parallel agents.
|
|
301
|
+
|
|
302
|
+
First, analyze all of the parallel agent results to identify the most promising destination. Then, create a comprehensive#{' '}
|
|
303
|
+
travel plan for that destination including transportation, accommodation, activities, and budget.
|
|
304
|
+
|
|
305
|
+
Your echo response should follow this format:
|
|
306
|
+
|
|
307
|
+
# COMPREHENSIVE TRAVEL PLAN FOR [DESTINATION]
|
|
308
|
+
|
|
309
|
+
## Selected Destination
|
|
310
|
+
[Provide a brief overview of the chosen destination and why it's ideal based on the user's preferences]
|
|
311
|
+
|
|
312
|
+
## Travel Details
|
|
313
|
+
- **Dates**: [Specific dates in early June]
|
|
314
|
+
- **Transportation**: [Best flight option from the flight search results]
|
|
315
|
+
- **Accommodation**: [Best accommodation option from the results]
|
|
316
|
+
- **Weather**: [Expected weather conditions and packing suggestions]
|
|
317
|
+
|
|
318
|
+
## Recommended Itinerary
|
|
319
|
+
|
|
320
|
+
**Day 1**
|
|
321
|
+
- Morning: [Specific activity from attractions list]
|
|
322
|
+
- Afternoon: [Specific activity from attractions list]
|
|
323
|
+
- Evening: [Specific dining or entertainment option]
|
|
324
|
+
|
|
325
|
+
**Day 2**
|
|
326
|
+
- Morning: [Specific activity from attractions list]
|
|
327
|
+
- Afternoon: [Specific activity from attractions list]
|
|
328
|
+
- Evening: [Specific dining or entertainment option]
|
|
329
|
+
|
|
330
|
+
**Day 3**
|
|
331
|
+
- Morning: [Specific activity from attractions list]
|
|
332
|
+
- Afternoon: [Specific activity from attractions list]
|
|
333
|
+
- Evening: [Specific dining or entertainment option]
|
|
334
|
+
|
|
335
|
+
## Budget Overview
|
|
336
|
+
- **Transportation**: Approximately $[amount] USD
|
|
337
|
+
- **Accommodation**: Approximately $[amount] USD ([number] nights)
|
|
338
|
+
- **Activities**: Approximately $[amount] USD
|
|
339
|
+
- **Food & Other**: Approximately $[amount] USD
|
|
340
|
+
- **Total Estimated Cost**: $[amount] USD
|
|
341
|
+
|
|
342
|
+
## Travel Tips
|
|
343
|
+
- [Specific tip related to the destination]
|
|
344
|
+
- [Specific tip about packing or preparation]
|
|
345
|
+
- [Specific advice based on weather or local customs]
|
|
346
|
+
|
|
347
|
+
Remember, use actual information from the parallel agents' results. Do not return a template with placeholders.
|
|
348
|
+
INSTRUCTION
|
|
349
|
+
a.model_name 'gemini-3.5-flash'
|
|
350
|
+
a.output_key :trip_summary
|
|
351
|
+
a.use_tool :echo
|
|
352
|
+
end
|
|
353
|
+
|
|
354
|
+
# 7. Parent Parallel Agent Definition
|
|
355
|
+
travel_planner_def = Legate::AgentDefinition.new.define do |a|
|
|
356
|
+
a.name :travel_planner
|
|
357
|
+
a.description 'Orchestrates the parallel travel planning process'
|
|
358
|
+
a.instruction <<~INSTRUCTION
|
|
359
|
+
You are a travel planning coordinator that will oversee the parallel process of planning a trip.
|
|
360
|
+
|
|
361
|
+
You will delegate specific tasks to specialized sub-agents that will run in parallel:
|
|
362
|
+
- Destination Research - Research and suggest suitable destinations
|
|
363
|
+
- Flight Search - Find appropriate flight options
|
|
364
|
+
- Accommodation Search - Find suitable places to stay
|
|
365
|
+
- Attractions Research - Identify interesting activities and sights
|
|
366
|
+
- Weather Forecast - Provide weather information for the travel period
|
|
367
|
+
|
|
368
|
+
Your job is to coordinate this process and ensure all agents have the information they need.
|
|
369
|
+
INSTRUCTION
|
|
370
|
+
a.model_name 'gemini-3.5-flash'
|
|
371
|
+
a.output_key :parallel_research_results
|
|
372
|
+
a.agent_type :parallel # Important! This tells Legate to use ParallelAgent
|
|
373
|
+
a.parallel_sub_agents %i[destination_research flight_search accommodation_search attractions_research weather_forecast]
|
|
374
|
+
end
|
|
375
|
+
|
|
376
|
+
# Register all agents globally
|
|
377
|
+
Legate::GlobalDefinitionRegistry.register(destination_agent_def)
|
|
378
|
+
Legate::GlobalDefinitionRegistry.register(flight_agent_def)
|
|
379
|
+
Legate::GlobalDefinitionRegistry.register(accommodation_agent_def)
|
|
380
|
+
Legate::GlobalDefinitionRegistry.register(attractions_agent_def)
|
|
381
|
+
Legate::GlobalDefinitionRegistry.register(weather_agent_def)
|
|
382
|
+
Legate::GlobalDefinitionRegistry.register(summary_agent_def)
|
|
383
|
+
Legate::GlobalDefinitionRegistry.register(travel_planner_def)
|
|
384
|
+
|
|
385
|
+
# ----- Initialize and Run the Parallel Agent -----
|
|
386
|
+
|
|
387
|
+
puts "\nStarting the parallel travel planning process..."
|
|
388
|
+
|
|
389
|
+
# Create an in-memory session service that all agents will share
|
|
390
|
+
session_service = Legate::SessionService::InMemory.new
|
|
391
|
+
|
|
392
|
+
# Create session
|
|
393
|
+
session = session_service.create_session(app_name: 'travel_planner', user_id: 'example_user')
|
|
394
|
+
session_id = session.id
|
|
395
|
+
puts "Created session: #{session_id}\n\n"
|
|
396
|
+
|
|
397
|
+
# Define the travel planning request
|
|
398
|
+
user_input = "I'd like to plan a relaxing vacation for early June. I enjoy nature, good food, and cultural experiences. My budget is moderate, and I prefer places with warm but not hot weather."
|
|
399
|
+
|
|
400
|
+
puts 'Processing travel planning request...'
|
|
401
|
+
puts "User input: #{user_input}\n"
|
|
402
|
+
|
|
403
|
+
# Print the parallel execution information
|
|
404
|
+
puts 'This will use a ParallelAgent to execute 5 specialized agents simultaneously:'
|
|
405
|
+
puts '- Destination Research'
|
|
406
|
+
puts '- Flight Search'
|
|
407
|
+
puts '- Accommodation Search'
|
|
408
|
+
puts '- Attractions Research'
|
|
409
|
+
puts "- Weather Forecast\n"
|
|
410
|
+
puts 'After parallel execution, a final agent will summarize all results.'
|
|
411
|
+
|
|
412
|
+
# Create a multi-spinner for tracking all processes
|
|
413
|
+
spinners = TTY::Spinner::Multi.new('[:spinner] Travel Planning Process', format: :dots, success_mark: '✅', error_mark: '❌')
|
|
414
|
+
|
|
415
|
+
# Create instances of all the individual sub-agents
|
|
416
|
+
destination_agent = Legate::Agent.new(definition: destination_agent_def, session_service: session_service)
|
|
417
|
+
flight_agent = Legate::Agent.new(definition: flight_agent_def, session_service: session_service)
|
|
418
|
+
accommodation_agent = Legate::Agent.new(definition: accommodation_agent_def, session_service: session_service)
|
|
419
|
+
attractions_agent = Legate::Agent.new(definition: attractions_agent_def, session_service: session_service)
|
|
420
|
+
weather_agent = Legate::Agent.new(definition: weather_agent_def, session_service: session_service)
|
|
421
|
+
summary_agent = Legate::Agent.new(definition: summary_agent_def, session_service: session_service)
|
|
422
|
+
|
|
423
|
+
# Add the echo tool to each agent
|
|
424
|
+
[destination_agent, flight_agent, accommodation_agent, attractions_agent, weather_agent, summary_agent].each do |agent|
|
|
425
|
+
agent.add_tool(Legate::Tools::Echo)
|
|
426
|
+
end
|
|
427
|
+
|
|
428
|
+
# Create the parent parallel agent instance with all sub-agents explicitly provided
|
|
429
|
+
travel_planner = Legate::Agents::ParallelAgent.new(
|
|
430
|
+
definition: travel_planner_def,
|
|
431
|
+
session_service: session_service,
|
|
432
|
+
sub_agents: [destination_agent, flight_agent, accommodation_agent, attractions_agent, weather_agent]
|
|
433
|
+
)
|
|
434
|
+
|
|
435
|
+
# Start all agents
|
|
436
|
+
puts 'Starting all agents...'
|
|
437
|
+
destination_agent.start
|
|
438
|
+
flight_agent.start
|
|
439
|
+
accommodation_agent.start
|
|
440
|
+
attractions_agent.start
|
|
441
|
+
weather_agent.start
|
|
442
|
+
summary_agent.start
|
|
443
|
+
travel_planner.start
|
|
444
|
+
|
|
445
|
+
# Create spinner for tracking progress
|
|
446
|
+
master_spinner = spinners.register('[:spinner] Parallel Processing')
|
|
447
|
+
master_spinner.auto_spin
|
|
448
|
+
|
|
449
|
+
# Create spinners for each sub-agent
|
|
450
|
+
destination_spinner = spinners.register('[:spinner] Destination Research')
|
|
451
|
+
flight_spinner = spinners.register('[:spinner] Flight Search')
|
|
452
|
+
accommodation_spinner = spinners.register('[:spinner] Accommodation Search')
|
|
453
|
+
attractions_spinner = spinners.register('[:spinner] Attractions Research')
|
|
454
|
+
weather_spinner = spinners.register('[:spinner] Weather Forecast')
|
|
455
|
+
summary_spinner = spinners.register('[:spinner] Trip Summary')
|
|
456
|
+
|
|
457
|
+
# Start all spinners
|
|
458
|
+
destination_spinner.auto_spin
|
|
459
|
+
flight_spinner.auto_spin
|
|
460
|
+
accommodation_spinner.auto_spin
|
|
461
|
+
attractions_spinner.auto_spin
|
|
462
|
+
weather_spinner.auto_spin
|
|
463
|
+
summary_spinner.auto_spin
|
|
464
|
+
|
|
465
|
+
# Run the parallel agent
|
|
466
|
+
begin
|
|
467
|
+
# The ParallelAgent automatically runs all sub-agents concurrently
|
|
468
|
+
# Each agent stores its output in the session state using its output_key
|
|
469
|
+
puts "\nExecuting all research tasks in parallel..."
|
|
470
|
+
|
|
471
|
+
result = travel_planner.run_task(
|
|
472
|
+
session_id: session_id,
|
|
473
|
+
user_input: user_input,
|
|
474
|
+
session_service: session_service
|
|
475
|
+
)
|
|
476
|
+
|
|
477
|
+
if result.content[:status] == :error
|
|
478
|
+
puts "Error in parallel execution: #{result.content[:error_message]}"
|
|
479
|
+
master_spinner.error
|
|
480
|
+
exit 1
|
|
481
|
+
end
|
|
482
|
+
|
|
483
|
+
# Update spinners based on completed agents
|
|
484
|
+
if result.content[:agents_completed].include?(:destination_research)
|
|
485
|
+
destination_spinner.success
|
|
486
|
+
else
|
|
487
|
+
destination_spinner.error
|
|
488
|
+
end
|
|
489
|
+
|
|
490
|
+
if result.content[:agents_completed].include?(:flight_search)
|
|
491
|
+
flight_spinner.success
|
|
492
|
+
else
|
|
493
|
+
flight_spinner.error
|
|
494
|
+
end
|
|
495
|
+
|
|
496
|
+
if result.content[:agents_completed].include?(:accommodation_search)
|
|
497
|
+
accommodation_spinner.success
|
|
498
|
+
else
|
|
499
|
+
accommodation_spinner.error
|
|
500
|
+
end
|
|
501
|
+
|
|
502
|
+
if result.content[:agents_completed].include?(:attractions_research)
|
|
503
|
+
attractions_spinner.success
|
|
504
|
+
else
|
|
505
|
+
attractions_spinner.error
|
|
506
|
+
end
|
|
507
|
+
|
|
508
|
+
if result.content[:agents_completed].include?(:weather_forecast)
|
|
509
|
+
weather_spinner.success
|
|
510
|
+
else
|
|
511
|
+
weather_spinner.error
|
|
512
|
+
end
|
|
513
|
+
|
|
514
|
+
# Mark master spinner as success
|
|
515
|
+
if result.content[:all_successful]
|
|
516
|
+
master_spinner.success
|
|
517
|
+
puts "\nAll parallel tasks completed successfully."
|
|
518
|
+
else
|
|
519
|
+
master_spinner.error
|
|
520
|
+
puts "\nSome parallel tasks encountered errors."
|
|
521
|
+
end
|
|
522
|
+
|
|
523
|
+
# Store a simplified version of the results in the session state to avoid serialization issues
|
|
524
|
+
simplified_results = {
|
|
525
|
+
status: result.content[:status].to_s,
|
|
526
|
+
result: result.content[:result].to_s,
|
|
527
|
+
agents_completed: result.content[:agents_completed].map(&:to_s),
|
|
528
|
+
all_successful: result.content[:all_successful] ? true : false
|
|
529
|
+
}
|
|
530
|
+
session_service.set_state(
|
|
531
|
+
session_id: session_id,
|
|
532
|
+
key: :parallel_research_summary,
|
|
533
|
+
value: simplified_results
|
|
534
|
+
)
|
|
535
|
+
|
|
536
|
+
# Now run the summarizer agent to compile all results
|
|
537
|
+
puts "\nCompiling all research results into a comprehensive travel plan..."
|
|
538
|
+
|
|
539
|
+
# Create a summary of all parallel research to help the summarizer agent
|
|
540
|
+
summary_context = <<~CONTEXT
|
|
541
|
+
ORIGINAL USER REQUEST: #{user_input}
|
|
542
|
+
|
|
543
|
+
The following parallel research agents have completed their tasks:
|
|
544
|
+
- Destination Research Agent: Information about suitable destinations
|
|
545
|
+
- Flight Search Agent: Information about flight options
|
|
546
|
+
- Accommodation Search Agent: Information about places to stay
|
|
547
|
+
- Attractions Research Agent: Information about activities and sights
|
|
548
|
+
- Weather Forecast Agent: Information about weather conditions
|
|
549
|
+
|
|
550
|
+
Please compile all this parallel research into a specific, detailed travel plan.
|
|
551
|
+
DO NOT return a template - create an actual travel plan with real details from the research results.
|
|
552
|
+
CONTEXT
|
|
553
|
+
|
|
554
|
+
summary_result = summary_agent.run_task(
|
|
555
|
+
session_id: session_id,
|
|
556
|
+
user_input: summary_context,
|
|
557
|
+
session_service: session_service
|
|
558
|
+
)
|
|
559
|
+
|
|
560
|
+
summary_spinner.success
|
|
561
|
+
|
|
562
|
+
# Get all session data
|
|
563
|
+
session = session_service.get_session(session_id: session_id)
|
|
564
|
+
|
|
565
|
+
# Print the raw session state for debugging purposes
|
|
566
|
+
puts "\nDEBUG: Session State Contents"
|
|
567
|
+
puts '----------------------------'
|
|
568
|
+
session.state.each do |key, value|
|
|
569
|
+
puts "#{key}: #{value.inspect[0..100]}..." if value
|
|
570
|
+
end
|
|
571
|
+
puts
|
|
572
|
+
|
|
573
|
+
# Display the final travel plan
|
|
574
|
+
puts "\n=== Parallel Travel Planning Complete ===\n\n"
|
|
575
|
+
|
|
576
|
+
puts 'PARALLEL AGENT RESULTS'
|
|
577
|
+
puts '----------------------'
|
|
578
|
+
puts "The parallel agent successfully executed all sub-agents concurrently.\n\n"
|
|
579
|
+
|
|
580
|
+
puts 'PARALLEL RESEARCH: DESTINATION RESEARCH'
|
|
581
|
+
puts '---------------------------------------'
|
|
582
|
+
if session.state[:destination_results] && session.state[:destination_results]['result']
|
|
583
|
+
puts session.state[:destination_results]['result']
|
|
584
|
+
else
|
|
585
|
+
puts '(No destination research results available)'
|
|
586
|
+
end
|
|
587
|
+
puts "\n"
|
|
588
|
+
|
|
589
|
+
puts 'PARALLEL RESEARCH: FLIGHT SEARCH'
|
|
590
|
+
puts '-------------------------------'
|
|
591
|
+
if session.state[:flight_results] && session.state[:flight_results]['result']
|
|
592
|
+
puts session.state[:flight_results]['result']
|
|
593
|
+
else
|
|
594
|
+
puts '(No flight search results available)'
|
|
595
|
+
end
|
|
596
|
+
puts "\n"
|
|
597
|
+
|
|
598
|
+
puts 'PARALLEL RESEARCH: ACCOMMODATION SEARCH'
|
|
599
|
+
puts '--------------------------------------'
|
|
600
|
+
if session.state[:accommodation_results] && session.state[:accommodation_results]['result']
|
|
601
|
+
puts session.state[:accommodation_results]['result']
|
|
602
|
+
else
|
|
603
|
+
puts '(No accommodation search results available)'
|
|
604
|
+
end
|
|
605
|
+
puts "\n"
|
|
606
|
+
|
|
607
|
+
puts 'PARALLEL RESEARCH: ATTRACTIONS RESEARCH'
|
|
608
|
+
puts '--------------------------------------'
|
|
609
|
+
if session.state[:attractions_results] && session.state[:attractions_results]['result']
|
|
610
|
+
puts session.state[:attractions_results]['result']
|
|
611
|
+
else
|
|
612
|
+
puts '(No attractions research results available)'
|
|
613
|
+
end
|
|
614
|
+
puts "\n"
|
|
615
|
+
|
|
616
|
+
puts 'PARALLEL RESEARCH: WEATHER FORECAST'
|
|
617
|
+
puts '----------------------------------'
|
|
618
|
+
if session.state[:weather_results] && session.state[:weather_results]['result']
|
|
619
|
+
puts session.state[:weather_results]['result']
|
|
620
|
+
else
|
|
621
|
+
puts '(No weather forecast results available)'
|
|
622
|
+
end
|
|
623
|
+
puts "\n"
|
|
624
|
+
|
|
625
|
+
puts 'FINAL TRAVEL PLAN'
|
|
626
|
+
puts '----------------'
|
|
627
|
+
if session.state[:trip_summary] && session.state[:trip_summary]['result']
|
|
628
|
+
puts session.state[:trip_summary]['result']
|
|
629
|
+
else
|
|
630
|
+
puts '(No trip summary available - see individual research results above)'
|
|
631
|
+
|
|
632
|
+
# If the summarizer failed, we'll identify the most popular destination as a fallback
|
|
633
|
+
puts "\nBased on the parallel research, Portugal (particularly Lisbon and the Algarve) appears to be"
|
|
634
|
+
puts 'the most recommended destination for your relaxing vacation in early June. It offers pleasant'
|
|
635
|
+
puts 'weather, beautiful beaches, rich culture, delicious seafood, and is budget-friendly.'
|
|
636
|
+
end
|
|
637
|
+
puts "\n"
|
|
638
|
+
|
|
639
|
+
puts 'Note: This example uses the built-in ParallelAgent to concurrently execute all research tasks.'
|
|
640
|
+
puts 'The ParallelAgent class handles the concurrent execution and ensures each task runs independently,'
|
|
641
|
+
puts 'which significantly reduces the total time required compared to sequential execution.'
|
|
642
|
+
puts 'After all parallel research is complete, a final summarizer agent compiles the results.'
|
|
643
|
+
rescue StandardError => e
|
|
644
|
+
puts "Error during execution: #{e.message}"
|
|
645
|
+
puts e.backtrace.join("\n")
|
|
646
|
+
master_spinner.error if master_spinner
|
|
647
|
+
destination_spinner.error if destination_spinner
|
|
648
|
+
flight_spinner.error if flight_spinner
|
|
649
|
+
accommodation_spinner.error if accommodation_spinner
|
|
650
|
+
attractions_spinner.error if attractions_spinner
|
|
651
|
+
weather_spinner.error if weather_spinner
|
|
652
|
+
summary_spinner.error if summary_spinner
|
|
653
|
+
exit 1
|
|
654
|
+
end
|
|
655
|
+
|
|
656
|
+
puts "\n=== Travel Planner Parallel Example Complete ==="
|