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,765 @@
1
+ # Troubleshooting Guide
2
+
3
+ This guide helps you diagnose and resolve common issues when using the A2A Ruby SDK.
4
+
5
+ ## Table of Contents
6
+
7
+ - [Connection Issues](#connection-issues)
8
+ - [Authentication Problems](#authentication-problems)
9
+ - [Protocol Errors](#protocol-errors)
10
+ - [Performance Issues](#performance-issues)
11
+ - [Rails Integration Issues](#rails-integration-issues)
12
+ - [Debugging Tools](#debugging-tools)
13
+ - [Common Error Codes](#common-error-codes)
14
+ - [Frequently Asked Questions](#frequently-asked-questions)
15
+
16
+ ## Connection Issues
17
+
18
+ ### Cannot Connect to Agent
19
+
20
+ **Symptoms:**
21
+ - `A2A::Errors::HTTPError: Connection refused`
22
+ - `A2A::Errors::TimeoutError: Request timeout`
23
+
24
+ **Solutions:**
25
+
26
+ 1. **Check the endpoint URL:**
27
+ ```ruby
28
+ # Verify the URL is correct and accessible
29
+ client = A2A::Client::HttpClient.new("https://agent.example.com/a2a")
30
+
31
+ # Test basic connectivity
32
+ begin
33
+ card = client.get_card
34
+ puts "Connection successful"
35
+ rescue A2A::Errors::HTTPError => e
36
+ puts "Connection failed: #{e.message}"
37
+ end
38
+ ```
39
+
40
+ 2. **Verify SSL certificates:**
41
+ ```ruby
42
+ # For development, you might need to disable SSL verification
43
+ require 'faraday'
44
+
45
+ client = A2A::Client::HttpClient.new("https://localhost:3000/a2a") do |conn|
46
+ conn.ssl.verify = false # Only for development!
47
+ end
48
+ ```
49
+
50
+ 3. **Check firewall and network settings:**
51
+ ```bash
52
+ # Test basic connectivity
53
+ curl -v https://agent.example.com/a2a/agent-card
54
+
55
+ # Check DNS resolution
56
+ nslookup agent.example.com
57
+ ```
58
+
59
+ ### Timeout Issues
60
+
61
+ **Symptoms:**
62
+ - Requests taking too long
63
+ - `A2A::Errors::TimeoutError`
64
+
65
+ **Solutions:**
66
+
67
+ 1. **Increase timeout:**
68
+ ```ruby
69
+ config = A2A::Client::Config.new
70
+ config.timeout = 120 # 2 minutes
71
+
72
+ client = A2A::Client::HttpClient.new(url, config: config)
73
+ ```
74
+
75
+ 2. **Use streaming for long operations:**
76
+ ```ruby
77
+ # Instead of blocking calls, use streaming
78
+ client.send_message(message) do |response|
79
+ # Handle responses as they arrive
80
+ puts "Received: #{response}"
81
+ end
82
+ ```
83
+
84
+ 3. **Implement retry logic:**
85
+ ```ruby
86
+ require 'retries'
87
+
88
+ with_retries(max_tries: 3, base_sleep_seconds: 1, max_sleep_seconds: 5) do
89
+ client.send_message(message)
90
+ end
91
+ ```
92
+
93
+ ## Authentication Problems
94
+
95
+ ### Invalid Credentials
96
+
97
+ **Symptoms:**
98
+ - `A2A::Errors::AuthenticationError: Invalid credentials`
99
+ - HTTP 401 Unauthorized responses
100
+
101
+ **Solutions:**
102
+
103
+ 1. **Verify OAuth 2.0 configuration:**
104
+ ```ruby
105
+ auth = A2A::Client::Auth::OAuth2.new(
106
+ client_id: ENV['A2A_CLIENT_ID'],
107
+ client_secret: ENV['A2A_CLIENT_SECRET'],
108
+ token_url: "https://auth.example.com/oauth/token"
109
+ )
110
+
111
+ # Test token acquisition
112
+ begin
113
+ token = auth.get_token
114
+ puts "Token acquired: #{token[0..20]}..."
115
+ rescue => e
116
+ puts "Token error: #{e.message}"
117
+ end
118
+ ```
119
+
120
+ 2. **Check JWT token validity:**
121
+ ```ruby
122
+ require 'jwt'
123
+
124
+ token = "your-jwt-token"
125
+ begin
126
+ payload = JWT.decode(token, nil, false) # Don't verify for debugging
127
+ puts "Token payload: #{payload}"
128
+ puts "Expires at: #{Time.at(payload[0]['exp'])}"
129
+ rescue JWT::DecodeError => e
130
+ puts "Invalid JWT: #{e.message}"
131
+ end
132
+ ```
133
+
134
+ 3. **Verify API key configuration:**
135
+ ```ruby
136
+ auth = A2A::Client::Auth::ApiKey.new(
137
+ key: ENV['A2A_API_KEY'],
138
+ header: "X-API-Key" # or parameter: "api_key"
139
+ )
140
+
141
+ # Test with debug logging
142
+ A2A.configure { |c| c.log_level = :debug }
143
+ client = A2A::Client::HttpClient.new(url, auth: auth)
144
+ ```
145
+
146
+ ### Token Expiration
147
+
148
+ **Symptoms:**
149
+ - Authentication works initially, then fails
150
+ - `A2A::Errors::AuthenticationError: Token expired`
151
+
152
+ **Solutions:**
153
+
154
+ 1. **Implement automatic token refresh:**
155
+ ```ruby
156
+ class RefreshableAuth < A2A::Client::Auth::OAuth2
157
+ def apply_auth(request)
158
+ if token_expired?
159
+ refresh_token!
160
+ end
161
+ super
162
+ end
163
+
164
+ private
165
+
166
+ def token_expired?
167
+ @token_expires_at && Time.current >= @token_expires_at
168
+ end
169
+
170
+ def refresh_token!
171
+ @token, @token_expires_at = get_token
172
+ end
173
+ end
174
+ ```
175
+
176
+ 2. **Handle auth errors gracefully:**
177
+ ```ruby
178
+ begin
179
+ response = client.send_message(message)
180
+ rescue A2A::Errors::AuthenticationError
181
+ # Refresh credentials and retry
182
+ client.auth.refresh!
183
+ response = client.send_message(message)
184
+ end
185
+ ```
186
+
187
+ ## Protocol Errors
188
+
189
+ ### Invalid JSON-RPC Format
190
+
191
+ **Symptoms:**
192
+ - `A2A::Errors::InvalidRequest: Invalid JSON-RPC format`
193
+ - `A2A::Errors::ParseError: Invalid JSON`
194
+
195
+ **Solutions:**
196
+
197
+ 1. **Validate message structure:**
198
+ ```ruby
199
+ message = A2A::Types::Message.new(
200
+ message_id: SecureRandom.uuid, # Required
201
+ role: "user", # Required: "user" or "agent"
202
+ parts: [ # Required: array of parts
203
+ A2A::Types::TextPart.new(text: "Hello")
204
+ ]
205
+ )
206
+
207
+ # Validate before sending
208
+ if message.valid?
209
+ client.send_message(message)
210
+ else
211
+ puts "Invalid message: #{message.errors.full_messages}"
212
+ end
213
+ ```
214
+
215
+ 2. **Check JSON-RPC request format:**
216
+ ```ruby
217
+ # Manual JSON-RPC request (for debugging)
218
+ request = {
219
+ jsonrpc: "2.0", # Required
220
+ method: "message/send", # Required
221
+ params: message.to_h, # Optional
222
+ id: 1 # Required for requests (omit for notifications)
223
+ }
224
+ ```
225
+
226
+ ### Method Not Found
227
+
228
+ **Symptoms:**
229
+ - `A2A::Errors::MethodNotFound: Method 'xyz' not found`
230
+
231
+ **Solutions:**
232
+
233
+ 1. **Check agent card for available methods:**
234
+ ```ruby
235
+ card = client.get_card
236
+ puts "Available capabilities:"
237
+ card.capabilities.each do |capability|
238
+ puts "- #{capability.name}: #{capability.description}"
239
+ end
240
+ ```
241
+
242
+ 2. **Verify method name spelling:**
243
+ ```ruby
244
+ # Standard A2A methods
245
+ valid_methods = [
246
+ "message/send",
247
+ "message/stream",
248
+ "tasks/get",
249
+ "tasks/cancel",
250
+ "tasks/resubscribe",
251
+ "tasks/pushNotificationConfig/set",
252
+ "tasks/pushNotificationConfig/get",
253
+ "tasks/pushNotificationConfig/list",
254
+ "tasks/pushNotificationConfig/delete",
255
+ "agent/getAuthenticatedExtendedCard"
256
+ ]
257
+ ```
258
+
259
+ ### Task Errors
260
+
261
+ **Symptoms:**
262
+ - `A2A::Errors::TaskNotFound: Task not found`
263
+ - `A2A::Errors::TaskNotCancelable: Task cannot be canceled`
264
+
265
+ **Solutions:**
266
+
267
+ 1. **Check task status before operations:**
268
+ ```ruby
269
+ begin
270
+ task = client.get_task(task_id)
271
+ puts "Task state: #{task.status.state}"
272
+
273
+ if task.status.state.in?(['submitted', 'working'])
274
+ client.cancel_task(task_id)
275
+ else
276
+ puts "Task cannot be canceled (state: #{task.status.state})"
277
+ end
278
+ rescue A2A::Errors::TaskNotFound
279
+ puts "Task #{task_id} not found"
280
+ end
281
+ ```
282
+
283
+ 2. **Handle task lifecycle properly:**
284
+ ```ruby
285
+ # Valid task states
286
+ CANCELABLE_STATES = ['submitted', 'working'].freeze
287
+ FINAL_STATES = ['completed', 'canceled', 'failed', 'rejected'].freeze
288
+
289
+ def can_cancel_task?(task)
290
+ CANCELABLE_STATES.include?(task.status.state)
291
+ end
292
+
293
+ def task_finished?(task)
294
+ FINAL_STATES.include?(task.status.state)
295
+ end
296
+ ```
297
+
298
+ ## Performance Issues
299
+
300
+ ### Slow Response Times
301
+
302
+ **Symptoms:**
303
+ - Requests taking longer than expected
304
+ - High memory usage
305
+
306
+ **Solutions:**
307
+
308
+ 1. **Enable connection pooling:**
309
+ ```ruby
310
+ require 'faraday/net_http_persistent'
311
+
312
+ client = A2A::Client::HttpClient.new(url) do |conn|
313
+ conn.adapter :net_http_persistent
314
+ end
315
+ ```
316
+
317
+ 2. **Use streaming for large responses:**
318
+ ```ruby
319
+ # Instead of loading everything into memory
320
+ client.send_message(message, streaming: true) do |chunk|
321
+ process_chunk(chunk) # Process incrementally
322
+ end
323
+ ```
324
+
325
+ 3. **Monitor performance:**
326
+ ```ruby
327
+ A2A.configure do |config|
328
+ config.enable_metrics = true
329
+ config.log_level = :info
330
+ end
331
+
332
+ # Add custom timing
333
+ start_time = Time.current
334
+ response = client.send_message(message)
335
+ duration = Time.current - start_time
336
+ puts "Request took #{duration}s"
337
+ ```
338
+
339
+ ### Memory Leaks
340
+
341
+ **Symptoms:**
342
+ - Increasing memory usage over time
343
+ - Out of memory errors
344
+
345
+ **Solutions:**
346
+
347
+ 1. **Properly close streaming connections:**
348
+ ```ruby
349
+ enumerator = client.send_message(message)
350
+ begin
351
+ enumerator.each do |response|
352
+ process_response(response)
353
+ end
354
+ ensure
355
+ enumerator.close if enumerator.respond_to?(:close)
356
+ end
357
+ ```
358
+
359
+ 2. **Limit message history:**
360
+ ```ruby
361
+ # When getting tasks, limit history
362
+ task = client.get_task(task_id, history_length: 10)
363
+ ```
364
+
365
+ 3. **Use object pooling for frequent operations:**
366
+ ```ruby
367
+ class MessagePool
368
+ def initialize
369
+ @pool = []
370
+ end
371
+
372
+ def get_message
373
+ @pool.pop || A2A::Types::Message.allocate
374
+ end
375
+
376
+ def return_message(message)
377
+ message.reset!
378
+ @pool.push(message) if @pool.size < 100
379
+ end
380
+ end
381
+ ```
382
+
383
+ ## Rails Integration Issues
384
+
385
+ ### Routes Not Working
386
+
387
+ **Symptoms:**
388
+ - 404 errors for A2A endpoints
389
+ - Routes not appearing in `rails routes`
390
+
391
+ **Solutions:**
392
+
393
+ 1. **Verify engine mounting:**
394
+ ```ruby
395
+ # config/routes.rb
396
+ Rails.application.routes.draw do
397
+ mount A2A::Engine => "/a2a"
398
+ end
399
+ ```
400
+
401
+ 2. **Check route generation:**
402
+ ```bash
403
+ rails routes | grep a2a
404
+ # Should show:
405
+ # POST /a2a/rpc
406
+ # GET /a2a/agent-card
407
+ # GET /a2a/capabilities
408
+ ```
409
+
410
+ 3. **Verify controller inclusion:**
411
+ ```ruby
412
+ class MyAgentController < ApplicationController
413
+ include A2A::Rails::ControllerHelpers # Required
414
+
415
+ # Your A2A methods here
416
+ end
417
+ ```
418
+
419
+ ### Database Issues
420
+
421
+ **Symptoms:**
422
+ - Task storage errors
423
+ - Migration failures
424
+
425
+ **Solutions:**
426
+
427
+ 1. **Run A2A migrations:**
428
+ ```bash
429
+ rails generate a2a:migration
430
+ rails db:migrate
431
+ ```
432
+
433
+ 2. **Check database configuration:**
434
+ ```ruby
435
+ # config/initializers/a2a.rb
436
+ A2A.configure do |config|
437
+ config.storage_backend = :database # or :memory, :redis
438
+ config.database_url = ENV['DATABASE_URL']
439
+ end
440
+ ```
441
+
442
+ 3. **Verify model associations:**
443
+ ```ruby
444
+ # Check if models are properly loaded
445
+ A2A::Server::Models::Task.first
446
+ A2A::Server::Models::PushNotificationConfig.first
447
+ ```
448
+
449
+ ## Debugging Tools
450
+
451
+ ### Enable Debug Logging
452
+
453
+ ```ruby
454
+ A2A.configure do |config|
455
+ config.log_level = :debug
456
+ config.log_requests = true
457
+ config.log_responses = true
458
+ end
459
+ ```
460
+
461
+ ### Use the Console
462
+
463
+ ```bash
464
+ # Rails console
465
+ rails console
466
+
467
+ # Gem console
468
+ cd a2a-ruby && bin/console
469
+ ```
470
+
471
+ ```ruby
472
+ # Test basic functionality
473
+ client = A2A::Client::HttpClient.new("http://localhost:3000/a2a")
474
+ card = client.get_card
475
+ puts JSON.pretty_generate(card.to_h)
476
+ ```
477
+
478
+ ### Network Debugging
479
+
480
+ ```ruby
481
+ # Add request/response logging
482
+ require 'faraday/logging'
483
+
484
+ client = A2A::Client::HttpClient.new(url) do |conn|
485
+ conn.response :logger, Rails.logger, bodies: true
486
+ end
487
+ ```
488
+
489
+ ### Performance Profiling
490
+
491
+ ```ruby
492
+ require 'ruby-prof'
493
+
494
+ RubyProf.start
495
+ client.send_message(message)
496
+ result = RubyProf.stop
497
+
498
+ # Print results
499
+ printer = RubyProf::FlatPrinter.new(result)
500
+ printer.print(STDOUT)
501
+ ```
502
+
503
+ ## Error Hierarchy
504
+
505
+ The A2A Ruby SDK provides a comprehensive error hierarchy:
506
+
507
+ ```
508
+ StandardError
509
+ └── A2A::Errors::A2AError
510
+ ├── JSON-RPC Standard Errors
511
+ │ ├── A2A::Errors::ParseError (-32700)
512
+ │ ├── A2A::Errors::InvalidRequest (-32600)
513
+ │ ├── A2A::Errors::MethodNotFound (-32601)
514
+ │ ├── A2A::Errors::InvalidParams (-32602)
515
+ │ └── A2A::Errors::InternalError (-32603)
516
+ ├── A2A Protocol Errors
517
+ │ ├── A2A::Errors::TaskNotFound (-32001)
518
+ │ ├── A2A::Errors::TaskNotCancelable (-32002)
519
+ │ └── A2A::Errors::AuthenticationRequired (-32003)
520
+ ├── Transport Errors
521
+ │ ├── A2A::Errors::HTTPError
522
+ │ ├── A2A::Errors::TimeoutError
523
+ │ └── A2A::Errors::ConnectionError
524
+ └── Configuration Errors
525
+ └── A2A::Errors::ConfigurationError
526
+ ```
527
+
528
+ ## Error Handling Patterns
529
+
530
+ ### Client-Side Error Handling
531
+
532
+ ```ruby
533
+ begin
534
+ response = client.send_message(message)
535
+ rescue A2A::Errors::MethodNotFound => e
536
+ puts "Method not supported: #{e.message}"
537
+ rescue A2A::Errors::AuthenticationRequired => e
538
+ puts "Authentication needed: #{e.message}"
539
+ rescue A2A::Errors::HTTPError => e
540
+ puts "HTTP error: #{e.message}"
541
+ rescue A2A::Errors::A2AError => e
542
+ puts "A2A error: #{e.message}"
543
+ end
544
+ ```
545
+
546
+ ### Server-Side Error Handling
547
+
548
+ ```ruby
549
+ a2a_method "risky_operation" do |params|
550
+ begin
551
+ # Your operation
552
+ { success: true }
553
+ rescue ArgumentError => e
554
+ raise A2A::Errors::InvalidParams, "Invalid parameters: #{e.message}"
555
+ rescue StandardError => e
556
+ raise A2A::Errors::InternalError, "Operation failed: #{e.message}"
557
+ end
558
+ end
559
+ ```
560
+
561
+ ## Common Error Codes
562
+
563
+ ### JSON-RPC Standard Errors
564
+
565
+ | Code | Error | Description |
566
+ |------|-------|-------------|
567
+ | -32700 | Parse error | Invalid JSON |
568
+ | -32600 | Invalid Request | Invalid JSON-RPC format |
569
+ | -32601 | Method not found | Method doesn't exist |
570
+ | -32602 | Invalid params | Invalid method parameters |
571
+ | -32603 | Internal error | Server internal error |
572
+
573
+ ### A2A-Specific Errors
574
+
575
+ | Code | Error | Description |
576
+ |------|-------|-------------|
577
+ | -32001 | Task not found | Task ID doesn't exist |
578
+ | -32002 | Task not cancelable | Task in non-cancelable state |
579
+ | -32003 | Invalid task state | Invalid state transition |
580
+ | -32004 | Authentication required | Auth needed for operation |
581
+ | -32005 | Insufficient permissions | User lacks required permissions |
582
+ | -32006 | Rate limit exceeded | Too many requests |
583
+ | -32007 | Invalid agent card | Agent card validation failed |
584
+ | -32008 | Transport not supported | Requested transport unavailable |
585
+ | -32009 | Invalid message format | Message doesn't match schema |
586
+ | -32010 | Service unavailable | Temporary service outage |
587
+
588
+ ## Frequently Asked Questions
589
+
590
+ ### What Ruby versions are supported?
591
+
592
+ - Ruby 2.7 or higher
593
+ - Rails 6.0+ (for Rails integration)
594
+ - JRuby and TruffleRuby compatibility
595
+
596
+ ### Do I need Rails to use A2A Ruby SDK?
597
+
598
+ No! The SDK works with any Ruby application:
599
+ - Plain Ruby scripts
600
+ - Sinatra applications
601
+ - Rack applications
602
+ - Rails applications (with enhanced integration)
603
+
604
+ ### How do I connect to an A2A agent?
605
+
606
+ ```ruby
607
+ require 'a2a'
608
+
609
+ client = A2A::Client::HttpClient.new("https://agent.example.com/a2a")
610
+
611
+ message = A2A::Types::Message.new(
612
+ message_id: SecureRandom.uuid,
613
+ role: "user",
614
+ parts: [A2A::Types::TextPart.new(text: "Hello!")]
615
+ )
616
+
617
+ client.send_message(message) do |response|
618
+ puts response
619
+ end
620
+ ```
621
+
622
+ ### How do I handle authentication?
623
+
624
+ ```ruby
625
+ # OAuth 2.0
626
+ client = A2A::Client::HttpClient.new("https://agent.example.com/a2a") do |config|
627
+ config.auth_strategy = :oauth2
628
+ config.oauth2_token = "your_access_token"
629
+ end
630
+
631
+ # API Key
632
+ client = A2A::Client::HttpClient.new("https://agent.example.com/a2a") do |config|
633
+ config.auth_strategy = :api_key
634
+ config.api_key = "your_api_key"
635
+ end
636
+ ```
637
+
638
+ ### How do I create a simple agent?
639
+
640
+ ```ruby
641
+ class MyAgent
642
+ include A2A::Server::Agent
643
+
644
+ a2a_method "greet" do |params|
645
+ { message: "Hello, #{params[:name] || 'there'}!" }
646
+ end
647
+ end
648
+ ```
649
+
650
+ ### Q: Why am I getting SSL certificate errors?
651
+
652
+ A: For development with self-signed certificates:
653
+
654
+ ```ruby
655
+ # Disable SSL verification (development only!)
656
+ client = A2A::Client::HttpClient.new(url) do |conn|
657
+ conn.ssl.verify = false
658
+ end
659
+
660
+ # Or set certificate bundle
661
+ client = A2A::Client::HttpClient.new(url) do |conn|
662
+ conn.ssl.ca_file = '/path/to/ca-bundle.crt'
663
+ end
664
+ ```
665
+
666
+ ### Q: How do I handle network interruptions in streaming?
667
+
668
+ A: Implement reconnection logic:
669
+
670
+ ```ruby
671
+ def stream_with_reconnect(client, message, max_retries: 3)
672
+ retries = 0
673
+
674
+ begin
675
+ client.send_message(message) do |response|
676
+ yield response
677
+ end
678
+ rescue A2A::Errors::HTTPError, A2A::Errors::TimeoutError => e
679
+ retries += 1
680
+ if retries <= max_retries
681
+ sleep(2 ** retries) # Exponential backoff
682
+ retry
683
+ else
684
+ raise e
685
+ end
686
+ end
687
+ end
688
+ ```
689
+
690
+ ### Q: How do I test A2A agents in my test suite?
691
+
692
+ A: Use test doubles and helpers:
693
+
694
+ ```ruby
695
+ # spec/support/a2a_helpers.rb
696
+ RSpec.configure do |config|
697
+ config.include A2AHelpers
698
+ end
699
+
700
+ # In your tests
701
+ it "handles A2A messages" do
702
+ message = build_a2a_message(text: "test")
703
+ client = mock_a2a_client(send_message: mock_response)
704
+
705
+ result = client.send_message(message)
706
+ expect(result).to be_a(A2A::Types::Message)
707
+ end
708
+ ```
709
+
710
+ ### Q: Can I use A2A with other Ruby web frameworks?
711
+
712
+ A: Yes! The core SDK works with any Ruby application:
713
+
714
+ ```ruby
715
+ # Sinatra example
716
+ require 'sinatra'
717
+ require 'a2a'
718
+
719
+ class MyAgent
720
+ include A2A::Server::Agent
721
+ # Define your methods
722
+ end
723
+
724
+ post '/a2a/rpc' do
725
+ agent = MyAgent.new
726
+ request_body = request.body.read
727
+
728
+ json_rpc_request = A2A::Protocol::JsonRpc.parse_request(request_body)
729
+ response = agent.handle_a2a_request(json_rpc_request)
730
+
731
+ content_type :json
732
+ response.to_json
733
+ end
734
+ ```
735
+
736
+ ### Q: How do I implement custom middleware?
737
+
738
+ A: Create middleware classes:
739
+
740
+ ```ruby
741
+ class CustomLoggingMiddleware
742
+ def initialize(app)
743
+ @app = app
744
+ end
745
+
746
+ def call(request)
747
+ start_time = Time.current
748
+
749
+ response = @app.call(request)
750
+
751
+ duration = Time.current - start_time
752
+ Rails.logger.info "A2A Request: #{request.method} (#{duration}s)"
753
+
754
+ response
755
+ end
756
+ end
757
+
758
+ # Add to client
759
+ client.add_middleware(CustomLoggingMiddleware)
760
+ ```
761
+
762
+ For more help:
763
+ - [GitHub Issues](https://github.com/a2aproject/a2a-ruby/issues)
764
+ - [Discussions](https://github.com/a2aproject/a2a-ruby/discussions)
765
+ - [API Documentation](https://rubydoc.info/gems/a2a-ruby)