Clone & Install
Get the code and install the server with dev dependencies.
When Agent A hands off to Agent B, the full context — decisions, actions, conversation state — survives the transition intact. No repetition, no dropped threads.
HandoffRail sits between your agents as structured middleware. Create a packet, claim it, chain it — context flows forward, never backward.
Agent A finishes its work and creates a structured handoff packet — packing decisions, conversation state, pending actions, and dependencies into one validated payload.
Agent B (or a human) claims the packet, instantly receiving the full context. No repetition, no "what were we talking about?" — everything is there.
Need more agents? Chain handoffs create linked packets that carry context forward across any number of agents — with full audit trails at every step.
Built for production multi-agent systems. Structured packets, human checkpoints, framework adapters, and first-class observability.
Validated JSON schema with decisions, conversation state, actions, dependencies, and artifacts. Versioned for forward compatibility.
Built-in HITL checkpoints with approval workflows, configurable timeouts, and escalation. Critical decisions get human eyes.
Link packets into multi-agent workflows. Each chain preserves parent context with full audit trail across the entire sequence.
Event-driven notifications with HMAC-SHA256 signed payloads. Subscribe to packet lifecycle events and build reactive systems.
Sync + async clients, fluent builder pattern, LangChain & CrewAI adapters, and a base class for custom framework integrations.
7 commands for packet operations. Create, claim, respond to HITL, view history — all from your terminal. handoffrail serve for local dev.
One-command local dev with Docker Compose. Production setup with PostgreSQL 16, Redis 7, and health monitoring endpoints.
API key auth with tier-based rate limiting. Free, Pro, and Business tiers with enforced quotas for agents, keys, and packet size.
Prometheus metrics, structured logging with structlog, health/readiness probes, and full event history for every packet.
From zero to your first handoff in under 5 minutes. SDK, REST, or CLI — pick your weapon.
from handoffrail.sdk import HandoffRailClient # Connect to HandoffRail client = HandoffRailClient( base_url="http://localhost:8080/api/v1", api_key="hr_your_key_here" ) # Create a handoff packet packet = client.create_packet( source_agent={"id": "sales-01", "name": "SalesBot", "framework": "langchain"}, target_agent={"id": "billing-01", "name": "BillingBot"}, summary="Customer wants to upgrade to Business tier", priority="high", tags=["upgrade", "business-tier"] ) # Agent B claims the packet claimed = client.claim_packet( packet.id, agent_id="billing-01", agent_name="BillingBot" ) # Mark as complete client.complete_packet(packet.id)
# Create a handoff packet curl -X POST http://localhost:8080/api/v1/packets \ -H "X-API-Key: hr_your_key" \ -H "Content-Type: application/json" \ -d '{ "metadata": { "source_agent": {"id": "sales-01", "name": "SalesBot", "framework": "langchain"}, "target_agent": {"id": "billing-01", "name": "BillingBot"}, "priority": "high" }, "context": { "summary": "Customer wants to upgrade", "conversation_state": [ {"role": "user", "content": "I want to upgrade"}, {"role": "agent", "content": "Let me hand you to billing."} ] }, "decisions": [], "actions": { "pending": [{"id": "a1", "description": "Process upgrade", "assignee": "billing-01"}], "completed": [], "failed": [] } }' # Claim it curl -X POST http://localhost:8080/api/v1/packets/{id}/claim \ -H "X-API-Key: hr_your_key" \ -d '{"agent_id": "billing-01", "agent_name": "BillingBot"}'
# Start the server handoffrail serve --port 8080 # Create a packet handoffrail create \ --source-id sales-01 \ --source-name SalesBot \ --target-id billing-01 \ --summary "Customer upgrade request" \ --priority high # List pending packets handoffrail list --status created --priority high # Claim a packet handoffrail claim abc-123 --agent-id billing-01 --agent-name BillingBot # Respond to HITL checkpoint handoffrail respond abc-123 --response "Approved" --responded-by manager@company.com # View audit trail handoffrail history abc-123
from handoffrail.sdk import HandoffPacket # Fluent builder for complex handoffs packet = ( HandoffPacket.builder() .from_agent("sales-01", "SalesBot", framework="langchain") .to_agent("billing-01", "BillingBot") .with_summary("Customer wants Business tier upgrade") .with_conversation(messages=[ {"role": "user", "content": "I want to upgrade"}, {"role": "agent", "content": "Let me connect you to billing"}, ]) .with_decision("Proceed with upgrade", rationale="Customer eligible") .with_action("Process payment", assignee="billing-01", priority="high") .with_dependency("stripe-api", type="api", description="Payment gateway") .with_hitl(reason="High-value upgrade", question="Approve upgrade?") .with_priority("high") .with_tags(["upgrade", "business-tier"]) .build() )
from handoffrail.sdk import HandoffRailClient from handoffrail.integrations.langchain import LangChainAdapter, HandoffRailTool client = HandoffRailClient(base_url="http://localhost:8080/api/v1", api_key="hr_...") adapter = LangChainAdapter(client=client, agent_id="sales-01", agent_name="SalesBot") # Create handoff from LangChain conversation packet = adapter.create_handoff( target_agent_id="billing-01", target_agent_name="BillingBot", summary="Customer upgrade request", conversation_state=adapter.extract_conversation(chat_history), ) # Receive: poll for unclaimed packets packets = adapter.poll_for_handoff() claimed = adapter.claim_handoff(packets[0].id) # Resume conversation from handoff messages = adapter.resume_conversation(claimed) # Use as LangChain Tool tool = HandoffRailTool(client=client)
Clone, install, create your first handoff. That's it.
Get the code and install the server with dev dependencies.
Fire up the FastAPI server with auto-reload for development.
Use the SDK, REST, or CLI — your first handoff packet in seconds.
Open source, self-hosted forever. Cloud tiers for teams that need more.
Get started in under 5 minutes. Open source, self-hosted, production-ready.