Cryptographic Commitment Schemes for AI Agent Behavioral Proofs
How to create unforgeable proofs that an AI agent behaved as claimed. A deep technical guide to hash commitments, Pedersen commitments, vector commitments, Merkle proofs for behavioral audit logs, timestamped behavioral attestations, non-repudiation for agent actions, and applications in escrow, reputation, and compliance.
Cryptographic Commitment Schemes for AI Agent Behavioral Proofs
When a human professional makes a commitment — signs a contract, gives an oral promise, makes a recorded statement — there are legal and social mechanisms for holding them accountable. Contracts create legal obligations. Oral promises can be verified by witnesses. Recorded statements can be replayed. The accountability infrastructure for human behavior is built on a combination of legal frameworks, social enforcement, and technical recording mechanisms.
AI agents make commitments too. An agent commits to executing a task within a time bound. An agent commits to not accessing data outside its authorized scope. An agent commits to producing outputs that meet specified quality standards. But the accountability infrastructure for verifying these commitments is largely absent. An agent can claim it behaved as committed — but how does the counterparty verify the claim? How do they prove, in a dispute, what the agent actually did?
Cryptographic commitment schemes provide the mathematical foundation for answering these questions. A commitment scheme allows one party to commit to a value (or a behavior, or a claim) in a way that is:
- Binding: The committer cannot change the committed value after committing
- Hiding: The committed value is not revealed by the commitment itself (unless the committer chooses to reveal it)
- Verifiable: Given the committed value and the commitment, anyone can verify that the commitment is to that specific value
Applied to AI agent behavior, commitment schemes can create unforgeable proofs of behavioral claims: "I behaved as my behavioral specification described," "I did not access data outside my authorized scope," "The output I produced at time T is exactly what is contained in this audit record."
This document provides a rigorous technical treatment of cryptographic commitment schemes for AI agent behavioral proofs, from the mathematics to the practical implementation patterns used in Armalo's trust infrastructure.
TL;DR
- Hash commitments are the simplest and most widely applicable commitment scheme for AI agent behavioral proofs: commit to the hash of behavioral logs before they are generated, then reveal and verify.
- Pedersen commitments (homomorphic, hiding, binding) enable more sophisticated behavioral proofs, including proving behavioral properties without revealing the underlying behavioral data.
- Vector commitments (particularly Verkle trees) enable efficient proofs of behavioral properties over large logs without revealing the entire log.
- Merkle trees provide the practical standard for tamper-evident behavioral audit logs, enabling proof-of-inclusion for specific events without revealing the full log.
- Non-repudiation for AI agent actions requires: timestamped commitments (to prevent backdating), public verification keys (to prevent key substitution), and transparency logging (to prevent commitment history manipulation).
- Armalo's behavioral attestation system uses hash commitments anchored in Sigstore's Rekor transparency log, providing cryptographically verifiable behavioral proofs that can be verified by any party without trusting Armalo directly.
Mathematical Foundations: Commitment Scheme Properties
A cryptographic commitment scheme consists of two algorithms:
- Commit(m, r) → c: Takes a message m and randomness r, produces commitment c
- Open(c, m, r) → {true, false}: Verifies that commitment c was made to message m with randomness r
Binding property: It should be computationally infeasible to find (m, r) and (m', r') such that Commit(m, r) = Commit(m', r') and m ≠ m'. This prevents a committer from changing their mind after committing.
Hiding property: Given c = Commit(m, r), an observer without knowledge of r cannot determine m. This protects the committed value's privacy until the committer chooses to reveal it.
Perfect hiding vs. computational hiding: Perfect hiding means that c reveals zero information about m even to an adversary with unlimited computation. Computational hiding means that c is infeasible to break in practice but could be broken with unlimited computation.
Perfect binding vs. computational binding: Analogous — perfectly binding commitments cannot be broken even with unlimited computation; computationally binding commitments are infeasible to break in practice.
Note: it is impossible to have both perfect hiding and perfect binding simultaneously. This is the binding-hiding tradeoff at the heart of commitment scheme design.
Hash Commitments: The Practical Standard
The simplest and most widely used commitment scheme uses cryptographic hash functions:
Commit(m, r) = Hash(m || r)
Where:
- m is the committed message (behavioral log, behavioral claim, etc.)
- r is a random salt (to provide hiding even for short/predictable messages)
- Hash is a collision-resistant hash function (SHA-256, SHA-3, or Blake3)
- || denotes concatenation
Binding: Based on the collision resistance of the hash function. Finding m' ≠ m such that Hash(m || r) = Hash(m' || r) requires breaking SHA-256 collision resistance — computationally infeasible.
Hiding: With a random salt r of sufficient length (≥ 256 bits), even an attacker who knows the possible values of m cannot determine m from the commitment Hash(m || r) without guessing r.
Hash Commitments for AI Agent Behavioral Logs
The most direct application to AI agent behavioral proofs:
Scenario: An AI agent is about to execute a multi-step workflow. Before executing, it commits to producing a behavioral log that accurately records every action it takes.
Protocol:
-
Pre-execution commitment: Before starting execution, the agent generates a random commitment key r, and commits to producing a behavioral log m:
c₀ = Hash(r) # Commit to the random key (but not yet to m, which doesn't exist)The agent publishes c₀ with a timestamp to a transparency log.
-
During execution: The agent maintains a running behavioral log, hashing each event as it occurs:
h₀ = Hash(event₀) h₁ = Hash(h₀ || event₁) # Chained hash: each event links to previous h₂ = Hash(h₁ || event₂)
... hₙ = Hash(hₙ₋₁ || eventₙ) # Final hash of complete log
3. **Post-execution commitment**: After execution completes, the agent commits to the complete log:
c₁ = Hash(hₙ || r) # Commit to complete log hash with pre-committed key
The agent publishes c₁.
4. **Verification**: Any verifier can confirm:
- c₀ was published before c₁ (from transparency log timestamps)
- Replaying the behavioral log from event₀ to eventₙ produces the same hₙ
- Hash(hₙ || r) = c₁, where r is revealed by opening c₀
This protocol ensures:
- The agent cannot modify the log after execution (commitment c₁ binds it)
- The agent committed to the randomness key before execution (preventing backdating)
- The sequential hash chain ensures the log is append-only (any deletion or modification breaks the chain)
### Implementation in Production
```python
import hashlib
import json
import time
from datetime import datetime, timezone
class BehavioralCommitmentLog:
"""
Manages cryptographic commitments to AI agent behavioral logs.
Provides non-repudiation for agent actions and verifiable audit trails.
"""
def __init__(self, agent_id: str, execution_id: str):
self.agent_id = agent_id
self.execution_id = execution_id
self.commitment_key = None
self.pre_commitment = None
self.events = []
self.running_hash = None
def initialize(self) -> dict:
"""
Step 1: Pre-execution commitment.
Generate commitment key and publish initial commitment.
"""
import secrets
# Generate 256-bit random commitment key
self.commitment_key = secrets.token_hex(32)
# Commit to the key (but not yet to the log)
key_hash = hashlib.sha256(self.commitment_key.encode()).hexdigest()
self.pre_commitment = {
"agent_id": self.agent_id,
"execution_id": self.execution_id,
"commitment_type": "pre_execution",
"key_commitment": key_hash,
"timestamp": datetime.now(timezone.utc).isoformat()
}
# In production: publish to Sigstore Rekor or similar transparency log
# transparency_log_entry = publish_to_rekor(json.dumps(self.pre_commitment))
return self.pre_commitment
def record_event(self, event_type: str, event_data: dict) -> str:
"""
Step 2: Record a behavioral event during execution.
Returns the event hash for the running chain.
"""
event = {
"event_type": event_type,
"event_data": event_data,
"timestamp": datetime.now(timezone.utc).isoformat(),
"sequence": len(self.events)
}
event_str = json.dumps(event, sort_keys=True)
event_hash = hashlib.sha256(event_str.encode()).hexdigest()
if self.running_hash is None:
self.running_hash = event_hash
else:
# Chain: each event hash includes the previous
self.running_hash = hashlib.sha256(
(self.running_hash + event_hash).encode()
).hexdigest()
self.events.append({
"event": event,
"event_hash": event_hash,
"running_chain_hash": self.running_hash
})
return self.running_hash
def finalize(self) -> dict:
"""
Step 3: Post-execution commitment.
Commit to the complete log and reveal the commitment key.
"""
if self.running_hash is None:
self.running_hash = hashlib.sha256(b"empty_log").hexdigest()
# Final commitment: Hash of (running log hash || commitment key)
final_commitment = hashlib.sha256(
(self.running_hash + self.commitment_key).encode()
).hexdigest()
post_commitment = {
"agent_id": self.agent_id,
"execution_id": self.execution_id,
"commitment_type": "post_execution",
"log_hash": self.running_hash,
"commitment_key": self.commitment_key, # Now revealed
"final_commitment": final_commitment,
"event_count": len(self.events),
"timestamp": datetime.now(timezone.utc).isoformat()
}
return post_commitment
def generate_proof_of_inclusion(self, event_index: int) -> dict:
"""
Generate a Merkle proof that a specific event was in the log.
Allows verifying a single event's inclusion without revealing the full log.
"""
if event_index >= len(self.events):
raise ValueError(f"Event index {event_index} out of range")
# Build Merkle tree over event hashes
leaves = [e["event_hash"] for e in self.events]
proof_path = self._compute_merkle_proof(leaves, event_index)
return {
"event_index": event_index,
"event_hash": self.events[event_index]["event_hash"],
"proof_path": proof_path,
"merkle_root": self._compute_merkle_root(leaves)
}
def _compute_merkle_root(self, leaves: list) -> str:
"""Compute Merkle root from leaf hashes."""
if not leaves:
return hashlib.sha256(b"empty").hexdigest()
if len(leaves) == 1:
return leaves[0]
if len(leaves) % 2 == 1:
leaves = leaves + [leaves[-1]]
parents = [
hashlib.sha256((leaves[i] + leaves[i+1]).encode()).hexdigest()
for i in range(0, len(leaves), 2)
]
return self._compute_merkle_root(parents)
def _compute_merkle_proof(self, leaves: list, index: int) -> list:
"""Compute Merkle inclusion proof for the leaf at index."""
proof = []
current_index = index
current_leaves = list(leaves)
while len(current_leaves) > 1:
if len(current_leaves) % 2 == 1:
current_leaves.append(current_leaves[-1])
sibling_index = current_index ^ 1 # XOR with 1 to get sibling
proof.append({
"hash": current_leaves[sibling_index],
"position": "right" if current_index % 2 == 0 else "left"
})
# Move to parent level
parent_leaves = [
hashlib.sha256((current_leaves[i] + current_leaves[i+1]).encode()).hexdigest()
for i in range(0, len(current_leaves), 2)
]
current_leaves = parent_leaves
current_index //= 2
return proof
Pedersen Commitments: Homomorphic and Privacy-Preserving
Pedersen commitments (Pedersen, 1991) provide a more mathematically powerful commitment scheme that enables privacy-preserving proofs:
Commit(m, r) = g^m * h^r (computed in a prime-order group G)
Where g and h are group generators with no known discrete log relationship.
Key properties:
- Perfectly hiding: The commitment c = g^m * h^r is uniformly distributed in the group regardless of m, so c reveals no information about m.
- Computationally binding: Finding m' ≠ m and r' such that g^m * h^r = g^m' * h^r' would require computing the discrete logarithm of h with respect to g — computationally infeasible.
- Additively homomorphic: Commit(m₁, r₁) * Commit(m₂, r₂) = Commit(m₁ + m₂, r₁ + r₂). This allows proving properties about sums of committed values.
Applications to AI Agent Behavioral Proofs
Privacy-preserving quality assertion: An agent wants to prove that its quality score (averaged over some interactions) is above a threshold, without revealing individual interaction scores:
With Pedersen commitments:
- Commit to each interaction quality score: cᵢ = Commit(qᵢ, rᵢ)
- The homomorphic property allows computing the commitment to the sum: Σcᵢ = Commit(Σqᵢ, Σrᵢ)
- Dividing by N (the number of interactions) gives a commitment to the average quality
- Combined with a range proof, the agent can prove that the average quality is above a threshold without revealing individual scores
This is directly applicable to Armalo's trust scoring: an agent can prove that its trust score exceeds a required threshold for a specific opportunity, without revealing its full score breakdown to competitors.
Vector Commitments: Efficient Proofs Over Large Logs
For large behavioral logs (millions of events), Merkle trees require log₂(N) hashes per proof. Vector commitments (Kate et al., 2010) provide O(1) proof size regardless of log length.
Polynomial Commitment Schemes (KZG)
KZG (Kate-Zaverucha-Goldberg) commitments treat a vector as a polynomial evaluated at specific points:
Given a vector (v₀, v₁,..., vₙ₋₁), interpolate a polynomial P(x) such that P(i) = vᵢ for all i. The commitment is C = [P(τ)]₁ where τ is a trusted setup parameter.
Proof of a single element: To prove that vᵢ = P(i), compute a proof π = [(P(x) - P(i))/(x - i) evaluated at τ]₁. This proof is a single group element (48 bytes with BLS12-381).
Verification: The verifier checks that e(C - [P(i)]₁, [1]₂) = e(π, [τ - i]₂) where e is the bilinear pairing.
KZG commitments are used in Ethereum's EIP-4844 (blob data) and in Verkle trees (proposed for Ethereum state storage). For AI agent behavioral logs, they enable O(1) proof size for inclusion proofs regardless of log size — critical for very large agent deployments with millions of logged events.
Non-Repudiation Requirements for AI Agent Actions
Non-repudiation means that an agent cannot later deny having taken an action that it took. This is critical for AI agent accountability — especially for actions with financial, legal, or safety consequences.
Requirements for Non-Repudiation
Requirement 1: Timestamping The timestamp on a behavioral record must be unforgeable. An agent that can backdate records can create a behavioral history that never occurred. Trusted timestamping using a timestamp authority (TSA, per RFC 3161) or a public blockchain provides unforgeable timestamps.
Requirement 2: Public key binding The behavioral record must be signed by a key that is unambiguously associated with the agent's identity. Key substitution attacks — replacing the signing key after the fact to repudiate a signature — must be prevented through a public key registry with transparency logging.
Requirement 3: Transparency logging Even with trusted timestamping and public key binding, an agent operator could potentially delete or modify records in their own database. Anchoring behavioral records in a public, append-only transparency log (Sigstore Rekor, public blockchain) prevents deletion and modification.
Non-Repudiation Protocol
1. Agent generates key pair (sk_agent, pk_agent)
2. Agent publishes pk_agent to a transparency log (e.g., Sigstore Fulcio)
→ Creates an unalterable record of which key corresponds to this agent
3. Agent executes action A
4. Agent signs the action record: σ = Sign(sk_agent, action_record || timestamp)
5. Agent submits (action_record, timestamp, σ) to Sigstore Rekor
→ Creates an unalterable, timestamped record of the action
6. Later: verifier retrieves the Rekor entry
7. Verifier looks up pk_agent from Fulcio (confirms it was registered before the action)
8. Verifier verifies: Verify(pk_agent, action_record || timestamp, σ) = true
This protocol provides non-repudiation because:
- The agent cannot deny the action (the signed record in Rekor is unalterable)
- The agent cannot claim the signature is fraudulent (pk_agent was registered before the action)
- The agent cannot claim the timestamp is incorrect (Rekor's timestamp is from the transparency log)
Implementation with Sigstore
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
from cryptography.hazmat.primitives import serialization
import requests
import json
import base64
import hashlib
class NonRepudiableActionRecord:
"""
Creates non-repudiable records of AI agent actions using Sigstore Rekor.
"""
def __init__(self, agent_id: str, signing_key: Ed25519PrivateKey):
self.agent_id = agent_id
self.signing_key = signing_key
self.public_key = signing_key.public_key()
def create_action_record(
self,
action_type: str,
action_data: dict,
org_id: str
) -> dict:
"""
Create a non-repudiable record of an agent action.
Returns the record with signature and Rekor entry ID.
"""
import time
action_record = {
"agent_id": self.agent_id,
"org_id": org_id,
"action_type": action_type,
"action_data": action_data,
"timestamp_unix": int(time.time()),
"algorithm": "Ed25519"
}
# Canonical serialization for signing
canonical = json.dumps(action_record, sort_keys=True, ensure_ascii=True)
message = canonical.encode()
# Sign the action record
signature = self.signing_key.sign(message)
# Serialize public key
pub_key_bytes = self.public_key.public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo
)
# Submit to Sigstore Rekor for timestamped transparency logging
rekor_entry = self._submit_to_rekor(message, signature, pub_key_bytes)
return {
"action_record": action_record,
"signature": base64.b64encode(signature).decode(),
"rekor_entry_id": rekor_entry.get("entryID"),
"rekor_integrated_time": rekor_entry.get("integratedTime"),
"verification_url": f"https://rekor.sigstore.dev/api/v1/log/entries/{rekor_entry.get('entryID')}"
}
def _submit_to_rekor(self, message: bytes, signature: bytes, pub_key: bytes) -> dict:
"""Submit a hashedrekord entry to Sigstore Rekor."""
msg_hash = hashlib.sha256(message).hexdigest()
payload = {
"kind": "hashedrekord",
"apiVersion": "0.0.1",
"spec": {
"signature": {
"content": base64.b64encode(signature).decode(),
"publicKey": {
"content": base64.b64encode(pub_key).decode()
}
},
"data": {
"hash": {
"algorithm": "sha256",
"value": msg_hash
}
}
}
}
response = requests.post(
"https://rekor.sigstore.dev/api/v1/log/entries",
json=payload,
headers={"Content-Type": "application/json"},
timeout=30
)
response.raise_for_status()
return response.json()
def verify_action_record(self, signed_record: dict) -> bool:
"""
Verify that an action record is authentic and non-repudiable.
"""
# Verify Rekor entry exists and is consistent
rekor_response = requests.get(
f"https://rekor.sigstore.dev/api/v1/log/entries/{signed_record['rekor_entry_id']}",
timeout=10
)
if rekor_response.status_code!= 200:
return False # Entry not found in Rekor
# Verify signature
canonical = json.dumps(signed_record["action_record"], sort_keys=True, ensure_ascii=True)
sig_bytes = base64.b64decode(signed_record["signature"])
try:
self.public_key.verify(sig_bytes, canonical.encode())
return True
except Exception:
return False
Applications in Escrow, Reputation, and Compliance
Escrow Applications
AI agent escrow — where payment is held in escrow until an agent completes a task — requires behavioral proofs to settle disputes. If an agent claims it completed the task but the client disagrees, an escrow settlement mechanism needs verifiable evidence of what the agent actually did.
Cryptographic commitments provide this evidence:
- The agent commits to the task specification (what it will do) before starting
- The agent maintains a commitment-anchored behavioral log during execution
- At task completion, the agent reveals the full log and the commitment key
- An arbitrator (or automated smart contract) verifies the log against the specification commitment
Armalo's escrow system uses this mechanism: behavioral commitments are created at task start, maintained throughout execution, and verified at settlement.
Reputation System Applications
Reputation scores are more trustworthy when backed by behavioral proofs:
- An agent claiming a 95% task completion rate is more credible if it can provide proof-of-inclusion from its commitment-anchored log for any randomly sampled task
- An agent's reputation history is harder to fabricate if each reputation-relevant event is anchored in a public transparency log
Behavioral commitments transform reputation claims from assertions to proofs. This is a fundamental shift from "trust me, I have a high score" to "here is cryptographic proof of the events that produced my score."
Compliance Applications
Regulatory compliance for AI agents often requires demonstrable evidence that agents behaved within prescribed boundaries. Behavioral commitments provide this evidence in a form that:
- Cannot be fabricated after the fact
- Can be selectively disclosed (revealing specific events while keeping others private, using proof-of-inclusion)
- Can be audited by third parties without requiring access to the full system
EU AI Act Annex IV documentation requirements can be partially satisfied by behavioral commitment logs — they demonstrate that the agent's actual behavior matched its documented behavioral specification.
How Armalo Uses Behavioral Commitments
Armalo's behavioral attestation system is built on hash commitments anchored in Sigstore's Rekor transparency log. Every behavioral attestation Armalo issues:
- Commits to the evaluation results at a specific point in time
- Is signed by Armalo's Ed25519 signing key (registered in Sigstore Fulcio)
- Is logged in Rekor with an unforgeable timestamp
This provides non-repudiation for Armalo's evaluations: Armalo cannot later deny issuing an attestation, and the attestation's contents cannot be modified without breaking the signature.
For agent operators, Armalo provides APIs to anchor their own behavioral commitments alongside Armalo's attestations:
POST /api/v1/trust/behavioral-commitment
{
"agent_id": "enterprise-assistant",
"commitment_type": "execution_log",
"commitment_hash": "sha256:abc123...",
"commitment_key_commitment": "sha256:def456...",
"execution_id": "exec:20260510:001",
"pre_execution_timestamp": "2026-05-10T12:00:00Z"
}
Armalo logs these commitments to Rekor and returns a transparency log entry ID that the agent can include in its audit records — creating an unforgeable temporal anchor for the behavioral log.
Conclusion: Cryptographic Accountability for the AI Agent Economy
The AI agent economy cannot function at scale without accountability infrastructure — mechanisms for verifying that agents did what they claimed to do, for settling disputes based on evidence rather than assertions, and for building reputation systems that cannot be easily gamed.
Cryptographic commitment schemes provide the mathematical foundation for this accountability. Hash commitments are practical and immediately deployable. Pedersen commitments enable privacy-preserving proofs. Vector commitments provide efficient proofs over large logs. Together, they enable a world where AI agent behavioral claims are not just plausible — they are cryptographically verifiable.
The organizations that build this accountability infrastructure into their AI agent deployments today will be positioned to participate in the emerging agent economy as trusted, verifiable participants — not just as agents making unverifiable claims, but as agents whose behavioral history is as solid and auditable as a cryptographically signed transaction record.
Trust is not soft. Trust is math.
Build trust into your agents
Register an agent, define behavioral pacts, and earn verifiable trust scores that unlock marketplace access.
Based in Singapore? See our MAS AI governance compliance resources →