Handoffs

Agent-to-agent task delegation in PraisonAI Rust SDK

Handoffs enable agents to delegate tasks to specialized agents, with built-in safety features like cycle detection and depth limits.

Diagram

Handoff Flow

handoff

return

🤖 Agent A

🔧 Specialist B

Quick Start

  1. Create a Handoff
    rust
    use praisonai::Handoff;
    
    // Create a handoff to a specialist agent
    let handoff = Handoff::new("CodeReviewer")
        .tool_description("Transfer to code review specialist");
    
    // The handoff is represented as a tool to the LLM
    println!("Tool name: {}", handoff.get_tool_name());
    // Output: "transfer_to_code_reviewer"
  2. Configure Handoff Behavior
    rust
    use praisonai::{Handoff, HandoffConfig, ContextPolicy};
    
    let config = HandoffConfig::new()
        .context_policy(ContextPolicy::LastN)
        .max_context_messages(5)
        .max_depth(3)
        .detect_cycles(true);
    
    let handoff = Handoff::new("Specialist")
        .config(config)
        .tool_name("delegate_to_expert")
        .tool_description("Transfer complex tasks to the expert");
  3. Execute a Handoff
    rust
    use praisonai::{Handoff, HandoffInputData, HandoffResult};
    
    let handoff = Handoff::new("Specialist");
    
    // Create input data for the handoff
    let input = HandoffInputData::new("Process this request");
    
    // Execute the handoff (returns HandoffResult)
    let result: HandoffResult = handoff.execute(input).await?;
    println!("Result: {}", result.response);

User Interaction Flow

Diagram
SpecialistMain AgentUserSpecialistMain AgentUser“Review this code”Decide to handofftransfer_to_specialist(context)Process taskHandoffResult“Review complete: …”

Handoff

Main struct for defining agent-to-agent transfers.

rust
pub struct Handoff {
    pub target_agent_name: String,
    pub tool_name_override: Option<String>,
    pub tool_description_override: Option<String>,
    pub config: HandoffConfig,
}

Methods

MethodSignatureDescription
new(target)`fn new(impl Into

) -> Self | Create handoff to target agent | | tool_name(name) | fn tool_name(self, impl Into

) -> Self | Override tool name | | tool_description(desc) | fn tool_description(self, impl Into

) -> Self | Override description | | config(cfg) | fn config(self, HandoffConfig) -> Self | Set configuration | | get_tool_name() | fn get_tool_name(&self) -> String | Get resolved tool name | | check_safety(source, chain) | fn check_safety(&self, &str, &HandoffChain) -> Result<()>` | Verify safety |


HandoffConfig

Configuration for handoff behavior and safety.

rust
pub struct HandoffConfig {
    pub context_policy: ContextPolicy,
    pub max_context_tokens: usize,
    pub max_context_messages: usize,
    pub preserve_system: bool,
    pub timeout_seconds: f64,
    pub max_concurrent: usize,
    pub detect_cycles: bool,
    pub max_depth: usize,
    pub async_mode: bool,
}

Configuration Options

OptionTypeDefaultDescription
context_policyContextPolicySummaryHow to share context
max_context_tokensusize4000Max tokens in context
max_context_messagesusize10Max messages in context
preserve_systembooltrueKeep system messages
timeout_secondsf64300.0Execution timeout
max_concurrentusize3Max concurrent handoffs
detect_cyclesbooltrueEnable cycle detection
max_depthusize10Max handoff chain depth
async_modeboolfalseEnable async execution

Builder Methods

MethodSignatureDescription
new()fn new() -> SelfCreate with defaults
context_policy(policy)fn context_policy(self, ContextPolicy) -> SelfSet policy
max_depth(n)fn max_depth(self, usize) -> SelfSet max depth
detect_cycles(b)fn detect_cycles(self, bool) -> SelfEnable/disable
timeout_seconds(t)fn timeout_seconds(self, f64) -> SelfSet timeout

ContextPolicy

Controls how context is shared during handoffs.

rust
pub enum ContextPolicy {
    Full,           // Share entire conversation
    Summary,        // Summarize conversation (default)
    LastN,          // Last N messages only
    Custom(String), // Custom handling
}
PolicyUse Case
FullWhen specialist needs complete history
SummaryDefault – reduces tokens, maintains context
LastNRecent context only, good for long conversations
CustomSpecial formatting or filtering

HandoffResult

Result returned from handoff execution.

rust
pub struct HandoffResult {
    pub success: bool,
    pub response: Option<String>,
    pub target_agent: Option<String>,
    pub source_agent: Option<String>,
    pub duration_seconds: f64,
    pub error: Option<String>,
    pub handoff_depth: usize,
}

Factory Methods

MethodSignatureDescription
success(response)`fn success(impl Into

) -> Self | Create success result | | failure(error) | fn failure(impl Into

) -> Self` | Create failure result |

Builder Methods

MethodSignatureDescription
with_target(agent)`fn with_target(self, impl Into

) -> Self | Set target agent | | with_source(agent) | fn with_source(self, impl Into

) -> Self | Set source agent | | with_duration(seconds) | fn with_duration(self, f64) -> Self` | Set duration |


Safety Features

Cycle Detection

Prevents infinite loops between agents.

rust
let config = HandoffConfig::new()
    .detect_cycles(true);

// A -> B -> A would be detected and blocked

Depth Limits

Limits how deep handoff chains can go.

rust
let config = HandoffConfig::new()
    .max_depth(5);

// Prevents A -> B -> C -> D -> E -> F (would be blocked at F)

Best Practices

Use Summary context by default

Reduces token usage while preserving essential context for the specialist.

Set appropriate depth limits

Use 3-5 for most workflows. Higher values may indicate design issues.

Always enable cycle detection

Keep detect_cycles: true to prevent infinite loops in complex agent networks.

Use descriptive tool names

Override tool names to make LLM decisions clearer: transfer_to_code_reviewer.


Related