Module: RobotLab::Robot::BusMessaging

Included in:
RobotLab::Robot
Defined in:
lib/robot_lab/robot/bus_messaging.rb

Overview

Inter-robot communication via TypedBus.

Expects the including class to provide:

@bus, @bus_poller, @bus_poller_group, @message_counter,
@outbox, @message_handler, @bus_subscriber_id, @name
and the `run` instance method.

Delivery Serialization

TypedBus delivers messages in concurrent Async fibers. Robots enqueue deliveries into a BusPoller rather than handling them inline. The BusPoller drains each group’s queue sequentially on a dedicated OS thread, so robot.run() calls never interleave.

Instance Method Summary collapse

Instance Method Details

#assign_bus_poller(poller, group: :default) ⇒ void

This method returns an undefined value.

Assign a shared BusPoller from a Network.

Stops any private poller this robot auto-created, then adopts the network’s shared poller for the given group.

Parameters:

  • poller (BusPoller)

    the network’s shared poller

  • group (Symbol) (defaults to: :default)

    poller group for this robot (default: :default)



123
124
125
126
127
128
# File 'lib/robot_lab/robot/bus_messaging.rb', line 123

def assign_bus_poller(poller, group: :default)
  @private_bus_poller&.stop
  @private_bus_poller = nil
  @bus_poller       = poller
  @bus_poller_group = group
end

#on_message {|message| ... } ⇒ self

Register a custom handler for incoming bus messages.

Block arity controls delivery handling:

  • 1 argument ‘|message|`: auto-acks before calling, auto-nacks on exception

  • 2 arguments ‘|delivery, message|`: manual mode, you call ack!/nack!

Yields:

  • (message)

    or [delivery, message]

Returns:

  • (self)


62
63
64
65
# File 'lib/robot_lab/robot/bus_messaging.rb', line 62

def on_message(&block)
  @message_handler = block
  self
end

#send_message(to:, content:) ⇒ RobotMessage

Send a message to another robot via the bus.

Parameters:

  • to (String, Symbol)

    target robot’s channel name

  • content (String, Hash)

    message payload

Returns:

Raises:

  • (BusError)

    if no bus is configured



26
27
28
29
30
31
32
33
34
# File 'lib/robot_lab/robot/bus_messaging.rb', line 26

def send_message(to:, content:)
  raise BusError, "No bus configured on robot '#{@name}'" unless @bus

  @message_counter += 1
  message = RobotMessage.build(id: @message_counter, from: @name, content: content)
  @outbox[message.key] = { message: message, status: :sent, replies: [] }
  publish_to_bus(to.to_sym, message)
  message
end

#send_reply(to:, content:, in_reply_to:) ⇒ RobotMessage

Send a reply to a specific message via the bus.

Parameters:

  • to (String, Symbol)

    target robot’s channel name

  • content (String, Hash)

    reply payload

  • in_reply_to (String)

    composite key of the message being replied to

Returns:

Raises:

  • (BusError)

    if no bus is configured



44
45
46
47
48
49
50
51
# File 'lib/robot_lab/robot/bus_messaging.rb', line 44

def send_reply(to:, content:, in_reply_to:)
  raise BusError, "No bus configured on robot '#{@name}'" unless @bus

  @message_counter += 1
  reply = RobotMessage.build(id: @message_counter, from: @name, content: content, in_reply_to: in_reply_to)
  publish_to_bus(to.to_sym, reply)
  reply
end

#spawn(name: "robot", system_prompt: nil, template: nil, local_tools: [], **options) ⇒ Robot

Spawn a new robot on a shared bus.

Creates a new Robot instance that shares this robot’s bus, allowing it to immediately send and receive messages with all other robots on the bus. If no bus exists yet, one is created automatically and the parent robot is connected to it.

Parameters:

  • name (String) (defaults to: "robot")

    unique name for the new robot

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

    inline system prompt

  • template (Symbol, nil) (defaults to: nil)

    prompt_manager template

  • local_tools (Array) (defaults to: [])

    tools for the new robot

  • options (Hash)

    additional options passed to RobotLab.build

Returns:

  • (Robot)

    the newly created robot



82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/robot_lab/robot/bus_messaging.rb', line 82

def spawn(name: "robot", system_prompt: nil, template: nil, local_tools: [], **options)
  ensure_bus

  RobotLab.build(
    name: name,
    system_prompt: system_prompt,
    template: template,
    local_tools: local_tools,
    bus: @bus,
    **options
  )
end

#with_bus(bus = nil) ⇒ self

Connect this robot to a message bus.

If a bus is provided, the robot joins it. If no bus is provided and the robot doesn’t already have one, a new bus is created. No-op if the robot is already on the given bus.

Parameters:

  • bus (TypedBus::MessageBus, nil) (defaults to: nil)

    bus to join (creates one if nil)

Returns:

  • (self)


105
106
107
108
109
110
111
112
# File 'lib/robot_lab/robot/bus_messaging.rb', line 105

def with_bus(bus = nil)
  return self if bus && @bus == bus

  teardown_bus_channel if @bus
  @bus = bus || @bus || TypedBus::MessageBus.new
  setup_bus_channel
  self
end