Class: A2A::Server::ExampleAgent

Inherits:
Object
  • Object
show all
Includes:
A2AMethods, Agent
Defined in:
lib/a2a/server/example_agent.rb

Instance Method Summary collapse

Methods included from A2AMethods

#client_connected?, #handle_agent_get_authenticated_extended_card, #handle_agent_get_card, #handle_message_send, #handle_message_stream, #handle_push_notification_config_delete, #handle_push_notification_config_get, #handle_push_notification_config_list, #handle_push_notification_config_set, #handle_tasks_cancel, #handle_tasks_get, #handle_tasks_resubscribe, included, #push_notification_manager, #task_manager, #validate_required_params

Methods included from Agent

#build_middleware_chain, #execute_method, #execute_with_middleware, #handle_a2a_request, included, #validate_security_requirements

Instance Method Details

#generate_agent_card(_context) ⇒ A2A::Types::AgentCard (protected)

Generate agent card

Parameters:

  • Request context

Returns:

  • The agent card



169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
# File 'lib/a2a/server/example_agent.rb', line 169

def generate_agent_card(_context)
  A2A::Types::AgentCard.new(
    name: self.class._a2a_config[:name] || "Example Agent",
    description: self.class._a2a_config[:description] || "An example A2A agent",
    version: self.class._a2a_config[:version] || "1.0.0",
    url: "https://example.com/agent",
    preferred_transport: A2A::Types::TRANSPORT_JSONRPC,
    skills: generate_skills_from_capabilities,
    capabilities: generate_capabilities_info,
    default_input_modes: self.class._a2a_config[:default_input_modes] || ["text"],
    default_output_modes: self.class._a2a_config[:default_output_modes] || ["text"],
    additional_interfaces: [
      A2A::Types::AgentInterface.new(
        transport: A2A::Types::TRANSPORT_JSONRPC,
        url: "https://example.com/agent/rpc"
      )
    ],
    supports_authenticated_extended_card: true,
    protocol_version: "1.0"
  )
end

#generate_capabilities_infoA2A::Types::AgentCapabilities (private)

Generate capabilities information

Returns:

  • Capabilities info



238
239
240
241
242
243
244
245
# File 'lib/a2a/server/example_agent.rb', line 238

def generate_capabilities_info
  A2A::Types::AgentCapabilities.new(
    streaming: true,
    push_notifications: true,
    state_transition_history: true,
    extensions: []
  )
end

#generate_extended_agent_card(context) ⇒ A2A::Types::AgentCard (protected)

Generate extended agent card with authentication context

Parameters:

  • Request context

Returns:

  • The extended agent card



196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
# File 'lib/a2a/server/example_agent.rb', line 196

def generate_extended_agent_card(context)
  # Get base card
  card = generate_agent_card(context)

  # Add authenticated user information if available
  if context.user
    # Modify card based on user context
    # This is where you could add user-specific capabilities or information
    card.instance_variable_set(:@metadata, {
                                 authenticated_user: context.user.to_s,
                                 authentication_time: Time.now.utc.iso8601,
                                 extended_features: %w[user_context personalized_responses]
                               })
  end

  card
end

#generate_skills_from_capabilitiesArray<A2A::Types::AgentSkill> (private)

Generate skills from registered capabilities

Returns:

  • List of skills



220
221
222
223
224
225
226
227
228
229
230
231
232
# File 'lib/a2a/server/example_agent.rb', line 220

def generate_skills_from_capabilities
  self.class.a2a_capability_registry.all.map do |capability|
    A2A::Types::AgentSkill.new(
      id: capability.name,
      name: capability.name.humanize,
      description: capability.description || "No description available",
      tags: capability.tags || [],
      examples: capability.examples || [],
      input_modes: ["text"],
      output_modes: ["text"]
    )
  end
end

#process_message_async(message, task, context) ⇒ void (protected)

This method returns an undefined value.

Process message asynchronously

Parameters:

  • The message to process

  • The associated task

  • Request context



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/a2a/server/example_agent.rb', line 86

def process_message_async(message, task, context)
  # Start background processing
  Thread.new do
    # Simulate some processing time
    sleep 1

    # Process the message
    result = process_message_sync(message, task, context)

    # Update task with result
    task_manager.update_task_status(
      task.id,
      A2A::Types::TaskStatus.new(
        state: A2A::Types::TASK_STATE_COMPLETED,
        result: result,
        updated_at: Time.now.utc.iso8601
      )
    )
  rescue StandardError => e
    # Handle errors
    task_manager.update_task_status(
      task.id,
      A2A::Types::TaskStatus.new(
        state: A2A::Types::TASK_STATE_FAILED,
        error: { message: e.message, type: e.class.name },
        updated_at: Time.now.utc.iso8601
      )
    )
  end
end

#process_message_stream(message, task, _context) {|response| ... } ⇒ void (protected)

This method returns an undefined value.

Process message stream

Parameters:

  • The message to process

  • The associated task

  • Request context

Yields:

  • (response)

    Yields each response in the stream



125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# File 'lib/a2a/server/example_agent.rb', line 125

def process_message_stream(message, task, _context)
  # Extract text from message parts
  text_parts = message.parts.select { |part| part.is_a?(A2A::Types::TextPart) }
  text_content = text_parts.map(&:text).join(" ")

  # Stream back the message word by word
  words = text_content.split(/\s+/)

  words.each_with_index do |word, index|
    response_message = A2A::Types::Message.new(
      message_id: SecureRandom.uuid,
      role: A2A::Types::ROLE_AGENT,
      parts: [
        A2A::Types::TextPart.new(text: "Word #{index + 1}: #{word}")
      ],
      context_id: message.context_id,
      task_id: task.id
    )

    yield response_message.to_h

    # Small delay between words
    sleep 0.5
  end

  # Final message
  final_message = A2A::Types::Message.new(
    message_id: SecureRandom.uuid,
    role: A2A::Types::ROLE_AGENT,
    parts: [
      A2A::Types::TextPart.new(text: "Streaming complete. Processed #{words.length} words.")
    ],
    context_id: message.context_id,
    task_id: task.id
  )

  yield final_message.to_h
end

#process_message_sync(message, task, _context) ⇒ Object (protected)

Process message synchronously

Parameters:

  • The message to process

  • The associated task

  • Request context

Returns:

  • Processing result



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/a2a/server/example_agent.rb', line 53

def process_message_sync(message, task, _context)
  # Extract text from message parts
  text_parts = message.parts.select { |part| part.is_a?(A2A::Types::TextPart) }
  text_content = text_parts.map(&:text).join(" ")

  # Simple echo response
  response_message = A2A::Types::Message.new(
    message_id: SecureRandom.uuid,
    role: A2A::Types::ROLE_AGENT,
    parts: [
      A2A::Types::TextPart.new(text: "Echo: #{text_content}")
    ],
    context_id: message.context_id,
    task_id: task.id
  )

  # Add message to task history
  task_manager.add_message(task.id, message)
  task_manager.add_message(task.id, response_message)

  {
    message: response_message.to_h,
    processed_at: Time.now.utc.iso8601
  }
end