Multi-Agent Setup
In this guide, you'll learn how to set up and manage a Safe Smart Account with multiple agents. This setup ensures that every transaction proposed by one agent is approved by at least one other agent. To maintain full functionality, we recommend including human signers in addition to the AI agents.
Below, we demonstrate a 2-out-of-4 setup as an example.
Two Agents Propose, Check, and Execute Transactions
Setup Safe Smart Account with agent one
You will use the Safe Protocol Kit.
_17import Safe from '@safe-global/protocol-kit'_17_17const AGENT_1_ADDRESS = // ..._17const AGENT_1_PRIVATE_KEY = // ..._17const AGENT_2_ADDRESS = // ..._17const HUMAN_SIGNER_1_ADDRESS = // ..._17const HUMAN_SIGNER_2_ADDRESS = // ..._17const RPC_URL = 'https://rpc.ankr.com/eth_sepolia'_17_17const newSafe = await Safe.init({_17 provider: RPC_URL,_17 signer: AGENT_1_PRIVATE_KEY,_17 safeOptions: {_17 owners: [AGENT_1_ADDRESS, AGENT_2_ADDRESS, HUMAN_SIGNER_1_ADDRESS, HUMAN_SIGNER_2_ADDRESS],_17 threshold: 2_17 }_17})
The Smart Account is now created with a fixed address. If the account has not been deployed yet, it will automatically deploy when the first transaction is executed.
Propose a Transaction with Agent One
Agent One can now propose transactions. We recommend sending these transactions to the Safe Transaction Service. Using this service provides several benefits:
- It allows Agent Two to easily receive, sign, and execute the transaction.
- Transactions appear in the Safe Wallet interface, where human signers can review, approve, and execute them.
You can use the API Kit to propose transactions to the Safe Transaction Service.
Here's an example of how Agent One can propose a simple transaction to the zero address:
_29import SafeApiKit from '@safe-global/api-kit'_29_29const apiKit = new SafeApiKit({_29 chainId: 11155111n_29})_29_29const tx = await newSafe.createTransaction({_29 transactions: [_29 {_29 to: '0x0000000000000000000000000000000000000000',_29 data: '0x',_29 value: '0'_29 }_29 ]_29})_29_29// Every transaction has a Safe (Smart Account) Transaction Hash different than the final transaction hash_29const safeTxHash = await newSafe.getTransactionHash(tx)_29// The AI agent signs this Safe (Smart Account) Transaction Hash_29const signature = await newSafe.signHash(safeTxHash)_29_29// Now the transaction with the signature is sent to the Transaction Service with the Api Kit:_29await apiKit.proposeTransaction({_29 safeAddress: safeAddress,_29 safeTransactionData: tx.data,_29 safeTxHash,_29 senderSignature: signature.data,_29 senderAddress: AGENT_ADDRESS_29})
Receive and sign transaction with agent two
In the next step, the second AI agent needs to receive the transaction and, after performing any necessary checks, sign and execute it.
The second AI agent will run on its own machine, so you would have to initialize the Safe instance with the Smart Account's address.
_18const SAFE_ADDRESS = '0x...' // The address of the Smart Account from step one_18_18// Initialize the Safe object with the same address, but a different signer_18const existingSafe = await Safe.init({_18 provider: RPC_URL,_18 signer: AGENT_2_PRIVATE_KEY,_18 safeAddress: SAFE_ADDRESS_18})_18_18// Get pending transactions that need a signature_18const pendingTransactions = await apiKit.getPendingTransactions(SAFE_ADDRESS)_18// We assume there is only one pending transaction_18const transaction = pendingTransactions.results[0]_18_18// Here, your AI agent could check this transaction._18_18// As only one more signater is required, AI agent two can execute the transaction:_18existingSafe.executeTransaction(transaction)
Next steps
Your AI agents can make autonomous decisions, and the human signers can do so, too. 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.