Skip to content

Agent Contract (the receipt is the interface)

A run that produces no receipt did not happen. The receipt is the only thing the estate trusts: not the transcript, not the summary, not the agent's own confidence.

Artifacts in this skill: - schemas/factory-receipt.v2.json is the contract. Twelve invariants, all adversarially tested. - scripts/validate_receipt.py runs schema plus the sixteen cross-field gate rules. Exit 0 accepts. - scripts/conformance_test.py proves each invariant rejects a violation and accepts honest work. - references/contract.yaml is the binding rule set to prepend to an agent's system prompt. - references/receipt-design.md explains why each field exists and what it catches. - examples/ holds five validated receipts covering the shapes agents actually produce. They are generated from the conformance test rather than hand-written, so they cannot drift from it: python3 scripts/conformance_test.py --emit-examples.

Before changing anything

python3 scripts/conformance_test.py     # 19 rejections, 5 acceptances, must be clean
python3 scripts/validate_receipt.py examples/01-operate-pass.json

A schema change that does not come with a new rejection test is decoration. Every invariant must prove it rejects something, or it is a comment with extra syntax.

The vocabulary, and why it is small

Verdicts are PASS, FAIL, DEGRADED, UNKNOWN, NOT_APPLICABLE. There is no "success", "done", "complete" or "looks good". The absence of a failing check is UNKNOWN, never PASS. This single restriction removes most agent self-report inflation.

Four status fields exist and their precedence is fixed. verification.overall is the evidence verdict and is the ceiling. result.status reports the requested effect and may never exceed the ceiling, which INV-01 enforces. witness_status is advisory unless witness_required is true, in which case INV-03 caps the verdict. terminal.state is disposition only and says nothing about correctness: a BLOCKED_DURABLY receipt with a FAIL result and one with an UNKNOWN result are both valid and mean different things.

Evidence classification uses the estate vocabulary, not a parallel one: PROVEN_IN_RUNTIME, CURRENT_SOURCE, CANONICAL_POLICY, CURRENT_PRODUCT_DIRECTION, ASPIRATIONAL, HISTORICAL_SUPERSEDED, NOT_ESTABLISHED. It matches the Evidence State table in product-definition, so a receipt and a product definition grade the same claim the same way.

Authority is earned, never configured

OBSERVE detects and reports and changes nothing, which INV-05 enforces by rejecting any receipt that claims OBSERVE alongside a source change, a runtime change or an applied artifact.

ASSIST prepares, tests and opens a reviewable change. A human approves deployment. Expect this to be the default operating mode for a long time.

OPERATE executes an approved remediation class within explicit policy. INV-06 makes the earning mechanical: an OPERATE receipt must carry a non-empty acceptance_ref, a non-empty remediation_class, and verified_history_runs >= 1. Authority is scoped to customer + remediation_class + verified_history + policy + acceptance, never to an account, and a regression in a class revokes that class.

Selling or configuring OPERATE as the starting point converts trust risk, usually the top risk, into the first thing that breaks.

What the receipt catches that a summary never does

changes.ownership_delta makes Net-Negative Ownership checkable per run. NEGATIVE is the goal. POSITIVE forces a human gate through INV-09, so custom-code surface cannot grow as a side effect of an agent being helpful.

work.existing_work_searched and duplicate_work_created enforce curate-before-create at the moment work is created, and INV-08 gates a duplicate rather than letting it quietly land.

factory.private_todo_remaining, polling_used and unsupported_internal_hack_used are honest reporting fields with teeth: gate rules G-05, G-06 and G-07 reject the receipt outright. An agent keeping work in its head instead of Beads fails the gate.

verification.criteria[].falsification_condition requires each criterion to state what would disprove it. Expected versus observed is easy to write after the fact. A falsification condition is not.

economics feeds the recurring model directly: model cost, infrastructure cost, human review minutes and cost, automated actions, human escalations, accepted outcomes, and cost per accepted outcome. estimate_basis: NOT_MEASURED is allowed precisely so unmeasured runs stay visible rather than absent. Human review minutes is the number that answers the capacity question in product-definition/references/pricing-economics.md.

Secrets and authentication

factory.secrets_referenced holds op:// references only, enforced by pattern and by gate rule G-12. A literal value there is a constitution violation, not a style problem.

A 401 or 403 is diagnosed by layer and never assumed to be token expiry or a 1Password failure. Declaring AUTH_BLOCKED requires all nine diagnostic fields (OPERATION, PRINCIPAL, EXISTING_AUTH_PATH, ATTEMPT, AUTHENTICATED, TARGET, TARGET_ROLE, AUTHORIZED, EXACT_DENIAL), which INV-04 enforces. A missing machine identity is reported as MACHINE_IDENTITY_PROVISIONING_GAP and never resolved by falling back to a human credential.

Durability

terminal.durable_transition_established generalizes "work on disk is not done". INV-07 rejects a COMPLETED receipt without it. Scheduled and unattended runs operate against remotes, so a local checkout or worktree is never the system of record.

terminal.receipt_complete is set by the validator, not the agent. Agents emit false. A field where the artifact certifies its own completeness is theatre unless something external stamps it.

Wiring structured output

Force a single tool call rather than asking for JSON in prose.

tools=[{"name": "emit_receipt",
        "description": "Terminal output. Call exactly once, at the end of the run.",
        "input_schema": SCHEMA}]
tool_choice={"type": "tool", "name": "emit_receipt"}

For providers whose strict mode rejects allOf, if, then, contains and minItems, strip the allOf block and rely on scripts/validate_receipt.py for the invariants. The gate is the enforcement point either way, because a model can be persuaded and a validator cannot.

Where this lives

This skill is the authority for the contract. The runnable Gas City pack that imports it is built separately and consumes these artifacts rather than restating them. If the pack and this skill disagree, this skill wins and the pack is corrected, exactly as generated outputs never become authority over the contract that produced them.