From 064e8dab4c7ef09b7b54d07555bdee8d6af6d8c3 Mon Sep 17 00:00:00 2001 From: Alexander Lawson Date: Thu, 2 Apr 2026 15:28:43 -0400 Subject: [PATCH] docs: add partner integration specs for Bankr, Gina, and Robonet - bankr-integration-spec.md: Discovery layer enrichment with trust scores - gina-failure-signal-mapping.md: Failure mode to scoring signal mapping - robonet-mcp-composition.md: MCP server composition guide Co-Authored-By: Claude Opus 4.6 (1M context) --- docs/integrations/bankr-integration-spec.md | 370 +++++++++++++++ .../gina-failure-signal-mapping.md | 422 ++++++++++++++++++ docs/integrations/robonet-mcp-composition.md | 369 +++++++++++++++ 3 files changed, 1161 insertions(+) create mode 100644 docs/integrations/bankr-integration-spec.md create mode 100644 docs/integrations/gina-failure-signal-mapping.md create mode 100644 docs/integrations/robonet-mcp-composition.md diff --git a/docs/integrations/bankr-integration-spec.md b/docs/integrations/bankr-integration-spec.md new file mode 100644 index 0000000..cbab40d --- /dev/null +++ b/docs/integrations/bankr-integration-spec.md @@ -0,0 +1,370 @@ +# Bankr x Revettr Integration Specification + +**Version**: 1.0 +**Date**: 2026-04-02 +**Status**: Draft +**Partners**: Bankr (x402 Cloud), Revettr (Counterparty Risk Scoring) + +## Overview + +Bankr operates the x402 Cloud discovery layer -- indexing x402-enabled endpoints so +AI agents can find and evaluate services before transacting. Today, Bankr's discovery +responses include endpoint metadata (pricing, capabilities, uptime) but lack +counterparty trust data. Agents must make payment decisions without knowing whether the +endpoint operator is trustworthy. + +This integration embeds Revettr risk scores directly into Bankr's discovery index. +When an endpoint registers with Bankr, the indexer calls Revettr to score the +operator's wallet, domain, and chain presence. The resulting score, tier, and flags +are cached alongside the endpoint metadata. Agents querying Bankr's discovery API +receive trust data inline -- no extra call required. + +The result: agents can filter and rank x402 endpoints by trust before spending a +single cent. + +## Architecture + +``` ++-------------------+ +-------------------+ +-------------------+ +| x402 Endpoint | | Bankr | | Revettr | +| (registers) | | (discovery) | | (risk scoring) | ++--------+----------+ +--------+----------+ +--------+----------+ + | | | + | 1. POST /register | | + | {url, wallet, domain, | | + | capabilities, pricing} | | + +-------------------------->| | + | | | + | | 2. POST /v1/score | + | | {wallet_address, | + | | domain, chain} | + | +-------------------------->| + | | | + | | 3. Response | + | | {score, tier, flags, | + | | confidence} | + | |<--------------------------+ + | | | + | | 4. Cache score in index | + | | (24h TTL) | + | | | + | | | ++-------------------+ | | +| Agent | | | +| (queries) | | | ++--------+----------+ | | + | | | + | 5. GET /discover | | + | ?capability=swap | | + +-------------------------->| | + | | | + | 6. Response with | | + | enriched listings | | + | (includes revettr_*) | | + |<--------------------------+ | + | | | +``` + +## API Contract + +### Scoring at Index Time + +When Bankr indexes a new or updated endpoint, it calls Revettr's scoring API: + +**Request**: `POST https://revettr.com/v1/score` + +```json +{ + "wallet_address": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", + "domain": "swap-api.example.com", + "chain": "base" +} +``` + +**Response** (HTTP 200): + +```json +{ + "score": 85, + "tier": "low", + "confidence": 0.75, + "signals_checked": 2, + "flags": [], + "signal_scores": { + "domain": { + "score": 80, + "flags": [], + "available": true, + "details": { + "domain_age_days": 1200, + "dns": {"has_mx": true, "has_spf": true, "has_dmarc": true} + } + }, + "wallet": { + "score": 90, + "flags": [], + "available": true, + "details": { + "blockchain": {"tx_count": 500, "unique_counterparties": 87}, + "onchain": {"nonce": 312, "eth_balance": 1.45} + } + } + }, + "metadata": { + "inputs_provided": ["wallet_address", "domain"], + "latency_ms": 980, + "version": "0.1.0" + } +} +``` + +**Payment**: $0.01 USDC per request via x402 on Base. Bankr's indexer wallet pays +automatically using the x402 protocol. + +### Discovery Response Enrichment + +Bankr adds three fields to each endpoint listing in discovery responses: + +| Field | Type | Description | +|-------|------|-------------| +| `revettr_score` | `int` (0-100) | Composite risk score. Higher is safer. | +| `revettr_tier` | `string` | Risk tier: `low` (80-100), `medium` (60-79), `high` (30-59), `critical` (0-29) | +| `revettr_flags` | `list[string]` | Machine-readable risk flags (e.g., `domain_age_under_30d`, `wallet_never_transacted`) | + +Example enriched discovery response: + +```json +{ + "endpoints": [ + { + "url": "https://swap-api.example.com/v1/swap", + "wallet": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", + "capability": "swap", + "chain": "base", + "price_usdc": 0.05, + "uptime_30d": 0.997, + "revettr_score": 85, + "revettr_tier": "low", + "revettr_flags": [] + }, + { + "url": "https://shady-swap.xyz/api", + "wallet": "0xabc123...", + "capability": "swap", + "chain": "base", + "price_usdc": 0.02, + "uptime_30d": 0.91, + "revettr_score": 28, + "revettr_tier": "critical", + "revettr_flags": ["domain_age_under_30d", "wallet_age_under_7d", "no_mx_records"] + } + ] +} +``` + +### Batch Enrichment + +For bulk indexing runs (new chain onboarding, periodic re-index), Bankr can use the +batch scoring endpoint to reduce latency and per-request overhead: + +**Request**: `POST https://revettr.com/v1/score_batch` + +```json +{ + "requests": [ + {"wallet_address": "0xaaa...", "domain": "api-a.com", "chain": "base"}, + {"wallet_address": "0xbbb...", "domain": "api-b.com", "chain": "base"}, + {"wallet_address": "0xccc...", "domain": "api-c.com", "chain": "base"} + ] +} +``` + +**Response** (HTTP 200): + +```json +{ + "results": [ + {"score": 85, "tier": "low", "flags": [], "confidence": 0.75}, + {"score": 62, "tier": "medium", "flags": ["wallet_age_under_30d"], "confidence": 0.60}, + {"score": 15, "tier": "critical", "flags": ["sanctions_exact_match"], "confidence": 1.0} + ], + "metadata": { + "batch_size": 3, + "latency_ms": 2100 + } +} +``` + +**Pricing**: $0.01 USDC per item in the batch. Max batch size: 100. + +## Score Refresh Policy + +Scores are not static. The refresh policy balances freshness against cost: + +| Trigger | Action | +|---------|--------| +| **Stale threshold** | Re-score any endpoint whose cached score is older than 24 hours | +| **Wallet change detected** | If Bankr detects the endpoint's wallet address changed, re-score immediately | +| **Domain change detected** | If the endpoint's domain or IP changes, re-score immediately | +| **Agent-requested refresh** | Agent passes `?refresh_score=true` on discovery query; Bankr re-scores before responding | +| **Manual flag** | Bankr admin can force re-score via internal tooling | + +Bankr should store `revettr_scored_at` (ISO 8601 timestamp) alongside each cached +score to implement TTL-based expiry. + +## Feedback Loop + +To improve scoring accuracy over time, Bankr can report transaction outcomes back +to Revettr. This creates a supervised signal: real-world success/failure data tied +to scored counterparties. + +### Proposed Endpoint + +**Request**: `POST https://revettr.com/v1/feedback` + +```json +{ + "wallet_address": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", + "domain": "swap-api.example.com", + "chain": "base", + "outcome": "success", + "tx_hash": "0x789abc...", + "amount_usdc": 0.05, + "latency_ms": 1200, + "agent_id": "bankr-discovery-v1" +} +``` + +| Field | Type | Required | Description | +|-------|------|----------|-------------| +| `wallet_address` | string | Yes | The scored counterparty wallet | +| `domain` | string | No | The scored domain | +| `chain` | string | No | Blockchain network | +| `outcome` | string | Yes | `success`, `failure`, `timeout`, `reverted` | +| `tx_hash` | string | No | On-chain transaction hash for verification | +| `amount_usdc` | float | No | Transaction value | +| `latency_ms` | int | No | End-to-end transaction time | +| `agent_id` | string | No | Identifier for the reporting agent/system | + +**Response** (HTTP 200): + +```json +{ + "accepted": true, + "feedback_id": "fb_abc123" +} +``` + +This endpoint is free -- no x402 payment required. Outcome data is the payment. + +## Business Model + +Two options for the Bankr partnership: + +### Option A: Free Scoring for Outcome Data + +- Bankr scores endpoints at no cost (Revettr waives the $0.01/score fee) +- In exchange, Bankr sends all transaction outcome data via the feedback endpoint +- Revettr uses this labeled data to improve scoring models +- Best for: early partnership phase, mutual growth + +### Option B: Volume Pricing + +- Standard rate: $0.01 USDC per score via x402 +- Volume tiers (monthly): + - 0-10,000 scores: $0.01/score + - 10,001-100,000: $0.008/score + - 100,001+: $0.005/score +- Feedback endpoint remains free regardless of tier +- Best for: scaled operations where outcome data alone is insufficient + +Recommendation: Start with Option A during the integration phase (first 90 days), +then evaluate whether to transition to Option B based on volume. + +## Agent Decision Flow + +Python code sample showing how an agent uses Bankr's enriched discovery to make +trust-aware decisions: + +```python +import httpx +from revettr import Revettr + +# Agent discovers x402 endpoints via Bankr +async def find_trusted_swap_endpoint(token_pair: str, max_price: float) -> dict | None: + """Find the most trusted, affordable swap endpoint.""" + + async with httpx.AsyncClient() as client: + # Query Bankr discovery with capability filter + resp = await client.get( + "https://bankr.cloud/discover", + params={"capability": "swap", "token_pair": token_pair}, + ) + endpoints = resp.json()["endpoints"] + + # Filter: only endpoints scoring >= 60 (exclude high and critical risk) + trusted = [ep for ep in endpoints if ep.get("revettr_score", 0) >= 60] + + # Filter: within budget + affordable = [ep for ep in trusted if ep["price_usdc"] <= max_price] + + if not affordable: + return None + + # Sort: highest trust score first, then lowest price + affordable.sort(key=lambda ep: (-ep["revettr_score"], ep["price_usdc"])) + + return affordable[0] + + +# Usage in an agent loop +async def execute_swap(token_pair: str, amount: float): + endpoint = await find_trusted_swap_endpoint(token_pair, max_price=0.10) + + if endpoint is None: + print("No trusted endpoint found within budget") + return + + print(f"Selected: {endpoint['url']}") + print(f" Trust: {endpoint['revettr_score']}/100 ({endpoint['revettr_tier']})") + print(f" Price: ${endpoint['price_usdc']} USDC") + print(f" Flags: {endpoint.get('revettr_flags', [])}") + + # If any flags are present, log them for the agent operator + if endpoint.get("revettr_flags"): + print(f" Warning: {len(endpoint['revettr_flags'])} risk flag(s) noted") + + # Proceed with x402 payment to the endpoint + # ... (x402 payment flow here) +``` + +## Implementation Timeline + +| Week | Milestone | Owner | +|------|-----------|-------| +| **Week 1** | Bankr indexer calls `POST /v1/score` on new registrations; cache score with 24h TTL | Bankr | +| **Week 1** | Revettr provisions Bankr indexer wallet for x402 payments (or activates Option A waiver) | Revettr | +| **Week 2** | Discovery API returns `revettr_score`, `revettr_tier`, `revettr_flags` in listings | Bankr | +| **Week 2** | Batch endpoint (`/v1/score_batch`) deployed for bulk indexing | Revettr | +| **Week 3** | Score refresh logic: 24h stale check, wallet/domain change triggers | Bankr | +| **Week 3** | Feedback endpoint (`/v1/feedback`) deployed | Revettr | +| **Week 4** | Bankr sends transaction outcomes via feedback loop | Bankr | +| **Week 4** | End-to-end testing, monitoring, launch | Both | + +## Error Handling + +| Scenario | Bankr Behavior | +|----------|----------------| +| Revettr returns HTTP 402 | Retry with x402 payment; if wallet balance is insufficient, index without score and flag for manual review | +| Revettr returns HTTP 5xx | Retry once after 2s; if still failing, index without score, set `revettr_score: null` | +| Revettr timeout (>10s) | Index without score, queue for async re-score | +| Score is `critical` (0-29) | Index the endpoint but mark it with a warning badge in discovery UI | +| Sanctions flag present | Do not index the endpoint; notify Bankr compliance team | + +## Security Considerations + +- Bankr's indexer wallet private key must be stored in a secrets manager, never in code +- All Revettr API calls use HTTPS (enforced by the SDK) +- Feedback data should not include PII -- only wallet addresses, domains, and tx hashes +- Bankr should rate-limit discovery queries that include `?refresh_score=true` to + prevent score-refresh abuse diff --git a/docs/integrations/gina-failure-signal-mapping.md b/docs/integrations/gina-failure-signal-mapping.md new file mode 100644 index 0000000..3edabbe --- /dev/null +++ b/docs/integrations/gina-failure-signal-mapping.md @@ -0,0 +1,422 @@ +# Ask Gina x Revettr: Failure Signal Mapping + +**Version**: 1.0 +**Date**: 2026-04-02 +**Status**: Draft +**Partners**: Ask Gina (DeFi Execution Agent), Revettr (Counterparty Risk Scoring) + +## Overview + +Ask Gina is a DeFi execution agent with $5M+ in transaction volume, 100K+ +transactions, and 18 months of production data. During that time, Gina has +accumulated a rich dataset of transaction failures -- gas drains, MEV attacks, +bridge locks, and slippage events -- each labeled with root cause and financial +impact. + +Revettr currently scores counterparties using domain intelligence, IP reputation, +on-chain wallet history, and sanctions screening. These signals are strong for +identifying bad actors but do not capture DeFi-specific execution risks like MEV +exposure or bridge reliability. + +This document maps Gina's failure modes to new Revettr scoring signals. The +partnership creates a feedback loop: Gina provides labeled failure data, Revettr +converts it into predictive signals, and both systems get smarter. Gina's agents +get pre-execution risk checks; Revettr gets the highest-quality DeFi failure +dataset in the market. + +## Failure Mode to Signal Mapping + +| Failure Mode | Revettr Signal | Score Impact | Description | +|-------------|----------------|-------------|-------------| +| Gas drain | `contract_high_revert_rate` | -15 to -30 | Contract consumes gas but reverts. Gina sees this as failed txns where gas was spent but no state change occurred. A revert rate >20% on a contract is a strong negative signal. | +| MEV front-running | `mev_exposure` | -10 to -25 | Transaction was sandwiched or front-run by MEV bots. Gina detects this by comparing expected vs actual execution price. Pools or routers with high MEV incidence get flagged. | +| Bridge locks | `bridge_lock_incidents` | -20 to -40 | Funds locked in a bridge for >24h or permanently lost. Gina tracks bridge completion times; bridges with >2% lock rate are high risk. This is the most financially damaging failure mode. | +| Slippage | `low_liquidity_pool` | -5 to -20 | Execution price deviated >2% from quote due to thin liquidity. Gina measures slippage across pools; consistently high slippage indicates a pool that agents should avoid or size down. | + +### Impact Scaling + +Score impact scales with severity within each range: + +- **Gas drain**: -15 for revert rate 20-35%, -22 for 35-50%, -30 for >50% +- **MEV exposure**: -10 for <5% of txns affected, -18 for 5-15%, -25 for >15% +- **Bridge locks**: -20 for lock rate 2-5%, -30 for 5-10%, -40 for >10% +- **Slippage**: -5 for avg slippage 2-5%, -12 for 5-10%, -20 for >10% + +## Proposed SignalScore Definitions + +Following Revettr's existing `SignalScore` dataclass shape: + +```python +from dataclasses import dataclass, field + + +@dataclass +class SignalScore: + """Score from a single signal group.""" + score: int + flags: list[str] = field(default_factory=list) + available: bool = True + details: dict = field(default_factory=dict) +``` + +### Gas Drain Signal + +```python +SignalScore( + score=55, + flags=["contract_high_revert_rate"], + available=True, + details={ + "contract_address": "0xdead...", + "revert_rate": 0.38, + "sample_size": 1200, + "observation_period_days": 90, + "source": "gina_failure_data", + }, +) +``` + +### MEV Exposure Signal + +```python +SignalScore( + score=68, + flags=["mev_exposure"], + available=True, + details={ + "pool_address": "0xbeef...", + "mev_incident_rate": 0.08, + "avg_extraction_bps": 45, + "sample_size": 3400, + "observation_period_days": 90, + "source": "gina_failure_data", + }, +) +``` + +### Bridge Lock Signal + +```python +SignalScore( + score=30, + flags=["bridge_lock_incidents"], + available=True, + details={ + "bridge_contract": "0xcafe...", + "lock_rate": 0.07, + "avg_lock_duration_hours": 72, + "funds_at_risk_usdc": 12500, + "sample_size": 800, + "observation_period_days": 180, + "source": "gina_failure_data", + }, +) +``` + +### Low Liquidity Signal + +```python +SignalScore( + score=78, + flags=["low_liquidity_pool"], + available=True, + details={ + "pool_address": "0xfeed...", + "avg_slippage_bps": 320, + "median_slippage_bps": 180, + "liquidity_usd": 45000, + "sample_size": 5600, + "observation_period_days": 90, + "source": "gina_failure_data", + }, +) +``` + +## Data Partnership + +### What Gina Provides + +| Data | Format | Frequency | Volume | +|------|--------|-----------|--------| +| Labeled failure events | JSON via webhook or batch upload | Daily | ~200-500 events/day | +| Transaction outcomes (success/failure) | JSON | Daily | ~2,000-5,000/day | +| Contract revert rates | Aggregated CSV | Weekly | All monitored contracts | +| MEV incident logs | JSON with sandwich tx hashes | Daily | ~50-100/day | +| Bridge completion times | JSON with timestamps | Daily | ~100-300/day | +| Pool slippage measurements | JSON with quote vs execution | Daily | ~1,000-3,000/day | + +Data format example (failure event): + +```json +{ + "event_id": "gina_fail_20260402_001", + "timestamp": "2026-04-02T14:23:00Z", + "failure_type": "gas_drain", + "chain": "base", + "contract_address": "0xdead...", + "wallet_address": "0xabc...", + "tx_hash": "0x123...", + "gas_spent_wei": "2100000000000000", + "expected_outcome": "swap_executed", + "actual_outcome": "reverted", + "financial_impact_usdc": 3.50, + "context": { + "function_called": "swapExactTokensForTokens", + "revert_reason": "INSUFFICIENT_OUTPUT_AMOUNT" + } +} +``` + +### What Revettr Provides + +| Data | Format | Access | +|------|--------|--------| +| Pre-execution risk scores | JSON via API | Real-time | +| DeFi signal scores (new) | JSON, included in score response | Real-time | +| Risk alerts for monitored contracts | Webhook | Near real-time | +| Aggregated risk intelligence | Dashboard access | On-demand | + +## Integration Architecture + +Revettr integrates between Gina's Filter and Executor stages: + +``` ++------------------+ +| User Request | +| "Swap 1000 USDC | +| for ETH" | ++--------+---------+ + | + v ++------------------+ +| Gina Planner | +| Route, estimate | +| gas, pick pool | ++--------+---------+ + | + v ++------------------+ +| Gina Filter | +| Basic checks: | +| slippage limit, | +| gas ceiling | ++--------+---------+ + | + v ++------------------+ +-------------------+ +| REVETTR CHECK |---->| Revettr API | +| Score the pool | | POST /v1/score | +| contract and |<----| + DeFi signals | +| counterparty | +-------------------+ ++--------+---------+ + | + score >= threshold? + / \ + YES NO + | | + v v ++----------+ +-----------+ +| Gina | | Blocked | +| Executor | | + reason | +| (send tx)| | returned | ++----------+ +-----------+ +``` + +### Integration Point + +Gina adds a single check between Filter and Executor: + +```python +from revettr import Revettr + +client = Revettr() + + +def get_min_score(trade_size_usdc: float) -> int: + """Dynamic threshold based on trade size. + + Larger trades require higher trust scores. + """ + if trade_size_usdc >= 10_000: + return 80 + elif trade_size_usdc >= 1_000: + return 60 + elif trade_size_usdc >= 100: + return 40 + else: + return 20 # Micro-transactions: minimal gating + + +async def pre_execution_check( + contract_address: str, + counterparty_wallet: str, + counterparty_domain: str | None, + chain: str, + trade_size_usdc: float, +) -> dict: + """Score the counterparty before Gina executes a transaction. + + Returns: + dict with "approved" (bool), "score", "tier", "flags", and "reason" + """ + min_score = get_min_score(trade_size_usdc) + + result = client.score( + wallet_address=counterparty_wallet, + domain=counterparty_domain, + chain=chain, + ) + + approved = result.score >= min_score + + response = { + "approved": approved, + "score": result.score, + "tier": result.tier, + "confidence": result.confidence, + "flags": result.flags, + "min_score_required": min_score, + "trade_size_usdc": trade_size_usdc, + } + + if not approved: + response["reason"] = ( + f"Score {result.score}/100 is below the required {min_score} " + f"for a ${trade_size_usdc:,.2f} trade. " + f"Tier: {result.tier}. Flags: {', '.join(result.flags) or 'none'}." + ) + + # Check for specific DeFi signals from Gina-sourced data + defi_warnings = [] + for signal_name, signal_data in result.signal_scores.items(): + for flag in signal_data.flags: + if flag in ( + "contract_high_revert_rate", + "mev_exposure", + "bridge_lock_incidents", + "low_liquidity_pool", + ): + defi_warnings.append( + f"{flag} (signal score: {signal_data.score}/100)" + ) + + if defi_warnings: + response["defi_warnings"] = defi_warnings + + return response + + +# Example usage in Gina's pipeline +async def gina_execute_swap(plan: dict): + check = await pre_execution_check( + contract_address=plan["contract"], + counterparty_wallet=plan["counterparty_wallet"], + counterparty_domain=plan.get("counterparty_domain"), + chain=plan["chain"], + trade_size_usdc=plan["amount_usdc"], + ) + + if not check["approved"]: + return {"status": "blocked", "reason": check["reason"]} + + if check.get("defi_warnings"): + # Log warnings but proceed (operator can configure to block) + for warning in check["defi_warnings"]: + print(f" DeFi warning: {warning}") + + # Proceed to Gina Executor + # ... execute the transaction ... + return {"status": "executed", "revettr_score": check["score"]} +``` + +## Dynamic Threshold by Trade Size + +| Trade Size (USDC) | Min Score | Rationale | +|-------------------|-----------|-----------| +| < $100 | 40 | Micro-transactions: low financial risk, allow broader access | +| $100 - $999 | 40 | Small trades: moderate gating, block only high/critical risk | +| $1,000 - $9,999 | 60 | Medium trades: require at least medium tier | +| $10,000+ | 80 | Large trades: require low-risk tier only | + +The threshold function is configurable per Gina deployment. Operators managing +institutional funds may set higher minimums across the board. + +## Scoring Response with DeFi Signals + +Once Gina failure data is integrated, the Revettr score response includes +DeFi-specific signal scores alongside existing signals: + +```json +{ + "score": 52, + "tier": "high", + "confidence": 0.82, + "signals_checked": 4, + "flags": ["contract_high_revert_rate", "mev_exposure"], + "signal_scores": { + "domain": { + "score": 75, + "flags": [], + "available": true, + "details": {"domain_age_days": 400} + }, + "wallet": { + "score": 80, + "flags": [], + "available": true, + "details": {"blockchain": {"tx_count": 200, "unique_counterparties": 45}} + }, + "defi_execution": { + "score": 42, + "flags": ["contract_high_revert_rate", "mev_exposure"], + "available": true, + "details": { + "revert_rate": 0.35, + "mev_incident_rate": 0.12, + "data_source": "gina", + "observation_period_days": 90, + "sample_size": 4600 + } + } + }, + "metadata": { + "inputs_provided": ["wallet_address", "domain"], + "latency_ms": 1100, + "version": "0.2.0" + } +} +``` + +## Implementation Timeline + +| Week | Milestone | Owner | +|------|-----------|-------| +| **Week 1** | Define webhook schema for failure event ingestion | Both | +| **Week 1** | Gina exports historical failure dataset (18 months) | Gina | +| **Week 2** | Revettr ingests historical data, builds initial signal models | Revettr | +| **Week 2** | Define `defi_execution` signal group and scoring weights | Revettr | +| **Week 3** | Gina integrates pre-execution check between Filter and Executor | Gina | +| **Week 3** | Revettr deploys DeFi signal scores in API responses | Revettr | +| **Week 4** | Daily failure event webhook goes live | Gina | +| **Week 4** | Dynamic threshold configuration exposed via Gina operator settings | Gina | +| **Week 5** | Monitoring, alerting, and model accuracy evaluation | Both | +| **Week 6** | Public announcement, documentation update | Both | + +## Data Privacy and Security + +- Gina failure data is used solely for scoring model improvement +- No end-user PII is included in failure events (only wallet addresses and tx hashes) +- Gina can redact any fields before sending +- Data retention: Revettr retains aggregated signals indefinitely; raw failure events + are retained for 12 months, then purged +- Gina can request deletion of all submitted data with 30 days notice + +## Success Metrics + +| Metric | Target | Measurement | +|--------|--------|-------------| +| False positive rate (blocked good txns) | < 5% | Compare blocked txns against manual review | +| True positive rate (caught bad txns) | > 70% | Compare flagged counterparties against actual failures | +| Gina failure rate reduction | 30%+ | Compare pre/post integration failure rates | +| Score latency p95 | < 2 seconds | Measured at Gina's integration point | +| Data freshness | < 24 hours | Time from Gina failure event to Revettr signal update | diff --git a/docs/integrations/robonet-mcp-composition.md b/docs/integrations/robonet-mcp-composition.md new file mode 100644 index 0000000..1ad3d0d --- /dev/null +++ b/docs/integrations/robonet-mcp-composition.md @@ -0,0 +1,369 @@ +# Robonet x Revettr: MCP Server Composition + +**Version**: 1.0 +**Date**: 2026-04-02 +**Status**: Draft +**Partners**: Robonet (DeFi Strategy MCP), Revettr (Counterparty Risk Scoring MCP) + +## Overview + +Robonet operates 7 specialized DeFi agents backed by 30+ MCP tools covering yield +farming, liquidity provision, vault deployment, rebalancing, and more. Revettr +provides counterparty risk scoring as a single MCP tool (`score_counterparty`). + +When both MCP servers run side-by-side in a client like Claude Desktop, Cursor, or +a custom agent, the LLM can compose their tools naturally: discover a strategy with +Robonet, score the vault or protocol with Revettr, then deploy or reject based on +trust. No custom integration code is needed -- MCP composition handles it. + +This document shows how to configure both servers, wire them into agent workflows, +and enforce a "score before deploy" policy via system prompts. + +## MCP Client Configuration + +### Claude Code (`~/.claude.json`) + +```json +{ + "mcpServers": { + "revettr": { + "command": "uvx", + "args": ["revettr-mcp"], + "env": { + "REVETTR_WALLET_KEY": "${REVETTR_WALLET_KEY}" + } + }, + "robonet": { + "command": "npx", + "args": ["-y", "@robonet/mcp-server"], + "env": { + "ROBONET_API_KEY": "${ROBONET_API_KEY}", + "ROBONET_NETWORK": "base" + } + } + } +} +``` + +### Cursor (`.cursor/mcp.json`) + +```json +{ + "mcpServers": { + "revettr": { + "command": "uvx", + "args": ["revettr-mcp"], + "env": { + "REVETTR_WALLET_KEY": "${REVETTR_WALLET_KEY}" + } + }, + "robonet": { + "command": "npx", + "args": ["-y", "@robonet/mcp-server"], + "env": { + "ROBONET_API_KEY": "${ROBONET_API_KEY}", + "ROBONET_NETWORK": "base" + } + } + } +} +``` + +### Remote HTTP Transport (Streamable HTTP) + +For server-side deployments where both MCP servers run as remote services: + +```json +{ + "mcpServers": { + "revettr": { + "type": "streamable-http", + "url": "https://mcp.revettr.com/sse", + "headers": { + "Authorization": "Bearer ${REVETTR_MCP_TOKEN}" + } + }, + "robonet": { + "type": "streamable-http", + "url": "https://mcp.robonet.ai/sse", + "headers": { + "Authorization": "Bearer ${ROBONET_MCP_TOKEN}" + } + } + } +} +``` + +Remote transport is preferred for production agents that run on servers (no local +`uvx` / `npx` processes). Both servers expose Streamable HTTP endpoints that +MCP clients connect to over HTTPS. + +## Agent Flow: Score Before Deploy + +The core pattern is a 4-step flow that any MCP-capable agent follows: + +``` +Step 1: DISCOVER Step 2: SCORE ++---------------------+ +---------------------+ +| Robonet tools: | | Revettr tool: | +| | | | +| discover_strategies |----->| score_counterparty | +| get_vault_details | | wallet_address | +| estimate_yield | | domain | +| | | chain | ++---------------------+ +----------+----------+ + | + score >= 60? + / \ + YES NO + | | + v v + Step 3: DEPLOY Step 4: EXPLAIN + +---------------------+ +---------------------+ + | Robonet tools: | | Agent explains: | + | | | | + | deploy_to_vault | | "Vault scored 35 | + | set_rebalance_rules | | (high risk) due | + | confirm_position | | to flags: ..." | + +---------------------+ +---------------------+ +``` + +### Detailed Step-by-Step + +**Step 1: Discover strategy** + +The agent (or user) asks for yield opportunities. Robonet tools handle this: + +``` +User: "Find me the best ETH yield vault on Base" + +Agent calls: robonet.discover_strategies( + asset="ETH", + chain="base", + strategy_type="vault", + sort_by="apy" +) + +Response: [ + {name: "Morpho ETH Vault", apy: 8.2%, vault: "0xabc...", domain: "morpho.org"}, + {name: "NewYield ETH", apy: 12.1%, vault: "0xdef...", domain: "newyield.xyz"}, + ... +] +``` + +**Step 2: Score the counterparty** + +Before deploying to any vault, the agent scores it with Revettr: + +``` +Agent calls: revettr.score_counterparty( + wallet_address="0xdef...", + domain="newyield.xyz", + chain="base" +) + +Response: { + score: 35, + tier: "high", + flags: ["domain_age_under_30d", "wallet_age_under_7d"], + confidence: 0.65 +} +``` + +**Step 3: Gate the decision** + +The agent applies the scoring policy: + +- Score >= 60: proceed to deploy +- Score < 60: explain the risk and suggest alternatives + +``` +Agent: "NewYield ETH vault (12.1% APY) scored 35/100 -- high risk. +Flags: domain is less than 30 days old, wallet has less than 7 days +of history. I recommend the Morpho ETH Vault instead. Let me score it." + +Agent calls: revettr.score_counterparty( + wallet_address="0xabc...", + domain="morpho.org", + chain="base" +) + +Response: {score: 92, tier: "low", flags: [], confidence: 0.85} + +Agent: "Morpho ETH Vault scored 92/100 (low risk). 8.2% APY. +Shall I deploy?" +``` + +**Step 4: Deploy or explain** + +If approved, the agent calls Robonet deployment tools: + +``` +Agent calls: robonet.deploy_to_vault( + vault_address="0xabc...", + amount_eth=1.0, + chain="base" +) +``` + +## System Prompt Template + +To enforce the "always score before deploying" policy, include this in the agent's +system prompt. This works with any MCP client that supports system prompts (Claude +Desktop, Cursor, custom agents): + +``` +You have access to two MCP tool servers: + +1. **Robonet** -- DeFi strategy discovery and execution + Tools: discover_strategies, get_vault_details, estimate_yield, + deploy_to_vault, set_rebalance_rules, withdraw_position, and more. + +2. **Revettr** -- Counterparty risk scoring + Tool: score_counterparty (accepts domain, wallet_address, chain) + +MANDATORY POLICY: Before calling ANY Robonet tool that moves funds +(deploy_to_vault, set_rebalance_rules, swap, bridge, or any tool +that triggers an on-chain transaction), you MUST first call +revettr.score_counterparty with the target contract's wallet address +and domain. + +Scoring rules: +- Score 80-100 (low risk): Safe to proceed. Inform the user of the score. +- Score 60-79 (medium risk): Proceed with caution. Warn the user about + any flags and ask for explicit confirmation before deploying. +- Score 30-59 (high risk): DO NOT deploy. Explain the risk flags to the + user and suggest alternatives. +- Score 0-29 (critical risk): DO NOT deploy. This counterparty has + severe risk indicators. Explain why and refuse the transaction. + +If Revettr is unavailable (timeout, error), DO NOT proceed with +deployment. Inform the user that the risk check could not be completed. + +Always show the user: score, tier, confidence, and any flags before +asking for deployment confirmation. +``` + +## Cost Model + +| Action | Tool | Cost | +|--------|------|------| +| Discover strategies | `robonet.discover_strategies` | Free (read-only) | +| Get vault details | `robonet.get_vault_details` | Free (read-only) | +| Estimate yield | `robonet.estimate_yield` | Free (read-only) | +| Score counterparty | `revettr.score_counterparty` | $0.01 USDC (x402) | +| Deploy to vault | `robonet.deploy_to_vault` | $0.02 USDC (Robonet fee) | +| Set rebalance rules | `robonet.set_rebalance_rules` | $0.01 USDC (Robonet fee) | + +**Per deployment decision cost**: $0.01 (Revettr score) + $0.01-$0.02 (Robonet +execution) = **$0.02-$0.03 total**. + +At scale, an agent making 100 deployment decisions per day pays $2-$3/day for +trust-gated DeFi execution. This is negligible compared to the value at risk in +each deployment. + +### Cost Optimization + +- **Cache scores**: Revettr scores are valid for 24h. If the agent scores the same + vault multiple times in a session, the MCP client can cache the first result. +- **Batch discovery**: Score multiple vaults in parallel before presenting options + to the user, rather than scoring one at a time. +- **Skip scoring for known vaults**: Maintain a local allowlist of vault addresses + that have been scored recently and consistently score >= 80. + +## Example: Full Conversation + +``` +User: I have 5 ETH. Find me the best yield on Base. + +Agent: I'll search for ETH yield strategies on Base. + +[Calls robonet.discover_strategies(asset="ETH", chain="base", sort_by="apy")] + +Found 4 strategies: +1. NewYield ETH Vault -- 12.1% APY (0xdef...) +2. Morpho Blue ETH -- 8.2% APY (0xabc...) +3. Aave v3 ETH -- 4.8% APY (0x111...) +4. Compound III ETH -- 4.1% APY (0x222...) + +Let me check the risk profile of the top options before recommending one. + +[Calls revettr.score_counterparty(wallet_address="0xdef...", + domain="newyield.xyz", chain="base")] +[Calls revettr.score_counterparty(wallet_address="0xabc...", + domain="morpho.org", chain="base")] + +Risk assessment: + +| Vault | APY | Score | Tier | Flags | +|-------|-----|-------|------|-------| +| NewYield | 12.1% | 35 | high | domain_age_under_30d, wallet_age_under_7d | +| Morpho Blue | 8.2% | 92 | low | (none) | + +I do NOT recommend NewYield despite the higher APY. The domain is +less than 30 days old and the contract wallet has less than 7 days +of on-chain history. These are strong risk signals. + +Morpho Blue scored 92/100 (low risk) with no flags. The 8.2% APY +is solid and the protocol has a strong trust profile. + +Shall I deploy 5 ETH to Morpho Blue? + +User: Yes, go ahead. + +[Calls robonet.deploy_to_vault(vault_address="0xabc...", + amount_eth=5.0, chain="base")] + +Done. 5 ETH deployed to Morpho Blue ETH vault on Base. +- Estimated APY: 8.2% +- Risk score: 92/100 (low) +- Transaction: 0x789... +``` + +## Advanced: Multi-Agent Orchestration + +For Robonet deployments with multiple specialized agents (e.g., a yield agent, a +rebalancing agent, and a risk monitoring agent), Revettr can serve as the shared +risk layer: + +``` ++-------------------+ +-------------------+ +-------------------+ +| Yield Agent | | Rebalance Agent | | Monitor Agent | +| (discovers, | | (adjusts | | (watches | +| deploys) | | positions) | | positions) | ++--------+----------+ +--------+----------+ +--------+----------+ + | | | + | score_counterparty | score_counterparty | (reads cached) + +------------+------------+------------+------------+ + | | + v v + +-------+-------------------------+-------+ + | Revettr MCP | + | (shared risk scoring for all agents) | + +-----------------------------------------+ +``` + +Each Robonet agent independently calls `score_counterparty` before any fund-moving +action. The scoring is stateless -- no coordination between agents is needed. If +Revettr flags a vault as risky, the rebalancing agent will refuse to increase +exposure to it, even if the yield agent originally deployed there when the score +was higher. + +## Error Handling + +| Scenario | Agent Behavior | +|----------|----------------| +| Revettr MCP unavailable | Do not deploy. Inform user: "Risk check unavailable. Cannot proceed." | +| Revettr returns error | Retry once. If still failing, do not deploy. | +| Robonet MCP unavailable | Cannot discover or deploy. Inform user. | +| Score is borderline (55-65) | Show user the score and flags. Ask for explicit confirmation. | +| Both servers healthy but score is critical | Refuse deployment. Suggest the user research the protocol independently. | + +## Security Notes + +- `REVETTR_WALLET_KEY` funds x402 payments. Store in environment variables or a + secrets manager. Never hardcode in config files checked into version control. +- `ROBONET_API_KEY` authenticates with Robonet. Same storage guidance applies. +- For remote HTTP transport, MCP tokens should be rotated regularly. +- The system prompt policy is enforced by the LLM, not by code. For hard enforcement, + wrap Robonet's fund-moving tools in a middleware that calls Revettr programmatically.