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,199 @@
1
+ # Examples Guide
2
+
3
+ Legate ships with a curated set of examples that walk you through every major feature of the framework. Each example is self-contained and can be run directly from the project root.
4
+
5
+ ```bash
6
+ bundle exec ruby examples/01_simple_agent.rb
7
+ ```
8
+
9
+ > **Note:** Examples that call the Gemini LLM require a `GOOGLE_API_KEY` environment variable. See `.env.example` for the full list.
10
+
11
+ ---
12
+
13
+ ## Core Examples
14
+
15
+ These numbered examples form a progressive learning path — start at 00 (the `agent.ask` quickstart) and work your way up.
16
+
17
+ ### Getting Started
18
+
19
+ #### 00 — Quickstart (`agent.ask`)
20
+ `examples/00_quickstart.rb`
21
+
22
+ The shortest path: define an agent and get an answer with `agent.ask('…').answer`. Shows the `Event` result accessors (`#answer` / `#success?` / `#error_message`), streaming progress via a block, and how to continue a conversation with `session_id:`. Start here.
23
+
24
+ #### 01 — Simple Agent
25
+ `examples/01_simple_agent.rb`
26
+
27
+ The "hello world" of Legate using the **explicit** lifecycle that `ask` automates: define → instantiate → start → run_task → stop, with a single agent and the built-in Echo tool. Reach for this when you need fine control over sessions and lifecycle.
28
+
29
+ #### 02 — Multi-Tool Agent
30
+ `examples/02_multi_tool_agent.rb`
31
+
32
+ Registers multiple tools (Echo, Calculator, CatFacts, RandomNumber) on a single agent and demonstrates how the Gemini planner selects the appropriate tool for each request. Also shows agent-to-agent delegation via the built-in `delegate_task` tool.
33
+
34
+ #### 03 — Custom Tool
35
+ `examples/03_custom_tool.rb`
36
+
37
+ How to build your own tool from scratch using the `Legate::Tool` DSL. Defines parameters with types, implements `perform_execution`, registers the tool globally, uses it both directly and through an agent.
38
+
39
+ ### Core Patterns
40
+
41
+ #### 04 — Agent Instructions
42
+ `examples/04_agent_instructions.rb`
43
+
44
+ Shows how the `instruction` field acts as a system prompt that guides the planner's behavior. Runs two tasks against the same agent — one that fits the instructions and one that doesn't — to demonstrate how instructions shape agent responses.
45
+
46
+ #### 05 — State & Sessions
47
+ `examples/05_state_and_sessions.rb`
48
+
49
+ Demonstrates session state management: creating sessions with initial state, reading and writing state from tools via `ToolContext`, scoped state keys (`user:`, `app:`, `temp:`), and inspecting event history after task execution.
50
+
51
+ #### 06 — Callbacks
52
+ `examples/06_callbacks.rb`
53
+
54
+ Registers all six lifecycle callbacks (`before_agent`, `after_agent`, `before_model`, `after_model`, `before_tool`, `after_tool`) on an agent and logs each invocation. Shows how callbacks can inspect and pass through context, prompts, and tool parameters.
55
+
56
+ ### Async & Jobs
57
+
58
+ #### 07 — Async Jobs
59
+ `examples/07_async_jobs.rb`
60
+
61
+ Uses the `SleepyTool` (a `BaseAsyncJobTool` subclass) to start a background job, then checks its status with `check_job_status`. Demonstrates the `:pending` → `:success` lifecycle for long-running operations.
62
+
63
+ ### Multi-Agent Systems
64
+
65
+ #### 08 — Loop Agent
66
+ `examples/08_loop_agent.rb`
67
+
68
+ Creates a `LoopAgent` that runs sub-agents in a cycle until a termination condition is met (or max iterations are reached). Uses a counter agent and a condition-checking agent to demonstrate state-driven loop control.
69
+
70
+ #### 09 — Sequential Workflow
71
+ `examples/09_sequential_workflow.rb`
72
+
73
+ Defines a pipeline of three agents (data gatherer → data processor → report writer) that execute in order using the `:sequential` agent type. Each agent stores its output via `output_key` for the next agent to consume.
74
+
75
+ #### 10 — Parallel Workflow
76
+ `examples/10_parallel_workflow.rb`
77
+
78
+ Defines two analyst agents that run concurrently using the `:parallel` agent type. Shows how to fan out work across multiple agents and merge their results.
79
+
80
+ #### 11 — Agent Delegation
81
+ `examples/11_agent_delegation.rb`
82
+
83
+ Sets up a manager agent that can delegate math problems to a specialist agent using `can_delegate_to`. Demonstrates the agent hierarchy and task handoff pattern.
84
+
85
+ ### Integration
86
+
87
+ #### 12 — HTTP Client Tool
88
+ `examples/12_http_client_tool.rb`
89
+
90
+ Builds a complete HTTP API tool using the `Legate::Tools::Base::HttpClient` mixin. Connects to JSONPlaceholder to demonstrate GET and POST requests, JSON parsing, and error handling for missing parameters and invalid actions.
91
+
92
+ #### 13 — Authentication
93
+ `examples/13_authentication.rb`
94
+
95
+ Covers HTTP Bearer authentication end-to-end: creating credentials, exchanging tokens, applying auth to requests, using the Excon middleware, and integrating auth into a custom tool. Uses httpbin.org for live verification.
96
+
97
+ #### 14 — MCP Client
98
+ `examples/14_mcp_client.rb`
99
+
100
+ Configures an agent to connect to an external MCP server (the `@modelcontextprotocol/server-filesystem` package) via stdio. Shows MCP server configuration, tool discovery, and running tasks that use external MCP tools alongside native Legate tools.
101
+
102
+ #### 15 — MCP Server
103
+ `examples/15_mcp_server.rb`
104
+
105
+ Wraps the built-in Calculator tool using `LegateToolAdapter` and exposes it on a `fast-mcp` STDIO server. Demonstrates how to make any Legate tool available to external MCP clients.
106
+
107
+ #### 16 — Webhooks
108
+ `examples/16_webhooks.rb`
109
+
110
+ Sends an HMAC-signed webhook payload to an external URL using the built-in `WebhookTool`. Uses [webhook.site](https://webhook.site) for easy testing. Demonstrates HMAC-SHA256 payload signing, custom headers, and delivery verification.
111
+
112
+ ---
113
+
114
+ ## Advanced Examples
115
+
116
+ The `examples/advanced/` directory contains deeper explorations of specific subsystems. These are useful as reference but assume familiarity with the core examples above.
117
+
118
+ ### Authentication (`advanced/auth/`)
119
+
120
+ In-depth authentication patterns beyond the basics in example 13:
121
+
122
+ | File | Description |
123
+ |------|-------------|
124
+ | `oauth2_auth.rb` | Full OAuth 2.0 authorization code flow |
125
+ | `oidc_auth.rb` | OpenID Connect authentication |
126
+ | `service_account.rb` | Service account / client credentials flow |
127
+ | `fiber_auth_example.rb` | Non-blocking auth using Ruby Fibers |
128
+ | `fiber_oidc_example.rb` | Fiber-based OIDC flow |
129
+ | `token_lifecycle_example.rb` | Token refresh, expiry, and lifecycle management |
130
+ | `cookie_auth_tool.rb` | Cookie-based authentication |
131
+ | `excon_middleware.rb` | Custom Excon middleware for auth |
132
+ | `excon_middleware_auth.rb` | Auth-specific Excon middleware |
133
+ | `httpbin_bearer_tool.rb` | Bearer auth against httpbin.org |
134
+ | `openweather_api.rb` | Real-world API key auth (OpenWeather) |
135
+ | `openweather_tool.rb` | Tool wrapping the OpenWeather API |
136
+ | `query_param_middleware_test.rb` | Query parameter auth scheme |
137
+ | `test_with_httpbin.rb` | Auth integration testing with httpbin |
138
+ | `custom_auth_flows_example.rb` | Building custom auth schemes |
139
+
140
+ ### Multi-Agent Systems (`advanced/mas/`)
141
+
142
+ Additional orchestration patterns beyond examples 08–11:
143
+
144
+ | File | Description |
145
+ |------|-------------|
146
+ | `fixed_delegation_example.rb` | Delegation with explicit agent routing |
147
+ | `proper_delegation_example.rb` | Production-style delegation patterns |
148
+ | `loop_workflow.rb` | Loop agent in a workflow context |
149
+ | `mock_planner.rb` | Testing agents with a mock planner |
150
+
151
+ ### MCP (`advanced/mcp/`)
152
+
153
+ Additional MCP server configurations beyond examples 14–15:
154
+
155
+ | File | Description |
156
+ |------|-------------|
157
+ | `mcp_server_rack.rb` | MCP server running on Rack |
158
+ | `mcp_server_async.rb` | Async MCP server |
159
+ | `mcp_server_async_tools.rb` | MCP server with async tool execution |
160
+ | `mcp_server_legate_agent.rb` | Expose a full agent (not just a tool) via MCP |
161
+ | `mcp_resource_server_example.rb` | MCP server with resource discovery |
162
+ | `legate_mcp_server_resource_example.rb` | Resource handling in MCP servers |
163
+
164
+ ### Webhooks (`advanced/webhooks/`)
165
+
166
+ End-to-end webhook patterns beyond example 16:
167
+
168
+ | File | Description |
169
+ |------|-------------|
170
+ | `webhook_receiver_agent.rb` | Agent that listens for incoming webhooks |
171
+ | `webhook_e2e_runner.rb` | End-to-end webhook sender + receiver test |
172
+
173
+ ### Workflows (`advanced/workflows/`)
174
+
175
+ Complex multi-agent workflow examples:
176
+
177
+ | File | Description |
178
+ |------|-------------|
179
+ | `travel_planner_sequential.rb` | 4-agent sequential travel planner with TTY spinners |
180
+ | `travel_planner_parallel.rb` | Travel planner with parallel research agents |
181
+ | `travel_planner_auto_sequential.rb` | Auto-wired sequential travel planner |
182
+ | `task_refinement_loop_agent.rb` | Iterative text refinement using a 3-agent loop |
183
+
184
+ ### Other (`advanced/`)
185
+
186
+ | File | Description |
187
+ |------|-------------|
188
+ | `callback_monitoring.rb` | Production-style monitoring with callbacks (metrics, timers, content filtering) |
189
+ | `random_calculator.rb` | Multi-step planning with random numbers and calculator |
190
+ | `sleep_agent.rb` | Async job agent with manual polling |
191
+
192
+ ---
193
+
194
+ ## Support Files
195
+
196
+ The `examples/tools/` directory contains shared tool definitions used by the examples:
197
+
198
+ - `sleepy_tool.rb` — A `BaseAsyncJobTool` subclass that simulates long-running work (used by examples 07 and the advanced sleep agent)
199
+ - `oauth2_example.rb` — OAuth2 tool helper for auth examples
@@ -0,0 +1,111 @@
1
+ # Getting Started with Legate
2
+
3
+ This guide will walk you through setting up your first Legate project using the `skaffold` command.
4
+
5
+ ## Prerequisites
6
+
7
+ Before you begin, ensure you have the following installed:
8
+
9
+ * **Ruby** (version 3.4 or higher is required)
10
+ * **Bundler** (`gem install bundler`)
11
+
12
+ ## 1. Install the Legate Gem
13
+
14
+ First, install the `legate` gem globally or add it to your Gemfile.
15
+
16
+ ```bash
17
+ gem install legate
18
+ ```
19
+
20
+ ## 2. Create a New Project
21
+
22
+ The easiest way to start is by using the `skaffold` command. This will generate a complete directory structure with sample files.
23
+
24
+ ```bash
25
+ legate skaffold my-awesome-agent
26
+ ```
27
+
28
+ This will create a directory named `my-awesome-agent` with the following structure:
29
+
30
+ * `Gemfile`: Dependency definitions.
31
+ * `config.ru`: Configuration for running the Legate Web UI.
32
+ * `agents/`: Directory for your agent definitions.
33
+ * `hello_world_agent.rb`: A simple sample agent that uses the sample tool.
34
+ * `tools/`: Directory for custom tools.
35
+ * `sample_tool.rb`: A sample tool implementation.
36
+ * `.env.example`: Template for environment variables.
37
+ * `bin/`: Helper scripts.
38
+ * `console`: Starts an IRB console with your agents loaded.
39
+
40
+ ## 3. Configure Your Environment
41
+
42
+ Navigate into your new project directory:
43
+
44
+ ```bash
45
+ cd my-awesome-agent
46
+ ```
47
+
48
+ Copy the example environment file:
49
+
50
+ ```bash
51
+ cp .env.example .env
52
+ ```
53
+
54
+ Open `.env` and add your configuration, specifically your `GOOGLE_API_KEY` if you plan to use Gemini models.
55
+
56
+ ```bash
57
+ GOOGLE_API_KEY=your_actual_api_key_here
58
+ ```
59
+
60
+ ## 4. Install Dependencies
61
+
62
+ Run Bundler to install the required gems:
63
+
64
+ ```bash
65
+ bundle install
66
+ ```
67
+
68
+ ## 5. Run the Application
69
+
70
+ You can now start the Legate Web UI to interact with your agents.
71
+
72
+ ```bash
73
+ bundle exec legate web start
74
+ ```
75
+
76
+ By default, this starts the server at `http://localhost:4567` (override with `--port`). Open this URL in your browser to see the Legate dashboard.
77
+
78
+ ## 6. Interact with Your Agent
79
+
80
+ **From the Web UI:**
81
+
82
+ 1. In the Web UI, go to the "Agents" tab.
83
+ 2. You should see the `hello_world` agent.
84
+ 3. Click "Start Chat" (or similar).
85
+ 4. Type "Say hello!" and see the agent respond.
86
+
87
+ **From Ruby code** — the quickest path is `Agent#ask`, which starts the agent,
88
+ runs the task, and returns the final event:
89
+
90
+ ```ruby
91
+ require 'legate'
92
+
93
+ agent = Legate::Agent.new(definition: Legate::AgentDefinition.new.define do |a|
94
+ a.name :hello_world
95
+ a.description 'Greets the user.'
96
+ a.instruction 'Say hello back to the user.'
97
+ a.use_tool :echo
98
+ end)
99
+
100
+ puts agent.ask('Say hello!').answer
101
+ ```
102
+
103
+ Call `.answer` for the result, or `.success?` / `.error_message` to branch on the
104
+ outcome. Pass `session_id:` to continue a conversation, and a block to watch
105
+ progress live (`agent.ask('…') { |event| ... }`).
106
+
107
+ ## Next Steps
108
+
109
+ * **Create more agents:** Use `legate agent generate my_new_agent` to create more agents.
110
+ * **Learn about Tools:** Check out the [Built-in Tools Reference](./tools/legate_built_in_tools) to see what tools are available.
111
+ * **Deploy:** When you're ready, use `legate deployment generate` to prepare for cloud deployment.
@@ -0,0 +1,137 @@
1
+ # Agentic Agents (ReAct loop)
2
+
3
+ By default a Legate LLM agent **plans once, then executes**: the planner asks the
4
+ model for a complete list of tool steps up front, and the agent runs them in
5
+ order. That is fast and predictable, but it can't react — if step 2 returns
6
+ something unexpected, step 3 still runs the original plan.
7
+
8
+ The **agentic** strategy replaces the single up-front plan with an
9
+ observe → think → act loop (the "ReAct" pattern): the agent takes **one** action,
10
+ observes the result, then decides the next action with that result in hand. It
11
+ keeps going until the model produces a final answer.
12
+
13
+ ## When to use it
14
+
15
+ | Use **`:plan`** (default) when… | Use **`:react`** when… |
16
+ |---|---|
17
+ | The steps are known ahead of time | Later steps depend on earlier results |
18
+ | You want the fewest LLM round-trips | The task is exploratory or multi-step |
19
+ | The task is a single tool call | A tool may fail and the agent should adapt |
20
+
21
+ `:react` makes more LLM calls (one per step) in exchange for the ability to
22
+ course-correct. For a one-shot tool call, `:plan` is cheaper and just as good.
23
+
24
+ ## Enabling it
25
+
26
+ ### In the DSL
27
+
28
+ ```ruby
29
+ definition = Legate::AgentDefinition.new
30
+ definition.define do |a|
31
+ a.name :researcher
32
+ a.description 'Looks things up step by step.'
33
+ a.instruction 'Answer the user by searching and reading, one step at a time.'
34
+ a.use_tool :search
35
+ a.use_tool :fetch
36
+ a.planning_strategy :react # opt in; omit (or :plan) for the default
37
+ end
38
+ ```
39
+
40
+ `planning_strategy` accepts `:plan` (default) or `:react`. It applies to `:llm`
41
+ agents; it has no effect on workflow agents (`:sequential`, `:parallel`, `:loop`).
42
+
43
+ ### In the web UI
44
+
45
+ On an agent's detail page, open **Edit Type**. Alongside *Agent Type* there is a
46
+ **Planning Strategy** dropdown — choose *ReAct (agentic loop)* and save. The same
47
+ control is available when creating a new agent. The agent's type panel shows a
48
+ **ReAct** tag when the loop is active.
49
+
50
+ ## How the loop works
51
+
52
+ Each turn, the planner sends the model the user's request plus every observation
53
+ so far, and asks for the single next action as a JSON object:
54
+
55
+ ```jsonc
56
+ // call a tool
57
+ {"thought": "I should search first", "action": "tool",
58
+ "tool_name": "search", "tool_input": {"q": "ruby agents"}}
59
+
60
+ // finish
61
+ {"thought": "I have enough to answer", "action": "final",
62
+ "answer": "Here's what I found…"}
63
+ ```
64
+
65
+ 1. **Think** — `Planner#reason_next_action` asks the adapter for the next action
66
+ and turns the answer into a `Legate::Agentic::Decision`. How it asks depends on
67
+ the provider (see [Native function calling](#native-function-calling) below):
68
+ either a native tool call or the JSON object above parsed out of the response.
69
+ 2. **Act** — if the decision is a tool call, the agent runs it through the same
70
+ executor, event logging, and state-delta machinery as the default strategy.
71
+ Tool requests and results are appended to the session exactly as usual.
72
+ 3. **Observe** — the (sanitized) result is appended to the running list of
73
+ observations and fed back into the next turn's prompt.
74
+
75
+ The loop ends when the model returns `"action": "final"`; the answer becomes the
76
+ agent's result event, identical in shape to a `:plan` run.
77
+
78
+ ### Tool errors don't abort the loop
79
+
80
+ If a tool returns an error — or raises — the failure is captured as an
81
+ **observation** rather than ending the turn. The model sees the error on the next
82
+ step and can retry with different input, try another tool, or give up gracefully.
83
+ This is the headline advantage over plan-then-execute, which stops at the first
84
+ failed step.
85
+
86
+ ### Safeguards
87
+
88
+ - **Iteration cap.** The loop runs at most `DEFAULT_MAX_ITERATIONS` (8) steps, so
89
+ a confused agent can't loop forever. If it hasn't finished by then it makes one
90
+ best-effort pass — asking the model to answer from the observations gathered —
91
+ and returns that as the result. If even that can't be produced (e.g. no LLM
92
+ available), it returns an error result noting the cap.
93
+ - **Loop-breaker.** If the model repeats the *exact same* action and gets the
94
+ *exact same* result, re-running won't help — the loop stops early (again with a
95
+ best-effort summary) instead of spinning through the rest of the budget.
96
+ - **Observation truncation.** Tool outputs are trimmed before being fed back so a
97
+ big result doesn't blow up the next turn's prompt: deeply-nested structures
98
+ become `[Complex Result Structure]`, and long strings are cut to ~2,000
99
+ characters with a `[truncated N chars]` marker. Simple scalar results pass
100
+ through intact.
101
+ - **Tool-name validation.** A tool name from the model is validated against the
102
+ agent's registry (and its delegation targets) before it is interned or run —
103
+ the same guard the multi-step planner uses — so untrusted model output can't
104
+ invoke arbitrary tools.
105
+
106
+ ## Native function calling
107
+
108
+ How the loop *asks* for the next action depends on the LLM adapter:
109
+
110
+ - **Adapters with native function calling** (Gemini, the default) receive the
111
+ tools as structured function declarations and return a real function call. No
112
+ JSON is parsed out of prose — the tool name and arguments come back typed,
113
+ which is markedly more reliable. This happens automatically; you don't
114
+ configure anything.
115
+ - **Adapters without it** (Ollama, custom adapters) fall back to the JSON-object
116
+ prompt shown above. Same `Decision`, same loop — only the mechanism differs.
117
+
118
+ An adapter advertises support via `supports_function_calling?` and implements
119
+ `generate_with_tools(prompt, tools:)` (see
120
+ [LLM Providers](llm_providers)). The validation, safeguards, and everything
121
+ downstream are identical on both paths; the agent's registered tools and its
122
+ delegation targets are offered either way.
123
+
124
+ > Scope: native function calling powers the **agentic** next-action decision. The
125
+ > default plan-then-execute planner still uses JSON-mode output.
126
+
127
+ ## What stays the same
128
+
129
+ Switching strategies does **not** change anything else about your agent. Tools,
130
+ sessions, state deltas, callbacks (`before_tool`, `after_tool`, `before_model`,
131
+ …), MCP integration, and the final result-event shape all behave identically.
132
+ `:react` is purely a change in *how the next action is chosen*.
133
+
134
+ ## Related
135
+
136
+ - [LLM Providers](llm_providers) — the adapter the loop reasons through.
137
+ - [Legate Planner](../core_concepts/legate_planner) — the default plan-then-execute flow.