{"slug": "show-hn-handoff-is-await-human-for-ai-agents", "title": "Show HN: Handoff is await human() for AI agents", "summary": "Handoff, an open protocol for requesting human decisions in AI agent workflows, has been released as a pre-release with a Rust reference implementation and conformance suite. The protocol ensures one human answer is delivered exactly once as typed data authorizing exactly one effect, and it does not resume program execution. A live hackathon demo is running at handoff.omegas.dev with no authentication, hosted on Fly.io.", "body_md": "**An open protocol for the moment a program needs a person.**\n\nAgents run continuously. The people who can unblock them do not, and those people are still the ones accountable for the decision. Handoff specifies what happens in between: how a request for a human decision is stated, how it reaches someone, how their answer comes back, and what record survives afterwards.\n\nThe claim the whole design is built to support is deliberately narrow:\n\nOne human answer, delivered to your agent exactly once, as typed data, authorizing exactly one effect.\n\nEvery clause of that is load-bearing:\n\n**One human answer.** A specific person acted, and the record says who. Clearance is*asserted*by a human, never*inferred*from a side effect. That distinction is the reason this project exists; the section on prior art below explains where it came from.**Exactly once.** An answer is consumed when it is used. A stored yes cannot be spent a second time by a retry, a replay, or a duplicate delivery.**As typed data.** The answer is a value against a declared schema, not free text that a prompt has to interpret. A field a renderer cannot draw is a field a human cannot answer, so unknown field types are rejected rather than degraded into a text box.**Authorizing exactly one effect.** The answer is bound to the specific thing it was shown against. It does not generalize to the next call, the next run, or a similar-looking request.\n\nIt does not resume your program's execution. There is no stack snapshot, no continuation capture, no reaching into your runtime. Your code asks, waits however it prefers (a blocking call, a webhook, a poll), and receives an answer. What it does with that answer is entirely yours. Any description that implies otherwise is overselling, including any we might write later.\n\nIt also does not make a self-hosted deployment good at reaching people. Delivery through email, SMS, or voice depends on sender reputation, aligned DNS records, a reviewed app, and carrier relationships. None of that ships in a container, and this repository will not pretend it does.\n\n**Pre-release. The protocol runs; it has not been published, and there is no hosted service running\nthis reference implementation.**\n\nA deployment of `examples/night-hack/`\n\n— the four-hour hackathon build preserved here as prior art,\nand not this implementation — **is running at handoff.omegas.dev with no authentication**. That\nwas checked on 2026-07-31: the host answers, served by Fly.io.\n\n`SECURITY.md`\n\nholds the detail and\nputs that hostname out of scope. It is a live hackathon demo, not this project, and not a dead\nlink. (This line previously said flatly that there is no hosted service, full stop,\nwhich is the sentence that was wrong.)Level 1 is 26 conformance cases: C-1 through C-16, plus C-6b and C-18 through C-26. C-17 is the only\nLevel 2 case, and this server deliberately does not implement what it covers — see below. The\nenumeration is spelled out rather than left as a bare count, because a count does not say *which*\ncases, and a Server passing every case but one is not Level 1 compliant. Read `docs/review-3.md`\n\nbefore relying on any of this — it is the most recent of three independent hostile reviews\n(`docs/hostile-review.md`\n\n, `docs/review-2.md`\n\n, `docs/review-3.md`\n\n), each of which found defects the\none before it had missed. `BACKLOG.md`\n\nstates the remaining gaps plainly rather than leaving them\nto be discovered.\n\n| Component | State |\n|---|---|\n`spec/` — the normative protocol |\nv0.1, frozen. 21 invariants, OpenAPI 3.1, signing test vectors that reproduce. |\n`conformance/` — the suite |\n26 Level 1 cases + 1 Level 2. Written before the server, and demonstrably red against one that implements nothing. |\n`core/` — the Rust reference implementation |\n`handoffd` , the target of the Level 1 suite. Level 2 (`continuation` ) is not implemented and is not advertised. |\n`sdk/python` — `handoff-human` |\n0.2.0. Standard library only. |\n`sdk/ts` — `@handoffproto/sdk` |\nZero runtime dependencies. |\n`managed/` — the hosted adapter |\nClosed-source, unpublished. Refuses where a dependency does not exist rather than pretending. |\n`ui/responder` — a standalone human-facing page |\nNot built. It appears in the layout below as intended; it is absent on disk. |\n\nNothing in this tree has been published. The one exception predates it: `handoff-human`\n\n0.1.0 is\nalready on PyPI from the hackathon build, under the MIT grant `NOTICE`\n\nrelies on. The 0.2.0 in\n`sdk/python`\n\nis not published, and the crate and npm names are not yet reserved.\n\nThis table is the honest state as of the last commit. If it disagrees with something else in this repository, this table is what was checked — and the disagreement is a defect worth reporting, because a status document that is trusted and stale is worse than one nobody reads.\n\n`spec/`\n\nis normative and is the source of truth for every implementation, including ours:\n\n| File | What it is |\n|---|---|\n`spec/handoff-protocol-v0.1.md` |\nThe normative protocol, using RFC 2119 keywords |\n`spec/openapi.yaml` |\nThe wire contract, and the source the typed SDKs are generated from |\n`spec/schemas/*.schema.json` |\nRequest, receipt, policy, and delivery-attempt schemas |\n`spec/signing.md` |\nThe receipt and callback signature scheme, with test vectors |\n`spec/CHANGELOG.md` |\nWhat changed and when |\n\nThe spec is versioned independently of the implementations, by tag namespace (`spec/v0.1`\n\n,\n`core/v0.3.1`\n\n, `sdk-py/v0.2.0`\n\n, and so on). See [GOVERNANCE.md](/OmegaAgent/handoff/blob/main/GOVERNANCE.md) for the version policy\nand for the process a spec change has to go through, which is stricter than the one for code.\n\n```\nspec/               The normative protocol. Apache-2.0.\ncore/               Rust workspace. Apache-2.0. Intended for crates.io; not yet published.\n  crates/handoff-protocol/        types, state machine, policy evaluation. No I/O.\n  crates/handoff-core/            the engine and the port traits a deployment implements\n  crates/handoff-store-postgres/  reference store and its own migration set\n  crates/handoff-adapters/        delivery channels, feature-gated per channel\n  crates/handoff-server/          the reference server. Binary: handoffd\n  crates/handoff-conformance/     the suite runner. Takes any base URL.\nconformance/        Declarative cases. The governance instrument, not a test helper.\nsdk/python/         handoff-human. MIT.\nsdk/ts/             @handoffproto/sdk. MIT. Zero runtime dependencies.\nui/responder/       PLANNED, not present. A standalone page for the person answering. Apache-2.0.\nexamples/           Worked examples, including the original hackathon build.\ndocs/               Documentation source.\n```\n\nSelf-hosting is the point rather than a concession, so it is worth being precise about what it does and does not get you.\n\n**The shape today:** point `handoffd`\n\nat a Postgres database, give it a configuration file naming the\npeople it can reach and the channels it may use, and run it. It has\nno dependency on any hosted service, no phone-home, no licence key, and no disabled feature waiting\nto be switched on. `CONTRIBUTING.md`\n\nmakes a dormant gate in this repository a mergeable-blocking\ndefect rather than a matter of taste.\n\n**What a self-hosted deployment genuinely guarantees:** correctness of the state machine;\nexactly-one-effect semantics; waits that survive a process restart; a complete local audit trail;\nfull data export; and no runtime dependency on anyone else being alive, solvent, or interested.\n\n**What it structurally cannot guarantee**, stated here rather than discovered later:\n\n**Independent attestation.** A receipt signed with a key you control is adequate for internal control and worthless as evidence*against*you. Only a party who is not the operator can attest to what an operator's system recorded. That is the definition of a third party, not a feature we are withholding.**Deliverability.** See above. A fresh deployment starts at zero reputation on every channel.**Cross-tenant signals.**\"This number has been paged 400 times today by twelve different senders\" is not computable by one deployment that cannot see the others.**Retention as a promise.** Your audit trail is exactly as durable as your backups. A promise needs a promisor.\n\nMeanwhile you can read the spec and implement it yourself. That is a supported outcome, and the conformance suite exists so you can prove you got it right without asking us.\n\nSome of the product around Handoff is commercial. The boundary is drawn by a published test rather than by convenience:\n\nOpen everything required to define, run, and independently verify a handoff on a single tenant's own machine. Keep closed only what derives its value from a third party operating it: shared infrastructure, cross-tenant knowledge, and promises that outlive the customer's own process.\n\nIn practice almost everything is open. The closed surface reduces to a delivery fleet, the\ncross-tenant view, third-party attestation, and one company's own billing and organization model,\nnone of which is protocol. Three clauses bind the maintainer and are written into\n[GOVERNANCE.md](/OmegaAgent/handoff/blob/main/GOVERNANCE.md): no crippleware, the receipt verifier is open unconditionally, and\nexport is open. If you think a change violates one, cite the clause in the pull request; it has to be\nanswered in public.\n\nThe mechanism that keeps this from becoming a slogan is the conformance suite. A hosted service that cannot pass the open suite has a red build, which turns \"we did not quietly fork the core\" from an intention into a check anyone can rerun.\n\n| Subtree | Licence |\n|---|---|\n`spec/` , `core/` , `conformance/` , `ui/` , `docs/` , repository default |\nApache-2.0 (\n|\n`sdk/**` |\nMIT (\n`LICENSE` files) |\n`examples/night-hack/` |\nMIT, unchanged from its original release |\n\nApache-2.0 on the spec and the implementation because its §3 grants patent rights expressly and terminates them on patent litigation against the project. MIT on the SDKs because a thin client gets vendored into everything, including projects whose licences make Apache-2.0 awkward, and its patent exposure is nil.\n\nThe Python SDK was first published under MIT, `Copyright (c) 2026 Noureddin Bakir`\n\n. That grant stands\nand is not rewritten here. Trademark conditions live in [TRADEMARKS.md](/OmegaAgent/handoff/blob/main/TRADEMARKS.md) and never in\nthe licence text.\n\nRead [CONTRIBUTING.md](/OmegaAgent/handoff/blob/main/CONTRIBUTING.md) first. The short version:\n\n**Sign off your commits**(`git commit -s`\n\n). We use the Developer Certificate of Origin.**There is no CLA and there will not be one**, because the only thing a CLA would buy beyond what Apache-2.0 §5 already grants is the option to close this later.** A**that fails before it and passes after, or two independent implementations.`spec/`\n\nchange needs a conformance case**A core behaviour change without a conformance case is not merged.**\n\nMost wanted: delivery adapters, SDK ports to other languages, conformance cases, and corrections to ambiguous spec prose. An ambiguity in a normative document is a real defect.\n\nSecurity issues go to the private channel in [SECURITY.md](/OmegaAgent/handoff/blob/main/SECURITY.md), never a public issue. Note\nthat in this protocol a request identifier can itself be a capability, so treat one like a\ncredential.\n\nHandoff started as a four-hour build at founders.inc Night Hack on 2026-07-24. That build is\npreserved under [ examples/night-hack/](/OmegaAgent/handoff/blob/main/examples/night-hack) with a README describing what it is\nand, more usefully, what it is not.\n\nIt is kept because it is the evidence. It also demonstrated the failure the protocol exists to prevent: before it, \"the human is finished\" was inferred from a page URL or title changing, which silently misses a wall cleared in place. A person ticks a verification checkbox, nothing about the page identity changes, and the agent waits until its deadline for an obstacle that is already gone. The fix generalizes into the rule stated at the top of this file: a human action is recorded, never detected.\n\n[DISCLOSURE.md](/OmegaAgent/handoff/blob/main/DISCLOSURE.md) is that build's honest accounting of what existed beforehand, what was\nmade during the event, and what was measured rather than asserted. It is kept at the root of this\nrepository on purpose. The standard it sets applies to everything here: say what was checked, say how\nit was checked, and say plainly what was not.", "url": "https://wpnews.pro/news/show-hn-handoff-is-await-human-for-ai-agents", "canonical_source": "https://github.com/OmegaAgent/handoff", "published_at": "2026-08-02 12:20:56+00:00", "updated_at": "2026-08-02 12:52:42.878155+00:00", "lang": "en", "topics": ["ai-agents", "ai-infrastructure", "developer-tools"], "entities": ["Handoff", "Fly.io", "handoffd", "handoff-human", "@handoffproto/sdk"], "alternates": {"html": "https://wpnews.pro/news/show-hn-handoff-is-await-human-for-ai-agents", "markdown": "https://wpnews.pro/news/show-hn-handoff-is-await-human-for-ai-agents.md", "text": "https://wpnews.pro/news/show-hn-handoff-is-await-human-for-ai-agents.txt", "jsonld": "https://wpnews.pro/news/show-hn-handoff-is-await-human-for-ai-agents.jsonld"}}