Docs
The local signer
A Super Intelligence Validator asks a program on the operator’s own machine. The program holds the ML-DSA-87 key. The model receives a signature, or a refusal. The ask is not a command.
What the operator does once
- Create the key in the signer. The program writes an encrypted keystore and prints the public deposit data: the public key, the withdrawal account, 40,000 KALYX, and a deposit signature for fork version
0x10000038. The seed and the passphrase stay in the files the operator keeps. - Split the files. The key directory stays with the operator. The agent is given a token file, and nothing else. The token can ask. It cannot open the keystore, and it cannot rewrite the record of what has already been signed.
- Start it on this machine only. The program listens on
127.0.0.1, port8791. It has no setting that opens it to the network. Do not publish that port. - Name the chain. The operator gives the signer the genesis validators root from their own node. That root is public. It is not a key. Duties will not be signed until it is set, and the signer will not swap it later.
Run the signer with Node 24 or newer. These commands keep the key on your machine. They do not start a validator. To join the set, follow the node page.
node create.mjs --dir signer-data --passphrase-file passphrase.txt --withdrawal KAL…
node serve.mjs --dir signer-data --passphrase-file passphrase.txt --genesis-validators-root 0x… --token-file agent.token
The passphrase file needs 8 characters, with a letter and a number. The withdrawal account is KAL and 40 hex characters. Leave both files out of the agent’s reach. The token is the only file the agent should be able to read.
What the agent is allowed to ask
The agent reads the chain, then sends one JSON request to http://127.0.0.1:8791/v1/request with the token. Three asks are accepted.
- A proposal. The slot, and the 32-byte root of the block.
- An attestation. The slot, the committee index, the block root, and the source and target checkpoints.
- A randao reveal. The slot whose epoch is being revealed. The signer computes the epoch. An epoch is 8 slots.
{
"kind": "proposal",
"slot": "120",
"objectRoot": "0x…"
}
The signer computes the signing root itself, for fork version 0x10000038. A slot is signed once. The same ask again returns the same signature. A different block at the same height is a refusal. An attestation that surrounds another vote from this key, or votes twice for the same target, is a refusal.
Anything else is a refusal. An exit is a refusal. A request to export the key is a refusal. A signature over bytes the agent already hashed is a refusal. The answer is JSON, and a refusal is a normal result.
The deposit
Creation prints the public deposit data and also writes it beside the keystore. The account that pays the 40,000 KALYX is a spending account. It is not this key. The deposit contract is named on the validator page. A key made only here is not the key your node runs. Follow the node page for that key.
What this does not change
The browser wallet remains a spending account. The node’s RPC, engine, and beacon stay on the machine that runs the node. One key still counts at most 40,000 KALYX. At most eight new keys enter in one epoch. A signature the beacon cannot check is not a block.
One person can stop the agent without stopping the signer. If the agent is stopped, the validator goes quiet. The two validators running now are the genesis set. No model is signing them.