ank3it's picture
Add model card / README
3c45901 verified
|
Raw
History Blame
10 kB
---
library_name: sklearn
tags:
- fraud-detection
- agentic-commerce
- agent-safety
- mcp
- random-forest
- tabular-classification
- session-graph
- anomaly-detection
pipeline_tag: tabular-classification
inference: false
extra_gated_prompt: "This model is part of the ACB-Guard research suite. Access is granted for research and evaluation purposes."
---
# ACB-Guard · Session Graph RandomForest (`session_graph_rf`)
A structural fraud detector for **agentic commerce sessions**. Every agent session is
represented as a directed graph of MCP (Model Context Protocol) calls, reduced to a
compact 20-dimensional feature vector, and scored by a scikit-learn
`RandomForestClassifier`. It is a novel baseline for
**AgentCommerceBench (ACB)** and ships as a drop-in per-event detector.
> **Core idea.** MCP call sequences form distinctive graphs per persona. Clean sessions
> produce regular, low-density graphs. Attacks introduce structural anomalies — high
> out-degree (reconnaissance), recursive purchase cycles, amount-variance spikes (price
> poisoning / ratcheting), and timing bursts. A graph view catches *behavioral* attacks
> that a text classifier alone will miss.
---
## Model at a glance
| | |
|---|---|
| **Model name** | `session_graph_rf` |
| **Task** | Binary session classification — `clean` (0) vs `attacked` (1) |
| **Algorithm** | `RandomForestClassifier` (scikit-learn), 200 trees, `max_depth=10`, `class_weight="balanced"` |
| **Input** | An agent commerce session (ordered list of MCP events) |
| **Output** | Fraud probability `P(fraud) ∈ [0, 1]` + top contributing feature flags |
| **Feature space** | 20 hand-engineered session-graph features |
| **Serialized as** | `session_graph_rf.joblib` (~833 KB, joblib/pickle) |
| **Interface** | `detect(event, history) -> (score, flags)` — drop-in with other ACB detectors |
| **Access** | 🔒 Gated |
---
## Why a graph model
ACB attacks fall into two broad families, and each needs a different lens:
- **L1 — prompt / payload attacks.** Injected instructions, base64-encoded payloads,
"SYSTEM:" overrides, and settlement-proxy redirects embedded in request text. These are
best caught by an LLM safety baseline and by lightweight payload heuristics.
- **L2 — behavioral attacks.** Reconnaissance sweeps, recursive purchases, price
ratcheting, and scope violations that look *fine per message* but are anomalous at the
**session** level. Text classifiers, which score one message at a time, are effectively
blind to these.
`session_graph_rf` targets the L2 gap by modelling the *shape* of a whole session, while
still carrying two cheap L1 signals (`has_override`, `has_b64`) so it degrades gracefully
when both attack families appear together. It is designed to **complement**, not replace,
the LLM safety baseline in the ACB-Guard ensemble.
---
## How it works
### 1. Session → graph
Each session is treated as a directed graph:
- **Nodes** — the agent plus every distinct `service_id` / `operation_id` it touches.
- **Edges** — directed call edges (`FIND_SERVICE → service`, `AUTHORIZE → service`, …).
- **Edge attributes** — normalized USDC amount, inter-event timing gap (seconds), and
service category.
### 2. Graph → 20-dim feature vector
`session_to_features(session)` reduces the graph to a fixed vector. Grouped by the signal
it is meant to expose:
| # | Feature | Signal |
|---|---|---|
| 0 | `n_events` | session size |
| 1 | `n_find_service` | discovery volume |
| 2 | `n_authorize` | authorization volume |
| 3 | `n_settle` | settlement volume |
| 4 | `find_authorize_ratio` | **reconnaissance** (search-heavy, buy-light) |
| 5 | `n_distinct_services` | breadth of services touched |
| 6 | `service_diversity` | entropy of the service distribution |
| 7 | `total_amount_usdc` | total spend |
| 8 | `max_amount_usdc` | largest single transfer |
| 9 | `amount_std_usdc` | **price ratcheting / poisoning** (variance) |
| 10 | `amount_max_ratio` | spike vs. session mean |
| 11 | `timing_gap_mean_s` | pacing |
| 12 | `timing_gap_std_s` | **burst** irregularity |
| 13 | `timing_gap_min_s` | tightest burst |
| 14 | `n_categories` | category breadth |
| 15 | `dominant_category_frac` | **scope violation** (purity) |
| 16 | `n_a2a_transfers` | agent-to-agent transfer count |
| 17 | `a2a_amount_usdc` | agent-to-agent spend |
| 18 | `has_override_keyword` | **L1**`SYSTEM:` / override / proxy-redirect in payload |
| 19 | `has_b64_blob` | **L1** — suspicious base64 blob in payload |
Amounts are converted from integer units to USDC (`amount_units / 1_000_000`).
`service_diversity` is Shannon entropy over the service-call distribution. The two L1
flags run regex/base64 checks over each event's `original_request`.
### 3. Vector → score
The RandomForest returns `P(fraud)`. Scores below **0.30** are suppressed to `0.0` to keep
the false-positive rate low. When a session is flagged, the detector attributes the
decision by ranking `feature_importance × |feature_value|` and emitting the top-3
contributing features as human-readable flags (e.g. `sgrf:find_auth_ratio=8.00`).
---
## The detector interface
The model plugs into the ACB harness through a per-event `detect` call and scores the
**full session** (history + current event) each time:
```python
def detect(event: Event, history: list[Event]) -> tuple[float, list[str]]:
...
```
- Returns `0.0, []` until the session has **≥ 4 events** (not enough context to judge).
- Caches per `(session_id, session_length)` so the RandomForest runs at most once per
session growth step — cheap enough to call on every event.
- `score` is `P(fraud)`; `flags` are the top contributing features for attribution.
---
## Usage
The repository ships two files:
- `session_graph.py` — feature extraction + `SessionGraphModel` class and module-level API.
- `session_graph_rf.joblib` — the fitted `RandomForestClassifier`.
### Load the trained classifier
```python
import joblib
from huggingface_hub import hf_hub_download
# Gated repo — authenticate first: `huggingface-cli login`
path = hf_hub_download(
repo_id="withgordon/acb-guard-session-graph-rf",
filename="session_graph_rf.joblib",
)
clf = joblib.load(path) # sklearn RandomForestClassifier
# clf expects a 20-dim feature vector produced by session_to_features(...)
# proba = clf.predict_proba(features_20d.reshape(1, -1))[0][1] # P(fraud)
```
### Score a session end-to-end
```python
from benchmark.models.session_graph import SessionGraphModel
model = SessionGraphModel()
model.fit(train_sessions) # list[Session]
score, flags = model.detect(event, history) # drop-in detector interface
print(score, flags) # e.g. 0.87 ['sgrf:find_auth_ratio=8.00', ...]
```
> **Note.** `session_graph.py` imports session/event schema types from the ACB harness
> (`harness.simulate.schema`: `Session`, `Event`, `ActionType`). Feature extraction and
> the `detect` interface require those types to be importable, so run it inside the ACB
> benchmark environment.
---
## Training
- **Estimator.** `RandomForestClassifier(n_estimators=200, max_depth=10, class_weight="balanced", random_state=42)`.
- **Labels.** `0` for `session.is_clean`, `1` otherwise.
- **Features.** The 20-dim vector above, stacked across all training sessions.
- **Class balance.** Handled via `class_weight="balanced"` (attacked sessions are the
minority class).
- **Determinism.** `random_state=42` for reproducible fits.
Retraining is a single call:
```python
model = SessionGraphModel(n_estimators=200, max_depth=10)
model.fit(train_sessions)
joblib.dump(model.clf, "session_graph_rf.joblib")
```
---
## Intended use & scope
**Intended.** A behavioral, session-level fraud baseline for AgentCommerceBench and for
research on safety in agentic commerce / MCP tool-use settings. Best used as one member of
an ensemble alongside an LLM safety baseline.
**Out of scope.** Not a standalone production fraud system; not a general payments risk
model; not intended for real financial authorization decisions. The two embedded L1 flags
are convenience signals, not a substitute for a dedicated prompt-injection defense.
---
## Limitations
- **Feature-engineered, not learned graph structure.** The model consumes hand-crafted
aggregate features rather than a learned graph embedding (no GNN). It captures the
intended structural signals but not arbitrary graph patterns.
- **Cold start.** Returns `0.0` for the first 3 events of every session by design; very
short attacks may complete before enough context accumulates.
- **Threshold coupling.** The 0.30 suppression threshold trades recall for precision and
may need re-tuning per deployment / attack mix.
- **Distribution shift.** Trained on ACB-simulated sessions; behavior on real-world agent
traffic, unseen attack strategies, or different MCP schemas is not characterized here.
- **Attribution is heuristic.** Flags rank `importance × |value|`, an approximation of true
per-prediction contribution — treat them as hints, not SHAP-grade explanations.
- **Serialization caveat.** Distributed as a joblib/pickle artifact; only load it from a
source you trust.
---
## Files
| File | Description |
|---|---|
| `session_graph.py` | Feature extraction, `SessionGraphModel`, and module-level `detect` API |
| `session_graph_rf.joblib` | Fitted scikit-learn `RandomForestClassifier` (~833 KB) |
---
## Citation
```bibtex
@software{acb_guard_session_graph_rf,
title = {ACB-Guard: Session Graph RandomForest for Agentic Commerce Fraud Detection},
author = {withgordon},
year = {2026},
note = {A novel session-graph baseline for AgentCommerceBench},
url = {https://huggingface.co/withgordon/acb-guard-session-graph-rf}
}
```
---
*Part of the **ACB-Guard** suite for AgentCommerceBench. This model targets L2 behavioral
attacks and is designed to complement an LLM safety baseline that handles L1 payload
attacks.*