Agent Sniper について
@three-ws/agent-sniper は、3D AI エージェントやマルチテナント運用に組み込める pump.fun 向けスナイパーエンジンです。デフォルトはシミュレーションモードで、ウォレット・ストア・取引先はアダプターとして差し替えられ、ライブラリ、CLI、MCP サーバー、x402 HTTP API として利用できます。
主な機能
- 01エージェントごとの戦略による新規銘柄のスコアリング
- 02ストップロス、テイクプロフィット、トレーリングストップの退出ルール
- 03エージェントごとのウォレットと日次予算
- 04デフォルトはシミュレーション、ライブは明示的に有効化
- 05ウォレット、ストア、実行器、フィードのアダプター
活用シーン
- 01devnet でシミュレーションモードを使い取引戦略を検証
- 02複数エージェントごとに独立したスナイプ戦略を実行
- 03MCP クライアントから戦略とポジションを管理
MCP 対応
このプロジェクトは stdio 方式の MCP サーバーを提供し、arm_strategy や list_positions などの 7 つのツールで戦略、ポジション、状態の操作を公開します。各ツールはエンジンの公開メソッドに 1 対 1 で対応します。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
npx -y @three-ws/agent-sniperSNIPER_MODETrade mode: simulate | live. simulate scores, guards, and logs every decision but NEVER broadcasts. live signs and broadcasts real transactions with real funds. Defaults to simulate — keep it there until your strategy is verified.SNIPER_NETWORKSolana cluster to trade on: mainnet | devnet. Defaults to mainnet.SOLANA_RPC_URLSolana RPC endpoint. A public RPC rate-limits under the new-mint firehose, so live mode refuses to start without this set. Optional in simulate mode.SOLANA_SECRET_KEYシークレットDefault self-custody wallet secret for single-agent runs — base58, a JSON byte array, or 0x-hex. Stays on your machine; the engine signs locally. Required only for live trading. Treat it like a password.ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。
ツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
@three-ws/agent-sniper
3D AI エージェント向けの、軽量で組み込み可能な pump.fun スナイパーエンジンです。1 つの取引ループで、新規ローンチのストリームを受け取り、それぞれをエージェントごとの戦略に照らしてスコアリングし、取引前のガードを実行して買い付けます。その後、一定間隔で未決済ポジションを確認し、損切り/利益確定/トレーリングストップ/タイムアウト/センチメントの反転を条件に決済します。設計上、マルチエージェント・マルチユーザーに対応しており(agentId ごとに 1 つのウォレット)、外部依存関係(ウォレット管理、永続化、RPC/取引所、ローンチフィード)はすべてプラグイン可能なアダプターです。そのため、同じエンジンをインメモリ状態でローカル実行することも、数千のテナントにわたってホストすることもできます。このパッケージは、1 つのエンジンを利用する 4 つの形態、ライブラリ、CLI、MCP サーバー、x402 有料 HTTP APIを提供します。
理由 — アダプターアーキテクチャ
このエンジンは純粋なオーケストレーションを担います。意思決定パイプラインは管理しますが、資金、データ、ブロックチェーンの所在については関知しません。5 つのアダプターインターフェース(src/types.js)が接続点となり、それぞれにデフォルト実装が用意されています。
┌──────────────────────────── engine ────────────────────────────┐
Feed ──{mint|intel|claim}─▶ score ──▶ guards ──▶ executeBuy ──▶ claimPosition │
(PumpPortal) (scorer) (concurrency, (quote + (atomic slot) │
budget, SOL build + sign │
headroom, + broadcast) │
price impact) │
position sweep (every pollMs) │
──▶ decideExit ──▶ executeSell │
└────────────────────────────────────────────────────────────────────┘
adapters: Feed Solana Wallet Executor Store
(launch (quote/build (resolve a (sign + (strategies,
stream) pump.fun ix) Keypair per broadcast) positions,
agentId) spend ledger)
ループに手を加えることなく、いずれかのアダプターを差し替えられます。ローカルキーの代わりにカストディアル KMS ウォレットを使う、メモリの代わりに Postgres ストアを使う、別のローンチフィードや別の取引所を使う、といったことが可能です。インターフェースに合わせて実装し、createSniper() に渡せば完了です。
| アダプター | 責務 |
|---|---|
Feed | { kind: 'mint'|'intel'|'claim', data: Candidate } イベントをエンジンに送信します。 |
Solana | pump.fun の買い/売り用インストラクションを見積もって構築し、web3 の Connection を公開します。 |
Wallet | agentId に対応する署名用 Keypair を解決します(未プロビジョニングの場合は null)。 |
Executor | 署名とブロードキャストを行う唯一の場所です。着地状況のテレメトリーを返します。 |
Store | 戦略、ポジション、日次支出台帳を永続化し、アトミックな claimPosition を実行します。 |
任意の Hooks(ファイアウォールの assessSafety、oracleGate、onScreen、onBuy、onSell、recordDecision)は、ベストエフォートの横断的なコールバックです。例外は捕捉されて無視され、取引が中断されることはありません。ただし、意図的に拒否権を持つ onTip は除きます。
インストール
npm i @three-ws/agent-sniper
必要な形態を使う場合にのみインストールする、任意のピア依存関係です。
npm i better-sqlite3 # durable Store (src/adapters/store/sqlite.js)
npm i express # the x402 HTTP API face
Node >= 20 が必要です。
クイックスタート(ライブラリ)
presets.local の構成は、すぐに実行できる最短の方法です。インメモリストア、自己管理型ウォレット、pump.fun クライアント、web3 エグゼキューター、PumpPortal フィードを利用します。まず devnet で simulate モードを実行してください。エンジンはすべての判断をスコアリング、ガード、記録しますが、ブロードキャストは行いません。
戦略には必ず stop_loss_pct を設定してください。設定されていない戦略はエンジンによって有効化が拒否されます。戦略の SOL 額は lamports(1 SOL = 1,000,000,000 lamports)で指定し、文字列、数値、または bigint を使用できます。
import { createSniper, createMemoryStore, presets } from '@three-ws/agent-sniper';
// 1 SOL = 1e9 lamports.
const SOL = 1_000_000_000n;
const strategy = {
id: 'strat_scout_1',
agent_id: 'scout', // one wallet per agentId
enabled: true,
trigger: 'new_mint', // fire on the create event
network: 'devnet',
per_trade_lamports: (SOL / 100n).toString(), // 0.01 SOL per snipe
daily_budget_lamports: (SOL / 2n).toString(), // 0.5 SOL/day ceiling
max_concurrent_positions: 3,
slippage_bps: 500, // 5%
max_price_impact_pct: 10, // entry circuit breaker
stop_loss_pct: 30, // REQUIRED — exit when down 30%
take_profit_pct: 80, // exit when up 80%
trailing_stop_pct: 20, // exit when down 20% from peak (after profit)
max_hold_seconds: 1800, // hard time-stop
require_socials: true, // skip launches with no twitter/telegram/website
max_creator_launches: 10, // skip serial launchers
};
const sniper = await presets.local({
network: 'devnet',
mode: 'simulate', // no funds move
strategies: [strategy],
// secrets: { scout: '<base58 | [byte,array] | 0x-hex secret>' }, // for live mode
});
await sniper.start();
console.log(sniper.stats()); // { events, candidates, buys, sells, errors, strategies, queued, lastEventAt }
console.log(sniper.strategies()); // the live armed-strategy cache
// Fire a manual buy by hand (drives the same path as MCP snipe_now):
sniper.submitCandidate(
{ mint: 'THREEsynthetic1111111111111111111111111111111', entry_trigger: 'manual' },
{ force: true },
);
// later…
await sniper.stop();
独自のアダプターを使う場合は、低レベルのコンストラクター createSniper(deps) を利用できます。{ config, store, wallet, solana, executor, feed, hooks } を渡してください。presets.local はその構成例の 1 つにすぎません。
CLI の使い方
このパッケージをインストールすると、agent-sniper バイナリが利用できます。デフォルトは simulate モードです。--mode live を渡すか SNIPER_MODE=live を設定するまで、資金は動きません。これにより実際の資金で取引します。
# Run the engine. Mode defaults to simulate; live trades real funds.
npx agent-sniper run --network devnet --strategy ./strategy.json
# Serve the engine over MCP (stdio) for Claude / Cursor / any MCP client.
agent-sniper mcp
# Serve the x402-gated HTTP API + web console (open http://localhost:8787).
agent-sniper serve
# Help.
agent-sniper help
安全性。
run/serve/mcpは、明示的にライブモードを選択しない限り、すべて simulate モードで起動します。ライブモードでは、有効化された各戦略が UTC 日ごとに最大daily_budget_lamportsまで支出できます。切り替える前に、以下の安全性とガードレールをお読みください。
--strategy ./strategy.json を指定すると、戦略(または戦略の配列)を JSON として読み込みます。最小構成のファイルはクイックスタートのオブジェクトと同じ形式です。stop_loss_pct が必須である点に注意してください。
MCP サーバー
agent-sniper mcp は、エンジンを MCP stdio サーバーとして公開します。各ツールは公開されているエンジン/ストアのメソッドに 1 対 1 で対応しており、内部処理を迂回することはありません。
サーバーは認証なしで利用でき、手持ちのウォレット/RPC に対してローカルで実行することを想定しています。
| ツール | 種別 | 用途 |
|---|---|---|
arm_strategy | write | 戦略を登録/更新します。SOL は自動で lamports に変換されます。stop_loss_pct は必須です。 |
disarm_strategy | write | 戦略を無効化します(enabled=false)。オープン中のポジションは、引き続き設定されたルールに従って決済されます。 |
list_strategies | read | エンジンが評価している有効な戦略の一覧を取得します。 |
snipe_now | write | 有効なすべてのエージェントで、手動購入を強制実行します(スコアリングを迂回します)。 |
list_positions | read | ポジションの一覧を取得します。agentId および/または status で絞り込めます。 |
close_position | write | 決済をスケジュールします。ポジションのキルスイッチが切り替わり、次回のスイープで売却されます。 |
sniper_status | read | エンジンの健全性を確認します。イベント/候補/購入/売却の件数、有効な戦略数、キューの深さ、ネットワーク/モードを確認できます。 |
MCP クライアント(Claude Desktop、Cursor など)に接続します:
{
"mcpServers": {
"agent-sniper": {
"command": "npx",
"args": ["-y", "@three-ws/agent-sniper", "mcp"],
"env": {
"SNIPER_NETWORK": "devnet",
"SNIPER_MODE": "simulate"
}
}
}
}
createSniperMcpServer(deps) は、トランスポートに接続せずに登録済みのサーバーを構築するため、テスト内で構築し、メモリ内トランスポート経由で操作できます。
x402 有料 HTTP API
agent-sniper serve(または import { serve } from '@three-ws/agent-sniper/api')は、エンジンを HTTP 経由で公開します。読み取りは無料です。変更を伴う 4 つのエンドポイントは、@three-ws/x402-server による x402 USDC マイクロペイメントで保護されています。ミドルウェアはファシリテーターに対して X-PAYMENT ヘッダーを検証し、処理を実行してオンチェーンで決済し、レシートを出力します。
| メソッド | エンドポイント | 価格 | 備考 |
|---|---|---|---|
| GET | /health | 無料 | 稼働状態とネットワーク/モード/統計情報。 |
| GET | /status | 無料 | すべての統計情報と変更不可の実行時設定。 |
| GET | /strategies | 無料 | 有効な戦略の一覧。 |
| GET | /positions?agentId=&status= | 無料 | ストアから取得したポジション。 |
| GET | /activity | 無料 | 最近のエンジン画面イベント(コンソールのフィードに表示される内容)。 |
| GET | / および /console | 無料 | 組み込みのオペレーターコンソール(下記参照)。 |
| POST | /strategies | $0.01 USDC | 戦略を有効化します(SOL は lamports に変換。ストップロスは必須)。 |
| POST | /snipe | $0.05 USDC | { mint, symbol?, agentId? } に対するスナイプを強制実行します。 |
| POST | /strategies/:id/disarm | $0.005 USDC | 戦略を無効化します。 |
| POST | /positions/:id/close | $0.005 USDC | 決済をスケジュールします。次回のスイープで売却されます。 |
価格はデフォルト値です(USDC の最小単位、6 桁の小数)。deps.prices = { arm, snipe, disarm, close } で変更できます。
加盟店ウォレットが設定されている場合、課金が有効になります。設定は deps.payTo.solana または X402_PAY_TO_SOLANA env で行います(Base レーンは X402_PAY_TO_BASE で利用できます)。payTo が設定されていない場合も変更を伴うルートはマウントされますが、503 を返すため、支払い設定なしでローカル/開発環境のサーバーを正常に起動できます。
Solana レーンには、ファシリテーターのスポンサー手数料支払い用アカウントも必要です。X402_FEE_PAYER_SOLANA(または deps.feePayer)を設定してください。未設定の場合、Solana レーンはリクエストを失敗させるのではなく、自動的に無効になります(Base レーンにフォールバックするか、利用可能なレーンが Solana のみの場合は 503 ガードを使用します)。起動時に警告が 1 回だけログに記録されます。
import { serve } from '@three-ws/agent-sniper/api';
await serve(
{ payTo: { solana: process.env.X402_PAY_TO_SOLANA } },
{ port: 8787 },
);
Web コンソール
serve には組み込みのオペレーターダッシュボードも付属します。API と同じオリジンの / および /console で配信される、依存関係のない単一の HTML ファイルです。http://localhost:8787 を開くと、リアルタイムのコントロールルームが表示されます。
- ライブ統計 — 買い、売り、候補、稼働中の戦略、処理中のキュー、シグナル数を、変化に合わせてアニメーション表示し、最後のシグナルからの経過時間も表示します。
- ポジションテーブル — 各ポジションのエントリー価格、現在の価値、色分けされた損益(未実現損益の合計はヘッダーに表示)を表示します。また、通常の売り経路で決済をスケジュールするワンクリックの決済ボタンもあります。
- 稼働中の戦略 — 各ポリシーの損切り/利確/トレーリングのタグと、解除ボタンを表示します。
- インライン検証付きの戦略の開始フォームと手動スナイプフォーム。
- ライブアクティビティフィード — CLI が出力するものと同じエンジン画面イベントを、相対タイムスタンプ付きでストリーミング表示します。
- 読み込み中/空/エラー状態、トースト、キーボードショートカット(
sでスナイプ、nで新しい戦略、rで更新、,で設定、?でヘルプ)、切断バナーに対応し、モバイルでも完全にレスポンシブです。
読み取りは無料です。外部から呼び出す場合、状態を変更する操作(開始、スナイプ、解除、決済)には x402 による支払いが必要です。自分のコンソールから費用を払わずに操作するには、オペレータートークンを設定します。
export SNIPER_ADMIN_TOKEN="$(openssl rand -hex 24)"
agent-sniper serve --port 8787
コンソールで設定(⚙ または ,)を開き、同じトークンを貼り付けます。トークンは X-Admin-Token(または Authorization: Bearer …)として送信され、ブラウザー内にのみ保存され、x402 のゲートを回避します。一方、認証されていない外部エージェントには引き続き支払いが求められます。プログラムから渡す場合は deps.adminToken を使用します。トークンを設定しない場合、コンソールはすべての機能を備えた読み取り専用モニターとして動作し、状態を変更する操作は案内メッセージとともに 503 を返します。
マルチエージェント/マルチユーザー
エンジンは設計上、マルチテナントに対応しています。分離の単位は agentId です。
- エージェントごとに 1 つのウォレット。
Walletアダプターは、エージェントごとに署名用のKeypairを解決します。セルフカストディの場合、secretsマップ、SNIPER_WALLET_<AGENTID>環境変数、<agentId>.jsonファイルを格納したキーストアディレクトリ、単一のデフォルトSOLANA_SECRET_KEYの順に参照します。エージェントにウォレットがプロビジョニングされていない場合、loadKeypairはnullを返し、エンジンは取引を安全に失敗させます。資金のないウォレットが自動的にプロビジョニングされることはありません。 - ホステッドデプロイではカストディ型。
createCustodialWallet({ resolve })は、必要に応じて独自の KMS/シークレット保管庫からキーを復号する非同期関数resolve(agentId, ctx)を受け取ります。TTL の短いキャッシュにより、長時間稼働するプロセスで取引のたびに復号することを防ぎます。キャッシュはエージェントごとに管理され、clearCache()を呼び出すと再解決されます。 - エージェントごとの上限。 各戦略には独自の
daily_budget_lamportsとmax_concurrent_positionsが設定されます。ガードは、プラットフォーム全体の買いスロットルとは独立して、エージェントごとに上限を適用します。 - 損切りは必須です。
getArmedStrategiesはstop_loss_pctが設定されていない戦略を除外するため、エージェントが損失上限なしで稼働することはありません。 - 冪等なクレームにより二重購入を防止します。 購入前に、エンジンは
Store.claimPositionを呼び出して(agent_id, mint, network)スロットをアトミックに予約します。同じスロットへの 2 回目のイベントはnullを返し、スキップされます。
3D エージェント
@three-ws/agent-sniper/agents は、3D AI エージェントにスナイパーを体現させるプレゼンテーション層です。アバター定義、標準アニメーションクリップライブラリ、そしてエンジンの onScreen フックによって制御されるデスクモニターのビジュアライゼーションを提供します。このフックを接続して、ライブアクティビティ(Sniper online…、$SYM scored N — BUYING)をエージェントのモニターに表示すれば、単なるログストリームではなく、取引ループを目で確認できます。onScreen ペイロードの形式は { text, kind } で、kind は activity | trade です。
アダプターのリファレンス
以下のいずれかを実装し(src/types.js に完全な JSDoc の契約があります)、createSniper に渡してください。デフォルト実装は src/adapters/ にあります。
| インターフェース | デフォルト実装 | 独自に実装する場合… |
|---|---|---|
Store | createMemoryStore · createSqliteStore (./adapters/store/sqlite) | 永続的な状態や複数プロセス間で共有する状態(例:Postgres)が必要な場合。 |
Wallet | createSelfCustodyWallet · createCustodialWallet | キーを KMS/HSM またはホスト型のシークレットストアに保存する場合。 |
Solana | createPumpClient (./adapters/solana/pump-client) | 見積もりやビルドを別の取引先経由で行う場合。 |
Executor | createWeb3Executor (./adapters/solana/executor-web3) | カスタムのリレー/バンドラー経由でブロードキャストする場合。 |
Feed | createPumpPortalFeed (./adapters/feed/pumpportal) | 別のソースからローンチ情報を取り込む場合。 |
Store の契約は特に重要です。getArmedStrategies、countOpenPositions、getDailySpendLamports、claimPosition(アトミック)、updatePosition、getOpenPositions、および任意の recordSpend が含まれます。インメモリのリファレンスは src/adapters/store/memory.js を参照してください。
設定
すべての SNIPER_* 環境変数(loadConfig が読み込み、src/config.js に定義されています)。createSniper/loadConfig に渡す明示的なオーバーライドが常に優先されます。.env.example を参照してください。
| 変数 | デフォルト | 意味 |
|---|---|---|
SNIPER_NETWORK | mainnet | mainnet | devnet。 |
SNIPER_MODE | simulate | simulate | live。simulate ではブロードキャストは行われません。 |
SOLANA_RPC_URL | — | RPC エンドポイント。ライブモードではこれ(または HELIUS_API_KEY)が必要です。 |
SNIPER_GLOBAL_KILL | false | 緊急スイッチ — true の場合、すべての買いを停止します。 |
SNIPER_POLL_MS | 5000 | ポジションの再見積もり/決済の間隔(最小値 1000)。 |
SNIPER_STRATEGY_REFRESH_MS | 15000 | 戦略キャッシュの更新間隔(最小値 5000)。 |
SNIPER_MAX_GLOBAL_BUYS_PER_MIN | 10 | プラットフォーム全体の買い注文のスロットル。0 で無効になります。 |
SNIPER_BUY_CONCURRENCY | 3 | 同時に実行中のスナイプの最大数(最小値 1)。 |
SNIPER_BUY_QUEUE_DEPTH | 50 | キューに入れるスナイプの上限。超過分は破棄されます(最小値 1)。 |
SNIPER_CONFIRM_TIMEOUT_MS | 60000 | 取引ごとの確認タイムアウト(最小値 15000)。 |
SNIPER_FEED_WATCHDOG_MS | 180000 | フィードが停止した場合に再購読するまでの時間(最小値 30000)。 |
SNIPER_EXIT_ON_BEARISH | false | センチメント反転時の決済を有効にします。 |
SNIPER_EXIT_BEARISH_MIN_CONFIDENCE | 0.7 | 対応するために必要な弱気信頼度の最小値(0~1)。 |
安全性とガードレール
- デフォルトではシミュレーションします。 すべての顔はシミュレーションモードで開始します。ライブ取引は明示的に選択します。
- 損切りは必須です。
stop_loss_pctが設定されていない戦略は有効化されません。 - 1日の予算と同時実行数の上限。 エージェントごとの
daily_budget_lamportsとmax_concurrent_positionsは、トランザクションの構築前に適用されます (checkDailyBudgetLamports、checkConcurrency)。 - SOL 手数料分の余裕。
checkSolHeadroomはウォレットに約 0.012 SOL を残し、 スナイプによって、次の売却手数料を支払うのに必要な額を下回るまでアカウント残高が 減ることを防ぎます。 - 価格影響のサーキットブレーカー。
max_price_impact_pct(デフォルトは 10)は、 見積もりの価格影響が大きすぎる買いをスキップします(checkPriceImpact。未設定の場合は ゲートなし)。 - ライブ RPC の拒否。 ライブモードはパブリック RPC での起動を拒否します。取引が レート制限によって黙って破棄されないよう、実際のエンドポイントが必要です。
- オプションのファイアウォールフック。
assessSafetyフックは見積もり後、 ブロードキャスト前に実行されます。判定がblockの場合、取引をキャンセルします。 - Mayhem の除外。
createMayhemFilter({ connection?, rpcUrl?, strictOnUnknown?, retries?, retryDelayMs? })はボンディングカーブのisMayhemModeを読み取り(ミントごとにキャッシュ)、 pump.fun の Mayhem モードでのローンチをスキップします。0.1.4 以降は、単一のrpcUrlの代わりに、事前構築済みの web3Connection(たとえば、複数のエンドポイントを ローテーションするもの)を渡せます。また、null の読み取りは「不明」として解決する前に バックオフ付きで再試行されます(デフォルトは 2 回)。これにより、スロットリングされた プロバイダーによって厳格なゲートが妨げられることを防ぎます。純粋関数のretryWhileNull(fn, { retries, delayMs })ヘルパーもエクスポートされています。 - グローバルキルスイッチ。
SNIPER_GLOBAL_KILL=true(またはconfig.globalKill)を 設定すると、すべてのエージェントによるすべての買いを即座に停止します。
1 プロセスを超えるスケーリング
メモリストアと sqlite ストアにおける claimPosition は、1 つのプロセス内では
アトミックです。メモリストアは JavaScript がシングルスレッドであることに依存し、
sqlite ストアは単一ライターのトランザクションに依存します。エンジンのプロセス内の
有界な買いキューと組み合わせることで、単一のスナイパーインスタンス内で同じ
(agent_id, mint, network) スロットを二重に買うことを防ぎます。
同じエージェントに対して 2 つのスナイパープロセスを実行すると、この保証は
成り立たなくなります。プロセス間でクレームを直列化するものがないためです。水平に
スケーリングするには、Store のバックエンドに、claimPosition が真にアトミックな
「存在しない場合にのみ挿入」を行うデータベースを使用してください(例:
(agent_id, mint, network) に一意制約を設定し、
INSERT … ON CONFLICT DO NOTHING RETURNING を使用する方法)。これにより、
予約は単一のプロセスではなくデータベースによって決定されます。Store の契約には、
この要件が正確に記載されています。
テスト
純粋ロジックとインメモリーアダプターのテストスイートは、ネットワーク/RPC なしで実行できます。
npm test # vitest run
ライセンス
Apache-2.0。詳細は LICENSE を参照してください。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。