> ## Documentation Index
> Fetch the complete documentation index at: https://docs.omegas.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# The Handoff protocol

> A tour of the normative v0.1 specification: the object model, the state machines, receipts, authorizations, and the signing scheme.

The normative text lives in the repository at
[`spec/handoff-protocol-v0.1.md`](https://github.com/OmegaAgent/handoff/blob/main/spec/handoff-protocol-v0.1.md),
written with RFC 2119 keywords, alongside the OpenAPI 3.1 wire contract
([`spec/openapi.yaml`](https://github.com/OmegaAgent/handoff/blob/main/spec/openapi.yaml)),
JSON Schemas, and the signing scheme with reproducible test vectors
([`spec/signing.md`](https://github.com/OmegaAgent/handoff/blob/main/spec/signing.md)).
This page is an orientation, not a replacement; where they disagree, the spec
wins.

## The object model

Five objects carry the protocol. Each has its own state machine in the spec.

| Object            | What it is                                                                                                                            |
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| **Request**       | The question. Declares what it needs (fields, capabilities, authority), never a `kind`.                                               |
| **Delivery**      | One attempt to put the request in front of a person, over a named channel, with a grade recording what that delivery actually proves. |
| **Receipt**       | The tamper-evident record that a specific actor answered a specific presentation of a specific request.                               |
| **Waiter**        | The durable server-side wait, keyed by your `waiter_ref`, so the process that asked can die and a successor can resume.               |
| **Authorization** | What an approving answer mints: a value that is redeemed against exactly one effect key, idempotently.                                |

## Declarations, not kinds

There is no `kind` enum on the wire and no branch behind one. A request
declares three things: the shape of the answer (`answer.fields`), what the
person must be handed to decide (`capabilities`, as opaque handles their own
client resolves), and the authority the answer requires (role, freshness,
quorum). All eight interaction patterns the spec requires are eight
declarations over that one shape.

Two consequences worth knowing before you design against it:

* A `secret` field never carries its value through the protocol. The answer
  says `{"provided": true}` and the value goes to a sink your runtime owns and
  can audit (§12, out-of-band secret custody). Declaring a secret field also
  raises the authority floor server-side, as a consequence of the request's
  shape.
* Unknown field types are rejected at raise time rather than degraded. A field
  a renderer cannot draw is a field a human cannot answer.

## Identity, and who may answer

Requests have three deliberately distinct keys: the server-minted id, your
`dedupe_key` (what makes two raises "the same request"), and your `waiter_ref`
(what a successor process presents to resume the wait). Identity is
tenant-scoped throughout.

The requester may not answer its own request (§4.2), an identifier is not an
authorization (§4.6), and a delivery channel never confers authority (§4.7).
Treat a request id as a capability: in this protocol it can be one, so it
belongs in the same custody as a credential.

## Defaults are declared, not guessed

A request that can proceed without an answer declares that at raise time, as a
TTL policy (`on_expiry: "default"` with the default value). When it fires, the
server mints a **policy receipt** with `actor.type = "policy"`, so no audit can
mistake a timeout for consent. Guessing the same value client-side afterwards
produces identical behaviour and no record at all; the difference between
those two is most of the reason to use the protocol.

## Receipts are evidence, not logs

A receipt binds the actor, the authority they held, and the exact presentation
the decision was made against (§9.3), and it lands on a hash chain
(`signing.md` §2.2) that any reader can walk with the standard library. The
chain makes tampering evident; it does not make the operator honest, which is
why the project says plainly that independent attestation requires a party who
is not the operator.

Corrections are new receipts that reference the old one. Nothing is edited in
place.

## Callbacks

Outbound callbacks are signed over the raw bytes on the wire. Verification
rules that both SDKs enforce:

* Verify the bytes as received; re-encoding a parsed body changes the hash.
* A valid signature proves the sender, never the tenant. Resolve tenancy from
  your own stored state, keyed on the endpoint or the secret, and never from a
  field in the body.
* `delivery_id` is your deduplication key.

## Errors

Every error carries a stable machine-readable `code` (§13). Branch on the
code, never the message. The SDKs raise typed classes that mirror the codes
and pass unknown codes through intact rather than coercing them into the
nearest familiar class.

## Level 2 exists and is deliberately not implemented

Conformance Level 2 adds the `continuation` extension (§14): a server that
stores an encrypted `resume_payload` alongside the wait. The reference
implementation refuses such payloads, because it has no encryption at rest to
protect one with, and it advertises Level 1, derived from that same capability
check so the advertisement and the behaviour cannot drift.
