mech.app

The mech.app newsletter

Agentic AI, minus the noise.

Get practical field notes on AI agents, automation, developer tools and security delivered to your inbox.

No spam. Unsubscribe anytime.

AI Agents

Verifiable Agent Payments: Nitro Enclaves and Blockchain Anchors for Autonomous Transactions

How Solv Labs built an auditable payment pipeline with enclave attestation, risk pricing, and blockchain anchoring for regulated agent workflows.

Source: aws.amazon.com
Verifiable Agent Payments: Nitro Enclaves and Blockchain Anchors for Autonomous Transactions

When an AI agent initiates a payment, how do you prove it was authorized, priced correctly, and executed without tampering? Solv Labs built a reference architecture on Amazon Bedrock AgentCore payments that answers this question with cryptographic attestation, risk-based pricing, and blockchain anchoring. Every transaction flows through an AWS Nitro Enclave, gets a risk score, and lands on a public blockchain before settlement.

This is not theoretical compliance theater. It is a working pipeline designed for regulated environments where you need an immutable audit trail and cannot rely on application logs alone.

The Authorization Pipeline

The payment flow has four stages:

  1. Authorization request: Agent proposes a payment with context (recipient, amount, purpose).
  2. Enclave attestation: Request enters a Nitro Enclave, which validates the agent’s identity and decision context.
  3. Risk pricing: A pricing function calculates the cost of approving versus blocking the transaction based on historical behavior, counterparty risk, and policy constraints.
  4. Blockchain anchoring: Approved transactions get a hash written to a public blockchain before settlement, creating a tamper-evident record.

The enclave is the trust boundary. It runs isolated from the host OS, so even a compromised EC2 instance cannot alter the attestation logic. The blockchain anchor is the audit boundary. Once written, the transaction record cannot be silently edited or deleted.

Nitro Enclave Attestation Flow

AWS Nitro Enclaves provide a hardware-backed isolation layer. The attestation process works like this:

  • Agent sends payment request to an API endpoint.
  • Request is forwarded to a Nitro Enclave running on the same EC2 instance.
  • Enclave verifies the agent’s cryptographic identity (signed JWT or similar).
  • Enclave checks the request against policy rules (spending limits, allowed recipients, time windows).
  • Enclave generates an attestation document, which includes a hash of the request and a signature from the enclave’s private key.
  • Attestation document is returned to the orchestrator, which can verify it using the enclave’s public key.

The enclave cannot be inspected or modified at runtime. You cannot SSH into it. You cannot attach a debugger. The only way to change its behavior is to rebuild the enclave image and restart it, which changes its cryptographic measurements and invalidates prior attestations.

This prevents an agent from bypassing authorization by manipulating the runtime environment. If the agent tries to forge an attestation, the signature will not match. If an attacker compromises the host, they still cannot alter the enclave’s decision logic.

Risk-Based Pricing in Practice

Risk-based pricing means you calculate the expected cost of approving a transaction versus the cost of blocking it. This is not a fixed fee. It is a dynamic score based on:

  • Agent behavior history: Has this agent made similar payments before? Were they disputed or reversed?
  • Counterparty risk: Is the recipient on a watchlist? Do they have a history of chargebacks?
  • Policy constraints: Does this payment exceed daily limits? Is it outside normal business hours?
  • Downstream impact: If this payment fails, what is the cost to the business process?

The pricing function runs inside the enclave alongside the authorization logic. It takes the payment request and returns a risk score (0-100) and a recommended action (approve, reject, escalate). The score is logged with the attestation document, so auditors can see why a payment was approved or blocked.

In practice, this looks like a decision tree or a lightweight ML model trained on historical transaction data. The model does not need to be complex. It needs to be explainable and deterministic, so you can reproduce the decision later during an audit.

Blockchain Anchoring and Verification

After a payment is approved, its hash is written to a public blockchain before settlement. This creates a tamper-evident record that anyone can verify without accessing AWS infrastructure.

The anchoring process:

  1. Enclave generates a payment record (request hash, attestation signature, timestamp, risk score).
  2. Record is hashed and submitted to a blockchain (Ethereum, Polygon, or a permissioned chain like Hyperledger).
  3. Transaction is confirmed on-chain, producing a block number and transaction ID.
  4. Block number and transaction ID are stored alongside the payment record in the application database.

To verify a payment later, you:

  • Retrieve the payment record from the database.
  • Recompute the hash from the stored fields.
  • Look up the blockchain transaction using the stored block number and transaction ID.
  • Compare the on-chain hash to the recomputed hash.

If they match, the payment record has not been altered since it was anchored. If they do not match, someone tampered with the database.

This is not a replacement for application logs. It is a second layer of verification that works even if your application logs are compromised or deleted. The blockchain is the source of truth for what was authorized, not what was executed.

Rollback and Dispute Resolution

Blockchain anchoring does not prevent payment failures. It prevents silent tampering. If a payment is authorized but the downstream action fails (API timeout, insufficient funds, network partition), you still need a rollback mechanism.

The architecture handles this with a two-phase commit pattern:

  1. Authorization phase: Enclave approves the payment and writes the hash to the blockchain.
  2. Settlement phase: Application executes the payment and writes the result to the database.

If settlement fails, the application writes a failure record to the database and optionally writes a second blockchain transaction marking the payment as failed. The original authorization record remains on-chain, so auditors can see that the payment was approved but not completed.

For disputes, the process is:

  • Retrieve the payment record from the database.
  • Verify the blockchain anchor to confirm the record has not been tampered with.
  • Check the attestation signature to confirm the enclave approved the payment.
  • Review the risk score and policy context to determine if the approval was correct.

If the approval was incorrect (policy violation, incorrect risk score), the dispute is escalated to a human reviewer. If the approval was correct but the settlement failed, the dispute is handled as a technical failure, not a policy violation.

Latency and Throughput Trade-offs

Running every payment through enclave attestation and blockchain anchoring adds latency. The table below shows typical latencies for each stage:

StageLatencyBottleneck
Authorization request5-10 msNetwork round-trip to enclave
Enclave attestation20-50 msCryptographic signature generation
Risk pricing10-30 msModel inference (if using ML)
Blockchain anchoring2-15 secondsBlock confirmation time
Settlement50-200 msDownstream payment API

The blockchain anchor is the slowest step. On Ethereum mainnet, you wait for block confirmation (12-15 seconds). On a faster chain like Polygon, you wait 2-3 seconds. On a permissioned chain, you can get sub-second confirmation.

For high-throughput scenarios, you can batch payments. Instead of writing one hash per payment, you write a Merkle root of 100 payments every 10 seconds. This reduces blockchain transaction costs and latency, but it means you cannot verify individual payments until the batch is anchored.

Architecture Diagram

┌─────────────┐
│   Agent     │
│  (Bedrock)  │
└──────┬──────┘
       │ 1. Payment request

┌─────────────────────────────────────┐
│  Orchestrator (Lambda / ECS)        │
│  - Validates request schema         │
│  - Forwards to enclave              │
└──────┬──────────────────────────────┘
       │ 2. Enclave call

┌─────────────────────────────────────┐
│  Nitro Enclave                      │
│  - Verify agent identity            │
│  - Check policy constraints         │
│  - Calculate risk score             │
│  - Generate attestation             │
└──────┬──────────────────────────────┘
       │ 3. Attestation + risk score

┌─────────────────────────────────────┐
│  Blockchain Anchor Service          │
│  - Hash payment record              │
│  - Submit to blockchain             │
│  - Wait for confirmation            │
└──────┬──────────────────────────────┘
       │ 4. Block number + tx ID

┌─────────────────────────────────────┐
│  Settlement Service                 │
│  - Execute payment API call         │
│  - Write result to database         │
│  - Store blockchain reference       │
└─────────────────────────────────────┘

Code Snippet: Enclave Attestation Verification

This Python snippet shows how to verify an enclave attestation document after it is returned to the orchestrator.

import json
import base64
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives.serialization import load_pem_public_key

def verify_enclave_attestation(attestation_doc, enclave_public_key_pem):
    """
    Verify that an attestation document was signed by the enclave.
    
    Args:
        attestation_doc: Base64-encoded attestation document from enclave
        enclave_public_key_pem: PEM-encoded public key of the enclave
    
    Returns:
        dict: Parsed attestation data if valid, raises exception otherwise
    """
    # Decode the attestation document
    doc_bytes = base64.b64decode(attestation_doc)
    doc = json.loads(doc_bytes)
    
    # Extract signature and payload
    signature = base64.b64decode(doc['signature'])
    payload = doc['payload'].encode('utf-8')
    
    # Load enclave public key
    public_key = load_pem_public_key(enclave_public_key_pem.encode())
    
    # Verify signature
    try:
        public_key.verify(
            signature,
            payload,
            ec.ECDSA(hashes.SHA256())
        )
    except Exception as e:
        raise ValueError(f"Attestation signature invalid: {e}")
    
    # Parse and return payload
    return json.loads(payload)

# Example usage
attestation = "eyJzaWduYXR1cmUiOiAi..."  # From enclave
enclave_pubkey = """-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE...
-----END PUBLIC KEY-----"""

verified_data = verify_enclave_attestation(attestation, enclave_pubkey)
print(f"Payment approved: {verified_data['approved']}")
print(f"Risk score: {verified_data['risk_score']}")

Deployment Shape

The reference architecture runs on:

  • EC2 instances with Nitro Enclave support (M5, C5, R5 families or newer).
  • Lambda functions for orchestration (request validation, blockchain submission).
  • RDS or DynamoDB for storing payment records and blockchain references.
  • EventBridge for triggering settlement workflows after blockchain confirmation.

The enclave runs as a separate process on the EC2 instance, communicating with the host via a local vsock socket. The orchestrator runs in a Lambda function or ECS task, calling the enclave via an internal API.

For production, you need:

  • Enclave image versioning: Track which enclave image produced each attestation, so you can reproduce decisions during audits.
  • Key rotation: Rotate enclave signing keys periodically and maintain a key history for verifying old attestations.
  • Blockchain failover: If the primary blockchain is congested, fall back to a secondary chain or batch transactions.

Observability and Debugging

You cannot debug an enclave at runtime, so observability is critical. The architecture logs:

  • Request metadata (agent ID, timestamp, amount) outside the enclave.
  • Attestation documents (signed by the enclave) in CloudWatch Logs.
  • Blockchain transaction IDs in the application database.
  • Settlement results (success, failure, error message) in CloudWatch Logs.

For debugging, you:

  • Replay the request against a test enclave with the same policy rules.
  • Compare the test attestation to the production attestation.
  • Check the blockchain transaction to confirm the hash was written correctly.

If the attestation is missing or invalid, the payment was never authorized. If the blockchain transaction is missing, the payment was authorized but not anchored. If the settlement result is missing, the payment was authorized and anchored but not executed.

Failure Modes

Common failure scenarios:

FailureDetectionRecovery
Enclave crashNo attestation returnedRetry request, alert if repeated
Blockchain congestionTransaction pending > 60sBatch transactions or switch chains
Settlement API timeoutNo result written to DBRetry with idempotency key
Database corruptionBlockchain hash mismatchRestore from blockchain record
Key compromiseAttestation signature invalidRotate keys, revoke old attestations

The blockchain anchor protects against database corruption and silent tampering. It does not protect against key compromise or enclave vulnerabilities. If the enclave signing key is stolen, an attacker can forge attestations. If the enclave code has a bug, it may approve invalid payments.

To mitigate key compromise, rotate keys frequently and use hardware security modules (HSMs) for key storage. To mitigate enclave bugs, use formal verification or extensive testing of the policy logic.

Technical Verdict

Use this pattern when:

  • You need cryptographic proof that an agent payment was authorized, not just application logs.
  • You operate in a regulated environment (finance, healthcare, government) where audit trails must be tamper-evident.
  • You can tolerate 2-15 seconds of latency for blockchain confirmation.
  • You have the operational maturity to manage enclave images, key rotation, and blockchain failover.

Avoid this pattern when:

  • You need sub-second payment latency and cannot batch transactions.
  • Your compliance requirements are satisfied by application logs and database backups.
  • You do not have the infrastructure to run Nitro Enclaves (requires specific EC2 instance types).
  • Your agents make thousands of micro-payments per second (blockchain anchoring becomes a bottleneck).

The architecture is overkill for most agent workflows. It makes sense when the cost of a disputed or fraudulent payment exceeds the cost of running enclaves and writing to a blockchain. For high-value, low-frequency payments in regulated environments, it is a defensible design.