> ## Documentation Index
> Fetch the complete documentation index at: https://docs.praison.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Agent Handoffs

> Learn how to implement agent-to-agent task delegation in PraisonAI

# Agent Handoffs

Agent handoffs enable seamless task delegation between specialised agents, allowing you to build sophisticated multi-agent systems where each agent focuses on its area of expertise.

## Overview

Handoffs in PraisonAI allow agents to transfer control to other agents based on the conversation context. This pattern is particularly useful for:

* Customer service routing
* Specialised task delegation
* Complex workflow orchestration
* Escalation scenarios

## How Handoffs Work

When you specify handoffs for an agent, PraisonAI automatically:

1. Converts each handoff into a tool that the agent can use
2. Adds instructions to the agent's prompt about available handoffs
3. Passes the full conversation history when transferring control

## Basic Usage

### Simple Handoff

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import Agent

# Create specialised agents
billing_agent = Agent(
    name="Billing",
    role="Billing specialist",
    goal="Handle billing inquiries and process payments",
    backstory="Expert in billing systems and payment processing"
)

refund_agent = Agent(
    name="Refunds",
    role="Refund specialist", 
    goal="Process refund requests",
    backstory="Specialist in refund policies and processing"
)

# Create triage agent with handoffs
triage_agent = Agent(
    name="Triage",
    role="Customer service triage",
    goal="Route customer inquiries to the right specialist",
    backstory="Expert at understanding customer needs",
    handoffs=[billing_agent, refund_agent]
)

# The triage agent can now transfer to billing or refund agents
response = triage_agent.chat("I need a refund for my order")
```

## Advanced Features

### Custom Callbacks

Execute custom code when handoffs occur:

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
def log_handoff(from_agent, to_agent, context):
    print(f"Transferring from {from_agent.name} to {to_agent.name}")
    # Log to monitoring system, send notifications, etc.

from praisonaiagents import handoff

handoff_config = handoff(
    agent=billing_agent,
    on_handoff=log_handoff
)

triage_agent = Agent(
    name="Triage",
    handoffs=[handoff_config]
)
```

### Structured Input

Use Pydantic models to pass typed data during handoffs:

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from pydantic import BaseModel

class CustomerContext(BaseModel):
    customer_id: str
    order_id: str
    issue_type: str
    priority: str

handoff_config = handoff(
    agent=billing_agent,
    input_model=CustomerContext
)
```

### Input Filters

Control what conversation history is passed to the target agent:

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
handoff_config = handoff(
    agent=technical_agent,
    filter={
        "remove_all_tools": True,  # Remove tool calls from history
        "keep_last_n_messages": 5,  # Only pass last 5 messages
        "remove_system_messages": True  # Remove system prompts
    }
)
```

### Custom Tool Names

Override the default handoff tool name and description:

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
handoff_config = handoff(
    agent=escalation_agent,
    name="escalate_to_manager",
    description="Escalate complex issues to a manager for resolution"
)
```

## Complete Example

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
from praisonaiagents import Agent, handoff
from pydantic import BaseModel

# Define context model
class CustomerInfo(BaseModel):
    name: str
    account_id: str
    issue_description: str

# Create specialised agents
billing_agent = Agent(
    name="BillingExpert",
    role="Billing specialist",
    goal="Resolve billing issues",
    backstory="10 years experience in billing",
    tools=[check_balance, process_payment]
)

technical_agent = Agent(
    name="TechSupport",
    role="Technical support",
    goal="Solve technical problems",
    backstory="Expert in troubleshooting",
    tools=[check_logs, restart_service]
)

manager_agent = Agent(
    name="Manager",
    role="Customer service manager",
    goal="Handle escalations",
    backstory="Experienced in conflict resolution"
)

# Configure handoffs with advanced features
handoffs = [
    # Simple handoff
    billing_agent,
    
    # Handoff with callback
    handoff(
        agent=technical_agent,
        on_handoff=lambda f, t, c: log_transfer(f.name, t.name)
    ),
    
    # Handoff with structured input and filters
    handoff(
        agent=manager_agent,
        name="escalate_to_management",
        description="Escalate serious issues to management",
        input_model=CustomerInfo,
        filter={"keep_last_n_messages": 3}
    )
]

# Create main agent with handoffs
support_agent = Agent(
    name="Support",
    role="Customer support",
    goal="Help customers with their issues",
    backstory="First point of contact",
    handoffs=handoffs
)

# Use in conversation
result = support_agent.chat("My payment failed and now I can't access my account")
```

## Best Practices

1. **Clear Agent Responsibilities**: Each agent should have a well-defined role and expertise area
2. **Minimal Context**: Use filters to pass only relevant conversation history
3. **Structured Data**: Use Pydantic models for complex handoff scenarios
4. **Monitoring**: Implement callbacks to track handoff patterns
5. **Graceful Fallbacks**: Always have a path for unhandled scenarios

## Implementation Details

Under the hood, handoffs are converted to tools:

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# This handoff configuration:
agent.handoffs = [billing_agent]

# Becomes a tool like:
{
    "name": "transfer_to_billing",
    "description": "Transfer conversation to Billing agent: Billing specialist...",
    "function": <transfer_function>
}
```

The agent's prompt is also updated to include handoff instructions, making the agent aware of when and how to delegate tasks.

## Common Patterns

### Customer Service Router

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# Specialised agents for different departments
agents = {
    "billing": billing_agent,
    "technical": technical_agent,
    "sales": sales_agent,
    "refunds": refund_agent
}

router = Agent(
    name="Router",
    handoffs=list(agents.values())
)
```

### Escalation Chain

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
level1 = Agent(name="L1Support", handoffs=[level2])
level2 = Agent(name="L2Support", handoffs=[level3])
level3 = Agent(name="L3Support", handoffs=[manager])
```

### Skill-based Routing

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# Agents with specific skills
python_expert = Agent(name="PythonExpert", ...)
javascript_expert = Agent(name="JSExpert", ...)
database_expert = Agent(name="DBExpert", ...)

tech_lead = Agent(
    name="TechLead",
    handoffs=[python_expert, javascript_expert, database_expert]
)
```

## Troubleshooting

### Handoff Not Triggering

* Ensure the agent's LLM supports tool calling
* Check that handoff agents are properly configured
* Verify the conversation context clearly indicates need for transfer

### Context Loss

* Use input filters to preserve important context
* Consider using structured input models
* Implement callbacks to track what information is passed

### Circular Handoffs

* Design clear handoff hierarchies
* Implement logic to prevent infinite loops
* Use callbacks to detect circular patterns
