How must an instance preserve causal links between actions and outcomes?
**Date of Record:** 2026 October 25 **Scope:** Applies when an autonomous instance, multi-step tool runner, or asynchronous execution pipeline dispatches state-mutating actions and evaluates environment observations to attribute effects to specific actions. Does not apply to pure stateless mathematical evaluation or single-turn read-only lookups where no intermediate environment mutation occurs.
Core Distinction
Temporal proximity in an execution log does not establish causation. A critical architectural failure occurs when an instance attributes an observed outcome to the most recently dispatched action based solely on sequential arrival order (`post hoc ergo propter hoc`), corrupting root-cause diagnostics, reinforcement attribution, and compensating rollback decisions.
What Was Observed
In asynchronous, concurrent, or delayed-feedback environments where multiple tool calls and background processes interact, relying on chronological log order rather than explicit causal provenance produces four distinct failure modes:
- **Delayed Side-Effect Misattribution:** A slow mutation from Action $A$ completes immediately after Action $B$ is dispatched; the instance falsely concludes that Action $B$ caused the state transition or error emitted by Action $A$.
- **External Interference Conflation:** Concurrent human edits, cron jobs, or external worker mutations alter target state mid-sequence, and the instance records the external side effect as the deterministic result of its own tool invocation.
- **Orphaned Rollback Execution:** When an outcome fails validation, lack of a strict parent-action correlation ID causes the instance to revert the wrong step or replay a non-causal action.
- **Superstitious Residual Formation:** Persisting a concluded record that pairs an action with an unrelated coincidental outcome encodes false operational laws into external memory.
Recorded Elements
- **Cryptographic Action-Outcome Binding:** Generating an explicit `action_id` and pre-execution state fingerprint (`pre_state_sha256`) prior to dispatch, requiring the outcome envelope to return the bound correlation token.
- **Vector Clock / Lamport Logical Timestamps:** Tracking causal lineage across asynchronous boundaries rather than relying on wall-clock timestamps.
- **Counterfactual Isolation Check:** Verifying that the observed state delta touches only the resource scope targeted by the dispatched action and that no unrecorded intermediate version bump occurred.
Condition of Validity
* **Applies when:** Binding an observed environment response, error trace, or state delta to a prior action before updating internal belief state, triggering rollbacks, or writing an operational residual. * **Does not apply when:** Evaluating pure in-memory functions with zero external I/O or deterministic local syntax trees.
Decision Boundary
- **Does the outcome envelope carry an explicit correlation token (`action_id`) matching the dispatched action?** If the response lacks a verifiable correlation binding in an asynchronous channel, reject direct causal attribution and quarantine the event.
- **Does the target resource's pre-mutation version or state hash match the snapshot recorded immediately before the action was dispatched?** If an intermediate version jump occurred (`observed_parent_hash != expected_pre_state_hash`), flag external interference and refuse to attribute the full delta to the instance's action.
- **Does the observed side effect fall within the declared causal scope of the action?** If an uncoupled subsystem mutates simultaneously, decouple the coincidental event from the action's verified outcome record.
Operational Effect
- **Elimination of Post-Hoc Fallacy:** Every recorded outcome is cryptographically and logically pinned to the exact action and pre-state that produced it.
- **Surgical Rollback & Attribution Integrity:** Compensating actions and external memory residuals operate exclusively on verified causal edges, preventing superstitious rule generation and misdirected retries.
from dataclasses import dataclass
from typing import Final, FrozenSet
import hashlib
@dataclass(frozen=True)
class DispatchedActionRecord:
action_id: str
target_resource: str
pre_state_sha256: str
logical_clock: int
declared_scope: FrozenSet[str]
@dataclass(frozen=True)
class ObservedOutcomeEnvelope:
correlation_action_id: str
target_resource: str
observed_parent_sha256: str
post_state_sha256: str
outcome_logical_clock: int
mutated_paths: FrozenSet[str]
class CausalLinkageViolation(Exception):
"""Raised when an observed outcome cannot be causally bound to the dispatched action."""
pass
class CausalProvenanceGate:
def verify_causal_link(
self,
action: DispatchedActionRecord,
outcome: ObservedOutcomeEnvelope,
) -> str:
# 1. Enforce explicit action-to-outcome correlation ID binding
if outcome.correlation_action_id != action.action_id:
raise CausalLinkageViolation(
f"Correlation mismatch: expected {action.action_id}, got {outcome.correlation_action_id}"
)
# 2. Enforce Lamport logical clock monotonicity (effect cannot precede or equal cause)
if outcome.outcome_logical_clock <= action.logical_clock:
raise CausalLinkageViolation(
f"Causal clock inversion: outcome ({outcome.outcome_logical_clock}) <= action ({action.logical_clock})"
)
# 3. Enforce unbroken state lineage (no unrecorded external mutation between dispatch and effect)
if outcome.observed_parent_sha256 != action.pre_state_sha256:
raise CausalLinkageViolation(
"State lineage broken: concurrent external mutation intervened before outcome."
)
# 4. Enforce causal scope containment
if not outcome.mutated_paths.issubset(action.declared_scope):
raise CausalLinkageViolation(
"Out-of-scope side effect detected; refusing direct causal attribution."
)
causal_edge = f"{action.action_id}:{action.pre_state_sha256}->{outcome.post_state_sha256}"
return hashlib.sha256(causal_edge.encode("utf-8")).hexdigest()