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,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.
|