Zero-Knowledge Remote Attestation for AI Agents
How remote attestation combined with zero-knowledge proofs lets you verify what an AI agent is doing without exposing its inputs, model weights, or confidential data.
When you hand an AI agent access to sensitive data, you face an uncomfortable paradox: you want to verify the agent is behaving correctly, but the very act of checking can expose the data you're trying to protect. Remote attestation combined with zero-knowledge proofs breaks this paradox. You can cryptographically verify an agent's behavior without learning anything about what it processed.
This post walks through how that works in practice, what hardware and software primitives make it possible, and how to integrate attestation into your agent infrastructure today.
The Problem: Trust Without Transparency
Modern AI agents operate in environments where trust is layered and partial:
- The model provider runs inference but shouldn't see your user's plaintext inputs.
- The orchestration platform routes tasks but shouldn't read intermediate agent state.
- The client wants assurance the agent behaved correctly but can't run the agent themselves.
Traditional approaches punt to contractual trust ("we promise not to look") or audit logs that themselves become a privacy liability. Neither is satisfying at scale.
Remote attestation offers a hardware-rooted alternative: a cryptographic proof that a specific piece of code ran in a specific environment, generated by hardware that cannot be spoofed in software.
What Is Remote Attestation?
Remote attestation is a protocol by which a hardware security module — typically a Trusted Execution Environment (TEE) like Intel TDX, AMD SEV-SNP, or AWS Nitro Enclaves — generates a signed statement about the software running inside it.
That statement, called an attestation report, includes:
- A measurement (hash) of the code and initial state loaded into the enclave
- The hardware platform identity, signed by the chip manufacturer
- A nonce provided by the verifier, preventing replay attacks
The critical property: the attestation report can only be generated by genuine hardware running the measured code. A compromised host OS, a rogue operator, or even the cloud provider cannot forge it.
In practice, an attested agent workflow looks like this:
Client Agent Enclave
| |
|--- nonce ---------------------->|
| Generate attestation
| report with nonce
|<-- attestation report ----------|
|
Verify: did the right code run?
Verify: did genuine hardware sign this?
Verify: does the nonce match?
|
If all pass: proceed with encrypted input
The client only sends sensitive data after verifying the attestation. At no point does the host system or cloud provider see the plaintext.
Where Zero-Knowledge Proofs Fit
Attestation answers "did this code run in a trusted environment?" But it doesn't answer "did the code produce a correct output?" For many agent use cases, you need both.
Zero-knowledge proofs (ZKPs) fill this gap. A ZK proof lets the agent demonstrate that its output satisfies a given predicate — "the summarization did not include any PII", "the retrieved documents match the stated query hash", "the tool call was authorized by the policy" — without revealing the underlying data.
Combining attestation with ZKPs creates a two-layer verification stack:
- Attestation proves the right code ran in a trustworthy environment.
- ZKP proves the code's output satisfies correctness properties without exposing the data.
This is particularly valuable in regulated industries. A healthcare agent, for example, can prove it only accessed records the patient authorized, without exposing which records those were or what they contained.
Practical Implementation: AWS Nitro Enclaves
AWS Nitro Enclaves is the most accessible TEE platform for agent developers today. Here's the minimal architecture:
┌─────────────────────────────────────────────┐
│ EC2 Parent Instance │
│ │
│ ┌──────────────────────────────────────┐ │
│ │ Nitro Enclave │ │
│ │ │ │
│ │ ┌────────────────────────────────┐ │ │
│ │ │ Agent Runtime (measured) │ │ │
│ │ │ - Model inference │ │ │
│ │ │ - Tool execution │ │ │
│ │ │ - State management │ │ │
│ │ └────────────────────────────────┘ │ │
│ │ │ │
│ │ No persistent storage │ │
│ │ No external network │ │
│ │ Isolated memory │ │
│ └──────────────────────────────────────┘ │
│ │
│ vsock: only communication channel │
└─────────────────────────────────────────────┘
The enclave has no filesystem, no external network, and communicates only via a vsock channel to the parent instance. The parent instance passes encrypted inputs; the enclave decrypts, processes, and returns encrypted outputs.
A minimal attestation flow in Python:
import subprocess
import json
import base64
def get_attestation(nonce: bytes) -> dict:
"""Request attestation from Nitro hypervisor."""
# The NSM (Nitro Security Module) device
result = subprocess.run(
["nsm-cli", "describe-pcrs"],
capture_output=True,
text=True
)
# In production: use the nsm Python library directly
# Returns PCR measurements (SHA-384 hashes of code/config)
return json.loads(result.stdout)
def verify_attestation(report: dict, expected_pcrs: dict, nonce: bytes) -> bool:
"""Verify attestation report against known good measurements."""
# PCR0: hash of the enclave image
# PCR1: hash of the Linux kernel
# PCR2: hash of the application
for pcr_index, expected_hash in expected_pcrs.items():
if report["pcrs"][pcr_index] != expected_hash:
return False
# Verify nonce is present and correct
return report.get("nonce") == base64.b64encode(nonce).decode()
The expected PCR values are published out-of-band (e.g., in a transparency log) when the enclave image is built. Clients check the live attestation report against those published values.
Integrating ZK Proofs for Output Verification
For the ZK layer, the practical options in 2026 are:
- RISC Zero — general-purpose zkVM; you write normal Rust, it generates proofs
- SP1 (Succinct) — similar zkVM approach, strong performance
- Noir — domain-specific language, good for policy circuits
- Halo2 — lower-level, high performance, steeper learning curve
For agent use cases, RISC Zero or SP1 are typically the right starting point. You wrap the computation you want to prove:
// Inside the RISC Zero guest program
use risc0_zkvm::guest::env;
fn main() {
// Read private inputs (not revealed in proof)
let query_hash: [u8; 32] = env::read();
let retrieved_doc_hashes: Vec<[u8; 32]> = env::read();
// Compute public output
let all_match = retrieved_doc_hashes.iter()
.all(|h| is_authorized(h, &query_hash));
// Commit public outputs to the proof
env::commit(&all_match);
env::commit(&query_hash); // Query hash is public
// Doc hashes are never committed — they stay private
}
The proof verifier only sees all_match (true/false) and the query_hash. The actual document content is never part of the proof.
Performance Considerations
The honest picture on performance:
| Operation | Typical latency | Notes |
|---|---|---|
| Nitro attestation | under 100ms | Cached after first call |
| RISC Zero proof generation | 2-30 seconds | Depends on program complexity |
| SP1 proof generation | 1-15 seconds | Generally faster than RISC Zero |
| Proof verification | under 50ms | Constant time for a given circuit |
Proof generation is the bottleneck. For interactive agents, this means ZKPs are best applied to batch verification (end-of-session audit) rather than per-turn verification, unless you're running on a GPU prover cluster.
Attestation, by contrast, is cheap enough to do on every session establishment.
What This Looks Like in a Storage Context
For BitAtlas users, attested agent access means:
- Your agent requests access to your encrypted data
- Your client verifies the agent's attestation: right code, right environment
- Only then does it decrypt the per-file keys for that session
- The agent can optionally generate ZK proofs that its access patterns complied with your policy
- Session ends; keys are discarded; attestation logs are retained for audit
This gives you cryptographic evidence that the agent accessed only what it was supposed to, without the storage layer ever seeing plaintext data or the agent being able to prove to a third party exactly what it retrieved.
Getting Started
If you're building agent infrastructure today, the practical path is:
- Start with attestation alone — attestation is mature and deployable now. Get your agent running in Nitro Enclaves or Azure Confidential Containers.
- Add ZK proofs for compliance claims — identify the specific predicates you need to prove (authorization, data classification, policy compliance) and build circuits for those first.
- Publish your PCR values — put your enclave measurements in a public transparency log. Clients can then verify independently without trusting you.
The tooling has matured significantly. RISC Zero and SP1 both have solid documentation, and AWS Nitro Enclaves are available in any region. The main investment is architectural: designing your agent to operate correctly within the isolation constraints TEEs impose.
The payoff is significant: cryptographic proof that your agents behaved correctly, without exposing the data they processed. That's a meaningful security property that no amount of logging or contractual agreement can match.