Class: A2A::Protocol::Capability

Inherits:
Object
  • Object
show all
Defined in:
lib/a2a/protocol/capability.rb

Overview

Represents a capability definition for A2A methods

Capabilities define the methods that an agent can perform, including input/output schemas, validation rules, and metadata.

Examples:

Defining a capability

capability = A2A::Protocol::Capability.new(
  name: "analyze_text",
  description: "Analyze text content for sentiment and topics",
  method: "text/analyze",
  input_schema: {
    type: "object",
    properties: {
      text: { type: "string" },
      options: { type: "object" }
    },
    required: ["text"]
  },
  output_schema: {
    type: "object",
    properties: {
      sentiment: { type: "string" },
      topics: { type: "array", items: { type: "string" } }
    }
  }
)

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name:, description:, method:, input_schema: nil, output_schema: nil, examples: nil, tags: nil, security_requirements: nil, metadata: nil, streaming_supported: false, async_supported: false) ⇒ Capability

Initialize a new capability

Parameters:

  • Capability name (required)

  • Capability description (required)

  • A2A method name (required)

  • (defaults to: nil)

    JSON Schema for input validation

  • (defaults to: nil)

    JSON Schema for output validation

  • (defaults to: nil)

    Usage examples

  • (defaults to: nil)

    Capability tags

  • (defaults to: nil)

    Required security schemes

  • (defaults to: nil)

    Additional metadata

  • (defaults to: false)

    Whether streaming is supported

  • (defaults to: false)

    Whether async execution is supported



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/a2a/protocol/capability.rb', line 52

def initialize(name:, description:, method:, input_schema: nil, output_schema: nil,
               examples: nil, tags: nil, security_requirements: nil, metadata: nil,
               streaming_supported: false, async_supported: false)
  @name = name
  @description = description
  @method = method
  @input_schema = input_schema
  @output_schema = output_schema
  @examples = examples
  @tags = tags
  @security_requirements = security_requirements
   = 
  @streaming_supported = streaming_supported
  @async_supported = async_supported

  validate!
end

Instance Attribute Details

#async_supportedObject (readonly)

Returns the value of attribute async_supported.



34
35
36
# File 'lib/a2a/protocol/capability.rb', line 34

def async_supported
  @async_supported
end

#descriptionObject (readonly)

Returns the value of attribute description.



34
35
36
# File 'lib/a2a/protocol/capability.rb', line 34

def description
  @description
end

#examplesObject (readonly)

Returns the value of attribute examples.



34
35
36
# File 'lib/a2a/protocol/capability.rb', line 34

def examples
  @examples
end

#input_schemaObject (readonly)

Returns the value of attribute input_schema.



34
35
36
# File 'lib/a2a/protocol/capability.rb', line 34

def input_schema
  @input_schema
end

#metadataObject (readonly)

Returns the value of attribute metadata.



34
35
36
# File 'lib/a2a/protocol/capability.rb', line 34

def 
  
end

#methodObject (readonly)

Returns the value of attribute method.



34
35
36
# File 'lib/a2a/protocol/capability.rb', line 34

def method
  @method
end

#nameObject (readonly)

Returns the value of attribute name.



34
35
36
# File 'lib/a2a/protocol/capability.rb', line 34

def name
  @name
end

#output_schemaObject (readonly)

Returns the value of attribute output_schema.



34
35
36
# File 'lib/a2a/protocol/capability.rb', line 34

def output_schema
  @output_schema
end

#security_requirementsObject (readonly)

Returns the value of attribute security_requirements.



34
35
36
# File 'lib/a2a/protocol/capability.rb', line 34

def security_requirements
  @security_requirements
end

#streaming_supportedObject (readonly)

Returns the value of attribute streaming_supported.



34
35
36
# File 'lib/a2a/protocol/capability.rb', line 34

def streaming_supported
  @streaming_supported
end

#tagsObject (readonly)

Returns the value of attribute tags.



34
35
36
# File 'lib/a2a/protocol/capability.rb', line 34

def tags
  @tags
end

Class Method Details

.from_h(hash) ⇒ Capability

Create from hash representation

Parameters:

  • The hash to create from

Returns:

  • The new capability instance



157
158
159
160
161
162
163
164
165
166
167
168
# File 'lib/a2a/protocol/capability.rb', line 157

def self.from_h(hash)
  return nil if hash.nil?

  # Convert string keys to symbols
  normalized_hash = {}
  hash.each do |key, value|
    snake_key = key.to_s.gsub(/([A-Z])/, '_\1').downcase.to_sym
    normalized_hash[snake_key] = value
  end

  new(**normalized_hash)
end

Instance Method Details

#async?Boolean

Check if the capability supports async execution

Returns:

  • True if async is supported



106
107
108
# File 'lib/a2a/protocol/capability.rb', line 106

def async?
  @async_supported == true
end

#has_tag?(tag) ⇒ Boolean

Check if the capability has a specific tag

Parameters:

  • The tag to check

Returns:

  • True if the tag is present



115
116
117
118
119
# File 'lib/a2a/protocol/capability.rb', line 115

def has_tag?(tag)
  return false if @tags.nil?

  @tags.include?(tag)
end

#requires_security?(scheme) ⇒ Boolean

Check if the capability requires a specific security scheme

Parameters:

  • The security scheme to check

Returns:

  • True if the scheme is required



126
127
128
129
130
# File 'lib/a2a/protocol/capability.rb', line 126

def requires_security?(scheme)
  return false if @security_requirements.nil?

  @security_requirements.include?(scheme)
end

#streaming?Boolean

Check if the capability supports streaming

Returns:

  • True if streaming is supported



98
99
100
# File 'lib/a2a/protocol/capability.rb', line 98

def streaming?
  @streaming_supported == true
end

#to_hHash

Convert to hash representation

Returns:

  • The capability as a hash



136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
# File 'lib/a2a/protocol/capability.rb', line 136

def to_h
  {
    name: @name,
    description: @description,
    method: @method,
    input_schema: @input_schema,
    output_schema: @output_schema,
    examples: @examples,
    tags: @tags,
    security_requirements: @security_requirements,
    metadata: ,
    streaming_supported: @streaming_supported,
    async_supported: @async_supported
  }.compact
end

#validate!Object (private)

Raises:



172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
# File 'lib/a2a/protocol/capability.rb', line 172

def validate!
  if @name.nil? || (respond_to?(:empty?) && empty?) || (is_a?(String) && strip.empty?)
    raise ArgumentError,
          "name is required"
  end
  if @description.nil? || (respond_to?(:empty?) && empty?) || (is_a?(String) && strip.empty?)
    raise ArgumentError,
          "description is required"
  end
  if @method.nil? || (respond_to?(:empty?) && empty?) || (is_a?(String) && strip.empty?)
    raise ArgumentError,
          "method is required"
  end

  raise ArgumentError, "name must be a String" unless @name.is_a?(String)
  raise ArgumentError, "description must be a String" unless @description.is_a?(String)
  raise ArgumentError, "method must be a String" unless @method.is_a?(String)

  validate_schema(@input_schema, "input_schema") if @input_schema
  validate_schema(@output_schema, "output_schema") if @output_schema
  validate_examples if @examples
  validate_array_of_strings(@tags, "tags") if @tags
  validate_array_of_strings(@security_requirements, "security_requirements") if @security_requirements
  validate_hash(, "metadata") if 
  validate_boolean(@streaming_supported, "streaming_supported")
  validate_boolean(@async_supported, "async_supported")
end

#validate_against_schema(data, schema, context) ⇒ Object (private)

Validate data against a JSON Schema (basic implementation)

Parameters:

  • The data to validate

  • The JSON Schema

  • Context for error messages



259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
# File 'lib/a2a/protocol/capability.rb', line 259

def validate_against_schema(data, schema, context)
  type = schema[:type] || schema["type"]

  case type
  when "object"
    validate_object(data, schema, context)
  when "array"
    validate_array(data, schema, context)
  when "string"
    validate_string(data, context)
  when "number", "integer"
    validate_number(data, context)
  when "boolean"
    validate_boolean_value(data, context)
  else
    # Allow unknown types for extensibility
    true
  end
end

#validate_array(data, schema, context) ⇒ Object (private)

Validate array type

Raises:



302
303
304
305
306
307
308
309
310
311
312
313
314
# File 'lib/a2a/protocol/capability.rb', line 302

def validate_array(data, schema, context)
  raise ArgumentError, "#{context} must be an array" unless data.is_a?(Array)

  # Validate items if schema defines them
  items_schema = schema[:items] || schema["items"]
  if items_schema
    data.each_with_index do |item, index|
      validate_against_schema(item, items_schema, "#{context}[#{index}]")
    end
  end

  true
end

#validate_array_of_strings(value, field_name) ⇒ Object (private)

Validate that a value is an array of strings

Raises:



218
219
220
221
222
223
224
# File 'lib/a2a/protocol/capability.rb', line 218

def validate_array_of_strings(value, field_name)
  raise ArgumentError, "#{field_name} must be an Array" unless value.is_a?(Array)

  value.each_with_index do |item, index|
    raise ArgumentError, "#{field_name}[#{index}] must be a String" unless item.is_a?(String)
  end
end

#validate_boolean(value, field_name) ⇒ Object (private)

Validate that a value is a boolean

Raises:



202
203
204
205
206
# File 'lib/a2a/protocol/capability.rb', line 202

def validate_boolean(value, field_name)
  return if value.is_a?(TrueClass) || value.is_a?(FalseClass)

  raise ArgumentError, "#{field_name} must be a Boolean"
end

#validate_boolean_value(data, context) ⇒ Object (private)

Validate boolean type

Raises:



334
335
336
337
338
# File 'lib/a2a/protocol/capability.rb', line 334

def validate_boolean_value(data, context)
  raise ArgumentError, "#{context} must be a boolean" unless data.is_a?(TrueClass) || data.is_a?(FalseClass)

  true
end

#validate_examplesObject (private)

Validate examples structure

Raises:



239
240
241
242
243
244
245
246
247
248
249
250
251
# File 'lib/a2a/protocol/capability.rb', line 239

def validate_examples
  raise ArgumentError, "examples must be an Array" unless @examples.is_a?(Array)

  @examples.each_with_index do |example, index|
    raise ArgumentError, "examples[#{index}] must be a Hash" unless example.is_a?(Hash)

    # Examples should have at least input or description
    unless example.key?(:input) || example.key?("input") ||
           example.key?(:description) || example.key?("description")
      raise ArgumentError, "examples[#{index}] must have 'input' or 'description'"
    end
  end
end

#validate_hash(value, field_name) ⇒ Object (private)

Validate that a value is a hash

Raises:



210
211
212
213
214
# File 'lib/a2a/protocol/capability.rb', line 210

def validate_hash(value, field_name)
  return if value.is_a?(Hash)

  raise ArgumentError, "#{field_name} must be a Hash"
end

#validate_input(input) ⇒ Boolean

Validate input data against the input schema

Raises:

  • If validation fails

Parameters:

  • The input data to validate

Returns:

  • True if valid



76
77
78
79
80
# File 'lib/a2a/protocol/capability.rb', line 76

def validate_input(input)
  return true if @input_schema.nil?

  validate_against_schema(input, @input_schema, "input")
end

#validate_number(data, context) ⇒ Object (private)

Validate number type

Raises:



326
327
328
329
330
# File 'lib/a2a/protocol/capability.rb', line 326

def validate_number(data, context)
  raise ArgumentError, "#{context} must be a number" unless data.is_a?(Numeric)

  true
end

#validate_object(data, schema, context) ⇒ Object (private)

Validate object type

Raises:



281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
# File 'lib/a2a/protocol/capability.rb', line 281

def validate_object(data, schema, context)
  raise ArgumentError, "#{context} must be an object" unless data.is_a?(Hash)

  # Check required properties
  required = schema[:required] || schema["required"] || []
  required.each do |prop|
    raise ArgumentError, "#{context} missing required property: #{prop}" unless data.key?(prop) || data.key?(prop.to_sym)
  end

  # Validate properties if schema defines them
  properties = schema[:properties] || schema["properties"]
  properties&.each do |prop_name, prop_schema|
    prop_value = data[prop_name] || data[prop_name.to_sym]
    validate_against_schema(prop_value, prop_schema, "#{context}.#{prop_name}") if prop_value
  end

  true
end

#validate_output(output) ⇒ Boolean

Validate output data against the output schema

Raises:

  • If validation fails

Parameters:

  • The output data to validate

Returns:

  • True if valid



88
89
90
91
92
# File 'lib/a2a/protocol/capability.rb', line 88

def validate_output(output)
  return true if @output_schema.nil?

  validate_against_schema(output, @output_schema, "output")
end

#validate_schema(schema, field_name) ⇒ Object (private)

Validate that a schema is a valid JSON Schema

Raises:



228
229
230
231
232
233
234
235
# File 'lib/a2a/protocol/capability.rb', line 228

def validate_schema(schema, field_name)
  raise ArgumentError, "#{field_name} must be a Hash" unless schema.is_a?(Hash)

  # Basic JSON Schema validation - check for type field
  return if schema.key?(:type) || schema.key?("type")

  raise ArgumentError, "#{field_name} must have a 'type' field"
end

#validate_string(data, context) ⇒ Object (private)

Validate string type

Raises:



318
319
320
321
322
# File 'lib/a2a/protocol/capability.rb', line 318

def validate_string(data, context)
  raise ArgumentError, "#{context} must be a string" unless data.is_a?(String)

  true
end