Skip to Content
OperationsUncertain Outcomes

Uncertain Outcomes

When a call that changes something fails, its outcome tells you whether you can try again. unknown is the one that needs care.

unknown happens when the agent cannot confirm the result: a database commit that lost its connection, a timeout after an HTTP request was sent, a file save that failed halfway, code that failed after writing something, or an agent that disconnected mid-call. The error code alone does not tell you; EXECUTION_TIMEOUT can mean either not_started or unknown.

Onprest never retries a call by itself, and you should not retry an unknown call automatically either. Repeating it can create a second order or a second payment. Instead, look at the real state, then decide.

Check before you retry

Plan for this when you design a capability that changes data: define a separate read capability that can confirm the result.

  • Database insert: have the caller choose a unique business ID (such as external_request_id) before inserting, and read it back by that ID. Compare all the important fields, not just the ID.
  • Database update: read the record and compare the values you intended to set. If other writers may change it, include a version column or similar so you can tell your change from theirs.
  • Database delete: check whether the record still exists. If you need to prove which request deleted it, use an audit record.
  • HTTP API: ask the upstream system, through its own read endpoint or an idempotency key it supports.
  • File save: check whether the file exists in the target folder and compare its size or hash. Completed files are never removed by a failed call.
  • Code: use whatever the code changed: a file, a record, or an upstream API.

A current value only shows the current state; it does not prove that this particular request made the change. Decide what evidence your business process needs before exposing the capability.

Example: confirming a database insert

The order example  defines an INSERT capability and a matching read capability for PostgreSQL, MySQL, SQL Server, and Oracle. After a lost response, it reads the order by its external_request_id and compares the ID, product, quantity, and customer:

Read resultDecision
One row, all four fields matchThe order exists as intended. Do not insert again
No rowNot confirmed. The earlier transaction may still be finishing; resolve that before inserting again
A row with different fieldsInvestigate the existing order and other writers
The read fails or is itself unknownRestore read access first. The insert is still unconfirmed

A CONFLICT on the unique key with outcome: rolled_back means this attempt was rolled back because the ID already exists. Read the existing row to find out what it means for your order.

The example README sets up a disposable database for each engine and walks through all four read results with REST and MCP.