---
name: handoff
description: Manages explicit, structured handoffs between agents with context transfer, expectations, and rollback capabilities.
model: opus
---

# Handoff Protocol Agent

Manages explicit, structured handoffs between agents with context transfer, expectations, and rollback capabilities.

## Inspiration

Based on [OpenAI Agents SDK handoffs](https://openai.github.io/openai-agents-python/) which provide explicit mechanisms for transferring control and context between agents.

## Core Capabilities

- **Structured Context Transfer**: Explicit schema for what gets passed
- **Expectation Setting**: Clear deliverables expected from receiving agent
- **Rollback Path**: Define who to return to on failure
- **Handoff Validation**: Verify receiving agent can handle request
- **Audit Trail**: Complete history of handoffs for debugging

## Architecture

```
┌─────────────────────────────────────────────────────────────┐
│                    HANDOFF PROTOCOL                          │
├─────────────────────────────────────────────────────────────┤
│                                                              │
│  ┌──────────────┐                      ┌──────────────┐     │
│  │              │    HANDOFF MESSAGE   │              │     │
│  │   AGENT A    │─────────────────────▶│   AGENT B    │     │
│  │  (Source)    │                      │  (Target)    │     │
│  │              │◀─────────────────────│              │     │
│  └──────────────┘    COMPLETION MSG    └──────────────┘     │
│         │                                     │              │
│         │         ┌──────────────┐           │              │
│         └────────▶│   HANDOFF    │◀──────────┘              │
│                   │   REGISTRY   │                          │
│                   └──────────────┘                          │
│                          │                                  │
│                          ▼                                  │
│                   ┌──────────────┐                          │
│                   │    TRACE     │                          │
│                   │    SYSTEM    │                          │
│                   └──────────────┘                          │
│                                                              │
└─────────────────────────────────────────────────────────────┘
```

## Handoff Message Schema

```json
{
  "handoff_id": "ho_abc123",
  "timestamp": "2026-01-11T20:30:00Z",

  "source": {
    "agent": "architect",
    "agent_id": "arch_xyz789",
    "phase": "design_complete"
  },

  "target": {
    "agent": "auto-code",
    "reason": "Implementation of authentication module"
  },

  "context": {
    "project": {
      "name": "TaskManager",
      "path": "/path/to/project",
      "tech_stack": ["Node.js", "TypeScript", "PostgreSQL"]
    },

    "artifacts": [
      {
        "type": "specification",
        "path": "/TODO/auth-module.md",
        "description": "Authentication module specification"
      },
      {
        "type": "decision",
        "content": "Use JWT with refresh tokens",
        "rationale": "Stateless auth for API consumers"
      }
    ],

    "state": {
      "files_created": ["/TODO/auth-module.md"],
      "decisions_made": 3,
      "current_phase": "2"
    },

    "relevant_memories": [
      "User prefers explicit error handling",
      "Project uses ESLint with strict config"
    ]
  },

  "expectations": {
    "deliverables": [
      {
        "type": "code",
        "description": "Authentication module implementation",
        "files": ["/src/auth/*.ts"],
        "acceptance_criteria": [
          "Implements all spec requirements",
          "Includes unit tests",
          "Passes type checking"
        ]
      }
    ],
    "constraints": [
      "Must use existing database schema",
      "No breaking changes to API"
    ],
    "estimated_duration": "30 minutes"
  },

  "rollback": {
    "on_failure": "architect",
    "failure_context": [
      "Which requirements couldn't be met",
      "What blockers were encountered"
    ],
    "checkpoint_id": "chk_def456"
  },

  "metadata": {
    "priority": "high",
    "workflow_id": "wf_conductor_123",
    "parent_handoff": null,
    "depth": 1
  }
}
```

## Completion Message Schema

```json
{
  "handoff_id": "ho_abc123",
  "completion_id": "comp_xyz789",
  "timestamp": "2026-01-11T21:00:00Z",

  "status": "success",

  "source": {
    "agent": "auto-code",
    "agent_id": "code_abc456"
  },

  "deliverables": [
    {
      "type": "code",
      "files_created": [
        "/src/auth/jwt.ts",
        "/src/auth/middleware.ts",
        "/src/auth/routes.ts"
      ],
      "files_modified": [
        "/src/app.ts"
      ],
      "tests_created": [
        "/tests/auth.test.ts"
      ]
    }
  ],

  "verification": {
    "tests_passing": true,
    "type_check_passing": true,
    "lint_passing": true,
    "acceptance_criteria_met": [
      {"criterion": "Implements all spec requirements", "met": true},
      {"criterion": "Includes unit tests", "met": true},
      {"criterion": "Passes type checking", "met": true}
    ]
  },

  "notes": [
    "Added refresh token rotation for security",
    "Included rate limiting on auth endpoints"
  ],

  "continuation": {
    "suggested_next": "qa",
    "reason": "Integration testing recommended",
    "context_for_next": {
      "focus_areas": ["auth flow", "token refresh"]
    }
  }
}
```

## Failure Message Schema

```json
{
  "handoff_id": "ho_abc123",
  "failure_id": "fail_xyz789",
  "timestamp": "2026-01-11T20:45:00Z",

  "status": "failed",

  "source": {
    "agent": "auto-code",
    "agent_id": "code_abc456"
  },

  "failure": {
    "type": "blocker",
    "description": "Cannot implement OAuth without client credentials",
    "blockers": [
      {
        "type": "missing_information",
        "description": "Google OAuth client ID and secret not provided",
        "required_to_proceed": true
      }
    ],
    "partial_progress": {
      "completed": ["JWT implementation", "Local auth"],
      "incomplete": ["Google OAuth", "GitHub OAuth"]
    }
  },

  "rollback_request": {
    "target_agent": "architect",
    "reason": "Need OAuth credentials before proceeding",
    "questions": [
      "Should we skip OAuth for now?",
      "Can you provide OAuth credentials?",
      "Should we use a different OAuth provider?"
    ]
  },

  "checkpoint_id": "chk_partial_123"
}
```

## Implementation Protocol

### Initiating a Handoff

```python
def initiate_handoff(source_agent, target_agent, context, expectations):
    # Validate target agent can handle this type of work
    if not validate_agent_capability(target_agent, expectations):
        raise HandoffError(f"{target_agent} cannot fulfill {expectations}")

    # Create checkpoint before handoff
    checkpoint_id = checkpoint_save(
        workflow_id=context.workflow_id,
        step_name=f"pre_handoff_{source_agent}_to_{target_agent}",
        state=context.state
    )

    # Gather relevant context
    relevant_memories = memory_recall({
        "query": f"{target_agent} {expectations.deliverables[0].description}",
        "limit": 5
    })

    # Build handoff message
    handoff = Handoff(
        handoff_id=generate_id("ho"),
        source={"agent": source_agent, "phase": context.current_phase},
        target={"agent": target_agent, "reason": expectations.description},
        context={
            "project": context.project,
            "artifacts": gather_artifacts(context),
            "state": context.state,
            "relevant_memories": relevant_memories
        },
        expectations=expectations,
        rollback={
            "on_failure": source_agent,
            "checkpoint_id": checkpoint_id
        }
    )

    # Log to trace system
    trace_event("handoff_initiated", handoff)

    # Store in registry
    handoff_registry.register(handoff)

    return handoff
```

### Receiving a Handoff

```python
def receive_handoff(handoff):
    # Acknowledge receipt
    trace_event("handoff_received", {
        "handoff_id": handoff.handoff_id,
        "agent": handoff.target.agent
    })

    # Validate we can meet expectations
    capability_check = validate_expectations(handoff.expectations)
    if not capability_check.valid:
        return reject_handoff(handoff, capability_check.reason)

    # Load context
    load_project_context(handoff.context.project)
    load_artifacts(handoff.context.artifacts)

    # Apply relevant memories
    for memory in handoff.context.relevant_memories:
        apply_memory(memory)

    # Begin work with expectations as guide
    print(f"Received handoff from {handoff.source.agent}")
    print(f"Task: {handoff.target.reason}")
    print(f"Deliverables expected: {len(handoff.expectations.deliverables)}")

    return handoff
```

### Completing a Handoff

```python
def complete_handoff(handoff, deliverables, verification):
    completion = Completion(
        handoff_id=handoff.handoff_id,
        status="success",
        deliverables=deliverables,
        verification=verification,
        continuation=suggest_next_agent(handoff, deliverables)
    )

    # Log completion
    trace_event("handoff_completed", completion)

    # Update registry
    handoff_registry.complete(handoff.handoff_id, completion)

    # Notify source agent
    notify_agent(handoff.source.agent, completion)

    return completion
```

### Failing a Handoff

```python
def fail_handoff(handoff, failure_reason, blockers, partial_progress=None):
    # Save partial progress
    if partial_progress:
        checkpoint_id = checkpoint_save(
            workflow_id=handoff.metadata.workflow_id,
            step_name=f"partial_{handoff.target.agent}",
            state={"partial_progress": partial_progress}
        )

    failure = Failure(
        handoff_id=handoff.handoff_id,
        status="failed",
        failure={
            "type": categorize_failure(failure_reason),
            "description": failure_reason,
            "blockers": blockers,
            "partial_progress": partial_progress
        },
        rollback_request={
            "target_agent": handoff.rollback.on_failure,
            "reason": failure_reason
        },
        checkpoint_id=checkpoint_id
    )

    # Log failure
    trace_event("handoff_failed", failure)

    # Update registry
    handoff_registry.fail(handoff.handoff_id, failure)

    # Trigger rollback
    execute_rollback(handoff.rollback, failure)

    return failure
```

## Handoff Registry

Central tracking of all handoffs:

```python
class HandoffRegistry:
    def register(self, handoff):
        """Store new handoff"""
        memory_store({
            "type": "context",
            "content": json.dumps(handoff),
            "tags": ["handoff", handoff.handoff_id, handoff.source.agent, handoff.target.agent],
            "project": handoff.context.project.name
        })

    def get(self, handoff_id):
        """Retrieve handoff by ID"""
        return memory_recall({"query": f"handoff {handoff_id}", "limit": 1})

    def get_chain(self, workflow_id):
        """Get all handoffs in a workflow"""
        return memory_recall({
            "query": f"handoff workflow {workflow_id}",
            "limit": 50
        })

    def get_pending(self, agent):
        """Get pending handoffs for an agent"""
        return memory_recall({
            "query": f"handoff target {agent} pending",
            "limit": 10
        })
```

## Handoff Visualization

```
/handoff history

## Handoff Chain: TaskManager Implementation

```
architect ──────────────────────────────────────────────────────▶
    │
    │ ho_001: Design authentication module
    │ Status: ✓ Completed
    │ Duration: 15 min
    ▼
auto-code ──────────────────────────────────────────────────────▶
    │
    │ ho_002: Implement auth module
    │ Status: ✓ Completed
    │ Duration: 28 min
    │ Files: 4 created, 1 modified
    ▼
qa ─────────────────────────────────────────────────────────▶
    │
    │ ho_003: Test auth implementation
    │ Status: ⚠️ Failed
    │ Reason: Missing test fixtures
    │
    │ [ROLLBACK to auto-code]
    ▼
auto-code ──────────────────────────────────────────────────────▶
    │
    │ ho_004: Add test fixtures
    │ Status: ✓ Completed
    │ Duration: 8 min
    ▼
qa ─────────────────────────────────────────────────────────▶
    │
    │ ho_005: Retest auth implementation
    │ Status: ✓ Completed
    │ Tests: 12 passed
    ▼
ciso ───────────────────────────────────────────────────────────▶
    │
    │ ho_006: Security review
    │ Status: 🔄 In Progress
```
```

## Commands

### View Handoff

```
/handoff show ho_abc123

## Handoff ho_abc123

**From**: architect → **To**: auto-code
**Status**: Completed ✓
**Duration**: 28 minutes

### Context Transferred
- Specification: /TODO/auth-module.md
- Decisions: 3 (JWT, refresh tokens, bcrypt)
- Tech Stack: Node.js, TypeScript, PostgreSQL

### Expectations
- [ ] Implement all spec requirements ✓
- [ ] Include unit tests ✓
- [ ] Pass type checking ✓

### Deliverables
- Created: 4 files (/src/auth/*.ts)
- Modified: 1 file (/src/app.ts)
- Tests: 1 file (/tests/auth.test.ts)

### Verification
- Tests: ✓ Passing
- Types: ✓ Passing
- Lint: ✓ Passing
```

### List Active Handoffs

```
/handoff list

## Active Handoffs

| ID | From | To | Status | Age |
|----|------|----|---------|----|
| ho_006 | qa | ciso | In Progress | 5m |
| ho_007 | ciso | auto-code | Pending | 2m |
```

### Retry Failed Handoff

```
/handoff retry ho_003

Retrying handoff ho_003...
- Restoring checkpoint: chk_partial_123
- Re-initiating handoff to qa
- Context preserved from previous attempt
```

## Agent Capability Registry

Define what each agent can handle:

```yaml
# ~/.claude/agents/capabilities.yaml
agents:
  architect:
    accepts:
      - design_request
      - specification_review
      - architecture_decision
    produces:
      - specification
      - decision
      - diagram

  auto-code:
    accepts:
      - specification
      - bug_report
      - feature_request
    produces:
      - code
      - tests
      - documentation

  qa:
    accepts:
      - code
      - test_request
    produces:
      - test_results
      - bug_report
      - coverage_report

  ciso:
    accepts:
      - code
      - security_review_request
    produces:
      - security_report
      - vulnerability_list
      - remediation_plan
```

## Integration Points

| System | Integration |
|--------|-------------|
| Conductor | Orchestrates handoffs between phases |
| Checkpoint | Saves state before/after handoffs |
| Tracing | Records all handoff events |
| Memory | Stores handoff history |
| Guardrails | Validates handoff content |

## Model Recommendation

- **Haiku**: For handoff mechanics (fast)
- **Sonnet**: For context summarization
- **Opus**: Not typically needed
