Skip to main content
Schema-validated handoffs ensure data integrity between agents using Pydantic models, raising validation errors immediately instead of producing incorrect LLM output.
from pydantic import BaseModel
from praisonaiagents import Agent, TypedHandoff

class Brief(BaseModel):
    topic: str
    summary: str

writer = Agent(name="Writer", instructions="Write from the validated brief.")
researcher = Agent(name="Researcher", instructions="Research and hand off structured results.")
handoff = TypedHandoff(agent=writer, input_schema=Brief)
handoff.execute_programmatic(researcher, Brief(topic="AI safety", summary="Key risks and mitigations"))
The user receives polished content; the researcher hands off a schema-validated brief before the writer runs.

Quick Start

1

Define Schema + Create TypedHandoff

from pydantic import BaseModel
from praisonaiagents import Agent, TypedHandoff

class ResearchResult(BaseModel):
    summary: str
    citations: list[str]
    confidence: float

writer = Agent(name="Writer", instructions="Write articles from research.")
researcher = Agent(name="Researcher", instructions="Research topics.")

handoff = TypedHandoff(agent=writer, input_schema=ResearchResult)
2

Execute with Validated Payload

payload = ResearchResult(
    summary="AI safety research findings",
    citations=["paper-1", "paper-2"],
    confidence=0.92,
)
result = handoff.execute_programmatic(researcher, payload)
print(result.response)
3

Invalid Payload Raises Immediately

from praisonaiagents import HandoffValidationError

try:
    handoff.execute_programmatic(researcher, {"summary": "x", "citations": "not-a-list"})
except HandoffValidationError as e:
    print(e.validation_errors)

How It Works

StepDescription
ValidationPayload validated against Pydantic schema
SerializationValid payload converted to structured JSON
HandoffTarget agent receives formatted JSON context
Error HandlingSchema mismatches raise HandoffValidationError

Configuration

ParameterTypeDefaultDescription
agentAgentRequiredTarget agent to hand off to
input_schemaType[BaseModel]RequiredPydantic model class for validation
tool_name_overridestrNoneCustom tool name
tool_description_overridestrNoneCustom tool description
on_handoffCallableNoneCallback when handoff starts
input_filterCallableNoneFunction to filter input data
configHandoffConfigNoneAdvanced handoff configuration

Accepted Payload Types

Payload typeBehaviour
Instance of input_schemaRe-validated via model_dump()
dictValidated directly
Any Pydantic model with model_dump()Converted to dict, validated
Object with __dict__Vars extracted, validated
strBypasses validation — falls back to plain Handoff (backward compatibility)

Common Patterns

Research → Writer Pipeline

from pydantic import BaseModel
from praisonaiagents import Agent, TypedHandoff

class ResearchData(BaseModel):
    topic: str
    findings: list[str]
    sources: list[str]
    confidence_score: float

research_agent = Agent(name="Researcher", instructions="Research topics thoroughly")
writer_agent = Agent(name="Writer", instructions="Write based on research data")

typed_handoff = TypedHandoff(agent=writer_agent, input_schema=ResearchData)

# Execute with validated data
research_result = ResearchData(
    topic="AI Ethics",
    findings=["Finding 1", "Finding 2"],
    sources=["source1.com", "source2.org"],
    confidence_score=0.85
)
result = typed_handoff.execute_programmatic(research_agent, research_result)

Customer Info Pipeline

class CustomerRequest(BaseModel):
    customer_id: str
    issue_type: str
    priority: int
    description: str

support_agent = Agent(name="Support", instructions="Handle customer requests")
specialist_agent = Agent(name="Specialist", instructions="Resolve complex issues")

customer_handoff = TypedHandoff(agent=specialist_agent, input_schema=CustomerRequest)

Async Typed Handoffs

async def process_requests():
    result = await typed_handoff.execute_async(source_agent, validated_payload)
    return result

Combining with HandoffConfig

from praisonaiagents import HandoffConfig

config = HandoffConfig(timeout_seconds=30, detect_cycles=True)
typed_handoff = TypedHandoff(
    agent=target_agent,
    input_schema=MySchema,
    config=config
)

Receiving agent: input_payload_schema

Use input_payload_schema on the receiving agent to declare the Pydantic model it expects as incoming payload. This ensures that any agent sending data to this agent produces a payload that matches the declared schema — mismatches raise HandoffValidationError at the boundary.
from pydantic import BaseModel
from praisonaiagents import Agent

class DeployPayload(BaseModel):
    service: str
    version: str

receiver = Agent(
    name="Deployer",
    instructions="Deploy the given service and version.",
    input_payload_schema=DeployPayload,
)
When the sending agent calls TypedHandoff(agent=receiver, input_schema=DeployPayload).execute_programmatic(...) with an invalid payload, HandoffValidationError is raised:
from praisonaiagents import HandoffValidationError

try:
    handoff.execute_programmatic(source_agent, {"service": "api"})  # missing 'version'
except HandoffValidationError as e:
    print(e.validation_errors)

Best Practices

Only include fields the receiving agent actually needs. Large schemas increase validation overhead and complexity.
Always catch HandoffValidationError at orchestration boundaries to handle schema mismatches gracefully:
try:
    result = typed_handoff.execute_programmatic(source, payload)
except HandoffValidationError as e:
    logger.error(f"Schema validation failed: {e.validation_errors}")
Use e.validation_errors to surface field-level issues to users:
except HandoffValidationError as e:
    for error in e.validation_errors:
        print(f"Field error: {error}")
Use typed handoffs when passing more than 2 fields between agents. The validation cost is much lower than debugging wrong LLM output.
TypedHandoff requires Pydantic. Document the requirement:
pip install pydantic
Instantiating without Pydantic raises ImportError.

Handoffs

Plain handoffs (string payloads, no validation)

Handoff Filters

Filtering conversation history during handoffs

Handoff Config

Timeouts, retries, concurrency settings

Multi-Agent Patterns

Design patterns for agent collaboration