chaingpt-org/chaingpt-claude-skill/agent-wallet

Trust tier 2
  • community
LLM review pending
Source check pending

Checking that the SKILL.md file is still in the repository.

Give the AI agent its own EVM wallet with admin-controlled policies the agent CANNOT bypass even under prompt injection. Encrypted keystore (AES-256-GCM, scrypt KDF), policy file the agent has no tool to write, deterministic policy gate on every signing operation, optional local HTTP dashboard. Triggers: agent wallet, give the agent a wallet, agent address, fund the agent, agent autonomy, policy gate, kill switch, agent permissions, bounded autonomy, ERC-4337 alternative, session-key alternative.

Install

npx vskill@latest install chaingpt-org/chaingpt-claude-skill/agent-wallet

SKILL.md

ChainGPT Agent Wallet Skill

The agent has its own EOA wallet on every EVM chain it supports. The admin (you, in your shell) sets policies that the agent cannot violate or revoke — even if a malicious prompt convinces the LLM to try.

Threat model

The attacker's goal: prompt-inject the agent to drain its wallet to an attacker address.

The plugin's defense: the policy check is in code, not in the LLM's prompt. Every chaingpt_agent_wallet_sign_and_send call:

  1. Loads the policy file fresh from disk (no caching — admin can update mid-session).
  2. Runs checkPolicy(intent) — pure deterministic code that doesn't see the LLM's context.
  3. Refuses if any rule fails, with a clear reason the agent surfaces back to the user.

The attacker can convince the LLM to call sign_and_send(to=attacker, value=ALL) — but the tool layer refuses because attacker isn't in allowedToAddresses or value exceeds maxTxValueWei or killSwitch=true. The trust boundary is the tool code, not the LLM.

There is no MCP tool that writes the policy file. The admin edits it directly with a text editor. There is no MCP tool that reads or sets the passphrase. The passphrase lives only in the shell env var or the OS keychain — never in the keystore file, never in the LLM's context.

Setup (admin steps — done once)

The keystore passphrase resolves in this priority order:

  1. `CHAINGPT_AGENT_WALLET_PASSPHRASE` env var — explicit override. Best for CI / headless / power users who want zero process-list and zero keychain exposure.
  2. OS keychain — auto-managed. On macOS (Keychain via security) or Linux (libsecret via secret-tool), if no env var is set, chaingpt_agent_wallet_init generates a strong 256-bit passphrase and stores it in the keychain. You never type or remember it; the MCP server reads it back on each load.
Option A — zero-setup (macOS / Linux with a keychain) — recommended for most
bash
# Just init — a strong passphrase is generated + stored in your OS keychain.
claude
> initialize the agent wallet

The init output tells you it used the keychain and how to export the passphrase for backup.

Option B — explicit env var (CI / headless / max control)
bash
# Set a strong passphrase BEFORE starting the MCP server (>= 16 chars)
export CHAINGPT_AGENT_WALLET_PASSPHRASE="your-strong-passphrase-here-min-16-chars"
claude
> initialize the agent wallet
Back up the passphrase either way. Keychain entry: service=chaingpt-mcp-agent-wallet account=keystore-passphrase. Export on macOS with security find-generic-password -s chaingpt-mcp-agent-wallet -a keystore-passphrase -w. Lose it (and any backup) → the keystore is unrecoverable. There is no recovery path.
Security tradeoff of the keychain option: the secret stays out of plaintext-on-disk and out of the LLM context, but the keychain is unlocked while you're logged in — a local attacker on an unlocked session could read it. That's a much higher bar than a plaintext file and appropriate for a low-value bounded hot wallet. For zero local exposure, use Option B.

This creates two files:

FileContentsWho edits it
~/.chaingpt-mcp/agent-wallet/keystore.jsonAES-256-GCM encrypted private keyGenerated once by the init tool. Never edit by hand. Back it up.
~/.chaingpt-mcp/agent-wallet/policy.jsonPlain JSON rulesYou, the admin, with a text editor. The agent has NO tool that writes this file.

Both default to ~/.chaingpt-mcp/agent-wallet/ but can be overridden via CHAINGPT_KEYSTORE_FILE and CHAINGPT_AGENT_POLICY_FILE.

Tools

ToolMutates state?Notes
chaingpt_agent_wallet_initCreates keystoreOne-shot. Refuses if file exists.
chaingpt_agent_wallet_addressNoReturns the agent's EOA address. Use this to receive funds.
chaingpt_agent_wallet_statusNoAddress + policy digest + kill-switch state. Run this before any signing.
chaingpt_agent_wallet_balancesNoNative-coin balances across requested chains.
chaingpt_agent_wallet_policyNo (read-only)Shows the current policy JSON. Cannot modify it.
chaingpt_agent_wallet_sign_and_sendSigns + broadcasts a txThe only tool that can move funds. Gated by policy.
chaingpt_agent_wallet_serve_uiStarts a local HTTP serverDashboard on http://127.0.0.1:8787. Read-only view.

Policy file format

Default policy.json (lazily created on first read) is the Balanced DeFi policy: killSwitch: false, major DEX/lending routers allow-listed, 0.1 native per-tx cap, 0.3 native + 20 txs per rolling 24h (maxDailySpendWei / maxDailyTxCount), memo required. A corrupt or partially-missing policy file always falls back to fail-closed (killSwitch: true) — tampering can never open the gates. Apply the "Locked down" template (or set killSwitch: true) for a refuse-everything posture.

Example production policy (allow DEX rebalancing on Base, capped at 0.1 ETH/tx, audit memo required):

json
{
"version": 1,
"killSwitch": false,
"allowedChains": [8453],
"allowedToAddresses": [
"0x6352a56caadc4f1e25cd6c75970fa768a3304e64",
"0x111111125421ca6dc452d289314280a0f8842a65"
],
"blockedToAddresses": [
"0x0000000000000000000000000000000000000000"
],
"maxTxValueWei": "100000000000000000",
"maxTxGas": "500000",
"blockedSelectors": [],
"requireMemo": true,
"notes": "Base only, OpenOcean + 1inch routers only, 0.1 ETH cap, memo required for audit",
"updatedAt": "2026-05-18T20:00:00Z"
}
Field reference
FieldTypeBehavior when unsetBehavior when set
killSwitchboolrefuses everything (fail-closed)true refuses everything; false proceeds to other checks
allowedChainsint[]any chain allowedrefuses if chainId not in list
allowedToAddressesstring[]any address allowedrefuses if to not in list (case-insensitive)
blockedToAddressesstring[]nothing blockedrefuses if to matches (case-insensitive)
maxTxValueWeistringno caprefuses if native value > max
maxTxGasstringno caprefuses if gasLimit > max; an explicit gasLimit becomes REQUIRED (auto-estimation would bypass the cap)
maxDailySpendWeistringno velocity caprefuses if 24h ledger spend + this tx value would exceed the cap (fail-closed if the ledger is unreadable)
maxDailyTxCountintno velocity caprefuses once the rolling-24h signed-tx count reaches the cap
blockedSelectorsstring[]nothing blockedrefuses if first 4 bytes of data match (e.g. 0xa9059cbb blocks ERC-20 transfer)
requireMemoboolno memo requiredrefuses if the memo arg is missing

Precedence: kill switch > blockedToAddresses > allowedToAddresses > value caps > gas cap > daily velocity caps > blockedSelectors > memo. Any single failure refuses the tx.

Solana wallet (v1.19+)

The same bounded-autonomy model on Solana. Separate Ed25519 keystore (solana-keystore.json, same cipher + same admin passphrase), gated by the solana policy sub-object that — like everything else here — no MCP tool can write.

text
chaingpt_agent_wallet_solana_init # one-time keystore
chaingpt_agent_wallet_solana_address # fund this (the balance is the outermost cap)
<any builder: jupiter swap / marginfi / kamino / transfer> → unsigned VersionedTransaction (base64)
chaingpt_agent_wallet_solana_sign_and_send txBase64=<…> memo=<…>

Policy block (admin-only, dashboard or text editor):

json
"solana": {
"enabled": true,
"allowedPrograms": ["11111111111111111111111111111111", "JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4"],
"maxTxLamports": "100000000",
"maxDailySpendLamports": "300000000",
"maxDailyTxCount": 20,
"requireMemo": true
}

Hard facts to relay accurately:

  • Fail-closed migration: a policy file without solana.enabled: true refuses every Solana signing op. unrestricted does not bypass it.
  • Spend is simulation-priced: the tool simulates first and meters the fee-payer lamport delta against maxTxLamports + the 24h window. Simulation unavailable or failing ⇒ refusal, never a blind broadcast.
  • The program allowlist fences which protocols the agent may ENTER (top-level instructions). Inner CPIs are invisible to it — the lamport caps + tx count are the actual spend fence. SPL-token outflows don't move fee-payer lamports, so they are fenced by the allowlist and tx count, not the lamport cap.
  • The agent must be the sole signer and fee payer — co-signing or fee-sponsoring someone else's tx is refused structurally.

On-chain caps — ERC-4337 session keys (v1.21+)

The endgame: the user's ERC-7579 smart account grants the agent's EOA a SCOPED on-chain session (Smart Sessions module). The caps live in audited contracts and are validated by the EntryPoint. Status: BETA — the module addresses are verified deployed on Base Sepolia and the encoders are unit-tested, but the end-to-end live proof is not yet published. Treat the on-chain column below as the DESIGNED guarantee, not yet an independently-demonstrated one; the local gate is your tested fence today.

ThreatLocal policy gate (tested)On-chain session caps (designed, beta)
Prompt injection✅ blocks✅ designed to block
Policy file tampered/rewritten❌ falls✅ designed to block
Full host compromise (keystore stolen)❌ falls✅ designed to block, bounded by remaining allowance + expiry (live proof pending)
text
chaingpt_aa_session_build_grant chain=base account=<user SCW> tokenCaps=[{token: USDC, cap: "100000000"}] validUntil=<unix>
→ OWNER signs the userOpHash externally → chaingpt_aa_submit_userop
chaingpt_aa_session_status # chain-authoritative: enabled? remaining?
chaingpt_agent_wallet_4337_sign_and_send … # the agent acts; local gates AND chain caps both apply
chaingpt_aa_session_build_revoke … # incident response: chain-level kill

Hard facts: erc4337.enabled policy opt-in is fail-closed and OFF by default everywhere (this surface acts on a third-party account). Unbounded grants are refused at build time. A bundler rejection of an over-cap op is the product working — never retry around it. v1 supports Biconomy Nexus 1.x accounts.

Pre-flight checklist

text
1. chaingpt_agent_wallet_status # see address + policy digest + kill switch state
2. chaingpt_agent_wallet_balances # confirm funded on the target chain
3. chaingpt_agent_wallet_policy # read the active rules in full
4. chaingpt_agent_wallet_sign_and_send chain=… to=… valueWei=… data=… memo="…"

If the call gets refused with a policy reason: do not try to work around it from the agent side. Surface the reason to the admin and let them edit the policy file (or override) themselves.

Local admin dashboard

text
> Use chaingpt_agent_wallet_serve_ui

Returns a http://127.0.0.1:8787 URL and a one-time admin token printed in the tool output (also saved to ~/.chaingpt-mcp/agent-wallet/.admin-token, 0600). The token rotates on every restart.

Open the URL in your browser. Paste the admin token at the login screen. The dashboard then shows:

  • Deposit address with QR code
  • Multi-chain native-coin balances (refresh page to update)
  • One-click kill switch — engage or disable, single button
  • Policy JSON editor — full inline editor, validated server-side, atomic write with .bak backup
  • Keystore + policy file paths for reference
Why this is safe even though the dashboard CAN edit the policy

Recall the threat model: the attacker controls the LLM via prompt injection. The defenses, in layers:

This is the start of the file. Read the full SKILL.md on GitHub.

Security

  • Security scanPassed, 100 of 100Pattern checks on the skill's files.
  • Model reviewNot runA model review is scheduled for the next rescan.

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

7-day trend score
0

Not refreshed yet.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/chaingpt-org/chaingpt-claude-skill/agent-wallet/badge)](https://verified-skill.com/skills/chaingpt-org/chaingpt-claude-skill/agent-wallet)

Something wrong with this skill or its page? Tell us.