Skip to content
awesome-applied-ai
← Design problems

17Orchestration & Protocols

Handoff contracts between agents

Agent A extracts requirements, hands to B which produces a plan, hands to C which executes. Post-mortems keep tracing failures to information silently lost at a handoff. Fix it.

The constraint. A natural-language handoff is unvalidated serialization. Each boundary is a lossy encoder with no checksum, and the failure mode is silent omission rather than a visible error — the downstream agent proceeds confidently on incomplete input.

Treat the handoff as an API.

  1. 01The contract is a schema, not a prompt instruction. JSON Schema or Pydantic, validated by the producer on emit and again by the consumer on receipt. An instruction to "include all constraints" is a wish; a required field is a contract.
  2. 02Required fields have no defaults. If A cannot determine budget_constraint, it must emit an explicit unknown with a reason. Omission is what goes silent; an explicit unknown is a fact the next agent can act on.
  3. 03Carry provenance per field. Record whether a value came from the user's words, a tool result, or the model's inference. C should treat an inferred budget differently from a stated one. This is the highest-value addition on this list and it is almost never done.
  4. 04Pass a reference to upstream context, not a copy. B rarely needs A's full transcript, but when it does it should fetch it rather than rely on A having guessed what to include. A handle costs nothing; a guess costs the failure you are debugging.
  5. 05Version the contract. Agents deploy independently, so the schema is the compatibility boundary. Treat a field change like a breaking API change.

How you pin down non-determinism. Contract tests at each boundary, exactly as with microservices: fixed inputs, assertions on the structured output, run in CI. You cannot assert on prose, which is why the schema matters — it converts an untestable boundary into a testable one.

Stack. Grammar-constrained decoding via XGrammar or llguidance so the schema is enforced during generation rather than validated afterwards — a retry loop on validation failure is a worse version of the same thing. Pydantic with instructor for the type layer. LangGraph typed state where the boundary is in-process. Pact-style contract tests where the agents deploy separately.

Where answers fail. Proposing a better prompt. The boundary needs a type system, not more adjectives.