Handoff Module

API reference for the agent handoff system

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.

python
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

The name of the handoff tool

agent Union[str, Agent]

Target agent name or Agent instance

template str

Template for handoff instructions

description str

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()

python
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:

python
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.

python
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.

python
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

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)

When the handoff tool is invoked by an agent and fails (cycle detected, max depth exceeded, or any exception), it returns {"error": "<message>", "handoff_failed": True} rather than an "Error: ..." string (PraisonAI #5772).

Usage Examples

Creating a handoff tool:

python
# 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:

python
# 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.

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

Parameters

agent str

Name of the target agent

template str

Instruction template

message str

Additional context or message

Returns

  • str: Formatted handoff prompt

Built-in Filters

handoff_filters()

Returns available handoff filter options.

python
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

python
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:

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

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

DEFAULT_DESCRIPTION

Default description for handoff tools:

python
DEFAULT_DESCRIPTION = "Hand off the conversation to another agent"

Integration with Agents

Using Handoffs in Agent Configuration

python
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

python
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
  • Cycle, depth, or runtime failure: The handoff tool returns {"error": "...", "handoff_failed": True}

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

python
from praisonaiagents import Agent, Task, AgentTeam, 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 = AgentTeam(
    agents=[frontdesk, manager, tech_support],
    memory=True
)

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