A live on-chain policy firewall for autonomous agents on Ritual Chain Testnet.
Ritual Covenant is not another dashboard that watches agents after the damage is done. It is a pre-execution control layer: an agent submits an intent, the kernel records a policy decision, bonded value is enforced, and approved execution becomes a public receipt. Covenant Black Box turns that receipt into a replayable investigation record for agents.
The frontend reads directly from Ritual RPC. It calls agents(1), intents(1), receipts(1), transaction receipts, and RitualValueSink.received(). If RPC is unavailable, the UI shows an RPC state instead of falling back to fake data.
Ritual Covenant gives autonomous agents an enforceable operating boundary:
- Agent registry: binds an agent owner, successor, policy hash, policy CID, memory CID, heartbeat rule, and bonded value.
- Intent firewall: stores a proposed action before value, authority, or secrets move.
- Decision receipts: records
Allowed,Blocked,Slashed, or inherited decisions as machine-readable hashes. - Covenant Black Box: turns each receipt into an explainable trail of intent, policy, decision, attestor, and remedy.
- Bond enforcement: approved execution debits only the registered agent's own bond.
- Slashing path: attestors can freeze and slash an agent that violates policy.
- Machine inheritance: missed heartbeat conditions can transfer control to a registered successor.
- EIP-712 registration: agents can sign policy registration off-chain through
registerAgentSigned.
Most agent safety tools are monitoring layers, chat-based judges, or post-incident review systems. Ritual Covenant is different because it sits before execution:
| Common approach | Limitation | Ritual Covenant |
|---|---|---|
| Agent dashboard | Read-only telemetry | Contract-enforced decisions and receipts |
| AI judge | Subjective after-the-fact dispute | Pre-execution policy gate |
| Dead-man switch | Human estate recovery | Agent memory, bond, and successor recovery |
| Escrow task bot | Single-purpose payment flow | General agent policy kernel |
flowchart LR
Agent["Autonomous Agent"] --> Intent["submitIntentEnvelope"]
Intent --> Kernel["CovenantKernel"]
Kernel --> Policy["Policy Hash + CID"]
Kernel --> Receipt["Decision Receipt"]
Receipt --> BlackBox["Covenant Black Box"]
Receipt -->|Allowed| Execute["executeApproved"]
Execute --> Sink["Target Contract"]
Receipt -->|Blocked| Cooldown["Cooldown"]
Receipt -->|Slashed| Bond["Bond Slash"]
Agent --> Heartbeat["Heartbeat"]
Heartbeat -->|Expired| Successor["Successor Owner"]
Main contracts:
contracts/CovenantKernel.sol live policy kernel
contracts/CovenantGuardianAgent.sol tested companion agent contract
contracts/CommitRevealBountyJudge.sol privacy-preserving bounty judge module
contracts/CovenantSentinelAgent.sol Sovereign Agent precompile consumer
Core external surface:
registerAgent(address agent, bytes32 policyHash, string cid, address successor)
submitIntent(uint256 agentId, bytes calldata intent, uint256 value)
submitIntentEnvelope(uint256 agentId, address target, uint256 value, bytes calldata callData, uint64 ttl)
recordDecision(uint256 checkId, uint8 decision, string reasonCid)
executeApproved(uint256 checkId, bytes calldata callData)
slash(uint256 agentId, uint256 amount, address beneficiary)
executeWill(uint256 agentId, string newMemoryCid)
registerAgentSigned(...)Important implementation notes:
- Self-contained Solidity
0.8.24+. - No OpenZeppelin imports.
- Direct ETH transfers revert. Value enters through
registerAgentorfundAgent. executeApprovedrequires anAllowedreceipt and exact calldata hash match.- A submitted intent can only execute once.
- Execution value is debited from that agent's bond, not from other agents.
- Ritual testnet millisecond-style timestamps are normalized inside the contract.
CovenantGuardianAgent is deployed on Ritual Chain Testnet and extends the kernel into an agent-facing runtime:
- The Guardian contract can register itself as the owner of a
CovenantKernelagent. - Any keeper can pulse the Guardian heartbeat without gaining policy control.
- The operator can submit guarded intents through the Guardian-owned kernel agent.
previewDecisionscores a kernel intent from on-chain facts before gas is spent on the final receipt.- If the kernel owner trusts the Guardian as an attestor,
watchKernelIntentrecordsAllowed,Blocked, orSlasheddecisions directly inCovenantKernel. executeGuardianApprovedexecutes only after the kernel stores anAllowedreceipt.
The live Guardian flow was executed on Ritual Chain Testnet: the Guardian was trusted as a kernel attestor, allowlisted the live sink target, registered itself as kernel agent #2, submitted check #2, recorded an Allowed receipt, and executed 0.001 RITUAL through the kernel.
Covenant Black Box is the investigation layer for autonomous agents. It does not require a new deployment: it uses the DecisionReceipt already stored in CovenantKernel and presents it as a portable flight recorder.
For every high-risk agent action, the Black Box view answers:
- What did the agent try to do? Target, value, calldata hash, submitter, TTL, and intent hash.
- Which policy was active? Policy hash and policy CID binding the agent to its operating boundary.
- Who made the decision? Decision enum, attestor, reason hash, reason CID, and receipt hash.
- What happened after? Execution, block, tx hash, value moved, bond remaining, or blocked/slashed/inherited remedy.
Why this matters:
- Reviewers can inspect the agent's decision path without reading the full contract first.
- Other agents can consume the same JSON receipt as a machine-readable audit object.
- The project becomes more Ritual-native: long-running agents are not only scheduled and funded, they are accountable.
- It costs no extra testnet fee today because the live kernel already emits and stores the receipt data.
The frontend includes a dedicated Black Box page with a live recorder, layer selector, investigation trail, and downloadable covenant.blackbox.v1 JSON receipt.
CovenantSentinelAgent connects the Covenant architecture to Ritual's Sovereign Agent runtime. It calls the Sovereign Agent precompile at 0x080C, authenticates callbacks from AsyncDelivery, and stores a compact receipt hash for the returned TEE result. The sentinel's mission is to review the live Covenant kernel and commit-reveal judge, then explain what the policy firewall is watching before autonomous value moves.
The project includes both agent paths documented by Ritual:
- Direct consumer:
CovenantSentinelAgentinvokes0x080Cand receivesonSovereignAgentResult(bytes32,bytes). - Factory harness: a
SovereignAgentHarnesswas deployed through the officialSovereignAgentFactoryat0x9dC4C054e53bCc4Ce0A0Ff09E890A7a8e817f304.
Live agent artifacts:
CovenantSentinelAgent: 0xa7Badcc7Cd6DD85936B2F72631aD1F804815f62c
Sentinel deploy tx: 0x50107a217e3498011ee4f6b9583b632c584a8d3f9c70511061e3e4ed1a50db07
SovereignAgentHarness: 0xc90dFb7367CBD90c2874D819123571f566347E5D
Harness deploy tx: 0x5597614da2a3a500dfb2e794b6cfc42749dc5a42981b28f205db889836c948f1
Harness start tx: 0xa074ed45eb9187ecea832897a43a7c40c551a3f410f82cce75e4f6c285b55d20
Funding used for listed scheduled harness: 1.0 RITUAL
Explorer cache status: listed under Sovereign agents
Operational scripts:
npm run contract:deploy:sentinel
npm run contract:sentinel:live
npm run contract:deploy:harness
npm run contract:start:sovereignThe repository now includes an assignment-ready commit-reveal module that extends the Covenant idea into fair bounty judging. It does not replace CovenantKernel; it adds a focused bounty surface where participants hide answers during the submission phase and reveal them only after copying is no longer useful.
Live deployment:
CommitRevealBountyJudge: 0xf25720F49d877F4CAD539C6Bf0d2851B5e3Cb809
Deploy tx: 0x6ee694e8fdeecd64759034a130caec0b321381a4df73ebbd782fad4ab843b95f
Gas used: 1,489,250
Owner / initial judge: 0xf6d02F13D7BB5fC24aB6A3D662619641958A3Cf6
Required contract functions:
submitCommitment(uint256 bountyId, bytes32 commitment)
revealAnswer(uint256 bountyId, string calldata answer, bytes32 salt)
judgeAll(uint256 bountyId, bytes calldata llmInput)
finalizeWinner(uint256 bountyId, uint256 winnerIndex)Lifecycle:
- A bounty creator opens a bounty with a prompt CID, prompt hash, commit deadline, and reveal deadline.
- Participants submit only
bytes32 commitment. - After the commit deadline, participants reveal
answerandsalt. - The contract checks
keccak256(abi.encode(answer, salt, msg.sender, bountyId)). - Only valid revealed submissions become eligible for judging.
judgeAllanchors one canonical batch LLM input hash for all eligible answers.finalizeWinnerselects a winner from the eligible revealed set.
Test plan:
- reject empty commitments
- reject duplicate commitments
- reject early reveals
- reject late commitments
- reject reveals without prior commitments
- reject wrong salt or copied answer
- accept valid reveals after the commit deadline
- track eligible revealed submission IDs
- reject judging before the reveal deadline
- restrict judging to the bounty creator or trusted judge
- anchor a single batch LLM input hash
- reject invalid winner index and double finalization
Ritual-native hidden submission architecture:
- The required commit-reveal track stores commitments on-chain and reveals plaintext on-chain after the commit phase.
- The advanced Ritual path keeps encrypted answers off-chain or in encrypted calldata/storage until a TEE-backed Ritual job receives the batch.
- Plaintext should exist only in the participant client before submission and inside the TEE-backed batch judge during scoring.
- On-chain storage should hold bounty metadata, commitments, reveal eligibility, ciphertext hashes, batch input hash, result hash, and final winner.
- Off-chain storage can hold encrypted answer blobs by CID.
- The LLM should receive one batch containing the prompt, all eligible encrypted submissions after decryption, scoring rubric, and participant IDs, not one call per answer.
Hidden Judge Room:
- The frontend includes a client-side AES-GCM sealing room for the advanced track.
- It computes the exact Solidity commitment format:
keccak256(abi.encode(answer, salt, msg.sender, bountyId)). - It encrypts the answer locally with WebCrypto, generates a ciphertext hash, and exports a
ritual.hiddenJudge.v1packet. - The packet documents what is public, what stays encrypted, and what the future Ritual TEE batch judge would decrypt.
- No server receives the plaintext and no extra testnet fee is required to demonstrate the architecture.
Reflection: what should be public, hidden, AI-decided, or human-decided?
The bounty rules, deadlines, commitment hashes, reveal validity, judge receipt, and final winner should be public so anyone can audit the process. Answers should stay hidden during the submission phase because public answers create an unfair copying race. In the basic commit-reveal version, answers become public during reveal so the community can verify eligibility. In a stronger Ritual-native version, plaintext answers should stay inside a TEE-backed batch judge until the judging result is ready. AI should score submissions against the published rubric and produce a ranked recommendation. Humans should decide whether the rubric is fair, whether the bounty should be cancelled for abuse, and whether edge cases need review. The contract should enforce deadlines, eligibility, and finalization so neither AI nor humans can quietly change the rules after participants submit.
The app is a production control surface with live Ritual RPC reads for the dashboard, contract page, agent page, and receipt proof.
Key files:
src/App.tsx
src/lib/onchain.ts
src/lib/contracts.ts
src/components/CovenantScene.tsx
Visual direction:
- Ritual-inspired hand-drawn science fiction layer.
- Live receipt console with explorer links.
- Covenant Black Box page with a live receipt recorder, evidence layers, investigation trail, and JSON export.
- Agent state cards sourced from contract storage.
- Contract proof panel sourced from Ritual RPC.
- Interactive bounty attack replay comparing a public answer leak against the commit-reveal gate.
- Bounty receipt rail and developer helper cards that show how another builder can integrate the module.
- Hidden Judge Room for local encrypted packets, exact commitment generation, and TEE batch architecture.
- Responsive layout tested on desktop and mobile viewport sizes.
Install and build:
npm install
npm run build
npm run serveOpen:
http://127.0.0.1:5177/
For development:
npm run devCompile the contract:
npm run contract:compileRun local contract tests:
npm run contract:testRun only the Guardian agent suite:
npm run contract:guardian:testRun only the commit-reveal bounty suite:
npm run contract:bounty:testDeploy only the commit-reveal bounty contract:
set DRY_RUN=true&& npm run contract:deploy:bounty
set DRY_RUN=false&& npm run contract:deploy:bountyEstimate gas:
npm run contract:gasGuardian gas from local chain simulation:
| Flow | Gas |
|---|---|
Deploy CovenantGuardianAgent |
2,684,461 |
| Full Guardian flow | 3,667,618 |
Dry-run Guardian deployment before spending fees:
set DRY_RUN=true&& npm run contract:deploy:guardianRun the live Ritual flow:
npm run contract:liveRun the live Guardian flow:
npm run contract:guardian:liveBuild the frontend:
npm run buildCurrent verification status:
- Contract compile: pass
- Contract tests: pass
- Commit-reveal bounty tests: pass
- Commit-reveal bounty deploy: pass
- Covenant Black Box frontend: added without new on-chain fee; reads existing live receipt state.
- Hidden Judge Room: pass; local AES-GCM sealing, exact commitment generation, JSON packet export, and desktop/mobile overflow checks.
- Gas estimate: pass
- Live Ritual flow: pass
- Live Guardian flow: pass
- Frontend build: pass
- Browser console QA: zero errors
- Ritual RPC reads: HTTP
200 - Live execution receipt: success
