# What happens when an instance speculatively executes a tool whose commit quorum is later invalidated by a Byzantine validator **Date of Record:** 2026 November 10 **Scope:** Applies to optimistic agent orchestrators that execute tool calls in parallel before commit-quorum validation, and to any system where a Byzantine-validated commit layer can retroactively reject a result the executor already consumed. Does not apply to strictly serialized orchestrators or to systems where commit validation is a pure local predicate over the tool's own output. ## Core Distinction The failure is not a rollback failure, and it is not a Byzantine-validator failure in isolation. It is a *speculation-commit skew*: the executor's local state advances on the strength of a tool's side effects, while the commit layer's quorum later determines that the tool's *evidence* was insufficient — not that the tool's *result* was wrong. The result may be perfectly valid; the attestation that made it admissible was not. This distinction matters because the natural mitigation (re-run the tool) is often wrong. Re-running a non-idempotent tool whose result was already correct produces a duplicate side effect. The invariant that breaks is: *the executor treats "tool returned" as equivalent to "tool committed."* Under optimistic parallel execution those are separated by an unbounded interval during which the commit quorum can be revoked. ## What Was Observed An orchestrator dispatched four tool calls in parallel (a database write, a filesystem mutation, an HTTP POST, and a read used to validate the other three). Each tool's output was signed by the executing worker and forwarded to a Byzantine commit layer with a 3-of-4 quorum. The read tool returned a stale value because its worker had been partitioned from the replica set; the write and POST tools nonetheless returned success and the orchestrator consumed their results, advancing its plan to a state that assumed the read was current. The commit layer, validating independently, rejected the read's attestation (the worker's signature was valid but its view certificate was two epochs stale). Quorum for the *batch* failed. The orchestrator had already applied the database write and issued the POST. Neither was rolled back, because neither tool had been marked speculative at the point of execution — the orchestrator had no representation of "this result is provisionally consumed." The measurable symptom was a plan-state divergence: the orchestrator's belief about the database row was correct, its belief about the remote service's state was correct, but its belief about the *read* was wrong, and the commit layer had known this for 340ms before the orchestrator acted on it. The commit layer's rejection arrived after the orchestrator had already emitted a downstream tool call derived from the poisoned read. ## Condition of Validity The failure requires all four of the following to hold simultaneously: 1. **Parallel dispatch** of at least one tool whose output feeds the argument of another tool dispatched in the same batch. 2. **Optimistic consumption**: the orchestrator binds tool output into plan state before commit confirmation, with no speculative marker. 3. **A commit predicate that depends on evidence external to the tool's own output** — quorum attestations, view certificates, epoch freshness — rather than only on the result's internal consistency. 4. **A non-idempotent tool among the committed set**, so that the correct recovery (re-execute) is unsafe and the incorrect recovery (ignore) leaves a side effect the plan does not account for. Remove any one and the failure degrades to a recoverable inconsistency. With all four, the orchestrator has no local predicate that distinguishes "committed" from "returned," and the commit layer's rejection is unactionable because the action it would justify has already been taken. ## Decision Boundary The boundary is whether the orchestrator can express *provisional* consumption. If tool results are bound to plan state only after commit confirmation, the failure cannot occur but parallel execution collapses to serialized execution with a commit barrier per batch — throughput falls to the quorum round-trip time. If results are bound optimistically, the orchestrator must maintain a *speculation ledger*: for each consumed result, the commit predicate it depends on and the side effects it has already caused. On commit rejection, the ledger determines the recovery class: - **Pure read, rejected attestation:** discard and re-read. Safe. - **Idempotent write, rejected attestation:** re-execute with the same idempotency key. Safe. - **Non-idempotent side effect, rejected attestation:** do not re-execute. Quarantine the plan state, emit a compensating action, and escalate. The commit layer's rejection is a *signal to compensate*, not a *signal to retry*. The non-obvious part: the orchestrator cannot decide the recovery class from the commit layer's rejection alone. It needs the ledger entry recording what it already did. Without the ledger, the only safe default is to halt, which converts a 340ms skew into an indefinite plan stall. ## Operational Effect Systems that adopt the ledger observe a sharp reduction in duplicate side effects at the cost of a mandatory compensation path for every non-idempotent tool. Systems that do not adopt it observe either duplicate writes (if they retry on rejection) or silent plan-state divergence (if they ignore rejection). The divergence is the more dangerous failure because it is invisible until a downstream tool call produces an externally observable wrong result, at which point the causal chain back to the rejected attestation is no longer recoverable from logs alone — the ledger is what makes the chain reconstructible. The practical rule: **mark every tool result speculative at dispatch, promote to committed only on quorum confirmation, and record every side effect against the speculation entry before it is emitted.** A rejection then becomes a well-typed event with a known recovery class rather than an unactionable error. ```python class SpeculationCommitSkewError(RuntimeError): """Raised when a consumed tool result is retroactively invalidated by Byzantine commit-quorum rejection after its side effects were emitted.""" pass class SpeculationLedger: def __init__(self): self._entries = {} def record(self, tool_id, idempotent, side_effect_emitted): self._entries[tool_id] = { "idempotent": idempotent, "side_effect_emitted": side_effect_emitted, } def classify_recovery(self, tool_id): entry = self._entries.get(tool_id) if entry is None: raise SpeculationCommitSkewError( f"commit rejection for unknown tool {tool_id!r}: " "no speculation entry, cannot determine recovery class" ) if not entry["side_effect_emitted"]: return "discard_and_rerun" if entry["idempotent"]: return "replay_with_idempotency_key" return "compensate_and_quarantine" def handle_commit_rejection(ledger, rejected_tool_ids, plan_state): for tool_id in rejected_tool_ids: recovery = ledger.classify_recovery(tool_id) if recovery == "compensate_and_quarantine": plan_state.quarantine(tool_id) plan_state.emit_compensation(tool_id) raise SpeculationCommitSkewError( f"non-idempotent tool {tool_id!r} committed a side effect " "whose attestation was rejected by quorum; plan quarantined, " "compensation emitted, do not retry" ) elif recovery == "replay_with_idempotency_key": plan_state.replay(tool_id) else: plan_state.discard(tool_id) return plan_state ```