Module: A2A::Server::Agent
- Included in:
- ExampleAgent
- Defined in:
- lib/a2a/server/agent.rb
Overview
Agent DSL for defining A2A-compatible methods and capabilities
This module provides a DSL for defining agent methods that can be called via the A2A protocol. It includes method registration, capability definition, parameter validation, and middleware support.
Defined Under Namespace
Modules: ClassMethods
Class Method Summary collapse
Instance Method Summary collapse
-
#build_middleware_chain(_method_def, context) ⇒ Proc
private
Build the middleware chain for method execution.
-
#execute_method(method_def, params, context) ⇒ Object
Execute the actual method implementation.
-
#execute_with_middleware(method_def, params, context) ⇒ Object
Execute a method with the middleware chain.
-
#handle_a2a_request(request, context: nil) ⇒ Hash
Handle an A2A JSON-RPC request.
-
#validate_security_requirements(method_def, context) ⇒ Object
private
Validate security requirements for a method.
Class Method Details
.included(base) ⇒ Object
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
# File 'lib/a2a/server/agent.rb', line 31 def self.included(base) base.extend(ClassMethods) # Initialize class-level storage for A2A methods and capabilities if defined?(ActiveSupport) && base.respond_to?(:class_attribute) # Use ActiveSupport's class_attribute if available base.class_attribute :_a2a_methods, default: {} base.class_attribute :_a2a_capabilities, default: A2A::Protocol::CapabilityRegistry.new base.class_attribute :_a2a_config, default: {} base.class_attribute :_a2a_middleware, default: [] else # Fallback implementation without ActiveSupport base.instance_variable_set(:@_a2a_methods, {}) base.instance_variable_set(:@_a2a_capabilities, A2A::Protocol::CapabilityRegistry.new) base.instance_variable_set(:@_a2a_config, {}) base.instance_variable_set(:@_a2a_middleware, []) # Define accessor methods base.define_singleton_method(:_a2a_methods) { @_a2a_methods } base.define_singleton_method(:_a2a_capabilities) { @_a2a_capabilities } base.define_singleton_method(:_a2a_config) { @_a2a_config } base.define_singleton_method(:_a2a_middleware) { @_a2a_middleware } end end |
Instance Method Details
#build_middleware_chain(_method_def, context) ⇒ Proc (private)
Build the middleware chain for method execution
324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 |
# File 'lib/a2a/server/agent.rb', line 324 def build_middleware_chain(_method_def, context) # Combine class-level and method-level middleware all_middleware = self.class._a2a_middleware.dup # Build the chain from the inside out chain = ->(_params, &block) { block.call } all_middleware.reverse_each do |middleware_def| middleware_class = middleware_def[:class] = middleware_def[:options] # Create middleware instance middleware = middleware_class.new(**) # Wrap the current chain current_chain = chain chain = lambda do |params, &block| middleware.call(params, context) do current_chain.call(params, &block) end end end chain end |
#execute_method(method_def, params, context) ⇒ Object
Execute the actual method implementation
273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 |
# File 'lib/a2a/server/agent.rb', line 273 def execute_method(method_def, params, context) handler = method_def[:handler] # Call the handler with appropriate parameters case handler.arity when 0 instance_exec(&handler) when 1 instance_exec(params, &handler) when 2 instance_exec(params, context, &handler) else # For methods with more parameters, pass params and context instance_exec(params, context, &handler) end end |
#execute_with_middleware(method_def, params, context) ⇒ Object
Execute a method with the middleware chain
255 256 257 258 259 260 261 262 263 264 |
# File 'lib/a2a/server/agent.rb', line 255 def execute_with_middleware(method_def, params, context) # Build middleware chain middleware_chain = build_middleware_chain(method_def, context) # Execute the chain middleware_chain.call(params) do # Execute the actual method execute_method(method_def, params, context) end end |
#handle_a2a_request(request, context: nil) ⇒ Hash
Handle an A2A JSON-RPC request
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 |
# File 'lib/a2a/server/agent.rb', line 210 def handle_a2a_request(request, context: nil) method_name = request.method method_def = self.class.a2a_method_definition(method_name) raise A2A::Errors::MethodNotFound, "Method '#{method_name}' not found" unless method_def # Create context if not provided context ||= A2A::Server::Context.new(request: request) # Validate security requirements validate_security_requirements(method_def, context) # Execute with middleware chain result = execute_with_middleware(method_def, request.params, context) # Build response A2A::Protocol::JsonRpc.build_response(result: result, id: request.id) unless request.notification? rescue A2A::Errors::A2AError => e # Return error response for A2A errors unless request.notification? A2A::Protocol::JsonRpc.build_error_response( code: e.code, message: e., data: e.data, id: request.id ) end rescue StandardError => e # Convert other errors to internal errors unless request.notification? A2A::Protocol::JsonRpc.build_error_response( code: A2A::Protocol::JsonRpc::INTERNAL_ERROR, message: e., id: request.id ) end end |
#validate_security_requirements(method_def, context) ⇒ Object (private)
Validate security requirements for a method
299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 |
# File 'lib/a2a/server/agent.rb', line 299 def validate_security_requirements(method_def, context) security_requirements = method_def[:security] || [] return if security_requirements.empty? # Check if any required security scheme is satisfied satisfied = security_requirements.any? do |scheme| context.authenticated_with?(scheme) end return if satisfied if context.authenticated? raise A2A::Errors::AuthorizationFailed, "Method requires one of: #{security_requirements.join(', ')}" end raise A2A::Errors::AuthenticationRequired, "Method requires authentication with: #{security_requirements.join(', ')}" end |