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.
Quick Start
- 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" - 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"); - 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
Handoff
Main struct for defining agent-to-agent transfers.
pub struct Handoff {
pub target_agent_name: String,
pub tool_name_override: Option<String>,
pub tool_description_override: Option<String>,
pub config: HandoffConfig,
}Methods
| Method | Signature | Description |
|---|---|---|
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.
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
| Option | Type | Default | Description |
|---|---|---|---|
context_policy | ContextPolicy | Summary | How to share context |
max_context_tokens | usize | 4000 | Max tokens in context |
max_context_messages | usize | 10 | Max messages in context |
preserve_system | bool | true | Keep system messages |
timeout_seconds | f64 | 300.0 | Execution timeout |
max_concurrent | usize | 3 | Max concurrent handoffs |
detect_cycles | bool | true | Enable cycle detection |
max_depth | usize | 10 | Max handoff chain depth |
async_mode | bool | false | Enable async execution |
Builder Methods
| Method | Signature | Description |
|---|---|---|
new() | fn new() -> Self | Create with defaults |
context_policy(policy) | fn context_policy(self, ContextPolicy) -> Self | Set policy |
max_depth(n) | fn max_depth(self, usize) -> Self | Set max depth |
detect_cycles(b) | fn detect_cycles(self, bool) -> Self | Enable/disable |
timeout_seconds(t) | fn timeout_seconds(self, f64) -> Self | Set timeout |
ContextPolicy
Controls how context is shared during handoffs.
pub enum ContextPolicy {
Full, // Share entire conversation
Summary, // Summarize conversation (default)
LastN, // Last N messages only
Custom(String), // Custom handling
}| Policy | Use Case |
|---|---|
Full | When specialist needs complete history |
Summary | Default – reduces tokens, maintains context |
LastN | Recent context only, good for long conversations |
Custom | Special formatting or filtering |
HandoffResult
Result returned from handoff execution.
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
| Method | Signature | Description |
|---|---|---|
success(response) | `fn success(impl Into |
) -> Self | Create success result | | failure(error) | fn failure(impl Into
) -> Self` | Create failure result |
Builder Methods
| Method | Signature | Description |
|---|---|---|
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.
let config = HandoffConfig::new()
.detect_cycles(true);
// A -> B -> A would be detected and blockedDepth Limits
Limits how deep handoff chains can go.
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.