Home
Quickstart Guides
Human approval for agent action

Human approval for AI agent actions

This page describes a setup, where an autonomous agent proposes transactions, and one or more human signers approve and execute the transaction.

This setup benefits from increased security, as the Smart Account can not be compromised by convincing the agent to execute a malicious transaction.

On the other hand, it can take minutes or hours to collect the necessary approvals, which reduces the agility of this setup.

Setup the Smart Account

For this setup, we recommend a 2-out-of-3, 3-out-of-5, or 5-out-of-7 threshold. The important considerations are:

  • The AI agent should be one signer
  • The threshold should be two more, so at least one human approval is required
  • The amount of signers should be higher than the threshold to make sure the Safe Smart Account is functional when one key is lost

Here is an example setup:

Deploy Safe

You can add the AI agent as a signer in the Safe Wallet (opens in a new tab).

You can also setup the Safe Smart Account programmatically like this using the Safe Protocol Kit:


_16
import Safe from '@safe-global/protocol-kit'
_16
_16
const AGENT_ADDRESS = // ...
_16
const AGENT_PRIVATE_KEY = // ...
_16
const HUMAN_SIGNER_1_ADDRESS = // ...
_16
const HUMAN_SIGNER_2_ADDRESS = // ...
_16
const RPC_URL = 'https://rpc.ankr.com/eth_sepolia'
_16
_16
const newSafe = await Safe.init({
_16
provider: RPC_URL,
_16
signer: AGENT_PRIVATE_KEY,
_16
safeOptions: {
_16
owners: [AGENT_ADDRESS, HUMAN_SIGNER_1_ADDRESS, HUMAN_SIGNER_2_ADDRESS],
_16
threshold: 2
_16
}
_16
})

Here, the AI agent creates the Safe Smart Account and adds two human signers for a 2-out-of-3 setup. The Smart Account will be deployed when the first transaction is executed.

Assemble and propose a transaction

The AI agent can now propose transactions. We recommend sending the transactions to the Safe Transaction Service. By this, you make sure that the transactions show up in the Safe Wallet interface and can easily be checked, approved and executed by the human signers.

You can use the API Kit to propose transactions to the Safe Transaction Service.

A simple example transaction to the zero address can be proposed like this:


_31
import SafeApiKit from '@safe-global/api-kit'
_31
_31
// How to get an Api key => http://docs.safe.global/core-api/how-to-use-api-keys
_31
const apiKit = new SafeApiKit({
_31
chainId: 11155111n,
_31
apiKey: 'YOUR_API_KEY'
_31
})
_31
_31
const tx = await newSafe.createTransaction({
_31
transactions: [
_31
{
_31
to: '0x0000000000000000000000000000000000000000',
_31
data: '0x',
_31
value: '0'
_31
}
_31
]
_31
})
_31
_31
// Every transaction has a Safe (Smart Account) Transaction Hash different than the final transaction hash
_31
const safeTxHash = await newSafe.getTransactionHash(tx)
_31
// The AI agent signs this Safe (Smart Account) Transaction Hash
_31
const signature = await newSafe.signHash(safeTxHash)
_31
_31
// Now the transaction with the signature is sent to the Transaction Service with the Api Kit:
_31
await apiKit.proposeTransaction({
_31
safeAddress: safeAddress,
_31
safeTransactionData: tx.data,
_31
safeTxHash,
_31
senderSignature: signature.data,
_31
senderAddress: AGENT_ADDRESS
_31
})

Approve and execute the transactions

The transactions will now show up in the transaction interface of the Safe Wallet (opens in a new tab). The human signers now have to connect their Metamask, and approve and/or execute the transactions with a click. They can also use the Mobile App (opens in a new tab) to sign the transactions.

In the Safe Wallet, the human signers will see the transaction in the queued transaction view:

ai-agent-approve-transaction-1

And can either add a signature or execute the transaction when enough signatures were collected:

ai-agent-approve-transaction-2

Next steps

Now your AI agent is equipped with a Safe Smart Account and you are in full control of the transactions. We are exited to see what you will build.

If you have a technical question, feel free to reach out on Stack Exchange (opens in a new tab) with the safe-core tag.

Was this page helpful?