A person signs off a completion contract before the action runs. It states what "done" means for one action: the outcome, the evidence that proves it, and the results that must never appear. The runtime checks the provider against it.

A contract is immutable, versioned, and hashable, so nobody moves the goalposts after a run. Every receipt records the contract id, version, and hash. A contract is data. Code interprets it and holds no provider rule, so a new service ships without a runtime change.

Where does a contract come from?

“Refund order 4471 for $142and email the customer.”context, toolsyou pass thiscompilestepstripe.refund.succeededevidenceE2 readback + E3 refund.updatedcorrelaterefund_id, payment_intentnegativeno second settled refundREQUIRES_REVIEW“the customer” resolves to one addresswhat done meanshow the runtime proves ityou confirm this once
You pass the task. The compiler returns the contract you confirm.
In words
  • The prompt and the context go into the compiler.
  • The compiler returns the steps, the evidence for each step, and the postconditions.
  • A part that no contract can check is marked REQUIRES_REVIEW.
  • You confirm the contract before it verifies anything.

Provely compiles it from the task. You pass the agent prompt, the context and the tools. The compiler returns the steps, the evidence, the correlation keys and the negative postconditions. You confirm the result before it runs.

A part of the task that no contract can check is marked REQUIRES_REVIEW, and it is never dropped in silence. Read intent compilation.

A contract states the promise. The four other concepts sit around it.
In words
  • Intent: what the user asked for.
  • Action: what the agent attempted.
  • Acknowledgement: what the provider returned.
  • Outcome: the observable state in the provider.
  • Completion: the outcome satisfies the contract.

What does a contract contain?

Twelve members. Four of them decide a verdict: the completion conditions, the negative conditions, the correlation keys, and the evidence policy. The rest bound how long the runtime waits and which provider versions the semantics hold for.

Explain: every member, with a Stripe example
MemberPurposeExample
intentWhat the user asked for, and the input schema.Refund the charge to the customer.
subjectThe real-world thing the contract talks about.stripe.refund identified by $action.result.id.
actionThe effect class and the idempotency rule.money.refund with Idempotency-Key: $operation.id.
correlationHow evidence ties to this exact operation.Match the refund id from the action response.
evidence_policyThe channels and the minimum evidence level.Readback at E2, event at E3, independent channel required.
completion.all_ofThe positive postconditions. Every one must hold.status eq succeeded, amount eq $input.amount_cents.
negative_conditions.any_ofThe false-success blockers. One gives CONTRADICTED.More than one refund for this operation.
verdict_mapObserved state to verdict, before completion.pending gives PENDING. failed gives FAILED.
timingPoll interval, backoff, deadline, stale-read window.Poll on an interval, and stop at a deadline.
on_timeoutThe verdict when the deadline passes. VERIFIED is never allowed.UNVERIFIABLE, escalated to a person.
valid_forThe provider API versions the semantics are proven for.>=2025-03-31.
overlaysVersion differences as a merge patch. One contract, no copies.The 2026-08-26 overlay adds requires_action.

What does a refund contract look like?

acme.refund.completed, a fictional provider
schema_version: '1.0.0'
id: acme.refund.completed
version: 1.0.0
service: acme
completion_level: completed
title: Acme Payments returned the money to the buyer.
intent:
  statement: Return the payment to the buyer.
subject:
  type: acme.refund
  identity: { refund_ref: $action.result.ref }
action:
  canonical_effect: money.refund
  idempotency: { strategy: idempotency_key, key: $operation.id, header: Acme-Request-Key }
correlation:
  strategies:
    - { name: resource_id, assurance: strong, required: true,
        keys: [{ name: refund_ref, source: $action.result.ref }] }
evidence_policy:
  minimum_evidence_level: E2
  require_independent_channel: true
  channels:
    - { name: ledger_lookup, evidence_level: E2, independence: provider_readback,
        verifier: { name: http, version: '^1' } }
completion:
  all_of:
    - { id: refund_settled, path: $observed.ledger_lookup.settlement,
        operator: eq, expected: settled, evidence: [ledger_lookup] }
    - { id: refund_value_matches, path: $observed.ledger_lookup.value_minor,
        operator: eq, expected: $input.value_minor, evidence: [ledger_lookup] }
negative_conditions:
  any_of:
    - { id: second_refund_seen, class: duplicate_side_effect, reason_code: duplicate_refund,
        path: $observed.ledger_lookup.refunds_for_operation, operator: gt, expected: 1,
        evidence: [ledger_lookup] }
timing: { poll_interval_ms: 30000, timeout_ms: 172800000 }
on_timeout: { result: UNVERIFIABLE, reason_code: evidence_unavailable_before_timeout,
              escalate_to_human_review: true }
valid_for: { provider_api_versions: ['>=2026-01-01'] }

Acme Payments is a fictional provider. The example shows the format, and no signed package holds it. The Stripe refund contract page states what the signed Stripe contract promises.

Why are completion levels separate contracts?

Because a service makes more than one promise. Resend accepts, sends, and delivers an email as three events. Each level is one contract, so an agent cannot upgrade the promise it made.

  • resend.email.accepted, resend.email.sent, resend.email.delivered, and resend.email.bounced are four contracts.
  • shopify.refund.created and shopify.refund.financially_completed are two contracts, because a Refund object does not prove money moved.
  • stripe.refund.created and stripe.refund.succeeded are two contracts, because pending is not succeeded.

Which rules does the schema enforce?

The loader refuses a contract that could produce a false VERIFIED. Seven rules do that work, and each one fails the document when it loads, not during a run.

Explain: the seven rules the loader enforces
  • Every condition names an evidence channel that the contract declares.
  • A channel cannot claim a level above its path. A reading of the action response is E1 at most.
  • A weak correlation strategy states a time window. An Official contract needs one strong strategy.
  • A PENDING result on timeout must escalate to a person. An operation always ends.
  • verdict_map and on_timeout can never give VERIFIED. Only the completion block can.
  • An overlay adds a condition. It cannot remove one, change the identity, or weaken the evidence policy.
  • The document rejects an unknown member with a clear error.

The published schema is completion-contract.schema.json, JSON Schema draft 2020-12, in the @provely/core package.

Source: Provely core schemas · retrieved 2026-09-05

How does composition work?

A contract can use other contracts as sub-contracts. The runtime combines their verdicts with frozen precedence rules. One CONTRADICTED component contradicts the whole. One PENDING component keeps the whole PENDING. VERIFIED needs every component VERIFIED.

Can I write a contract by hand?

Yes. The schema and the loader are public. The Integration Compiler writes the Official contracts, because it records provenance and runs the conformance matrix.