Class: RobotLab::A2A::Server

Inherits:
Object
  • Object
show all
Defined in:
lib/robot_lab/a2a/server.rb

Overview

Thin builder that registers RobotLab robots and networks as A2A agents and delegates to simple_a2a for HTTP serving.

Each robot or network is mounted at its own URL path. The path defaults to “/dns-label-of-name” and can be overridden with the path: keyword.

Examples:

Basic usage

server = RobotLab::A2A::Server.new
server.add_robot(my_robot)
server.run(port: 9292)

Interactive robot (AskUser bridged to A2A input_required)

server = RobotLab::A2A::Server.new(interactive: :a2a_tool)
server.add_robot(my_robot)
server.run(port: 9292)

Multiple agents

server = RobotLab::A2A::Server.new
server.add_robot(analyst, path: "/analyst")
server.add_robot(writer,  path: "/writer")
server.add_network(pipeline, name: "pipeline", path: "/pipeline")
server.run(port: 9292)

Rack/Rails mount

map "/agents" do
  run RobotLab::A2A::Server.new.add_robot(my_robot).to_app
end

Constant Summary collapse

DEFAULT_VERSION =
'1.0'

Instance Method Summary collapse

Constructor Details

#initialize(host: 'localhost', port: 9292, storage: nil, interactive: :none) ⇒ Server

Returns a new instance of Server.



35
36
37
38
39
40
41
# File 'lib/robot_lab/a2a/server.rb', line 35

def initialize(host: 'localhost', port: 9292, storage: nil, interactive: :none)
  @host        = host
  @port        = port
  @storage     = storage || ::A2A::Storage::Memory.new
  @interactive = interactive
  @agents      = {}
end

Instance Method Details

#add_network(network, name:, description: nil, path: nil) ⇒ self

Register a network as a single A2A agent (non-interactive).

Parameters:

  • network (RobotLab::Network)
  • name (String)

    required — used for agent card and default path

  • description (String, nil) (defaults to: nil)
  • path (String, nil) (defaults to: nil)

    URL path prefix (defaults to “/dns-label”)

Returns:

  • (self)

    for chaining



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/robot_lab/a2a/server.rb', line 68

def add_network(network, name:, description: nil, path: nil)
  if @interactive != :none
    raise ArgumentError,
          'NetworkAdapter only supports interactive: :none. ' \
          'Wrap individual robots with RobotAdapter for interactive flows.'
  end

  agent_name = name.to_s
  agent_desc = description || agent_name
  agent_path = path || "/#{dns_label(agent_name)}"
  adapter    = NetworkAdapter.new(network, interactive: :none)
  card       = build_agent_card(agent_name, agent_desc, path: agent_path)

  @agents[agent_path] = { agent_card: card, executor: adapter, storage: @storage }
  self
end

#add_robot(robot, name: nil, description: nil, path: nil) ⇒ self

Register a robot as an A2A agent.

Parameters:

  • robot (RobotLab::Robot)
  • name (String, nil) (defaults to: nil)

    overrides robot.name

  • description (String, nil) (defaults to: nil)

    overrides robot.description

  • path (String, nil) (defaults to: nil)

    URL path prefix (defaults to “/dns-label”)

Returns:

  • (self)

    for chaining



50
51
52
53
54
55
56
57
58
59
# File 'lib/robot_lab/a2a/server.rb', line 50

def add_robot(robot, name: nil, description: nil, path: nil)
  agent_name = (name || robot.name).to_s
  agent_desc = description || robot.description || agent_name
  agent_path = path || "/#{dns_label(agent_name)}"
  adapter    = RobotAdapter.new(robot, interactive: @interactive)
  card       = build_agent_card(agent_name, agent_desc, path: agent_path)

  @agents[agent_path] = { agent_card: card, executor: adapter, storage: @storage }
  self
end

#runObject

Start the Falcon HTTP server.



86
87
88
# File 'lib/robot_lab/a2a/server.rb', line 86

def run
  ::A2A.multi_server(agents: @agents, host: @host, port: @port).run
end

#to_appObject

Return a Rack app for embedding in other servers (e.g. Rails, Puma).



91
92
93
94
95
96
97
98
99
100
# File 'lib/robot_lab/a2a/server.rb', line 91

def to_app
  url_map = @agents.transform_values do |cfg|
    ::A2A.server(
      agent_card: cfg[:agent_card],
      executor: cfg[:executor],
      storage: cfg[:storage]
    ).rack_app
  end
  Rack::URLMap.new(url_map)
end