Provelyact → prove
Outcome verification for AI agents

Your agent’s word is the weakest evidence there is.

A 200 response proves that a refund object exists. It does not prove that the money moved. Provely reads the provider, not the agent. It holds the word “done” until the provider agrees, and then it signs a receipt that anyone can check offline.

Free for 1,000 verified actions. You get the first verdict in 10 minutes.
Your agent never holds the verifier credentials.

E0the agent says it is doneNEVER ENOUGH
E1the action responseWEAK
E2provider readbackGOOD
E3provider eventGOOD
E4an independent systemSTRONG
E5the outcome in the worldSTRONGEST

Six levels. Provely prefers the evidence that sits furthest from the agent.

workflow verification

A workflow is a promise with several parts.

An agent can finish three parts and drop the fourth. It still reports success, because a successful tool call is the only thing it sees. Provely writes the parts down before the work starts. Then it checks each part against the system that knows.

1 / 5 workflows
coding agent

“Ship the change.”

Write the test. Run the suite. Update the documents. Open the pull request.

  1. Write a test that fails firstE4 · ci

    The test file appears in the diff. The same test fails on the parent commit.

  2. Run the whole suiteE4 · ci

    The run for this commit is complete. No test is skipped and no test is filtered.

  3. Update the documentsE2 · repository

    The documentation files change in the same commit as the code.

  4. Open the pull requestE2 · readback

    The pull request exists. Its head commit is the commit under test.

The agent says “tests pass”. It ran one file. Provely reads the run, not the sentence.

support agent

“Refund and close.”

Refund the customer. Restock the item. Email the confirmation. Close the ticket.

  1. Refund the customer $142E2 + E3 · stripe

    Provely reads the refund by id. The amount, the currency and the payment intent match.

  2. Restock the returned itemE2 · shopify

    Provely reads the inventory level. It correlates by line item, never by a matching count.

  3. Email the confirmationE0 only

    There is no message id and no delivery event. Only the agent claims this step.

  4. Close the support ticketE2 · helpdesk

    Provely reads the status from the helpdesk. An open step blocks the workflow.

Three steps pass. One step has no evidence. The workflow is not done, and Provely says so.

finance agent

“Pay the invoice.”

Send the payment. Mark the invoice. Send the remittance. Pay it only once.

  1. Send the payment of $8,400E4 · bank

    The bank reports the transfer as settled. A created payment object is not enough.

  2. Mark the invoice as paidE2 · ledger

    Provely reads the invoice in the ledger. The paid amount matches the transfer.

  3. Send the remittance adviceE3 · resend

    The mail provider reports the message as delivered, not as accepted.

  4. Never pay the same invoice twiceE4 · bank

    A second settled transfer for this invoice exists. The negative postcondition fails.

Every positive check passed. The supplier was paid twice. CONTRADICTED, so a person decides.

operations agent

“Onboard the new hire.”

Create the account. Order the laptop. Add the payroll record. Send the welcome note.

  1. Create the identity accountE2 · identity

    The account exists in the directory and it holds the correct group.

  2. Order the laptopE3 · supplier

    The supplier confirms the order. A cart is not an order.

  3. Add the payroll recordE2 · payroll

    The payroll system returns the record with the start date of the contract.

  4. Send the welcome noteE5 · outcome

    The invitation is accepted, so the person received it.

Four systems, four owners, one promise. One receipt covers the whole workflow.

revenue agent

“Book the demo.”

Hold the slot. Send the invitation. Move the deal. Log the call.

  1. Hold the calendar slotE2 · calendar

    The event exists on both calendars, and the time matches the customer request.

  2. Send the invitationE5 · outcome

    The mail provider reports delivery. The customer accepted the event.

  3. Move the deal to Demo BookedE2 · crm

    The stage of this deal id changed. A matching deal at the same stage does not count.

  4. Log the call notesE0 only

    There is no note on the deal. The agent reported the step as complete.

A pre-existing deal at the right stage must never verify. Provely correlates by deal id.

The verifier never acts.

Provely returns a directive and nothing else. Your host carries it out: a Claude Code hook, a framework node or the CI gate. A verifier that acts is no longer independent of the action it checks.

Every directive carries the idempotency key of the first attempt and a retry budget. An executor that reaches the budget stops and asks a person.

The directive is also feedback. It names the step that has no evidence and the evidence that the step still needs. Pass it into the next agent turn, and the agent finishes the part that it dropped.

verdictwhat the agent may do nextwhy
PENDINGWait. Do not retry the action.The action can still succeed. A retry refunds twice.
UNVERIFIABLERetry the check. Do not retry the action.The action is not in doubt. The evidence has not arrived.
FAILEDRetry the action with the first idempotency key.The provider refused. The key stops a double effect.
CONTRADICTEDStop. Ask a person.Reality already differs from the promise.
intent compilation

You do not write the contract. You pass the prompt.

Provely compiles the task into a machine-readable contract: the steps, the evidence that proves each step, and the negative postconditions that catch a duplicate. You confirm the contract once. Its hash goes into the receipt, so an auditor can compare the ask with the promise.

What you pass

intent
"Refund order 4471 for $142 and email the customer."
context
{ order_id: "4471", customer: "cus_8k2Rv1LmQ9xT" }
tools
[stripe.refunds, shopify.inventory, resend.emails]

What the compiler returns

  1. stripe.refund.succeededE2 + E3

    Read the refund by id, then wait for refund.updated. Correlate by refund id and payment intent. Amount 14200 usd.

  2. shopify.inventory.adjustedE2

    Read the inventory level back. Correlate by line item, never by a matching count.

  3. resend.email.deliveredE3

    Wait for the delivery event. Accepted and sent are different promises.

  4. negative postconditionduplicate

    No second settled refund exists for this payment intent.

  5. REQUIRES_REVIEWyou confirm

    “the customer” must resolve to one address. Confirm it before the run.

Provely never drops a part of the task in silence. A part that no contract can check is marked REQUIRES_REVIEW, and it says so on the confirmation screen.

verify.ts
// Three lines. Provely compiles the rest.
const op = await provely.begin({ intent: task.prompt, context })

await agent.run(task)

const v = await op.verify()
order.refund.completed.yaml
contract: order.refund.completed     # compiled from the intent
subject:  { order_id: "4471" }
steps:
  - stripe.refund.succeeded          # E2 readback + E3 event
    correlate: [refund_id, payment_intent]
    amount:    14200 usd
  - shopify.inventory.adjusted       # E2 readback, by line item
  - resend.email.delivered           # E3 delivery event
negative:
  - no second settled refund for this payment intent
review:
  - "the customer" resolves to one address
execute.ts
let v = await op.verify()

// PENDING: wait. Never run the action again.
while (v.verdict === "PENDING" && v.retry.remaining > 0) {
  await sleep(v.retry.after_ms)
  v = await op.verify()
}

// A step with no evidence: hand the reason back to the agent.
// v.feedback names the step and the evidence it still needs.
while (v.verdict === "UNVERIFIABLE" && v.retry.remaining > 0) {
  await agent.run(task, { feedback: v.feedback })
  v = await op.verify()
}

// FAILED: the provider refused. The first key stops a double effect.
if (v.verdict === "FAILED") {
  await stripe.refunds.create(input, { idempotencyKey: op.idempotency_key })
  v = await op.verify()
}

// CONTRADICTED: reality already differs. A person decides.
if (v.verdict === "CONTRADICTED") await escalate(v)
why an acknowledgement is not an outcome

Five states. One state moves the money.

This is one operation at one vendor. Each state returns a refund object and HTTP 200. From the response they look the same.

pendingThe bank holds the refund in a queue. No money leaves the account.NO MONEY
requires_actionA person outside your system must act first.NO MONEY
failedThe bank refused the refund. The object still reads 200.NO MONEY
canceledSomeone withdrew the refund before settlement. The customer waits.NO MONEY
succeededThe money moved. Only this state earns the word “done”.MONEY MOVED
the integration compiler

One verifier. Hundreds of vendors.

Each vendor puts the line between an acknowledgement and an outcome in a different place. You never write that logic. The compiler reads the vendor’s schema, documents, events and sandbox behaviour, and it produces one signed skill. A new vendor is a command, not a project.

$provely skill generate stripe$provely skill generate --openapi ./vendor.yaml
  1. 1

    Ingest

    Read the OpenAPI or GraphQL schema, the reference documents, the event catalogue and the SDK types.

  2. 2

    Classify

    Mark every operation that changes the world. Infer the lifecycle of each resource it touches.

  3. 3

    Plan the evidence

    Find the readback, the event and the independent system that prove the real outcome.

  4. 4

    Synthesise

    Write the completion contracts. Add the negative postconditions that catch duplicates.

  5. 5

    Test

    Generate the conformance cases. Run them against the vendor sandbox.

  6. 6

    Certify and sign

    Score six dimensions. Apply the hard caps. Sign the skill and publish it.

Every skill carries a score across six dimensions. Generated draft at 50, Verified at 75, Official at 90. An undocumented semantic caps the score at 49 and is marked REQUIRES_REVIEW. One known false VERIFIED rejects the skill. The compiler never guesses.

The first three skills

The same pipeline produced all three. It produces the next hundred the same way.

Resend

Accepted, sent and delivered are three different promises.

accepted
bounced
delivered
sent

Webhooks arrive at least once and out of order. Arrival order is not the truth.

Shopify Admin API

A Refund record does not prove that money left the merchant.

created
financially_completed

Provely verifies “the refund exists” and “the refund settled” as two separate promises.

Stripe

A refund object records a request. It does not record a transfer.

created
succeeded

A retry without the first idempotency key makes a second refund. Every positive check still passes.

questions developers ask

Does a successful call mean the work is done?

Every answer below comes from a signed skill manifest. Each one names its source and the date we read it. The site writes no provider claim by hand.

Does a Resend send call mean the email was delivered?

No. The email holds one of 12 states. delivered, opened and clicked are terminal success. The Resend skill proves accepted, bounced, delivered, sent as separate promises, at certification community. Source: resend.openapi, retrieved 2026-09-05.

Does a Shopify Refund object mean money moved?

No. The order_transaction holds one of 6 states, and only SUCCESS is terminal success. The Shopify Admin API skill proves created, financially_completed as separate promises, at certification community. Source: shopify.graphql, retrieved 2026-09-05.

Does a successful Stripe refund call mean the customer got the money?

No. The refund holds one of 5 states, and only succeeded is terminal success. The Stripe skill proves created, succeeded as separate promises, at certification community. Source: stripe.openapi, retrieved 2026-09-05.

start

See what your agents already call done.

The scanner reads your codebase. It finds each place where a 200 response becomes success. You need no account, and no code leaves your machine.

Contracts are versioned, hashed and immutable. Receipts use Ed25519 and verify offline.
Verifier credentials are read only.