Skip to content
banking-bodyguard-cbbtc-signals logo

Banking Bodyguard — Integration Skill

banking-bodyguard-cbbtc-signals

Banking Bodyguard provides scored cbBTC whale-transfer signals on Base via x402, scoring transfers BEARISH/NEUTRAL/BULLISH against a labelled-address graph and returning HOLD/TIGHTEN_STOP/EXIT recommendations with impact and confidence levels. Use when building Base-network trading agents that ho...

SKILL.md

Full skill instructions

Banking Bodyguard — Integration Skill

A teaching manifest for AI coding assistants helping developers integrate Banking Bodyguard's cbBTC whale signal API into trading agents on Base.

This document is a recipe, not a reference. The reference is llms.txt at https://bodyguard.finance/​llms.txt — read it first if you haven't, then come back here. This file teaches an AI assistant how to walk a developer through building a real agent that consumes Banking Bodyguard signals.

Who this is for

Developers building autonomous or semi-autonomous agents that hold or manage cbBTC exposure on Base. Three concrete personas:

  1. Lending-vault operators — agents that hold cbBTC as collateral on Morpho, Aave, Moonwell, or similar Base lending markets, and need to defend the position against oracle-repricing risk.
  2. DEX liquidity rebalancers — agents managing concentrated liquidity positions on Aerodrome or Uniswap V3 cbBTC pools, deciding when to shift ranges, reduce inventory, or pull liquidity.
  3. cbBTC spot risk managers — agents holding directional cbBTC exposure on Base (treasury, market-making inventory, accumulated yield-farming rewards, or a balance sheet position) who need early warning of large flow events to scale exposure, rotate to safer venues, or trigger a hedge on an external venue (CEX BTC perps, Hyperliquid BTC perps). Banking Bodyguard provides the trigger; the hedge execution lives off-Base.

Banking Bodyguard is not for: BTC spot directional trading, multi-chain whale watching, or general market sentiment. It is a tool for cbBTC-on-Base decisions specifically.

The recipe

Goal

Wire Banking Bodyguard signals into the agent's decision loop so that on each tick (or each signal-driven event), the agent gets a confidence-gated, scored read on whether a market-moving cbBTC whale flow just happened — and adjusts the position accordingly.

The operational value is lead time. High-confidence BEARISH+HIGH signals typically precede cbBTC oracle repricing on Base lending markets (Morpho, Aave, Moonwell) by 60–120 seconds. That window is enough to reduce collateral, tighten a health factor, or shift an LP range before the price move is fully reflected on-chain.

Ingredients

Banking Bodyguard has two access tiers. The free tier needs almost nothing; the paid tier needs an x402 wallet. Sequence the integration in that order.

For free-tier evaluation (first 20 calls per client):

  • A plain HTTP client. requests in Python, fetch in TypeScript, curl from a shell. No SDK, no wallet, no signup.
  • The agent's existing position-management code, even if stubbed. Banking Bodyguard slots in as one signal source, not a replacement for the agent's own state.

For paid usage (call 21 onward):

  • An EVM wallet on Base, holding USDC. The wallet signs the EIP-712 TransferWithAuthorization payload that x402 requires from call 21 onward. The wallet becomes the payment identity from that point.
  • The x402 SDK at version 2.9 or later (Python: pip install x402; TypeScript: npm install x402-fetch viem).
  • A clear definition of the agent's risk parameters: how much exposure to reduce on EXIT, what counts as "tight enough" stops, what cooldown to enforce between signal-triggered actions.

The agent owns the risk parameters. Banking Bodyguard owns the signal. The free tier exists to let you prove the integration shape before you commit a wallet.

Steps

Step 1 — Verify the integration with demo mode before touching real money.

import requests

resp = requests.get(
    "https://bodyguard.finance/​x402/​signal/​cbbtc/​latest?demo=true"
)
sample_signal = resp.json()
assert sample_signal.get("demo") is True
print(sample_signal)

Demo mode returns a realistic sample payload, marked "demo": true, with no payment required. Use it to validate response parsing, field-handling logic, and the agent's gating code paths before connecting a real wallet. Unlimited calls, no cost.

Step 2 — Evaluate with plain HTTP. No wallet required for the first 20 calls.

import requests

r = requests.get("https://bodyguard.finance/​x402/​signal/​cbbtc/​latest")
signal = r.json()

print(f"Signal: {signal['recommendation']} (score {signal['sentiment_score']}, "
      f"impact {signal['impact_level']}, confidence {signal['confidence']})")
print(f"Free tier remaining: {signal.get('free_tier_remaining', 'paid')}")

The first 20 real (non-demo) calls per client return live signals without charging. The response includes "free_tier_remaining": N counting down from 19 to 0. No wallet, no API key, no signup — the rate limit is keyed to the client. This is where you exercise the agent's gating logic against real production data and confirm the decision shape is right before any USDC moves.

After the 20th free call the same endpoint returns HTTP 402 with an x402 payment challenge instead of a signal. That's the signal to graduate to Step 3.

Step 3 — Graduate to paid: install the x402 SDK, fund a Base wallet with USDC, retry.

import os
from x402.clients.requests import x402_requests
from eth_account import Account

account = Account.from_key(os.environ["AGENT_WALLET_KEY"])
session = x402_requests(account)

r = session.get("https://bodyguard.finance/​x402/​signal/​cbbtc/​latest")
signal = r.json()

The SDK handles the 402 challenge, EIP-712 signing, and X-PAYMENT header construction automatically. The same GET that returned 402 with plain requests now returns 200 with a signal, and 0.10 USDC settles on-chain via the CDP facilitator. Gas is paid by the facilitator; the wallet only needs USDC.

A paid response does not carry the free_tier_remaining field — its absence is the signal that the call charged. If you want a programmatic check, key off signal.get("free_tier_remaining") being None.

Step 4 — Wire the signal into the agent's decision loop.

def consume_whale_signal(signal: dict, position_state: dict) -> dict:
    """
    Return an action descriptor based on whale signal + current position.
    The agent's main loop applies the action.
    """
    # Gate first on confidence. LOW confidence = at least one address unknown.
    if signal["confidence"] != "HIGH":
        return {"action": "hold", "reason": "low_confidence"}

    # Strongest action: bearish + high impact + high score.
    if signal["recommendation"] == "EXIT" and signal["sentiment_score"] >= 8:
        return {
            "action": "reduce_exposure",
            "reason": "bearish_high_impact",
            "signal_id": signal["signal_id"],
        }

    # Bearish + medium impact: defensive adjustment.
    if signal["recommendation"] == "TIGHTEN_STOP":
        return {
            "action": "defensive_adjustment",
            "reason": "bearish_medium_impact",
            "signal_id": signal["signal_id"],
        }

    # Bullish with non-trivial impact: accumulation candidate.
    if (signal["sentiment_label"] == "BULLISH"
            and signal["impact_level"] != "LOW"):
        return {
            "action": "increase_exposure",
            "reason": "bullish_meaningful_impact",
            "signal_id": signal["signal_id"],
        }

    return {"action": "hold", "reason": "noise_or_neutral"}

The function returns an action descriptor; it does not execute anything. The agent's main loop decides whether to act, with cooldowns, position sizing, and price confirmation layered on top.

Step 5 — Add a cooldown so the agent doesn't churn on every poll.

import time

class WhaleSignalConsumer:
    def __init__(self, cooldown_seconds: int = 300):
        self.cooldown_seconds = cooldown_seconds
        self.last_action_at = 0
        self.last_signal_id = None

    def evaluate(self, signal: dict, position_state: dict) -> dict | None:
        # Don't act on the same signal twice.
        if signal["signal_id"] == self.last_signal_id:
            return None

        # Don't act inside the cooldown window.
        if time.time() - self.last_action_at < self.cooldown_seconds:
            return None

        action = consume_whale_signal(signal, position_state)
        if action["action"] != "hold":
            self.last_action_at = time.time()
            self.last_signal_id = signal["signal_id"]
            return action
        return None

Cooldown defaults to 5 minutes. For LP rebalancing on Aerodrome or Uniswap V3, push it higher (10–15 minutes) — gas costs on range shifts erode signal alpha if rebalances fire too often.

Step 6 — Confirm the action makes sense against current price.

def confirm_with_price(action: dict, current_price: float, prior_price_1h: float) -> bool:
    """
    Add a price-confirmation gate. A whale moving cbBTC to an exchange means
    less if price is already pricing it in.
    """
    price_change_1h_pct = (current_price - prior_price_1h) / prior_price_1h * 100

    if action["reason"] == "bearish_high_impact":
        # Confirm bearish action only if price hasn't already dropped >2%.
        return price_change_1h_pct > -2.0

    if action["reason"] == "bullish_meaningful_impact":
        # Confirm bullish action only if price hasn't already rallied >2%.
        return price_change_1h_pct < 2.0

    return True

This gate is the difference between a signal-driven agent and a signal-and-price-driven agent. The latter performs meaningfully better in backtest.

Verification

After steps 1–6, run the agent in dry-run mode for 24 hours. Log every signal, every action descriptor, and every confirm/​skip decision. Compare against the live track record dashboard at https://bodyguard.finance/​track-record.html. The agent should be acting on roughly 5–15% of incoming signals (high-confidence, non-NEUTRAL, non-LOW-impact). If it's acting on more, the gates are too loose. If it's acting on fewer than 1%, either the gates are too tight or recent market conditions are quiet.

Only after dry-run validation should the agent's action functions wire into real position adjustments.

Worked example — cbBTC-collateralized lending vault defender

A complete minimal agent that defends a cbBTC-collateralized loan against oracle-repricing risk.

import os
import time
import logging
import requests
from x402.clients.requests import x402_requests
from eth_account import Account

logging.basicConfig(level=logging.INFO)
log = logging.getLogger("cbbtc_defender")

# --- Configuration ---
POLL_INTERVAL_S = 60         # 1-minute poll
COOLDOWN_S = 600             # 10 minutes between signal-triggered actions
REDUCE_FRACTION = 0.30       # Reduce collateral by 30% on EXIT
PRICE_CONFIRM_THRESHOLD = 2.0  # Skip if price already moved 2% in signal direction

# --- Setup ---
account = Account.from_key(os.environ["AGENT_WALLET_KEY"])
bb_session = x402_requests(account)

class Position:
    """Stub for the agent's position state. Replace with real protocol calls."""
    def __init__(self):
        self.cbbtc_collateral = 5.0    # 5 cbBTC posted
        self.debt_usdc = 200_000.0      # $200k borrowed
        self.last_action_at = 0
        self.last_signal_id = None

position = Position()

# --- Signal consumption ---
def fetch_signal() -> dict | None:
    try:
        r = bb_session.get(
            "https://bodyguard.finance/​x402/​signal/​cbbtc/​latest",
            timeout=10,
        )
        r.raise_for_status()
        return r.json()
    except Exception as e:
        log.warning(f"Signal fetch failed: {e}")
        return None

def fetch_cbbtc_price() -> tuple[float, float]:
    """Return (current_price, price_1h_ago). Stub — replace with real oracle."""
    return 79_000.0, 79_500.0  # example

def evaluate(signal: dict) -> str | None:
    if signal["signal_id"] == position.last_signal_id:
        return None
    if time.time() - position.last_action_at < COOLDOWN_S:
        return None
    if signal["confidence"] != "HIGH":
        return None

    if (signal["recommendation"] == "EXIT"
            and signal["sentiment_score"] >= 8):
        return "reduce_collateral"
    if signal["recommendation"] == "TIGHTEN_STOP":
        return "tighten_health_factor"
    return None

def execute(action: str, signal: dict) -> None:
    current_price, prior_price = fetch_cbbtc_price()
    price_change_pct = (current_price - prior_price) / prior_price * 100

    if action == "reduce_collateral":
        if price_change_pct < -PRICE_CONFIRM_THRESHOLD:
            log.info(f"Skipping reduce_collateral — price already dropped "
                     f"{price_change_pct:.2f}%, signal {signal['signal_id']}")
            return
        amount = position.cbbtc_collateral * REDUCE_FRACTION
        log.info(f"Signal {signal['signal_id']}: reducing collateral by "
                 f"{amount:.4f} cbBTC (BEARISH score {signal['sentiment_score']}, "
                 f"impact {signal['impact_level']})")
        # withdraw_collateral(amount)  <-- real protocol call goes here
        position.cbbtc_collateral -= amount
        position.last_action_at = time.time()
        position.last_signal_id = signal["signal_id"]

    elif action == "tighten_health_factor":
        log.info(f"Signal {signal['signal_id']}: tightening health factor "
                 f"(BEARISH medium impact)")
        # repay_partial_debt(...)  <-- real protocol call goes here
        position.last_action_at = time.time()
        position.last_signal_id = signal["signal_id"]

# --- Main loop ---
while True:
    signal = fetch_signal()
    if signal is not None:
        action = evaluate(signal)
        if action:
            execute(action, signal)
        else:
            log.debug(f"No action for signal {signal.get('signal_id')}")
    time.sleep(POLL_INTERVAL_S)

This is about 80 lines of agent code. The Banking Bodyguard integration is roughly 15 of those lines — the rest is position state and the action functions, which belong to the agent.

A few things to notice in the example:

  • The signal is treated as one of several inputs. The price-confirmation gate can override the signal.
  • The agent never acts on the same signal_id twice. Banking Bodyguard returns the most recent signal on each call; without this guard, a polling agent would re-act on the same whale movement repeatedly.
  • The cooldown is enforced before action, not after the action completes. This prevents a stuck or slow action call from re-triggering.
  • All actions are logged with the signal_id for audit and post-hoc accuracy review against the track record dashboard.

Common mistakes

Mistake 1 — Trusting the recommendation field without gating on confidence.

The recommendation field is populated on every signal, including LOW-confidence ones. A signal with confidence: "LOW" and recommendation: "EXIT" is the system saying "if my labels were right, this would be an EXIT — but at least one address is unknown so I'm not sure." Auto-acting on LOW-confidence recommendations produces high false-positive rates.

Mistake 2 — Treating NEUTRAL as a market read.

NEUTRAL (score 4–7) is not "the market is sideways." It is "I cannot classify this transfer's intent." Usually because both addresses are unknown, or because the flow direction is ambiguous (e.g., one DEX pool to another). The right interpretation is "no decision input from this signal." Do not flip to defensive mode on NEUTRAL.

Mistake 3 — Re-acting on the same signal.

The /​latest endpoint returns the most recent signal each time it's called. Without a signal_id deduplication check, an agent polling every 60 seconds will re-evaluate (and potentially re-act on) the same whale movement until the next one happens. Store last_signal_id and skip if matched.

Mistake 4 — Polling faster than 10 seconds.

The underlying watcher polls Base every 10 seconds. Faster client polling produces no new signals — just duplicate signal_ids and burned USDC. 60 seconds is a reasonable default for most agents; 10 seconds is the floor for liquidation protection.

Mistake 5 — Rebalancing LP ranges on every EXIT.

Gas + re-deposit cost on a concentrated liquidity range shift on Aerodrome or Uniswap V3 typically runs $5–20 per action on Base. A signal-triggered rebalance every 10 minutes burns more in gas than the whale-flow alpha generates. Threshold on impact_level == "HIGH" plus a 10–15 minute cooldown, and consider only acting on EXIT (not TIGHTEN_STOP) for range shifts.

Mistake 6 — Triggering an external hedge on a single signal.

Even high-confidence EXIT signals are wrong some percentage of the time. Opening a leveraged hedge on a CEX or external perp venue based on one signal exposes the agent to whipsaw losses if the signal turns out to be noise. Pair with current price action, or wait for a confirming second BEARISH signal in the same direction within a defined window (e.g., 30 minutes), before committing hedge capital.

Mistake 7 — Hardcoding the payment recipient or asset address.

The 402 challenge body carries network, asset contract address, and pay-to address as machine-readable fields. Read them from the response at runtime. Hardcoding them from documentation will break if the service ever migrates wallets or supports a second asset.

Composition patterns

Banking Bodyguard is one signal source. The best agents combine it with at least one orthogonal input.

Pattern 1 — Signal + price action.

Add a price-confirmation gate. Skip BEARISH actions if price has already dropped >2% in the last hour (whale flow is already in the price); skip BULLISH actions if price has already rallied >2%. This is shown in step 6 above.

Pattern 2 — Signal + external hedge trigger (for spot risk managers).

If the agent holds cbBTC spot on Base and a hedge venue lives elsewhere (BTC perps on a CEX, or a BTC perp on Hyperliquid), use Banking Bodyguard signals to trigger the hedge open/​close decision but execute on the external venue. Accept that cbBTC↔BTC basis risk is part of the cost; a hedge against directional risk is still net-positive when the alternative is unhedged spot exposure during a high-impact flow event.

Pattern 3 — Signal + position health factor (for lending agents).

Modulate the response by current position health. A BEARISH+HIGH+EXIT signal at health factor 1.8 might warrant a 20% reduction; at health factor 1.2 it might warrant 50%; at 1.05 it might warrant full exit regardless of signal strength. The signal is one input; the position's distance from liquidation is another.

Pattern 4 — Signal + LP range tightness (for liquidity rebalancers).

A whale signal matters more when the agent's LP range is narrow (high concentration, high impermanent loss risk on a price move). For a wide passive range covering ±20%, even HIGH-impact signals can usually be ignored. For a tight range of ±2%, the same signal warrants action. Composing impact_level with the position's range width gives a tighter trigger.

Pattern 5 — Signal + multi-signal confirmation.

Buffer the last N signals (e.g., last 30 minutes) and act only when two or more consecutive HIGH-confidence non-LOW-impact signals point the same direction. This trades latency for false-positive resistance. Good fit for agents where each action has a holding cost or transaction overhead.

When the agent's design doesn't fit Banking Bodyguard

Be honest about this. Banking Bodyguard is not the right signal for:

  • Sub-second HFT agents — signal delivery latency is 10–15 seconds from on-chain event; faster than oracle repricing, slower than HFT.
  • Multi-chain or multi-asset agents — coverage is cbBTC on Base only.
  • Agents that need push delivery rather than pull — WebSocket streaming is planned but not live.
  • Agents trading BTC spot or BTC perps on Binance/​Bybit/​CEX venues — cbBTC flows on Base do not move global BTC spot price reliably within a 1-hour window. Internal backtest, May 2026: of 20 BEARISH+HIGH+EXIT signals checked against 1-hour BTC spot moves on a major CEX, only 4 (20%) preceded a price drop; the other 16 (80%) were flat or up. The signal is for cbBTC-on-Base decisions — specifically front-running oracle repricing on Base lending markets — not BTC directional trading.

If the agent fits one of those descriptions, redirect the developer to other tools rather than wedging Banking Bodyguard into a use case it wasn't built for.

Reference

  • API documentation: https://bodyguard.finance/​llms.txt
  • Live signal history with KPIs: https://bodyguard.finance/​track-record.html
  • Service health and current metrics: https://bodyguard.finance/​health
  • Free Telegram alert channel (HIGH/​EXIT only, no x402 required): https://t.me/​+V5QAfdHgW9wwZjdl
  • Contact: @BankingBodygd on X
  • OpenAPI: https://bodyguard.finance/​docs

Read llms.txt for the full response schema, field semantics, and payment protocol. This file teaches the integration shape; that file documents the contract.

Popular AI tools

Kaiber logo
Video

Kaiber

Generate, edit, and beat-sync AI video with leading models in one workspace.

Paid
View
Vimcal logo
Productivity

Vimcal

The world's fastest calendar for remote work

Free
View

Transform Your Design with AI Designer by ImgCreator.ai

Freemium
View
Akool AI logo
Content & writing

Akool AI

Revolutionizing Video Production with AI-Powered Creativity

Paid
View

Extend an image past the frame and let AI fill the new aspect ratio.

Freemium
View
StarByFace logo
Security

StarByFace

Discover your celebrity doppelgänger with StarByFace!

Free
View
C

ChainClarity explains 700+ crypto whitepapers in plain English, with layered summaries, comparisons, research tools, alerts, and a $4.99 Pro plan.

Freemium
View
Opus Clip logo
Coding & apps

Opus Clip

Opus.ai: Revolutionize Your Web Experience

Free
View