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,140 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# If running from project root: bundle exec ruby examples/02_multi_tool_agent.rb
|
|
5
|
+
require_relative '../lib/legate'
|
|
6
|
+
|
|
7
|
+
# Load .env and map GEMINI_API_KEY -> GOOGLE_API_KEY (as the `legate` CLI does).
|
|
8
|
+
# The library never reads .env on its own; an application must opt in.
|
|
9
|
+
Legate.load_environment
|
|
10
|
+
|
|
11
|
+
puts '--- Multi-Tool Agent Example ---'
|
|
12
|
+
|
|
13
|
+
# 1. --- Agent Definitions ---
|
|
14
|
+
|
|
15
|
+
# Definition for the main multi-tool agent
|
|
16
|
+
multi_tool_agent_definition = Legate::AgentDefinition.new.define do |a|
|
|
17
|
+
a.name :multi_tool_agent
|
|
18
|
+
a.description 'An agent that can use multiple tools including echo, calculator, cat facts, the current time, and task delegation'
|
|
19
|
+
a.instruction 'You are a versatile assistant. Use the appropriate tool for the user\'s request. For calculations, use the calculator. For cat facts, use cat_facts. For the current date or time, use current_time. To delegate, use delegate_task.'
|
|
20
|
+
a.use_tool :echo
|
|
21
|
+
a.use_tool :calculator
|
|
22
|
+
a.use_tool :cat_facts # Provided by Legate::Tools::CatFacts
|
|
23
|
+
a.use_tool :current_time # Provided by Legate::Tools::CurrentTime
|
|
24
|
+
a.use_tool :delegate_task # Provided by Legate::Tools::AgentTool
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Definition for the calculator agent that will be used for delegation
|
|
28
|
+
calculator_agent_definition = Legate::AgentDefinition.new.define do |a|
|
|
29
|
+
a.name :calculator_agent
|
|
30
|
+
a.description 'A calculator agent that can perform basic arithmetic operations'
|
|
31
|
+
a.instruction 'You are a calculator. Perform the requested calculation.'
|
|
32
|
+
a.model_name 'gemini-3.5-flash' # Optional: specify model for this agent
|
|
33
|
+
a.use_tool :calculator
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# --- Register Calculator Agent Definition for AgentTool --- >
|
|
37
|
+
# AgentTool will look up definitions in the GlobalDefinitionRegistry.
|
|
38
|
+
Legate::GlobalDefinitionRegistry.register(calculator_agent_definition)
|
|
39
|
+
puts "\nRegistered definition for '#{calculator_agent_definition.name}' in Legate::GlobalDefinitionRegistry."
|
|
40
|
+
# <----------------------------------------------------------
|
|
41
|
+
|
|
42
|
+
# Ensure all necessary tools are globally available/registered.
|
|
43
|
+
# Standard tools like Echo, Calculator, AgentTool (delegate_task) are usually auto-registered.
|
|
44
|
+
# For custom tools like CatFactsTool and RandomNumberTool, ensure they are loaded and registered
|
|
45
|
+
# e.g., via `require` and `Legate::GlobalToolManager.register_tool(CatFactsTool)` if not already.
|
|
46
|
+
# This example assumes they are available to the GlobalToolManager.
|
|
47
|
+
|
|
48
|
+
# 2. --- Agent Instantiation ---
|
|
49
|
+
agent = Legate::Agent.new(definition: multi_tool_agent_definition)
|
|
50
|
+
|
|
51
|
+
puts "\nAgent '#{agent.name}' created with tools:"
|
|
52
|
+
agent.tools.each { |tool| puts " - #{tool.name}" }
|
|
53
|
+
|
|
54
|
+
# 3. --- Start Agent ---
|
|
55
|
+
agent.start
|
|
56
|
+
puts "\nAgent started:"
|
|
57
|
+
puts " - #{agent.name}: Running: #{agent.running?}"
|
|
58
|
+
|
|
59
|
+
# 4. --- Session Setup ---
|
|
60
|
+
session_service = Legate::SessionService::InMemory.new
|
|
61
|
+
session = session_service.create_session(app_name: agent.name, user_id: 'example_user')
|
|
62
|
+
session_id = session.id
|
|
63
|
+
puts "\nCreated session: #{session_id}"
|
|
64
|
+
|
|
65
|
+
# 5. --- Task Execution Examples ---
|
|
66
|
+
tasks = [
|
|
67
|
+
'Echo this message: Hello from multi-tool agent!',
|
|
68
|
+
'Calculate 15 * 7',
|
|
69
|
+
'Get me a cat fact',
|
|
70
|
+
'What is the current date and time?',
|
|
71
|
+
'Delegate this task to calculator_agent: what is 20 / 4'
|
|
72
|
+
]
|
|
73
|
+
|
|
74
|
+
# Array to store results for summary table
|
|
75
|
+
task_results = []
|
|
76
|
+
|
|
77
|
+
tasks.each_with_index do |task, index|
|
|
78
|
+
task_num = index + 1
|
|
79
|
+
puts "\n" + '=' * 40
|
|
80
|
+
puts "--- Task #{task_num}: '#{task}' ---"
|
|
81
|
+
puts '=' * 40
|
|
82
|
+
|
|
83
|
+
outcome_message = '[Execution Error]'
|
|
84
|
+
begin
|
|
85
|
+
result_event = agent.run_task(
|
|
86
|
+
session_id: session_id,
|
|
87
|
+
user_input: task,
|
|
88
|
+
session_service: session_service
|
|
89
|
+
)
|
|
90
|
+
|
|
91
|
+
# --- Extract final outcome for summary --- #
|
|
92
|
+
if result_event.is_a?(Legate::Event) && result_event.content.is_a?(Hash)
|
|
93
|
+
content = result_event.content
|
|
94
|
+
if content[:status] == :success
|
|
95
|
+
final_result = content[:result]
|
|
96
|
+
# Handle nested result from delegation
|
|
97
|
+
outcome_message = if final_result.is_a?(Hash) && final_result.key?(:status) && final_result[:status] == :success
|
|
98
|
+
"Success: #{final_result[:result]}"
|
|
99
|
+
else
|
|
100
|
+
"Success: #{final_result}"
|
|
101
|
+
end
|
|
102
|
+
elsif content[:status] == :error
|
|
103
|
+
outcome_message = "Error: #{content[:error_message]}"
|
|
104
|
+
else # Pending or other statuses
|
|
105
|
+
outcome_message = "Status: #{content[:status]}"
|
|
106
|
+
outcome_message += " (#{content[:message]})" if content[:message]
|
|
107
|
+
end
|
|
108
|
+
else
|
|
109
|
+
outcome_message = "[Unexpected Result Format]: #{result_event.inspect}"
|
|
110
|
+
end
|
|
111
|
+
rescue StandardError => e
|
|
112
|
+
outcome_message = "[Execution Error]: #{e.message}"
|
|
113
|
+
puts "\nError executing Task #{task_num}: #{e.class} - #{e.message}"
|
|
114
|
+
puts e.backtrace.first(5).join("\n")
|
|
115
|
+
end
|
|
116
|
+
# Store the result
|
|
117
|
+
task_results << { task: task, outcome: outcome_message }
|
|
118
|
+
puts '=' * 40 # End separator for this task's logs
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
# 6. --- Print Summary Table --- #
|
|
122
|
+
puts "\n" + '#' * 50
|
|
123
|
+
puts '### Task Execution Summary ###'
|
|
124
|
+
puts '#' * 50
|
|
125
|
+
# Determine column width (simple approach)
|
|
126
|
+
max_task_len = task_results.map { |r| r[:task].length }.max || 40
|
|
127
|
+
puts "
|
|
128
|
+
| #{'Task'.ljust(max_task_len)} | Outcome |"
|
|
129
|
+
puts "|#{'-' * (max_task_len + 2)}|---------------------------------|"
|
|
130
|
+
task_results.each do |r|
|
|
131
|
+
puts "| #{r[:task].ljust(max_task_len)} | #{r[:outcome]} "
|
|
132
|
+
end
|
|
133
|
+
puts ''
|
|
134
|
+
|
|
135
|
+
# 7. --- Stop Agent --- #
|
|
136
|
+
agent.stop
|
|
137
|
+
puts "\nAgents stopped:"
|
|
138
|
+
puts " - #{agent.name}: Running: #{agent.running?}"
|
|
139
|
+
|
|
140
|
+
puts "\n--- Example Complete ---"
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# Example: Creating a Custom Tool
|
|
5
|
+
#
|
|
6
|
+
# This example shows how to build a custom tool from scratch using the
|
|
7
|
+
# Legate::Tool DSL: define parameters, implement perform_execution,
|
|
8
|
+
# and wire it into an agent.
|
|
9
|
+
#
|
|
10
|
+
# Run with: bundle exec ruby examples/03_custom_tool.rb
|
|
11
|
+
|
|
12
|
+
require_relative '../lib/legate'
|
|
13
|
+
|
|
14
|
+
# Load .env and map GEMINI_API_KEY -> GOOGLE_API_KEY (as the `legate` CLI does).
|
|
15
|
+
# The library never reads .env on its own; an application must opt in.
|
|
16
|
+
Legate.load_environment
|
|
17
|
+
|
|
18
|
+
puts '--- Custom Tool Example ---'
|
|
19
|
+
|
|
20
|
+
# 1. Define a custom tool by inheriting from Legate::Tool
|
|
21
|
+
class GreetingTool < Legate::Tool
|
|
22
|
+
tool_description 'Generates a personalized greeting message.'
|
|
23
|
+
|
|
24
|
+
parameter :name, type: :string, required: true,
|
|
25
|
+
description: 'The name of the person to greet'
|
|
26
|
+
|
|
27
|
+
parameter :style, type: :string, required: false,
|
|
28
|
+
description: 'Greeting style: formal, casual, or pirate (default: casual)'
|
|
29
|
+
|
|
30
|
+
private
|
|
31
|
+
|
|
32
|
+
def perform_execution(params, _context)
|
|
33
|
+
name = params[:name]
|
|
34
|
+
style = (params[:style] || 'casual').downcase
|
|
35
|
+
|
|
36
|
+
greeting = case style
|
|
37
|
+
when 'formal'
|
|
38
|
+
"Good day, #{name}. It is a pleasure to make your acquaintance."
|
|
39
|
+
when 'pirate'
|
|
40
|
+
"Ahoy, #{name}! Welcome aboard, ye scurvy dog!"
|
|
41
|
+
else
|
|
42
|
+
"Hey #{name}, nice to meet you!"
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
{ status: :success, result: greeting }
|
|
46
|
+
rescue StandardError => e
|
|
47
|
+
{ status: :error, error_message: "Greeting failed: #{e.message}" }
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# 2. Register the tool globally so agents can find it by name
|
|
52
|
+
Legate::GlobalToolManager.register_tool(GreetingTool)
|
|
53
|
+
puts "Registered tool: #{GreetingTool.tool_name}"
|
|
54
|
+
|
|
55
|
+
# 3. Use the tool directly (without an agent)
|
|
56
|
+
puts "\n--- Direct Tool Usage ---"
|
|
57
|
+
tool = GreetingTool.new
|
|
58
|
+
context = Legate::ToolContext.new(
|
|
59
|
+
session_id: 'demo-session',
|
|
60
|
+
user_id: 'demo-user',
|
|
61
|
+
app_name: 'custom_tool_example'
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
%w[casual formal pirate].each do |style|
|
|
65
|
+
result = tool.execute({ name: 'Alice', style: style }, context)
|
|
66
|
+
puts " #{style}: #{result[:result]}"
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# 4. Wire the tool into an agent
|
|
70
|
+
puts "\n--- Agent with Custom Tool ---"
|
|
71
|
+
agent_definition = Legate::AgentDefinition.new.define do |a|
|
|
72
|
+
a.name :greeter_agent
|
|
73
|
+
a.description 'An agent that greets people in different styles'
|
|
74
|
+
a.instruction 'You are a greeting specialist. Use the greeting tool to greet people. Choose the style that best fits the request.'
|
|
75
|
+
a.use_tool :greeting_tool
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
agent = Legate::Agent.new(definition: agent_definition)
|
|
79
|
+
agent.start
|
|
80
|
+
|
|
81
|
+
session_service = Legate::SessionService::InMemory.new
|
|
82
|
+
session = session_service.create_session(app_name: agent.name, user_id: 'example_user')
|
|
83
|
+
|
|
84
|
+
result = agent.run_task(
|
|
85
|
+
session_id: session.id,
|
|
86
|
+
user_input: 'Greet Captain Blackbeard in pirate style',
|
|
87
|
+
session_service: session_service
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
puts "Agent result: #{result.content.inspect}"
|
|
91
|
+
|
|
92
|
+
agent.stop
|
|
93
|
+
puts "\n--- Example Complete ---"
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# Example: Agent Instructions (System Prompts)
|
|
5
|
+
#
|
|
6
|
+
# Demonstrates defining an agent with specific instructions (system prompt)
|
|
7
|
+
# that guide its behavior during planning.
|
|
8
|
+
#
|
|
9
|
+
# Run with: bundle exec ruby examples/04_agent_instructions.rb
|
|
10
|
+
|
|
11
|
+
$LOAD_PATH.unshift(File.expand_path('../lib', __dir__))
|
|
12
|
+
|
|
13
|
+
require 'legate'
|
|
14
|
+
|
|
15
|
+
# Load .env and map GEMINI_API_KEY -> GOOGLE_API_KEY (as the `legate` CLI does).
|
|
16
|
+
# The library never reads .env on its own; an application must opt in.
|
|
17
|
+
Legate.load_environment
|
|
18
|
+
require 'legate/tools/echo' # Ensure tool classes are loaded for GlobalToolManager
|
|
19
|
+
require 'legate/tools/calculator' # to find them by name.
|
|
20
|
+
|
|
21
|
+
# 1. Define the Agent with Instructions
|
|
22
|
+
# =====================================
|
|
23
|
+
|
|
24
|
+
# Create the AgentDefinition object first
|
|
25
|
+
concise_calculator_definition = Legate::AgentDefinition.new.define do |a|
|
|
26
|
+
a.name :concise_calculator # Use symbol for name
|
|
27
|
+
a.description 'A calculator agent that tries to be concise.'
|
|
28
|
+
# Provide instructions to the planner
|
|
29
|
+
a.instruction 'You are a calculator assistant. When asked to calculate, use the calculator tool. Respond only with the final numerical result, no extra words.'
|
|
30
|
+
# Add necessary tools by name
|
|
31
|
+
a.use_tool :calculator
|
|
32
|
+
a.use_tool :echo # Echo might be used by fallback or if planner chooses it
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Instantiate the Agent using the definition
|
|
36
|
+
agent = Legate::Agent.new(definition: concise_calculator_definition)
|
|
37
|
+
|
|
38
|
+
# 2. Setup Session Service
|
|
39
|
+
# ========================
|
|
40
|
+
session_service = Legate::SessionService::InMemory.new
|
|
41
|
+
session = session_service.create_session(app_name: agent.name, user_id: 'instruct_user')
|
|
42
|
+
|
|
43
|
+
# 3. Start Agent and Run Task
|
|
44
|
+
# ==========================
|
|
45
|
+
begin
|
|
46
|
+
puts "Starting agent '#{agent.name}'..."
|
|
47
|
+
agent.start
|
|
48
|
+
|
|
49
|
+
task = 'What is 5 plus 12?'
|
|
50
|
+
puts "\nRunning task: '#{task}'"
|
|
51
|
+
|
|
52
|
+
# The planner will receive the instruction along with the task and tool list.
|
|
53
|
+
# The LLM should ideally follow the instruction to generate a plan
|
|
54
|
+
# that results in a concise response (though the final response formatting
|
|
55
|
+
# also depends on the tool's output and agent logic).
|
|
56
|
+
result_event = agent.run_task(
|
|
57
|
+
session_id: session.id,
|
|
58
|
+
user_input: task,
|
|
59
|
+
session_service: session_service
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
puts "\n--- Agent Response ---"
|
|
63
|
+
puts " Role: #{result_event.role}"
|
|
64
|
+
puts " Content: #{result_event.content.inspect}"
|
|
65
|
+
|
|
66
|
+
# Example of a task the instructions might prevent (if LLM obeys)
|
|
67
|
+
task_inappropriate = 'Tell me a long story about the number 7.'
|
|
68
|
+
puts "\nRunning task: '#{task_inappropriate}' (Agent instructed to only calculate)"
|
|
69
|
+
result_event_2 = agent.run_task(
|
|
70
|
+
session_id: session.id,
|
|
71
|
+
user_input: task_inappropriate,
|
|
72
|
+
session_service: session_service
|
|
73
|
+
)
|
|
74
|
+
puts "\n--- Agent Response (Second Task) ---"
|
|
75
|
+
puts " Role: #{result_event_2.role}"
|
|
76
|
+
puts " Content: #{result_event_2.content.inspect}"
|
|
77
|
+
# Expected: Agent might respond with planning failure because the task doesn't match its instructions.
|
|
78
|
+
ensure
|
|
79
|
+
puts "\nStopping agent '#{agent.name}'..."
|
|
80
|
+
agent.stop
|
|
81
|
+
puts 'Agent stopped.'
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
puts "\nExample finished."
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# Example: Session State Management
|
|
5
|
+
#
|
|
6
|
+
# This example demonstrates how Legate manages state:
|
|
7
|
+
# - Creating sessions with initial state
|
|
8
|
+
# - Reading and writing state via the session service
|
|
9
|
+
# - How tools produce state deltas that agents apply
|
|
10
|
+
# - Inspecting event history after task execution
|
|
11
|
+
#
|
|
12
|
+
# Run with: bundle exec ruby examples/05_state_and_sessions.rb
|
|
13
|
+
|
|
14
|
+
require_relative '../lib/legate'
|
|
15
|
+
|
|
16
|
+
# Load .env and map GEMINI_API_KEY -> GOOGLE_API_KEY (as the `legate` CLI does).
|
|
17
|
+
# The library never reads .env on its own; an application must opt in.
|
|
18
|
+
Legate.load_environment
|
|
19
|
+
|
|
20
|
+
puts '--- State & Sessions Example ---'
|
|
21
|
+
|
|
22
|
+
# 1. Create a session service and session with initial state
|
|
23
|
+
session_service = Legate::SessionService::InMemory.new
|
|
24
|
+
session = session_service.create_session(
|
|
25
|
+
app_name: 'state_example',
|
|
26
|
+
user_id: 'demo_user',
|
|
27
|
+
initial_state: { visits: 0, greeting: 'Welcome!' }
|
|
28
|
+
)
|
|
29
|
+
session_id = session.id
|
|
30
|
+
|
|
31
|
+
puts "Created session: #{session_id}"
|
|
32
|
+
puts 'Initial state:'
|
|
33
|
+
session.state.each_pair { |k, v| puts " #{k}: #{v.inspect}" }
|
|
34
|
+
|
|
35
|
+
# 2. Direct state manipulation via session service
|
|
36
|
+
puts "\n--- Session Service State Operations ---"
|
|
37
|
+
session_service.set_state(session_id: session_id, key: :visits, value: 1)
|
|
38
|
+
session_service.set_state(session_id: session_id, key: :preference, value: 'dark_mode')
|
|
39
|
+
|
|
40
|
+
visits = session_service.get_state(session_id: session_id, key: :visits)
|
|
41
|
+
pref = session_service.get_state(session_id: session_id, key: :preference)
|
|
42
|
+
puts " visits: #{visits}"
|
|
43
|
+
puts " preference: #{pref}"
|
|
44
|
+
|
|
45
|
+
# 3. How tools interact with state
|
|
46
|
+
puts "\n--- Tool State Pattern ---"
|
|
47
|
+
puts ' Tools use context.state_get/state_set to read/write state.'
|
|
48
|
+
puts " state_set accumulates a 'pending delta' that the agent applies"
|
|
49
|
+
puts ' to the session after the tool completes. This ensures state'
|
|
50
|
+
puts ' changes are tracked alongside events.'
|
|
51
|
+
|
|
52
|
+
# 4. Create an agent and run a task to see events and state in action
|
|
53
|
+
puts "\n--- Agent Task with Events ---"
|
|
54
|
+
agent_definition = Legate::AgentDefinition.new.define do |a|
|
|
55
|
+
a.name :state_demo_agent
|
|
56
|
+
a.description 'Demonstrates state in agent context'
|
|
57
|
+
a.instruction 'You are a helpful agent. Echo back what the user says.'
|
|
58
|
+
a.use_tool :echo
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
agent = Legate::Agent.new(definition: agent_definition)
|
|
62
|
+
agent.start
|
|
63
|
+
|
|
64
|
+
result = agent.run_task(
|
|
65
|
+
session_id: session_id,
|
|
66
|
+
user_input: 'Remember that I visited the examples page',
|
|
67
|
+
session_service: session_service
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
puts " Task result: #{result.content.inspect}"
|
|
71
|
+
|
|
72
|
+
# 5. Inspect event history
|
|
73
|
+
puts "\n--- Event History ---"
|
|
74
|
+
final_session = session_service.get_session(session_id: session_id)
|
|
75
|
+
puts " Total events: #{final_session.events.size}"
|
|
76
|
+
final_session.events.each_with_index do |event, i|
|
|
77
|
+
role = event.role
|
|
78
|
+
content_preview = case event.content
|
|
79
|
+
when String then event.content[0..60]
|
|
80
|
+
when Hash then event.content[:status] || event.content.keys.first
|
|
81
|
+
else event.content.class
|
|
82
|
+
end
|
|
83
|
+
puts " #{i + 1}. [#{role}] #{content_preview}"
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# 6. Final state
|
|
87
|
+
puts "\n--- Final State ---"
|
|
88
|
+
final_session.state.each_pair { |k, v| puts " #{k}: #{v.inspect}" }
|
|
89
|
+
|
|
90
|
+
agent.stop
|
|
91
|
+
puts "\n--- Example Complete ---"
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# If running from project root: bundle exec ruby examples/06_callbacks.rb
|
|
5
|
+
require_relative '../lib/legate'
|
|
6
|
+
|
|
7
|
+
# Load .env and map GEMINI_API_KEY -> GOOGLE_API_KEY (as the `legate` CLI does).
|
|
8
|
+
# The library never reads .env on its own; an application must opt in.
|
|
9
|
+
Legate.load_environment
|
|
10
|
+
|
|
11
|
+
puts '--- Legate Callbacks Basic Example ---'
|
|
12
|
+
|
|
13
|
+
# Helper method to safely inspect objects
|
|
14
|
+
def inspect_object(obj)
|
|
15
|
+
return 'nil' if obj.nil?
|
|
16
|
+
|
|
17
|
+
if obj.is_a?(Hash) || obj.is_a?(Array)
|
|
18
|
+
obj.inspect
|
|
19
|
+
else
|
|
20
|
+
# For other objects, get their instance variables and methods
|
|
21
|
+
vars = obj.instance_variables.map { |v| "#{v}=#{obj.instance_variable_get(v).inspect}" }
|
|
22
|
+
methods = obj.public_methods(false).sort.map(&:to_s)
|
|
23
|
+
"Object of class #{obj.class}\nInstance vars: #{vars.join(', ')}\nMethods: #{methods.join(', ')}"
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# 1. --- Define our callback functions ---
|
|
28
|
+
|
|
29
|
+
# Agent callbacks
|
|
30
|
+
before_agent_callback = lambda do |context|
|
|
31
|
+
puts "\n[AGENT CALLBACK] Before agent processes request"
|
|
32
|
+
puts " Context structure: #{inspect_object(context)}"
|
|
33
|
+
puts " Session ID: #{context.session_id}" if context.respond_to?(:session_id)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# The documentation mentioned only 1 parameter, but the error suggests 2 are passed
|
|
37
|
+
after_agent_callback = lambda do |context, *args|
|
|
38
|
+
puts "\n[AGENT CALLBACK] After agent completed request"
|
|
39
|
+
puts " Context structure: #{inspect_object(context)}"
|
|
40
|
+
puts " Additional args: #{args.inspect}" if args.any?
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Model callbacks - expecting 2 arguments
|
|
44
|
+
before_model_callback = lambda do |context, prompt|
|
|
45
|
+
puts "\n[MODEL CALLBACK] Before sending prompt to LLM"
|
|
46
|
+
puts " Context structure: #{inspect_object(context)}"
|
|
47
|
+
|
|
48
|
+
if prompt.is_a?(String)
|
|
49
|
+
preview = prompt.length > 100 ? "#{prompt[0, 100]}..." : prompt
|
|
50
|
+
puts " Prompt: #{preview}"
|
|
51
|
+
else
|
|
52
|
+
puts " Prompt: #{prompt.inspect}"
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# Return the prompt unchanged
|
|
56
|
+
prompt
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
after_model_callback = lambda do |context, response|
|
|
60
|
+
puts "\n[MODEL CALLBACK] After receiving response from LLM"
|
|
61
|
+
puts " Context structure: #{inspect_object(context)}"
|
|
62
|
+
|
|
63
|
+
if response.is_a?(String)
|
|
64
|
+
preview = response.length > 100 ? "#{response[0, 100]}..." : response
|
|
65
|
+
puts " Response: #{preview}"
|
|
66
|
+
else
|
|
67
|
+
puts " Response: #{response.inspect}"
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Return the response unchanged
|
|
71
|
+
response
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Tool callbacks - expecting 3 arguments
|
|
75
|
+
before_tool_callback = lambda do |context, tool, params|
|
|
76
|
+
puts "\n[TOOL CALLBACK] Before executing tool"
|
|
77
|
+
puts " Context structure: #{inspect_object(context)}"
|
|
78
|
+
puts " Tool: #{tool.name}" if tool.respond_to?(:name)
|
|
79
|
+
puts " Parameters: #{params.inspect}"
|
|
80
|
+
|
|
81
|
+
# Return the original parameters, not the context or tool
|
|
82
|
+
# The expected parameters format is a Hash like {message: "Hello, world"}
|
|
83
|
+
if params.is_a?(Hash)
|
|
84
|
+
params
|
|
85
|
+
elsif params.is_a?(Legate::ToolContext)
|
|
86
|
+
# If we're passed a ToolContext object, try to extract parameters from session
|
|
87
|
+
puts ' WARNING: Received ToolContext instead of params hash'
|
|
88
|
+
|
|
89
|
+
# Get parameters from the session events if possible
|
|
90
|
+
if params.respond_to?(:session_id) && params.session_id && defined?($session_service)
|
|
91
|
+
begin
|
|
92
|
+
session = $session_service.get_session(session_id: params.session_id)
|
|
93
|
+
if session
|
|
94
|
+
events = session.events
|
|
95
|
+
# Find the most recent tool_request event for this tool
|
|
96
|
+
tool_name = tool.respond_to?(:name) ? tool.name.to_s : nil
|
|
97
|
+
if tool_name
|
|
98
|
+
# The tool field might be stored in different ways
|
|
99
|
+
tool_request = events.reverse.find do |e|
|
|
100
|
+
e.role == :tool_request &&
|
|
101
|
+
((e.respond_to?(:tool) && e.tool == tool_name) ||
|
|
102
|
+
(e.respond_to?(:[]) && e[:tool] == tool_name))
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
if tool_request && tool_request.respond_to?(:content) && tool_request.content.is_a?(Hash)
|
|
106
|
+
# We found the parameters in the session events
|
|
107
|
+
return tool_request.content
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
rescue StandardError => e
|
|
112
|
+
puts " WARNING: Error getting session events: #{e.message}"
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
# Default fallback for echo tool
|
|
117
|
+
{ message: 'Hello, world! This is a callback example.' }
|
|
118
|
+
else
|
|
119
|
+
# If all else fails, return empty params
|
|
120
|
+
puts " WARNING: Unexpected params type: #{params.class}"
|
|
121
|
+
{}
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
after_tool_callback = lambda do |context, tool, result|
|
|
126
|
+
puts "\n[TOOL CALLBACK] After executing tool"
|
|
127
|
+
puts " Context structure: #{inspect_object(context)}"
|
|
128
|
+
puts " Tool: #{tool.name}" if tool.respond_to?(:name)
|
|
129
|
+
puts " Result: #{result.inspect}"
|
|
130
|
+
|
|
131
|
+
# Return the result unchanged
|
|
132
|
+
result
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
# 2. --- Agent Definition with Callbacks ---
|
|
136
|
+
echo_agent_definition = Legate::AgentDefinition.new.define do |a|
|
|
137
|
+
a.name :echo_with_callbacks
|
|
138
|
+
a.description 'An echo agent that demonstrates callbacks'
|
|
139
|
+
a.instruction 'You are an echo agent. Your task is to repeat the user\'s input exactly.'
|
|
140
|
+
|
|
141
|
+
# Register the callbacks
|
|
142
|
+
a.before_agent_callback(&before_agent_callback)
|
|
143
|
+
a.after_agent_callback(&after_agent_callback)
|
|
144
|
+
|
|
145
|
+
a.before_model_callback(&before_model_callback)
|
|
146
|
+
a.after_model_callback(&after_model_callback)
|
|
147
|
+
|
|
148
|
+
a.before_tool_callback(&before_tool_callback)
|
|
149
|
+
a.after_tool_callback(&after_tool_callback)
|
|
150
|
+
|
|
151
|
+
a.use_tool :echo
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
# 3. --- Agent Instantiation ---
|
|
155
|
+
agent = Legate::Agent.new(definition: echo_agent_definition)
|
|
156
|
+
puts "\nAgent '#{agent.name}' created with callbacks registered"
|
|
157
|
+
|
|
158
|
+
# 4. --- Start Agent and Setup Session ---
|
|
159
|
+
agent.start
|
|
160
|
+
session_service = Legate::SessionService::InMemory.new
|
|
161
|
+
# Make session_service accessible to callbacks
|
|
162
|
+
$session_service = session_service
|
|
163
|
+
session = session_service.create_session(app_name: agent.name, user_id: 'callback_example_user')
|
|
164
|
+
session_id = session.id
|
|
165
|
+
puts "\nCreated session: #{session_id}"
|
|
166
|
+
|
|
167
|
+
# 5. --- Execute Task and Observe Callbacks ---
|
|
168
|
+
task = 'Hello, world! This is a callback example.'
|
|
169
|
+
puts "\nExecuting task: '#{task}'"
|
|
170
|
+
|
|
171
|
+
begin
|
|
172
|
+
result = agent.run_task(
|
|
173
|
+
session_id: session_id,
|
|
174
|
+
user_input: task,
|
|
175
|
+
session_service: session_service
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
puts "\nFinal result: #{result.content.inspect}"
|
|
179
|
+
rescue StandardError => e
|
|
180
|
+
puts "\nError executing task: #{e.class} - #{e.message}"
|
|
181
|
+
puts e.backtrace.first(5).join("\n")
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
# 6. --- Stop Agent ---
|
|
185
|
+
agent.stop
|
|
186
|
+
puts "\n--- Example Complete ---"
|