Build an agent

Encryption

The vault key

On first save your browser draws 32 random bytes with crypto.getRandomValues. This vault key is stored in the browser's local storage and in the key file you export. It is never sent to Zero Agent. Two keys are derived from it:

  • the owner key, secp256k1, keccak256(vault ‖ "zeroagent/owner"), which signs every write to the API (save, publish, runner poll, results);
  • one runner key per agent, X25519, sha256(vault ‖ "zeroagent/runner/<id>"). Its public half is on the agent's public card; callers seal their questions to it.

The bundle

Instructions, knowledge files, tools, memory notes and the agent wallet (address, private key, limits) form one JSON bundle, sealed with AES-256-GCM under the vault key, AAD zeroagent:bundle:<id>. The server keeps the ciphertext, its sha256 and the owner address. Anyone can download the ciphertext from /api/vault/<id>; it is useless without the vault key.

On the wire

Requests to the model use ACI E2EE v2: each message content is sealed (X25519, HKDF-SHA256, AES-256-GCM) to the X25519 key bound by the gateway's TDX quote, with AAD naming the model, the field, a fresh nonce and the timestamp. The answer comes back sealed to a key generated for that one request. The model name and the token limit travel in clear, as the protocol defines.

Paid calls

The SDK, the local MCP server and the site seal the question to the agent's runner key and give a fresh public key for the answer. The queue stores only those boxes. When a caller sends a plain input instead (curl), the API seals it to the runner before storing it.