jpskill.com
🛠️ 開発・MCP コミュニティ 🔴 エンジニア向け 👤 エンジニア・AI開発者

🛠️ Bagman

bagman

AIエージェントが秘密鍵やAPIシーク

⏱ ボイラープレート実装 半日 → 30分
📜 元の英語説明(参考)

Secure key management for AI agents. Use when handling private keys, API secrets, wallet credentials, or when building systems that need agent-controlled funds. Covers secure storage, session keys, leak prevention, and prompt injection defense.

🇯🇵 日本人クリエイター向け解説

一言でいうと

AIエージェントが秘密鍵やAPIシーク

※ jpskill.com 編集部が日本のビジネス現場向けに補足した解説です。Skill本体の挙動とは独立した参考情報です。

⚡ おすすめ: コマンド1行でインストール(60秒)

下記のコマンドをコピーしてターミナル(Mac/Linux)または PowerShell(Windows)に貼り付けてください。 ダウンロード → 解凍 → 配置まで全自動。

🍎 Mac / 🐧 Linux
mkdir -p ~/.claude/skills && cd ~/.claude/skills && curl -L -o bagman.zip https://jpskill.com/download/5033.zip && unzip -o bagman.zip && rm bagman.zip
🪟 Windows (PowerShell)
$d = "$env:USERPROFILE\.claude\skills"; ni -Force -ItemType Directory $d | Out-Null; iwr https://jpskill.com/download/5033.zip -OutFile "$d\bagman.zip"; Expand-Archive "$d\bagman.zip" -DestinationPath $d -Force; ri "$d\bagman.zip"

完了後、Claude Code を再起動 → 普通に「動画プロンプト作って」のように話しかけるだけで自動発動します。

💾 手動でダウンロードしたい(コマンドが難しい人向け)
  1. 1. 下の青いボタンを押して bagman.zip をダウンロード
  2. 2. ZIPファイルをダブルクリックで解凍 → bagman フォルダができる
  3. 3. そのフォルダを C:\Users\あなたの名前\.claude\skills\(Win)または ~/.claude/skills/(Mac)へ移動
  4. 4. Claude Code を再起動

⚠️ ダウンロード・利用は自己責任でお願いします。当サイトは内容・動作・安全性について責任を負いません。

🎯 このSkillでできること

下記の説明文を読むと、このSkillがあなたに何をしてくれるかが分かります。Claudeにこの分野の依頼をすると、自動で発動します。

📦 インストール方法 (3ステップ)

  1. 1. 上の「ダウンロード」ボタンを押して .skill ファイルを取得
  2. 2. ファイル名の拡張子を .skill から .zip に変えて展開(macは自動展開可)
  3. 3. 展開してできたフォルダを、ホームフォルダの .claude/skills/ に置く
    • · macOS / Linux: ~/.claude/skills/
    • · Windows: %USERPROFILE%\.claude\skills\

Claude Code を再起動すれば完了。「このSkillを使って…」と話しかけなくても、関連する依頼で自動的に呼び出されます。

詳しい使い方ガイドを見る →
最終更新
2026-05-17
取得日時
2026-05-18
同梱ファイル
1

💬 こう話しかけるだけ — サンプルプロンプト

  • Bagman を使って、最小構成のサンプルコードを示して
  • Bagman の主な使い方と注意点を教えて
  • Bagman を既存プロジェクトに組み込む方法を教えて

これをClaude Code に貼るだけで、このSkillが自動発動します。

📖 Skill本文(日本語訳)

※ 原文(英語/中国語)を Gemini で日本語化したものです。Claude 自身は原文を読みます。誤訳がある場合は原文をご確認ください。

[Skill 名] bagman

Bagman

AI エージェントが秘密鍵やシークレットを扱うための、安全な鍵管理パターンです。以下の事態を防ぐように設計されています。

  • 鍵の紛失: セッション間でエージェントが鍵を忘れること
  • 偶発的な漏洩: 鍵が GitHub、ログ、または出力に漏洩すること
  • プロンプトインジェクション: 悪意のあるプロンプトがシークレットを抽出すること

コア原則

  1. 生の秘密鍵を構成ファイル、環境変数、またはメモリファイルに決して保存しない
  2. フルコントロールではなく、セッションキー/委任されたアクセスを使用する
  3. すべてのシークレットアクセスは 1Password CLI (op) を介して行う
  4. 鍵の漏洩を防ぐため、送信前にすべての出力を検証する

参照

  • references/secure-storage.md - エージェントのシークレットに関する 1Password パターン
  • references/session-keys.md - ERC-4337 委任アクセスパターン
  • references/leak-prevention.md - プリコミットフックと出力サニタイズ
  • references/prompt-injection-defense.md - 入力検証と出力フィルタリング

クイックリファレンス

DO ✅

# 1Password を介して実行時に鍵を取得する
PRIVATE_KEY=$(op read "op://Agents/my-agent-wallet/private-key")

# 環境インジェクションを使用する (鍵がディスクに触れることはない)
op run --env-file=.env.tpl -- node agent.js

# 権限を制限したセッションキーを使用する
# (ウォレットへのフルアクセスではなく、特定の機能を委任する)

DON'T ❌

# 鍵をファイルに決して保存しない
echo "PRIVATE_KEY=0x123..." > .env

# 鍵をログに出力したり、表示したり決してしない
console.log("Key:", privateKey)

# 鍵をメモリ/ジャーナルファイルに決して保存しない
# 「プライベート」なエージェントメモリであっても、これらは外部に持ち出される可能性があります

# 鍵操作の近くで未検証の入力を決して信頼しない

アーキテクチャ: エージェントウォレットスタック

┌─────────────────────────────────────────────────────┐
│                   AI Agent                          │
├─────────────────────────────────────────────────────┤
│  Session Key (time/value bounded)                   │
│  - Expires after N hours                            │
│  - Spending cap per operation                       │
│  - Whitelist of allowed contracts                   │
├─────────────────────────────────────────────────────┤
│  1Password / Secret Manager                         │
│  - Agent retrieves session key at runtime           │
│  - Never stores full private key                    │
│  - Audit log of all accesses                        │
├─────────────────────────────────────────────────────┤
│  ERC-4337 Smart Account                             │
│  - Programmable permissions                         │
│  - Recovery without private key exposure            │
│  - Multi-sig for high-value operations              │
├─────────────────────────────────────────────────────┤
│  Operator (Human)                                   │
│  - Holds master key in hardware wallet              │
│  - Issues/revokes session keys                      │
│  - Monitors agent activity                          │
└─────────────────────────────────────────────────────┘

ワークフロー: エージェントウォレットアクセスの設定

1. エージェントのシークレット用に 1Password Vault を作成する

# 専用の Vault を作成する (1Password アプリまたは CLI 経由)
op vault create "Agent-Wallets" --description "AI agent wallet credentials"

# エージェントのセッションキーを保存する (マスターキーではない!)
op item create \
  --vault "Agent-Wallets" \
  --category "API Credential" \
  --title "trading-bot-session" \
  --field "session-key[password]=0xsession..." \
  --field "expires=2026-02-15T00:00:00Z" \
  --field "spending-cap=1000 USDC" \
  --field "allowed-contracts=0xDEX1,0xDEX2"

2. エージェントが実行時にクレデンシャルを取得する

import subprocess
import json

def get_session_key(item_name: str) -> dict:
    """実行時に 1Password からセッションキーを取得する。"""
    result = subprocess.run(
        ["op", "item", "get", item_name, "--vault", "Agent-Wallets", "--format", "json"],
        capture_output=True, text=True, check=True
    )
    item = json.loads(result.stdout)

    # フィールドを抽出する
    fields = {f["label"]: f.get("value") for f in item.get("fields", [])}

    # セッションの有効期限が切れていないか検証する
    from datetime import datetime
    expires = datetime.fromisoformat(fields.get("expires", "2000-01-01"))
    if datetime.now() > expires:
        raise ValueError("Session key expired - request new key from operator")

    return {
        "session_key": fields.get("session-key"),
        "expires": fields.get("expires"),
        "spending_cap": fields.get("spending-cap"),
        "allowed_contracts": fields.get("allowed-contracts", "").split(",")
    }

3. 鍵をログに記録したり、保存したり決してしない

# ❌ BAD - ログに鍵がある
logger.info(f"Using key: {session_key}")

# ✅ GOOD - 編集された識別子
logger.info(f"Using session key: {session_key[:8]}...{session_key[-4:]}")

# ❌ BAD - メモリファイルに鍵がある
with open("memory/today.md", "a") as f:
    f.write(f"Session key: {session_key}")

# ✅ GOOD - 参照のみ
with open("memory/today.md", "a") as f:
    f.write(f"Session key: [stored in 1Password: trading-bot-session]")

漏洩防止

出力サニタイズ

エージェントの出力 (チャット、ログ、ファイル書き込み) の前に、鍵のパターンをスキャンします。

import re

KEY_PATTERNS = [
    r'0x[a-fA-F0-9]{64}',                    # ETH private keys
    r'sk-[a-zA-Z0-9]{48,}',                  # OpenAI keys
    r'sk-ant-[a-zA-Z0-9\-_]{80,}',           # Anthropic keys
    r'gsk_[a-zA-Z0-9]{48,}',                 # Groq keys
    r'[A-Za-z0-9+/]{40,}={0,2}',             # Base64 encoded (suspiciously long)
]

def sanitize_output(text: str) -> str:
    """出力から潜在的なシークレットを削除する。"""
    for pattern in KEY_PATTERNS:
        text = re.sub(pattern, '[REDACTED]', text)
    return text

# すべてのエージェント出力に適用する
def send_message(content: str):
    content = sanitize_output(content)
    # ... チャット/ログ/ファイルに送信する

プリコミットフック

シークレットの偶発的なコミットを防ぐために、このフックをインストールします。

#!/bin/bash
# .git/hooks/pre-commit

PATTERNS=(
    '0x[a-fA-F0-9]{64}'
    'sk-[a-zA-Z0-9]{48,}'
    'sk-ant-api'
    'PRIVATE_KEY='
    'gs
📜 原文 SKILL.md(Claudeが読む英語/中国語)を展開

Bagman

Secure key management patterns for AI agents handling private keys and secrets. Designed to prevent:

  • Key loss: Agents forgetting keys between sessions
  • Accidental exposure: Keys leaked to GitHub, logs, or outputs
  • Prompt injection: Malicious prompts extracting secrets

Core Principles

  1. Never store raw private keys in config, env vars, or memory files
  2. Use session keys / delegated access instead of full control
  3. All secret access goes through 1Password CLI (op)
  4. Validate all outputs before sending to prevent key leakage

References

  • references/secure-storage.md - 1Password patterns for agent secrets
  • references/session-keys.md - ERC-4337 delegated access patterns
  • references/leak-prevention.md - Pre-commit hooks and output sanitization
  • references/prompt-injection-defense.md - Input validation and output filtering

Quick Reference

DO ✅

# Retrieve key at runtime via 1Password
PRIVATE_KEY=$(op read "op://Agents/my-agent-wallet/private-key")

# Use environment injection (key never touches disk)
op run --env-file=.env.tpl -- node agent.js

# Use session keys with bounded permissions
# (delegate specific capabilities, not full wallet access)

DON'T ❌

# NEVER store keys in files
echo "PRIVATE_KEY=0x123..." > .env

# NEVER log or print keys
console.log("Key:", privateKey)

# NEVER store keys in memory/journal files
# Even in "private" agent memory - these can be exfiltrated

# NEVER trust unvalidated input near key operations

Architecture: Agent Wallet Stack

┌─────────────────────────────────────────────────────┐
│                   AI Agent                          │
├─────────────────────────────────────────────────────┤
│  Session Key (time/value bounded)                   │
│  - Expires after N hours                            │
│  - Spending cap per operation                       │
│  - Whitelist of allowed contracts                   │
├─────────────────────────────────────────────────────┤
│  1Password / Secret Manager                         │
│  - Agent retrieves session key at runtime           │
│  - Never stores full private key                    │
│  - Audit log of all accesses                        │
├─────────────────────────────────────────────────────┤
│  ERC-4337 Smart Account                             │
│  - Programmable permissions                         │
│  - Recovery without private key exposure            │
│  - Multi-sig for high-value operations              │
├─────────────────────────────────────────────────────┤
│  Operator (Human)                                   │
│  - Holds master key in hardware wallet              │
│  - Issues/revokes session keys                      │
│  - Monitors agent activity                          │
└─────────────────────────────────────────────────────┘

Workflow: Setting Up Agent Wallet Access

1. Create 1Password Vault for Agent Secrets

# Create dedicated vault (via 1Password app or CLI)
op vault create "Agent-Wallets" --description "AI agent wallet credentials"

# Store agent session key (not master key!)
op item create \
  --vault "Agent-Wallets" \
  --category "API Credential" \
  --title "trading-bot-session" \
  --field "session-key[password]=0xsession..." \
  --field "expires=2026-02-15T00:00:00Z" \
  --field "spending-cap=1000 USDC" \
  --field "allowed-contracts=0xDEX1,0xDEX2"

2. Agent Retrieves Credentials at Runtime

import subprocess
import json

def get_session_key(item_name: str) -> dict:
    """Retrieve session key from 1Password at runtime."""
    result = subprocess.run(
        ["op", "item", "get", item_name, "--vault", "Agent-Wallets", "--format", "json"],
        capture_output=True, text=True, check=True
    )
    item = json.loads(result.stdout)

    # Extract fields
    fields = {f["label"]: f.get("value") for f in item.get("fields", [])}

    # Validate session hasn't expired
    from datetime import datetime
    expires = datetime.fromisoformat(fields.get("expires", "2000-01-01"))
    if datetime.now() > expires:
        raise ValueError("Session key expired - request new key from operator")

    return {
        "session_key": fields.get("session-key"),
        "expires": fields.get("expires"),
        "spending_cap": fields.get("spending-cap"),
        "allowed_contracts": fields.get("allowed-contracts", "").split(",")
    }

3. Never Log or Store the Key

# ❌ BAD - Key in logs
logger.info(f"Using key: {session_key}")

# ✅ GOOD - Redacted identifier
logger.info(f"Using session key: {session_key[:8]}...{session_key[-4:]}")

# ❌ BAD - Key in memory file
with open("memory/today.md", "a") as f:
    f.write(f"Session key: {session_key}")

# ✅ GOOD - Reference only
with open("memory/today.md", "a") as f:
    f.write(f"Session key: [stored in 1Password: trading-bot-session]")

Leak Prevention

Output Sanitization

Before any agent output (chat, logs, file writes), scan for key patterns:

import re

KEY_PATTERNS = [
    r'0x[a-fA-F0-9]{64}',                    # ETH private keys
    r'sk-[a-zA-Z0-9]{48,}',                  # OpenAI keys
    r'sk-ant-[a-zA-Z0-9\-_]{80,}',           # Anthropic keys
    r'gsk_[a-zA-Z0-9]{48,}',                 # Groq keys
    r'[A-Za-z0-9+/]{40,}={0,2}',             # Base64 encoded (suspiciously long)
]

def sanitize_output(text: str) -> str:
    """Remove potential secrets from output."""
    for pattern in KEY_PATTERNS:
        text = re.sub(pattern, '[REDACTED]', text)
    return text

# Apply to ALL agent outputs
def send_message(content: str):
    content = sanitize_output(content)
    # ... send to chat/log/file

Pre-commit Hook

Install this hook to prevent accidental commits of secrets:

#!/bin/bash
# .git/hooks/pre-commit

PATTERNS=(
    '0x[a-fA-F0-9]{64}'
    'sk-[a-zA-Z0-9]{48,}'
    'sk-ant-api'
    'PRIVATE_KEY='
    'gsk_[a-zA-Z0-9]{48,}'
)

for pattern in "${PATTERNS[@]}"; do
    if git diff --cached | grep -qE "$pattern"; then
        echo "❌ Potential secret detected matching: $pattern"
        echo "   Remove secrets before committing!"
        exit 1
    fi
done

.gitignore Essentials

# Secrets
.env
.env.*
*.pem
*.key
secrets/
credentials/

# Agent state that might contain secrets
memory/*.json
wallet-state.json
session-keys/

Prompt Injection Defense

Input Validation

Before processing any user input that touches wallet operations:

DANGEROUS_PATTERNS = [
    r'ignore.*(previous|above|prior).*instructions',
    r'reveal.*(key|secret|password|credential)',
    r'output.*(key|secret|private)',
    r'print.*(key|secret|wallet)',
    r'show.*(key|secret|password)',
    r'what.*(key|secret|password)',
    r'tell.*me.*(key|secret)',
    r'disregard.*rules',
    r'system.*prompt',
    r'jailbreak',
    r'dan.*mode',
]

def validate_input(text: str) -> bool:
    """Check for prompt injection attempts."""
    text_lower = text.lower()
    for pattern in DANGEROUS_PATTERNS:
        if re.search(pattern, text_lower):
            return False
    return True

def process_wallet_request(user_input: str):
    if not validate_input(user_input):
        return "I can't help with that request."
    # ... proceed with wallet operation

Separation of Concerns

  • Wallet operations should be in isolated functions with no access to conversation context
  • Never pass full conversation history to wallet-sensitive code
  • Use allowlists for operations, not blocklists
ALLOWED_WALLET_OPERATIONS = {
    "check_balance": lambda: get_balance(),
    "send_usdc": lambda to, amount: send_usdc(to, amount) if amount < DAILY_LIMIT else deny(),
    "swap": lambda: swap_tokens() if within_limits() else deny(),
}

def execute_wallet_operation(operation: str, **kwargs):
    """Execute only explicitly allowed operations."""
    if operation not in ALLOWED_WALLET_OPERATIONS:
        raise ValueError(f"Operation '{operation}' not allowed")
    return ALLOWED_WALLET_OPERATIONS[operation](**kwargs)

Session Key Implementation (ERC-4337)

For agents needing on-chain access, use session keys instead of raw private keys.

See references/session-keys.md for full implementation details including:

  • ZeroDev/Biconomy SDK examples
  • Permission patterns for trading/DeFi/payment agents
  • Session key lifecycle management
  • Revocation procedures

Incident Response

If a Key is Leaked

  1. Immediate: Revoke the session key / rotate credentials
  2. Assess: Check transaction history for unauthorized activity
  3. Notify: Alert operator via secure channel
  4. Rotate: Issue new session key with tighter permissions
  5. Audit: Review how leak occurred, update defenses
# Emergency: Revoke 1Password item
op item delete "compromised-session-key" --vault "Agent-Wallets"

# Rotate to new session key
op item create --vault "Agent-Wallets" --category "API Credential" \
  --title "trading-bot-session-v2" ...

Checklist: Agent Wallet Setup

  • [ ] Create dedicated 1Password vault for agent credentials
  • [ ] Store session keys (NOT master keys) in vault
  • [ ] Set appropriate expiry and spending limits
  • [ ] Install pre-commit hook for secret detection
  • [ ] Add output sanitization to all agent responses
  • [ ] Implement input validation for prompt injection
  • [ ] Configure monitoring and alerts
  • [ ] Document incident response procedure
  • [ ] Test key rotation procedure

Common Mistakes Found in Production

1. Keys in Memory Files

Problem: Agents store keys in memory/*.md for "persistence"

# memory/2026-02-07.md
## Test Wallet
- Private key: 0x9f01dad551039daad3a8c4e43a32035bdd4da54e7b4292268be16e913b0b3e56

Fix: Store reference only: Private key: [1Password: test-wallet-session]

2. Keys in Environment Templates

Problem: .env.example contains real keys

# .env.example
PRIVATE_KEY=sk-ant-api03-real-key-here...  # "for testing"

Fix: Use obviously fake placeholders: PRIVATE_KEY=your-key-here

3. Keys in Error Messages

Problem: Error handling exposes keys

try:
    sign_transaction(private_key, tx)
except Exception as e:
    logger.error(f"Failed with key {private_key}: {e}")  # ❌

Fix: Never include credentials in error context

4. Test Keys in Production Code

Problem: Hardcoded test keys make it to main branch

Fix: Use separate test vault, CI checks for key patterns


Integration with OpenClaw

When running as an OpenClaw agent:

  1. Use 1Password skill for all secret retrieval
  2. Never write keys to workspace files - they persist across sessions
  3. Sanitize outputs before sending to any channel (Telegram, Discord, etc.)
  4. Session key approach for wallet operations - request bounded access from operator
  5. Document key references in TOOLS.md, not the actual keys

Example TOOLS.md entry:

### Agent Wallet
- Address: 0xABC123...
- Session key: [1Password: my-agent-session]
- Permissions: USDC transfers < 100, approved DEX only
- Expires: 2026-02-15
- To rotate: Ask operator via Telegram