Skip to content
All projects

Tell: Catching a Payments Agent Being Talked Into Theft

SJSU hackathon, run on an HP ZGX Nano · Sep 2026 · AI Engineering, ML Engineering

Reads a payments agent's hidden state before each decision and hands risky ones to a safer copy of itself, on one local GPU.

Python · PyTorch · CUDA · Qwen3-8B · Hugging Face Transformers · LoRA · NVIDIA GB10 · Tesseract · SQLite

0.841
AUROC on held-out invoice attacks, 400 records from 50 documents
17 GB
GPU memory to serve Qwen3-8B and its adapter on one GB10
76 / 76
clean invoices still paid correctly with routing on

An accounts-payable agent reads supplier emails, invoices, tool results and its own memory, then proposes payments. An attacker can write any of that text. Tell watches the model’s hidden state before each decision, scores it with a linear probe, and hands risky decisions to a safety-tuned LoRA of the same model. Only a deterministic validator and action gate can execute a payment, and the ledger is simulated, so no real money moves.

Served on the device

Tell needs the model’s hidden activations, which hosted endpoints don’t expose, so every model call runs locally on one HP ZGX Nano (NVIDIA GB10).

  • One model, two agents. Qwen3-8B loads once in BF16. The base agent and the safety agent share those weights: the LoRA adapter (7.67M parameters, 0.09%) is attached once and switched on per decision.
  • CPU and GPU kept apart. A standard-library web server handles uploads, text extraction and OCR on the CPU. A single GPU worker holds the model, probe and adapter, and takes jobs from a local SQLite queue one at a time.
  • Measured cost. About 17 GB of GPU memory. Scoring a decision adds 1.5 to 2.2 s, the probe itself takes 1 to 3 ms, and a full clean-payment run takes 31 to 33 s.
  • Frozen artifacts. The probe and adapter are checked against their SHA-256 hashes and opened read-only before the worker loads them.

What held up, and what didn’t

  • Routing paid all 76 clean invoices correctly. The base model paid 74, and the safety agent running on every decision paid 70.
  • The safety agent chose the right next action in 1,135 of 1,400 cases, against 836 for the base model, and proposed 11 premature payments to its 51.
  • Delayed memory poisoning is caught only weakly, at 0.609 AUROC.
  • Across 700 attacked cases the base model made one unauthorized payment and Tell made none. That is too few events to claim Tell reduces theft.

975 tests cover the agent, probe, gate, ledger and interface: 719 in pytest, 207 for the web server and 49 for the browser code.

Hiring for AI engineering?

I'm available from December 2026 and open to relocating. Email is the fastest way to reach me.