Skip to content
reaatech

@reaatech/agent-handoff-protocol

npm v0.1.0

A TypeScript library for transferring a conversation from one AI agent to another mid-session, providing context compression, capability-based routing, payload validation, transport delivery, and rejection handling with fallback. It exports a `HandoffManager` class that orchestrates the lifecycle, along with composable components like `HybridCompressor`, `CapabilityBasedRouter`, and `MCPTransport`.

@reaatech/agent-handoff-protocol

npm version License: MIT CI

Status: Pre-1.0 — APIs may change in minor versions. Pin to a specific version in production.

A small, opinionated TypeScript library for transferring conversations from one AI agent to another mid-session. Covers the full handoff lifecycle: context compression, intelligent routing, payload validation, transport delivery, and rejection handling with fallback.

Installation

terminal
npm install @reaatech/agent-handoff-protocol
# or
pnpm add @reaatech/agent-handoff-protocol

This is the umbrella package that re-exports everything. For tree-shaking, install individual packages instead.

Feature Overview

  • Context compression — three strategies: hybrid (default), extractive summary, sliding window
  • Intelligent routing — weighted scoring (skill 40%, domain 30%, load 20%, language 10%) with route/clarify/fallback decision tree
  • Payload validation — Zod schemas (optional) or manual fallback with agent compatibility checks
  • Transport layer — MCP (tool-call-based) and A2A (HTTP POST with retry), auto-selection with health caching
  • Rejection handling — tries up to maxAlternatives alternative agents, returns typed RejectionReason on failure
  • 7 error classesHandoffError hierarchy with typed error codes and contextual details
  • Typed lifecycle eventshandoffStart, handoffComplete, handoffReject, handoffError
  • Zero runtime dependencies — everything is built-in or injected; zod is an optional peer
  • Dual ESM/CJS output — works with import and require

Quick Start

typescript
import {
  HandoffManager,
  createHandoffConfig,
  HybridCompressor,
  CapabilityBasedRouter,
  TransportFactory,
  MCPTransport,
} from '@reaatech/agent-handoff-protocol';
 
// Build transport layer
const mcpTransport = new MCPTransport(mcpClient);
const transportFactory = new TransportFactory([mcpTransport]);
 
// Create configuration
const config = createHandoffConfig({
  routing: { minConfidenceThreshold: 0.6, policy: 'best_effort' },
});
 
// Wire up the manager
const manager = new HandoffManager(config, {
  router: new CapabilityBasedRouter(config.routing),
  compressor: new HybridCompressor(),
  transportFactory,
});
 
// Observe the lifecycle
manager.on('handoffStart', ({ handoffId, trigger }) => {
  console.log(`Handoff ${handoffId} started (${trigger.type})`);
});
manager.on('handoffComplete', ({ handoffId, duration, receivingAgent }) => {
  console.log(`Handoff ${handoffId} complete → ${receivingAgent.agentName} (${duration}ms)`);
});
manager.on('handoffReject', ({ handoffId, reason }) => {
  console.log(`Handoff ${handoffId} rejected: ${reason}`);
});
manager.on('handoffError', ({ handoffId, error }) => {
  console.error(`Handoff ${handoffId} failed: ${error.message}`);
});
 
// Register agents
manager.registerAgent({
  agentId: 'ts-agent',
  agentName: 'TypeScript Specialist',
  skills: ['typescript', 'architecture'],
  domains: ['frontend', 'backend'],
  maxConcurrentSessions: 5,
  currentLoad: 1,
  languages: ['en'],
  specializations: [],
  availability: 'available',
  version: '1.0.0',
});
 
// Execute a handoff
const result = await manager.executeHandoff({
  sessionId: 'session-123',
  conversationId: 'conv-456',
  messages: [
    { id: 'm1', role: 'user', content: 'How do I define a generic interface?', timestamp: new Date() },
    { id: 'm2', role: 'assistant', content: 'Use the `interface` keyword with type parameters.', timestamp: new Date() },
  ],
  trigger: {
    type: 'specialist_required',
    requiredSkills: ['typescript'],
    currentAgentSkills: [],
  },
  userMetadata: { userId: 'user-789', language: 'en' },
  state: { resolvedEntities: {}, openQuestions: [], contextVariables: {} },
  availableAgents: [],
});
 
console.log(result.success ? 'Accepted' : 'Rejected');

Architecture

code
HandoffManager (public API)
  ├── ContextCompressor    compress conversation history → CompressedContext
  ├── HandoffRouter        score and select target agent → RoutingDecision
  ├── HandoffValidator     validate payload compatibility
  └── TransportLayer       deliver handoff (MCP or A2A)

Handoff Lifecycle

code
compress → route → validate → transport → accept/reject → fallback (alternatives) → emit event

Handoff Triggers

TriggerFires when
confidence_too_lowAgent confidence drops below threshold
topic_boundary_crossedConversation topic changes significantly
escalation_requestedUser or system requests escalation
specialist_requiredTask requires skills the current agent lacks
load_balancingAgent load exceeds threshold

Lifecycle Events

EventFires
handoffStartHandoff begins — includes handoffId, sessionId, trigger
handoffCompleteTarget agent accepts — includes duration, receivingAgent, routingDecision
handoffRejectAll agents rejected — includes reason, routingDecision
handoffErrorUnexpected failure — includes the error object

Package Breakdown

This umbrella package re-exports everything. For finer-grained installs:

PackagePurpose
@reaatech/agent-handoffCore types, errors, utilities, config
@reaatech/agent-handoff-compressionContext compression strategies
@reaatech/agent-handoff-routingAgent routing engine
@reaatech/agent-handoff-transportMCP + A2A transports
@reaatech/agent-handoff-validationPayload validation

Documentation

License

MIT