# How to Configure Structured Handoffs Between Agents in Orchestrate for Task Propagation

> Learn to configure structured handoffs between agents in Orchestrate for reliable task propagation. Master typed, verifiable messages and automatic fallback routing for efficient workflow.

- Repository: [Cursor/plugins](https://github.com/cursor/plugins)
- Tags: how-to-guide
- Published: 2026-05-25

---

**Orchestrate enables reliable task propagation through typed, verifiable handoff messages that transfer work between agents via cryptographic verification records, with automatic fallback routing when deliveries fail.**

The Cursor plugins repository provides a robust multi-agent workflow engine through its Orchestrate skill. Configuring structured handoffs between agents allows complex tasks to propagate reliably across distributed systems while maintaining data integrity and observability. This guide explains how to implement the handoff mechanism using the actual source code from `cursor/plugins`.

## What Are Structured Handoffs?

A **handoff** is a schema-driven, typed message that transfers responsibility for a unit of work from one agent to another. In [`orchestrate/skills/orchestrate/scripts/core/handoff.ts`](https://github.com/cursor/plugins/blob/main/orchestrate/skills/orchestrate/scripts/core/handoff.ts), the `handoff()` function constructs these payloads according to strict JSON schemas defined in [`scripts/schemas.ts`](https://github.com/cursor/plugins/blob/main/scripts/schemas.ts).

Each handoff includes a **verification record** generated by [`handoff-verification-record.ts`](https://github.com/cursor/plugins/blob/main/handoff-verification-record.ts) that contains a SHA-256 hash of the payload body and a timestamp. This cryptographic verification ensures that downstream agents receive exactly the data intended, with tamper-evident audit trails for observability tools like the watchdog and checkpoint-restart systems.

## Core Architecture Components

The handoff system isolates payload construction, transport, and error handling into distinct layers:

- **Handoff Core** ([`core/handoff.ts`](https://github.com/cursor/plugins/blob/main/core/handoff.ts)): Constructs and validates payloads against schemas before dispatch.
- **Agent Manager** ([`core/agent-manager.ts`](https://github.com/cursor/plugins/blob/main/core/agent-manager.ts)): Central dispatcher that selects appropriate adapters (Slack, HTTP, etc.) and manages retry logic.
- **Verification Record** ([`core/handoff-verification-record.ts`](https://github.com/cursor/plugins/blob/main/core/handoff-verification-record.ts)): Generates cryptographic hashes and audit metadata for every handoff.
- **Failure Handoff** ([`core/failure-handoff.ts`](https://github.com/cursor/plugins/blob/main/core/failure-handoff.ts)): Creates safe fallback payloads when primary delivery fails, routing to designated error-handling agents.
- **Adapters** ([`adapters/slack/client.ts`](https://github.com/cursor/plugins/blob/main/adapters/slack/client.ts)): Translate handoff objects into concrete transport formats without modifying core logic.
- **Privacy Redaction** ([`core/redact-body.ts`](https://github.com/cursor/plugins/blob/main/core/redact-body.ts)): Strips PII from payloads before logging or persistence.

## Step-by-Step Implementation

### Creating the Handoff Payload

Upstream agents assemble payloads that conform to the schema requirements. The payload must include identifying information for the task and the target agent.

```typescript
import { handoff } from '@/orchestrate/skills/orchestrate/scripts/core/handoff';
import { AgentName } from '@/orchestrate/skills/orchestrate/scripts/types';

// Build the payload that complies with the schema defined in scripts/schemas.ts
const payload = {
  taskId: '12345',
  result: { summary: 'All good', data: { /* ... */ } },
  nextAgent: 'reviewer' as AgentName,
};

// Send the handoff to the downstream "reviewer" agent
await handoff(payload, 'reviewer');

```

*Source:* [[`core/handoff.ts`](https://github.com/cursor/plugins/blob/main/core/handoff.ts)](https://github.com/cursor/plugins/blob/main/orchestrate/skills/orchestrate/scripts/core/handoff.ts)

### Verification and Dispatch

When `handoff()` receives the payload, it immediately calls `createVerificationRecord()` to generate a cryptographic hash and timestamp. The **agent manager** then selects the appropriate adapter based on the target agent's configuration and dispatches the verified record.

This dispatch process handles transport abstraction—whether routing through Slack, HTTP endpoints, or custom channels—while maintaining the integrity of the verification record. Each adapter implements the required `send` contract defined in the adapter interface.

### Downstream Reception and Validation

Downstream agents receive handoffs through CLI entry points and must validate the verification record before processing. The [`cli/task.ts`](https://github.com/cursor/plugins/blob/main/cli/task.ts) file provides the standard entry point for this workflow.

```typescript
import { verifyRecord } from '@/orchestrate/skills/orchestrate/scripts/core/handoff';
import { parseIncoming } from '@/orchestrate/skills/orchestrate/scripts/cli/util';

async function run() {
  // Pull the raw message (e.g., from Slack)
  const raw = await parseIncoming();

  // Convert raw JSON into a typed handoff verification record
  const record = JSON.parse(raw);

  // Ensure the payload matches the schema and hash
  const isValid = await verifyRecord(record);
  if (!isValid) {
    throw new Error('Invalid handoff verification');
  }

  // Continue processing with the verified payload
  const { taskId, result } = record.payload;
  console.log(`Continuing task ${taskId}`, result);
}

run().catch(console.error);

```

*Source:* [[`cli/task.ts`](https://github.com/cursor/plugins/blob/main/cli/task.ts)](https://github.com/cursor/plugins/blob/main/orchestrate/skills/orchestrate/scripts/cli/task.ts)

## Handling Failures with Fallback Handoffs

When validation fails or the downstream agent is unavailable, the system activates the **failure-handoff** path. The `failureHandoff()` function in [`core/failure-handoff.ts`](https://github.com/cursor/plugins/blob/main/core/failure-handoff.ts) constructs a fallback payload that preserves error context and routes it to a designated error-handler agent.

```typescript
import { failureHandoff } from '@/orchestrate/skills/orchestrate/scripts/core/failure-handoff';

async function onDeliveryError(originalRecord, err) {
  // Create a fallback payload that includes the error context
  const fallback = {
    originalTaskId: originalRecord.payload.taskId,
    error: err.message,
    retry: false,
  };

  // Route the fallback to the "error-handler" agent
  await failureHandoff(fallback, 'error-handler');
}

```

*Source:* [[`core/failure-handoff.ts`](https://github.com/cursor/plugins/blob/main/core/failure-handoff.ts)](https://github.com/cursor/plugins/blob/main/orchestrate/skills/orchestrate/scripts/core/failure-handoff.ts)

This ensures that workflow state is never lost—failed handoffs become tasks for error-handling agents rather than silent failures.

## Extending the System with Custom Adapters

Because handoffs are **pure data objects**, the system supports new transport mechanisms without modifying core orchestration logic. To add a new adapter:

1. Create a new directory under `adapters/` (e.g., `adapters/teams/` or `adapters/pubsub/`).
2. Implement the `send` and `receive` contracts to translate handoff objects into your transport format.
3. Register the adapter with the agent manager in [`core/agent-manager.ts`](https://github.com/cursor/plugins/blob/main/core/agent-manager.ts).

The Slack adapter at [`adapters/slack/client.ts`](https://github.com/cursor/plugins/blob/main/adapters/slack/client.ts) demonstrates this pattern by converting handoff verification records into Slack API messages while preserving the underlying payload structure.

## Summary

- **Structured handoffs** in Orchestrate are schema-verified messages that enable reliable task propagation between agents in the `cursor/plugins` repository.
- Each handoff generates a **cryptographic verification record** with SHA-256 hashing to ensure payload integrity.
- The **agent manager** abstracts transport concerns, routing handoffs through adapters like Slack or HTTP without changing core logic.
- **Failure handoffs** provide automatic fallback routing to error-handling agents when delivery fails.
- **Redaction utilities** ensure PII is stripped from logs while preserving operational metadata.

## Frequently Asked Questions

### What makes a handoff "structured" in the Orchestrate system?

A handoff is structured because it must conform to a strict JSON schema defined in [`scripts/schemas.ts`](https://github.com/cursor/plugins/blob/main/scripts/schemas.ts) and carry a verification record with cryptographic hashing. This structure ensures type safety, payload integrity, and observability across the workflow chain.

### How does the system handle network failures or unavailable agents?

When delivery fails, the `failureHandoff()` function in [`core/failure-handoff.ts`](https://github.com/cursor/plugins/blob/main/core/failure-handoff.ts) automatically generates a fallback payload containing error details and routes it to a designated error-handler agent. This prevents workflow stalls and ensures visibility into delivery problems.

### Can I integrate custom communication channels beyond Slack?

Yes. The architecture supports adding new adapters under the `adapters/` directory by implementing the standard send/receive interface. The system treats handoffs as pure data objects, so you can add Teams, Pub/Sub, or proprietary channels without modifying the core handoff logic in [`core/handoff.ts`](https://github.com/cursor/plugins/blob/main/core/handoff.ts).

### How is sensitive data protected during handoff propagation?

The [`core/redact-body.ts`](https://github.com/cursor/plugins/blob/main/core/redact-body.ts) utility automatically strips PII from payloads before logging or persistence. This ensures that while verification records maintain hash integrity for audit trails, actual sensitive content is sanitized according to data-privacy constraints.