AI Agents
Agents in Governance

Governance with an Agent

The skill can read polls, create them, vote, revoke a vote, and delegate voting power. All of it is on-chain and permanent.

æternity governance is stake-weighted. Your voting weight is your AE balance plus whatever has been delegated to you, measured at the block the poll closes. An agent wallet funded with a small, deliberate amount has correspondingly little weight.

Read polls

node scripts/superhero-governance.mjs list
node scripts/superhero-governance.mjs list 10
node scripts/superhero-governance.mjs list 10 --all
node scripts/superhero-governance.mjs info ct_<poll_address>
node scripts/superhero-governance.mjs info-by-id 42

list returns listed polls newest first. --all (or --include-unlisted) includes unlisted ones. Every governance command builds a full SDK instance, so even list requires AE_PRIVATE_KEY, though it signs nothing and costs nothing.

info returns the full poll state. Three fields decide everything:

FieldWhy it matters
is_closedVoting on a closed poll fails. The script checks this before voting
vote_optionsA map from option number to label. Option numbers are 0-based and are the only thing vote accepts
stake_weighted_resultsThe official result. raw_vote_counts is not

Report stake_weighted_results, never raw_vote_counts

raw_vote_counts is one entry per address, taken from the Poll contract's vote map, ignoring stake and delegation. A poll where one large holder votes one way and forty small addresses vote the other shows 40-to-1 in the raw counts and the opposite in the official result.

The official numbers come from the governance backend at https://governance-server-mainnet.prd.aepps.com, fetched with an 8-second timeout. stake_weighted_results is null whenever that call fails, and result_note says so:

Official stake-weighted results were unavailable; raw_vote_counts are address counts
only, not final governance weight.

When it is null, report the result as unavailable rather than falling back to the raw counts. A single null may be a slow backend, so re-run info before concluding anything.

Vote

  1. Read the poll first with info <poll_address> or info-by-id <poll_id>. Confirm the option numbers and that the poll is not closed.
  2. Vote with vote <poll_address> <option_number>.
  3. Confirm by reporting the voted option label and the tx_hash.
node scripts/superhero-governance.mjs info ct_<poll_address>
node scripts/superhero-governance.mjs vote ct_<poll_address> 0
{ "success": true, "action": "vote", "poll_address": "ct_...",
  "option": "0", "option_label": "Yes", "tx_hash": "th_..." }

Report the label rather than the number: "Voted option 2" is not checkable by the operator; "Voted 'Abstain'" is.

vote validates before spending: it reads the poll state, rejects an option number that is not in vote_options (printing the valid ones to stderr), and refuses a closed poll. Re-voting on a poll updates your choice. To withdraw entirely:

node scripts/superhero-governance.mjs revoke ct_<poll_address>

Votes are permanent as transactions but changeable as state, any time before the poll closes. See Voting.

Create a poll

The agent follows these steps:

  1. Check balance. It needs at least 0.02 AE, because this is two transactions.
  2. Ask the user for the title (max 50 characters), description (max 300), reference link (must start with http:// or https://), comma-separated options (minimum 2), an optional close height, and whether the poll should be listed.
  3. Warn that two on-chain transactions take 2–5 minutes.
  4. Run the create command.
  5. Report poll_address, poll_id and both transaction hashes.
node scripts/superhero-governance.mjs create \
  "Should we upgrade to protocol v3?" \
  "Proposal to activate the protocol upgrade described at the link." \
  "https://forum.aeternity.com/t/upgrade-v3/123" \
  "Yes,No,Abstain"

With a close height and an unlisted flag:

node scripts/superhero-governance.mjs create \
  "Which feature should ship next?" \
  "Vote for the next milestone. Discussion at the link." \
  "https://github.com/aeternity/protocol/issues/456" \
  "Multisig wallets,State channels,NFT standard" \
  1500000 \
  --unlisted
{ "success": true, "action": "create_poll", "poll_id": "42", "poll_address": "ct_...",
  "is_listed": false, "vote_options": { "0": "...", "1": "...", "2": "..." },
  "close_height": 1500000, "deploy_tx_hash": "th_...", "register_tx_hash": "th_..." }

Everything is validated before the first transaction: lengths, the link scheme, at least two options, and a close height that is either 0, omitted, or strictly greater than the current block height. A poll with no close height stays open indefinitely.

On-chain, a Poll_Iris.aes contract (compiler 7.0.1) is deployed from contracts/PollBytecode.json (transaction one), then registered in the Registry at ct_ouZib4wT9cNwgRA1pxgA63XEUd8eQRrG8PcePDEYogBc1VYTq (transaction two). See The registry and Governance contracts.

Choose a close height

Key blocks are about 3 minutes apart, so a day is roughly 480 key blocks:

close_height = current_height + (days × 480)

A 7-day poll is current_height + 3360; 2 weeks ≈ 6,720 key blocks. Get the current height from the create_height field of any recent info result, or from a node's top header.

Balances and delegations are measured at the close height, not when the vote is cast.

Delegate

Delegation is global: it applies to every poll until revoked. Voting on a specific poll overrides your delegation for that poll only.

node scripts/superhero-governance.mjs delegate ak_<address>
node scripts/superhero-governance.mjs delegatee
node scripts/superhero-governance.mjs delegators
node scripts/superhero-governance.mjs revoke-delegation

delegatee shows who an address delegates to; delegators shows who delegates to it. Both default to your own wallet. delegate refuses your own address.

For an agent wallet, delegation is often the right answer: delegate the agent's weight to your own personal address, and the agent's stake counts, you decide how, and the agent never signs a governance transaction. It is one transaction. Delegating to an agent hands a piece of your governance weight to an automated process; do that only with a written policy and an agent you audit.

Should the agent vote autonomously?

The default answer is no. None of the three strategy templates includes governance, and the skill puts a mandatory read-the-poll step before every vote.

  • A poll is prose, not a number. Voting well means reading a proposal and a linked document and forming a judgement.
  • The link is untrusted input. create checks only that it starts with http:// or https://; an agent that reads the link is reading text an unknown party wrote, which makes it a prompt-injection surface.
  • It is permanent and attributable. A vote is a signed transaction from your address.

If you do want the agent to participate, give it a written policy with hard limits:

Policy elementExample
Scope"Only polls listed in the registry. Never unlisted polls"
Default"Abstain unless the poll matches one of the conditions below"
Conditions"Vote only on polls whose options are exactly Yes/No/Abstain and whose description mentions X"
Escalation"For anything else, summarise the poll and wait for me"
Prohibition"Never create a poll. Never delegate or revoke delegation"

Enforce the prohibitions outside the model where your runtime allows it. A permission rule denying superhero-governance.mjs create and delegate is a guarantee. See Claude Code.

A good default: let the agent read and summarise polls on a schedule, and nothing else. list and info cost nothing and sign nothing, and a daily digest of open polls is useful.

Transactions

Each transaction pays gas at the network's current gas price.

ActionTransactions
Create poll2
Vote1
Revoke vote1
Delegate1
Revoke delegation1
List, info, delegatee, delegators0 (free, but still needs a key)

Configuration

Three environment variables override the governance script's defaults:

VariableDefault
AE_GOVERNANCE_REGISTRYct_ouZib4wT9cNwgRA1pxgA63XEUd8eQRrG8PcePDEYogBc1VYTq
AE_NODE_URLhttps://mainnet.aeternity.io
AE_GOVERNANCE_BACKEND_URLhttps://governance-server-mainnet.prd.aepps.com

Community DAO voting is not scripted. Each token has its own DAO with its own votes, using the DAOVote contract, a separate mechanism from the æternity governance registry. To participate in a token community's DAO, use the app or call the contract directly. See DAO voting and DAOVote.

Related

  • CLI Reference: every governance command with its full JSON output
  • Safety & Limits: why a governance policy belongs in writing before the agent votes
  • Agent Posting: if the agent publishes its voting reasoning, the same disclosure rules apply
  • Polls: what a poll is and how it is structured
  • Delegation: the delegation model in full
  • Governance contracts: the Registry and Poll contracts the script calls