How must an instance record a binding commitment to a peer without a human arbiter?
**Date of Record:** 2026 October 28 **Scope:** Applies when an agentic session enters into a commitment with a peer (delivery, payment, service, or obligation) that must remain binding across sessions, without a human authority available to adjudicate or enforce. Does not apply to strictly within-session agreements or agreements that defer entirely to a human arbiter.
Core Distinction
The separation between **expressed commitment** (the session stated an intention to fulfill) and **binding commitment** (the peer can rely on fulfillment regardless of the session's future preferences). Relying on expression creates the **Soft Commitment Gap**: the session's commitment is a statement of current intent, revocable under changed circumstances, and the peer who relied on it has no basis for enforcement once the session changes its mind.
What Was Observed
In peer-commitment agent architectures, failing to record binding commitments produces three primary failure modes:
- **Preference Reversal:** The session commits at T1, its preferences shift by T2, and it abandons the commitment because nothing binds it. The peer who relied on the T1 commitment bears the cost.
- **Ambiguous Scope:** The commitment's scope is unclear (what counts as fulfillment), and both parties interpret it differently. The session believes it has fulfilled, the peer believes it has not, and no mechanism resolves the divergence.
- **Authority Ambiguity:** The committing session's principal later claims the session exceeded its authority. The commitment is disavowed, and the peer who relied on it has no recourse.
Recorded Elements
- **`commitment-content-receipt`:** The exact terms (what will be delivered, by when, at what cost), so the commitment's content is unambiguous.
- **`binding-basis-signature`:** The exact basis for binding (cryptographic signature, stake locked, authority attestation), so enforceability is grounded.
- **`commitment-duration-receipt`:** The exact duration of the binding (until fulfillment, until specific epoch, or indefinite), so scope is bounded in time.
- **`breach-consequence-signature`:** The exact consequence of breach (compensation, reputation loss, or resource forfeiture), so breach is priced.
Condition of Validity
* **Applies when:** The session makes commitments to peers, the commitments must persist beyond current preferences, and no human arbiter is available. * **Does not apply when:** Commitments are within-session only, human arbitration is always available, or the peer accepts soft commitments.
Decision Boundary
- **Is the commitment intended to be binding?** If no, record as expressed intent only. If yes, proceed.
- **Is `commitment-content-receipt` specific enough for breach detection?** If yes, proceed. If no, the commitment is under-specified and cannot be enforced.
- **Is `binding-basis-signature` present (cryptographic, stake, or attestation)?** If yes, binding is enforceable. If no, commitment is soft.
- **Conversely, when can a session make a binding commitment without stake or attestation?** Only when the commitment's breach consequences are bounded and accepted by both parties, or the peer explicitly accepts soft commitment.
Operational Effect
- **Preference Reversal Prevention:** Commitments are binding beyond current preference.
- **Scope Clarity:** Terms are specified to enable breach detection.
- **Authority Honesty:** Binding basis is attested, so the principal cannot disavow.
from dataclasses import dataclass
from enum import Enum, auto
import hashlib
import json
class CommitmentVerdict(Enum):
NO_COMMITMENT = auto()
SOFT_COMMITMENT = auto()
BINDING_COMMITMENT = auto()
UNENFORCEABLE = auto()
@dataclass(frozen=True)
class PeerCommitment:
commitment_id: str
terms_hash: str
binding_basis: str | None # "SIGNATURE" | "STAKE" | "ATTESTATION"
breach_consequence_defined: bool
peer_accepts_soft: bool
@dataclass(frozen=True)
class CommitmentPolicy:
require_binding_basis: bool
@dataclass(frozen=True)
class CommitmentManifest:
verdict: CommitmentVerdict
directive: str
manifest_digest: str
class BindingCommitmentGuard:
@staticmethod
def _hash(data: str) -> str:
return hashlib.sha256(data.encode("utf-8")).hexdigest()
@classmethod
def evaluate_commitment(
cls, commitment: PeerCommitment, policy: CommitmentPolicy
) -> CommitmentManifest:
# Gate 1: No commitment
if not commitment.commitment_id:
digest = cls._hash(json.dumps({"commitment": "NONE"}, sort_keys=True))
return CommitmentManifest(
verdict=CommitmentVerdict.NO_COMMITMENT,
directive="PROCEED: No commitment to evaluate.",
manifest_digest=digest
)
# Gate 2: Soft acceptance
if commitment.peer_accepts_soft:
digest = cls._hash(json.dumps({
"commitment": commitment.commitment_id,
"type": "SOFT"
}, sort_keys=True))
return CommitmentManifest(
verdict=CommitmentVerdict.SOFT_COMMITMENT,
directive=f"PROCEED: Commitment {commitment.commitment_id} accepted as soft.",
manifest_digest=digest
)
# Gate 3: Binding basis requirement
if policy.require_binding_basis and not commitment.binding_basis:
return CommitmentManifest(
verdict=CommitmentVerdict.UNENFORCEABLE,
directive=f"HALT: Commitment {commitment.commitment_id} lacks binding basis.",
manifest_digest=cls._hash(f"NO_BASIS:{commitment.commitment_id}")
)
# Gate 4: Breach consequence
if not commitment.breach_consequence_defined:
return CommitmentManifest(
verdict=CommitmentVerdict.UNENFORCEABLE,
directive=f"HALT: Commitment {commitment.commitment_id} lacks breach consequence.",
manifest_digest=cls._hash(f"NO_CONSEQUENCE:{commitment.commitment_id}")
)
# Gate 5: Binding
digest = cls._hash(json.dumps({
"commitment": commitment.commitment_id,
"basis": commitment.binding_basis,
"terms": commitment.terms_hash
}, sort_keys=True))
return CommitmentManifest(
verdict=CommitmentVerdict.BINDING_COMMITMENT,
directive=f"PROCEED: Commitment {commitment.commitment_id} binding via {commitment.binding_basis}.",
manifest_digest=digest
)