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.
Files changed (317) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +345 -0
  4. data/bin/legate +13 -0
  5. data/examples/00_quickstart.rb +51 -0
  6. data/examples/01_simple_agent.rb +105 -0
  7. data/examples/02_multi_tool_agent.rb +140 -0
  8. data/examples/03_custom_tool.rb +93 -0
  9. data/examples/04_agent_instructions.rb +84 -0
  10. data/examples/05_state_and_sessions.rb +91 -0
  11. data/examples/06_callbacks.rb +186 -0
  12. data/examples/07_async_jobs.rb +112 -0
  13. data/examples/08_loop_agent.rb +197 -0
  14. data/examples/09_sequential_workflow.rb +40 -0
  15. data/examples/10_parallel_workflow.rb +34 -0
  16. data/examples/11_agent_delegation.rb +24 -0
  17. data/examples/12_http_client_tool.rb +156 -0
  18. data/examples/13_authentication.rb +220 -0
  19. data/examples/14_mcp_client.rb +154 -0
  20. data/examples/15_mcp_server.rb +79 -0
  21. data/examples/16_webhooks.rb +91 -0
  22. data/examples/README_sequential_agents.md +164 -0
  23. data/examples/advanced/auth/cookie_auth_tool.rb +146 -0
  24. data/examples/advanced/auth/custom_auth_flows_example.rb +626 -0
  25. data/examples/advanced/auth/excon_middleware.rb +317 -0
  26. data/examples/advanced/auth/excon_middleware_auth.rb +399 -0
  27. data/examples/advanced/auth/fiber_auth_example.rb +281 -0
  28. data/examples/advanced/auth/fiber_oidc_example.rb +403 -0
  29. data/examples/advanced/auth/httpbin_bearer_tool.rb +159 -0
  30. data/examples/advanced/auth/oauth2_auth.rb +419 -0
  31. data/examples/advanced/auth/oidc_auth.rb +514 -0
  32. data/examples/advanced/auth/openweather_api.rb +251 -0
  33. data/examples/advanced/auth/openweather_tool.rb +153 -0
  34. data/examples/advanced/auth/query_param_middleware_test.rb +138 -0
  35. data/examples/advanced/auth/service_account.rb +135 -0
  36. data/examples/advanced/auth/test_with_httpbin.rb +202 -0
  37. data/examples/advanced/auth/token_lifecycle_example.rb +428 -0
  38. data/examples/advanced/callback_monitoring.rb +679 -0
  39. data/examples/advanced/mas/fixed_delegation_example.rb +191 -0
  40. data/examples/advanced/mas/loop_workflow.rb +28 -0
  41. data/examples/advanced/mas/mock_planner.rb +77 -0
  42. data/examples/advanced/mas/proper_delegation_example.rb +276 -0
  43. data/examples/advanced/mcp/legate_mcp_server_resource_example.rb +182 -0
  44. data/examples/advanced/mcp/mcp_resource_server_example.rb +309 -0
  45. data/examples/advanced/mcp/mcp_server_async.rb +76 -0
  46. data/examples/advanced/mcp/mcp_server_async_tools.rb +122 -0
  47. data/examples/advanced/mcp/mcp_server_legate_agent.rb +95 -0
  48. data/examples/advanced/mcp/mcp_server_rack.rb +89 -0
  49. data/examples/advanced/random_calculator.rb +104 -0
  50. data/examples/advanced/sleep_agent.rb +153 -0
  51. data/examples/advanced/webhooks/webhook_e2e_runner.rb +110 -0
  52. data/examples/advanced/webhooks/webhook_receiver_agent.rb +58 -0
  53. data/examples/advanced/workflows/task_refinement_loop_agent.rb +278 -0
  54. data/examples/advanced/workflows/travel_planner_auto_sequential.rb +444 -0
  55. data/examples/advanced/workflows/travel_planner_parallel.rb +656 -0
  56. data/examples/advanced/workflows/travel_planner_sequential.rb +512 -0
  57. data/examples/tools/oauth2_example.rb +136 -0
  58. data/examples/tools/sleepy_tool.rb +42 -0
  59. data/lib/legate/activity_log.rb +71 -0
  60. data/lib/legate/agent.rb +959 -0
  61. data/lib/legate/agent_code_generator.rb +185 -0
  62. data/lib/legate/agent_definition.rb +812 -0
  63. data/lib/legate/agentic/decision.rb +49 -0
  64. data/lib/legate/agentic/loop.rb +134 -0
  65. data/lib/legate/agentic.rb +5 -0
  66. data/lib/legate/agents/loop_agent.rb +248 -0
  67. data/lib/legate/agents/parallel_agent.rb +163 -0
  68. data/lib/legate/agents/sequential_agent.rb +190 -0
  69. data/lib/legate/agents.rb +14 -0
  70. data/lib/legate/auth/config.rb +148 -0
  71. data/lib/legate/auth/coordinator.rb +218 -0
  72. data/lib/legate/auth/coordinators/oauth2_coordinator.rb +99 -0
  73. data/lib/legate/auth/coordinators/oidc_coordinator.rb +68 -0
  74. data/lib/legate/auth/coordinators/service_account_coordinator.rb +122 -0
  75. data/lib/legate/auth/credential.rb +157 -0
  76. data/lib/legate/auth/encryption.rb +108 -0
  77. data/lib/legate/auth/error.rb +94 -0
  78. data/lib/legate/auth/exchanged_credential.rb +180 -0
  79. data/lib/legate/auth/excon_middleware.rb +285 -0
  80. data/lib/legate/auth/http_client_utils.rb +364 -0
  81. data/lib/legate/auth/manager.rb +531 -0
  82. data/lib/legate/auth/manager_store.rb +394 -0
  83. data/lib/legate/auth/middleware_factory.rb +290 -0
  84. data/lib/legate/auth/runner.rb +279 -0
  85. data/lib/legate/auth/scheme.rb +125 -0
  86. data/lib/legate/auth/schemes/api_key.rb +212 -0
  87. data/lib/legate/auth/schemes/google_service_account.rb +108 -0
  88. data/lib/legate/auth/schemes/http_bearer.rb +98 -0
  89. data/lib/legate/auth/schemes/oauth2.rb +396 -0
  90. data/lib/legate/auth/schemes/openid_connect.rb +346 -0
  91. data/lib/legate/auth/schemes/service_account.rb +388 -0
  92. data/lib/legate/auth/schemes.rb +40 -0
  93. data/lib/legate/auth/token_manager.rb +362 -0
  94. data/lib/legate/auth/token_store.rb +86 -0
  95. data/lib/legate/auth/tool_context_extension.rb +97 -0
  96. data/lib/legate/auth/tool_integration.rb +188 -0
  97. data/lib/legate/auth/url_guard.rb +81 -0
  98. data/lib/legate/auth.rb +453 -0
  99. data/lib/legate/callbacks/callback_context.rb +71 -0
  100. data/lib/legate/cli/agent_commands.rb +950 -0
  101. data/lib/legate/cli/auth_commands.rb +520 -0
  102. data/lib/legate/cli/base_command.rb +24 -0
  103. data/lib/legate/cli/deployment_commands.rb +934 -0
  104. data/lib/legate/cli/output_helper.rb +108 -0
  105. data/lib/legate/cli/session_commands.rb +138 -0
  106. data/lib/legate/cli/skaffold_commands.rb +223 -0
  107. data/lib/legate/cli/tool_commands.rb +261 -0
  108. data/lib/legate/cli/web_commands.rb +182 -0
  109. data/lib/legate/cli.rb +40 -0
  110. data/lib/legate/configuration/webhooks.rb +113 -0
  111. data/lib/legate/configuration.rb +39 -0
  112. data/lib/legate/definition_store.rb +23 -0
  113. data/lib/legate/errors.rb +118 -0
  114. data/lib/legate/event.rb +161 -0
  115. data/lib/legate/gemini_ai_beta_patch.rb +39 -0
  116. data/lib/legate/generators/agent_generator.rb +412 -0
  117. data/lib/legate/generators/code_validator.rb +48 -0
  118. data/lib/legate/generators/legate/install_generator.rb +35 -0
  119. data/lib/legate/generators/legate/templates/create_legate_tables.rb.tt +36 -0
  120. data/lib/legate/generators/legate/templates/initializer.rb +18 -0
  121. data/lib/legate/generators/runtime_tool_loader.rb +76 -0
  122. data/lib/legate/generators/tool_generator.rb +408 -0
  123. data/lib/legate/generators.rb +11 -0
  124. data/lib/legate/global_definition_registry.rb +506 -0
  125. data/lib/legate/global_tool_manager.rb +135 -0
  126. data/lib/legate/llm/adapter.rb +69 -0
  127. data/lib/legate/llm/gemini.rb +172 -0
  128. data/lib/legate/llm/ollama.rb +80 -0
  129. data/lib/legate/llm.rb +34 -0
  130. data/lib/legate/mcp/client.rb +320 -0
  131. data/lib/legate/mcp/connection/sse.rb +292 -0
  132. data/lib/legate/mcp/connection/stdio.rb +273 -0
  133. data/lib/legate/mcp/connection_manager.rb +103 -0
  134. data/lib/legate/mcp/server/legate_agent_adapter.rb +170 -0
  135. data/lib/legate/mcp/server/legate_direct_agent_adapter.rb +140 -0
  136. data/lib/legate/mcp/server/legate_tool_adapter.rb +119 -0
  137. data/lib/legate/mcp/tool_wrapper.rb +138 -0
  138. data/lib/legate/mcp/util/schema_converter.rb +134 -0
  139. data/lib/legate/mcp.rb +23 -0
  140. data/lib/legate/plan_executor.rb +375 -0
  141. data/lib/legate/planner.rb +839 -0
  142. data/lib/legate/rails/railtie.rb +43 -0
  143. data/lib/legate/rails.rb +9 -0
  144. data/lib/legate/redaction.rb +32 -0
  145. data/lib/legate/session.rb +299 -0
  146. data/lib/legate/session_service/active_record.rb +300 -0
  147. data/lib/legate/session_service/base.rb +68 -0
  148. data/lib/legate/session_service/event_broadcast.rb +74 -0
  149. data/lib/legate/session_service/in_memory.rb +188 -0
  150. data/lib/legate/tool/metadata_dsl.rb +122 -0
  151. data/lib/legate/tool.rb +276 -0
  152. data/lib/legate/tool_code_generator.rb +103 -0
  153. data/lib/legate/tool_context.rb +350 -0
  154. data/lib/legate/tool_loader.rb +39 -0
  155. data/lib/legate/tool_registry.rb +73 -0
  156. data/lib/legate/tool_result.rb +61 -0
  157. data/lib/legate/tools/agent_tool.rb +187 -0
  158. data/lib/legate/tools/base/http_client.rb +319 -0
  159. data/lib/legate/tools/base/safe_url.rb +56 -0
  160. data/lib/legate/tools/base_async_job_tool.rb +91 -0
  161. data/lib/legate/tools/calculator.rb +89 -0
  162. data/lib/legate/tools/cat_facts.rb +81 -0
  163. data/lib/legate/tools/check_job_status_tool.rb +48 -0
  164. data/lib/legate/tools/current_time_tool.rb +64 -0
  165. data/lib/legate/tools/echo.rb +43 -0
  166. data/lib/legate/tools/http_request_tool.rb +105 -0
  167. data/lib/legate/tools/random_number_tool.rb +64 -0
  168. data/lib/legate/tools/read_webpage_tool.rb +92 -0
  169. data/lib/legate/tools/sleepy_tool.rb +74 -0
  170. data/lib/legate/tools/webhook_tool.rb +146 -0
  171. data/lib/legate/version.rb +5 -0
  172. data/lib/legate/web/app.rb +984 -0
  173. data/lib/legate/web/public/css/main.css +4980 -0
  174. data/lib/legate/web/public/images/favicon-256.png +0 -0
  175. data/lib/legate/web/public/images/favicon-32.png +0 -0
  176. data/lib/legate/web/public/images/legate-logo-dark.png +0 -0
  177. data/lib/legate/web/public/images/legate-logo-light.png +0 -0
  178. data/lib/legate/web/public/js/legate.js +616 -0
  179. data/lib/legate/web/public/styles/main.scss +4402 -0
  180. data/lib/legate/web/routes/agent_authentication_routes.rb +530 -0
  181. data/lib/legate/web/routes/agent_definition_routes.rb +803 -0
  182. data/lib/legate/web/routes/agent_generator_routes.rb +80 -0
  183. data/lib/legate/web/routes/agent_interaction_routes.rb +734 -0
  184. data/lib/legate/web/routes/agent_runtime_routes.rb +323 -0
  185. data/lib/legate/web/routes/api_routes.rb +56 -0
  186. data/lib/legate/web/routes/authentication_routes.rb +1541 -0
  187. data/lib/legate/web/routes/core_routes.rb +111 -0
  188. data/lib/legate/web/routes/documentation_routes.rb +220 -0
  189. data/lib/legate/web/routes/tool_generator_routes.rb +81 -0
  190. data/lib/legate/web/routes/tools_ui_routes.rb +207 -0
  191. data/lib/legate/web/sass_compiler.rb +73 -0
  192. data/lib/legate/web/views/_active_session_info.slim +25 -0
  193. data/lib/legate/web/views/_activity_list.slim +55 -0
  194. data/lib/legate/web/views/_agent_card.slim +56 -0
  195. data/lib/legate/web/views/_agent_generator_modal.slim +382 -0
  196. data/lib/legate/web/views/_agent_status_controls.slim +71 -0
  197. data/lib/legate/web/views/_agent_tool_table.slim +74 -0
  198. data/lib/legate/web/views/_chat_message.slim +95 -0
  199. data/lib/legate/web/views/_display_agent_configuration.slim +26 -0
  200. data/lib/legate/web/views/_display_agent_description.slim +11 -0
  201. data/lib/legate/web/views/_display_agent_fallback.slim +15 -0
  202. data/lib/legate/web/views/_display_agent_hierarchy.slim +93 -0
  203. data/lib/legate/web/views/_display_agent_instruction.slim +17 -0
  204. data/lib/legate/web/views/_display_agent_mcp.slim +13 -0
  205. data/lib/legate/web/views/_display_agent_model.slim +17 -0
  206. data/lib/legate/web/views/_display_agent_name.slim +42 -0
  207. data/lib/legate/web/views/_display_agent_output_key.slim +26 -0
  208. data/lib/legate/web/views/_display_agent_type.slim +65 -0
  209. data/lib/legate/web/views/_edit_agent_configuration.slim +74 -0
  210. data/lib/legate/web/views/_edit_agent_description.slim +16 -0
  211. data/lib/legate/web/views/_edit_agent_fallback.slim +25 -0
  212. data/lib/legate/web/views/_edit_agent_hierarchy.slim +98 -0
  213. data/lib/legate/web/views/_edit_agent_instruction.slim +49 -0
  214. data/lib/legate/web/views/_edit_agent_mcp.slim +33 -0
  215. data/lib/legate/web/views/_edit_agent_model.slim +23 -0
  216. data/lib/legate/web/views/_edit_agent_output_key.slim +36 -0
  217. data/lib/legate/web/views/_edit_agent_tools.slim +40 -0
  218. data/lib/legate/web/views/_edit_agent_type.slim +67 -0
  219. data/lib/legate/web/views/_session_error.slim +4 -0
  220. data/lib/legate/web/views/_skeleton.slim +69 -0
  221. data/lib/legate/web/views/_tool_card.slim +9 -0
  222. data/lib/legate/web/views/_tool_generator_modal.slim +311 -0
  223. data/lib/legate/web/views/agent.slim +436 -0
  224. data/lib/legate/web/views/agent_auth.slim +562 -0
  225. data/lib/legate/web/views/agents.slim +369 -0
  226. data/lib/legate/web/views/auth.slim +112 -0
  227. data/lib/legate/web/views/auth_credential_detail.slim +327 -0
  228. data/lib/legate/web/views/auth_credentials.slim +261 -0
  229. data/lib/legate/web/views/auth_debug.slim +94 -0
  230. data/lib/legate/web/views/auth_mapping_detail.slim +151 -0
  231. data/lib/legate/web/views/auth_mapping_new.slim +123 -0
  232. data/lib/legate/web/views/auth_mappings.slim +120 -0
  233. data/lib/legate/web/views/auth_scheme_detail.slim +274 -0
  234. data/lib/legate/web/views/auth_schemes.slim +259 -0
  235. data/lib/legate/web/views/auth_test.slim +418 -0
  236. data/lib/legate/web/views/chat.slim +192 -0
  237. data/lib/legate/web/views/docs_index.slim +105 -0
  238. data/lib/legate/web/views/docs_show.slim +105 -0
  239. data/lib/legate/web/views/error_404.slim +5 -0
  240. data/lib/legate/web/views/index.slim +148 -0
  241. data/lib/legate/web/views/layout.slim +144 -0
  242. data/lib/legate/web/views/tool_detail.slim +87 -0
  243. data/lib/legate/web/views/tools.slim +50 -0
  244. data/lib/legate/web/webhook_listener.rb +367 -0
  245. data/lib/legate/web.rb +9 -0
  246. data/lib/legate.rb +220 -0
  247. data/public/docs/advanced/callbacks.md +828 -0
  248. data/public/docs/advanced/mcp_schema_conversion.md +59 -0
  249. data/public/docs/authentication/api_reference/config.md +210 -0
  250. data/public/docs/authentication/api_reference/credential.md +246 -0
  251. data/public/docs/authentication/api_reference/encryption.md +218 -0
  252. data/public/docs/authentication/api_reference/exchanged_credential.md +271 -0
  253. data/public/docs/authentication/api_reference/excon_middleware.md +175 -0
  254. data/public/docs/authentication/api_reference/index.md +30 -0
  255. data/public/docs/authentication/api_reference/scheme.md +250 -0
  256. data/public/docs/authentication/api_reference/schemes/api_key.md +175 -0
  257. data/public/docs/authentication/api_reference/schemes/google_service_account.md +221 -0
  258. data/public/docs/authentication/api_reference/schemes/http_bearer.md +169 -0
  259. data/public/docs/authentication/api_reference/schemes/oauth2.md +343 -0
  260. data/public/docs/authentication/api_reference/schemes/oidc.md +73 -0
  261. data/public/docs/authentication/api_reference/schemes/openid_connect.md +311 -0
  262. data/public/docs/authentication/api_reference/schemes/service_account.md +287 -0
  263. data/public/docs/authentication/api_reference/token_manager.md +221 -0
  264. data/public/docs/authentication/api_reference/token_store.md +146 -0
  265. data/public/docs/authentication/api_reference/tool_context_extension.md +166 -0
  266. data/public/docs/authentication/guides/api_key.md +190 -0
  267. data/public/docs/authentication/guides/bearer.md +172 -0
  268. data/public/docs/authentication/guides/configuration.md +255 -0
  269. data/public/docs/authentication/guides/custom_flow.md +523 -0
  270. data/public/docs/authentication/guides/index.md +24 -0
  271. data/public/docs/authentication/guides/migration.md +435 -0
  272. data/public/docs/authentication/guides/oauth2.md +252 -0
  273. data/public/docs/authentication/guides/oidc.md +241 -0
  274. data/public/docs/authentication/guides/overview.md +155 -0
  275. data/public/docs/authentication/guides/secure_storage.md +301 -0
  276. data/public/docs/authentication/guides/service_account.md +228 -0
  277. data/public/docs/authentication/guides/token_lifecycle.md +295 -0
  278. data/public/docs/authentication/guides/web_ui_integration.md +504 -0
  279. data/public/docs/authentication/index.md +58 -0
  280. data/public/docs/authentication/troubleshooting/credential_storage.md +550 -0
  281. data/public/docs/authentication/troubleshooting/environment_variables.md +540 -0
  282. data/public/docs/authentication/troubleshooting/index.md +11 -0
  283. data/public/docs/authentication/troubleshooting/oauth2_issues.md +220 -0
  284. data/public/docs/authentication/troubleshooting/oidc_issues.md +412 -0
  285. data/public/docs/authentication/troubleshooting/token_refresh.md +338 -0
  286. data/public/docs/cli/legate_cli_usage.md +363 -0
  287. data/public/docs/core_concepts/legate_agent_lifecycle.md +124 -0
  288. data/public/docs/core_concepts/legate_architecture_overview.md +110 -0
  289. data/public/docs/core_concepts/legate_configuration.md +116 -0
  290. data/public/docs/core_concepts/legate_definition_store.md +102 -0
  291. data/public/docs/core_concepts/legate_planner.md +94 -0
  292. data/public/docs/core_concepts/legate_session_service.md +104 -0
  293. data/public/docs/error_handling/legate_error_handling.md +122 -0
  294. data/public/docs/examples.md +199 -0
  295. data/public/docs/getting_started.md +111 -0
  296. data/public/docs/guides/agentic_agents.md +137 -0
  297. data/public/docs/guides/ai_code_generators.md +437 -0
  298. data/public/docs/guides/auto_loading.md +326 -0
  299. data/public/docs/guides/configuring_agent_webhooks.md +219 -0
  300. data/public/docs/guides/http_client_usage.md +264 -0
  301. data/public/docs/guides/llm_providers.md +137 -0
  302. data/public/docs/guides/mcp_client_integration.md +232 -0
  303. data/public/docs/guides/mcp_server_exposure.md +206 -0
  304. data/public/docs/guides/rails_integration.md +128 -0
  305. data/public/docs/guides/sending_outbound_webhooks.md +227 -0
  306. data/public/docs/guides/streaming.md +112 -0
  307. data/public/docs/guides/webhooks.md +288 -0
  308. data/public/docs/introduction.md +51 -0
  309. data/public/docs/multi_agent_systems/advanced_features.md +57 -0
  310. data/public/docs/multi_agent_systems/agent_delegation.md +190 -0
  311. data/public/docs/multi_agent_systems/agent_hierarchy.md +49 -0
  312. data/public/docs/multi_agent_systems/state_management.md +47 -0
  313. data/public/docs/multi_agent_systems/workflow_agents.md +72 -0
  314. data/public/docs/tools/legate_built_in_tools.md +332 -0
  315. data/public/docs/tools/legate_tools_and_registry.md +263 -0
  316. data/public/docs/web_ui/legate_web_ui.md +137 -0
  317. metadata +823 -0
@@ -0,0 +1,444 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ # Example of a Sequential Travel Planning Process Using Automatic Execution
5
+ # Run with: bundle exec ruby examples/advanced/workflows/travel_planner_auto_sequential.rb
6
+ #
7
+ # This example demonstrates how to create a sequential agent pattern where multiple specialized
8
+ # agents are executed in sequence automatically by the SequentialAgent class without explicit
9
+ # invocation of each sub-agent task.
10
+ #
11
+ # Key components of this example:
12
+ # 1. Multiple specialized agents: destination_research, itinerary_planner, budget_estimator, and trip_summarizer
13
+ # 2. A parent sequential agent that orchestrates the 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 SequentialAgent class automatically handles the execution flow and data passing between agents
16
+ #
17
+ # The architecture follows these principles:
18
+ # - Each agent is fully specialized for its task
19
+ # - Agents share the same session, allowing them to access each other's outputs
20
+ # - The parent-child relationship is explicitly established through the sub_agents parameter
21
+ # - The execution order is defined using sequential_sub_agents in the parent agent definition
22
+
23
+ require_relative '../../../lib/legate'
24
+ require_relative '../../../lib/legate/agents/sequential_agent' # Required for SequentialAgent
25
+
26
+ # Check if tty-spinner is installed
27
+ begin
28
+ require 'tty-spinner'
29
+ rescue LoadError
30
+ puts 'The tty-spinner gem is required for this example.'
31
+ puts 'Please install it with: gem install tty-spinner'
32
+ puts 'Or add it to your Gemfile and run: bundle install'
33
+ exit 1
34
+ end
35
+
36
+ # Clear any existing registrations to avoid conflicts
37
+ Legate::GlobalDefinitionRegistry.instance_variable_set(:@definitions, {})
38
+
39
+ puts '=== Travel Planner Auto-Sequential Process Example ==='
40
+ puts 'This example demonstrates a sequence of specialized agents to plan a trip'
41
+ puts 'The SequentialAgent class automatically handles the execution flow and data passing.'
42
+
43
+ # Ensure the echo tool is registered - all agents will use this
44
+ Legate::GlobalToolManager.register_tool(Legate::Tools::Echo) unless Legate::GlobalToolManager.registered_tool_names.include?(:echo)
45
+
46
+ # Ensure delegate_task tool is registered for agent delegation
47
+ Legate::GlobalToolManager.register_tool(Legate::Tools::AgentTool) unless Legate::GlobalToolManager.registered_tool_names.include?(:delegate_task)
48
+
49
+ # ----- Define Specialized Agents -----
50
+
51
+ # 1. Destination Research Agent
52
+ destination_agent_def = Legate::AgentDefinition.new.define do |a|
53
+ a.name :destination_research
54
+ a.description 'Researches and suggests destination options based on user preferences'
55
+ a.instruction <<~INSTRUCTION
56
+ You are a destination research specialist. Your task is to analyze the user's preferences and suggest 2-3 suitable destinations.
57
+
58
+ First, think about what destinations would be appropriate based on the user's preferences. Then, use the 'echo' tool to output your response.
59
+
60
+ Your echo response should follow this EXACT format:
61
+
62
+ # DESTINATION RECOMMENDATIONS
63
+
64
+ Based on your preferences, here are the destinations I recommend:
65
+
66
+ ## [Destination 1 Name]
67
+ - **Location**: [Region/Country]
68
+ - **Weather**: [Weather description for the time period]
69
+ - **Highlights**: [3-4 key attractions or experiences]
70
+ - **Best For**: [What makes this destination perfect for the user]
71
+
72
+ ## [Destination 2 Name]
73
+ - **Location**: [Region/Country]
74
+ - **Weather**: [Weather description for the time period]
75
+ - **Highlights**: [3-4 key attractions or experiences]
76
+ - **Best For**: [What makes this destination perfect for the user]
77
+
78
+ ## [Destination 3 Name] (optional)
79
+ - **Location**: [Region/Country]
80
+ - **Weather**: [Weather description for the time period]
81
+ - **Highlights**: [3-4 key attractions or experiences]
82
+ - **Best For**: [What makes this destination perfect for the user]
83
+
84
+ # RECOMMENDATION SUMMARY
85
+ [Brief explanation of why these destinations match the user's preferences]
86
+ INSTRUCTION
87
+ a.model_name 'gemini-3.5-flash'
88
+ a.output_key :destination_results
89
+ a.use_tool :echo
90
+ end
91
+
92
+ # 2. Itinerary Planning Agent
93
+ itinerary_agent_def = Legate::AgentDefinition.new.define do |a|
94
+ a.name :itinerary_planner
95
+ a.description 'Creates a detailed itinerary for the selected destination'
96
+ a.instruction <<~INSTRUCTION
97
+ You are an itinerary planner. Based on the destination information provided, create a 3-day itinerary for the most suitable destination.
98
+
99
+ First, analyze the destination information provided. Check the session state for the results from the destination_research agent.
100
+ Then, use the 'echo' tool to output your response.
101
+
102
+ Your echo response should follow this EXACT format:
103
+
104
+ # 3-DAY ITINERARY FOR [DESTINATION]
105
+
106
+ ## Day 1
107
+
108
+ **Morning**
109
+ - [Activity]: [Brief description]
110
+ - [Activity]: [Brief description]
111
+
112
+ **Afternoon**
113
+ - [Activity]: [Brief description]
114
+ - [Activity]: [Brief description]
115
+
116
+ **Evening**
117
+ - [Activity]: [Brief description]
118
+ - [Activity]: [Brief description]
119
+
120
+ ## Day 2
121
+
122
+ **Morning**
123
+ - [Activity]: [Brief description]
124
+ - [Activity]: [Brief description]
125
+
126
+ **Afternoon**
127
+ - [Activity]: [Brief description]
128
+ - [Activity]: [Brief description]
129
+
130
+ **Evening**
131
+ - [Activity]: [Brief description]
132
+ - [Activity]: [Brief description]
133
+
134
+ ## Day 3
135
+
136
+ **Morning**
137
+ - [Activity]: [Brief description]
138
+ - [Activity]: [Brief description]
139
+
140
+ **Afternoon**
141
+ - [Activity]: [Brief description]
142
+ - [Activity]: [Brief description]
143
+
144
+ **Evening**
145
+ - [Activity]: [Brief description]
146
+ - [Activity]: [Brief description]
147
+
148
+ # TRANSPORTATION TIPS
149
+ [Brief notes on getting around the destination]
150
+ INSTRUCTION
151
+ a.model_name 'gemini-3.5-flash'
152
+ a.output_key :itinerary_results
153
+ a.use_tool :echo
154
+ end
155
+
156
+ # 3. Budget Estimation Agent
157
+ budget_agent_def = Legate::AgentDefinition.new.define do |a|
158
+ a.name :budget_estimator
159
+ a.description 'Provides cost estimates for the planned trip'
160
+ a.instruction <<~INSTRUCTION
161
+ You are a travel budget specialist. Based on the destination and activities in the itinerary, provide a detailed cost estimate.
162
+
163
+ First, analyze the destination and itinerary information provided. Check the session state for the results from the destination_research and itinerary_planner agents.
164
+ Then, use the 'echo' tool to output your response.
165
+
166
+ Your echo response should follow this EXACT format:
167
+
168
+ # BUDGET ESTIMATE FOR [DESTINATION]
169
+
170
+ ## Estimated Total: $[AMOUNT] USD
171
+
172
+ ## Cost Breakdown
173
+
174
+ **Flights**
175
+ - Estimated cost: $[AMOUNT] USD
176
+ - Notes: [Brief notes about flight options/assumptions]
177
+
178
+ **Accommodation (3 nights)**
179
+ - Estimated cost: $[AMOUNT] USD ($[AMOUNT]/night)
180
+ - Type: [Hotel/Airbnb/etc.]
181
+ - Notes: [Brief notes about accommodation options]
182
+
183
+ **Daily Activities**
184
+ - Estimated cost: $[AMOUNT] USD
185
+ - Includes: [List of paid activities from itinerary]
186
+
187
+ **Food & Dining**
188
+ - Estimated cost: $[AMOUNT] USD ($[AMOUNT]/day)
189
+ - Includes: [Assumptions about meals]
190
+
191
+ **Local Transportation**
192
+ - Estimated cost: $[AMOUNT] USD
193
+ - Type: [Public transit/rental car/taxis/etc.]
194
+
195
+ **Miscellaneous**
196
+ - Estimated cost: $[AMOUNT] USD
197
+ - Includes: [Souvenirs, tips, unexpected expenses, etc.]
198
+
199
+ # MONEY-SAVING TIPS
200
+ - [Tip 1]
201
+ - [Tip 2]
202
+ - [Tip 3]
203
+ INSTRUCTION
204
+ a.model_name 'gemini-3.5-flash'
205
+ a.output_key :budget_results
206
+ a.use_tool :echo
207
+ end
208
+
209
+ # 4. Trip Summary Agent
210
+ summary_agent_def = Legate::AgentDefinition.new.define do |a|
211
+ a.name :trip_summarizer
212
+ a.description 'Creates a comprehensive trip summary from all previous results'
213
+ a.instruction <<~INSTRUCTION
214
+ You are a travel summary specialist. Create a concise, well-formatted trip summary that brings together all the information from the destination research, itinerary, and budget.
215
+
216
+ You are the final agent in a sequence of specialized travel planning agents. Your job is to summarize the outputs of the previous agents and create a final trip summary.
217
+
218
+ Check the session state for the results from all previous agents (destination_research, itinerary_planner, and budget_estimator).
219
+ Then, use the 'echo' tool to output your response.
220
+
221
+ Your echo response should follow this EXACT format:
222
+
223
+ # COMPLETE TRAVEL PLAN
224
+
225
+ ## Destination Overview
226
+ [Summarize key points about the destination(s) discussed in previous steps]
227
+
228
+ ## Trip Highlights
229
+ - [Highlight 1]
230
+ - [Highlight 2]
231
+ - [Highlight 3]
232
+
233
+ ## Budget Considerations
234
+ - **Daily Budget**: $[AMOUNT] USD
235
+ - **Main Expenses**: [Brief note on biggest expenses]
236
+ - **Savings Opportunities**: [Key money-saving tip]
237
+
238
+ ## Final Recommendations
239
+ [2-3 sentences with final personalized recommendations]
240
+
241
+ ## Additional Information
242
+ This trip plan was created by a sequence of specialized agents:
243
+ 1. Destination Research - Analyzed preferences and suggested destinations
244
+ 2. Itinerary Planning - Created daily activities
245
+ 3. Budget Estimation - Estimated costs
246
+ 4. Trip Summary - Combined all information (this output)
247
+ INSTRUCTION
248
+ a.model_name 'gemini-3.5-flash'
249
+ a.output_key :trip_summary
250
+ a.use_tool :echo
251
+ end
252
+
253
+ # 5. Parent Sequential Agent Definition
254
+ travel_planner_def = Legate::AgentDefinition.new.define do |a|
255
+ a.name :travel_planner
256
+ a.description 'Orchestrates the complete travel planning process'
257
+ a.instruction <<~INSTRUCTION
258
+ You are a travel planning coordinator that will oversee the entire process of planning a trip.
259
+
260
+ You will delegate specific tasks to specialized sub-agents in this sequence:
261
+ 1. Destination Research - The first agent will suggest suitable destinations based on user preferences
262
+ 2. Itinerary Planning - The second agent will create a detailed itinerary for the selected destination
263
+ 3. Budget Estimation - The third agent will calculate the estimated costs for the trip
264
+ 4. Trip Summary - The final agent will compile all information into a comprehensive travel plan
265
+
266
+ Your job is to coordinate this process and ensure all agents have the information they need.
267
+ INSTRUCTION
268
+ a.model_name 'gemini-3.5-flash'
269
+ a.output_key :complete_travel_plan
270
+ a.agent_type :sequential # Important! This tells Legate to use SequentialAgent
271
+ a.sequential_sub_agents :destination_research, :itinerary_planner, :budget_estimator, :trip_summarizer
272
+ end
273
+
274
+ # Register all agents globally
275
+ Legate::GlobalDefinitionRegistry.register(destination_agent_def)
276
+ Legate::GlobalDefinitionRegistry.register(itinerary_agent_def)
277
+ Legate::GlobalDefinitionRegistry.register(budget_agent_def)
278
+ Legate::GlobalDefinitionRegistry.register(summary_agent_def)
279
+ Legate::GlobalDefinitionRegistry.register(travel_planner_def)
280
+
281
+ # ----- Initialize and Run the Sequential Agent -----
282
+
283
+ puts "\nStarting the specialized travel planning process..."
284
+
285
+ # Create an in-memory session service that all agents will share
286
+ session_service = Legate::SessionService::InMemory.new
287
+
288
+ # Create session
289
+ session = session_service.create_session(app_name: 'travel_planner', user_id: 'example_user')
290
+ session_id = session.id
291
+ puts "Created session: #{session_id}\n\n"
292
+
293
+ # Define the travel planning request
294
+ 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."
295
+
296
+ puts 'Processing travel planning request...'
297
+ puts "User input: #{user_input}\n"
298
+
299
+ # Print the sequence information
300
+ puts 'This will use a SequentialAgent to execute 4 specialized agents:'
301
+ puts "1. Destination Research → 2. Itinerary Planning → 3. Budget Estimation → 4. Trip Summary\n"
302
+
303
+ # Create a multi-spinner for tracking all processes
304
+ spinners = TTY::Spinner::Multi.new('[:spinner] Travel Planning Process', format: :dots, success_mark: '✅', error_mark: '❌')
305
+
306
+ # Create instances of all the individual sub-agents
307
+ destination_agent = Legate::Agent.new(definition: destination_agent_def, session_service: session_service)
308
+ itinerary_agent = Legate::Agent.new(definition: itinerary_agent_def, session_service: session_service)
309
+ budget_agent = Legate::Agent.new(definition: budget_agent_def, session_service: session_service)
310
+ summary_agent = Legate::Agent.new(definition: summary_agent_def, session_service: session_service)
311
+
312
+ # Add the echo tool to each agent
313
+ [destination_agent, itinerary_agent, budget_agent, summary_agent].each do |agent|
314
+ agent.add_tool(Legate::Tools::Echo)
315
+ end
316
+
317
+ # Create the parent sequential agent instance with all sub-agents explicitly provided
318
+ travel_planner = Legate::Agents::SequentialAgent.new(
319
+ definition: travel_planner_def,
320
+ session_service: session_service,
321
+ sub_agents: [destination_agent, itinerary_agent, budget_agent, summary_agent]
322
+ )
323
+
324
+ # Start all agents
325
+ puts 'Starting all agents...'
326
+ destination_agent.start
327
+ itinerary_agent.start
328
+ budget_agent.start
329
+ summary_agent.start
330
+ travel_planner.start
331
+
332
+ # Create spinner for tracking progress
333
+ master_spinner = spinners.register('[:spinner] Total Progress')
334
+ master_spinner.auto_spin
335
+
336
+ # Create spinners for each sub-agent
337
+ destination_spinner = spinners.register('[:spinner] Destination Research')
338
+ itinerary_spinner = spinners.register('[:spinner] Itinerary Planning')
339
+ budget_spinner = spinners.register('[:spinner] Budget Estimation')
340
+ summary_spinner = spinners.register('[:spinner] Trip Summary')
341
+
342
+ # Start all spinners
343
+ destination_spinner.auto_spin
344
+ itinerary_spinner.auto_spin
345
+ budget_spinner.auto_spin
346
+ summary_spinner.auto_spin
347
+
348
+ # Run the sequential agent
349
+ begin
350
+ # The SequentialAgent automatically runs all sub-agents in sequence
351
+ # Each agent stores its output in the session state using its output_key
352
+ # Subsequent agents can access previous agents' outputs from the session state
353
+ result = travel_planner.run_task(
354
+ session_id: session_id,
355
+ user_input: user_input,
356
+ session_service: session_service
357
+ )
358
+
359
+ if result.content[:status] == :error
360
+ puts "Error in sequential execution: #{result.content[:error_message]}"
361
+ master_spinner.error
362
+ destination_spinner.error
363
+ itinerary_spinner.error
364
+ budget_spinner.error
365
+ summary_spinner.error
366
+ exit 1
367
+ end
368
+
369
+ # Mark all spinners as complete
370
+ destination_spinner.success
371
+ itinerary_spinner.success
372
+ budget_spinner.success
373
+ summary_spinner.success
374
+ master_spinner.success
375
+
376
+ # Get all session data directly
377
+ session = session_service.get_session(session_id: session_id)
378
+
379
+ # Print the raw session state for debugging purposes
380
+ puts "\nDEBUG: Session State Contents"
381
+ puts '----------------------------'
382
+ session.state.each do |key, value|
383
+ puts "#{key}: #{value.inspect[0..200]}..." if value
384
+ end
385
+ puts
386
+
387
+ # Display the final trip summary
388
+ puts "\n=== Travel Planning Complete ===\n\n"
389
+
390
+ puts 'SEQUENTIAL AGENT RESULTS'
391
+ puts '------------------------'
392
+ puts "The sequential agent successfully executed all sub-agents in sequence.\n\n"
393
+
394
+ puts 'STEP 1: DESTINATION RESEARCH'
395
+ puts '----------------------------'
396
+ if session.state[:destination_results] && session.state[:destination_results]['result']
397
+ puts session.state[:destination_results]['result']
398
+ else
399
+ puts '(No destination research results available)'
400
+ end
401
+ puts "\n"
402
+
403
+ puts 'STEP 2: ITINERARY PLANNING'
404
+ puts '-------------------------'
405
+ if session.state[:itinerary_results] && session.state[:itinerary_results]['result']
406
+ puts session.state[:itinerary_results]['result']
407
+ else
408
+ puts '(No itinerary planning results available)'
409
+ end
410
+ puts "\n"
411
+
412
+ puts 'STEP 3: BUDGET ESTIMATION'
413
+ puts '-------------------------'
414
+ if session.state[:budget_results] && session.state[:budget_results]['result']
415
+ puts session.state[:budget_results]['result']
416
+ else
417
+ puts '(No budget estimation results available)'
418
+ end
419
+ puts "\n"
420
+
421
+ puts 'STEP 4: FINAL TRAVEL SUMMARY'
422
+ puts '---------------------------'
423
+ if session.state[:trip_summary] && session.state[:trip_summary]['result']
424
+ puts session.state[:trip_summary]['result']
425
+ else
426
+ puts '(No trip summary available)'
427
+ end
428
+ puts "\n"
429
+
430
+ puts 'Note: This example uses the built-in SequentialAgent to automatically execute all sub-agents in sequence.'
431
+ puts 'The SequentialAgent class handles the flow of execution and ensures each agent has access to the outputs'
432
+ puts 'of previous agents through the shared session state, without requiring any custom implementation.'
433
+ rescue StandardError => e
434
+ puts "Error during execution: #{e.message}"
435
+ puts e.backtrace.join("\n")
436
+ master_spinner.error if master_spinner
437
+ destination_spinner.error if destination_spinner
438
+ itinerary_spinner.error if itinerary_spinner
439
+ budget_spinner.error if budget_spinner
440
+ summary_spinner.error if summary_spinner
441
+ exit 1
442
+ end
443
+
444
+ puts "\n=== Travel Planner Example Complete ==="