Skip to content

Agent Handoff

When multiple agent profiles run on the same issue — for example a research profile followed by an implementer followed by a reviewer — they can share structured deliverables via a per-issue handoff directory on the worktree branch. This guide walks through the convention and a three-profile worked example.

Each worker run leaves a Markdown deliverable at:

.itervox/handoff/<ISO8601-timestamp>_<profile-name>.md

The ISO8601 timestamp is generated by the orchestrator at dispatch time, with : replaced by - so it is filename-safe. Lexicographic order equals chronological order, so a plain ls of the directory is also the timeline.

Before dispatching any worker, the orchestrator:

  1. Reads every .md file in the directory.
  2. Sorts by filename (chronological).
  3. Concatenates them, applying a 30 KB budget — oldest files are dropped first with a [earlier handoffs truncated] marker.
  4. Inlines the result as a ## Prior Agent Handoffs block in the worker’s prompt.
  5. Adds a ## Run Context block with run.timestamp and run.handoff_path so the agent knows where to write its own deliverable.

The profile’s INSTRUCTIONS.md is responsible for telling the agent to read the prior handoffs and write its own — the orchestrator does not interpret the content.

.itervox/handoff/** is committable. itervox init and itervox init --update --workflow WORKFLOW.md patch the root .gitignore to whitelist it alongside .itervox/agents/**:

.itervox/
!.itervox/
!.itervox/agents/
!.itervox/agents/**
!.itervox/handoff/
!.itervox/handoff/**

Commit the handoff files into PRs so reviewers can read the chain. The pipeline trail becomes part of the PR’s documentation: research notes, design briefs, implementation summaries, and review findings all live alongside the code.

If a worker exits with TerminalFailed (process crash, render error) or TerminalStalled (the orchestrator’s stall watchdog cancelled the worker context), the orchestrator finds the most recent <timestamp>_<profile>.md file authored by that worker and renames it to <timestamp>_<profile>.partial.md. Subsequent agents still see the partial in their handoff context but with an explicit marker:

### 2026-05-26T15-12-00Z_implementer.partial.md (partial — prior agent exited before completing this deliverable)

TerminalInputRequired does NOT mark partial — the agent intentionally paused and will resume; its in-progress file remains as-is and can be extended on resume.

Worked example: research → implement → review

Section titled “Worked example: research → implement → review”

This example uses three profiles wired through issue_entered_state automations. As the orchestrator moves an issue between tracker states, each new state fires a different profile, and each profile reads the prior handoffs from .itervox/handoff/.

---
itervox_schema_version: 2
tracker:
kind: linear
api_key: ${LINEAR_API_KEY}
project_slug: my-project
active_states: ["Todo", "Researching", "Implementing", "Reviewing"]
completion_state: "Done"
failed_state: "Won't Do"
workspace:
root: ~/.itervox/workspaces/my-project
worktree: true
base_branch: main
auto_clear: true # clears when issue reaches Done or Won't Do
agent:
max_concurrent_agents: 3
reviewer_profile: reviewer
auto_review: false # we drive the reviewer via automation instead
profiles:
researcher:
command: claude
soul_file: .itervox/agents/researcher/SOUL.md
instructions_file: .itervox/agents/researcher/INSTRUCTIONS.md
allowed_actions: ["move_state", "comment"]
implementer:
command: claude
soul_file: .itervox/agents/implementer/SOUL.md
instructions_file: .itervox/agents/implementer/INSTRUCTIONS.md
allowed_actions: ["move_state", "comment"]
reviewer:
command: claude
soul_file: .itervox/agents/reviewer/SOUL.md
instructions_file: .itervox/agents/reviewer/INSTRUCTIONS.md
allowed_actions: ["move_state", "comment"]
automations:
- id: kick-off-research
trigger:
type: issue_entered_state
states: ["Todo"]
profile: researcher
policy:
move_to_state: "Researching"
- id: kick-off-implementation
trigger:
type: issue_entered_state
states: ["Researching"]
profile: implementer
policy:
move_to_state: "Implementing"
- id: kick-off-review
trigger:
type: issue_entered_state
states: ["Implementing"]
profile: reviewer
policy:
move_to_state: "Reviewing"
---
Implement issue {{ issue.identifier }}: {{ issue.title }}.
{{ issue.description }}

Each profile’s INSTRUCTIONS.md includes a Handoff Protocol section. itervox init scaffolds this automatically; here are the relevant excerpts.

.itervox/agents/researcher/INSTRUCTIONS.md:

# researcher INSTRUCTIONS
## Workflow
- Map the parts of the codebase relevant to this issue.
- Identify existing patterns to follow.
- Flag risks: timezones, multi-tenant data, retry semantics, schema drift.
- Do NOT edit code or run state-changing commands.
## Done Criteria
- Findings cover relevant files, existing patterns, and risks.
- The handoff file ends with an explicit next-step recommendation.
- Move the issue to "Researching" via the daemon action.
## Handoff Protocol
- The orchestrator prepends a "## Prior Agent Handoffs" block to your prompt with every prior agent's deliverable on this issue's branch.
- Before exiting, write a concise Markdown deliverable to `run.handoff_path` (see the "## Run Context" block).
- Do not edit handoff files authored by prior agents.

.itervox/agents/implementer/INSTRUCTIONS.md:

# implementer INSTRUCTIONS
## Workflow
- Read the researcher's handoff for context — do not re-explore.
- Implement the smallest complete change.
- Match existing patterns flagged by the researcher.
- Write or update tests alongside the implementation.
## Done Criteria
- The change addresses the issue's intent.
- Tests pass (capture command output in the handoff).
- Move the issue to "Implementing" via the daemon action.
## Handoff Protocol
- Read the prior "## Prior Agent Handoffs" block in your prompt.
- Write your deliverable to `run.handoff_path` — list files changed, tests added, commands run, and any risks the reviewer should focus on.

.itervox/agents/reviewer/INSTRUCTIONS.md:

# reviewer INSTRUCTIONS
## Workflow
- Read every prior handoff: the researcher's brief, the implementer's summary.
- Inspect the diff against the brief — verify the implementation actually does what was scoped.
- Look for: real bugs, regressions, race conditions, missing tests, security issues, scope creep.
## Done Criteria
- Findings are specific (file path + line number) and grouped by severity (Critical / Important / Minor).
- If no findings, say so plainly — do NOT invent issues to look thorough.
- Move the issue to "Done" if clean; back to "Implementing" with critical findings if not.
## Handoff Protocol
- Read all prior handoffs to understand intent before evaluating the diff.
- Write your review to `run.handoff_path` grouped by severity.

Working on ENG-42, after all three profiles have run:

Terminal window
$ ls .itervox/handoff/
2026-05-26T14-30-45Z_researcher.md
2026-05-26T14-58-12Z_implementer.md
2026-05-26T15-22-08Z_reviewer.md

Each agent’s prompt contained everything that came before it. The implementer saw the researcher’s brief; the reviewer saw both. The full reasoning trail lives in the PR alongside the code changes.

If the implementer crashes mid-run (e.g. the model hits a transient API error and exhausts retries), the file it had started writing is renamed:

Terminal window
$ ls .itervox/handoff/
2026-05-26T14-30-45Z_researcher.md
2026-05-26T14-58-12Z_implementer.partial.md # crash here

When the next implementer attempt fires (either via retry or via an operator manually moving the issue back through state), it reads the partial in its prior-handoffs context and can decide whether to start fresh or build on the partial work. The partial marker makes the distinction unambiguous; you do not need a separate “this run failed” flag.

The 30 KB token budget on the prior-handoffs section is a default chosen to leave ample room for the rest of the prompt (issue body, profile content, sub-agent roster, PR context). Issues that accumulate many handoffs — for example after several retry attempts or a long-running multi-profile pipeline — will see the oldest files dropped first with:

_[N earlier handoffs truncated to fit budget — see `.itervox/handoff/` for full history]_

When this happens, the dropped files still exist on disk. The agent can read them directly with the Read tool if it needs detail; the prerender is just the default convenience.

The handoff convention shines when:

  • Multiple profiles run sequentially on the same issue.
  • The work splits into distinguishable phases (research, design, build, verify, review).
  • You want the pipeline reasoning trail to commit into PRs.

It is unnecessary when:

  • A single profile handles the whole issue end-to-end.
  • The profile’s own output is already captured in code commits and tracker comments.
  • The team’s review tradition is “read the diff” rather than “read the design brief.”

In those cases, skip the chain and use a single profile with auto_review for the post-implementation reviewer pass. The handoff convention is opt-in — agents that do not write to run.handoff_path simply leave no trail.