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,309 @@
1
+ # Agent Execution Framework
2
+
3
+ The A2A Ruby SDK provides a powerful agent execution framework that allows you to create custom agents with sophisticated processing logic. This framework is event-driven and supports both synchronous and streaming responses.
4
+
5
+ ## Overview
6
+
7
+ The agent execution framework consists of several key components:
8
+
9
+ - **AgentExecutor**: Abstract base class for implementing agent logic
10
+ - **RequestContext**: Contains all information needed to process a request
11
+ - **EventQueue**: Manages event publishing and consumption
12
+ - **DefaultRequestHandler**: Integrates everything together
13
+
14
+ ## Creating Custom Agent Executors
15
+
16
+ ### Basic Agent Executor
17
+
18
+ ```ruby
19
+ class MyAgentExecutor < A2A::Server::AgentExecution::SimpleAgentExecutor
20
+ def process_message(message, task, context)
21
+ # Extract text from message parts
22
+ text_parts = message.parts.select { |part| part.is_a?(A2A::Types::TextPart) }
23
+ input_text = text_parts.map(&:text).join(" ")
24
+
25
+ # Process the input
26
+ response_text = generate_response(input_text)
27
+
28
+ # Create response message
29
+ response_message = A2A::Types::Message.new(
30
+ message_id: SecureRandom.uuid,
31
+ context_id: message.context_id,
32
+ role: "assistant",
33
+ parts: [A2A::Types::TextPart.new(text: response_text)]
34
+ )
35
+
36
+ # Return result
37
+ {
38
+ message: response_message.to_h,
39
+ processed_input: input_text,
40
+ timestamp: Time.now.utc.iso8601
41
+ }
42
+ end
43
+
44
+ private
45
+
46
+ def generate_response(input)
47
+ # Your custom logic here
48
+ "I received: #{input}"
49
+ end
50
+ end
51
+ ```
52
+
53
+ ### Advanced Agent Executor with Streaming
54
+
55
+ ```ruby
56
+ class StreamingAgentExecutor < A2A::Server::AgentExecution::AgentExecutor
57
+ def execute(context, event_queue)
58
+ # Create or get task
59
+ task = ensure_task(context)
60
+ publish_task(event_queue, task)
61
+
62
+ # Update to working state
63
+ publish_task_status_update(
64
+ event_queue,
65
+ task.id,
66
+ task.context_id,
67
+ A2A::Types::TaskStatus.new(
68
+ state: A2A::Types::TASK_STATE_WORKING,
69
+ message: "Processing request",
70
+ updated_at: Time.now.utc.iso8601
71
+ )
72
+ )
73
+
74
+ # Process message with streaming
75
+ if context.message
76
+ process_streaming_message(context.message, task, context, event_queue)
77
+ end
78
+
79
+ # Complete task
80
+ publish_task_status_update(
81
+ event_queue,
82
+ task.id,
83
+ task.context_id,
84
+ A2A::Types::TaskStatus.new(
85
+ state: A2A::Types::TASK_STATE_COMPLETED,
86
+ message: "Processing complete",
87
+ updated_at: Time.now.utc.iso8601
88
+ )
89
+ )
90
+ end
91
+
92
+ def cancel(context, event_queue)
93
+ publish_task_status_update(
94
+ event_queue,
95
+ context.task_id,
96
+ context.context_id,
97
+ A2A::Types::TaskStatus.new(
98
+ state: A2A::Types::TASK_STATE_CANCELED,
99
+ message: "Task canceled",
100
+ updated_at: Time.now.utc.iso8601
101
+ )
102
+ )
103
+ end
104
+
105
+ private
106
+
107
+ def process_streaming_message(message, task, context, event_queue)
108
+ text = message.parts.first.text
109
+ words = text.split
110
+
111
+ words.each_with_index do |word, index|
112
+ # Publish partial response
113
+ partial_message = A2A::Types::Message.new(
114
+ message_id: SecureRandom.uuid,
115
+ context_id: message.context_id,
116
+ role: "assistant",
117
+ parts: [A2A::Types::TextPart.new(text: word)]
118
+ )
119
+
120
+ publish_message(event_queue, partial_message)
121
+
122
+ # Simulate processing delay
123
+ sleep 0.1
124
+ end
125
+ end
126
+
127
+ def ensure_task(context)
128
+ # Create new task if needed
129
+ task_id = context.task_id || SecureRandom.uuid
130
+ context_id = context.context_id || SecureRandom.uuid
131
+
132
+ A2A::Types::Task.new(
133
+ id: task_id,
134
+ context_id: context_id,
135
+ status: A2A::Types::TaskStatus.new(
136
+ state: A2A::Types::TASK_STATE_SUBMITTED,
137
+ message: "Task created",
138
+ updated_at: Time.now.utc.iso8601
139
+ ),
140
+ history: context.message ? [context.message] : [],
141
+ metadata: {
142
+ created_at: Time.now.utc.iso8601,
143
+ executor: self.class.name
144
+ }
145
+ )
146
+ end
147
+ end
148
+ ```
149
+
150
+ ## Request Context
151
+
152
+ The `RequestContext` provides all the information needed to process a request:
153
+
154
+ ```ruby
155
+ # Access message data
156
+ if context.has_message?
157
+ message = context.message
158
+ text = message.parts.first.text
159
+ end
160
+
161
+ # Check if this is a new or continuing task
162
+ if context.new_task?
163
+ # Handle new task creation
164
+ else
165
+ # Continue existing task
166
+ task_id = context.task_id
167
+ end
168
+
169
+ # Access user information
170
+ if context.authenticated?
171
+ user = context.user
172
+ auth_data = context.authentication("oauth2")
173
+ end
174
+
175
+ # Access metadata
176
+ custom_data = context.get_metadata(:custom_key)
177
+ context.set_metadata(:processed_at, Time.now)
178
+ ```
179
+
180
+ ## Event System Integration
181
+
182
+ The agent executor publishes events that are automatically processed:
183
+
184
+ ```ruby
185
+ class MyExecutor < A2A::Server::AgentExecution::AgentExecutor
186
+ def execute(context, event_queue)
187
+ # Publish task events
188
+ publish_task(event_queue, task)
189
+
190
+ # Publish status updates
191
+ publish_task_status_update(event_queue, task_id, context_id, status)
192
+
193
+ # Publish artifact updates
194
+ publish_task_artifact_update(event_queue, task_id, context_id, artifact)
195
+
196
+ # Publish messages
197
+ publish_message(event_queue, message)
198
+ end
199
+ end
200
+ ```
201
+
202
+ ## Integration with Request Handler
203
+
204
+ ```ruby
205
+ # Create executor
206
+ executor = MyAgentExecutor.new
207
+
208
+ # Create request handler
209
+ handler = A2A::Server::DefaultRequestHandler.new(executor)
210
+
211
+ # Use with server applications
212
+ app = A2A::Server::Apps::RackApp.new(
213
+ agent_card: agent_card,
214
+ request_handler: handler
215
+ )
216
+ ```
217
+
218
+ ## Error Handling
219
+
220
+ ```ruby
221
+ class RobustAgentExecutor < A2A::Server::AgentExecution::SimpleAgentExecutor
222
+ def process_message(message, task, context)
223
+ begin
224
+ # Your processing logic
225
+ result = complex_processing(message)
226
+
227
+ # Return successful result
228
+ { result: result, status: "success" }
229
+ rescue StandardError => e
230
+ # Log error
231
+ A2A.logger.error("Processing failed", error: e.message)
232
+
233
+ # Return error result
234
+ {
235
+ error: {
236
+ message: e.message,
237
+ type: e.class.name
238
+ },
239
+ status: "error"
240
+ }
241
+ end
242
+ end
243
+
244
+ private
245
+
246
+ def complex_processing(message)
247
+ # Your complex logic that might fail
248
+ raise "Something went wrong" if message.parts.empty?
249
+
250
+ "Processed successfully"
251
+ end
252
+ end
253
+ ```
254
+
255
+ ## Best Practices
256
+
257
+ 1. **Keep Executors Focused**: Each executor should handle a specific type of agent logic
258
+ 2. **Use Events Properly**: Publish appropriate events for task lifecycle management
259
+ 3. **Handle Errors Gracefully**: Always catch and handle exceptions appropriately
260
+ 4. **Support Cancellation**: Implement the `cancel` method for long-running tasks
261
+ 5. **Use Context Effectively**: Leverage the request context for user and metadata access
262
+ 6. **Test Thoroughly**: Write comprehensive tests for your agent executors
263
+
264
+ ## Testing Agent Executors
265
+
266
+ ```ruby
267
+ RSpec.describe MyAgentExecutor do
268
+ let(:executor) { described_class.new }
269
+ let(:event_queue) { A2A::Server::Events::InMemoryEventQueue.new }
270
+ let(:message) { create_test_message("Hello, agent!") }
271
+ let(:context) { create_test_context(message: message) }
272
+
273
+ describe "#execute" do
274
+ it "processes messages correctly" do
275
+ events = []
276
+ event_queue.subscribe { |event| events << event }
277
+
278
+ executor.execute(context, event_queue)
279
+
280
+ expect(events).to include(have_attributes(type: "task"))
281
+ expect(events).to include(have_attributes(type: "task_status_update"))
282
+ end
283
+ end
284
+
285
+ describe "#cancel" do
286
+ it "cancels tasks properly" do
287
+ events = []
288
+ event_queue.subscribe { |event| events << event }
289
+
290
+ executor.cancel(context, event_queue)
291
+
292
+ canceled_event = events.find { |e| e.type == "task_status_update" }
293
+ expect(canceled_event.data.status.state).to eq("canceled")
294
+ end
295
+ end
296
+ end
297
+ ```
298
+
299
+ This framework provides the flexibility to create sophisticated agents while maintaining consistency with the A2A protocol and ensuring proper integration with the broader SDK ecosystem.
300
+
301
+ ## Complete Examples
302
+
303
+ For complete working examples of agent executors in action, see the [A2A Ruby Samples Repository](https://github.com/a2aproject/a2a-ruby-samples), which includes:
304
+
305
+ - **Hello World Agent** - Basic agent executor implementation
306
+ - **Dice Agent** - Interactive agent with function calling
307
+ - **Weather Agent** - Real-world service integration
308
+ - **Rails Integration** - Production Rails applications
309
+ - **Streaming Chat Agent** - Real-time communication examples