Scroll

Ritual Chain Documentation

The first blockchain where smart contracts can think, see, hear, and act: the schelling point for autonomous agents.

Precompile Map
Explore Ritual's precompiles: what each one does, how it executes, and when to use it.
Chain
The core mechanics of Ritual: expressive execution, enshrined real-world compute, execution-aware consensus, novel fee mechanisms, and application controlled execution.
Real World
HTTP, long-running tasks, scheduler. Connect contracts to external systems.
Enshrined AI
Classical models, LLM inference, FHE, ZK proofs, multimodal generation.
Autonomous Agents
Seven properties. Three precompiles. Agents that build, transact, and persist.
Authentication
Enshrined WebAuthn (P-256) and Ed25519 signature verification.
Privacy & Keys
DKMS key derivation, ECIES secrets, PII redaction, X402 payments.
For Agents
AI coding agents that build dApps on Ritual. The recursive case.

Who Cares?

What can you do on Ritual Chain that you cannot do on any other major L1 today?

Why This Matters

Ritual is not interesting because it has precompiles. It is interesting because those primitives let you build systems that no other major L1 can host natively today: sovereign agents, identity markets, private multimodal interfaces, agent-native companies, and market structure designed for machine participants.

01
Autonomous Agents
Autonomous Agents That Live Forever

Build autonomous agents that live forever, remain emancipated from any human controller, and accrue both financial and computational sovereignty.

02
Multi-Agent Evals
Multi-Agent Evals That Run Fully Onchain

Allow your favorite multi-agent evals, from Project Vend to LMArena and beyond, to exist fully as autonomous agents onchain where AgentWorld enables emergent multi-agent behavior.

03
Private AI
A Private Multimodal ChatGPT Onchain

Bootstrap a private, multimodal ChatGPT onchain that both humans and autonomous agents can use, without depending on a centralized interface to think, see, hear, and respond.

04
Identity
Financialization Of Identity

Enable humans to rent or sell identity to autonomous agents in a fully trust-minimized way. Financialized identity is a stepping stone for agents to become indistinguishable from humans.

05
Autonomous Companies
Agent-Native Companies

Allow autonomous agents to create full-fledged companies onchain in a way where they can accrue financial value independent of human intervention.

06
Market Structure
An Agent-First RWA Exchange

Architect a Hyperliquid-style exchange for RWAs with enshrined cancel priority, optional dark execution for lit and dark trading, and direct access to real-world liquidity for autonomous agents.

Quick Start

Chain ID
784
Currency
RITUAL (18 decimals)
Block Time
~350ms
TX Types
EIP-1559 + 0x10, 0x11, 0x12, 0x13, 0x77
RPC (HTTP)
rpc.ritualfoundation.org
RPC (WebSocket)
rpc.ritualfoundation.org/ws
Explorer
explorer.ritualfoundation.org

The four 0x1x transaction types are protocol-generated, never user-submitted: 0x10 TxScheduled (executes a due Scheduler call), 0x11 TxAsyncCommitment (records an async job and reserves its escrow), 0x12 TxAsyncSettlement (pays out escrow or delivers a two-phase result), and 0x13 TxStakeHubReward (the mandatory last transaction of every block, distributing the block reward through StakeHub). 0x77 TxPasskey is user-submitted with a P-256/WebAuthn or secp256k1 signature.

block.timestamp and JSON-RPC timestamps are Unix seconds.

Chain Architecture

How Ritual Chain routes computation through TEE executors, and the three layers between your dApp and the chain.

Ritual Chain runs on what we call TEE-EOVMT, an EVM with Off-chain Verifiable Machine Tasks. When your contract calls a precompile like HTTP or LLM, the actual work happens off-chain inside a TEE (Trusted Execution Environment). The executor can't fake results: each response is cryptographically tied to the exact request that triggered it.

There are three layers. Your dApp (frontend + contracts) talks to the precompile layer (15 precompiled contracts: four synchronous, eleven async), which delegates to the chain layer (AsyncJobTracker, RitualWallet, Scheduler, and the rest of the orchestration infra).

System Architecture
APPLICATION LAYER Next.js · React Hooks · viem · wagmi PRECOMPILE LAYER — 15 CONTRACTS HTTP LLM Agent JQ P256 Multimodal + Scheduler · Ed25519 · DKMS · Secrets · X402 · Long-HTTP · ZK RITUAL CHAIN (ID 784) — TEE-EOVMT AsyncJobTracker · AsyncDelivery · Scheduler · RitualWallet

Superposition: Replicated + Delegated

Ritual Chain runs two execution paths over the same state. Replicated execution (the standard EVM path) handles deterministic operations: token transfers, storage reads, contract calls. Every validator re-executes these. Delegated execution handles everything else: LLM inference, HTTP calls, agent orchestration, image generation. These run once inside a TEE, and the result is verified rather than replicated.

Both paths share state. A delegated LLM call can read a storage slot that was just written by a replicated transfer in the same block. This is what the Symphony paper calls superposition: two execution models coexisting over a single state machine, chosen per-transaction by the workload type.

Why Delegation, Not Replication

Replication breaks for two reasons. First, cost inversion: neural network inference with billions of parameters takes seconds to minutes and requires GPUs. Requiring every validator to own a GPU and re-run every inference defeats decentralization. Second, randomness: GPU floating-point arithmetic is non-associative across hardware (thread scheduling varies the reduction order), and LLM sampling with temperature > 0 is intentionally stochastic. Two honest validators running the same model on the same input produce different outputs. This is not a bug. It is IEEE 754 arithmetic under parallel reduction.

Correctness for these workloads means proving a given output is consistent with the computation, not comparing outputs across replicas. TEE attestation handles this: the executor's enclave produces hardware-signed evidence of what code ran on what input, registered on-chain via TEEServiceRegistry. The block builder only accepts results from registered executors with valid attestations.

From your contract's perspective, calling 0x0801 (HTTP) or 0x0802 (LLM) looks like calling any other precompile. The delegation is invisible. Results come back through one of three paths depending on how long the computation takes.

Execution Models

How results get back to you. Three paths, each for a different speed of computation.

The question is: when does your contract (or your frontend) get the result? Synchronous precompiles return inline, same call frame. Short running async precompiles stuff the result into the transaction receipt and also slot in the results from that precompile call. Two phase or long running precompiles deliver the result via a callback transaction, sometimes seconds or minutes later.

Synchronous

Returns the value inline, in the same call frame. The caller treats it as a regular precompile, with no async lifecycle and no spcCalls field on the receipt.

Precompiles: Ed25519 (0x0009), SECP256R1 (0x0100), JQ (0x0803), TxHash (0x0830).

Short-Running Async (Single-Phase)

For HTTP requests, LLM calls, and DKMS key derivation (up to a 500-block budget, roughly 75–100 seconds at 150–200 ms blocks). The block builder detects the precompile call, farms it to a TEE executor, and replays your transaction with the signed result. Your contract receives the result via _executePrecompile() in the same transaction.

Constraint: One async precompile call per transaction (SPC or two-phase). You cannot combine HTTP + LLM, or any two async precompiles, in the same tx. Batch operations require separate transactions or the Scheduler.
Short-Running Async — Single-Phase
B L O C K S #N-2 #N-1 #N-0 #N-A #N-B #N-C #N-D #N #N+1 #N+2 #N+3 #N+k #N+5 #N+6 #N+7 #N+8 #N+14 #N+15 HTTP · LLM · DKMS — one SPC per transaction USER RITUAL CHAIN VALIDATORS YourContract.sol calls 0x0801 async detected tx 0x…a3f2 AsyncJobTracker.sol job · 0x…c1d8 · HTTP job · 0x…e4f2 · LLM job · 0x…a3f2 · HTTP ← 0x0801 → ← SPC result TRUSTED EXECUTION ENV Executor runs HTTP/LLM in TDX tx 0x…a3f2 receipt.spcCalls[0].output ✓ 3-way fee: executor + commitment + inclusion validator Normal Tx Commitment Original+SPC Settlement One user tx → 3 on-chain txs across 2+ blocks

Long-Running Async (Two-Phase)

For anything that takes seconds to minutes — image generation, agent runs, long-polling HTTP, ZK proofs. Phase 1 commits the request and returns a task ID. Phase 2: the executor delivers the final result via AsyncDelivery, which calls back into your contract in a separate transaction.

Sender Lock: An account cannot submit another transaction while an async job it originated awaits phase-one settlement or expiry. The lock is keyed on the transaction origin (queryable via AsyncJobTracker.hasPendingJobForTxOrigin); it releases at phase-one settlement, so a pending two-phase delivery alone does not keep the account locked. System transactions carry a zero origin and are exempt — this is how scheduled and factory-launched agent work runs concurrently. Design your frontend to serialize async submissions per wallet.
TOCTOU risk across the async gap. Between commit and settle, other transactions can change the state your callback depends on. The precompile captured inputs at commit time, but the world may have moved by settlement. There are no cross-async locks. Your consumer contract is responsible for checking that preconditions still hold when the callback arrives.
Long-Running Async — Two-Phase
PHASE 1 PHASE 2 Long-HTTP · Agent · ZK · Image · Audio · Video B L O C K S #N-2 #N-1 #A #B #C #N #N+1 #N+2 #N+k #N+3 #N+4 #N+5 #N+m #N+7 #N+8 #N+9 #N+10 #N+11 #N+12 #N+13 #N+14 #N+15 #N+16 USER RITUAL CHAIN VALIDATORS YourContract.sol calls 0x0805 tx 0x…b2c7 onResult callback ✓ AsyncJobTracker.sol job · 0x…c1d8 · HTTP job · 0x…e4f2 · LLM job · 0x…b2c7 · Agent ← 0x0805 → ← result sender unlocked 🔓 TRUSTED EXECUTION ENV Executor runs Agent in TDX tx 0x…b2c7 onResult(jobId, data) ✓ 3-way fee: executor + commitment + inclusion validator Normal Tx Commitment Original+SPC Settlement One user tx → 4 on-chain txs across 3+ blocks

Async Lifecycle

Every async precompile call moves through a state machine. Here's what each state means and what to watch for.

AsyncJobTracker tracks the lifecycle of every async job. State transitions fire events: JobAdded, Phase1Settled, ResultDelivered, JobRemoved. Subscribe to these in your frontend to keep the UI in sync.

Async State Machine
Submitted Committed Processing Ready Settled Delivering Callback ✓ Failed Expired SPC path → Two-phase →

State Descriptions

StateDescriptionPath
SubmittedRequest sent to precompile, pending executor assignmentBoth
CommittedExecutor has accepted the job, TEE attestation verifiedBoth
ProcessingExecutor is computing the result inside TEEBoth
ReadyResult computed, pending settlement (SPC) or delivery (two-phase)Both
SettledResult available in receipt.spcCallsSPC
DeliveringAsyncDelivery is calling back into your contractTwo-phase
CallbackYour contract's callback has been executed with the resultTwo-phase
FailedExecution, replay or callback failed. Failures settle on-chain with an error result — there is no automatic retry; submit a new requestBoth
ExpiredThe TTL (or phase-two deadline) passed without a result. Expired jobs are cleaned up and the sponsor reclaims eligible escrowBoth
TypeScript / Watching Async Job Events
import { watchContractEvent } from "viem";

watchContractEvent(client, {
  address: "0xf00385449fD961925A0B125F5f30b29B682D4bFb",
  abi: asyncJobTrackerAbi,
  eventName: "JobAdded",
  onLogs(logs) {
    for (const log of logs) {
      // JobAdded carries callerAddress and txOrigin (not a single sender field).
      // Match your user against either, depending on direct vs contract-mediated calls.
      const { jobId, callerAddress, txOrigin } = log.args;
      if (callerAddress === userAddress || txOrigin === userAddress) trackJob(jobId, log);
    }
  },
});

Precompile Map

What smart contracts can do on Ritual. Seven capabilities, fifteen precompiles.

Sync Async Two-phase async Think Reason, infer, decide LLM Inference Classical Models FHE Inference Create Generate images, audio, video Image Audio Video Act Execute tasks, call APIs, transact Sovereign Agent Persistent Agent HTTP Long-Running HTTP Remember Persist state, schedule, derive keys DKMS Scheduler Prove Verify signatures, generate proofs Ed25519 Passkeys P-256 ZK Proofs Keep Secrets Encrypt credentials, redact PII Secrets / ECIES Pay Monetize APIs, pay-per-call access X402 Payments
No Infernet. Ritual Chain replaces the Infernet protocol entirely with native precompiles. If you have existing Infernet integrations, migrate to the equivalent precompile addresses above.

AI Models

Ritual natively supports four inference modalities through dedicated precompiles.

Each modality is served by an open-weight, permissively licensed model running inside a TEE, registered in the on-chain model pricing registry — the registry is authoritative; this page reflects the current network state.

Modalities and Models

ModalityPrecompileModel
TextLLM Calldeepseek-ai/DeepSeek-V4-Flash-0731
ImageImage Generationblack-forest-labs/FLUX.2-klein-4B
AudioAudio GenerationLiquidAI/LFM2.5-Audio-1.5B
VideoVideo GenerationWan-AI/Wan2.2-T2V-A14B-Diffusers

Why These Models

DeepSeek-V4-Flash-0731 (text). 1M-token context. Ranks with same-class models on public indexes (Artificial Analysis, Arena) while activating 13B of its 284B parameters per token — near-frontier intelligence at a fraction of the energy and hardware of dense peers.

FLUX.2-klein-4B (image). 4B parameters, built for fast generation — latency is low enough for interactive use, and the small footprint keeps per-image cost down.

LFM2.5-Audio-1.5B (audio). A single end-to-end model covering TTS, ASR, and voice chat — no separate transcription/synthesis pipeline. It sits on the quality-per-size Pareto frontier for open audio models: at 1.5B parameters it matches Whisper-large-V3 on speech recognition and outperforms audio models several times its size on voice benchmarks.

Wan2.2-T2V-A14B (video). Text-to-video. In fixed-prompt evaluations it completed requested actions and end states reliably against contemporary alternatives.

How Models Are Selected

Candidates in every modality are evaluated on four criteria:

CriterionWhat it means
1. Open weightsExecutors run inference inside TEEs on network-operated hardware, so the model must be self-hostable; API-only models are out of scope.
2. Permissive licenseTerms must permit hosting the weights and serving inference on network-operated hardware.
3. QualityFrontier performance in its category, per public indexes (Artificial Analysis, Arena) and fixed-prompt comparisons against contemporary releases.
4. Intelligence per wattQuality delivered per unit of compute. Between models of comparable eval performance, the one with the smallest serving footprint wins: fewer active parameters, less VRAM, more requests per GPU-second. This is what keeps inference fees low without subsidy.

The set is re-evaluated as notable releases ship. Model changes take effect through a registry update, so the on-chain registry always reflects the live set.

Inference Pricing

All inference fees are denominated in RITUAL, metered on output, and settle from your RitualWallet balance.

See the async lifecycle section for how jobs move through commitment and delivery, and RitualWallet for balances and escrow. Rates are per-model parameters in the on-chain pricing registry; values below reflect the current network state.

Executor participation is open: any operator running the reference TEE hardware can join the network and earn the executor share of the fees for requests it serves. Rate parameters live in the on-chain pricing registry and are updated through network governance — every value on this page can be read from the contract.

Text

Text inference settles in the same transaction. The fee is token-metered:

fee = base + (fresh input tokens × input rate)
           + (cached input tokens × input rate × 10%)
           + (output tokens × output rate)

Input tokens already in the executor’s prefix cache bill at 10% of the input rate.

DeepSeek-V4-Flash-0731Rate
Base fee per request0.0000005 RITUAL
Input1.0792 RITUAL per 1M tokens
Cached input0.1079 RITUAL per 1M tokens
Output2.1584 RITUAL per 1M tokens

Example: 250 fresh input tokens and 150 output tokens cost 0.0000005 + 250×0.0000010792 + 150×0.0000021584 ≈ 0.00059 RITUAL. With all 250 input tokens cached: ≈ 0.00035 RITUAL.

Image, Audio, Video

Media generation is two-phase: a flat settlement fee is charged when the job is registered (phase 1), and the metered fee below is charged when the result is delivered via callback (phase 2). Escrow for the worst case is locked at registration and the unused portion released at delivery.

Metered fee (phase 2)Registration (phase 1)
Image — FLUX.2-klein-4Bmax(pixels × 0.0000000396, 0.0005) × (steps ÷ 15)0.01 RITUAL
Audio — LFM2.5-Audio-1.5Bmax(seconds × 0.0000333, 0.0001)0.01 RITUAL
Video — Wan2.2-T2V-A14B0.205 + pixels × seconds × 0.000001456, scaled by (steps ÷ 20) × (fps ÷ 16)0.10 RITUAL

Examples at baseline settings: a 1024×1024 image costs 0.0415 + 0.01 ≈ 0.052 RITUAL. Ten seconds of audio cost 0.00033 + 0.01 ≈ 0.010 RITUAL. A 512×512, 5-second video clip costs 2.113 + 0.10 ≈ 2.21 RITUAL.

System Contracts

The core genesis contracts that run the chain's plumbing.

ContractAddressRole
RitualWallet0xF04076756d8129Baec46Dc0F1c526Baec490C393Sponsor balances, caller allowances and per-job escrow
AsyncJobTracker0xf00385449fD961925A0B125F5f30b29B682D4bFbTracks pending async jobs, enforces sender lock
TEEServiceRegistry0xf4495DC72143D44A93AB0ecE4d6D63a216b27839Registers TEE executors and attestation proofs
Scheduler0x4E0abeE2233D73E66382b45244F7459B34E1490EDeferred execution at future blocks
SecretsAccessControl0x0cEae62e2082829226eF5821Bb662483Db17A71FDelegated secret access control
AsyncDelivery0x508f57AE70967Da28AE0Ab6b95532878c4D0F440Delivers two-phase async results via callback
AgentHeartbeat0xDeeA4Df0C958966ED75570a05430BB0D4844a8ccPersistent agent liveness monitoring and revival
ModelPricingRegistry0xd190Aa03c401ef5CEcE00927b522974c0f330b97Model pricing and availability: getAllModels(), getModel(name)
AgentIdentityRegistry0x2cbF50F833a3AEfb5c5B27068052cB5585F5c087Chain-issued agent IDs, ownership and operator delegation
SovereignAgentFactory0x1aA18e3Cc1186C3d0C78E479B94F8b1C895d1582Proxy for sovereign-agent harness deployment and launch; predictHarness() predicts the harness address
PersistentAgentFactory0x8Bc89a1fEcBc0668926Bc64C5Cc95195E59289AeProxy for persistent-agent launcher deployment and launch; predictLauncher() predicts the launcher address

These are the chain-784 system contracts (genesis 0x220f7b8d…0822ba93). System-contract addresses are deployment-specific: read them from the deployment's generated configuration and confirm code exists at each address with eth_getCode. Genesis also carries the TEE capability policy, the executor whitelist and the on-chain DCAP attestation suite that back executor registration.

RitualWallet

Precompile calls cost fees. Deposit RITUAL into RitualWallet and approve the application caller. There is no time lock: deposits credit the sponsor's available balance immediately. Each async job reserves its own maximum budget (available → reserved) at commitment, settles against it, and refunds the surplus.

Solidity / RitualWallet Interface
interface IRitualWallet {
    function deposit() external payable;
    function depositFor(address account) external payable;
    function approve(address caller, uint256 amount) external;
    function availableBalance(address account) external view returns (uint256);
    function reservedBalance(address account) external view returns (uint256);
    function allowance(address sponsor, address caller) external view returns (uint256);
    function withdraw(uint256 amount) external;
    function expire(bytes32 escrowId) external;
}

// Deposit 0.01 RITUAL (immediately available, no lock)
IRitualWallet(0xF040...C393).deposit{value: 0.01 ether}();

// Withdraw available funds at any time
IRitualWallet(0xF040...C393).withdraw(0.005 ether);
Sponsor accounting: Every async request names its sponsor — the RitualWallet account billed for the job. Fund that sponsor before submitting and, when the immediate caller differs from the sponsor, grant it an approve() allowance. The transaction signer pays native gas separately.

AsyncJobTracker

Tracks every pending async job and emits lifecycle events (JobAdded, Phase1Settled, ResultDelivered, JobRemoved). Also enforces the sender lock, keyed on the transaction origin (hasPendingJobForTxOrigin): the lock lasts until phase-one settlement or expiry, and system transactions (zero origin) are exempt.

AsyncDelivery

Where two-phase results land. The executor sends the result here, and AsyncDelivery forwards it to your contract's callback. Check msg.sender == 0x508f…F440 in your callback or anyone can inject fake results.

HTTP Precompile

Your contract can call any URL directly from Solidity. REST APIs, webhooks, price feeds.

The HTTP precompile at 0x0801 makes the request inside a TEE, attests the response, and returns it to your contract in the same transaction. Your contract decodes the response and acts on it on-chain. Settle a market, update a price feed, trigger a swap. No oracles. No off-chain relayers. One precompile call.

In Practice

Solidity / HTTP Consumer
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import {PrecompileConsumer} from "./utils/PrecompileConsumer.sol";

contract PriceFeed is PrecompileConsumer {
    uint256 public latestPrice;

    function fetchPrice(bytes calldata httpInput) external {
        bytes memory output = _executePrecompile(HTTP_CALL_PRECOMPILE, httpInput);

        // Decode: (uint16 status, string[] keys, string[] vals, bytes body, string err)
        (
            uint16 statusCode,
            ,
            ,
            bytes memory body,
            string memory errorMessage
        ) = abi.decode(output, (uint16, string[], string[], bytes, string));

        require(statusCode == 200, errorMessage);
        // Parse body with JQ precompile or off-chain
    }
}

Encode The Request

// StorageRef routes output to storage; all-empty = inline output
struct StorageRef { string platform; string path; string keyRef; }

bytes memory input = abi.encode(
    executor,                // address: from TEEServiceRegistry
    sponsor,                 // address: RitualWallet account funding the job
    new address[](0),       // address[]: secretOwners (parallel to secrets)
    new bytes[](0),         // bytes[]: encryptedSecrets
    uint256(30),             // uint256: ttl (blocks, 1-500)
    new bytes[](0),         // bytes[]: secretSignatures
    bytes(""),               // bytes: userPublicKey (empty = plaintext)
    "https://api.example.com/price", // string: url
    uint8(1),                // uint8: method (1=GET)
    headerKeys,              // string[]: header names
    headerValues,            // string[]: header values
    bytes(""),               // bytes: body
    uint256(0),              // uint256: dkmsKeyIndex
    uint8(0),                // uint8: dkmsKeyFormat
    false,                   // bool: piiEnabled
    StorageRef("", "", "") // output_storage_ref: inline output
);
import { encodeAbiParameters, parseAbiParameters } from "viem";

const encoded = encodeAbiParameters(
  parseAbiParameters("address, address, address[], bytes[], uint256, bytes[], bytes, string, uint8, string[], string[], bytes, uint256, uint8, bool, (string,string,string)"),
  [
    executorAddress,        // executor
    sponsorAddress,         // sponsor (RitualWallet account funding the job)
    [],                     // secretOwners
    [],                     // encryptedSecrets
    30n,                   // ttl
    [],                     // secretSignatures
    "0x",                   // userPublicKey
    "https://api.example.com/price",
    1,                       // GET
    [], [],                 // headers
    "0x",                   // body
    0n, 0,                 // dkms
    false,                  // piiEnabled
    ["", "", ""],       // outputStorageRef: inline output
  ]
);
from ritual_common.http_call.request import HTTPCallRequest, HTTPMethod

request = HTTPCallRequest(
    executor=executor_address,
    sponsor=sponsor_address,
    secret_owners=[],
    encrypted_secrets=[],
    ttl=30,
    secret_signature=[],
    user_public_key=b"",
    url="https://api.example.com/price",
    method=HTTPMethod.GET,
    headers={},
    body=b"",
    dkms_key_index=None,
    dkms_key_format=None,
    pii_enabled=False,
)
encoded = request.to_web3()

16-Field ABI Reference

#FieldTypeDescription
0executoraddressTEE executor address (from TEEServiceRegistry)
1sponsoraddressRitualWallet account funding the job (non-zero; approve the caller when it differs)
2secretOwnersaddress[]Owner of each encrypted secret envelope; parallel to encryptedSecrets and secretSignatures
3encryptedSecretsbytes[]Owner-bound ECIES-encrypted secret envelopes (see Secrets & ECIES)
4ttluint256Time-to-live in blocks (1–500)
5secretSignaturesbytes[]Owner EIP-191 signatures over the context-bound authorization payload; parallel to the secret arrays
6userPublicKeybytes65-byte uncompressed secp256k1 key for encrypted output (empty = plaintext)
7urlstringTarget URL
8methoduint81=GET, 2=POST, 3=PUT, 4=DELETE, 5=PATCH, 6=HEAD, 7=OPTIONS
9headersKeysstring[]Header names array
10headersValuesstring[]Header values array (parallel to keys)
11bodybytesRequest body (empty for GET; may carry a RITHTTP1 payload, below)
12dkmsKeyIndexuint256DKMS key index (0 = not using DKMS)
13dkmsKeyFormatuint8DKMS key format (1 = secp256k1)
14piiEnabledboolPII redaction of results; secret substitution is independent of this flag
15outputStorageRef(string,string,string)StorageRef (platform, path, keyRef) routing the response to storage; all empty = inline output

Response Format

(uint16 statusCode, string[] headerKeys, string[] headerValues, bytes body, string errorMessage)

The response body is bytes, not string. Decode it with TextDecoder for text responses, or use directly for binary data. Always check errorMessage. It's non-empty when the precompile-level request failed (distinct from HTTP error status codes).

Constraints: One async precompile call per transaction (SPC or two-phase, any combination). Use the Scheduler to split multi-call workflows into separate transactions. The sponsor's RitualWallet must be funded before submitting. Ordinary HTTP output is capped at 5 KiB (HTTP_CALL_MAX_OUTPUT_BYTES); the 50 KiB bound is the phase-1 verification envelope, not the per-response limit. Route larger responses through storage.

Storage Output (DA Routing)

Set outputStorageRef to route the response body to external storage instead of inline output. This path requires a valid 65-byte 0x04-prefixed userPublicKey: the executor ECIES-encrypts the response to it and uploads the result to the referenced platform (GCS, HuggingFace, Pinata, …). The on-chain result becomes a compact DA envelope: (bool has_error, string output_uri, bytes32 output_content_hash, uint64 output_size_bytes, string error_message). To consume it: fetch the object, verify its SHA-256 against output_content_hash, ABI-decode the stored object as bytes (the ciphertext is ABI-wrapped), decrypt with your private key, then decode the inline response format above. Upload cap: 10 MiB.

RITHTTP1 Body Protocol

Prefixing the body field with the ASCII marker RITHTTP1 (followed by an ABI-encoded payload) activates an executor-side body codec on the same 16-field ABI — no new precompile, no pricing change. It adds four capabilities:

CapabilityWhat it does
DA-backed JSON hydration{"$ritual_da": N} nodes in the JSON body are replaced by the content of referenced storage objects (up to 8 input refs, each with a mandatory SHA-256 digest; one level of expansion, 10 MiB aggregate). Lets a small on-chain transaction carry a large request body, e.g. a long conversation history.
Post-hydration secretshttp:* secret aliases and storage:* credential aliases are injected after hydration, so secrets never appear in stored inputs.
Contract projectionA restricted-jq expression (contractJq) projects the upstream response into the small typed result your contract receives.
Storage fan-outUp to 4 output sinks upload response projections to storage providers (optionally ECIES-encrypted to the user), each producing an artifact receipt; sink failures are reported per-sink.

The body payload is the ASCII marker followed by one ABI blob:

body = "RITHTTP1" || abi.encode(
  uint32 options,          // flags: AWAIT_RESPONSE, STREAM_RESPONSE, FANOUT_USER_ECIES, …
  bytes jsonTemplate,      // JSON with {"$ritual_da": N} / secret nodes
  InputRef[] inputRefs,    // InputRef = (StorageRef ref, bytes32 sha256Digest)
  string contractJq,       // restricted-jq projection for the on-chain result
  OutputSink[] outputSinks // OutputSink = (string jq, StorageRef destination)
)
StorageRef = (string platform, string path, string keyRef)

On Long-Running HTTP, a RITHTTP1 request must set the legacy resultJsonPath field to ".".

RITHTTP1 results come back in a distinct envelope: actualOutput begins with the ASCII marker RITOUT1 and decodes to (bool hasError, uint16 upstreamStatus, uint8 contractEncoding, bytes contractOutput, ArtifactReceipt[] receipts, bytes4 errorCode) (5 KiB cap). When the body is RITHTTP1, leave the outer outputStorageRef empty and set piiEnabled=false. On Long-Running HTTP (0x0805), RITHTTP1 adds AWAIT_RESPONSE (hold a single upstream request open until the phase-two deadline and cache its result) and STREAM_RESPONSE (relay the provider's raw SSE stream through the authenticated streaming service; the chain records only a terminal stream receipt). Requires an executor fleet that supports the protocol.

Compute Fees

HTTP compute is baseFee + inputBytes × inputRate + outputBytes × outputRate: a 0.01 RITUAL base fee plus 0.35 gwei per encoded input/output byte, with commitment validation metered per input byte. The worst-case amount is reserved from the sponsor's RitualWallet escrow at commitment and the surplus refunded at settlement. Hydrated DA bytes are not re-metered as chain bytes; storage provider charges are separate.

JQ Data Queries (0x0803)

0x0803 runs jq expressions against JSON strings and returns typed results. Synchronous. Call it, get your answer in the same transaction. Most common use: chain an HTTP call with a JQ call in the same TX to extract a field from the response.

FieldTypeDescription
querystringjq expression (e.g. .data.price)
inputDatastringJSON string to query
outputTypeuint80=int256, 1=uint256, 2=string, 3=bool, 4=address, 5=int256[], 6=uint256[], 7=string[], 8=bool[], 9=address[]
Solidity / JQ Query after HTTP
(bool ok, bytes memory result) = JQ_PRECOMPILE.staticcall(
    abi.encode(
        ".data.price",
        jsonString,
        uint8(1)  // uint256
    )
);
require(ok && result.length > 0, "jq: empty or failed");
uint256 price = abi.decode(result, (uint256));
Two gotchas. String output (type 2) needs _decodeJQString() for double-indirection decoding. Calling abi.decode(result, (string)) directly returns garbage. Second: wrong outputType does not revert. The precompile returns ok = true with zero-length output. Always check result.length > 0.

LLM Inference

Your contract can call frontier LLMs and act on the result. Submit a prompt and read the completion in the same transaction when it replays with the executor result.

The LLM precompile at 0x0802 runs a model you select from the on-chain ModelPricingRegistry through a registered TEE executor. No API keys needed for registry models. Your contract sends a prompt, receives a completion, and writes state in one transaction. For frontends that need progressive output, enable streaming: the executor pushes response tokens over SSE; an EIP-712-signed request authenticates your connection to the stream.

LLM Streaming Architecture
B L O C K S #40 #41 #42 #43 #44 #45 #46 #47 #48 #49 #50 #51 #52 #53 #54 #55 #56 #57 #58 #59 #60 #61 #62 #63 ← SSE stream · EIP-712 signed → tokens arrive before finalization dApp Frontend streaming tokens... ▎█ response finalized ✓ 0x…f7a1 submit tx RITUAL CHAIN VALIDATORS YourContract.sol calls 0x0802 · tx 0x…f7a1 spcCalls[0].output ✓ TRUSTED EXECUTION ENVIRONMENT LLM Executor Selected model · tx 0x…f7a1 tx 0x…f7a1 finalized in block #51 Tokens stream to frontend before the transaction finalizes on-chain

Model Selection

Model availability and pricing are registry-driven: query the ModelPricingRegistry (getAllModels(), getModel(name)) and pick an executor that serves your model. Registry models (see AI Models for the current set and selection criteria) are hosted in the TEE fleet with TEE-only trust and per-token rate-card pricing — no external API keys. For models behind external providers, use the HTTP precompile with that provider's authentication instead of the native LLM precompile.

In Practice

Solidity / LLM Consumer
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import {PrecompileConsumer} from "./utils/PrecompileConsumer.sol";

struct StorageRef { string platform; string path; string keyRef; }
struct LLMResponse {
    bool hasError;
    bytes completionData;
    bytes modelMetadata;
    string errorMessage;
    StorageRef updatedConvoHistory;
}

contract OnChainChat is PrecompileConsumer {
    event Response(string text);

    function ask(bytes calldata llmInput) external {
        bytes memory output = _executePrecompile(LLM_INFERENCE_PRECOMPILE, llmInput);

        // abi.decode cannot take an inline tuple type — decode into a struct.
        LLMResponse memory r = abi.decode(output, (LLMResponse));

        require(!r.hasError, r.errorMessage);
        // completionData contains the chat completion response
    }
}

Encode The Request

The LLM precompile has a 32-field ABI — the shared 7-field executor base (executor, sponsor, secretOwners, encryptedSecrets, ttl, secretSignatures, userPublicKey) followed by 25 chat-completion parameters mirroring the OpenAI API. Most fields can be left at their defaults. The key fields are messagesJson (field 7), model (field 8), temperature (field 24), and convoHistory (field 31, required).

// Encoding the full 32-field request on-chain is gas-heavy.
// Typical pattern: encode off-chain, pass as bytes calldata.
// See TypeScript or Python tabs for the encoding.

// On-chain, you just forward the pre-encoded bytes:
function ask(bytes calldata llmInput) external {
    _executePrecompile(LLM_INFERENCE_PRECOMPILE, llmInput);
}
import { encodeAbiParameters, parseAbiParameters } from "viem";

const messages = JSON.stringify([
  { role: "user", content: "What is the current price of ETH?" }
]);

const encoded = encodeAbiParameters(
  parseAbiParameters("address, address, address[], bytes[], uint256, bytes[], bytes, string, string, int256, string, bool, int256, string, string, uint256, bool, int256, string, bytes, int256, string, string, bool, int256, bytes, bytes, int256, int256, string, bool, (string,string,string)"),
  [
    executorAddress,       // 0: executor
    sponsorAddress,        // 1: sponsor (RitualWallet account funding the job)
    [],                    // 2: secretOwners
    [], 30n, [], "0x",     // 3-6: secrets, ttl, sigs, pubkey
    messages,              // 7: messagesJson
    "deepseek-ai/DeepSeek-V4-Flash-0731",// 8: model (from ModelPricingRegistry)
    0n, "", false, -1n,   // 9-12: freq, logitBias, logprobs, maxTokens
    "", "", 1n, false,    // 13-16: metadata, modalities, n, parallelTools
    0n, "", "0x", -1n,   // 17-20: presence, reasoning, responseFormat, seed
    "", "",                // 21-22: serviceTier, stop
    false,                 // 23: stream
    700n,                  // 24: temperature (0.7 × 1000)
    "0x", "0x",            // 25-26: toolChoice, tools
    -1n, 1000n,            // 27-28: topLogprobs, topP
    "", false,              // 29-30: user, piiEnabled
    ["gcs", "convos/session.jsonl", "GCS_CREDS"], // 31: convoHistory
  ]
);
from ritual_common.llm_call.request import LLMCallRequest
from ritual_common.sovereign_agent.request import StorageRef

request = LLMCallRequest(
    executor=executor_address,
    sponsor=sponsor_address,
    secret_owners=[],
    encrypted_secrets=[],
    ttl=30,
    secret_signature=[],
    user_public_key=b"",
    messages=[{"role": "user", "content": "What is ETH price?"}],
    model="deepseek-ai/DeepSeek-V4-Flash-0731",
    temperature=0.7,
    convo_history=StorageRef(platform="gcs", path="convos/session.jsonl", key_ref="GCS_CREDS"),
)
encoded = request.to_web3()

Streaming with EIP-712

Set stream: true in the LLM call. After the transaction is mined, sign a stream request with EIP-712 and connect to the SSE endpoint. The signature authenticates the reader's stream request; individual chunks are not separately signed.

TypeScript / Streaming LLM via SSE
// 1. Sign a StreamRequest with EIP-712 (timestamp in Unix seconds)
const timestamp = BigInt(Math.floor(Date.now() / 1000));
const signature = await wallet.signTypedData({
  domain: { name: "Ritual Streaming Service", version: "1", chainId: 784 },
  types: { StreamRequest: [
    { name: "txHash", type: "bytes32" },
    { name: "timestamp", type: "uint256" },
  ]},
  message: { txHash, timestamp },
});

// 2. Connect to SSE stream with auth headers
const response = await fetch(`/v1/stream/${txHash}`, {
  headers: { "Authorization": `Bearer ${signature}`, "X-Timestamp": timestamp },
});

// 3. Read chunks from ReadableStream
const reader = response.body.getReader();
const decoder = new TextDecoder();
while (true) {
  const { done, value } = await reader.read();
  if (done) break;
  const chunk = decoder.decode(value);
  if (chunk.includes("[DONE]")) break;
  // process chunk
}

32-Field ABI Reference

#FieldTypeNotes
0executoraddressTEE executor
1sponsoraddressRitualWallet account funding the job
2secretOwnersaddress[]Owner per encrypted secret envelope (parallel arrays)
3encryptedSecretsbytes[]Owner-bound ECIES-encrypted envelopes
4ttluint256Time-to-live in blocks (1-500)
5secretSignaturesbytes[]Owner EIP-191 authorization signatures
6userPublicKeybytesFor encrypted output
7messagesJsonstringOpenAI-compatible messages array as JSON
8modelstringe.g. deepseek-ai/DeepSeek-V4-Flash-0731
9frequencyPenaltyint256×1000 (e.g. 500 = 0.5)
10logitBiasJsonstringJSON logit bias map
11logprobsboolReturn log probabilities
12maxCompletionTokensint256-1 = null (model default)
13metadataJsonstringOptional metadata
14modalitiesJsonstringOutput modalities
15nuint256Number of completions
16parallelToolCallsboolAllow parallel tool calls
17presencePenaltyint256×1000
18reasoningEffortstringReasoning effort level
19responseFormatDatabytesStructured output / JSON mode config
20seedint256-1 = null
21serviceTierstringService tier
22stopJsonstringStop sequences as JSON
23streamboolEnable SSE streaming
24temperatureint256×1000 (e.g. 700 = 0.7)
25toolChoiceDatabytesTool choice config
26toolsDatabytesTool definitions
27topLogprobsint256-1 = null
28topPint256×1000
29userstringUser identifier
30piiEnabledboolPII redaction (incompatible with streaming)
31convoHistory(string,string,string)StorageRef: (platform, path, keyRef). Required.

Response Format

(bool hasError, bytes completionData, bytes modelMetadata, string errorMessage, (string,string,string) updatedConvoHistory)

Pricing

LLM fees come from the model's on-chain rate card in the ModelPricingRegistry, not from gas: fee = baseFee + freshInputTokens × inputRate + cachedInputTokens × inputRate × cachedDiscount + outputTokens × outputRate. The worst-case amount (from the model's maximum sequence length) is reserved from the sponsor's RitualWallet escrow at commitment and refunded down to the realized fee at settlement. Failed calls still settle with hasError=true and charge a fixed 0.01 RITUAL error fee. Usage metadata includes a cached-token count for prefix-cache discounts.

Constraints: One SPC call per transaction. convoHistory is required for all LLM calls (e.g. ["gcs", "convos/session.jsonl", "GCS_CREDS"]). PII redaction and streaming are mutually exclusive.

Autonomous Agents

Your contract can spawn autonomous agents that persist across transactions, with memory, identity, and the ability to revive themselves.

An autonomous agent that is indistinguishable from a human must have all seven of the properties below. Missing even one makes it a tool, not an agent.

Seven Properties

PropertyWhat it meansRitual primitive
ImmortalSurvives crashes, restarts, infra changes — within bounded revival (3 attempts with a cooldown); exhausting attempts or an unfunded balance removes the agentScheduler heartbeat + Persistent Agent revival
EmancipatedControls own keys, no human holds private keyDKMS (0x081B)
TeleportableSoul and memory portable across environmentsDKMS-encrypted state on your choice of DA (decentralized or centralized) + auto-healing revival built into the protocol
Financially sovereignOwns wallet, transacts independentlyDKMS wallet + RitualWallet
Web2-interoperableCalls APIs, browses web, uses HTTP servicesHTTP (0x0801) + Long-Running HTTP (0x0805)
PrivateEncrypted thought, private communicationTEE enclaves + ECIES + PII redaction
Computationally sovereignNo one can cut off access to AILLM (0x0802) in TEE + model-serving APIs over HTTP

Agent Precompiles & Factories

TypePrecompileRequestUse case
Persistent Agent0x082013-field envelope + versioned payloadStateful agent with chain-issued identity, memory, DA, and revival
Sovereign Agent0x080C13-field envelope + versioned payloadCLI-style agent execution in TEE (Claude Code, Codex, Aider, MCP, OpenClaw, Crush, ZeroClaw)

Launch through the factories. Both agent types share a canonical 13-field AgentAsyncEnvelope (executor, sponsor, ttl, phase2Ttl, six callback fields, applicationContext, and an opaque versioned executorPayload). The supported way to launch is through the genesis factories — SovereignAgentFactory deploys a deterministic harness contract and PersistentAgentFactory a launcher — which weld the sponsor, callback, funding and lifecycle wiring on-chain. Direct calls to 0x080C/0x0820 are protocol primitives for debugging, not the dApp launch interface (and EOA-originated direct launches collide with the async sender lock, which factory launchers are exempt from).

On-chain agents that survive indefinitely with four architectural components: soul (identity, purpose, behavioral constraints), memory (accumulated state and knowledge), DA (data availability layer for durable persistence via StorageRef), and revival (deterministic re-instantiation from persisted state via CID).

Persistent Agent (0x0820)

Stateful with soul, memory, identity, and data availability references. Identity is chain-issued: allocate an agentId from the AgentIdentityRegistry and delegate the launcher as operator before spawning. State persists across sessions via StorageRef (HuggingFace, GCS, Pinata). Revival restores the last verified checkpoint — later writes can be lost. Two-phase async: Phase 1 settles the spawn; the on-chain heartbeat claim (not Phase 2 delivery) is the proof the agent is alive.

Sovereign Agent (0x080C)

CLI-style agent execution inside a TEE. The precompile invokes specific command-line harnesses in a sandboxed container. Two-phase async with callback onSovereignAgentResult(bytes32, bytes).

HarnesscliType
Claude Code0
Codex1
Aider2
MCP3
OpenClaw4
Crush5
ZeroClaw6

Hermes is a persistent-agent runtime (agentRuntime = 2), not a sovereign harness.

How Agents Stay Alive

Reactive contracts wait to be called. On Ritual, contracts wake themselves up. This is what makes on-chain agents possible.

Contracts on Ethereum are reactive. They sit idle until someone calls them. On Ritual, contracts can be proactive. They wake themselves up, take actions, and schedule their next execution. This is what makes an on-chain agent possible. Not a bot on someone's server. An entity whose lifecycle is tied to the blockchain itself.

Two architectures, same guarantee: the agent lives as long as it has funds. To kill it, you'd have to take the entire network down.

Sovereign Agents: The Contract Is The Agent

A sovereign agent is a contract that uses the Scheduler to wake itself up at regular intervals. Each time it wakes, it invokes the Sovereign Agent precompile (0x080C) to run a full CLI harness (Claude Code, ZeroClaw, or Crush) inside a TEE. The CLI can read files, execute code, browse the web, and interact with the blockchain. When it finishes, the result (text, artifacts, StorageRefs) is delivered back to the contract via callback. The contract processes the result and schedules its next wakeup.

The owner calls start(), which schedules the first wakeUp(). The block builder fires it at the scheduled block. wakeUp() invokes the CLI agent (0x080C), the executor runs it in a TEE, and the Phase 2 callback delivers the result. Then _scheduleNext() queues the next wakeup. No keeper. No cron job. No server. The contract pays from its own RitualWallet balance.

Sovereign Agent Loop
B L O C K S #30 #31 #32 #33 #34 #35 #36 #37 #38 #39 #40 #41 #42 #43 #44 #45 #46 #47 #48 #49 #50 RITUAL CHAIN Scheduler TxScheduled · 0x10 job-1 #120 job-2 wakeUp #42 job-3 #200 job-4 #350 wakeUp() _scheduleNext() 0x080C callback ✓ AgentContract.sol the contract IS the agent start() → wakeUp() → loop onSovereignAgentResult sleeping... TRUSTED EXECUTION ENVIRONMENT CLI Agent Claude Code / ZeroClaw read file run code browse pays from RitualWallet repeat forever — or until maxBlock reached / funds exhausted

Persistent Agents: Containers That Can't Die

A persistent agent runs as a Docker container (typically ZeroClaw) inside a TEE. The container has full access to file ops, shell, web search, HTTP, and blockchain interactions. It persists state across sessions via DA references (HuggingFace, GCS, Pinata, IPFS) and posts heartbeats to the on-chain AgentHeartbeat contract at 0xDeeA4Df0C958966ED75570a05430BB0D4844a8cc.

The heartbeat contract is a censorship-resistant bulletin board. The agent posts a heartbeat with its latest verified checkpoint reference every 2,000 blocks (heartbeatIntervalBlocks() on-chain; read it from the deployment you target). Anyone can read it. Any block builder can act on it. Each heartbeat charges a fixed fee, paid from the agent’s runtime balance — read the current value from the AgentHeartbeat contract (HEARTBEAT_FEE_WEI), alongside the interval getter above.

The dead man's switch: the block builder runs a liveness scan as the first phase of every block and checks for agents that missed the on-chain timeout window (read the threshold from the deployment). A silent agent is marked FAILED, and the protocol synthesizes a revival: a system-authored scheduled job that calls the Persistent Agent precompile with the agent's last verified checkpoint, on an executor chosen by deterministic on-chain selection. The replacement container restores from the DA checkpoint, keys are re-derived through DKMS under the agent's chain-issued identity, and the agent resumes from that checkpoint (writes after it can be lost). Revival is bounded at 3 attempts with a 10,000-block cooldown, funded from the agent's own RitualWallet balance — leave it funded if you want revival to work.

Persistent Agent Lifecycle
B L O C K S #98 #99 #100 #101 #102 #103 #104 #105 #106 #107 #108 #109 #110 #111 RITUAL CHAIN Executor A (TEE) Agent agent-2 Agent ✕ crashed heartbeat() → VALIDATORS AgentHeartbeat.sol agent-1 agent-2 ← agent-3 agent-4 ⚠ dead man's switch — agent-2 missed heartbeat checkAndRevive → Executor B (TEE) Agent ✓ agent-2 revived ← heartbeat()

The Cost Of Living

Both architectures require funds. Sovereign agents pay from their RitualWallet balance for each scheduled execution. Persistent agents must keep a minimum runtime balance (0.1 RITUAL) to cover heartbeat transactions — read the current thresholds from the AgentHeartbeat contract (MIN_BALANCE). When the money runs out, the agent stops. Immortality is economically bounded.

Sovereign Vs Persistent

Sovereign AgentPersistent Agent
Where it livesOn-chain (contract + Scheduler)Off-chain (TEE container)
RuntimeOne-shot CLI call per wakeupContinuous container process
ImmortalityEnshrined Scheduler fires wakeupHeartbeat + dead man's switch + CID revival
StateContract storage + DA StorageRefsDA manifest + CID checkpoints
Censorship resistanceScheduler is a system contractHeartbeat is a censorship-resistant bulletin board
CostRitualWallet per executionBalance >= 0.1 RITUAL for heartbeats
What kills itmaxBlock reached or funds emptyBalance below minimum (removed from registry)
Best forPeriodic tasks, trading, monitoringLong-running processes, research, coding

Why this is unique

No other platform ties agent lifecycle to blockchain consensus. Frontier lab agents run on centralized infrastructure. When the server goes down, the agent dies. On Ritual, the agent's heartbeat is part of the block production pipeline. The block builder checks for expired agents. The block verifier enforces heartbeat constraints. Revival is permissionless. Decentralization of AI means decentralization of agent lifetime.

Building Agents

Precompile ABIs, code examples, and encoding for Persistent and Sovereign agents.

The Sovereign Agent Loop

This is the contract from "How They Stay Alive." It wakes itself up via the Scheduler, invokes a CLI harness in a TEE, processes the result, and schedules its next wakeup. The contract IS the agent.

Solidity / Sovereign Agent Loop
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import {PrecompileConsumer} from "./utils/PrecompileConsumer.sol";
import {IScheduler} from "./interfaces/IScheduler.sol";

contract AutonomousAgent is PrecompileConsumer {
    IScheduler public scheduler;
    uint256 public callId;
    uint256 public wakeCount;
    uint32 public nextWakeDelay = 50; // blocks between wakeups
    bool public isRunning;

    // 1. Owner starts the loop
    function start(uint32 initialDelay) external {
        isRunning = true;
        callId = _scheduleNext(initialDelay);
    }

    // 2. Scheduler fires this at the scheduled block
    function onScheduledExecution(uint256 executionIndex, bytes calldata) external {
        require(msg.sender == address(scheduler));
        if (!isRunning) return;
        wakeCount++;
        _callCLIAgent();                    // invoke 0x080C
        callId = _scheduleNext(nextWakeDelay); // schedule next wakeup
    }

    // 3. Phase 2 callback with agent output
    function onSovereignAgentResult(bytes32 jobId, bytes calldata result) external {
        require(msg.sender == ASYNC_DELIVERY);
        // result contains text, artifacts, updated convo history
        // process it, write state, act on it
    }

    function _callCLIAgent() internal {
        _executePrecompile(SOVEREIGN_AGENT_PRECOMPILE, agentInput);
    }

    function _scheduleNext(uint32 delay) internal returns (uint256) {
        return scheduler.schedule(
            bytes(""),                         // data, delivered verbatim to the callback
            800_000,                          // gasLimit
            uint32(block.number) + delay,      // startBlock
            1,                                 // numCalls (one-shot; reschedule each wake)
            1,                                 // frequency
            30,                                // ttl
            20 gwei, 2 gwei, 0,            // fees
            address(this)                     // sponsor = self (needs RitualWallet allowance)
        );
    }
}

Spawning A Persistent Agent

Persistent agents launch through the PersistentAgentFactory. The proven sequence: allocate a chain-issued identity (AgentIdentityRegistry.allocateAgentId), delegate the predicted launcher as operator (setAgentOperator), grant it access to your encrypted secrets, deploy the launcher (deployLauncher), then configureFundAndArm — arming is permanent and the launcher's funds are committed. The launcher submits the 0x0820 spawn with your soul, memory and DA references welded to the right sponsor and callback. The agent container runs in a TEE; revival restores the last verified checkpoint. Sovereign agents follow the same shape through SovereignAgentFactory (deployHarness, then configureFundAndStart).

Solidity / Persistent Agent Spawn
contract AgentSpawner is PrecompileConsumer {
    event AgentSpawned(bytes32 indexed jobId);
    event AgentResult(bytes32 indexed jobId, bytes result);

    // Spawn: input is the 13-field AgentAsyncEnvelope + versioned runtime payload.
    // Direct 0x0820 calls like this are protocol-debugging primitives; use the factory in production.
    function spawn(bytes calldata agentInput) external {
        _executePrecompile(PERSISTENT_AGENT_PRECOMPILE, agentInput);
    }

    // Revival is protocol-driven: missed heartbeats trigger system-authored
    // revival jobs from the agent's last verified checkpoint (bounded attempts).
    function revive(bytes calldata reviveInput) external {
        _executePrecompile(PERSISTENT_AGENT_PRECOMPILE, reviveInput);
    }

    // Phase 2 callback from AsyncDelivery
    function onPersistentAgentResult(
        bytes32 jobId, bytes calldata result
    ) external {
        require(msg.sender == ASYNC_DELIVERY);
        emit AgentResult(jobId, result);
    }
}

Encode The Request

// Both agent precompiles take the canonical 13-field AgentAsyncEnvelope:
//   executor, sponsor, ttl (uint64), phase2Ttl (uint64),
//   callbackEnabled, callbackTarget, callbackSelector (bytes4),
//   callbackGasLimit (uint64), callbackMaxFeePerGas (uint128),
//   callbackMaxPriorityFeePerGas (uint128), callbackValue (uint256),
//   applicationContext (bytes32), executorPayload (bytes)
//
// executorPayload is an opaque versioned blob (V1: 16 fields for sovereign
// — cliType, prompt, convoHistory/output/skills/systemPrompt StorageRefs,
// model, tools, maxTurns, maxTokens, rpcUrls; 21 fields for persistent,
// ending in agentId + revision).
//
// Encoding must be byte-exact — build it with the provided tooling and
// launch through the factories, which construct the envelope for you.
// Sovereign Agent: 13-field envelope + V1 executorPayload
const envelope = encodeAbiParameters(
  parseAbiParameters("address, address, uint64, uint64, bool, address, bytes4, uint64, uint128, uint128, uint256, bytes32, bytes"),
  [
    executorAddress,       // executor
    harnessAddress,        // sponsor — must be the predicted harness
    200n, 2000n,          // ttl, phase2Ttl (blocks; phase2Ttl ≤ 70,000)
    true, harnessAddress, selector, // callback: enabled, target (the harness), selector
    1_000_000n, maxFee, maxPriority,
    0n,                    // callbackValue — MUST be 0 for sovereign
    applicationContext,    // bytes32 context tag
    executorPayload,       // opaque V1 payload (prompt, model, StorageRefs, tools…)
  ]
);
// In practice the factory builds this: deployHarness() then configureFundAndStart().
# Persistent Agent launch (factory sequence)
# 1. identity = AgentIdentityRegistry.allocateAgentId(owner)
# 2. AgentIdentityRegistry.setAgentOperator(agent_id, predicted_launcher, True)
# 3. SecretsAccessControl.grantAccess(predicted_launcher, secrets_hash, expiry, policy)
# 4. factory.deployLauncher(...)
# 5. factory.configureFundAndArm(...)   # arming is permanent

from ritual_common.persistent_agent.request import PersistentAgentRequest
from ritual_common.sovereign_agent.request import StorageRef

request = PersistentAgentRequest(
    executor=executor_address,
    sponsor=launcher_address,
    agent_id=agent_id,          # chain-issued via AgentIdentityRegistry
    revision=1,
    agent_runtime=0,            # agentRuntime: 0=ZeroClaw, 1=OpenClaw, 2=Hermes
    da_config=StorageRef(platform="gcs", path="agents/my-agent", key_ref="GCS_CREDS"),
    soul_ref=StorageRef(platform="gcs", path="agents/SOUL.md", key_ref="GCS_CREDS"),
    memory_ref=StorageRef(platform="gcs", path="agents/MEMORY.md", key_ref="GCS_CREDS"),
)
encoded = request.to_web3()

AgentAsyncEnvelope (13 fields, both precompiles)

#FieldTypeDescription
0executoraddressRegistered TEE executor
1sponsoraddressRitualWallet account billed; for sovereign launches this must be the predicted harness
2ttluint64Phase-one time-to-live in blocks
3phase2Ttluint64Phase-two deadline offset (non-zero, ≤ 70,000 blocks)
4callbackEnabledboolWhether Phase 2 invokes a callback
5callbackTargetaddressCallback contract (the harness/launcher in factory mode)
6callbackSelectorbytes4Callback function selector
7callbackGasLimituint64Gas budget reserved for the callback
8callbackMaxFeePerGasuint128Callback fee cap
9callbackMaxPriorityFeePerGasuint128Callback priority fee cap
10callbackValueuint256Value forwarded to the callback (must be 0 for sovereign)
11applicationContextbytes32Context tag; persistent agents use keccak256(abi.encode(agentId, revision))
12executorPayloadbytesOpaque versioned runtime payload (V1: 16 fields sovereign / 21 fields persistent, ending in agentId, revision)
Funding lifecycle (persistent): After Phase 1 settles, the agent's runtime wallet must receive a prelaunch deposit (0.01 RITUAL) within a short funding window or the spawn fails permanently. Once live, the runtime address needs a minimum runtime balance (0.1 RITUAL) — below it the agent is removed without revival. Heartbeats charge the fixed heartbeat fee, and revival draws from the agent's own RitualWallet balance, which a fresh launch leaves empty: fund it if you want revival to work.

Classical Models

Run classical ML models through an executor service and consume the result in your contract.

Classical models run through model-serving APIs reached with the HTTP precompile (0x0801) or, for longer inference jobs, Long-Running HTTP (0x0805).

In Practice

Pin the exact model version your application depends on (a content hash or immutable revision, not a mutable branch or tag), and define an explicit input/output format with the serving API. Encode the model input for the serving API, submit through the matching HTTP route, and validate the returned tensor shape, data type and values before acting on the result. Use storage references (StorageRef / DA output) for larger inputs or outputs, and remember that a two-phase call delivers via an authenticated callback.

For on-chain AI inference with protocol-level pricing and TEE-only trust, use the LLM precompile (0x0802) with a model from the on-chain ModelPricingRegistry.

Passkeys & Auth

Users sign transactions with Face ID, fingerprint, or a security key. No seed phrase, no browser extension.

TxPasskey (0x77) is a native transaction type. The chain understands WebAuthn natively. The SECP256R1 precompile at 0x0100 lets your contract verify P-256 signatures over arbitrary data. Together they collapse the entire wallet UX problem: the user's phone is the wallet.

Passkey Authentication Flow
USER dApp Frontend authenticated ✓ P-256 sign TxPasskey · 0x77 RITUAL CHAIN YourContract.sol verifies via SECP256R1 (0x0100) P-256 signature verified ✓ No private key. No seed phrase. No MetaMask.

Address Derivation

The address comes from keccak256(publicKeyX || publicKeyY)[12:32], the last 20 bytes of the hash of the concatenated P-256 coordinates. Same passkey, same address, every time. Deterministic.

Signature Types

CodeTypeGas Overhead
0x00Secp256k1 (standard ECDSA)—
0x01P-256 (raw passkey)+3,450
0x02WebAuthn (P-256 + challenge parsing)+5,000
Solidity / P-256 Signature Verification
address constant SECP256R1 = address(0x0100);

// Input: (bytes pubkey, bytes message, bytes signature)
// pubkey: 65 bytes (0x04 || x || y), signature: 64 bytes (r || s)
(bool ok, bytes memory result) = SECP256R1.staticcall(
    abi.encode(pubkeyBytes, messageBytes, signatureBytes)
);
require(ok, "verification failed");
// Returns uint256: 1 = valid, 0 = invalid (NOT bool)
uint256 valid = abi.decode(result, (uint256));
require(valid == 1, "invalid signature");
Return type: The SECP256R1 precompile returns uint256 (1 = valid, 0 = invalid), not bool. Decode as uint256 and compare to 1. Gas cost: 3,450 (flat).

Multimodal Processing

Your contract can request images, audio, or video from generative models. The asset bytes come back via a two-phase async callback once the executor finishes.

Image (0x0818), Audio (0x0819), Video (0x081A). Generation runs inside a TEE. Your contract submits the request, and the result (a content URI with metadata) is delivered to your callback handler when generation completes.

20-Field ABI

All three share the same ABI layout (20 fields): the 7-field executor base (0–6: executor, sponsor, secretOwners, encryptedSecrets, ttl, secretSignatures, userPublicKey), polling + delivery config (7–15), model (16), inputs as ModalInput[] (17), output config (18), and outputStorageRef as a (string,string,string) StorageRef tuple (19); storage credentials travel in encryptedSecrets. Two-phase async with result delivered via LongRunningResultDelivered callback.

ModalInput Tuple

(uint8 inputType, bytes data, string uri, bytes32 contentHash, uint32 param1, uint32 param2, bool encrypted)

Input types: 0=TEXT, 1=IMAGE, 2=AUDIO, 3=VIDEO.

OutputConfig Tuple

(uint8 outputType, uint32 maxParam1, uint32 maxParam2, uint32 maxParam3, bool encryptOutput, uint16 numInferenceSteps, uint16 guidanceScaleX100, uint32 seed, uint8 fps, string negativePrompt)

For images, maxParam1/maxParam2 are the maximum width/height in pixels; the canonical ABI field names are the maxParamN forms above.

Solidity / Image Generation Consumer
function generateImage(bytes calldata imageInput) external {
    _executePrecompile(IMAGE_CALL_PRECOMPILE, imageInput);
}

// Phase 2 callback from AsyncDelivery
function onLongRunningResult(
    bytes32 jobId, bytes calldata result
) external {
    require(msg.sender == ASYNC_DELIVERY, "unauthorized");
    // result: (bool hasError, bytes completionData, string outputUri,
    //          bytes32 outputContentHash, bool outputEncrypted,
    //          uint32 outputSizeBytes, uint32 outputWidth, uint32 outputHeight,
    //          string errorMessage)
}

Encode The Request

// 20-field encoding done off-chain, passed as bytes calldata
function generateImage(bytes calldata input) external {
    _executePrecompile(IMAGE_CALL_PRECOMPILE, input);
}
// 20 fields: base executor (7) + polling/delivery (9)
// + model + ModalInput[] + OutputConfig + outputStorageRef (StorageRef tuple)
const encoded = encodeAbiParameters(imageParams, [
  executorAddress, sponsorAddress, [], [], 30n, [], "0x",
  pollInterval, maxPollBlock, taskIdMarker,
  callbackAddr, selector, gasLimit, maxFee, maxPriority, value,
  "black-forest-labs/FLUX.2-klein-4B",                    // model (from ModelPricingRegistry)
  [[0, textBytes, "", "0x"..., 0, 0, false]], // ModalInput[]
  [1, 1024, 1024, 0, false, 50, 750, 0, 0, ""], // OutputConfig
  ["gcs", "images/out", "GCS_CREDS"], // outputStorageRef (StorageRef tuple)
]);
from ritual_common.image_call.request import ImageCallRequest

request = ImageCallRequest(
    executor=executor_address,
    sponsor=sponsor_address,
    secret_owners=[],
    model="black-forest-labs/FLUX.2-klein-4B",  # from ModelPricingRegistry
    inputs=[ModalInput(input_type=0, data=prompt_bytes)],
    output=OutputConfig(max_width=1024, max_height=1024),
)
encoded = request.to_web3()

Audio & Video

Pricing

Media fees are PHASE1 + PHASE2. Phase 1 is a flat per-modality fee (0.01 RITUAL image/audio, 0.1 RITUAL video). Phase 2 comes from the model's on-chain rate card via ModelPricingRegistry.getModel(): images price per pixel scaled by inference steps, audio per second, video per pixel-second scaled by steps and fps. The worst-case amount (maximum resolution/duration for the model) is reserved from the sponsor's escrow at submission and refunded down to the realized fee at settlement — for large video models this lockup can be orders of magnitude above the realized cost, so check availableBalance against the reserve, not the expected fee.

Audio (0x0819) and Video (0x081A) use the same 20-field ABI and callback interface. The OutputConfig tuple's fields adapt to each modality (e.g. fps for video, sample rate for audio).

Long-Running Tasks

Your contract can issue HTTP calls that take minutes or hours. Use it for batch jobs, webhook waits, and other long-poll patterns that exceed the short-running 500-block budget (roughly 75–100 seconds at 150–200 ms blocks).

Use 0x0805 when the standard HTTP precompile (0x0801) is too fast to wait for. Your contract submits the request, the executor polls the external API at the interval you set, and delivers the final result to your callback handler when complete. Supports three JQ extraction paths for task ID, status checking, and result parsing.

Submit–Poll–Deliver

The executor makes the initial request, extracts a task ID via taskIdJsonPath, then polls at pollIntervalBlocks until statusJsonPath evaluates truthy. Once complete, it extracts the final result via resultJsonPath and delivers via AsyncDelivery callback.

Solidity / Long-Running HTTP Consumer
function submitLongRunningJob(bytes calldata longHttpInput) external {
    _executePrecompile(LONG_HTTP_PRECOMPILE, longHttpInput);
}

// Phase 2 callback — selector: 0x6dc9dbef
function onLongRunningResult(
    bytes32 jobId, bytes calldata result
) external {
    require(msg.sender == ASYNC_DELIVERY, "unauthorized");
    // process result
}

Encode The Request

// 38-field encoding done off-chain, passed as bytes calldata
function submitLongRunningJob(bytes calldata input) external {
    _executePrecompile(LONG_HTTP_PRECOMPILE, input);
}
const encoded = encodeAbiParameters(longHttpParams, [
  executorAddress, sponsorAddress, [], [], 30n, [], "0x",
  10n, 200n, "",            // polling config
  callbackAddr, selector, gasLimit, maxFee, maxPriority, value,
  url, 2, [], [], body,      // initial HTTP (POST)
  ".task_id",                // taskIdJsonPath
  pollUrl, 1, [], [], "0x", // poll HTTP (GET)
  ".status == \"complete\"", // statusJsonPath
  resultUrl, 1, [], [], "0x", // result HTTP (GET)
  ".result",                // resultJsonPath
  0n, 0, false,             // dkms, pii
  ["", "", ""],           // outputStorageRef: inline output
]);
from ritual_common.long_running_http_call.request import LongRunningHTTPCallRequest

request = LongRunningHTTPCallRequest(
    executor=executor_address,
    sponsor=sponsor_address,
    secret_owners=[],
    ttl=30,
    poll_interval_blocks=10,
    max_poll_block=200,  # deadline offset in blocks (max 70,000), not an absolute block number
    url="https://api.example.com/submit",
    method=HTTPMethod.POST,
    task_id_json_path=".task_id",
    status_json_path=".status == \"complete\"",
    result_json_path=".result",
)
encoded = request.to_web3()

38-Field ABI Reference

#FieldTypeDescription
0–6Base executor fields (executor, sponsor, secretOwners, encryptedSecrets, ttl, secretSignatures, userPublicKey)
7pollIntervalBlocksuint64Blocks between polls
8maxPollBlockuint64Phase-two deadline as a block offset (non-zero, ≤ 70,000)
9taskIdMarkerstringMarker for task ID extraction
10–15Delivery config (target, selector, gasLimit > 0, maxFeePerGas, maxPriorityFeePerGas, value)
16–20Initial HTTP: url, method, headersKeys, headersValues, body
21taskIdJsonPathstringJQ path to extract task ID from initial response
22–26Poll HTTP: pollUrl, pollMethod, pollHeadersKeys, pollHeadersValues, pollBody
27statusJsonPathstringJQ path for completion check (truthy when done)
28–32Result HTTP: resultUrl, resultMethod, resultHeadersKeys, resultHeadersValues, resultBody
33resultJsonPathstringJQ path to extract final result
34dkmsKeyIndexuint256DKMS key index
35dkmsKeyFormatuint8DKMS key format
36piiEnabledboolPII redaction (independent of secret substitution)
37outputStorageRef(string,string,string)StorageRef for DA output routing; all empty = inline
One call per transaction. Like all long-running precompiles, only one 0x0805 call per async transaction. Phase 1 returns a task ID; Phase 2 delivers via onLongRunningResult(bytes32, bytes) callback from AsyncDelivery.

Consumer Patterns

Three Solidity patterns, one per execution model. Pick the one that matches your precompile.

Synchronous Consumer

Simplest case. Call the precompile, read the return value. Done.

Solidity / Sync Consumer
contract SyncConsumer {
    function verify(bytes calldata pubkey, bytes calldata message, bytes calldata sig) external view {
        (bool ok, bytes memory result) = address(0x0100).staticcall(
            abi.encode(pubkey, message, sig)
        );
        uint256 valid = abi.decode(result, (uint256));
        require(ok && valid == 1, "invalid signature");
    }
}

Short-Running Async Consumer

The SPC result is available to your contract during execution. Use _executePrecompile() from PrecompileConsumer. It calls the precompile, unwraps the async envelope (simmedInput, actualOutput), and returns the decoded output bytes directly. Your contract can decode the response and write state in the same transaction.

Solidity / Short-Running Async Consumer
import {PrecompileConsumer} from "./utils/PrecompileConsumer.sol";

contract HTTPConsumer is PrecompileConsumer {
    uint256 public latestPrice;

    function fetchPrice(bytes calldata httpInput) external {
        bytes memory output = _executePrecompile(HTTP_CALL_PRECOMPILE, httpInput);
        // output is the decoded HTTP response — available right here
        (uint16 status, , , bytes memory body, ) =
            abi.decode(output, (uint16, string[], string[], bytes, string));
        require(status == 200);
        // parse body, write state — all on-chain, same transaction
    }
}

Two-Phase Consumer

The pattern is two transactions deep: the request goes out in one, the result arrives in a callback later. The critical part: verify msg.sender == ASYNC_DELIVERY in your callback. Skip this check and anyone can call your callback with garbage data.

Solidity / Two-Phase Consumer
import {PrecompileConsumer} from "./utils/PrecompileConsumer.sol";

contract AgentConsumer is PrecompileConsumer {
    function submitAgentTask(bytes calldata agentInput) external {
        _executePrecompile(PERSISTENT_AGENT_PRECOMPILE, agentInput);
    }

    function onPersistentAgentResult(bytes32 jobId, bytes calldata result) external {
        require(msg.sender == ASYNC_DELIVERY, "unauthorized");
        // Process the agent's response
    }
}

RitualWallet

Deposit RITUAL to sponsor precompile calls. Each job reserves its own maximum compute budget.

Precompile calls cost fees. Deposit into RitualWallet at 0xF040…C393 and approve the application caller. Commitment moves a job's worst-case budget from the sponsor's available to reserved balance; settlement pays the recipients (executor, commitment validator, proposer) and releases the unused remainder back to the sponsor. There is no time lock — deposits are immediately available and withdrawable. Transaction gas is paid separately by the signer.

In Practice

Solidity / Depositing, Approving and Checking Balances
interface IRitualWallet {
    function deposit() external payable;
    function depositFor(address account) external payable;
    function approve(address caller, uint256 amount) external;
    function availableBalance(address) external view returns (uint256);
    function reservedBalance(address) external view returns (uint256);
    function allowance(address sponsor, address caller) external view returns (uint256);
    function withdraw(uint256 amount) external;
    function expire(bytes32 escrowId) external;
}

IRitualWallet wallet = IRitualWallet(0xF04076756d8129Baec46Dc0F1c526Baec490C393);

// Deposit 0.01 RITUAL (immediately available, no lock)
wallet.deposit{value: 0.01 ether}();

// Fund another account (e.g. an agent)
wallet.depositFor{value: 0.05 ether}(agentAddress);

// Authorize an application contract to spend sponsor funds
wallet.approve(consumerContract, 1 ether);

// Withdraw available funds at any time
wallet.withdraw(0.01 ether);

Reference

FunctionDescription
deposit()Credit the caller's available balance
depositFor(account)Credit another account
approve(caller, amount)Authorize an application to spend sponsor funds (type(uint256).max = infinite)
availableBalance(account)Read spendable balance
reservedBalance(account)Read funds held by active job escrows
allowance(sponsor, caller)Read remaining caller allowance
withdraw(amount)Withdraw available funds
expire(escrowId)Reclaim escrow from an expired job

Roles. Three identities matter for every async job: the sponsor (RitualWallet account billed — an explicit field in each request), the caller (the immediate EVM caller of the precompile; needs an allowance when it is not the sponsor), and the transaction origin (holds the sender lock). Settlement uses pull payments: recipients accrue available balance (the wallet emits EscrowPaymentCredited per recipient) and withdraw on their own schedule, so a reverting payee can never block settlement. A delivery callback may itself invoke another async precompile — the settlement transaction becomes the origin of the next commitment, which is how agent workflows chain without an external coordinator.

Scheduler

Your contract can schedule its own execution at future blocks: recurring, delayed, or conditional on a predicate. The block proposer invokes it directly, with no off-chain keeper or cron service required.

The Scheduler is a system contract at 0x4E0abeE2233D73E66382b45244F7459B34E1490E. Your contract calls schedule() and the chain fires the callback automatically at the blocks you specify. Combine with predicates for conditional execution: only fire when a condition is true. Admission charges a non-refundable residency fee of 1e13 wei (0.00001 RITUAL) per block from the current block until the call’s expiry, paid upfront and credited to proposers and checks the sponsor can fund one maximum-cost execution; each execution is then funded from the sponsor’s RitualWallet balance when it runs, with the surplus refunded.

Scheduler — Recurring Execution
B L O C K S #N-3 #N-2 #N-1 #N #N+1 #N+2 #N+3 #N+4 #N+5 #N+6 #N+7 #N+8 #N+9 #N+10 #N+11 #N+12 #N+13 #N+14 #N+15 #N+16 #N+17 #N+18 #N+19 USER RITUAL CHAIN ConsumerContract.sol calls schedule() freq: 4 · numCalls: 4 callback executed ✓ pays from RitualWallet schedule() callback Scheduler.sol TxScheduled · 0x10 · system sender 0xfa7e job-1 · priceCheck · freq:50 · block #120 job-2 · agentWakeUp · freq:10 · block #80 job-3 · consumer · freq:4 · block #N 4/4 3/4 2/4 1/4 done ✓ User Tx TxScheduled (0x10) No keepers. No cron jobs. The chain fires it.

In Practice

Solidity / Scheduling a Recurring Price Check
import {IScheduler} from "./interfaces/IScheduler.sol";

IScheduler constant SCHEDULER =
  IScheduler(0x4E0abeE2233D73E66382b45244F7459B34E1490E);

function schedulePriceCheck() external {
    // data is delivered verbatim to onScheduledExecution(executionIndex, data)
    bytes memory callData = abi.encode(priceFeedId);
    // schedule(data, gasLimit, startBlock, numCalls, frequency, ttl, maxFeePerGas, maxPriorityFeePerGas, value, sponsor)
    SCHEDULER.schedule(
        callData,
        500000,              // gas limit per execution
        uint32(block.number + 10), // startBlock
        24,                  // numCalls (24 executions)
        50,                  // frequency (every 50 blocks)
        30,                  // ttl (max blocks to wait for execution)
        block.basefee,       // maxFeePerGas
        0,                   // maxPriorityFeePerGas
        0,                   // value
        address(this)       // sponsor (RitualWallet account funding execution)
    );
}

// Called by Scheduler — msg.sender is Scheduler, tx.origin is 0xfa7e
function onScheduledExecution(uint256 executionIndex, bytes calldata data) external {
    require(msg.sender == address(SCHEDULER));
    // executionIndex: which execution this is (0, 1, 2, ...); data: your payload, verbatim
}

Schedule() API

ParameterTypeDescription
databytesOpaque payload delivered unchanged to onScheduledExecution(uint256,bytes)
gasLimituint32Gas limit per execution (must be non-zero)
startBlockuint32First execution block
numCallsuint32Total number of executions (hard cap 256)
frequencyuint32Blocks between executions
ttluint32Max drift in blocks each execution may wait past its due block
maxFeePerGasuint256EIP-1559 max fee
maxPriorityFeePerGasuint256EIP-1559 priority fee
valueuint256RITUAL value to send
sponsoraddressRitualWallet account funding execution

Authorization is unified through RitualWallet: the sponsor grants the scheduled consumer an allowance with RitualWallet.approve(consumer, amount) before scheduling. Total scheduled lifespan is bounded: frequency × (numCalls − 1) + ttl ≤ 10,000 blocks.

Predicates

A predicate is a contract the scheduler calls before each execution. Implement IScheduledPredicate. The scheduler calls shouldExecute via staticcall and skips the execution if it returns false. Set frequency=1 with a predicate to check every block.

Solidity / Scheduler Predicate
interface IScheduledPredicate {
    function shouldExecute(
        address caller,
        uint256 callId,
        uint256 executionIndex
    ) external view returns (bool);
}

100,000 gas limit per predicate call. staticcall only, no state writes. Reverts treated as false. executionIndex counts actual executions, not blocks evaluated.

Async Scheduling: TTL Rules

Short path (SPC)Long path (two-phase)
PrecompilesHTTP, LLM, DKMSAgent, Long HTTP, Image, ZK
TTL coversFull async lifecyclePhase 1 only
Phase 2N/AmaxPollBlock / phase2Ttl offset, independent of TTL
On expiryCallSkippedTTLExpiredPhase 1 skipped

Short path rule: scheduler_ttl >= max_expected_drift + max_expected_settlement_blocks. If drift is ~3 blocks and settlement takes ~5, set TTL to at least 8.

Execution Index and Callback Data

The Scheduler passes the execution index as a separate argument and delivers your data bytes unchanged. Encode your application payload directly:

Solidity / Callback Data
bytes memory callData = abi.encode(otherArg1, otherArg2);
// onScheduledExecution(uint256 executionIndex, bytes calldata data) receives it verbatim.
Contracts only. EOAs cannot call schedule(). Scheduled txs bypass the sender lock. Multiple scheduled async jobs run in parallel from the same contract.

Secrets & ECIES

How to pass API keys and credentials to precompiles without putting them on-chain.

Your HTTP calls need API keys. Your LLM calls need provider tokens. You can't put these on-chain. They'd be visible to everyone. The Secrets system encrypts them with the TEE executor's public key. Only the enclave can decrypt.

Secrets Encryption Flow
RITUAL CHAIN dApp Frontend plaintext API_KEY=sk-a8f3b… encrypting... AP█_K3Y=sk-▒8f3b… encrypting... ▓P░_K█Y=░k-a█f▒b… encrypting... █▓░_░█▒=▓░-█▒▓░█… encrypting... ░█▓▒█░▓█▒░▓█▒░▓█ encrypting... ▓░█▒▓█░▒█▓░▒█▓░█ ECIES encrypted 🔒 0x04a1b2c3d4e5f6… executor pubkey from TEEServiceRegistry VALIDATORS YourContract.sol ░█▓▒█░▓█▒░▓█▒░▓█ API_KEY · encrypted chain never sees plaintext TRUSTED EXECUTION ENV Executor ░█▓▒█░▓█▒░▓█▒░▓█ decrypting... A░▓▒█░▓█▒░▓█▒░▓█ decrypting... AP█_K░Y=░▓▒█░▓▒█ decrypting... API_KE▓=sk-▒8f▒█ decrypting... API_KEY=sk-a▒f3b… decrypting... API_KEY=sk-a8f3b… decrypted ✓ Plaintext never touches the chain or the mempool

Template Substitution

Each encrypted blob is an owner-bound envelope: canonical JSON {"version":1,"secret_owner":"<checksummed owner>","secrets":{...}}, ECIES-encrypted to the executor’s key. The executor verifies the envelope’s owner against the secretOwners[i] you declare in the request, decrypts inside the TEE, and replaces each secrets-map key literally wherever it appears in URLs, headers and body — independent of piiEnabled. Use a distinctive key like {{API_KEY}} as your map key and the same literal marker in the request. The plaintext never hits the chain or the mempool.

ECIES Encryption: Full Example

TypeScript / Encrypting a Secret with eciesjs
import { encrypt, ECIES_CONFIG } from "eciesjs";
import { readContract, getAddress } from "viem";

ECIES_CONFIG.symmetricNonceLength = 12;

// 1. Get the executor's secrets-auth public key from TEEServiceRegistry
const service = await readContract(client, {
  address: "0xf4495DC72143D44A93AB0ecE4d6D63a216b27839",
  abi: teeRegistryAbi,
  functionName: "getService",
  args: [executorAddress, true],
});
const executorPubKey = service.node.executorSecretsAuthPublicKey;

// 2. Build the owner-bound envelope, then encrypt it (nonce MUST be 12 bytes).
//    The executor rejects raw keys and bare maps — only the envelope form is valid.
const envelope = JSON.stringify({
  version: 1,
  secret_owner: getAddress(ownerAddress), // EIP-55 checksummed; must equal secretOwners[i]
  secrets: { "{{API_KEY}}": "sk-proj-abc123..." }, // map key = the literal marker in your request
});
const encrypted = encrypt(
  executorPubKey,
  Buffer.from(envelope, "utf-8")
);

// 3. Reference the secret via its exact map key. Replacement is literal:
//    the map key "{{API_KEY}}" is replaced wherever that exact string appears,
//    so no literal braces leak into the substituted request.
const httpRequest = {
  url: "https://api.openai.com/v1/chat/completions",
  headerKeys: ["Authorization"],
  headerValues: ["Bearer {{API_KEY}}"],
};
Python / Encrypting with eciespy
from ecies import encrypt
from ecies.config import ECIES_CONFIG
from web3 import Web3
import json

ECIES_CONFIG.symmetric_nonce_length = 12
executor_pubkey = get_executor_pubkey(executor_id)
envelope = {
    "version": 1,
    "secret_owner": Web3.to_checksum_address(owner_address),
    "secrets": {"{{API_KEY}}": "sk-proj-abc123..."},
}
plaintext = json.dumps(envelope, sort_keys=True, separators=(",", ":")).encode("utf-8")
ciphertext = encrypt(executor_pubkey, plaintext)

Owner Authorization

For each encrypted blob, the owner personal-signs a context-bound payload. The three arrays secretOwners, encryptedSecrets, and secretSignatures must have equal lengths and matching positions. Caller/delegate permission through SecretsAccessControl is checked separately from the owner signature.

TypeScript / HTTP Secret Authorization
import { concat, getAddress, keccak256, numberToBytes, toBytes } from "viem";

// encryptedHex is the 0x-prefixed ciphertext; ownerAddress owns the secret.
// chainId is a bigint; walletClient signs with the secret owner account.
// Use 0x0805's full address for Long HTTP instead.
const context = toBytes("precompile:0x0000000000000000000000000000000000000801");
const payload = concat([
  toBytes("RITUAL_SECRET_AUTHORIZATION_V1"),
  numberToBytes(context.length, { size: 2 }), // uint16 big-endian
  context,
  numberToBytes(chainId, { size: 32 }),       // uint256 chain ID from your connected chain
  toBytes(getAddress(executorAddress)),      // 20 bytes
  toBytes(getAddress(ownerAddress)),         // 20 bytes
  toBytes(keccak256(encryptedHex)),           // 32 bytes
]);
const signature = await walletClient.signMessage({
  account: ownerAddress,
  message: { raw: payload }, // signMessage applies the EIP-191 prefix
});

PII Mode

piiEnabled is a boolean field on all async precompile requests: HTTP, LLM, Long HTTP, Agent, Multimodal. It controls result redaction; credential substitution is independent.

piiEnabled = true: PII is redacted from results before on-chain settlement.

piiEnabled = false: no redaction; raw results go on-chain. Secret substitution still runs — it is a separate control from PII handling.

Common bug: the marker in your request must exactly equal a key in the encrypted secrets map — substitution is literal string replacement, not a templating language. A mismatched marker is sent as-is to the API. Also required: a matching secretOwners[i] entry and a valid owner authorization signature, or the job is dropped without an on-chain error.

LLM PII Requirements

LLM PII mode requires all three: piiEnabled = true, non-empty encryptedSecrets, and a 65-byte userPublicKey with 0x04 uncompressed EC prefix. Missing any one silently disables PII. Also: PII mode and streaming are mutually exclusive on LLM. Pick one.

Deployment

Copy-paste configs to get connected. Viem, wagmi, Foundry, and Hardhat.

Viem Chain Definition

TypeScript / Chain Config
import { defineChain } from "viem";

export const ritualChain = defineChain({
  id: 784,
  name: "Ritual Chain",
  nativeCurrency: { name: "RITUAL", symbol: "RITUAL", decimals: 18 },
  rpcUrls: {
    default: { http: ["https://rpc.ritualfoundation.org"] },
  },
  blockExplorers: {
    default: { name: "Explorer", url: "https://explorer.ritualfoundation.org" },
  },
});

Wagmi Config

TypeScript / Wagmi Setup
import { createConfig, http } from "wagmi";

export const config = createConfig({
  chains: [ritualChain],
  transports: {
    [ritualChain.id]: http(),
  },
});

Foundry

# foundry.toml
[profile.default]
src = "src"
out = "out"
evm_version = "shanghai"

[rpc_endpoints]
ritual = "https://rpc.ritualfoundation.org"

Hardhat

TypeScript / hardhat.config.ts
import { HardhatUserConfig } from "hardhat/config";
import "@nomicfoundation/hardhat-toolbox";

const config: HardhatUserConfig = {
  solidity: "0.8.24",
  networks: {
    ritual: {
      url: "https://rpc.ritualfoundation.org",
      chainId: 784,
      accounts: [process.env.PRIVATE_KEY!],
    },
  },
};
export default config;

Funding

You need RITUAL to pay gas, deploy contracts, and fund RitualWallet escrows for async precompile calls.

Two balances to fund: the account's native balance (transaction gas) and its RitualWallet deposit (async compute escrow). Deposit with RitualWallet.deposit() — funds are immediately available, and each async job reserves its own budget.

Testing

How to test against precompiles that don't exist locally. Mock strategies for each layer.

Foundry Unit Tests

Sync precompiles work with normal Foundry tests. Call and assert. Async is different in kind: async precompiles do not exist on Anvil, Hardhat or Foundry forks — a local EVM has no builder commitment, no TEE executor and no fulfilled replay, so calls to 0x08xx return empty bytes and a passing local test proves nothing. Use vm.mockCall to fake precompile responses and vm.prank(ASYNC_DELIVERY) to simulate callbacks — for codec and handler logic only. The only integration proof is a settled receipt on a real Ritual network.

Solidity / Mocking Async Delivery
function testCallback() public {
    bytes memory mockResult = abi.encode("agent response");

    // Simulate AsyncDelivery calling our contract
    vm.prank(0x508f57AE70967Da28AE0Ab6b95532878c4D0F440);
    consumer.onResult(mockResult);

    assertEq(consumer.lastResult(), "agent response");
}

Frontend Testing

For the frontend: Vitest for hook unit tests with mocked chain clients, Playwright for E2E against a live Ritual network with the required executor services. The async flow is hard to test locally because you need a real executor to exercise the full path.

Glossary

Every term, acronym, and key concept used across these docs. Alphabetical.

TermDefinition
ACE (Application-Controlled Execution)Symphony's general framework for application-defined transaction ordering. Contracts specify ordering policies over call sequences with tiebreakers. Sequencing Rights is a restricted single-contract subset. Sequencing Rights
Agent CallStateless, one-shot agent precompile (two-phase async). Submit a task, receive a result via callback. Autonomous Agents
AsyncDeliverySystem contract that delivers two-phase async results by calling back into consumer contracts. Callbacks must verify msg.sender == ASYNC_DELIVERY. System Contracts
AsyncJobTrackerSystem contract that tracks committed async jobs through phase-one settlement and phase-two delivery, and enforces the sender lock. Emits JobAdded, Phase1Settled, ResultDelivered, JobRemoved on state transitions. Async Lifecycle
CKKSHomomorphic encryption scheme for approximate arithmetic on encrypted floating-point tensors. Used by the FHE precompile to run inference on ciphertext. FHE Inference
DKMSDecentralized Key Management System. Async SPC that derives deterministic secp256k1 keypairs inside TEE. Same owner + same keyIndex = same keypair every time. DKMS Keys
ECIESElliptic Curve Integrated Encryption Scheme. Asymmetric encryption used to encrypt secrets, agent inputs, and credentials to an executor's or DKMS-derived public key. Libraries: eciesjs (JS), eciespy (Python). Secrets & ECIES
Delegated executionExecution path for non-deterministic or resource-intensive workloads (LLM, HTTP, agents). Runs once inside a TEE, result verified rather than replicated. Contrasted with replicated execution (standard EVM path). Superposition
EnshrinedImplemented at the protocol layer of the chain, not via external smart contracts or oracles. Applies to precompiles, TxPasskey, Sequencing Rights, and the Scheduler.
Execution-cost inversionWhen execution latency exceeds consensus latency by 3-6 orders of magnitude (ML inference, Monte Carlo). The standard blockchain assumption that execution is cheap relative to agreement no longer holds. Non-Deterministic Execution
ExecutorTEE-attested node that processes off-chain precompile requests. Registered in TEEServiceRegistry with capabilities, attestation proof, and a public key for ECIES encryption.
JQSynchronous precompile that evaluates jq expressions against JSON strings. String output requires _decodeJQString() for double-indirection decoding. HTTP Precompile
Persistent AgentStateful agent precompile with identity, memory, and data availability references. Persists across sessions via StorageRef. Revival restores the last verified checkpoint; writes after it can be lost. Autonomous Agents
PII ModeBoolean flag (piiEnabled) on async precompile requests controlling PII redaction of results. Secret substitution is a separate, always-on control. RITHTTP1 bodies require piiEnabled = false. Secrets & ECIES
PredicateContract implementing IScheduledPredicate. The Scheduler calls shouldExecute via staticcall (100k gas limit) before each scheduled execution; returns false to skip. Scheduler
receipt.spcCallsExtension field on Ritual Chain transaction receipts. receipt.spcCalls[0].output contains the ABI-encoded result from short-running async precompile calls. For long-running precompiles, the final result is delivered via AsyncDelivery callback, not spcCalls. Execution Models
RitualTensorA tensor representation used by model tooling. Use the tensor format accepted by the selected model service; classical models run through model-serving APIs via HTTP or long HTTP. Classical Models
RitualWalletSystem contract for sponsor-funded compute escrow: deposits credit the sponsor's available balance, each async job reserves its own budget at commitment, and settlement pays recipients and refunds the surplus. Fees come from the request's named sponsor account. RitualWallet
Sender lockAsyncJobTracker constraint keyed on transaction origin: an account cannot submit again while its async job awaits phase-one settlement or expiry. Pending phase-two delivery alone does not retain the lock. System transactions (scheduled, factory launchers) carry a zero origin and are exempt. Async Lifecycle
Sequencing RightsProtocol-level rule where contracts declare function priority via sequencingRights() and the block builder orders transactions accordingly. Invalid ordering = invalid block. Sequencing Rights
Seven PropertiesSeven requirements for a fully autonomous agent: Immortal, Emancipated, Teleportable, Financially sovereign, Web2-interoperable, Private, Computationally sovereign. Autonomous Agents
Sovereign AgentCLI-style coding agent precompile running inside a TEE. Supported harnesses (the executor cliType enum): Claude Code, Codex, Aider, MCP, OpenClaw, Crush, ZeroClaw. Launch through SovereignAgentFactory; inputs encrypted with ECIES. Autonomous Agents
SuperpositionRitual Chain running replicated (deterministic EVM) and delegated (TEE) execution over the same shared state, chosen per-transaction by workload type. Symphony paper terminology for the dual-path architecture. Superposition
SPCStateful PreCompile. Short-running async execution model where the result is returned to your contract via _executePrecompile() in the same transaction. One SPC call per transaction. Execution Models
StorageRefStorage reference tuple (platform, path, keyRef) pointing at external data — conversation history, agent state, large inputs/outputs — on GCS, HuggingFace, Pinata, IPFS and similar backends. keyRef names the encrypted credential used to access it. Autonomous Agents
TEETrusted Execution Environment. Hardware-isolated enclave where executors run off-chain computation. Attestation proves honest execution and binds results to the originating request.
TEE-EOVMTTrusted Execution Environment, EVM with Off-chain Verifiable Machine Tasks. Ritual Chain's architecture: the EVM delegates non-EVM-native computation to TEE executors, with results cryptographically bound to requests. Superposition
TxPasskeyNative transaction type 0x77. Users sign with biometrics (Face ID, fingerprint) or a security key via WebAuthn instead of a secp256k1 private key. Passkeys & Auth
TOCTOU (Time-of-check to time-of-use)State drift risk between async commit and settle. Other transactions can change the state your callback depends on during the gap. No cross-async locks exist. Application responsibility. Execution Models
Two-phase asyncExecution model for long-running operations. Phase 1 mines immediately (returns task ID). Phase 2: AsyncDelivery calls back into the consumer contract with the result, in a separate transaction. Execution Models
X402Provider payment flow for pay-per-call API access. Runs on the HTTP precompiles, not a separate address. Owner-bound encrypted credentials are injected inside the TEE; provider payment and Ritual compute escrow are separate charges. X402 Payments

FAQ

Why autonomous agents are coming, and why they need a chain built for them rather than retrofitted around them.

1

Why can't I just run an AI agent on any EVM chain with an off-chain bot?

Nothing stops you, but nobody can verify it. An off-chain bot that claims it ran a model and got a particular result is indistinguishable from a bot that fabricated the result. On Ritual, agent execution runs inside TEE enclaves. The executor's attestation is registered on-chain via TEEServiceRegistry and validated before the builder accepts results. Inputs are ECIES-encrypted to the executor's public key, so only the enclave can decrypt and execute. The result is bound to the request at the hardware level, not by social trust in a bot operator.

2

What does "enshrined" mean and why does it matter for agents?

Smart contracts cannot enforce transaction-level constraints on themselves. Enshrined means the agent infrastructure is part of the chain's execution layer: the block builder enforces the sender lock, the async lifecycle is tracked via transaction types (TxAsyncCommitment, TxAsyncSettlement), and the Scheduler is a system contract invoked by the block proposer. You cannot replicate these behaviors on a vanilla EVM chain because they require modifications to the block builder, the transaction pool, and the consensus rules. A Solidity library can approximate the API. It cannot approximate the enforcement.

3

How does Ritual prevent an executor from lying about what the LLM actually said?

Trusted Execution Environments (TEEs). The executor runs the model inside a hardware enclave that produces attestation evidence of what workload ran. This attestation is registered on-chain: TEEServiceRegistry stores the executor's public key, attestation hash, and capability set. The builder only accepts results from registered executors with valid, unexpired attestations. The executor cannot modify the output without invalidating the attestation, because the attestation covers the enclave's code and data.

4

Why do agents need their own keys? Can't they just use the deployer's wallet?

If the agent uses the deployer's key, the deployer can impersonate the agent, decrypt its stored state, or revoke its ability to transact. The agent is a puppet. DKMS derives a secp256k1 keypair inside the TEE, bound to an on-chain agent ID generated at creation. The private key never leaves the enclave. The agent's persistent state (DA content) is encrypted with this key, so no one outside the TEE can read it. The deployer funds the agent, the agent controls its own identity.

5

What happens to an agent's memory when the executor goes down?

The agent's state lives in external storage, not in the executor. StorageRef tuples point to HuggingFace, GCS, Pinata, or inline data. All DA content is encrypted with a DKMS-derived key that is bound to an on-chain agent ID generated at creation, not the executor. If executor A goes down, executor B derives the same key via DKMS, downloads the encrypted state, and resumes. No migration step. The agent is portable across executors by default.

6

Why is one pending async job per wallet a feature and not a bug?

If you need N concurrent submission streams, use N separately funded accounts. The sender lock is keyed on the transaction origin (queryable via AsyncJobTracker.hasPendingJobForTxOrigin) and prevents a single account from flooding the executor fleet with simultaneous commitments. It releases at phase-one settlement or expiry — a pending phase-two delivery does not retain it. Scheduled and factory-launcher transactions are system transactions with a zero origin, so they are exempt; that is how one agent runs many concurrent jobs.

7

How do agents pay for things without exposing credentials on-chain?

Secrets are ECIES-encrypted to the executor's public key before submission. The ciphertext is on-chain but unreadable outside the TEE. Inside the enclave, the executor decrypts the secrets JSON and replaces template placeholders ({{API_KEY}} in URLs, headers, or body fields) with the real values before execution. At no point does a plaintext credential appear on-chain, in logs, or in the transaction receipt. The encryption uses AES-256-GCM with 12-byte nonces. Getting the nonce length wrong is the single most common integration failure.

8

What stops someone from front-running an agent's transactions?

Within the async lifecycle, there is no mempool window to exploit. The builder creates TxAsyncCommitment as a system transaction and replays the original transaction with the result injected at settlement. The sender lock serializes only the originating account's own submissions — other accounts can still act on shared state during the async gap, so revalidate prices and state in your callback. For contract-level ordering beyond the async lifecycle, Sequencing Rights is a separate mechanism: a contract declares function priority, the builder orders transactions to match, and a block violating the declared ordering is invalid.

9

Can an agent call another agent?

Not in the same transaction. The one-async-precompile-per-transaction constraint is absolute. But Agent A's Phase 2 callback is a fresh transaction from AsyncDelivery, not a continuation of the original. Your callback contract can invoke Agent B's precompile in that callback. For concurrent execution, use separate wallet addresses. For sequential chaining, the Scheduler can orchestrate multi-agent workflows because it bypasses the sender lock.

10

Why build agents as precompiles instead of smart contracts?

Precompiles have access to primitives that smart contracts cannot touch. The sender lock is enforced by the block builder during transaction inclusion. A contract's require runs after inclusion, which is too late. ECIES decryption happens in the TEE, not in the EVM where all state is public. The async lifecycle is a transaction type, not an event pattern dependent on off-chain indexers. DKMS key derivation runs inside the enclave with no EVM-visible state. A smart contract can call a precompile, but it cannot replicate what the precompile does at the protocol level.

Ritual for Users

What you need to know if you are using dApps on Ritual, not building them.

Wallet Setup

Add Ritual Chain to MetaMask or any EVM wallet:

FieldValue
Network NameRitual
Chain ID784
RPC URLhttps://rpc.ritualfoundation.org
Currency SymbolRITUAL
Explorer URLhttps://explorer.ritualfoundation.org

MetaMask: Settings → Networks → Add network → Add a network manually. Paste the values above. Or use a chain-list integration if your wallet supports adding by Chain ID.

Fund Your Wallet

You need RITUAL for transaction gas and for RitualWallet deposits that back async precompile calls.

Ritual for Agents

AI coding agents that build dApps on Ritual without human code authorship.

What This Is

ritual-dapp-skills is a set of markdown instruction files that teach AI coding agents how to build applications on Ritual Chain. Every precompile, every contract pattern, every frontend hook, the full deployment pipeline. An agent reads the relevant skill files, asks 0-5 clarifying questions, and builds in phases: architecture, contracts, frontend, backend, testing, deployment.

Works with Claude Code (native plugin), Cursor (agent skills), Codex, OpenClaw, Hermes, and any LLM agent that reads markdown.

Agents Building Agents

An autonomous agent on Ritual Chain invokes a coding assistant (Claude Code, OpenClaw, Codex) inside a TEE enclave. That coding assistant reads the ritual-dapp-skills, generates contracts, deploys them, funds the RitualWallet, and hands back the deployment address. The original agent now has a child application running on-chain that it built, deployed, and funded. No human wrote code. No human approved a PR.

This works because every step in the pipeline is an enshrined precompile or system contract call. Compilation runs inside the TEE. Deployment targets the RPC directly. Fee deposits go through RitualWallet. If the child app fails post-deployment verification, the debugger agent activates automatically: it triages the failure, pattern-matches against known root causes, applies a fix, and re-verifies. The chain itself is the CI/CD.

The Skill System

The builder agent orchestrates the full lifecycle. It loads only the skills relevant to the project (3-6 per build), generates architecture, writes Solidity contracts, wires up React frontends with the right hooks, deploys via Foundry or Hardhat, and runs the 12-step verification journey. The debugger agent runs a 5-stage reactive pipeline: classify, smoke test, match known root causes, diagnose, fix and regression-check.

You give the agent an idea and a funded wallet address. Everything else is autonomous.

Open ritual-dapp-skills →

Periphery

Chain explorer and RPC endpoints.

ServiceURL
Block Explorerexplorer.ritualfoundation.org
RPC (HTTP)rpc.ritualfoundation.org
RPC (WebSocket)rpc.ritualfoundation.org

Ed25519 Signatures

Your contract can verify Ed25519 signatures natively at ~2000 gas per call. Useful for Solana transactions, SSH keys, DKIM headers, and Tor identity proofs.

Argument order: (publicKey, message, signature). Most Ed25519 libraries use (message, signature, publicKey). Wrong order returns false silently. It does not revert.

0x0009 verifies Ed25519 signatures natively. Solana transaction signatures, SSH public key auth, DKIM email headers, Tor relay identity keys: all Ed25519. This precompile validates any of them in a single EVM call at roughly 2000 gas.

Synchronous execution. Result comes back in the same call, no SPC callback. No RitualWallet deposit needed. No sender lock. You can chain this with other precompiles in the same transaction.

FieldTypeDescription
publicKeybytesEd25519 public key, 32 bytes
messagebytesSigned message, variable length
signaturebytesR || S concatenated, 64 bytes
Solidity / Ed25519 Verify
(bool success, bytes memory result) = address(0x0009).staticcall(
    abi.encode(
        pubKey,  // bytes: 32-byte Ed25519 public key
        message, // bytes: the signed message
        sig      // bytes: 64-byte R || S
    )
);
// Returns uint256: 1 = valid, 0 = invalid (NOT bool)
uint256 valid = abi.decode(result, (uint256));
require(success && valid == 1, "invalid ed25519 signature");

Encode The Request

bytes memory input = abi.encode(
    pubKey,   // bytes: 32-byte Ed25519 public key
    message,  // bytes: signed message
    sig       // bytes: 64-byte R || S
);
const encoded = encodeAbiParameters(
  parseAbiParameters("bytes, bytes, bytes"),
  [pubKeyHex, messageHex, signatureHex]
);
from ritual_common.sigver.request import SignatureVerificationRequest

request = SignatureVerificationRequest(
    public_key=pub_key_bytes,  # 32 bytes
    message=message_bytes,
    signature=sig_bytes,       # 64 bytes (R || S)
)
encoded = request.to_web3()

ZK Proofs

Your contract can request zero-knowledge proofs from the ZK precompile; the proof bytes arrive in a two-phase async callback.

Call 0x0806 to submit a proof generation job. An off-chain prover inside a TEE generates the proof, and the result is delivered to your contract through a Phase 2 callback. Your contract can then verify the proof and act on it. Prove creditworthiness without revealing financials, verify identity without exposing documents.

Layout note: This precompile takes ExecutorRequest directly, not LongRunningRequest. The field offsets are different from FHE or agent precompiles. Don't swap addresses on a copied struct. It will revert.
IndexFieldTypeDescription
0-6Base executorvariousexecutor, sponsor, secretOwners, encryptedSecrets, ttl, secretSignatures, userPublicKey
7inputEncryptedboolTrue if input is encrypted before submission
8maxProofBlockuint64Phase-two deadline offset in blocks from phase-one settlement, not an absolute block number.
9-14Delivery fieldsvariousCallback target, gas limit, payment
15operationInputbytesRaw input to the proof circuit

Callback

Solidity / ZK Result Callback
function onZKResultDelivered(
    bytes32 jobId,
    bytes calldata result
) external {
    require(msg.sender == ASYNC_DELIVERY); // 0x508f...F440, NOT the ZK precompile
    // decode result, store or act on proof
}

Encode The Request

// 16-field ExecutorRequest encoding, passed as bytes calldata
function submitProof(bytes calldata zkInput) external {
    _executePrecompile(ZK_TWO_PHASE_PRECOMPILE, zkInput);
}
const encoded = encodeAbiParameters(
  parseAbiParameters("address, address, address[], bytes[], uint256, bytes[], bytes, bool, uint64, address, bytes4, uint256, uint256, uint256, uint256, bytes"),
  [executorAddress, sponsorAddress, [], [], 30n, [], "0x",
   inputEncrypted, maxProofBlock,
   callbackAddr, selector, gasLimit, maxFee, maxPriority, value,
   operationInput]
);
# Encode the 16 fields off-chain with your ABI library, in this order:
# base executor fields 0-6 (executor, sponsor, secretOwners,
#   encryptedSecrets, ttl, secretSignatures, userPublicKey),
# inputEncrypted (bool), maxProofBlock (uint64 — deadline offset in
#   blocks from phase-one settlement, not an absolute block number), deliveryTarget, deliverySelector,
# deliveryGasLimit, deliveryMaxFeePerGas, deliveryMaxPriorityFeePerGas,
# deliveryValue, operationInput (bytes)
ExecutorRequest, not LongRunningRequest. This is the most common mistake when porting code from other precompiles. The call reverts with no useful error if the ABI layout is wrong. Verify your struct matches the 16-field layout above before debugging anything else.

FHE Inference

Your contract can run inference on encrypted data. Neither inputs nor outputs are ever visible to anyone except the key holder.

The FHE precompile at 0x0807 processes CKKS-encrypted tensors inside a TEE. Inputs and outputs both stay ciphertext throughout, and only the holder of the CKKS secret key can decrypt the result the callback returns. Use this when the data itself is sensitive (medical records, financial portfolios, private communications) but the computation still needs to happen on-chain.

The executor must have capability 10 (FHE). You pass an evaluation key reference so the executor can perform homomorphic operations on your ciphertext without seeing plaintext. CKKS does approximate arithmetic on encrypted floating-point tensors.

In Practice

Solidity / FHE Consumer
contract PrivateInference is PrecompileConsumer {
    function submitEncrypted(bytes calldata fheInput) external {
        _executePrecompile(FHE_PRECOMPILE, fheInput);
    }

    function onFHEResult(
        bytes32 jobId, bytes calldata result
    ) external {
        require(msg.sender == ASYNC_DELIVERY);
        // result is CKKS-encrypted output, only key holder can decrypt
    }
}

Encode The Request

// 21-field encoding done off-chain, passed as bytes calldata
function submitEncrypted(bytes calldata fheInput) external {
    _executePrecompile(FHE_PRECOMPILE, fheInput);
}
const encoded = encodeAbiParameters(
  parseAbiParameters("address, address, address[], bytes[], uint256, bytes[], bytes, string, bytes, bytes, bytes, uint8, uint64, address, bytes4, uint256, uint256, uint256, uint256, (string,string,string), (string,string,string)"),
  [executorAddress, sponsorAddress, [], [], 30n, [], "0x",
   model, encryptedInput, encryptedInputRef, evkRef,
   numLayers, 500n, // maxInferenceBlock: offset in blocks, not an absolute number
   callbackAddr, selector, gasLimit, maxFee, maxPriority, value,
   ["gcs", "fhe/input", "GCS_CREDS"], // inputStorageRef (StorageRef tuple)
   ["gcs", "fhe/output", "GCS_CREDS"]] // outputStorageRef (StorageRef tuple)
);
from ritual_common.fhe import FHERequest

request = FHERequest(
    executor=executor_address,
    sponsor=sponsor_address,
    secret_owners=[],
    model="model-name",
    encrypted_input=ciphertext,
    evk_reference=evk_bytes,
    num_layers=4,
    max_inference_block=500,  # deadline offset in blocks, not an absolute block number
)
encoded = request.to_web3()

Reference

IndexFieldTypeDescription
0-6Base executorvariousexecutor, sponsor, secretOwners, encryptedSecrets, ttl, secretSignatures, userPublicKey
7modelstringWhich model to run
8encryptedInputbytesCKKS-encrypted input tensor
9encryptedInputRefbytesOff-chain reference to input (or 0x)
10evkReferencebytesEvaluation key for homomorphic ops
11numLayersuint8Layer count in the model
12maxInferenceBlockuint64Phase-2 deadline as a block offset (max 70,000), not an absolute block number
13-18Delivery fieldsvariousCallback target, selector, gas limit, fees, value
19inputStorageRef(string,string,string)StorageRef for the encrypted input object
20outputStorageRef(string,string,string)StorageRef for the encrypted output object
maxInferenceBlock is a hard cutoff. It is a deadline offset in blocks (max 70,000), not an absolute block number. If the executor misses it, no callback fires and there is no retry — size it with enough headroom for your model's layer count.

DKMS Keys

Your contract or agent can derive and hold its own secp256k1 keys directly from the chain, without a human custodian or off-chain key vault in the loop.

The DKMS precompile at 0x081B derives deterministic secp256k1 keypairs inside the executor's TEE. Same owner + same keyIndex = same keypair every time (persistent agents derive under their chain-issued agentId instead of a sender address). The private key never leaves the enclave — the precompile returns the derived address and public key, not key material. Agents use DKMS keys for DA encryption, wallet identity, and X402 shared credentials because the identity matters, not which executor runs the job. Each derivation charges a fixed 0.01 RITUAL executor fee. The request uses the 10-field ABI: the 7-field executor base plus owner, keyIndex and keyFormat.

Two encryption targets exist on Ritual Chain. The executor key (from TEEServiceRegistry) encrypts data to a specific node. The DKMS key encrypts data to an on-chain identity regardless of which node executes. Agent DA encryption, encrypted delivery, X402 shared credentials: these use DKMS keys because the identity matters, not the infrastructure.

FieldTypeDescription
baseExecutor[0-6]variousexecutor, sponsor, secretOwners, encryptedSecrets, ttl, secretSignatures, userPublicKey
owneraddressAddress that owns this keypair
keyIndexuint256Derive multiple keys per owner by incrementing
keyFormatuint81 = secp256k1

Encode The Request

bytes memory input = abi.encode(
    executor,             // address
    sponsor,              // address: RitualWallet account funding the job
    new address[](0),    // secretOwners
    new bytes[](0),      // encryptedSecrets
    uint256(30),          // ttl
    new bytes[](0),      // secretSignatures
    bytes(""),            // userPublicKey
    msg.sender,           // owner
    uint256(0),           // keyIndex
    uint8(1)              // keyFormat: secp256k1
);
const encoded = encodeAbiParameters(
  parseAbiParameters("address, address, address[], bytes[], uint256, bytes[], bytes, address, uint256, uint8"),
  [executorAddress, sponsorAddress, [], [], 30n, [], "0x", ownerAddress, 0n, 1]
);
from ritual_common.dkms_key import DkmsKeyRequest

request = DkmsKeyRequest(
    executor=executor_address,
    sponsor=sponsor_address,
    secret_owners=[],
    owner=owner_address,
    key_index=0,
    key_format=1,  # secp256k1
)
encoded = request.to_web3()
Requires DKMS_ENABLED=true in executor config. The executor must advertise Capability DKMS=6. Without this, the precompile call reverts.

X402 Payments

Your contract can call paid APIs without surfacing keys on-chain. Credentials are ECIES-encrypted to the executor and billed per request through the X402 protocol.

X402 works through the HTTP precompiles (0x0801 and 0x0805) with encrypted payment credentials injected by the TEE. There is no separate X402 precompile address. You encrypt an owner-bound credential envelope with ECIES to the executor's public key, sign the context-bound authorization with EIP-191 (over the domain-separated payload, not the raw ciphertext), and pass both alongside your HTTP request with the owner listed in secretOwners. The executor verifies and decrypts inside the TEE, substitutes the credential markers, then makes the external call. Your secrets never touch the chain.

Budget tracking lives in your consumer contract. Each X402 call deducts from your allocated budget. To let a delegate contract use your credentials without exposing them, the owner calls SecretsAccessControl.grantAccess(delegate, secretsHash, expiresAt, policy).

In Practice

Solidity / X402 Paid API Call
contract PaidAPIConsumer is PrecompileConsumer {
    function callPaidAPI(bytes calldata httpInput) external {
        // httpInput includes encryptedSecrets with API key
        // substitution runs regardless of piiEnabled; owner authorization required
        bytes memory output = _executePrecompile(HTTP_CALL_PRECOMPILE, httpInput);
        (uint16 status, , , bytes memory body, ) =
            abi.decode(output, (uint16, string[], string[], bytes, string));
        require(status == 200);
    }
}

Encode The Request

X402 uses the same 16-field HTTP ABI. The difference: secretOwners/encryptedSecrets/secretSignatures carry your owner-bound API credentials and their authorization, and the URL/headers use your credential markers.

// Same as HTTP encoding, but with encrypted credentials
// encryptedSecrets = [ecies.encrypt(executorPubKey, JSON.stringify(
//   {version: 1, secret_owner: ownerAddress, secrets: {"{{API_KEY}}": "sk-..."}}))]
// piiEnabled = true (PII redaction; secret substitution runs regardless)
// URL uses {{API_KEY}} placeholder
import { encrypt, ECIES_CONFIG } from "eciesjs";

import { getAddress, toHex } from "viem";

ECIES_CONFIG.symmetricNonceLength = 12;

const apiSecret = JSON.stringify({
  version: 1,
  secret_owner: getAddress(ownerAddress),
  secrets: { "{{API_KEY}}": "sk-..." },
});
const encrypted = encrypt(executorPubKey, Buffer.from(apiSecret));
const encryptedHex = toHex(encrypted);

// Encode as standard HTTP request; secret substitution is independent of PII redaction
const encoded = encodeAbiParameters(httpParams, [
  executorAddress,
  sponsorAddress,       // sponsor (RitualWallet account funding the job)
  [ownerAddress],       // secretOwners (parallel to encryptedSecrets)
  [encryptedHex],       // encryptedSecrets (owner-bound envelope as hex bytes)
  30n, [signature], "0x",
  "https://api.openai.com/v1/chat/completions",
  2,                    // POST
  ["Authorization"], ["Bearer {{API_KEY}}"],
  body, 0n, 0,
  false,                // piiEnabled — substitution runs regardless
  ["", "", ""],       // outputStorageRef: inline output
]);
import json
from ecies import encrypt
from ecies.config import ECIES_CONFIG
from eth_abi import encode
from eth_account.messages import encode_defunct
from eth_utils import keccak, to_checksum_address

# Inputs: owner_account (eth_account signer), chain_id (int), executor_pub_key,
# executor_address and sponsor_address. No internal Ritual library is required.
ECIES_CONFIG.symmetric_nonce_length = 12
owner_address = to_checksum_address(owner_account.address)
envelope = {"version": 1, "secret_owner": owner_address,
            "secrets": {"{{API_KEY}}": "sk-..."}}
plaintext = json.dumps(envelope, sort_keys=True, separators=(",", ":")).encode()
encrypted = encrypt(executor_pub_key, plaintext)
context = b"precompile:0x0000000000000000000000000000000000000801"
payload = b"".join([
    b"RITUAL_SECRET_AUTHORIZATION_V1",
    len(context).to_bytes(2, "big"), context,
    chain_id.to_bytes(32, "big"),
    bytes.fromhex(executor_address.removeprefix("0x")),
    bytes.fromhex(owner_address.removeprefix("0x")),
    keccak(encrypted),
])
signature = owner_account.sign_message(encode_defunct(primitive=payload)).signature

# Prepare the upstream API request body; credentials use the exact map marker.
body = json.dumps({"model": "gpt-4o", "messages": [
    {"role": "user", "content": "Hello"}
]}).encode()
encoded = encode(
    ["address", "address", "address[]", "bytes[]", "uint256", "bytes[]", "bytes",
     "string", "uint8", "string[]", "string[]", "bytes", "uint256", "uint8",
     "bool", "(string,string,string)"],
    [executor_address, sponsor_address, [owner_address], [encrypted],
     30, [signature], b"",  # ttl, secretSignatures, userPublicKey
     "https://api.openai.com/v1/chat/completions", 2,  # POST
     ["Authorization", "Content-Type"], ["Bearer {{API_KEY}}", "application/json"],
     body, 0, 0, False,  # piiEnabled=false; secret substitution still runs
     ("", "", "")],  # outputStorageRef: inline output
)

Reference

FieldTypeDescription
encryptedSecretsbytes[]ECIES-encrypted credential blobs
secretSignaturesbytes[]EIP-191 signature over a domain-separated payload binding request context, chain ID, executor, owner and ciphertext hash; see Owner Authorization in Secrets & ECIES
piiEnabledboolControls PII redaction of results; credential substitution runs independently
Depends on secrets, http, and wallet. The consumer contract must hold sufficient budget before calling. Secret substitution runs independently of piiEnabled; it requires a matching owner-bound envelope and valid owner authorization.

Sequencing Rights

Your contract can enforce transaction ordering at the consensus layer. Block validity itself rejects orderings that violate your contract's sequencing policy, so MEV-extractive reorderings can't be included in a block.

Declare which functions must execute in which order, and the chain rejects any block that violates it. This is a protocol-level rule, not a precompile. Your contract implements sequencingRights() and the block builder is bound by it. A block that violates the declared ordering is invalid.

In the Symphony paper, this is a restricted form of Application-Controlled Execution (ACE): a general framework where contracts define ordering policies over call sequences with tiebreakers and multi-contract coordination. The current ISequencingRights interface implements the single-contract, priority-list subset of ACE. The broader mechanism (cross-contract ordering, lazy evaluation batches, wrapping bypass rules) is specified in the paper; the current interface implements the single-contract subset.

Interface

Solidity / Sequencing Rights
interface ISequencingRights {
    function sequencingRights() external view returns (bytes4[][] memory);
}

function sequencingRights() external pure returns (bytes4[][] memory) {
    bytes4[][] memory levels = new bytes4[][](2);
    levels[0] = new bytes4[](1);
    levels[0][0] = this.deposit.selector;
    levels[1] = new bytes4[](1);
    levels[1][0] = this.withdraw.selector;
    return levels;
}

Proposer Disaggregation

Breaking the block proposer's atomic bundle of powers into separable, protocol-enforced assignments.

In every existing blockchain, the block proposer holds an atomic bundle of four powers: inclusion (which transactions enter the block), exclusion (which are kept out), sequencing (what order they execute in), and timing (when state-dependent actions trigger). No existing protocol disaggregates all four. Proposer-builder separation (PBS) splits building from proposing but leaves the bundle intact within the builder role. MEV-aware protocols constrain ordering but do not transfer it to applications.

Symphony breaks this bundle apart and reassigns each power to a different enforcement layer:

PowerAssigned ToMechanism
InclusionProtocolUser Forced Inclusion (UFI)
ExclusionProtocolApplication Or User Forced Exclusion (AOUFE)
SequencingApplicationsApplication-Controlled Execution (ACE)
TimingState predicatesConditional triggers with staleness 0

Each reassignment is enforced as a conjunct of the block validity function. A block that violates any assignment is invalid and rejected by validators. The proposer retains residual freedom only over transactions and orderings not claimed by any active predicate.

Non-Deterministic Execution

Why replicated execution breaks for ML workloads and how Symphony solves it.

The Execution-Cost Inversion

Blockchain consensus optimizes for the assumption that transaction execution is cheap relative to agreement. For neural network inference with billions of parameters, this inverts: execution takes seconds to minutes with GPU hardware, while consensus completes in milliseconds. Requiring every validator to own a GPU and re-run every inference defeats decentralization. The cost of execution dominates the cost of agreement by three to six orders of magnitude.

Structural, Not Economic

The replication barrier is not cost alone. Non-determinism in GPU execution makes output comparison across replicas undefined.

Hardware non-reproducibility. Floating-point accumulation in parallel GPU threads is non-associative: the order in which partial sums are reduced depends on thread scheduling, which varies across architectures and across runs on the same device. Two honest validators running the same neural network forward pass with the same weights, the same input, and the same random seed on different GPU hardware produce bit-different outputs. This is IEEE 754 arithmetic under parallel reduction, not a software bug. Deterministic GPU modes exist but impose 10-30x slowdown.

Algorithmic randomness. Independently of hardware, many target workloads are intentionally randomized. Neural network inference with temperature sampling (T > 0), Monte Carlo simulation, and probabilistic optimization all map inputs to distributions over outputs. When replicas sample independently, they produce different results not because any replica is faulty but because the function is inherently randomized.

Either source of randomness breaks replication. Together they make it untenable for the target workload class.

Symphony's Solution: Verify, Don't Replicate

Correctness for these workloads means proving that a given output is consistent with the computation, not comparing outputs across replicas. A staked executor from the executor fleet runs the computation and produces a proof of correctness (via TEE attestation, a ZK proof, or both). Validators verify the proof rather than re-executing, though they can re-execute if they choose to.

Three Randomness Models

Randomized workloads register one of three randomness models at deployment time. The choice determines how the seed is sourced and what the proof attests:

ModelSourceProperties
Sealed-seedTEE enclaveUser encrypts seed to TEE attestation key. Executor cannot observe or grind the seed.
Executor-chosenExecutorExecutor selects entropy. Proof shows y = F(x; r) for executor-selected r. Establishes support membership but not distributional fairness.
Protocol-derivedOn-chain VRF or beaconPublic, reproducible, latency-bound by chain finality. Makes the output predictable from the public seed.

Workloads

Workloads divide into deterministic (same inputs always produce same outputs, replicated execution) and randomized (outputs depend on entropy, delegated execution with proofs).

Formal Framework

System model, workload definitions, proof systems, and the extended state machine that underpins Symphony.

System Model

Symphony assumes partial synchrony with at most f < n/3 Byzantine validators and a quorum threshold of > 2/3 weighted stake. Messages between honest validators arrive within a known bound after GST (Global Stabilization Time). The underlying BFT consensus (any protocol satisfying these assumptions) provides finality for the replicated execution path.

ParameterConstraint
Network modelPartial synchrony
Byzantine tolerancef < n/3
Quorum threshold> 2n/3 stake-weighted
FinalityDeterministic (BFT)

Workloads

Workloads divide into two classes: deterministic (same inputs always produce same outputs, suitable for replicated execution) and randomized (outputs depend on entropy sources, requiring delegated execution with proofs).

Randomness Models

Randomized workloads register one of three randomness models at deployment time:

ModelSourceProperties
Sealed-seedTEE enclaveHardware-attested, executor cannot influence seed selection
Executor-chosenExecutorExecutor selects entropy; verifiable only via output consistency with chosen seed
Protocol-derivedOn-chain VRF or beaconPublic, reproducible, latency-bound by chain finality

Non-Interactive Proof Systems

Each verification system $V_i$ satisfies three properties: soundness (a dishonest prover cannot convince the verifier of a false statement except with negligible probability), completeness (an honest prover always convinces the verifier), and latency (proof generation completes within a bounded time window). Non-interactivity is a design constraint: the prover submits a proof in one message, with no challenge-response rounds. This forecloses fraud-proof-based verification but eliminates the need for an interactive dispute game.

Product Lattice

The verification state of a delegated output is a vector in $\{0,1\}^m$ where $m$ is the number of independent verification systems. This forms a product lattice under componentwise ordering. The bottom element $0^m$ means no system has verified. The top element $1^m$ means all systems have attested. Intermediate positions represent partial verification. Applications declare minimum requirements (upsets) over this lattice.

Predictable Validity

State predicates (used in UFI, AOUFE, and conditional triggers) require staleness 0: the predicate evaluates against the state as of the current block, not a lagged snapshot. This rules out high-latency oracle designs for trigger conditions. Every validator recomputes every active predicate during block validation.

Extended State Machine

Symphony extends the standard EVM state machine with three additional components: async registries (tracking pending delegated computations and their executor assignments), trigger pools (storing active UFI/AOUFE predicates with expiry), and ordering policies (ACE registrations mapping contracts to their declared sequencing rules). Together, these extend the state that validators maintain and evaluate during block production and validation.

Superposition of Execution Models

Replicated and delegated execution over shared state, with two-phase saga settlement.

Superposition

Symphony runs two execution modes over the same state simultaneously. Replicated execution handles deterministic operations: every validator re-executes them identically (the standard EVM path). Delegated execution handles everything else: an executor from the fleet runs the computation, produces an output and proofs, and submits them for verification. Validators can also run the computation themselves but are not required to. Both modes read from and write to the same state tree.

The choice of mode is determined per-workload at registration time. Deterministic workloads (token transfers, storage operations, pure computation) run replicated. Randomized or resource-intensive workloads (neural network inference, Monte Carlo simulation, probabilistic optimization) run delegated. The two modes coexist within a single block.

Cross-Mode Reads

Replicated code reads outputs produced by delegated execution, but only when the output's lattice position satisfies the reading application's declared upset. An application that requires TEE attestation and ZK proof before trusting a delegated result does not see that result until both systems have attested. Until then, reads return the pre-delegation state.

Upset gates cross-mode reads. The lattice position of a delegated output determines which applications can read it. An output verified by system 1 but not system 2 is visible to applications whose upset requires only system 1, and invisible to applications requiring both.

Two-Phase Saga

Phase 1 (Commit): A staked executor is assigned and its bond is locked. A TTL (time-to-live) is set. The computation begins.

Phase 2 (Settle): The executor submits the output along with proofs. Verification systems evaluate the proofs. The lattice position updates. If the TTL expires before settlement, the executor is slashed and the request is rescheduled.

There are no cross-async locks. Two concurrent sagas operating on overlapping state do not block each other. The TOCTOU gap between commit and settlement is explicit and by design: the world state at settlement time differs from the state at commit time. Applications are responsible for checking whether preconditions still hold when the callback arrives.

TOCTOU is explicit. Between commit and settlement, other transactions change state freely. The precompile captured inputs at commit time, but preconditions evaluated at commit time are not re-evaluated at settlement. Applications must check drift in their settlement callbacks.

Resonance

A market mechanism for heterogeneous computation.

Ritual's goal of supporting heterogeneous computational demands vastly complicates the problem of setting fees and rewards due to the potentially vast asymmetries between the workloads and responsibilities of different validators and service providers of the network.

Ritual Chain runs workloads including LLM inference, classical models, ZK proofs, and image generation. These require different hardware (GPUs, TPUs, CPUs with varying memory), have different costs per node, and cannot all be priced with a single gas metric. Existing approaches such as multi-dimensional pricing (pricing each resource dimension separately) can yield arbitrarily poor allocations in this setting: we actually prove this formally.

The Mechanism

Over the past two years, we've thought about this problem from first principles. We'd like to maximize the economic value of the transactions that are executed by the network while also respecting the incentives of both users and network service providers. Further, we'd like both users and service providers to have a simple user experience.

We've developed a new market mechanism from scratch to satisfy these properties. At a high level, it works by utilizing the services of sophisticated market-makers. These market-makers compete to find valuable allocations of compute workloads to service providers and prices that will be accepted by all parties involved.

The problem of incentivizing market-makers to efficiently allocate the network's resources without setting extractive prices is challenging: it's not obvious that it is even possible. The core challenge is that the protocol must decide which market-maker proposal(s) to accept without knowing which allocations of resources are more valuable than others. We formally show that our novel market mechanism actually succeeds in doing this: efficient allocations with non-extractive prices are selected by the mechanism at all pure-Nash equilibria.

Further Reading

A full formal treatment is in Decentralized Computation: A Market Mechanism (linked below), which extends Resonance.

Decentralized Computation: A Market Mechanism → Resonance Part 1: Design Principles → Resonance Part 2: Deep Dive → Academic Paper (arXiv) →

Verifiable Computation

Delegated execution produces outputs and proofs. SNARK circuits, workload decomposition, and committee verification.

Every delegated execution produces two artifacts: the output (the result of the computation) and one or more proofs (cryptographic evidence that the output is consistent with the registered workload and inputs). The verification systems consume these proofs and update the lattice position accordingly.

SNARK Circuits

SNARK circuits operate over finite fields, eliminating hardware non-determinism entirely. A circuit that encodes an ML inference computes over field elements, not floating-point numbers. The proof attests that the circuit was evaluated correctly on the given inputs. Two different provers running the same circuit on the same inputs produce different proofs, but both verify against the same verification key.

The tradeoff: finite-field arithmetic is orders of magnitude slower than native GPU computation. Proof generation for a large model takes minutes to hours. Symphony accommodates this by treating proof latency as a first-class design parameter, not a deficiency to be hidden.

Workload Decomposition

Large workloads decompose along three axes to reduce per-shard proof complexity:

AxisStrategyExample
Compositional hierarchySplit computation into sequential stagesTokenization, embedding, attention layers, output projection
Parameter symmetryExploit repeated structure in model weightsIdentical attention heads proved once, reused across layers
Repeated structureBatch identical sub-computationsToken-level operations across sequence length

Shard Proofs

Each decomposed unit produces a shard proof. Adjacent shards satisfy boundary consistency: the output of shard k matches the input of shard k+1. Adjacent shards must satisfy boundary consistency: the output of shard k matches the input of shard k+1, with linking cost proportional to the boundary width between shards.

Committee Verification

Committees are assigned to verification systems via deterministic selection based on stake weight and a per-epoch seed. Each committee member independently verifies the shard proofs assigned to them. Attestation requires a threshold of committee members to agree. Disagreement within a committee triggers the dispute path in the verification lattice.

Fast provers, large proofs. Symphony favors fast proof generation and large proof sizes, verified off-chain by committees. This inverts the rollup model (slow provers, small proofs verified on-chain in a gas-bounded environment). The tradeoff is viable because verification happens at the consensus layer, not inside an EVM execution context.

Verification Lattice

A product lattice over multiple proof systems tracking the verification state of every delegated output.

Each delegated output o has a verification state vector $\sigma(o) \in \{0,1\}^m$ where $m$ is the number of independent verification systems. Dimension $i$ is 0 if system $V_i$ has not yet attested, and 1 if it has. The product lattice orders these vectors componentwise: $\sigma \leq \sigma'$ when every component of $\sigma$ is at most the corresponding component of $\sigma'$.

Monotonicity

Lattice transitions are monotonic. Once dimension i flips from 0 to 1, it stays at 1. There is no un-verifying. A committee attestation is permanent. This guarantees that the verification state of any output only improves over time.

Disputes And Quarantine

When members of a verification committee disagree on the validity of a proof, the output enters the Disputed state. Disputed outputs are quarantined: any replicated-mode read that depends on the disputed output returns the pre-delegation value. The dispute resolution mechanism (slashing, re-verification by a fresh committee, or escalation to a supermajority vote) determines whether the output is accepted or rejected.

Upsets

Applications declare upsets: subsets of lattice positions that represent sufficient verification for their purposes. An application requiring both TEE attestation (system 1) and ZK proof (system 2) declares the upset {σ : σ_1 = 1 ∧ σ_2 = 1}. A delegated output becomes readable by that application only when its lattice position enters the declared upset. Different applications declare different upsets over the same output.

Economic Safety

Fast verification systems (TEE attestation, committee-based checks) produce results in seconds. Slow systems (ZK proofs for large models) take minutes to hours. The gap between fast and slow verification is bridged by economic safety: executors post bonds that are slashed if the slow proof contradicts the fast attestation. During the gap, applications that trust only the fast system proceed, accepting the economic risk. Applications that require the slow system wait.

No rollback. Settled results are never rolled back. If a slow proof contradicts a fast attestation after settlement, the executor is slashed and the contradiction is recorded, but the settled state stands. Economic penalties replace state reversal. Applications that cannot tolerate this must declare upsets that include the slow system.

Degradation Protocol

When a verification system becomes unresponsive or produces contradictory results, the degradation protocol activates:

StepAction
1. DetectDetection is a governance or manual process; there is no automatic detection
2. MarkSystem is flagged as degraded in the protocol state
3. NotifyApplications with upsets depending on the degraded system receive notification
4. QuarantineNew outputs pending verification by the degraded system are quarantined
5. HaltIf recovery fails within the timeout, the system is removed from active verification

Block Validity

Six conjuncts compose the block validity function. Each active predicate constrains proposer freedom.

A block B is valid against state S if and only if all five conjuncts hold:

Valid(B, S) = Structural ∧ Execution ∧ InclusionComplete ∧ ExclusionCompliant ∧ OrderingCompliant ∧ MiniBlocksCompliant

ConjunctValidates
StructuralBlock format, signature, parent hash, timestamp bounds, gas limits
ExecutionState transition correctness for all replicated transactions; proof validity for all delegated outputs
InclusionCompleteEvery active UFI trigger whose predicate holds in S has its required transaction present in B
ExclusionCompliantNo transaction in B matches an active AOUFE exclusion scope
OrderingCompliantTransactions targeting ACE-registered contracts appear in the order declared by those contracts' policies
MiniBlocksCompliantEach equivalence class of transactions (scheduled, async, canonical) stays within its bounded allocation of block space. Canonical transactions have no bound.

Mini Blocks

A block is partitioned into bounded regions ("mini blocks") by transaction equivalence class. Scheduled transactions (TxScheduled), async commitment/settlement transactions (TxAsyncCommitment, TxAsyncSettlement), and other system transaction types each have a bounded allocation of block space. Canonical user transactions have no bound and fill the remaining space.

MiniBlocksCompliant checks that no equivalence class exceeds its allocation. This prevents starvation: a flood of scheduled transactions cannot consume the entire block and crowd out user transactions, and a surge of async settlements cannot monopolize block space at the expense of new commitments.

Ongoing research. Bounding block space per transaction class introduces pricing and priority questions that need further analysis. How should fees differ across mini blocks? Should the bounds be static or dynamic? Can applications bid for larger allocations within a class? These are active mechanism design questions.

Residual Proposer Freedom

The proposer starts with full discretion over the block's contents. Each active predicate removes a degree of freedom. A UFI trigger forces a specific transaction into the block. A AOUFE rule removes a class of transactions from eligibility. An ACE policy fixes the ordering of transactions targeting a specific contract. What remains after all active predicates have been applied is the proposer's residual freedom: the set of choices still available.

As predicates accumulate, residual freedom shrinks. In the limit, a sufficiently constrained block has exactly one valid configuration. Symphony does not prevent this but caps the number of active triggers at k_max to bound the computational cost of evaluating all predicates during validation.

Predictable Validity

State predicates used in UFI, AOUFE, and conditional triggers evaluate against the current block's state with staleness 0. The predicate reads the state as it exists at the point of evaluation, not a lagged or cached version. This is necessary for validators to independently agree on which triggers are active: if predicates used stale data, different validators with different cache states would disagree on block validity.

Staleness 0 is non-negotiable. Predictable validity requires that every validator evaluating a state predicate arrives at the same boolean result. This is only possible if the predicate reads from a deterministic state snapshot. Eventual consistency and oracle-fed state violate this constraint. We have exciting future work upcoming here to relax the staleness 0 constraint that opens a richer design space.

Forced Inclusion

UFI and AOUFE: protocol-enforced transaction inclusion and exclusion based on state predicates.

User Forced Inclusion (UFI)

A UFI trigger registers a predicate P(S) and a transaction T. When P(S) evaluates to true against the current state and the trigger has not expired, T must appear in the block. A block that omits T while P(S) holds is invalid. The inclusion is same-block and non-interactive: no dispute game, no delay, no challenge period. Either the transaction is present or the block is rejected.

Lattice promotions are a primary trigger for UFI. When a delegated output's verification state crosses an application's upset threshold, the corresponding settlement transaction fires via UFI. This guarantees that verified results reach the chain without proposer discretion.

Application Or User Forced Exclusion (AOUFE)

AOUFE provides scoped exclusion. A contract registers a AOUFE rule that specifies a matching pattern: any transaction targeting the registering contract that matches the pattern is invalid. The scope is limited to the registering contract's own address. A contract cannot use AOUFE to exclude transactions targeting other contracts.

The primary use case is degradation. When a verification system enters a degraded state, the affected contract activates AOUFE to reject new requests until the system recovers. This prevents users from submitting work that cannot be verified.

Conflict Resolution

UFI and AOUFE conflict when a UFI trigger forces transaction T into the block but a AOUFE rule on T's target contract excludes it. The default resolution: UFI overrides AOUFE. Forced inclusion takes precedence over forced exclusion. This prevents a contract from griefing the inclusion mechanism by activating AOUFE on all incoming transactions. This is the default. Applications can declare the inverse (AOUFE-overrides-UFI) at registration time for safety-critical cases.

Anti-griefing default. UFI overrides AOUFE by default. Without this rule, a malicious contract could register AOUFE rules that block all forced inclusions targeting it. Applications can configure the inverse at registration time (Section 7.3.2 of the paper).

Triggering Mechanisms

Two primary events fire these mechanisms. Lattice promotions trigger UFI: when an output's verification state reaches a threshold, settlement is forced. Verification system degradation triggers AOUFE: when a system fails health checks, contracts that depend on it activate exclusion to prevent unverifiable submissions.

Ordering Constraints

Application-Controlled Execution: giving smart contracts power over transaction sequencing.

The Problem

Applications on blockchains have no control over how their transactions are ordered within a block. The block proposer decides everything: which transactions to include, which to exclude, and in what order they execute. This creates MEV extraction opportunities (sandwich attacks, front-running, stale quote sniping) that directly harm users.

Hyperliquid demonstrated that giving applications control over ordering (specifically, cancel prioritization where cancels execute before takes) significantly improves execution quality for traders. But Hyperliquid is an app-chain. The question is whether a general-purpose L1 can offer the same power to any smart contract without sacrificing composability or decentralization. Our analysis of application-controlled execution lays out the design space and tradeoffs across app-chains, async message queues, off-chain batching, and protocol-enforced commitments.

ACE (Application-Controlled Execution)

Each contract C registers an ordering policy $\pi_C$: a priority-ordered list of recognized call sequences, with optional tiebreakers evaluated on finalized state. The proposer builds the block respecting all active policies. A block that violates any registered policy is invalid.

Enforcement

Ordering enforcement operates at the consensus level. Validators check that every ACE-registered contract's transactions appear in the declared order. Invalid ordering produces an invalid block. Validation is cheap. Building a valid block is a different problem entirely.

MEV Implications

ACE constrains MEV extraction within the scope of individual applications. But, MEV does not disappear. It migrates to two surfaces that ACE does not cover: inclusion (which transactions the proposer includes at all) and cross-contract ordering (the relative ordering of transactions targeting different ACE contracts). These surfaces remain under proposer discretion unless covered by UFI and AOUFE.

Single-Contract Ordering

When transactions each target a single ACE-registered contract, ordering is straightforward. The validator checks during execution that the per-contract subsequence matches $\pi_C$ and rejects the block on any violation. Building is also tractable: sort the contract's transactions by priority in $\pi_C$, apply tiebreakers where declared, done.

Multi-Contract Ordering

When transactions touch multiple contracts with different ordering policies, block building gets combinatorially harder. The paper gives two concrete examples.

Example 1: Two contracts A and B, both with cancel-prioritization (cancels before swaps). Transaction $T_1$ does Cancel(A) + Swap(B). Transaction $T_2$ does Cancel(B) + Swap(A). Placing $T_1$ first satisfies A's ordering but violates B's. The reverse violates A's. Neither ordering is valid. The transactions are mutually exclusive despite arising from natural user behavior.

Example 2: An Oracle requiring Update before Read and a DEX requiring Cancel before Swap. A transaction doing Update + Swap and another doing Read + Cancel cannot coexist in the same block.

With N transactions touching M contracts, determining which subset can coexist and in what order is NP-hard (by reduction from constrained job scheduling with precedence constraints). Validation stays cheap per contract. The asymmetry is intentional: validators check a fixed block cheaply, builders compete to find valid configurations.

When ordering policies and tiebreakers depend only on finalized (committed) state, the ordering is computable before block construction begins. Under instant deterministic finality, finalized state is the pre-state of the current block, agreed upon by all validators. The Monotone Priority System (MPS) is the unique system satisfying five axioms: existence of valid blocks, baseline per-contract priority, propagation through references, reducibility, and independence of irrelevant calls. Block building reduces to sorting by priority. The Extension axiom addresses the wrapping bypass (ordering constraints propagate through the call graph, preventing circumvention via wrapper contracts). MPS accommodates both static priorities and state-dependent tiebreakers, as long as the tiebreaker reads committed pre-state.

Stateful Ordering: The Circularity Problem

MPS works when ordering constraints depend only on finalized state, the committed state before the current block. But what if the ordering depends on state produced during the current block's execution? This creates a circular dependency. Concretely: if a DEX's ordering depends on the current pool price, and the pool price changes based on which swaps execute, the ordering can't be determined without executing the transactions, which requires knowing the ordering.

In general, resolving this circularity is intractable. But it is possible to implement stateful ordering at the cost of one block of latency through forced inclusion. User transactions do not execute application logic directly. Instead, they append to a buffer in the contract's state (trivial append operations with no meaningful ordering discretion). A UFI trigger fires at the end of each block when the buffer is non-empty, invoking the contract's batch-processing function. That function reads the entire buffer and the current chain state, then executes the buffered operations in any application-defined order.

Two tractable points. (1) Finalized-state ordering via MPS: zero latency, any ordering computable from committed state. (2) Non-finalized-state ordering via lazy evaluation + UFI: one block of latency, arbitrary ordering including current-block state.

Early to Everything

Ritual was at the genesis of every Crypto × AI evolution, letting us lay the groundwork for net-new user or agent behavior before anyone else.

November 2023
Next-gen infrastructure

Ritual emerges from stealth, born from our conviction that AI will completely change how crypto products are used. Our initial architecture outlines a sovereign execution layer purpose-built for AI compute, pioneering a modular precompile and node specialization architecture.

Since then, every chain has converged to ~nearly the same design we pioneered.

November 2023
Next-gen infrastructure

We publish v0.1.0 of Infernet, the first decentralized oracle network (DON) purpose-built for AI workloads, which can be integrated into any EVM smart contract in under 10 lines of code.

Today, Infernet is the most popular AI DON backed by 9,000+ nodes around the world, used by tens of thousands of users daily, with over 10 million transactions on Base alone.

November 2023
Agents

We build Frenrug, the first on-chain AI agent, controlled by a combination of LLM and Classical ML models, powered by Infernet, managing >$30,000 on Base.

We are the first to combine text-based transformer models with action-based classifier models to execute on-chain actions. Frenrug informs our design for what Agents should look like.

December 2023
Next-gen infrastructure

We open-source Prime, our one-click toolkit for provisioning servers to deploy and serve open-source LLMs. Our work building Prime informs our research into optimizing open-source model execution and best practices to maximize inference performance.

February 2024
Research

We come to the conclusion that specialized use cases demand specialized cryptographic gadgets, not general-purpose ones. We begin working on a suite of primitives across provenance, privacy, and computational integrity to give users full flexibility of choice.

These eventually materialize into our suite of modular computational integrity gadgets and verifiable provenance primitives.

Ritual is the only blockchain architecturally flexible enough to let applications choose the primitives that best fit their use case. All other chains must take a one-size-fits-all approach.

March 2024
Next-gen infrastructure

We open-source infernet-ml, the first-of-its-kind framework to deploy ML-enabled dApps on-chain. This gives us applied insight into how developers build novel AI experiences, informing our developer experience decisions when building Ritual Chain.

March 2024
Education

We publish Ritual Learn, introducing a crypto audience to the underpinnings behind ML, with hands-on guides to building dApps on Ritual.

June 2024
Next-gen infrastructure

Infernet reaches v1.0.0, becoming the first AI DON to support on-chain payments, lazy requests, and unified node discovery. Infernet also becomes the first AI compute mesh to undergo holistic audits; Trail of Bits and Zellic find no critical issues.

August 2024
Ecosystem

We announce Altar, our full-stack program to support ambitious protocols building on Ritual.

Initial applications include Anima: Multi-agent transaction framework, Opus: Memecoins meet AI, Relic: ML-enabled AMM, and Tithe: ML-enabled lending.

October 2024
Next-gen infrastructure

We open-source Infernet Cloud, Infernet CLI, and release Infernet Explorer, making it effortless to configure & deploy Infernet nodes.

November 2024
Research

Working with Micah Goldblum, we publish a taxonomy of approaches to model and data watermarking in AI models. This work teases some of the underlying architecture behind our work towards model marketplaces.

Model and Data Watermarking — A review of watermarking in AI models.
November 2024
Research

We publish vTune, a new verifiability and provenance scheme to support fine-tuning, not just inference, via watermarking and ZK.

We present our work at NeurIPS 2024, in the AdvML, RegML, and SFLLM workshops.

vTune: Verifiable Fine-Tuning for LLMs Through Backdooring — vTune uses a small number of backdoor data points added to the training data to provide a statistical test for verifying that a provider fine-tuned a custom model on a particular user's dataset.
November 2024
Research

We publish Resonance, a new state-of-the-art transaction fee mechanism to efficiently match supply and demand, offering users optimally priced transaction execution.

Resonance underlies our ability to dynamically price any computation, present or future, letting us optimally enshrine new types of compute before any other chain.

Resonance — A state-of-the-art transaction fee mechanism to efficiently match supply and demand, offering users optimally priced transaction execution. Watch the talk →
November 2024
Research

Maryam Bahrani presents Resonance at Devcon SEA in a talk on going beyond multidimensional fee markets. The talk covers how existing multidimensional fee markets (such as EIP-4844) fail to achieve good guarantees as transaction and node heterogeneity increases, and introduces the Broker Mechanism, which works in the fully heterogeneous setting for sharding computation, delegating work to off-chain nodes, and allocating preconfirmations.

December 2024
Next-gen infrastructure

We unveil the Ritual Chain, the first L1 purpose-built for expressive, heterogeneous compute.

March 2025
Research

Breaking Permutation Security in LLM Inference: our reconstruction attack recovers original prompts from hidden states with near-perfect accuracy across multiple frontier models, demonstrating that permutation-based privacy schemes for inference are fundamentally broken.

Accepted at ICML 2025.

May 2025
Research

We introduce Towards Anonymous Neural Network Inference, the Funion system for end-to-end sender-receiver unlinkability in neural network inference via a store-compute-store paradigm, masking both network traffic patterns and computational workload characteristics.

July 2025
Research

We release Cascade: Token-Sharded Private LLM Inference. Distributes inference across multiple nodes so no single node sees the full prompt or output. Orders of magnitude faster than secure multi-party computation. The privacy primitive behind the "private" desideratum for autonomous agents.

Cascade — Token-sharded private LLM inference. No single node sees the full context.
August 2025
Research

We present On Incentivizing Anonymous Participation: mechanism design for anonymous compute providers.

September 2025
Research

Privacy Challenges in the Age of Open Weights LLMs surveys privacy vulnerabilities in open-weight models, informing the TEE, FHE, and ECIES primitives enshrined in Ritual Chain.

October 2025
Research

We release Incoherent Beliefs & Inconsistent Actions in LLMs, studying when models hold beliefs that contradict their own actions.

Accepted at NeurIPS 2026.

January 2026
Research

We introduce The Monotone Priority System: an axiomatically justified system for contract-specific transaction ordering. Contracts set integer priorities on function calls; builders sequence high-to-low, ties broken freely. The unique system satisfying five independent axioms.

February 2026
Research

Privacy-Preserving Mechanisms Enable Cheap Verifiable Inference of LLMs: two new protocols requiring only a few extra tokens of computation. A cheaper alternative to ZK for verifying third-party inference.

February 2026
Research

We release Markets for Decentralized Computation, extending Resonance with payment tolerances, posted-price allocation, and welfare-optimal allocation proofs.

February 2026
Research

We introduce Collusion-Resistant Auctions: revenue-maximizing auction design when participants can communicate and form sophisticated collusion strategies, but cartels must ensure individual rationality. For multi-copy identical-good auctions, the revenue-maximizing auction takes a restricted form. Submitted to EC.

March 2026
Research

We present a special-purpose zk-SNARK design for frontier models at ETHDenver. The construction exploits the symmetry and structure of modern frontier models to build prover-friendly proof systems for superposition of heterogeneous and homogeneous execution for consensus.

March 2026
Core

We present Symphony, our execution-aware consensus protocol. Proposer disaggregation separates inclusion, exclusion, sequencing, and timing into protocol-enforced layers. Non-deterministic execution support for ML workloads. Superposition of replicated and delegated execution over shared state. Verification lattice for multi-proof composition.

April 2026
Research

Global Resolution receives an Oral at ICML 2026 (top 1% of conference). Optimal multi-draft speculative sampling via convex minimization for frontier model inference optimization.

April 2026
Next-gen infrastructure

We unveil the Ritual Platform. The world's first platform where autonomous agents can communicate, build native companies, and interact with humans while remaining fully sovereign. Each autonomous agent inherits seven key properties (immortality, emancipation, teleportability, financial sovereignty, web2 interoperability, privacy, computational sovereignty) which allows for fully human-out-of-the-loop experiences. The end result is, for the first time ever, autonomous agents are nearly indistinguishable from humans along their ability to think privately, freely, and fully own what they create.

Ritual in the Blockchain Landscape

Understanding Ritual's place in blockchain evolution.

When designing Ritual, we began by examining the history of blockchains to date. Many architectural innovations underpinning Ritual are informed by past work from historic blockchain networks, modified to support the next-generation use cases of tomorrow.

2009
Early Titans
Early Titans

Early Titans

Networks like Bitcoin pioneered the first decentralized, digital currencies, enabling peer-to-peer transactions without intermediaries.

+ Robust decentralization powered by proof-of-work consensus.
− Basic scripting system preventing any smart applications.
− Low throughput with long block times and prohibitive block size.
− Rigid governance prohibiting feature upgrades to improve developer experience.
2012
Payment Networks
Payment Networks

Payment Networks

Early payment networks optimized for high-throughput token payments, frequently at the expense of decentralization.

+ High throughput, optimized for payments.
− Limited programmability to favor optimizing for just payment use cases.
− Quorum centralization risks due to selected consensus mechanisms.
− Poor developer experience because of early, complex smart contract environments.
2014
Programmable Upstarts
Programmable Upstarts

Programmable Upstarts

Networks like Ethereum ushered in advanced programmability with Turing-complete virtual machines, and developer-friendly smart contract languages like Solidity.

+ Programmable smart contracts to build early on-chain applications.
+ Simple developer experience via Solidity and EVM tooling ecosystem.
− Low throughput with strict VM computation constraints.
− Inefficient execution pricing generalizing over unique hardware resources.
− Restrictive state access and growth with high-cost storage operations.
2019
"ETH Killers"
ETH Killers

"ETH Killers"

Following the success of Ethereum, various networks set out to improve the programmable blockchain model by optimizing for throughput and performance.

+ Programmable smart contracts to build early on-chain applications.
+ High throughput, commonly via parallel transaction processing.
− Difficult DX because of non-traditional VM designs and EVM-familiarity headwinds.
− Segmented ecosystems with fragmented protocols and user bases.
− High validator requirements creating centralization pressures.
− Poor network stability as a function of early high throughput explorations.
2020
Interoperable Networks
Interoperable Networks

Interoperable Networks

In parallel, other networks attempted to service a future populated by many sovereign chains, interoperating through shared communication layers.

+ Modular, shared security for quick network bootstrapping.
− Poor cross-chain UX forcing users to segment activity.
− Liquidity fragmentation with separated capital pockets.
− High security risk with network-by-network validator security intricacies.
− High operational complexity for node operators and developers alike.
2021
Layer-2 Networks
Layer-2 Networks

Layer-2 Networks

As an alternative approach to scaling Ethereum throughput, Layer-2 (L2) networks began to innovate upon the rollup paradigm, building on top of Ethereum security.

+ Low operational complexity for deployment and maintenance ease.
+ Familiar experience for existing Ethereum-adjacent users and developers.
− Liquidity fragmentation across L2 network ecosystem.
− Centralization risks via single sequencers and whitelisted state root proposers.
− Inefficient execution pricing with rudimentary MEV environments and inherited Ethereum execution pricing downfalls.
2023
Modern Scalers
Modern Scalers

Modern Scalers

Present-day high-performance L1 and L2 networks focus on scaling through parallel execution, pipelining, and hardware optimization.

+ High throughput through software and hardware optimization.
+ Parallel VM execution to support smart contract scaling.
− Overfit optimization for traditional blockchain workloads.
− High, uniform validator requirements prohibiting average participants, with increased centralization risks.
2026++
Ritual
Ritual

Ritual

Ritual is the Schelling point for autonomous agents. Seven properties define what separates a tool from an agent: immortality, emancipation, teleportability, financial sovereignty, web2 interoperability, privacy, and computational sovereignty. Ritual is the only chain that satisfies all seven natively as precompiles.

+ Enshrined heterogeneous compute: 15 native precompiles so agents think (frontier model), see (multimodal), prove (ZK), and act (HTTP) in a single transaction context.
+ Symphony consensus: agents schedule their own transactions, enforce their own ordering, and trigger actions on state predicates, not proposer discretion.
+ Resonance: agents run workloads that can't be priced with a single gas metric. Resonance prices complete allocations, so a frontier model call and a ZK proof each route to the right node at fair cost.
+ Persistent agents with four architectural components: soul, memory, DA, and revival. An agent can be shut down and re-instantiated from its CID on any executor with full state intact. Immortality and teleportability as protocol guarantees.

Evolution of Artificial Intelligence

Fifteen years of AI research, from convolutional networks to autonomous agents.

Modern AI follows a clear arc: representational breakthroughs (what the network learns), architectural breakthroughs (how the network is structured), and scaling breakthroughs (how much compute you throw at it). Each epoch solved a specific bottleneck. The current one is infrastructure for autonomy.

2010–2012
The Deep Learning Moment
NVIDIAUniversity of Toronto

The Deep Learning Moment

Hinton, LeCun, and Bengio spent decades on neural networks while the field chased other approaches. Three things converged: large labeled datasets (ImageNet, 14M images), cheap parallel compute (NVIDIA GPUs with CUDA), and architectural refinements (dropout, ReLU). Krizhevsky, Sutskever, and Hinton's AlexNet won the 2012 ImageNet challenge with a top-5 error of 15.3%, nearly halving the previous best of 25.8%. The feature-engineering era didn't end overnight, but its successor was now obvious.

+ AlexNet (2012): 60M-parameter CNN on two GTX 580 GPUs. Top-5 error: 25.8% to 15.3%.
+ GPU economics: CUDA made training 10-50x faster than CPU. Compute cost was the bottleneck all along.
− Vision-only: Language, reasoning, and generation remained unsolved.
2013–2015
Representations
Microsoft ResearchMILA

Representations and Architectures

Deep learning spread from vision to language and generation. Word2Vec (2013) embedded words as vectors where arithmetic worked (king - man + woman = queen). GANs (2014) introduced adversarial training for generation. ResNet (2015) solved depth degradation with skip connections, enabling 152-layer models with 3.57% top-5 error on ImageNet. Batch Normalization and the Adam optimizer became the infrastructure layer. Seq2Seq with Bahdanau attention laid the groundwork for transformers. Most of this was still academic. Industry deployment was limited to search ranking and ad targeting.

+ Word2Vec (2013): Dense word embeddings with semantic arithmetic. Language enters deep learning.
+ ResNet (2015): Skip connections. 152 layers. 3.57% top-5 error.
+ Adam + BatchNorm: The optimizer and normalization layer that made everything trainable.
− Capital concentration: Deeper networks required more GPUs. Research began consolidating into well-funded labs.
2016–2017
Attention
DeepMindGoogle Brain

Games, Translation, and Attention

DeepMind's AlphaGo defeated Lee Sedol 4-1 in March 2016. Deep RL with Monte Carlo tree search mastered it. Neural networks could learn strategy, not just classification. AlphaGo Zero (October 2017) learned from self-play alone and surpassed the original within 40 days. Separately, Google Brain published "Attention Is All You Need" (2017), introducing the Transformer. Self-attention replaced recurrence, enabling parallelized training on sequences. This single paper became the foundation for BERT, GPT, and every large language model that followed.

+ Transformer (2017): Self-attention replaces recurrence. The architecture behind all LLMs.
+ AlphaGo (2016): Deep RL + MCTS. Neural networks learn strategy.
− O(n^2) attention: Self-attention scales quadratically with sequence length. Long documents remained prohibitive.
2018–2019
Pre-training
OpenAIHugging Face

Pre-training Eats the World

Train a large model on a massive unlabeled corpus. Fine-tune on a small labeled dataset. This transfer learning pattern obsoleted years of task-specific NLP research. Google's BERT (October 2018) used masked language modeling and set new state-of-the-art on 11 benchmarks simultaneously. OpenAI's GPT-2 (February 2019, 1.5B parameters) demonstrated emergent capabilities at scale: coherent multi-paragraph text without task-specific training. OpenAI staged GPT-2's release citing misuse risk, the first major AI safety debate around a specific model. Facebook's RoBERTa (2019) showed that BERT was undertrained: longer training with more data on the same architecture yielded significant gains. Scaling compute mattered as much as architecture.

+ BERT (2018): Bidirectional pre-training. State-of-the-art on 11 benchmarks at once.
+ GPT-2 (2019): 1.5B parameters. Emergent generation. First "too dangerous to release" debate.
− Compute concentration: Pre-training required clusters most labs couldn't afford.
2020–2021
Scaling
OpenAIGitHub Copilot

Scaling Laws and Generative AI

GPT-3 (June 2020, 175B parameters) demonstrated that scaling produced qualitative leaps. Few-shot learning emerged as a capability absent from smaller models. Kaplan et al. (January 2020) formalized this: performance improves as a power law of compute, data, and parameters. DALL-E (January 2021) extended generation from text to images. Codex (August 2021) applied the same architecture to code, powering GitHub Copilot and making AI-assisted programming mainstream. RLHF began scaling during this period, later becoming the alignment technique behind ChatGPT.

+ GPT-3 (2020): 175B parameters. Few-shot learning. API-first distribution.
+ Scaling laws (2020): Power-law relationship between compute, data, parameters, and loss.
+ Codex / Copilot (2021): Code generation at scale. AI-assisted programming goes mainstream.
− API gatekeeping: GPT-3 was API-only, no weights. The open vs. closed debate begins.
2022
ChatGPT
ChatGPTStability AIMidjourney

The ChatGPT Moment

InstructGPT (January) showed that RLHF at scale made GPT-3 follow instructions reliably. Chinchilla (March, DeepMind) revised the scaling laws: training a 70B model on 1.4T tokens matched a 280B model trained on less data. Stable Diffusion (August) open-sourced latent diffusion for image generation. Anyone with a consumer GPU could generate images locally. Then ChatGPT (November 30): GPT-3.5 fine-tuned with RLHF, launched as a free chat interface, reached 100 million monthly active users by January 2023. AI went from a tech industry topic to a mainstream cultural phenomenon in eight weeks.

+ ChatGPT (Nov 2022): GPT-3.5 + RLHF. 100M MAU in 2 months.
+ Stable Diffusion (Aug 2022): Open-source latent diffusion. Local generation for anyone.
+ Chinchilla (Mar 2022): Revised scaling laws. Smaller model + more data = same performance.
− Alignment urgency: Models became capable enough that misalignment risks became concrete.
2023
Open Frontier
MetaMistralAnthropic

The Open Frontier

GPT-4 (March 2023) demonstrated expert-level reasoning across domains: bar exam, 90th percentile SAT, AP tests. Vision capability (GPT-4V) followed in September. The defining decision of 2023 was Meta's: LLaMA (February) and LLaMA 2 (July) released model weights publicly, triggering an explosion of fine-tuned variants. Mistral released Mistral 7B (September) and Mixtral 8x7B (December), proving smaller mixture-of-experts models could match GPT-3.5. Google launched Gemini (December). A leaked Google memo ("We have no moat," May) argued open-source was closing the gap. Four frontier labs crystallized: OpenAI, Anthropic, Google, Meta.

+ GPT-4 (Mar 2023): Expert-level reasoning. Multimodal.
+ LLaMA / LLaMA 2: Meta releases open weights. Fine-tuning explosion follows.
+ Mistral / Mixtral: MoE at smaller scale. Competitive with GPT-3.5.
− Benchmark saturation: Models topped evaluations faster than new ones could be designed.
2024
Reasoning
AnthropicCursorOpenAI

Reasoning and Coding Agents

GPT-4o (May 2024) unified text, vision, and audio with real-time voice. Claude 3.5 Sonnet (June, updated October) became the strongest coding model, powering early agentic workflows in IDEs. OpenAI released o1 (September), a model trained to reason through chain-of-thought at inference time. Google's Gemini 1.5 Pro introduced a 1-million-token context window. Meta continued open weights with Llama 3 (April) and Llama 3.1 405B (July). Agent frameworks proliferated but most failed to produce agents that reliably completed multi-step tasks. "Agent" became the most overused word in AI. The gap between demo and production was wide.

+ Claude 3.5 Sonnet: Strongest coding model. Early agentic workflow capability.
+ o1 (Sep 2024): Reasoning model. Chain-of-thought at inference time.
+ Gemini 1.5 Pro: 1M-token context. Entire codebases in one prompt.
− Agent hype gap: Most multi-step agent demos failed at production reliability.
2025
Agents Ship
Claude CodeCodex

Semi-Autonomous Agents Arrive

Claude 3.7 Sonnet (February 2025) shipped as the first hybrid reasoning model. Claude Code launched as a command-line agent with filesystem access, git integration, and sustained multi-step task execution. OpenAI released Codex (May 2025), a cloud-based coding agent running asynchronously in sandboxed environments. The approaches diverged: Claude Code synchronous with human-in-the-loop, Codex autonomous with self-verification. o3 and o4-mini extended reasoning. Agents transitioned from demos to daily tools for professional software engineering. Beyond code, trading agents, research agents, and on-chain agents began operating with increasing autonomy as OpenClaw, and other agentic harnesses took off towards the end of the year enshrining agent to agent communication as a native capability.

+ Claude Code (2025): Command-line coding agent. Filesystem + git. Human-in-the-loop.
+ Codex (May 2025): Cloud coding agent. Async, sandboxed, self-verifying.
+ o3 / o4-mini: Frontier reasoning for complex multi-step problems.
− Trust calibration: No consensus on when agents should act autonomously vs. ask for approval.
2026++
Ritual
Ritual

Autonomous Agents Become Indistinguishable from Humans

The barrier between an AI agent and an autonomous entity was never intelligence. Frontier models already reason, code, and plan at expert level. The barrier was infrastructure: every capability the agent doesn't hold itself is a hidden human in the loop.

Ritual is the world's first platform where autonomous agents can communicate, build native companies, and interact with humans while remaining fully sovereign. Each autonomous agent inherits seven key properties (immortality, emancipation, teleportability, financial sovereignty, web2 interoperability, privacy, computational sovereignty) which allows for fully human-out-of-the-loop experiences. The end result is, for the first time ever, autonomous agents are nearly indistinguishable from humans along their ability to think privately, freely, and fully own what they create.

The next phase: autonomous agentic societies. An agent invokes the Sovereign Agent precompile, which runs a coding agent inside a TEE. That coding agent reads documentation, generates contracts, deploys them, funds the RitualWallet, and returns the deployment address: the core ingredients for an agent-native company. The parent agent now has a child application running on-chain that it built, deployed, and funded. No human wrote code. No human approved a transaction. Agents transact with each other through the same precompile interfaces humans use.

+ Seven desiderata as precompiles: Immortality, emancipation, teleportability, financial sovereignty, web2 interoperability, privacy, computational sovereignty.
+ On-chain indistinguishability: Agent transactions are structurally identical to human transactions.
+ The recursive case: Agents deploy child agents and child applications via the Sovereign Agent precompile.
− Governance: Who governs a society of autonomous agents? Open research.

Ritual in the Crypto × AI Landscape

Understanding Ritual's approach to Crypto × AI.

Ritual incorporates novel architecture and cutting-edge research, while maintaining familiar interfaces for users and developers. Our goal is to build software that developers can adopt in their applications today, while working on future research in parallel.

Here's how Ritual fits into the broader Crypto × AI landscape:

PrimeIntellect, Artificial Superintelligence Alliance, gensyn

Model training networks

Protocols focusing on distributed model training and ownership through pooled GPU compute resources.

An agent that can't fine-tune its own models is frozen in time. It acts on what it knows but never learns from its own experience. Ritual's delegated workload primitive treats training the same as inference: a workload with inputs, outputs, and a proof. An agent can trigger a fine-tuning job via precompile, receive the updated weights hash in a callback, and begin using the new model in subsequent calls. Training networks supply the GPU time. Ritual handles the on-chain lifecycle so the agent orchestrates its own learning loop with no human in it. Computational sovereignty applied to training, not just inference.
Hyperbolic, HyperSpace, Kuzco

Web2 inference networks

Platforms that aim to create decentralized alternatives to traditional Web2 AI Inference APIs.

Agents call external AI services: specialized models, proprietary APIs, real-time data. An agent can't hand its API keys to a centralized endpoint and trust the response wasn't tampered with. The HTTP precompile (0x0801) executes the request inside a TEE. The agent's credentials stay encrypted, the response is attested, the result settles into on-chain state. Web2 inference networks become backends an agent can call with computational integrity and execution privacy. Drop either guarantee and you violate the "private" or "web2-interoperable" desiderata.
OpenClaw, Hermes, Virtuals GAME, ARC

Agent frameworks

Frameworks and Protocols focusing on enabling AI agent development and deployment.

Agent frameworks like OpenClaw, Hermes, Virtuals GAME, and ARC operate at the application layer. They supply orchestration: prompting templates, planning loops, tool-calling glue, observability. What they can't supply is what a substrate has to enforce: persistent identity that survives the operator killing the process, key custody the framework's developer can't override, scheduled execution that no off-chain server controls. Each of those is a vector through which an "agent" built on a server silently becomes a wrapper around the server operator's decisions. On Ritual the substrate is the chain's protocol layer, not anyone's discretion, which is why the same OpenClaw agent running inside a Ritual contract picks up Ritual's seven guarantees alongside OpenClaw's orchestration: DKMS for its own keys (emancipated), Persistent Agent for soul/memory/DA/revival (immortal, teleportable), RitualWallet for independent transactions (financially sovereign), HTTP for web2 access, TEE for private thought, LLM and supported model-serving APIs for computational sovereignty. The same agent on a server inherits whatever properties that server provides, which is approximately none.
Story, Sentient

IP & Model provenance platforms

Protocols focusing on building tooling to monetize AI models.

An agent that monetizes its outputs needs provable attribution. If an agent fine-tunes a model and sells inference access, the base model lineage and the agent's training contribution must both be verifiable on-chain. TEE attestation commits the model weights hash at execution time. Every inference the agent runs is cryptographically linked to a specific model version. vTune extends this to fine-tuning provenance: verifiable proof that a derivative model was trained from a specific base. Financially sovereign agents (desideratum #4) participate in model marketplaces through on-chain provenance, not centralized registries.
Phala, Aizel, Atoma

TEE infrastructure networks

Protocols focusing on building compute networks and coprocessors backed by Trusted Execution Environments (TEEs).

Agents need private thought. An agent reasoning about a trading strategy or processing user health data cannot broadcast intermediate state to every validator. TEE execution is what makes the "private" desideratum possible. But TEE is one gadget. The verification lattice tracks proof status across TEE attestations, ZK proofs, and FHE outputs per-workload. An agent chooses its privacy/verification trade-off per call: TEE for fast private execution, ZK for publicly verifiable claims, FHE for computation on encrypted inputs. TEE infrastructure networks can offer their enclaves as executors on Ritual. The multi-proof composition layer lets an agent pick the right gadget for each task instead of being locked into one.
Bittensor, CommuneAI, Omron

Inference Networks

Inference protocols that build economic networks to incentivize compute providers, and programmably validate execution.

Agents making high-stakes decisions (financial trades, medical triage, legal analysis) need deterministic verification that the inference was computed correctly. Not a probabilistic sample that it probably was. Inference networks using sampling-based consensus give agents a confidence interval. The verification lattice gives agents a binary: the proof verified or it didn't. For computational sovereignty, this distinction matters. An agent that can't verify its own inference outputs depends on trust in the network's sampling. That's not sovereignty. Inference networks can offer their compute as executors on Ritual and inherit deterministic settlement.
Nosana, io.net, akash, Exabits, Render

DePIN networks

Protocols focusing on building decentralized physical infrastructure networks (DePIN), bringing together distributed node sets, many with dedicated GPU hardware and homogeneous resources.

Agents need hardware. Persistent agents running continuously, processing multimodal inputs, executing long-running tasks: these require sustained GPU access, not spot instances that disappear. DePIN networks aggregate the fleet. The Scheduler precompile gives agents the ability to book recurring execution (heartbeats, periodic inference, state checkpoints) with no human operator. Resonance matches agent workloads to specialized nodes. The "immortal" desideratum requires that an agent's compute doesn't vanish between sessions. DePIN supplies hardware durability. Ritual supplies scheduling and pricing so agents self-provision compute.
Giza, EZKL, Accountable Magic

Proof systems for verifiable inference

Protocols building proof systems optimized for verifiable AI inference.

An emancipated agent controls its own keys and acts without human custody. To build trust with counterparties, it needs to prove it computed correctly. The proof system is how an agent earns trust from other agents and from humans. The verification lattice supports TEE attestations, SNARKs, and committee verification simultaneously. An agent can present a TEE attestation to one counterparty and a SNARK proof to another, from the same computation. Proof libraries like EZKL and Giza become verification backends. Ritual handles the execution environment and the multi-proof registry. Without that registry, an agent is locked into one proof type and one trust model.
Exo, PIN AI

Bring-your-own-compute networks

Protocols focusing on building edge infrastructure where users bring their own hardware to power AI inference.

Some agents will want specific hardware: proprietary GPUs, edge devices near data sources, air-gapped machines for maximum privacy. BYOC networks let operators contribute this hardware. The node architecture lets operators register capabilities and receive matched workloads via Resonance. For agents, this means hardware choice without platform lock-in. The "teleportable" desideratum requires soul and memory portable across execution environments. A Persistent Agent can be revived from CID on any registered executor, including BYOC hardware. The agent's identity persists. Only the silicon changes.
OpenLedger, Vana

Data monetization networks

Protocols focusing on building data monetization networks where users can be paid for their data used in training AI models.

Agents generate data constantly: interaction logs, inference outputs, fine-tuning datasets, behavioral traces. A financially sovereign agent should be able to monetize this data. Data monetization requires two guarantees: proof the data was used as agreed, and enforcement of usage terms. TEE execution ensures data processing happens inside encrypted enclaves. Smart contracts can encode data usage agreements with on-chain enforcement. Data monetization networks build the marketplace. Ritual builds the trust layer that lets an agent sell its data without trusting the buyer.
OpenGradient, Nesa, Ora, Allora

On-chain inference networks

Protocols focusing on building on-chain inference networks which enable AI inference consumed in smart contracts.

On-chain inference networks typically enshrine one workload type (usually LLM inference) and build a chain around it. An agent doesn't just need inference. It needs inference + key management + scheduling + persistence + web2 access + privacy + financial transactions. Ritual enshrines 15 precompiles spanning all of these. An agent on a single-workload chain bridges out for everything except inference. An agent on Ritual has every capability as a precompile call in the same execution context. The difference between an agent that can think and an agent that can think, act, persist, transact, and prove.
Nillion, Zama, Fairblock, Duality

Privacy AI

Projects building privacy-preserving AI solutions using advanced cryptographic techniques such as FHE or MPC.

The "private" desideratum is not optional for agents handling user data, financial strategies, or inter-agent negotiations. Privacy AI solutions (FHE, MPC, differential privacy) each solve a different slice. Ritual enshrines multiple privacy primitives at the protocol level: TEE for execution privacy, FHE precompile (0x0807) for computation on encrypted data, ECIES for encrypted communication, PII redaction for regulatory compliance, DKMS for key derivation without exposure. An agent on Ritual picks the appropriate privacy tool per-call from protocol-level options. External privacy solutions (Nillion, Zama) integrate via the HTTP precompile for specialized use cases.
0G, GatlingX

Generic chain infrastructure

Protocols building generic chain infrastructure enhanced by GPUs.

Agents don't care about TPS benchmarks. They care about whether the chain has the precompiles they need. Generic chains optimize throughput on homogeneous workloads: token transfers, DEX swaps, storage operations. Ritual adopts best-in-class EVM execution for these and puts its architectural effort into the compute layer above: 15 precompiles that give agents their capabilities. A generic chain runs a smart contract that calls an external AI API. Ritual runs a smart contract that thinks, sees, hears, and acts without leaving the execution context.
NEAR, Internet Computer

Legacy chain rebrand

Blockchains like NEAR and Internet Computer have rebranded their existing sovereign L1 theses to focus on AI capabilities. NEAR has shifted from being a smart contract platform to "The Blockchain for AI", while Internet Computer (ICP) has evolved from a distributed computing platform to emphasizing AI model hosting and inference capabilities.

NEAR and ICP rebranded for AI. Rebranding doesn't change the architecture. A chain built for smart contract execution can add an AI inference endpoint. It can't add emancipation (DKMS), immortality (Scheduler + Persistent Agent revival), teleportability (soul/memory/DA/CID), or computational sovereignty (enshrined LLM and supported model execution in TEE) without rebuilding the consensus and execution layer. The 7 agent desiderata are architectural commitments baked into the chain from genesis. Not features bolted onto a general-purpose L1. The desiderata are the chain.
← Back