本文へ移動
Safe Ops & Web3 Operations

AIエージェントが準備できることと人が署名する場所:Safeマルチシグ運用の権限境界

AIエージェントはSafeトランザクションを準備し検証できますが、資金を動かす署名は人間のオーナーの手に残すべきです。

公開日 更新日 14 分で読める
SafemultisigAI agentsWeb3 opshuman approval

この記事は教育目的であり、正式なスマートコントラクト監査、法的助言、金融助言、またはプロトコル固有のセキュリティレビューに代わるものではありません。

AIエージェントをトレジャリーにつなぐと、仕事の性質が変わります。残高の読み取り、コールのデコード、送金の下書きは、資金の移動を承認することとは別物です。準備・署名・実行の境界は、AIエージェントのプロンプトではなく、エージェントが触れられるツール、鍵、コントラクト上の経路によって強制する必要があります。

光る青い立方体と書類がガラスのパネルの向こうにあり、手前では片手が署名デバイスのオレンジ色のボタンを押している。
エージェントはガラスの向こうで準備し、署名は人の手に残る。コンセプトイラスト。

Safeでの権限レビューは、オーナーとしきい値だけでは終わりません。有効化されたモジュール、トランザクションガード、そして各署名者が承認する正確なEIP-712ハッシュが、誰が資金を動かせるかを決めます。

マルチシグを運用する小規模なWeb3チームにとって役に立つ成果物は、署名者が中身を確認できるレビューパッケージです。何をするのか、どのチェーンで、どのコントラクトに対して、どんな条件で、どんな証跡があるのか。サービスページはこの方法を概要レベルで説明しています。本記事はそれをオペレーターのレベルまで落とし込み、表示しているインターフェースに頼らずに各要素を確認できるコマンドを示します。

署名・権限ポイントとは何か

AIエージェントとともに運用するSafeマルチシグにおいて、署名・権限ポイントとは、エージェントが準備できる作業と、人が承認する操作とを分ける技術的・運用的な境界です。誰が提案するのか、どんな権限を持つのか、どのトランザクションをレビューするのか、誰が署名するのか、そして後から何が起きたかを確認できる証跡は何かを特定します。

人による承認は、すでに文書化されたアーキテクチャの一部であり、新しい考え方ではありません。AIエージェントの操作に対する人の承認についてのSafeのガイドでは、エージェントを署名者の一人とし、2-of-3、3-of-5、5-of-7のようなしきい値によって少なくとも一人の人間の承認が必要になる構成を示しています。本記事では、より制限の強い構成を選びます。どの署名もエージェントの権限下には置きません。これはこの運用フローのための設計判断です。

この違いにはコストがあり、きちんと見ておく価値があります。エージェントを署名者にすれば、操作ごとに人の署名を一つ減らせますが、エージェントが持つ鍵がSafeの権限の一部になります。さらに、エージェントがオーナーであり、かつトランザクションを送信するアカウントでもある場合、Safeは追加の署名なしにその承認を数えます。事前承認ハッシュという署名タイプが、実行するオーナーを承認済みとして扱うためです。署名の委任は、繰り返し発生する範囲の限られた操作では意味を持ち得ますが、その場合の制限はエージェントの指示ではなく、別途レビューしたモジュールやガードに置くべきです。

エージェントがオーナーでなくても提案できるように、Safe Transaction Serviceはデリゲートをサポートしています。デリゲートとは、オーナーが自分に代わって提案を投稿することを信頼して認めたアドレスです。デリゲートまたはオーナーが署名した提案はSafe Walletに表示され、それ以外はサービスに保存されても表示されません。デリゲートにはオンチェーンの権限がなく、オーナーではないため、コントラクトはその署名をしきい値に数えません。

準備をレビュー可能にする五つの要素

署名者とは別のアイデンティティ。エージェントの実行環境には専用の運用アイデンティティが必要で、参照すべきデータソースのための認証情報だけを持たせます。提案も行うなら、どのオーナーとも異なるデリゲートアドレスを用意します。これにより、一つ一つの読み取りや下書きを特定の実行に結び付けられます。署名者の鍵は各自のウォレットやカストディシステムに置いたままにし、エージェントのコンテキストやツールには入れません。

操作ごとに定義する権限。ポリシーには、特定ネットワークへの問い合わせ、Safeの状態の読み取り、コールのデコード、固定ブロックでのシミュレーション、提案の投稿といった具体的な操作を書きます。読み取り、シミュレーション、提案のツールは分け、署名や送信を行うRPCメソッドは明示的に拒否します。広すぎる認証情報や任意のコマンドを受け付けるツールは、その範囲を追加でレビューする必要があります。

次のスニペットは独自フォーマットによる例示であり、特定の製品のスキーマではありません。RPCメソッド名は、Ethereumとウォレットの標準的な名称です。

yaml
# エージェントのツールポリシー:例示、独自フォーマット
agent: treasury-preparer
chains: [1]                      # 許可するchainId
safes: ["0xSAFE..."]             # 読み取りと提案を許可するSafe
rpc:
  allow: [eth_chainId, eth_blockNumber, eth_call, eth_getCode, eth_getStorageAt, eth_getLogs]
  deny:  [eth_sendTransaction, eth_sendRawTransaction, eth_sign, eth_signTransaction,
          eth_signTypedData, eth_signTypedData_v3, eth_signTypedData_v4, personal_sign,
          wallet_sendCalls, eth_sendUserOperation]
  default: deny                  # allowにないものはすべて拒否
tools:
  decode_calldata: allow
  simulate_call: allow           # 読み取り専用、固定ブロック
  propose_to_tx_service: allow   # デリゲートとして:オンチェーン権限なし
  sign: deny
  execute: deny
payload_rules:
  operation: [0]                 # 0 = CALL、1 = DELEGATECALLは人にエスカレーション
  safeTxGas: 0                   # 0なら、内部コールが失敗するとトランザクション全体がリバートする
  baseGas: 0
  gasPrice: 0                    # ガスの払い戻しなし
  gasToken: "0x0000000000000000000000000000000000000000"
  refundReceiver: "0x0000000000000000000000000000000000000000"
  on_missing_data: stop_and_escalate

私たちが提案する設計では、制限はモデルの推論の外側で適用されます。ツールは付与された権限を超える要求を拒否します。操作の評価に必要なデータが欠けていれば、フローは止まり、レビューを求めます。

ペイロードに結び付いたレビューパッケージ。オーナーが署名するのは、to、value、data、operation、safeTxGas、baseGas、gasPrice、gasToken、refundReceiver、nonceの十個のフィールドに対するEIP-712ハッシュです。バージョン1.3.0以降、このハッシュのドメインには、chainIdとSafe自身のアドレスが含まれます。パッケージには宛先と金額だけでなく十個すべてのフィールドを示す必要があります。そのうちのいくつかが署名の意味を変えるからです。

  • operationは、CALLなら0、DELEGATECALLなら1です。DELEGATECALLでは宛先のコードがSafeのコンテキストで実行され、設定を含むSafeのストレージに書き込めます。このフローでは、0以外の値はすべて人にエスカレーションします。
  • gasPrice、gasToken、refundReceiverは、Safeが支払うガスの払い戻しを定義します。gasPriceが0なら払い戻しはありません。refundReceiverがゼロアドレスなら、払い戻しはtx.origin、つまりトランザクションを送信した者に支払われます。
  • nonceは順序を決めます。リバートしなかったexecTransactionのたびに、内部コールが失敗していても(safeTxGasまたはgasPriceが0でない場合に起こりえます)増えるため、ある署名の組は特定のnonceに対してだけ有効です。

Safeは、スマートアカウントのトランザクションハッシュであるsafeTxHashと、最終的にネットワークに送られるトランザクションのハッシュとを区別しています。パッケージには両方を記録し、人の判断との対応関係を残します。

署名前の独立したチェック。ネットワーク、アドレス、パラメーター、nonce、適用されるポリシーなど、決定論的に確認できるものはすべて、エージェントから独立したコードとツールで検証することを提案します。中心となるのは、提案したツールの外でsafeTxHashを再計算し、ウォレットや署名デバイスに表示されるハッシュと照合することです。画面にドメインハッシュとメッセージハッシュが別々に表示される場合は、両方を照合します。

署名が承認するのは、ウォレットに提示された特定のメッセージです。ペイロードのフィールドが一つでも変われば、ハッシュが変わり、レビューはやり直しになります。前の下書きへの承認が次の下書きに引き継がれることはありません。

準備と結果をつなぐ証跡。運用記録には、参照したソース、下書き、チェック結果、レビュー担当者の判断、署名、最終的な実行を、各読み取りのブロック番号とともに結び付けて残します。提案するモデルでは、エージェントは証跡を提供できますが、人の判断を変更したり、検証ツールの元の結果を置き換えたりすることはできません。

提案するフローの手順

  • ステップ1:読み取りと提案の権限を持つエージェントが、Safeの状態を集め、証跡とともに下書きを作成します。
  • ステップ2:エージェントから独立した検証ツールが、コールをデコードし、safeTxHashを再計算し、固定ブロックでシミュレーションします。
  • ステップ3:パッケージが不完全な場合やチェックが失敗した場合、下書きはステップ1に戻るか人にエスカレーションされます。データが欠けたまま先に進むことはありません。
  • ステップ4:パッケージが有効なら、署名者がレビューし、自分で確認したハッシュに署名します。
  • ステップ5:エージェントが管理していないアカウントが、集まった署名を付けてexecTransactionを送信します。
  • ステップ6:チームが結果を検証します。Safeの成功または失敗のイベント、宛先コントラクトへの影響、承認内容との一致を確認します。

署名と実行には、エージェントの外にあるコンポーネントと権限が必要です。

汎用的な権限ポリシーにオンチェーンの文脈が必要な理由

汎用的な権限システムは、あるアイデンティティがツールを使えるかどうかを判断します。オンチェーンの操作をレビューするには、それに加えて、各署名が何を承認するのか、その権限をどの経路で行使できるのかを知る必要があります。

Safeでは、通常のexecTransactionの経路が、設定されたしきい値に照らしてオーナーの署名を検証します。この検証は、誰がトランザクションを送信するかには依存しません。しきい値分の署名があれば、どのアカウントでも実行できます。したがって「エージェントは実行しない」というのは、エージェントがどの鍵とツールを持つかで決まる運用ルール、あるいは送信元アドレスを確認するガードのルールであって、コントラクト自体の性質ではありません。コントラクトが実際に防ぐのは、署名済みペイロードの改変です。どんな変更でも別のハッシュになり、署名は無効になります。

Safeが受け付ける署名タイプは四つです。ECDSA、eth_sign、EIP-1271のコントラクト署名、そしてapproveHashで事前承認されたハッシュです。オーナー自体がコントラクト、たとえば別のSafeである場合、その権限はそのコントラクトのルールに依存するため、そちらもレビューが必要です。

さらに、署名検証を経ずに実行できるモジュール経由の経路もあります。Safeのドキュメントは、モジュールは任意のトランザクションを実行でき、悪意あるモジュールはSafeを乗っ取り得ると警告しています。オーナーとしきい値だけを見るレビューでは、権限の分析は不完全です。エージェントがモジュールの経路を起動できるなら、オーナーでなくてもその能力を評価しなければなりません。デプロイ直後からモジュールが有効になっている構成もあります。たとえばERC-4337モジュールです。モジュールのリストは空だと決めつけないでください。

ガードはトランザクションの前後にチェックを追加するもので、バージョン1.3.0から存在します。1.4.1までは、setGuardで設定したガードがチェックするのはexecTransactionだけで、モジュールのトランザクションは通りません。1.5.0ではsetModuleGuardが追加され、モジュールの経路もカバーできるようになりました。Safeは、不具合のあるガードが実行を止めてしまう可能性を警告しているため、デプロイごとに、ガードがどの経路をカバーし、どんな復旧手段があるかを確認してください。

この権限スナップショットは、FoundryのcastでSafeを固定ブロックに対して読み取れば取得できます。ストレージスロットはSafeのコード上の定数で、バージョン1.4.1と1.5.0で照合済みです。

bash
# bash:この記事のブロックは、同じシェルセッションで順番に実行する
export ETH_RPC_URL=...            # 対象ネットワークのRPC
SAFE=0x...                        # Safeのアドレス
BLOCK=$(cast block-number)        # すべての読み取りをそろえるためにブロックを固定

cast call $SAFE "VERSION()(string)" --block $BLOCK
cast call $SAFE "getOwners()(address[])" --block $BLOCK
cast call $SAFE "getThreshold()(uint256)" --block $BLOCK
cast call $SAFE "nonce()(uint256)" --block $BLOCK

# モジュール:センチネル 0x...01 から始まる連結リスト。
# 返り値の2つ目が 0x...01 でなければ、次のページがある。
cast call $SAFE "getModulesPaginated(address,uint256)(address[],address)" \
  0x0000000000000000000000000000000000000001 50 --block $BLOCK

# トランザクションガード:slot = keccak256("guard_manager.guard.address")
cast storage $SAFE 0x4a204f620c8c5ccdca3fd54d003badd85ba500436a431f0cbda4f558c93c34c8 --block $BLOCK

# フォールバックハンドラー:slot = keccak256("fallback_manager.handler.address")
cast storage $SAFE 0x6c9a6c4a39284e37ed1cf53d337577d14212a4870fb976a4366c693b939918d5 --block $BLOCK

# 1.5.0のみ、モジュールガード:slot = keccak256("module_manager.module_guard.address")
cast storage $SAFE 0xb104e0b93118902c651344349b610029d694cfdec91c589c91ebafbcd0289947 --block $BLOCK

スロットの値がゼロなら、ガードやハンドラーは設定されていません。ただし、それは前の呼び出しが応答した場合に限ります。コードのないアドレスや別のネットワークでは、どのスロットもゼロとして読まれます。フォールバックハンドラーとDELEGATECALLは別の権限経路を開きます。これらは権限マトリクスを扱う別の記事で取り上げます。バージョン1.3.0より前のSafeにはガードがないため、ガードのスロットがゼロでも、そのバージョンが対応していないことを示すだけです。

チェーンも署名の文脈の一部です。EIP-712はchainIdやverifyingContractなどのドメインフィールドを定義しており、どれを使うかは各プロトコルが決めます。バージョン1.3.0以降のSafeはその両方、つまりchainIdとSafeのアドレスを使うため、同じSafeに対する同じペイロードでも、別のチェーンで署名すれば別のハッシュになります。それより前のSafeはドメインにchainIdを含めないため、Safeが同じアドレスを持つ別のチェーンでは、同じ署名が有効になりえます。この標準自体は署名済みメッセージの再利用を防ぎません。Safeでは、その役割をnonceが担います。

エージェントが準備するトレジャリーの支払い

例示のシナリオを考えます。顧客事例でも成果の測定でもありません。あるチームが、オーナー5人、しきい値3署名のSafeから、あるERC-20トークンを5,000単位送金したいとします。

ERC-20を直接送金する場合、コールの宛先はトークンコントラクトです。支払いの受取人と金額は、transferのデータの中に入ります。金額は最小単位で表すため、コントラクトのdecimalsを読み取る必要があります。ERC-20標準ではdecimalsは任意項目とされており、小数点以下6桁なら5,000単位は5000000000になります。

bash
TOKEN=0x...                       # そのネットワーク上のトークンコントラクト。承認済みの情報源と照合
RECIPIENT=0x...                   # 承認済みの受取人
cast call $TOKEN "decimals()(uint8)" --block $BLOCK
DATA=$(cast calldata "transfer(address,uint256)" $RECIPIENT 5000000000)
cast decode-calldata "transfer(address,uint256)" $DATA   # レビュー担当者が見るべき内容

# コントラクト自身が返すsafeTxHash:CALL、ガスの払い戻しなし
NONCE=$(cast call $SAFE "nonce()(uint256)" --block $BLOCK | cut -d' ' -f1)   # 10000以上では、castが" [1e4]"を付け加える
ZERO=0x0000000000000000000000000000000000000000
SAFE_TX_HASH=$(cast call $SAFE \
  "getTransactionHash(address,uint256,bytes,uint8,uint256,uint256,uint256,address,address,uint256)(bytes32)" \
  $TOKEN 0 $DATA 0 0 0 0 $ZERO $ZERO $NONCE --block $BLOCK)
echo $SAFE_TX_HASH

インターフェースにも問い合わせ先のコントラクトにも頼らないよう、Safeのコード上の定数を使ってオフラインでハッシュを再計算できます。この計算は、バージョン1.3.0以降でgetTransactionHashの結果と一致します。1.3.0と1.4.1のSafeで、また1.5.0のコードと照合して確認しました。それより前のバージョンは別のドメインを使うため、先にVERSIONを読んでください。

bash
SAFE_TX_TYPEHASH=0xbb8310d486368db6bd6f849402fdd73ad53d316b5a4b2644ad6efe0f941286d8
DOMAIN_TYPEHASH=0x47e79534a245952e8b16893a336b85a3d9ea9fa8c573f3d803afb92a79469218
CHAIN_ID=$(cast chain-id)
DOMAIN_HASH=$(cast keccak "$(cast abi-encode "f(bytes32,uint256,address)" $DOMAIN_TYPEHASH $CHAIN_ID $SAFE)")
MESSAGE_HASH=$(cast keccak "$(cast abi-encode \
  "f(bytes32,address,uint256,bytes32,uint8,uint256,uint256,uint256,address,address,uint256)" \
  $SAFE_TX_TYPEHASH $TOKEN 0 "$(cast keccak "$DATA")" 0 0 0 0 $ZERO $ZERO $NONCE)")
RECOMPUTED=$(cast keccak 0x1901${DOMAIN_HASH:2}${MESSAGE_HASH:2})
# $SAFE_TX_HASHと一致すること。値が空なら、前の読み取りが失敗しています
[ -n "$SAFE_TX_HASH" ] && [ "$RECOMPUTED" = "$SAFE_TX_HASH" ] && echo "MATCH $RECOMPUTED" || echo "NO MATCH"

内部コールは、Safeが送信したものとして、スナップショットのブロックでシミュレーションします。コマンドはこのセクションの最後のコードブロックにあります。このシミュレーションでは、署名検証もガードも動きません。それには後述するフォーク環境が必要です。この支払いのレビューパッケージでは、次の点を確認できるようにします。

  • ネットワークとSafe:chainIdとアドレスを承認済みの設定と照合し、VERSION、オーナー、しきい値、nonce、モジュール、ガード、フォールバックハンドラーを特定のブロックで読み取っていること。
  • 宛先コントラクト:そのネットワーク上のトークンアドレスを承認済みの情報源と照合し、decimalsも確認していること。
  • コール:デコードしたtransferで、受取人と最小単位の金額が示されていること。
  • Safeのパラメーター:operationが0、ネイティブ通貨の量が0、safeTxGas、baseGas、gasPriceが0、gasTokenとrefundReceiverがゼロアドレスであること。
  • ハッシュ:コントラクトが返したsafeTxHashと、オフラインで再計算したものが一致していること。
  • シミュレーション:使ったブロック、コールの結果、確認した残高の変化。
  • レビューと署名:レビューしたペイロード、各署名者に表示されるハッシュ、それぞれの判断。
bash
# Safeが送信したものとして、スナップショットのブロックで内部コールをシミュレーション
# USDTなど、boolを返さないトークンもある。その場合は(bool)を外し、リバートしないことだけを確認する
cast call $TOKEN "transfer(address,uint256)(bool)" $RECIPIENT 5000000000 --from $SAFE --block $BLOCK

チェックに問題がなければ、署名者はいつもの手順で必要な3つの署名を提供し、エージェントが管理していないアカウントがexecTransactionを送信します。その後チームは、二つの別々のことを確認します。トランザクションがマイニングされたこと、そして内部コールが成功したことです。SafeはsafeTxHashとともにExecutionSuccessまたはExecutionFailureを発行します。safeTxGasまたはgasPriceがゼロでない場合、内部コールが失敗してもトランザクション全体はリバートしません。トランザクションがマイニングされたことだけでは、支払いが行われた証明にはなりません。

このシナリオが示すのは責任の分離です。支払い額としきい値は例示上の前提であり、時間の削減、インシデントの減少、特定の実装の性能を示すものではありません。

このアーキテクチャにおけるエージェントの五つの制限

提案するフローでは、エージェントの権限から次の操作を除外します。

  • 秘密鍵、シードフレーズ、署名用の認証情報へのアクセス。
  • Safeに対する権限を持つメッセージやトランザクションへの署名。ECDSAもeth_signも使わず、オーナーアカウントからのapproveHashも行いません。
  • モジュール経由でのSafe操作の実行、または自分の鍵でのexecTransactionの送信。前者はモジュールのリストで、1.5.0以降はモジュールガードでも確認します。後者は運用ルールまたはガードのルールです。コントラクトはどの送信者でも受け付けるためです。
  • 自らの権限を広げるためのオーナー、しきい値、モジュール、ガード、フォールバックハンドラーの変更、またはそれを可能にするDELEGATECALLの提案。
  • 改変されたペイロードを承認済みとして扱うこと、または保留中の人の判断を覆すこと。

チームは、これらの制限をツール、認証情報、到達可能な経路のそれぞれで確認する必要があります。エージェントへの指示はその作業を方向付けるものですが、運用上の制限はモデルの出力が誤っている場合にも維持されなければなりません。デジタル資産を扱うエージェントの権限マトリクス全体とエスカレーション経路は、このシリーズの別の記事で扱います。本番環境のエージェントにおける権限の基本は、末尾にリンクした「本番AIエージェントに必要なのは雰囲気ではなく権限」にまとめています。

Web3チームへの導入方法

担当者と署名プロセスがすでにある、繰り返し発生する範囲の限られた操作から始めます。このモデルでは、次の四つのステップを提案します。

  • 既存の権限を洗い出す:誰が準備し、レビューし、署名し、実行するのか。どんなモジュール、ガード、デリゲート、コントラクトであるオーナーがあるのか。castで取得する権限スナップショットが出発点です。
  • レビューパッケージを定義する:署名を依頼する前に、どのフィールド、チェック、証跡がそろっている必要があるか。
  • 管理された環境で準備をテストする。anvilで立ち上げたローカルフォークなら、実際の資金を使わずに操作全体を実行でき、なりすましたアカウントからapproveHashでハッシュを承認できます。ここでネットワーク、アドレス、decimals、operation、nonceの誤りを意図的に入れ、フローがそれを止めるかエスカレーションするかを確認します。
  • 作業全体を評価する:準備とレビューにかかる時間、差し戻された下書き、承認したペイロードと実行された操作との一致。
bash
# スナップショットのブロックでローカルフォークをバックグラウンド起動:実際の資金は一切動かない
anvil --fork-url $ETH_RPC_URL --fork-block-number $BLOCK --silent &
sleep 5                           # anvilがポート8545で待ち受けるまで待つ
export ETH_RPC_URL=http://127.0.0.1:8545
OWNERS="0x... 0x... 0x..."        # しきい値分のSafeのオーナー(この例では3つ)
EXECUTOR=0x...                    # オーナーではない任意のアカウント
cast rpc anvil_setBalance $EXECUTOR 0xDE0B6B3A7640000   # ガス代用のテスト用 1 ETH

# 各オーナーが、なりすましたアカウントからハッシュを承認する。
# 事前承認ハッシュ署名:r = 先頭をゼロで埋めて32バイトにしたオーナーのアドレス、s = 0、v = 1、
# オーナーのアドレスの昇順に連結する(Safeはそれ以外の順序を拒否する)。
SIG=0x
for OWNER in $(printf '%s\n' $OWNERS | tr 'A-F' 'a-f' | LC_ALL=C sort); do
  cast rpc anvil_setBalance $OWNER 0xDE0B6B3A7640000
  cast rpc anvil_impersonateAccount $OWNER
  cast send $SAFE "approveHash(bytes32)" $SAFE_TX_HASH --from $OWNER --unlocked
  SIG=${SIG}000000000000000000000000${OWNER:2}000000000000000000000000000000000000000000000000000000000000000001
done

# オーナーでないアカウントを含め、どのアカウントでも実行を送信できる
cast rpc anvil_impersonateAccount $EXECUTOR
cast send $SAFE \
  "execTransaction(address,uint256,bytes,uint8,uint256,uint256,uint256,address,address,bytes)" \
  $TOKEN 0 $DATA 0 0 0 0 $ZERO $ZERO $SIG --from $EXECUTOR --unlocked
# 終わったら:kill %1でanvilを止める

受け入れテストでは、人に留保された権限をエージェントが行使できる経路が存在しないことも示す必要があります。一度うまく動いた実行だけでは、この境界は評価できません。フォーク上では、オーナーではないアカウントから同じ署名を再送信すると失敗しなければなりません。nonceが変わり、それに伴ってハッシュも変わっているからです。

引き続き人の判断が必要なこと

権限を分ければエージェントの直接の権限は小さくなりますが、その提案の質は引き続きレビューが必要です。受け取った情報が不完全だったり、照合しなかったりすれば、人も誤ったペイロードに署名し得ます。

チェック結果の有効期間も管理する必要があります。準備から実行までの間に、nonce、Safeの設定、宛先コントラクトの状態が変わることがあります。そうした変化が判断に影響する場合に検証とシミュレーションをやり直すための、明確な基準を設けることを提案します。うまくいったシミュレーションが示すのは確認した条件であり、将来の条件ではありません。

このフローは統合作業と署名者間の調整を増やすため、その有用性は実際のプロセスを測定して判断すべきです。別の委任ポリシーが必要な繰り返しの操作については、委任する権限とその制限を個別に設計し、レビューします。エージェントが独自のポリシーエンジンを持つウォレットプロバイダー上で動く場合も、この問いはなくなりません。ポリシーを執行するのはプロバイダーですが、その中身を決めるのは引き続きチームであり、Safeに到達する他の経路も確認する必要があります。このシリーズの別の記事で、権限マトリクスとあわせてこのケースを扱います。

トレジャリーをつなぐ前に境界を設計する

最初の一歩は、実際の操作を一つ選び、誰が準備でき、誰が承認でき、誰が実行できるかを図にすることです。そのうえで、権限、Safeの権限スナップショット、レビューパッケージがその分担を反映しているかを確認します。エージェントはペイロード、証跡、チェックを準備できますが、自分で確認したEIP-712ハッシュに署名するのは人だけであり、この設計はエージェントに、それを実行するための鍵も、ツールも、モジュール経路も残しません。

Nexuainでは、この方法をWeb3運用のためのポートフォリオコンセプトとして紹介しています。支援付きの準備、人による承認、外部での実行を、例示用の成果物とともに示すものです。エージェント向けのツール範囲、承認、トレーサビリティのサービスは、「ガードレール、承認、監査ログを備えたAIエージェント」のページで紹介しています。

特定のSafe操作にこのアプローチを適用したい場合、最初の成果物は、その操作の権限マップとレビューパッケージの定義です。権限マップには、オーナー、しきい値、モジュール、ガード、デリゲート、そして署名や実行に到達しうるすべての経路を含めます。技術レビューはお問い合わせページから依頼できます。メッセージでは、この記事と想定している操作に触れてください。鍵や機密の運用資料は含めないでください。

参考資料

ドキュメントの参照日:2026年10月1日。これらの資料はメカニズムとアーキテクチャを説明するものです。支払いのシナリオ、ポリシーの例、導入ステップは本記事による例示的な提案です。コードブロックはこの記事からそのままコピーし、Foundryのcastとanvil 1.8.3で最初から最後まで実行しました。対象はメインネット上のSafe 1.3.0とSafe 1.4.1、およびそれぞれのローカルフォークです。

関連記事

この内容をローンチやワークフローに適用したいですか?

技術レビューを依頼し、最も安全な第一歩を整理しましょう。

関連記事