Development Choices

Agent Handoffs Across System Boundaries

Author
Gregory MostizkySoftware Engineer
Published
Section
AI Agents
Length
7 min read3 sources cited

Handing work between agents is reliable only when the boundary carries a compact task contract: objective, constraints, current state, idempotency key, correlation identifier, and failure policy. Transcripts are poor handoff records. The receiver must be able to retry safely, trace the run across systems, and recover when no receiver responds.

Handing work between agents and systems

A handoff transfers responsibility for a task from one agent or system to another. It works only when the boundary preserves enough explicit state to continue safely, identify the same run everywhere, and recover when delivery or execution fails.

A handoff is a serialisation boundary

Whatever crosses the boundary is what the receiver knows. Anything left in the sending agent’s context—an assumption, a rejected approach, an approval limit, the meaning of an ambiguous filename—disappears regardless of how well the sender understood it.

That makes every handoff a serialisation boundary. The sender must turn its working understanding into a durable, readable record. The record can be carried in a queue message, workflow state, tool call, job row, or file, but the medium does not remove the requirement. If the receiver needs a fact to act correctly, that fact has to be represented.

Temporal’s workflow documentation (accessed 26 August 2026) provides the relevant durability model: execution can recover only from state represented in the workflow’s recorded history. Agent handoffs need the same discipline even when Temporal is not the system carrying them.

The useful boundary is also a deliberate compression point. Persist the objective, current state, constraints, completed effects, required inputs, and expected result. Do not try to preserve every intermediate thought. The engineering cost is schema design and maintenance, but the alternative is an undocumented dependency on one agent’s temporary context. Decisions that must survive outside a single run belong in agent memory and state, not only in a prompt window.

Pass the task and constraints, not the transcript

A transcript records how the sender arrived at the handoff. It does not reliably state what the receiver must do. It may contain abandoned plans, tool errors, speculative claims, superseded instructions, and several versions of the same decision. Passing it whole transfers that confusion along with the useful context.

The receiving side needs a task contract: the requested outcome, the inputs it may rely on, the constraints it must obey, what has already happened, and the condition that counts as completion. It also needs explicit authority boundaries. A receiver told to publish a prepared article, for example, must know whether it may edit the text, create missing assets, or only validate and publish the supplied files.

A compact handoff record might read:

handoff_id: article-184-publish
objective: validate and publish the prepared article
inputs:
  article_path: src/content/guides/article-184.md
constraints:
  content_changes: prohibited
  destination: preview
completed_effects:
  - hero image uploaded as asset-731
completion:
  - preview build passes
  - preview URL is returned

The exact field names matter less than the separation between instructions, evidence, and status. Summarising takes work and can omit something important, so the contract should be validated before responsibility moves. The transcript can remain available as supporting evidence when an investigation requires it, but it should not be the receiver’s operating specification. The same distinction determines whether sub-agent delegation reduces context pressure or merely distributes an unclear task.

Anthropic’s engineering guide to building effective agents (accessed 26 August 2026) describes agent systems in terms of simple, composable workflow patterns. A written task contract is what keeps those compositions understandable at the point where one component assigns work to another.

Idempotency must survive the boundary

The most common handoff failure is a retry that repeats work already completed on the other side. The sender times out before receiving confirmation, concludes that delivery failed, and sends the task again. The receiver may then publish twice, create another resource, send a second notification, or charge for the same operation again.

Idempotency therefore has to hold across the boundary, not merely inside each component. The sender must attach a stable idempotency key to the logical action and reuse that key on every retry. The receiver must record the key with the result or side effect, then return the recorded result when it sees the same key again. Generating a new key for each delivery attempt defeats the mechanism because every retry appears to be new work.

The key should identify the intended effect rather than the transport message. If one logical task is delivered three times, all three deliveries carry the same action key. If the task legitimately contains two distinct side effects, each effect needs an identity that prevents its own duplication. A receiver should record completion atomically with the protected effect where its storage model permits; otherwise a crash between performing the effect and recording it leaves an interval in which the retry cannot be classified safely.

This adds storage, lookup work, and a retention decision. Those costs are justified for side-effecting operations. Read-only computation that is cheap and deterministic may simply run again, but that does not make repeated external effects safe. The detailed design belongs with idempotency keys for agent actions.

Carry one correlation identifier throughout the run

A multi-system run is traceable only when every participant records the same correlation identifier. Without it, the sending agent, transport, and receiving system hold three unrelated stories: each has local timestamps and local identifiers, but nothing proves that their records describe the same handoff.

Create the correlation identifier when the overall run begins and propagate it unchanged across every boundary. Record it in handoff payloads, workflow state, structured logs, trace attributes, and returned status. Local job IDs and attempt IDs can still exist, but they should be associated with the shared identifier rather than replacing it.

OpenTelemetry’s trace concepts documentation (accessed 26 August 2026) defines a trace as the path a request takes through an application and explains how spans represent units of work along that path. A handoff should preserve that relationship even when execution changes process, service, queue, or agent.

Correlation does not repair a failed run; it makes the run reconstructable. It costs payload space and requires consistent logging conventions, while sensitive data must remain outside the identifier. The identifier should be opaque: encoding customer names, prompts, or task contents into it turns an observability field into a disclosure risk.

Define the failure path before the success path

A handoff with no defined behaviour for an unresponsive receiver becomes a task that quietly ceases to exist. Delivery may have failed, the receiver may be unavailable, or the work may have completed without its acknowledgement returning. The sender cannot distinguish those states merely from silence.

The contract must define when acknowledgement is due, what acknowledgement means, how long the sender waits, which failures may be retried, and who owns the task after the wait expires. It must also define a terminal destination for work that cannot progress. That destination can hold the original task contract, correlation identifier, attempt history, last known status, and the reason execution stopped so that a person or recovery process can make a decision.

Retries must use the original idempotency key. Otherwise the failure policy creates the duplicate-work failure it is meant to contain. Timeouts also need ownership semantics: until responsibility has been accepted, the sender remains responsible; after acceptance, the receiver must either complete the work or make its failure visible. A task must never sit in a state where both sides assume the other owns recovery.

This design costs queue or workflow state, monitoring, and operational attention. It is still necessary when a receiver is usually dependable, because the undefined case is precisely the one operators need during an outage. Work that has exhausted its permitted attempts needs an explicit review or disposal policy; dead-letter queues for agent jobs covers that terminal path.

What to specify next

A complete handoff specification should leave a reviewer able to locate the serialised task contract, identify its constraints, prove which effects already occurred, follow one correlation identifier across every participating system, and state who owns recovery at every point. If any answer depends on reading an agent’s old transcript or guessing what silence meant, the boundary is not yet defined.

Sources

  1. workflow documentationdocs.temporal.io
  2. engineering guide to building effective agentsanthropic.com
  3. trace concepts documentationopentelemetry.io

See also