Replaces the deprecated
allow_delegation=True — see Legacy Agent Parameters.Handoffs are secure by default — the target agent only inherits tools shared with the source agent. See Handoff Tool Policy.
Quick Start
1
Pass agents directly
Pass specialist agents to
handoffs and the routing agent gets a transfer tool for each.2
Configure the handoff tool
Use
handoff() to rename the transfer tool or steer when the agent should call it.How It Works
When you sethandoffs, PraisonAI converts each target into a transfer_to_<agent> tool, adds routing instructions to the agent’s prompt, and passes conversation history when control transfers.
Which Handoff Setup to Use?
Configuration Options
handoff() builds a configured transfer tool for a target agent.
Handoff Tool Policy — tool security boundary options
Common Patterns
Pattern 1 — Callback on handoff
Pattern 2 — Filter passed history
Pattern 3 — Type-safe handoff
Running handoffs in parallel
parallel_handoffs runs several handoffs at once with concurrency control.
1
List the targets
Pass
(agent, prompt) tuples — each runs as its own task.2
Run them concurrently
Await
parallel_handoffs and inspect each HandoffResult.Sibling tasks spawned by
parallel_handoffs (or any asyncio.gather over handoff_to_async) each get an isolated handoff chain. Cycle detection and max_depth are enforced per task, not shared across siblings. See Handoff chain isolation under asyncio.gather.A handoff rejected by a safety check (e.g.
allowed_agents block, cycle guard, max_depth) does not consume a chain slot. The parent agent’s cycle detection and max_depth counters remain accurate for any subsequent handoffs it attempts in the same turn.Per-Handoff concurrency
max_concurrent is enforced by a semaphore private to each Handoff instance, not shared across the process.
Two Handoffs with different max_concurrent values each get their own limit — the earlier one no longer clamps the later one.
asyncio.run() more than once keeps working.
Handoff Results
handoff_to() returns a HandoffResult describing the outcome.
Best Practices
Give each agent one clear responsibility
Give each agent one clear responsibility
A specialist with a focused role routes cleanly. Overlapping responsibilities make the routing agent’s tool choice ambiguous.
Filter history to cut tokens
Filter history to cut tokens
Pass
input_filter=handoff_filters.remove_all_tools or handoff_filters.keep_last_n_messages(5) so the target agent gets only the context it needs.Use TypedHandoff for structured data
Use TypedHandoff for structured data
When a specialist needs typed fields, use
TypedHandoff(agent=..., input_schema=Model) — the framework validates the payload at the boundary.Keep a fallback path
Keep a fallback path
Let the routing agent answer requests it cannot route rather than failing silently.
Related
Handoff Tool Policy
Secure tool boundaries during handoff
Typed Handoffs
Schema-validated handoffs with Pydantic models

