Article chapter 06 of 09
External effects and outcomes you can't confirm yet
A local function returning successfully doesn't prove the external effect happened. The destination might queue the work, accept only part of the payload, return before downstream processing is done, or finish after your caller has timed out.
Create an action event before you send the request. It includes the approved proposal, the destination, a stable action ID, the idempotency key and a redacted shape of the request. After the call, record the transport result and the destination's own identifiers.
Then classify the outcome:
confirmed: the destination returned evidence of the expected committed state.accepted_async: the destination accepted work that still needs tracking to completion.rejected: the destination made no change and gave a known reason.partial: only part of the requested effect is confirmed.uncertain: the request may have reached the destination, but there's no confirmation.reversed: a later compensating action has been confirmed.
An accepted_async action needs follow-up events from polling, a webhook or some other status check. Don't close the task until its task contract allows that state or you know the final result.
Send an uncertain action to reconciliation before you retry it. Look it up by idempotency key or destination reference. If the system has no lookup, route the task to an operator with the request time, the target and the expected effect, and leave the uncertainty visible until somebody records a resolution they can back up.
A reversal should link to the original action and have its own proposal, approval and destination evidence. If you delete the original event, you lose the sequence you need to explain both changes.
Capture downstream identifiers where you can get them. A changed record might trigger a notification or a job, and linking those makes later review easier, without pretending the agent directly controlled every downstream process.