a2a-ruby 1.0.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 (128) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +3 -0
  3. data/.rubocop.yml +137 -0
  4. data/.simplecov +46 -0
  5. data/.yardopts +10 -0
  6. data/CHANGELOG.md +33 -0
  7. data/CODE_OF_CONDUCT.md +128 -0
  8. data/CONTRIBUTING.md +165 -0
  9. data/Gemfile +43 -0
  10. data/Guardfile +34 -0
  11. data/LICENSE.txt +21 -0
  12. data/PUBLISHING_CHECKLIST.md +214 -0
  13. data/README.md +171 -0
  14. data/Rakefile +165 -0
  15. data/docs/agent_execution.md +309 -0
  16. data/docs/api_reference.md +792 -0
  17. data/docs/configuration.md +780 -0
  18. data/docs/events.md +475 -0
  19. data/docs/getting_started.md +668 -0
  20. data/docs/integration.md +262 -0
  21. data/docs/server_apps.md +621 -0
  22. data/docs/troubleshooting.md +765 -0
  23. data/lib/a2a/client/api_methods.rb +263 -0
  24. data/lib/a2a/client/auth/api_key.rb +161 -0
  25. data/lib/a2a/client/auth/interceptor.rb +288 -0
  26. data/lib/a2a/client/auth/jwt.rb +189 -0
  27. data/lib/a2a/client/auth/oauth2.rb +146 -0
  28. data/lib/a2a/client/auth.rb +137 -0
  29. data/lib/a2a/client/base.rb +316 -0
  30. data/lib/a2a/client/config.rb +210 -0
  31. data/lib/a2a/client/connection_pool.rb +233 -0
  32. data/lib/a2a/client/http_client.rb +524 -0
  33. data/lib/a2a/client/json_rpc_handler.rb +136 -0
  34. data/lib/a2a/client/middleware/circuit_breaker_interceptor.rb +245 -0
  35. data/lib/a2a/client/middleware/logging_interceptor.rb +371 -0
  36. data/lib/a2a/client/middleware/rate_limit_interceptor.rb +142 -0
  37. data/lib/a2a/client/middleware/retry_interceptor.rb +161 -0
  38. data/lib/a2a/client/middleware.rb +116 -0
  39. data/lib/a2a/client/performance_tracker.rb +60 -0
  40. data/lib/a2a/configuration/defaults.rb +34 -0
  41. data/lib/a2a/configuration/environment_loader.rb +76 -0
  42. data/lib/a2a/configuration/file_loader.rb +115 -0
  43. data/lib/a2a/configuration/inheritance.rb +101 -0
  44. data/lib/a2a/configuration/validator.rb +180 -0
  45. data/lib/a2a/configuration.rb +201 -0
  46. data/lib/a2a/errors.rb +291 -0
  47. data/lib/a2a/modules.rb +50 -0
  48. data/lib/a2a/monitoring/alerting.rb +490 -0
  49. data/lib/a2a/monitoring/distributed_tracing.rb +398 -0
  50. data/lib/a2a/monitoring/health_endpoints.rb +204 -0
  51. data/lib/a2a/monitoring/metrics_collector.rb +438 -0
  52. data/lib/a2a/monitoring.rb +463 -0
  53. data/lib/a2a/plugin.rb +358 -0
  54. data/lib/a2a/plugin_manager.rb +159 -0
  55. data/lib/a2a/plugins/example_auth.rb +81 -0
  56. data/lib/a2a/plugins/example_middleware.rb +118 -0
  57. data/lib/a2a/plugins/example_transport.rb +76 -0
  58. data/lib/a2a/protocol/agent_card.rb +8 -0
  59. data/lib/a2a/protocol/agent_card_server.rb +584 -0
  60. data/lib/a2a/protocol/capability.rb +496 -0
  61. data/lib/a2a/protocol/json_rpc.rb +254 -0
  62. data/lib/a2a/protocol/message.rb +8 -0
  63. data/lib/a2a/protocol/task.rb +8 -0
  64. data/lib/a2a/rails/a2a_controller.rb +258 -0
  65. data/lib/a2a/rails/controller_helpers.rb +499 -0
  66. data/lib/a2a/rails/engine.rb +167 -0
  67. data/lib/a2a/rails/generators/agent_generator.rb +311 -0
  68. data/lib/a2a/rails/generators/install_generator.rb +209 -0
  69. data/lib/a2a/rails/generators/migration_generator.rb +232 -0
  70. data/lib/a2a/rails/generators/templates/add_a2a_indexes.rb +57 -0
  71. data/lib/a2a/rails/generators/templates/agent_controller.rb +122 -0
  72. data/lib/a2a/rails/generators/templates/agent_controller_spec.rb +160 -0
  73. data/lib/a2a/rails/generators/templates/agent_readme.md +200 -0
  74. data/lib/a2a/rails/generators/templates/create_a2a_push_notification_configs.rb +68 -0
  75. data/lib/a2a/rails/generators/templates/create_a2a_tasks.rb +83 -0
  76. data/lib/a2a/rails/generators/templates/example_agent_controller.rb +228 -0
  77. data/lib/a2a/rails/generators/templates/initializer.rb +108 -0
  78. data/lib/a2a/rails/generators/templates/push_notification_config_model.rb +228 -0
  79. data/lib/a2a/rails/generators/templates/task_model.rb +200 -0
  80. data/lib/a2a/rails/tasks/a2a.rake +228 -0
  81. data/lib/a2a/server/a2a_methods.rb +520 -0
  82. data/lib/a2a/server/agent.rb +537 -0
  83. data/lib/a2a/server/agent_execution/agent_executor.rb +279 -0
  84. data/lib/a2a/server/agent_execution/request_context.rb +219 -0
  85. data/lib/a2a/server/apps/rack_app.rb +311 -0
  86. data/lib/a2a/server/apps/sinatra_app.rb +261 -0
  87. data/lib/a2a/server/default_request_handler.rb +350 -0
  88. data/lib/a2a/server/events/event_consumer.rb +116 -0
  89. data/lib/a2a/server/events/event_queue.rb +226 -0
  90. data/lib/a2a/server/example_agent.rb +248 -0
  91. data/lib/a2a/server/handler.rb +281 -0
  92. data/lib/a2a/server/middleware/authentication_middleware.rb +212 -0
  93. data/lib/a2a/server/middleware/cors_middleware.rb +171 -0
  94. data/lib/a2a/server/middleware/logging_middleware.rb +362 -0
  95. data/lib/a2a/server/middleware/rate_limit_middleware.rb +382 -0
  96. data/lib/a2a/server/middleware.rb +213 -0
  97. data/lib/a2a/server/push_notification_manager.rb +327 -0
  98. data/lib/a2a/server/request_handler.rb +136 -0
  99. data/lib/a2a/server/storage/base.rb +141 -0
  100. data/lib/a2a/server/storage/database.rb +266 -0
  101. data/lib/a2a/server/storage/memory.rb +274 -0
  102. data/lib/a2a/server/storage/redis.rb +320 -0
  103. data/lib/a2a/server/storage.rb +38 -0
  104. data/lib/a2a/server/task_manager.rb +534 -0
  105. data/lib/a2a/transport/grpc.rb +481 -0
  106. data/lib/a2a/transport/http.rb +415 -0
  107. data/lib/a2a/transport/sse.rb +499 -0
  108. data/lib/a2a/types/agent_card.rb +540 -0
  109. data/lib/a2a/types/artifact.rb +99 -0
  110. data/lib/a2a/types/base_model.rb +223 -0
  111. data/lib/a2a/types/events.rb +117 -0
  112. data/lib/a2a/types/message.rb +106 -0
  113. data/lib/a2a/types/part.rb +288 -0
  114. data/lib/a2a/types/push_notification.rb +139 -0
  115. data/lib/a2a/types/security.rb +167 -0
  116. data/lib/a2a/types/task.rb +154 -0
  117. data/lib/a2a/types.rb +88 -0
  118. data/lib/a2a/utils/helpers.rb +245 -0
  119. data/lib/a2a/utils/message_buffer.rb +278 -0
  120. data/lib/a2a/utils/performance.rb +247 -0
  121. data/lib/a2a/utils/rails_detection.rb +97 -0
  122. data/lib/a2a/utils/structured_logger.rb +306 -0
  123. data/lib/a2a/utils/time_helpers.rb +167 -0
  124. data/lib/a2a/utils/validation.rb +8 -0
  125. data/lib/a2a/version.rb +6 -0
  126. data/lib/a2a-rails.rb +58 -0
  127. data/lib/a2a.rb +198 -0
  128. metadata +437 -0
@@ -0,0 +1,200 @@
1
+ # <%= class_name.humanize %> A2A Agent
2
+
3
+ <%= agent_description %>
4
+
5
+ ## Overview
6
+
7
+ This agent provides A2A (Agent2Agent) protocol endpoints for <%= class_name.humanize.downcase %> functionality. It was generated using the A2A Ruby SDK Rails generator.
8
+
9
+ ## Endpoints
10
+
11
+ ### Agent Card
12
+ - **URL**: `<%= agent_card_path %>`
13
+ - **Method**: GET
14
+ - **Description**: Returns the agent card with capabilities and interface information
15
+
16
+ ### JSON-RPC Interface
17
+ - **URL**: `<%= rpc_path %>`
18
+ - **Method**: POST
19
+ - **Content-Type**: application/json
20
+ - **Description**: Handles A2A JSON-RPC method calls
21
+
22
+ ## Skills and Capabilities
23
+
24
+ <% if skills.any? %>
25
+ This agent provides the following skills:
26
+
27
+ <% skills.each do |skill| %>
28
+ ### <%= skill.humanize %>
29
+ - **Method**: `<%= skill.underscore %>`
30
+ - **Description**: <%= skill.humanize %> functionality
31
+ - **Tags**: `<%= skill %>`, `generated`
32
+
33
+ <% end %>
34
+ <% else %>
35
+ ### Default Processing
36
+ - **Method**: `process`
37
+ - **Description**: Default <%= class_name.humanize.downcase %> processing functionality
38
+ - **Tags**: `<%= class_name.underscore %>`, `default`
39
+ <% end %>
40
+
41
+ ### Status
42
+ - **Method**: `status`
43
+ - **Description**: Get agent status and health information
44
+ - **Tags**: `status`, `health`
45
+
46
+ ## Usage Examples
47
+
48
+ ### Get Agent Card
49
+ ```bash
50
+ curl -X GET <%= agent_card_path %>
51
+ ```
52
+
53
+ ### Call Agent Method
54
+ ```bash
55
+ curl -X POST <%= rpc_path %> \
56
+ -H "Content-Type: application/json" \
57
+ -d '{
58
+ "jsonrpc": "2.0",
59
+ "method": "status",
60
+ "params": {},
61
+ "id": 1
62
+ }'
63
+ ```
64
+
65
+ <% if skills.any? %>
66
+ <% skills.first(2).each do |skill| %>
67
+ ### <%= skill.humanize %> Example
68
+ ```bash
69
+ curl -X POST <%= rpc_path %> \
70
+ -H "Content-Type: application/json" \
71
+ -d '{
72
+ "jsonrpc": "2.0",
73
+ "method": "<%= skill.underscore %>",
74
+ "params": {
75
+ "action": "<%= skill %>"
76
+ },
77
+ "id": 1
78
+ }'
79
+ ```
80
+ <% end %>
81
+ <% end %>
82
+
83
+ <% if with_authentication? %>
84
+ ## Authentication
85
+
86
+ This agent requires authentication for certain methods:
87
+
88
+ <% authentication_methods.each do |method| %>
89
+ - `<%= method %>` - Requires valid authentication
90
+ <% end %>
91
+
92
+ ### Authentication Example
93
+ ```bash
94
+ curl -X POST <%= rpc_path %> \
95
+ -H "Content-Type: application/json" \
96
+ -H "Authorization: Bearer YOUR_TOKEN" \
97
+ -d '{
98
+ "jsonrpc": "2.0",
99
+ "method": "<%= authentication_methods.first %>",
100
+ "params": {},
101
+ "id": 1
102
+ }'
103
+ ```
104
+ <% end %>
105
+
106
+ ## Development
107
+
108
+ ### Customizing the Agent
109
+
110
+ 1. **Add New Skills**: Define new skills using the `a2a_skill` DSL in the controller
111
+ 2. **Implement Methods**: Add method implementations using the `a2a_method` DSL
112
+ 3. **Configure Authentication**: Customize authentication requirements using `a2a_authenticate`
113
+
114
+ ### Example: Adding a New Skill
115
+
116
+ ```ruby
117
+ # In <%= controller_file_path %>
118
+
119
+ a2a_skill "new_feature" do |skill|
120
+ skill.description = "Description of the new feature"
121
+ skill.tags = ["new", "feature"]
122
+ skill.examples = [
123
+ {
124
+ input: { param: "value" },
125
+ output: { result: "success" }
126
+ }
127
+ ]
128
+ end
129
+
130
+ a2a_method "new_feature" do |params|
131
+ # Implement your logic here
132
+ {
133
+ result: "Feature implemented",
134
+ params: params,
135
+ timestamp: Time.current.iso8601
136
+ }
137
+ end
138
+ ```
139
+
140
+ ### Testing
141
+
142
+ Run the generated tests:
143
+
144
+ ```bash
145
+ # RSpec
146
+ bundle exec rspec spec/controllers/<%= namespace ? "#{namespace}/" : "" %><%= file_name %>_controller_spec.rb
147
+
148
+ # Or Rails test
149
+ bundle exec rails test test/controllers/<%= namespace ? "#{namespace}/" : "" %><%= file_name %>_controller_test.rb
150
+ ```
151
+
152
+ ### Debugging
153
+
154
+ Use the Rails console to test your agent:
155
+
156
+ ```ruby
157
+ # Start Rails console
158
+ rails console
159
+
160
+ # Test agent methods directly
161
+ controller = <%= controller_class_name %>.new
162
+ controller.request = ActionDispatch::Request.new({})
163
+
164
+ # Generate agent card
165
+ card = controller.send(:generate_agent_card)
166
+ puts JSON.pretty_generate(card.to_h)
167
+
168
+ # Test method execution
169
+ result = controller.send(:handle_a2a_request,
170
+ A2A::Protocol::JsonRpc::Request.new(
171
+ jsonrpc: "2.0",
172
+ method: "status",
173
+ params: {},
174
+ id: 1
175
+ )
176
+ )
177
+ puts JSON.pretty_generate(result)
178
+ ```
179
+
180
+ ## Configuration
181
+
182
+ The agent inherits configuration from `config/initializers/a2a.rb`. You can customize:
183
+
184
+ - Authentication requirements
185
+ - Middleware settings
186
+ - Storage backends
187
+ - Logging levels
188
+
189
+ ## Documentation
190
+
191
+ - [A2A Protocol Specification](https://a2a-protocol.org/)
192
+ - [A2A Ruby SDK Documentation](https://a2a-protocol.org/sdk/ruby/)
193
+ - [Rails Integration Guide](https://a2a-protocol.org/sdk/ruby/rails/)
194
+
195
+ ## Support
196
+
197
+ For issues and questions:
198
+ - Check the [A2A Ruby SDK Issues](https://github.com/a2aproject/a2a-ruby/issues)
199
+ - Review the [Rails Integration Documentation](https://a2a-protocol.org/sdk/ruby/rails/)
200
+ - Join the [A2A Community](https://a2a-protocol.org/community/)
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Create<%= table_prefix.classify %>PushNotificationConfigs < ActiveRecord::Migration<%= migration_version %>
4
+ def change
5
+ create_table :<%= push_notification_configs_table_name %>, id: false do |t|
6
+ # Primary key
7
+ <% if postgresql? %>
8
+ t.uuid :id, primary_key: true, default: "gen_random_uuid()"
9
+ t.uuid :task_id, null: false
10
+ <% else %>
11
+ t.string :id, primary_key: true, limit: 36, null: false
12
+ t.string :task_id, limit: 36, null: false
13
+ <% end %>
14
+
15
+ # Push notification configuration
16
+ t.string :url, null: false
17
+ t.string :token, null: true
18
+ t.<%= json_column_type %> :authentication, null: true, default: -> {
19
+ <% if postgresql? %>
20
+ "'{}'::jsonb"
21
+ <% else %>
22
+ "'{}'"
23
+ <% end %>
24
+ }
25
+
26
+ # Configuration metadata
27
+ t.<%= json_column_type %> :metadata, null: true, default: -> {
28
+ <% if postgresql? %>
29
+ "'{}'::jsonb"
30
+ <% else %>
31
+ "'{}'"
32
+ <% end %>
33
+ }
34
+
35
+ # Status tracking
36
+ t.boolean :active, null: false, default: true
37
+ t.integer :retry_count, null: false, default: 0
38
+ t.datetime :last_success_at, null: true
39
+ t.datetime :last_failure_at, null: true
40
+ t.text :last_error, null: true
41
+
42
+ # Timestamps
43
+ t.timestamps null: false
44
+
45
+ # Soft delete support
46
+ t.datetime :deleted_at, null: true
47
+ end
48
+
49
+ <% if with_indexes? %>
50
+ # Add indexes for performance
51
+ add_index :<%= push_notification_configs_table_name %>, :id, unique: true
52
+ add_index :<%= push_notification_configs_table_name %>, :task_id
53
+ add_index :<%= push_notification_configs_table_name %>, :active
54
+ add_index :<%= push_notification_configs_table_name %>, :created_at
55
+ add_index :<%= push_notification_configs_table_name %>, :deleted_at
56
+
57
+ <% if postgresql? %>
58
+ # PostgreSQL-specific indexes for JSON columns
59
+ add_index :<%= push_notification_configs_table_name %>, :authentication, using: :gin
60
+ add_index :<%= push_notification_configs_table_name %>, :metadata, using: :gin
61
+ <% end %>
62
+ <% end %>
63
+
64
+ # Foreign key constraint to tasks table
65
+ add_foreign_key :<%= push_notification_configs_table_name %>, :<%= tasks_table_name %>,
66
+ column: :task_id, primary_key: :id, on_delete: :cascade
67
+ end
68
+ end
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Create<%= table_prefix.classify %>Tasks < ActiveRecord::Migration<%= migration_version %>
4
+ def change
5
+ create_table :<%= tasks_table_name %>, id: false do |t|
6
+ # Primary key - use UUID if PostgreSQL, string otherwise
7
+ <% if postgresql? %>
8
+ t.uuid :id, primary_key: true, default: "gen_random_uuid()"
9
+ t.uuid :context_id, null: false
10
+ <% else %>
11
+ t.string :id, primary_key: true, limit: 36, null: false
12
+ t.string :context_id, limit: 36, null: false
13
+ <% end %>
14
+
15
+ # Task metadata
16
+ t.string :kind, null: false, default: "task"
17
+ t.string :type, null: true # For task type classification
18
+
19
+ # Task status information
20
+ t.string :status_state, null: false, default: "submitted"
21
+ t.text :status_message, null: true
22
+ t.decimal :status_progress, precision: 5, scale: 2, null: true
23
+ t.<%= json_column_type %> :status_result, null: true
24
+ t.<%= json_column_type %> :status_error, null: true
25
+ t.datetime :status_updated_at, null: false, default: -> { "CURRENT_TIMESTAMP" }
26
+
27
+ # Task data
28
+ t.<%= json_column_type %> :artifacts, null: true, default: -> {
29
+ <% if postgresql? %>
30
+ "'[]'::jsonb"
31
+ <% else %>
32
+ "'[]'"
33
+ <% end %>
34
+ }
35
+ t.<%= json_column_type %> :history, null: true, default: -> {
36
+ <% if postgresql? %>
37
+ "'[]'::jsonb"
38
+ <% else %>
39
+ "'[]'"
40
+ <% end %>
41
+ }
42
+ t.<%= json_column_type %> :metadata, null: true, default: -> {
43
+ <% if postgresql? %>
44
+ "'{}'::jsonb"
45
+ <% else %>
46
+ "'{}'"
47
+ <% end %>
48
+ }
49
+
50
+ # Task parameters and configuration
51
+ t.<%= json_column_type %> :params, null: true, default: -> {
52
+ <% if postgresql? %>
53
+ "'{}'::jsonb"
54
+ <% else %>
55
+ "'{}'"
56
+ <% end %>
57
+ }
58
+
59
+ # Timestamps
60
+ t.timestamps null: false
61
+
62
+ # Soft delete support
63
+ t.datetime :deleted_at, null: true
64
+ end
65
+
66
+ <% if with_indexes? %>
67
+ # Add indexes for performance
68
+ add_index :<%= tasks_table_name %>, :id, unique: true
69
+ add_index :<%= tasks_table_name %>, :context_id
70
+ add_index :<%= tasks_table_name %>, :status_state
71
+ add_index :<%= tasks_table_name %>, :type
72
+ add_index :<%= tasks_table_name %>, :created_at
73
+ add_index :<%= tasks_table_name %>, :status_updated_at
74
+ add_index :<%= tasks_table_name %>, :deleted_at
75
+
76
+ <% if postgresql? %>
77
+ # PostgreSQL-specific indexes for JSON columns
78
+ add_index :<%= tasks_table_name %>, :metadata, using: :gin
79
+ add_index :<%= tasks_table_name %>, :params, using: :gin
80
+ <% end %>
81
+ <% end %>
82
+ end
83
+ end
@@ -0,0 +1,228 @@
1
+ # frozen_string_literal: true
2
+
3
+ ##
4
+ # Example A2A Agent Controller
5
+ #
6
+ # This controller demonstrates how to create an A2A agent using the Rails integration.
7
+ # It includes examples of skills, capabilities, and method definitions.
8
+ #
9
+ # To test this agent:
10
+ # 1. Start your Rails server
11
+ # 2. Visit <%= mount_path %>/agent-card to see the agent card
12
+ # 3. Send JSON-RPC requests to <%= mount_path %>/rpc
13
+ #
14
+ class ExampleAgentController < ApplicationController
15
+ include A2A::Rails::ControllerHelpers
16
+
17
+ # Configure this agent
18
+ a2a_agent name: "Example Agent",
19
+ description: "A demonstration A2A agent for Rails integration",
20
+ version: "1.0.0",
21
+ tags: ["example", "demo", "rails"]
22
+
23
+ <% if with_authentication? %>
24
+ # Configure authentication (uncomment and customize as needed)
25
+ # a2a_authenticate :<%= authentication_strategy %>, methods: ["secure_greeting"]
26
+ <% end %>
27
+
28
+ # Define agent skills
29
+ a2a_skill "greeting" do |skill|
30
+ skill.description = "Greet users with personalized messages"
31
+ skill.tags = ["greeting", "conversation", "social"]
32
+ skill.examples = [
33
+ {
34
+ input: { name: "Alice" },
35
+ output: { message: "Hello, Alice! Welcome to our A2A agent." }
36
+ }
37
+ ]
38
+ end
39
+
40
+ a2a_skill "echo" do |skill|
41
+ skill.description = "Echo back any message sent to the agent"
42
+ skill.tags = ["utility", "testing", "echo"]
43
+ skill.examples = [
44
+ {
45
+ input: { message: "Hello, world!" },
46
+ output: { echo: "Hello, world!" }
47
+ }
48
+ ]
49
+ end
50
+
51
+ a2a_skill "time" do |skill|
52
+ skill.description = "Get current server time in various formats"
53
+ skill.tags = ["utility", "time", "datetime"]
54
+ skill.examples = [
55
+ {
56
+ input: { format: "iso8601" },
57
+ output: { time: "2024-01-01T12:00:00Z", format: "iso8601" }
58
+ }
59
+ ]
60
+ end
61
+
62
+ # A2A method implementations
63
+
64
+ ##
65
+ # Greet a user with a personalized message
66
+ #
67
+ # @param params [Hash] Request parameters
68
+ # @option params [String] :name The name to greet
69
+ # @option params [String] :style Greeting style (formal, casual, friendly)
70
+ # @return [Hash] Greeting response
71
+ #
72
+ a2a_method "greeting" do |params|
73
+ name = params[:name] || "there"
74
+ style = params[:style] || "friendly"
75
+
76
+ message = case style
77
+ when "formal"
78
+ "Good day, #{name}. It is a pleasure to make your acquaintance."
79
+ when "casual"
80
+ "Hey #{name}! What's up?"
81
+ else
82
+ "Hello, #{name}! Welcome to our A2A agent."
83
+ end
84
+
85
+ {
86
+ message: message,
87
+ name: name,
88
+ style: style,
89
+ timestamp: Time.now.iso8601
90
+ }
91
+ end
92
+
93
+ ##
94
+ # Echo back the provided message
95
+ #
96
+ # @param params [Hash] Request parameters
97
+ # @option params [String] :message The message to echo
98
+ # @return [Hash] Echo response
99
+ #
100
+ a2a_method "echo" do |params|
101
+ message = params[:message] || ""
102
+
103
+ {
104
+ echo: message,
105
+ length: message.length,
106
+ timestamp: Time.now.iso8601,
107
+ agent: "ExampleAgent"
108
+ }
109
+ end
110
+
111
+ ##
112
+ # Get current server time
113
+ #
114
+ # @param params [Hash] Request parameters
115
+ # @option params [String] :format Time format (iso8601, unix, human)
116
+ # @option params [String] :timezone Timezone (default: UTC)
117
+ # @return [Hash] Time response
118
+ #
119
+ a2a_method "get_time" do |params|
120
+ format = params[:format] || "iso8601"
121
+ timezone = params[:timezone] || "UTC"
122
+
123
+ begin
124
+ time = Time.now.in_time_zone(timezone)
125
+
126
+ formatted_time = case format
127
+ when "unix"
128
+ time.to_i
129
+ when "human"
130
+ time.strftime("%B %d, %Y at %I:%M %p %Z")
131
+ else
132
+ time.iso8601
133
+ end
134
+
135
+ {
136
+ time: formatted_time,
137
+ format: format,
138
+ timezone: timezone,
139
+ server_timezone: Time.zone.name
140
+ }
141
+ rescue ArgumentError => e
142
+ raise A2A::Errors::InvalidParams, "Invalid timezone: #{timezone}"
143
+ end
144
+ end
145
+
146
+ <% if with_authentication? %>
147
+ ##
148
+ # Secure greeting method (requires authentication)
149
+ #
150
+ # @param params [Hash] Request parameters
151
+ # @option params [String] :message Personal message
152
+ # @return [Hash] Authenticated greeting response
153
+ #
154
+ a2a_method "secure_greeting" do |params|
155
+ message = params[:message] || "Hello from the secure zone!"
156
+
157
+ {
158
+ message: message,
159
+ user: current_user_info,
160
+ permissions: current_user_permissions,
161
+ authenticated_at: Time.now.iso8601,
162
+ security_level: "authenticated"
163
+ }
164
+ end
165
+ <% end %>
166
+
167
+ ##
168
+ # Get agent status and health information
169
+ #
170
+ # @param params [Hash] Request parameters (unused)
171
+ # @return [Hash] Status response
172
+ #
173
+ a2a_method "status" do |params|
174
+ {
175
+ status: "healthy",
176
+ version: "1.0.0",
177
+ uptime: Time.now - Rails.application.config.booted_at,
178
+ rails_version: Rails.version,
179
+ a2a_version: A2A::VERSION,
180
+ capabilities: self.class._a2a_capabilities&.map(&:name) || [],
181
+ methods: self.class._a2a_methods&.keys || [],
182
+ timestamp: Time.now.iso8601
183
+ }
184
+ end
185
+
186
+ # Standard Rails actions for agent card and RPC handling
187
+
188
+ ##
189
+ # Serve the agent card
190
+ #
191
+ def agent_card
192
+ render_agent_card
193
+ end
194
+
195
+ ##
196
+ # Handle JSON-RPC requests
197
+ #
198
+ def rpc
199
+ handle_a2a_rpc
200
+ end
201
+
202
+ private
203
+
204
+ # Override authentication methods if needed
205
+ <% if with_authentication? %>
206
+
207
+ def current_user_info
208
+ if respond_to?(:current_user) && current_user.present?
209
+ {
210
+ id: current_user.id,
211
+ email: current_user.email,
212
+ name: current_user.name || current_user.email
213
+ }
214
+ else
215
+ { id: "anonymous", name: "Anonymous User" }
216
+ end
217
+ end
218
+
219
+ def current_user_permissions
220
+ # Customize based on your authorization system
221
+ if respond_to?(:current_user) && current_user.present?
222
+ ["read", "write"] # Example permissions
223
+ else
224
+ ["read"] # Anonymous permissions
225
+ end
226
+ end
227
+ <% end %>
228
+ end
@@ -0,0 +1,108 @@
1
+ # frozen_string_literal: true
2
+
3
+ # A2A Ruby SDK Configuration
4
+ #
5
+ # This file configures the A2A (Agent2Agent) Protocol integration for your Rails application.
6
+ # For more information, visit: https://a2a-protocol.org/sdk/ruby/
7
+
8
+ A2A.configure do |config|
9
+ # Enable Rails integration
10
+ config.rails_integration = true
11
+
12
+ # Mount path for A2A endpoints (default: "/a2a")
13
+ config.mount_path = "<%= mount_path %>"
14
+
15
+ # Protocol configuration
16
+ config.protocol_version = "0.3.0"
17
+ config.default_transport = "JSONRPC"
18
+
19
+ # Feature flags
20
+ config.streaming_enabled = true
21
+ config.push_notifications_enabled = true
22
+
23
+ # Default MIME types for input/output
24
+ config.default_input_modes = ["text/plain", "application/json"]
25
+ config.default_output_modes = ["text/plain", "application/json"]
26
+
27
+ # Middleware configuration
28
+ config.middleware_enabled = true
29
+ config.cors_enabled = true
30
+ config.rate_limiting_enabled = false
31
+ config.logging_enabled = Rails.env.development?
32
+
33
+ # Authentication configuration
34
+ config.authentication_required = <%= with_authentication? %>
35
+ config.webhook_authentication_required = false
36
+
37
+ # Storage configuration
38
+ <% case storage_backend %>
39
+ <% when "database" %>
40
+ # Database storage (requires running migrations)
41
+ config.task_storage = :database
42
+ <% when "redis" %>
43
+ # Redis storage configuration
44
+ config.task_storage = :redis
45
+ config.redis_config = {
46
+ url: ENV.fetch("REDIS_URL", "redis://localhost:6379/0"),
47
+ pool_size: 5,
48
+ pool_timeout: 5
49
+ }
50
+ <% else %>
51
+ # In-memory storage (default - not recommended for production)
52
+ config.task_storage = :memory
53
+ <% end %>
54
+
55
+ # Timeout configuration
56
+ config.default_timeout = 30
57
+
58
+ # Logging configuration
59
+ config.log_level = Rails.env.production? ? :info : :debug
60
+
61
+ # User agent for HTTP requests
62
+ config.user_agent = "#{Rails.application.class.module_parent_name}/#{Rails.application.config.version rescue '1.0.0'} A2A-Ruby/<%= a2a_version %>"
63
+ end
64
+
65
+ # Rails-specific configuration
66
+ Rails.application.configure do
67
+ # A2A engine configuration
68
+ config.a2a.enabled = true
69
+ config.a2a.mount_path = "<%= mount_path %>"
70
+ config.a2a.auto_mount = true
71
+
72
+ # Middleware configuration
73
+ config.a2a.middleware_enabled = true
74
+ config.a2a.cors_enabled = true
75
+ config.a2a.rate_limiting_enabled = false
76
+ config.a2a.logging_enabled = Rails.env.development?
77
+
78
+ # Authentication configuration
79
+ config.a2a.authentication_required = <%= with_authentication? %>
80
+ end
81
+
82
+ # Environment-specific configuration
83
+ case Rails.env
84
+ when "development"
85
+ A2A.configure do |config|
86
+ config.log_level = :debug
87
+ config.logging_enabled = true
88
+ end
89
+
90
+ when "test"
91
+ A2A.configure do |config|
92
+ config.task_storage = :memory
93
+ config.log_level = :warn
94
+ config.logging_enabled = false
95
+ end
96
+
97
+ when "production"
98
+ A2A.configure do |config|
99
+ config.log_level = :info
100
+ config.authentication_required = true
101
+ config.webhook_authentication_required = true
102
+
103
+ # Use Redis in production if available
104
+ if ENV["REDIS_URL"].present?
105
+ config.task_storage = :redis
106
+ end
107
+ end
108
+ end