Instructions to use withgordon/acb-guard-session-graph-rf with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Scikit-learn
How to use withgordon/acb-guard-session-graph-rf with Scikit-learn:
from huggingface_hub import hf_hub_download import joblib model = joblib.load( hf_hub_download("withgordon/acb-guard-session-graph-rf", "sklearn_model.joblib") ) # only load pickle files from sources you trust # read more about it here https://skops.readthedocs.io/en/stable/persistence.html - Notebooks
- Google Colab
- Kaggle
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_idit 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:
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. scoreisP(fraud);flagsare the top contributing features for attribution.
Usage
The repository ships two files:
session_graph.py— feature extraction +SessionGraphModelclass and module-level API.session_graph_rf.joblib— the fittedRandomForestClassifier.
Load the trained classifier
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
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.pyimports session/event schema types from the ACB harness (harness.simulate.schema:Session,Event,ActionType). Feature extraction and thedetectinterface 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.
0forsession.is_clean,1otherwise. - 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=42for reproducible fits.
Retraining is a single call:
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.0for 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
@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.