Class: Agents::HandoffTool
- Defined in:
- lib/agents/handoff.rb
Overview
A special tool that enables agents to transfer conversations to other specialized agents. Handoffs are implemented as tools (following OpenAI’s pattern) because this allows the LLM to naturally decide when to transfer based on the conversation context.
## How Handoffs Work
-
Agent A is configured with handoff_agents: [Agent B, Agent C]
-
This automatically creates HandoffTool instances for B and C
-
The LLM can call these tools like any other tool
-
The tool signals the handoff through context
-
The Runner detects this and switches to the new agent
## Loop Prevention The library prevents infinite handoff loops by processing only the first handoff tool call in any LLM response. This is handled automatically by the Chat class which detects handoff tools and processes them separately from regular tools.
## Why Tools Instead of Instructions Using tools for handoffs has several advantages:
-
LLMs reliably use tools when appropriate
-
Clear schema tells the LLM when each handoff is suitable
-
No parsing of free text needed
-
Works consistently across different LLM providers
Instance Attribute Summary collapse
-
#target_agent ⇒ Object
readonly
Returns the value of attribute target_agent.
Instance Method Summary collapse
-
#description ⇒ Object
Override the description.
-
#initialize(target_agent) ⇒ HandoffTool
constructor
A new instance of HandoffTool.
-
#name ⇒ Object
Override the auto-generated name to use our specific name.
-
#perform(tool_context) ⇒ Object
Use RubyLLM’s halt mechanism to stop continuation after handoff Store handoff info in context for Runner to detect and process.
Methods inherited from Tool
Constructor Details
#initialize(target_agent) ⇒ HandoffTool
Returns a new instance of HandoffTool.
52 53 54 55 56 57 58 59 60 |
# File 'lib/agents/handoff.rb', line 52 def initialize(target_agent) @target_agent = target_agent # Set up the tool with a standardized name and description @tool_name = "handoff_to_#{target_agent.name.downcase.gsub(/\s+/, "_")}" @tool_description = "Transfer conversation to #{target_agent.name}" super() end |
Instance Attribute Details
#target_agent ⇒ Object (readonly)
Returns the value of attribute target_agent.
50 51 52 |
# File 'lib/agents/handoff.rb', line 50 def target_agent @target_agent end |
Instance Method Details
#description ⇒ Object
Override the description
68 69 70 |
# File 'lib/agents/handoff.rb', line 68 def description @tool_description end |
#name ⇒ Object
Override the auto-generated name to use our specific name
63 64 65 |
# File 'lib/agents/handoff.rb', line 63 def name @tool_name end |
#perform(tool_context) ⇒ Object
Use RubyLLM’s halt mechanism to stop continuation after handoff Store handoff info in context for Runner to detect and process
74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/agents/handoff.rb', line 74 def perform(tool_context) # Store handoff information in context for Runner to detect # TODO: The following is a race condition that needs to be addressed in future versions # If multiple handoff tools execute concurrently, they overwrite each other's pending_handoff data. tool_context.run_context.context[:pending_handoff] = { target_agent: @target_agent, timestamp: Time.now } # Return halt to stop LLM continuation halt("I'll transfer you to #{@target_agent.name} who can better assist you with this.") end |