Class: Tools::SpawnSpecialist
- Includes:
- SubagentPrompts
- Defined in:
- lib/tools/spawn_specialist.rb
Overview
Spawns a named specialist sub-agent from the agent registry. The specialist has a predefined system prompt and tool set defined in its Markdown definition file under agents/.
Nickname assignment is handled by the Melete::Runner which runs synchronously at spawn time, generating a unique nickname based on the task — same as generic sub-agents.
Results are delivered through natural text messages routed by Events::Subscribers::SubagentMessageRouter.
Constant Summary
Constants included from SubagentPrompts
Tools::SubagentPrompts::COMMUNICATION_INSTRUCTION, Tools::SubagentPrompts::IDENTITY_TEMPLATE, Tools::SubagentPrompts::PROMPT_GUIDELINES
Class Method Summary collapse
-
.description ⇒ Object
Builds description dynamically to include available specialists.
-
.input_schema ⇒ Object
Builds input schema dynamically to include named agent enum.
- .prompt_guidelines ⇒ Object
- .prompt_snippet ⇒ Object
- .tool_name ⇒ Object
Instance Method Summary collapse
-
#execute(input) ⇒ String, Hash{Symbol => String}
Creates a child session with the specialist’s predefined prompt and tools, pins the task as a Goal, and enqueues the task as the child’s first user_message PendingMessage — which kicks the standard inbound pipeline (Melete → (Mneme) → StartProcessing → DrainJob) so the specialist self-starts the same way a human-typed message would.
-
#initialize(session:, agent_registry: nil, tool_use_id: nil) ⇒ SpawnSpecialist
constructor
A new instance of SpawnSpecialist.
Methods inherited from Base
Constructor Details
#initialize(session:, agent_registry: nil, tool_use_id: nil) ⇒ SpawnSpecialist
Returns a new instance of SpawnSpecialist.
69 70 71 72 73 |
# File 'lib/tools/spawn_specialist.rb', line 69 def initialize(session:, agent_registry: nil, tool_use_id: nil, **) @session = session @agent_registry = agent_registry || Agents::Registry.instance @tool_use_id = tool_use_id end |
Class Method Details
.description ⇒ Object
Builds description dynamically to include available specialists.
23 24 25 26 27 28 29 30 31 32 33 |
# File 'lib/tools/spawn_specialist.rb', line 23 def self.description base = "Need a specific skill set for the job? Bring in a specialist. " \ "Its messages appear as tool responses in your conversation. " \ "Prefix its nickname with @ to send instructions." registry = Agents::Registry.instance return base unless registry.any? specialist_list = registry.catalog.map { |name, desc| "- #{name}: #{desc}" }.join("\n") "#{base}\n\nAvailable specialists:\n#{specialist_list}" end |
.input_schema ⇒ Object
Builds input schema dynamically to include named agent enum.
40 41 42 43 44 45 46 47 48 49 |
# File 'lib/tools/spawn_specialist.rb', line 40 def self.input_schema { type: "object", properties: { name: name_property, task: {type: "string", description: "State the goal — the specialist knows its method."} }, required: %w[name task] } end |
.prompt_guidelines ⇒ Object
37 |
# File 'lib/tools/spawn_specialist.rb', line 37 def self.prompt_guidelines = SubagentPrompts::PROMPT_GUIDELINES |
.prompt_snippet ⇒ Object
35 |
# File 'lib/tools/spawn_specialist.rb', line 35 def self.prompt_snippet = "Bring in a specialist by skill set. Reachable later via @." |
.tool_name ⇒ Object
20 |
# File 'lib/tools/spawn_specialist.rb', line 20 def self.tool_name = "spawn_specialist" |
Instance Method Details
#execute(input) ⇒ String, Hash{Symbol => String}
Creates a child session with the specialist’s predefined prompt and tools, pins the task as a Goal, and enqueues the task as the child’s first user_message PendingMessage — which kicks the standard inbound pipeline (Melete → (Mneme) → StartProcessing →DrainJob) so the specialist self-starts the same way a human-typed message would. Returns immediately after Melete completes.
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 |
# File 'lib/tools/spawn_specialist.rb', line 85 def execute(input) task = input["task"].to_s.strip name = input["name"].to_s.strip return {error: "Name cannot be blank"} if name.empty? return {error: "Task cannot be blank"} if task.empty? definition = @agent_registry.get(name) return {error: "Unknown agent: #{name}"} unless definition child = spawn_child(definition, task) nickname = child.name "Specialist #{nickname} spawned (session #{child.id}). " \ "Its messages will appear in your conversation. " \ "To address it, prefix its name with @ in your message." end |