Class: Events::Subscribers::SubagentMessageRouter

Inherits:
Object
  • Object
show all
Includes:
Events::Subscriber
Defined in:
lib/events/subscribers/subagent_message_router.rb

Overview

Routes text messages between parent and child sessions, enabling bidirectional @mention communication.

**Child → Parent:** When a sub-agent emits an AgentMessage, the router persists a UserMessage in the parent session with attribution prefix, then wakes the parent via AgentRequestJob.

**Parent → Child:** When a parent agent emits an AgentMessage containing ‘@name` mentions, the router persists the message in each matching child session and wakes them via AgentRequestJob.

Both directions use direct persistence + job enqueue (same pattern as Tools::SpawnSubagent#spawn_child) to avoid conflicts with the global Persister which skips non-pending user messages.

This replaces the return_result tool — sub-agents communicate through natural text messages instead of structured tool calls.

Constant Summary collapse

ATTRIBUTION_FORMAT =

Attribution prefix format for messages routed from child to parent.

Examples:

“[sub-agent @loop-sleuth]: Here’s what I found…”

"[sub-agent @%s]: %s"
MENTION_PATTERN =

Regex to extract @mention names from parent agent messages.

/@(\w[\w-]*)/

Instance Method Summary collapse

Instance Method Details

#emit(event) ⇒ void

This method returns an undefined value.

Routes agent text messages between parent and child sessions.

For sub-agent sessions: forwards to parent with attribution prefix. For parent sessions: scans for @mentions and routes to matching children.

Parameters:

  • event (Hash)

    Rails.event notification hash with :payload containing an agent_message event (type, session_id, content)



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'lib/events/subscribers/subagent_message_router.rb', line 40

def emit(event)
  payload = event[:payload]
  return unless payload.is_a?(Hash)
  return unless payload[:type] == "agent_message"

  session_id = payload[:session_id]
  return unless session_id

  content = payload[:content].to_s
  return if content.empty?

  session = Session.find_by(id: session_id)
  return unless session

  if session.sub_agent?
    route_to_parent(session, content)
  else
    route_mentions_to_children(session, content)
  end
end