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

# Handoff Filters

> Filter and transform context when handing off between agents

Handoff filters control what context passes when one agent hands off to another — reducing tokens, focusing relevance, and stripping sensitive data.

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

coordinator = Agent(
    name="Coordinator",
    instructions="Route tasks to specialists with trimmed context",
    handoffs=[
        Handoff(
            agent=Agent(name="Analyst", instructions="Analyse the handoff payload"),
            input_filter=handoff_filters.compress_history,
        )
    ],
)

coordinator.start("Prepare a focused brief for the analyst")
```

The user asks the coordinator; filtered context is passed on handoff.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
graph LR
    subgraph "Handoff Filters"
        H[📋 Full History] --> F[🔍 Filters]
        F --> C[✅ Clean Context]
    end

    classDef input fill:#6366F1,stroke:#7C90A0,color:#fff
    classDef tool fill:#189AB4,stroke:#7C90A0,color:#fff
    classDef output fill:#10B981,stroke:#7C90A0,color:#fff
    class H input
    class F tool
    class C output
```

> [!NOTE]
>
> **New in v2.x**: Chain multiple filters with `input_filter=[filter1, filter2]` and use `compress_history` to reduce token usage.

## Overview

Handoff filters let you control what context is passed when one agent hands off to another. This helps:

* **Reduce token usage** by removing unnecessary messages
* **Focus context** on relevant information
* **Protect privacy** by filtering sensitive data

## Quick Start

**1. Single filter**

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

analyst = Agent(name="Analyst", instructions="Analyze data")

coordinator = Agent(
    name="Coordinator",
    handoffs=[
        Handoff(
            agent=analyst,
            input_filter=handoff_filters.compress_history
        )
    ]
)
```

**2. Chain filters**

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

analyst = Agent(name="Analyst", instructions="Analyze data")

coordinator = Agent(
    name="Coordinator",
    handoffs=[
        Handoff(
            agent=analyst,
            input_filter=[
                handoff_filters.remove_all_tools,
                handoff_filters.remove_system_messages,
                handoff_filters.compress_history,
            ]
        )
    ]
)
```

## Available Filters

### compress\_history

Compresses all messages into a single summary message. Great for reducing token usage.

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

# Before: Multiple messages
# [
#   {"role": "user", "content": "Hello"},
#   {"role": "assistant", "content": "Hi there!"},
#   {"role": "user", "content": "How are you?"}
# ]

# After: Single compressed message
# [{"role": "user", "content": "Previous conversation summary:\n[user]: Hello\n[assistant]: Hi there!\n[user]: How are you?"}]
```

### remove\_all\_tools

Removes all tool-related messages (tool calls and tool results).

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# Removes:
# - Messages with role="tool"
# - Messages with tool_calls field
```

### keep\_last\_n\_messages

Keeps only the last N messages.

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# Keep last 5 messages
filter_fn = handoff_filters.keep_last_n_messages(5)
```

### remove\_system\_messages

Removes all system messages from the history.

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
# Removes all messages where role="system"
```

## Filter Chaining

> [!TIP]
>
> Filters are applied **in order**. Put removal filters first, then compression last.

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

# Recommended order:
# 1. Remove unwanted content
# 2. Limit message count
# 3. Compress remaining

handoff = Handoff(
    agent=target_agent,
    input_filter=[
        handoff_filters.remove_all_tools,      # First: remove tool noise
        handoff_filters.remove_system_messages, # Second: remove system prompts
        handoff_filters.keep_last_n_messages(10), # Third: limit to recent
        handoff_filters.compress_history,       # Last: compress into one
    ]
)
```

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
flowchart TB
    subgraph Input["Original History (20 messages)"]
        M1[User + Assistant + Tools + System]
    end
    
    subgraph Step1["Step 1: remove_all_tools"]
        M2[User + Assistant + System]
    end
    
    subgraph Step2["Step 2: remove_system_messages"]
        M3[User + Assistant only]
    end
    
    subgraph Step3["Step 3: keep_last_n(10)"]
        M4[Last 10 messages]
    end
    
    subgraph Step4["Step 4: compress_history"]
        M5[1 summary message]
    end
    
    M1 --> M2 --> M3 --> M4 --> M5
    
    style M1 fill:#8B0000,color:#fff
    style M5 fill:#189AB4,color:#fff
```

## How It Works

The user asks the coordinator; on handoff the input filters run in order and the filtered messages are seeded onto the target agent's `chat_history` for the duration of the handoff, then restored on exit.

```mermaid theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
sequenceDiagram
    participant Src as Source Agent
    participant Cfg as HandoffConfig
    participant F as input_filter chain
    participant Tgt as Target Agent

    Src->>Cfg: chat_history + kwargs
    Cfg->>Cfg: apply context_policy<br/>(FULL / LAST_N / SUMMARY / NONE)
    Cfg->>F: filtered messages
    F-->>Cfg: transformed messages
    Cfg->>Tgt: seed chat_history<br/>(scoped to this handoff)
    Tgt-->>Src: response
    Note over Tgt: chat_history restored on exit
```

> [!NOTE]
>
> On releases **before PR #4213**, `input_filter` (and `context_policy`) had **no runtime effect** — the target only ever received the literal `[Handoff from …] <prompt>` string, so "what the target sees" examples above were aspirational. Filtered history now genuinely reaches the target's context.

***

## Custom Filters

Create your own filter function:

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

def my_custom_filter(data: HandoffInputData) -> HandoffInputData:
    """Remove messages containing sensitive keywords."""
    sensitive_words = ["password", "secret", "api_key"]
    
    filtered = []
    for msg in data.messages:
        if isinstance(msg, dict):
            content = msg.get("content", "").lower()
            if not any(word in content for word in sensitive_words):
                filtered.append(msg)
    
    data.messages = filtered
    return data

# Use with handoff
handoff = Handoff(
    agent=target_agent,
    input_filter=[
        my_custom_filter,
        handoff_filters.compress_history,
    ]
)
```

## API Reference

### HandoffInputData

The data structure passed to filter functions:

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
@dataclass
class HandoffInputData:
    messages: List[Dict[str, Any]]  # Conversation messages
    context: Dict[str, Any]         # Additional context
    source_agent: str               # Name of source agent
    handoff_depth: int = 0          # Current handoff depth
    handoff_chain: List[str] = []   # Chain of agent names
```

### Filter Function Signature

```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
def filter_function(data: HandoffInputData) -> HandoffInputData:
    # Modify data.messages as needed
    return data
```

## Examples

> [accordion] Token-Efficient Handoff
>
> ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
> from praisonaiagents import Agent, Handoff, handoff_filters
>
> # Minimize tokens passed to specialist
> specialist = Agent(name="Specialist", instructions="Handle complex tasks")
>
> coordinator = Agent(
>     name="Coordinator",
>     handoffs=[
>         Handoff(
>             agent=specialist,
>             input_filter=[
>                 handoff_filters.remove_all_tools,
>                 handoff_filters.keep_last_n_messages(3),
>                 handoff_filters.compress_history,
>             ]
>         )
>     ]
> )
> ```

> [accordion] Privacy-Aware Handoff
>
> ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
> from praisonaiagents import Agent, Handoff, handoff_filters
> from praisonaiagents import HandoffInputData
>
> def remove_pii(data: HandoffInputData) -> HandoffInputData:
>     """Remove personally identifiable information."""
>     import re
>
>     for msg in data.messages:
>         if isinstance(msg, dict) and "content" in msg:
>             # Remove email addresses
>             msg["content"] = re.sub(
>                 r'\b[\w.-]+@[\w.-]+\.\w+\b',
>                 '[EMAIL REDACTED]',
>                 msg["content"]
>             )
>             # Remove phone numbers
>             msg["content"] = re.sub(
>                 r'\b\d{3}[-.]?\d{3}[-.]?\d{4}\b',
>                 '[PHONE REDACTED]',
>                 msg["content"]
>             )
>
>     return data
>
> external_agent = Agent(name="External", instructions="Process request")
>
> internal_agent = Agent(
>     name="Internal",
>     handoffs=[
>         Handoff(
>             agent=external_agent,
>             input_filter=[remove_pii, handoff_filters.compress_history]
>         )
>     ]
> )
> ```

> [accordion] Focus on Recent Context
>
> ```python theme={"theme":{"light":"vitesse-light","dark":"vitesse-dark"}}
> from praisonaiagents import Agent, Handoff, handoff_filters
>
> # Only pass last 5 messages, no tools
> analyst = Agent(name="Analyst", instructions="Analyze recent conversation")
>
> coordinator = Agent(
>     name="Coordinator",
>     handoffs=[
>         Handoff(
>             agent=analyst,
>             input_filter=[
>                 handoff_filters.remove_all_tools,
>                 handoff_filters.keep_last_n_messages(5),
>             ]
>         )
>     ]
> )
> ```

## Best Practices

> [accordion] Compress history before large handoffs
>
> Passing a full conversation to a specialist wastes tokens on context it doesn't need. Use `handoff_filters.compress_history` (or a custom trim) so the receiving agent gets a focused brief, not the entire transcript.

> [accordion] Strip tool calls the next agent can't use
>
> Tool-call messages from the source agent are noise to a specialist with different tools. Filter them out (`remove_tools`) so the receiving model reasons over content, not stale tool invocations it will never repeat.

> [accordion] Redact sensitive data at the boundary
>
> Handoffs are the natural place to drop secrets, PII, or credentials before another agent sees them. Add a redaction filter to the chain so sensitive fields never cross into an agent that doesn't need them.

> [accordion] Chain filters in order of intent
>
> Filters compose left to right, each receiving the previous filter's output. Order them so structural cuts (remove tools) run before compression, and redaction runs last, so nothing sensitive slips through a later transform.

## Related

> [card] [Handoffs](https://praison.ai/docs/features/handoffs.md)
>
> Agent-to-agent delegation

> [card] [Agent as Tool](https://praison.ai/docs/features/agent-as-tool.md)
>
> Use agents as callable tools

> [card] [Context Policies](https://praison.ai/docs/features/context-files.md)
>
> Control context sharing across agents

> [card] [Handoff Tool Policy](https://praison.ai/docs/features/handoff-tool-policy.md)
>
> Secure tool boundaries during handoff


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.