# How does Provely decide that an agent action is done?

> Provely keeps intent, action, acknowledgement, outcome, and completion apart, runs one frozen state machine, and ranks evidence from E0 to E5.

Canonical: https://provely.sh/how-it-works  
Last reviewed: 2026-09-05  

**Provely reads the real system after the agent acts, evaluates a versioned completion contract against that evidence, and returns one of five verdicts. The agent never decides.**

The agent keeps its write credentials and makes the same API call. A separate verifier reads the provider with read-only credentials and signs a receipt. An agent report is E0, and E0 is never sufficient.

## Where does the contract come from?

You pass the agent prompt, the context and the tools. Provely compiles the completion contract, and you confirm it before it runs. You never write the contract by hand.

A language model may propose the contract. The contract decides completion, and a language model judgement is never completion evidence. A part of the task that no contract can check is marked REQUIRES_REVIEW. Read [intent compilation](/docs/intent-compilation).

## What are the five concepts that most agent stacks collapse?

Provely keeps five concepts apart in the data model, the API, and the interface.

*Figure: The five concepts, on the Stripe refund example.*

- Intent: what the user asked for.
- Action: what the agent attempted.
- Acknowledgement: what the provider returned at once.
- Outcome: the observable resulting state.
- Completion: the outcome satisfies the contract. Only this earns VERIFIED.

| Concept | Question it answers | Stripe refund example |
| --- | --- | --- |
| [Intent](/glossary/intent) | What did the user ask for? | Refund USD 142.00 to customer cus_8k2. |
| [Action](/glossary/action) | What did the agent attempt? | `POST /v1/refunds` with an idempotency key. |
| [Acknowledgement](/glossary/acknowledgement) | What did the provider return at once? | HTTP 200 and a refund object with `status: pending`. |
| [Outcome](/glossary/outcome) | What state does the provider hold now? | `status: succeeded` on a readback. |
| [Completion](/glossary/completion) | Does the outcome satisfy the contract? | Amount, charge, and status match. No duplicate. VERIFIED. |

## Which states can an operation be in?

**An operation moves through one frozen state machine: CREATED, ACTION_STARTED, ACTION_ACCEPTED, OBSERVING, PENDING, and then one terminal state. The terminal states are VERIFIED, CONTRADICTED, FAILED, UNVERIFIABLE, EXPIRED, and HUMAN_REVIEW.**

*Figure: The operation state machine. No plugin can change it.*

- CREATED moves to ACTION_STARTED when the agent begins the action.
- ACTION_STARTED moves to ACTION_ACCEPTED when the provider acknowledges.
- ACTION_ACCEPTED moves to OBSERVING when the verifier starts to read evidence.
- OBSERVING moves to PENDING while the evidence is not sufficient.
- PENDING moves to VERIFIED, CONTRADICTED, FAILED, UNVERIFIABLE, EXPIRED, or HUMAN_REVIEW.

| Verdict | Meaning | Example |
| --- | --- | --- |
| VERIFIED | Every positive postcondition holds and no negative one holds. | The refund shows `succeeded` for the right amount and charge. |
| [PENDING](/glossary/pending) | The operation can still make progress. | The refund shows `pending` or `requires_action`. |
| [CONTRADICTED](/glossary/contradicted) | The evidence shows an outcome the intent does not allow. | Two refunds exist for one operation. |
| FAILED | The provider reports a terminal failure. | The refund shows `failed` or `canceled`. |
| [UNVERIFIABLE](/glossary/unverifiable) | The evidence never became sufficient. | The readback stayed unavailable until the deadline. |
| HUMAN_REVIEW | A person must decide. | The contract escalates a timeout to a person. |

## What are the frozen safety rules?

1. **A false VERIFIED is the highest-severity defect.** When evidence is not sufficient, the answer is UNVERIFIABLE.
2. **Progress is not failure.** While an operation can still complete, the answer is PENDING, never FAILED.
3. **An agent assertion is never sufficient.** E0 cannot support VERIFIED, alone or combined.
4. **Acknowledgement is never terminal success.** HTTP 200 and an object id prove only that a request was accepted.
5. **Evidence must correlate with the exact operation.** A matching state that already existed must not verify.
6. **The verifier reads with read-only credentials** where the provider permits it. The agent never holds them.

> A pre-existing refund for the same amount is the classic false proof. A search by amount finds it. A correlation by refund id and payment intent does not.

## What does a false completion look like?

**A Shopify refund shows it. The mutation succeeds, the Refund object exists, and the webhook fires. The money has not moved: the order transaction is still PENDING. Two promises, two contracts.**

*Figure: A Refund object exists while the order transaction is still pending, so the money did not move.*

- The refundCreate mutation succeeds.
- The Refund object exists and the refunds/create webhook fires. Neither proves that money moved.
- The OrderTransaction still shows PENDING.
- Money moved is not yet true. The financially_completed contract proves it. The created contract does not.

The [Shopify page](/verify/shopify) states the contracts and the evidence that separate the two promises.

## Why is not all evidence equal?

**Provely ranks evidence by its independence from the action path. E0 is the agent word. E5 is an external outcome, such as a bank credit. The runtime prefers the more independent level.**

*Figure: The evidence hierarchy. E0 is never sufficient.*

- E0 agent assertion: never sufficient.
- E1 action response: proves acknowledgement, rarely completion.
- E2 provider readback: deterministic state, subject to stale reads.
- E3 provider event: strong timing, needs deduplication and ordering.
- E4 independent system: the provider plus your own ledger.
- E5 external outcome: a bank, a carrier, or a recipient acknowledgement.

## What happens between the action and the answer?

*Figure: One operation, from begin to receipt.*

- begin: the agent opens an operation against a contract and gets an idempotency key.
- act: the agent makes the provider call with that key.
- action_result: the agent submits the provider acknowledgement.
- verify: the runtime reads the provider and evaluates the contract.
- receipt: the runtime signs the verdict with Ed25519.

### Can a plugin change what VERIFIED means?

No. A plugin adds an evidence channel or an operator. The state machine, the verdicts, and the safety rules are frozen.

### What does the agent say while the verdict is PENDING?

It says: "The action is accepted but not yet verified. Operation: <id>." Any caller can check that id later.

## Read next

- [Read what a completion contract contains](https://provely.sh/contracts)
- [Read what a signed receipt proves](https://provely.sh/receipts)
- [See the whole loop in code](https://provely.sh/docs/quick-start)
- [Read the false-completion benchmark](https://provely.sh/benchmark)
- [Read the Stripe verification page](https://provely.sh/verify/stripe)
- [Read the evidence level definition](https://provely.sh/glossary/evidence-level)
