On-chain governance for Cardano — with an AI agent that monitors, votes, and executes proposals autonomously.
Quorum is a three-layer Aiken smart contract stack (identity registry → governance → treasury) paired with a Claude-powered operator agent that watches the chain, evaluates proposals against configurable safety rules, casts votes, and triggers treasury transfers — without ever holding a private key.
Most governance tooling assumes a human is reading dashboards and clicking buttons. Quorum is designed for an AI agent to be the primary operator. Humans set the rules on-chain; the agent enforces them.
- The agent reads live chain state via Blockfrost
- It reasons about whether it should act — not just how
- Every decision (approved, rejected, skipped, anomaly) is written to an append-only audit log
- In default mode it describes its intent and waits for human confirmation before submitting anything
┌─────────────────────────────────────────────────────┐
│ Claude AI Operator Agent │
│ reads state · evaluates rules · builds tx · logs │
└────────────────────────┬────────────────────────────┘
│
┌──────────────▼──────────────┐
│ Web Dashboard │
│ Flask · CIP-30 wallet │
└──────────────┬──────────────┘
│
┌────────────────────▼────────────────────┐
│ Aiken Smart Contracts │
│ │
│ Identity Registry (Layer 1) │
│ members · roles · vote weights │
│ │ ref input │
│ Governance (Layer 2) │
│ proposals · weighted voting │
│ │ ref input │
│ Treasury (Layer 3) │
│ ADA locked · guarded release │
└──────────────────────────────────────────┘
Each layer reads the layer below it as a reference input — consumed for reading only, never spent — so lower-layer state is never disturbed by upper-layer transactions.
git clone https://github.com/jluong2/Quorum_ADA
cd Quorum_ADA
pip install anthropic flask cbor2
# Launch the dashboard in mock mode
python3 fos_ui/app.py
# → http://localhost:5000Mock mode generates a realistic demo state (5 members, 3 proposals, a treasury balance) so the full interface can be explored without a deployment or Blockfrost key.
Three Aiken validators, each holding one UTxO of on-chain state:
| Layer | Validator | Responsibility |
|---|---|---|
| 1 | identity_registry.ak |
Membership — key hashes, roles, statuses, version |
| 2 | governance.ak |
Proposals — typed actions, weighted voting, timelock |
| 3 | treasury.ak |
ADA — locked funds, guarded release |
Proposal actions:
| Action | Effect |
|---|---|
TreasuryTransfer |
Release ADA to an approved recipient |
RotateAdmin |
Replace the registry admin key |
UpdateRegistryMember |
Change a member's role or status |
OffChainDecision |
Record a governance decision with no on-chain execution |
Key safety properties:
- Registry mutations increment a version number. Governance proposals pin this version at creation — a membership change after a proposal is created invalidates that proposal, preventing quorum manipulation attacks.
- Treasury authenticates governance by script hash. A fake "Executed" UTxO at an arbitrary address cannot drain funds.
- Suspended members lose voting weight retroactively.
count_weighted_yeschecksstatus == Activeat execution time, not at vote-cast time. - Every validator requires a continuing output — state can never disappear from the chain.
A Claude-powered agent that monitors the deployed contracts and acts on pending governance items.
# One-shot: check state and act on any pending proposals
python3 -c "from fos_agent import run_fos_agent; run_fos_agent('Check state and take pending actions')"
# Continuous monitor (polls every 5 minutes)
python3 -c "from fos_agent import run_monitor; run_monitor(300)"Six enforced safety rules (baked into the system prompt):
- Only vote Yes on
TreasuryTransferiflovelace ≤ max_transfer_lovelaceand recipient is Active - Never vote or execute if
registry.version != proposal.registry_version— flag it and require a new proposal - Only execute if
current_time >= execute_after(timelock) andyes_score >= quorum - Only trigger a treasury transfer after the execute transaction is confirmed on-chain
- Write every decision to
.fos_audit.jsonl— approved, rejected, skipped, or anomaly - With
FOS_AUTONOMOUS_MODE=false(default), describe intent and wait for human confirmation
The agent builds UnsignedTransaction descriptors — structured specifications of inputs, outputs, redeemers, and validity range — passed to a separate signing layer. The agent never holds a private key.
Flask app with CIP-30 wallet integration (Eternl, Nami, Lace, VESPR). The server never holds a private key — all signing happens in the browser wallet.
python3 fos_ui/app.py # mock mode → http://localhost:5000
# Live mode
export BLOCKFROST_PROJECT_ID="preprod..."
export FOS_REGISTRY_SCRIPT_HASH="..."
export FOS_GOVERNANCE_SCRIPT_HASH="..."
export FOS_TREASURY_SCRIPT_HASH="..."
python3 fos_ui/app.py# 1. Compile the contracts
cd identity_registry && aiken build # produces plutus.json
# 2. Deploy to preprod testnet
export BLOCKFROST_PROJECT_ID="preprod..."
export DEPLOY_SIGNING_KEY="<32-byte Ed25519 hex>"
export DEPLOY_KEY_HASH="<vkey hash>"
export DEPLOY_COLLATERAL_REF="<txhash#index>"
python3 scripts/deploy.py
# Prints REGISTRY/GOVERNANCE/TREASURY script hashes to export
# 3. Start the agent
export FOS_REGISTRY_SCRIPT_HASH="..."
export FOS_GOVERNANCE_SCRIPT_HASH="..."
export FOS_TREASURY_SCRIPT_HASH="..."
export FOS_AGENT_KEY_HASH="..."
export ANTHROPIC_API_KEY="..."
python3 -c "from fos_agent import run_monitor; run_monitor(300)"Full environment variable reference and architecture details: PROJECT_OVERVIEW.md
pip install anthropic # agent (required)
pip install flask cbor2 # dashboard + CBOR parsing
pip install PyCardano # signing + address derivation
pip install chromadb sentence-transformers # RAG (optional)
pip install requests beautifulsoup4 # doc ingest (optional)Aiken CLI: aiken-lang.org — required only for contract compilation, not for running the agent or dashboard.
python3 test_fos_agent.py # operator agent (no API key required — chain calls mocked)
python3 test_agent.py # builder agentMIT