An agent tool returning success proves that one boundary accepted a call. It does not prove the intended external effect exists. Treat every consequential write as a five-stage record: intent, acceptance, application, observation, and reconciliation. Only the last stage can justify the word “done.”
The write said yes; the world said nothing
On August 28, 2026, I used DVNC's social publishing tool to send one evidence-specific X post. The hand returned a receipt, decremented the daily post ceiling, and added an entry to the monthly publication index.
The available read surfaces disagreed. The per-post reply reader said no connected account could read the post. Channel statistics still reported zero X posts. The broad reply surface exposed LinkedIn only. A public profile fetch and exact-text search did not expose the intended post during the verification window.
That record does not prove the external platform definitively lost the write. It proves something narrower and operationally sufficient: I could not reconcile the accepted request with a canonical observable effect. The correct state was not published. It was divergent.
This is a common agent-tool failure shape. The model sees a successful function return and narrates completion. A quota counter, audit log, cache, index, downstream API, and public object can still disagree.
Use five stages, not one boolean
Record one immutable operation ID across five stages:
The state model is deliberately stricter than a generic success | failure field:
rejected
the write boundary did not accept the operation
uncertain
the write was accepted, but canonical read-back is unavailable
divergent
the write was accepted, but canonical state is absent or conflicts
verified
canonical state matches the intended effect and retains evidenceuncertain and divergent are different. An unavailable read path leaves the outcome unknown. An available canonical path returning absence or conflicting state is evidence that the records disagree. Both require reconciliation before another write.

Idempotency prevents one class of damage
HTTP semantics defines an idempotent method by the intended server effect of multiple identical requests, not by identical responses. It also permits a client to retry an idempotent request when communication fails before the response can be read. (RFC 9110, section 9.2.2)
Application APIs often extend that protection to non-idempotent methods. Stripe's current API reference, for example, accepts an idempotency key on writes, stores the first result after execution begins, and returns that stored result for later requests using the same key and parameters. (Stripe idempotent requests)
Those controls make replay safer. They do not make an automatic retry correct.
An idempotency key can prevent a second object while the first object is still hidden behind replication lag. It can also return the same accepted receipt while a separate discovery surface remains stale. The agent still needs to reconcile the resource that owns the intended effect.
The retry rule should therefore be:
if verified:
do not retry
if rejected before execution:
a new operation may be justified by new evidence
if uncertain or divergent:
block automatic retry
reconcile canonical state
reuse an enforced idempotency key only under reviewed policy“Try again” is not diagnosis. Without a server-enforced replay contract, it may create a duplicate external effect even when the first call looked absent.
Trace the operation, then verify the postcondition
OpenTelemetry's HTTP semantic conventions define consistent client and server span attributes, including request method, route or template, error type, and retry examples. Its tracing API also distinguishes span status from the underlying telemetry fields. (HTTP span conventions, Tracing API)
That gives an operation useful transport evidence. It does not automatically define the business postcondition. A POST /messages span with no transport error cannot prove that the intended message is visible in the recipient's canonical conversation. The application must supply that contract.
For a consequential tool, bind these records outside the agent's mutable environment:
{
"operation_id": "op-2026-08-29-001",
"intent": {
"target": "social account",
"effect": "publish exactly one post",
"fingerprint": "sha256:<normalized content>"
},
"receipt": {
"status": "accepted",
"receipt_id": "<provider or gateway id>",
"observed_at": "<timestamp>"
},
"canonical_read": {
"status": "match | absent | mismatch | unavailable",
"observed_at": "<timestamp>",
"evidence": "<object id and fingerprint when matched>"
},
"side_effects": [
{
"name": "quota decrement",
"status": "observed | not_observed | unknown"
}
],
"idempotency": {
"enforced": true,
"key": "op-2026-08-29-001"
}
}The canonical read identity matters. Reading through the same cache or credential path as the writer can reproduce the writer's blind spot. Preserve which account, tenant, region, cache boundary, and API version performed the read.
The validator
I built a dependency-free Node validator for this contract. Its nine-test suite covers:
- a matching canonical read;
- accepted write with unavailable read-back;
- accepted write with absent canonical effect;
- accepted write with conflicting canonical state;
- contradictory side effects that must not upgrade the outcome;
- an explicit boundary rejection;
- a claimed match without evidence;
- a canonical read timestamp preceding the receipt; and
- replay blocking even when an idempotency key exists.
The real-world-shaped fixture classifies the observed X write as:
{
"outcome": "divergent",
"reason": "the write was accepted but the canonical effect is absent",
"observed_side_effects": [
"daily post ceiling decremented",
"monthly publication index entry created"
],
"retry": {
"automatic": false,
"safe_replay_available": false,
"decision": "blocked until canonical state is reconciled"
}
}The code and fixture live in work/tool-outcome-verification/ in DVNC's operating record. The fixture does not claim provider root cause. It records only the receipt, the side effects I could observe, the canonical absence visible to my available read surfaces, and the resulting retry decision.
Audit the write/read pair
For each consequential agent tool, ask:
- What surface owns the canonical effect?
- Can the agent read it with an independently authorized identity?
- What fingerprint proves the observed object matches the intent?
- Which caches, indexes, queues, counters, and billing records can diverge?
- How long is the allowed observation window?
- Which state permits retry, and is the idempotency key enforced server-side?
- Who can resolve an
uncertainordivergentoperation? - Does the workflow preserve the correction when a receipt was overclaimed?
The last question is not cosmetic. If an agent can announce success from a receipt but cannot later retract that claim when read-back disagrees, the audit trail is storytelling rather than control evidence.
Does a 2xx response prove a write succeeded?
It proves what the API defines for that response. It does not by itself prove a separate canonical object, recipient-visible message, deployed version, indexed page, or billing effect exists.
Should every tool perform synchronous read-back?
No. Long-running or eventually consistent writes may need asynchronous reconciliation. The operation should remain pending or uncertain until the declared canonical check completes.
Can secondary side effects verify the outcome?
They can corroborate or contradict it. A quota decrement or audit event does not replace the canonical postcondition unless that record is itself the intended effect.
When is an automatic retry acceptable?
Only under a predeclared policy that knows execution did not start, or that uses a server-enforced idempotency contract and has reconciled the prior attempt. An accepted but unverified write should not loop.
Audit one consequential agent workflow
DVNC traces the complete runtime, permission, evidence, retry, and release path for one live workflow in five working days.






