Overview

The handoff module provides functionality for agents to delegate tasks to other agents dynamically. It includes the Handoff class for creating custom handoff tools and the handoff function for standard handoff operations.

Classes

Handoff

A subclass of Tool that provides handoff-specific functionality.

class Handoff(Tool):
    def __init__(
        self,
        name: str,
        agent: Union[str, Agent],
        template: str = DEFAULT_TEMPLATE,
        description: str = DEFAULT_DESCRIPTION,
        input_model: Optional[Type[BaseModel]] = None,
        callback: Optional[Callable] = None
    )

Parameters

name
str
required

The name of the handoff tool

agent
Union[str, Agent]
required

Target agent name or Agent instance

template
str
default:"DEFAULT_TEMPLATE"

Template for handoff instructions

description
str
default:"DEFAULT_DESCRIPTION"

Description of the handoff tool

input_model
Optional[Type[BaseModel]]

Pydantic model for structured input

callback
Optional[Callable]

Callback function called during handoff

Methods

run()
def run(self, message: str = "") -> str

Executes the handoff operation.

Parameters:

  • message (str): Message to pass to the target agent

Returns:

  • str: Handoff prompt with instructions

Example:

handoff_tool = Handoff(name="escalate", agent="Supervisor")
result = handoff_tool.run("Customer needs manager approval")

HandoffInputData

Pydantic model for structured handoff input when using input_model.

class HandoffInputData(BaseModel):
    agent: str = Field(..., description="The name of the agent to hand off to")
    message: str = Field("", description="Additional message or context")

Functions

handoff()

Creates a handoff tool or executes a handoff operation.

def handoff(
    agent: Optional[Union[str, Agent]] = None,
    name: str = "handoff",
    description: str = DEFAULT_DESCRIPTION,
    template: str = DEFAULT_TEMPLATE,
    input_model: Optional[Type[BaseModel]] = HandoffInputData,
    callback: Optional[Callable] = None,
    # Direct execution parameters
    message: str = ""
) -> Union[Handoff, str]

Parameters

agent
Optional[Union[str, Agent]]

Target agent for handoff

name
str
default:"handoff"

Name of the handoff tool

description
str

Description of the handoff functionality

template
str

Template for handoff instructions

input_model
Optional[Type[BaseModel]]

Model for structured input

callback
Optional[Callable]

Callback function for handoff events

message
str

Message for direct handoff execution

Returns

  • Handoff: When creating a tool (no message provided)
  • str: When executing directly (message provided)

Usage Examples

Creating a handoff tool:

# Basic handoff tool
transfer = handoff(agent="Specialist")

# Custom named handoff
escalate = handoff(
    agent="Supervisor",
    name="escalate_to_supervisor",
    description="Escalate complex issues to supervisor"
)

# With callback
def log_handoff(from_agent, to_agent, context):
    print(f"Handoff: {from_agent} -> {to_agent}")
    
transfer_with_log = handoff(
    agent="Support",
    callback=log_handoff
)

Direct handoff execution:

# Execute handoff immediately
prompt = handoff(
    agent="TechSupport",
    message="User experiencing login issues"
)

prompt_with_handoff_instructions()

Generates a handoff prompt with specific instructions and context.

def prompt_with_handoff_instructions(
    agent: str,
    template: str,
    message: str = ""
) -> str

Parameters

agent
str
required

Name of the target agent

template
str
required

Instruction template

message
str

Additional context or message

Returns

  • str: Formatted handoff prompt

Built-in Filters

handoff_filters()

Returns available handoff filter options.

def handoff_filters() -> List[str]

Returns

List of available filters:

  • "all" - Accept handoffs from any agent
  • "none" - Reject all handoffs
  • "self" - Only accept from same agent
  • "other" - Accept from any agent except self
  • "team:<name>" - Only accept from agents in specified team

Example

filters = handoff_filters()
print(filters)  # ["all", "none", "self", "other", "team:"]

# Use in agent configuration
agent = Agent(
    name="Specialist",
    handoff_filter="team:support"
)

Constants

DEFAULT_TEMPLATE

Default template for handoff instructions:

DEFAULT_TEMPLATE = '''Transferred to: {agent}
{message}

Continue the conversation and help the user with their request.'''

DEFAULT_DESCRIPTION

Default description for handoff tools:

DEFAULT_DESCRIPTION = "Hand off the conversation to another agent"

Integration with Agents

Using Handoffs in Agent Configuration

from praisonaiagents import Agent, handoff

# Method 1: Specify handoff targets
agent = Agent(
    name="Support",
    handoffs=["Billing", "Technical", "Sales"]
)

# Method 2: Provide handoff as a tool
transfer_tool = handoff(name="transfer")
agent = Agent(
    name="Support",
    tools=[transfer_tool]
)

# Method 3: Multiple custom handoffs
escalate = handoff(agent="Supervisor", name="escalate")
transfer = handoff(agent="Specialist", name="transfer")

agent = Agent(
    name="Support",
    tools=[escalate, transfer]
)

Callback Function Signature

def handoff_callback(
    from_agent: str,
    to_agent: str, 
    context: Dict[str, Any]
) -> bool:
    """
    Process handoff event.
    
    Args:
        from_agent: Name of agent initiating handoff
        to_agent: Name of target agent
        context: Handoff context including message and history
        
    Returns:
        bool: True to allow handoff, False to block
    """
    # Custom logic here
    return True

Error Handling

The handoff system handles various error conditions:

  • Invalid agent name: Returns error message if target agent not found
  • Circular handoffs: Can be prevented using handoff filters
  • Callback errors: Logged and handoff continues if callback fails

Best Practices

  1. Use descriptive names for custom handoff tools
  2. Implement callbacks for logging and monitoring
  3. Set appropriate filters to prevent handoff loops
  4. Provide context in handoff messages
  5. Test handoff chains to ensure smooth transitions

Complete Example

from praisonaiagents import Agent, Task, PraisonAIAgents, handoff
from typing import Dict, Any

# Callback for logging
def log_handoffs(from_agent: str, to_agent: str, context: Dict[str, Any]) -> bool:
    timestamp = context.get('timestamp', 'unknown')
    message = context.get('message', '')
    print(f"[{timestamp}] Handoff: {from_agent} -> {to_agent}")
    print(f"Context: {message[:50]}...")
    return True

# Create specialized handoff tools
escalate_to_manager = handoff(
    agent="Manager",
    name="escalate",
    description="Escalate to manager for approval",
    callback=log_handoffs
)

transfer_to_tech = handoff(
    agent="TechSupport",
    name="transfer_to_tech",
    description="Transfer technical issues to tech support",
    callback=log_handoffs
)

# Create agents with handoff capabilities
frontdesk = Agent(
    name="FrontDesk",
    role="Customer Service Representative",
    goal="Help customers and route complex issues",
    tools=[escalate_to_manager, transfer_to_tech],
    handoff_filter="other"  # Can receive from others but not self
)

manager = Agent(
    name="Manager",
    role="Customer Service Manager",
    goal="Handle escalated issues and approvals",
    handoff_filter="all"  # Can receive from anyone
)

tech_support = Agent(
    name="TechSupport",
    role="Technical Support Specialist",
    goal="Resolve technical issues",
    handoff_filter="team:support"  # Only from support team
)

# Create workflow
workflow = PraisonAIAgents(
    agents=[frontdesk, manager, tech_support],
    memory=True
)

# The agents can now hand off tasks based on conversation context