YAML Metadata Warning:empty or missing yaml metadata in repo card
Check out the documentation for more information.
- Enterprise AP-Env: Turning fraud into foresight
- Try It Right Now
- The Problem We Are Solving
- Features:
- What the Environment Forces the Agent to Do
- The Reward Architecture: Why This Environment Actually Teaches
- The 5 Levels of Enterprise Complexity
- Proving the Gym Works: GRPO Reinforcement Learning
- Full Tech Stack:
- Technical Architecture
- API Reference
- Quick Start
- Try It Right Now
Enterprise AP-Env: Turning fraud into foresight
Meta AI Hackathon Grand Finale 2026 Β· Team SHIPWithTEA β Prachi & Dharmendra
Problem: Business Email Compromise layered on top of duplicate invoicing layered on top of lookalike domain fraud β costs enterprises $2.9 billion every year. And yet, until now, there has been no standardised environment to test whether an AI agent would have caught it.
We built that environment. Then we trained an LLM inside it and watched it learn.
For judges: nothing in this demo is scripted or static. Every episode generates a new vendor, new invoice, new prices, new fraud IBAN (using OS-level entropy via Python's
secretsmodule) β the agent cannot memorise answers, it must reason live. When you open the Gradio demo, you can plug in any HuggingFace-compatible model (Llama, Mistral, Qwen, your own fine-tuned checkpoint) and watch it play a real episode autonomously. If no token is provided, a clearly-labelled Rule-Based Reference Agent runs instead so you can observe the environment without an API key β the UI badge makes this explicit.
Try It Right Now
| Resource | Link |
|---|---|
| Live Demo (HuggingFace Space) | spaces/decent-cow26/invoice-env |
| (Multi-App-RL-Env-Invoice-Processing-Schema-Drift-Fraud-Detection-Vendor-Negotiation) | |
| GRPO Training Notebook (Colab T4) | colab_rl_training.ipynb β full RL loop in ~35 min |
| GitHub Source | (https://github.com/dharmendra26-wiz/Enterprise-AP-Environment) |
The Problem We Are Solving
The AI industry is racing to deploy LLMs into enterprise Accounts Payable departments. Automate the invoice. Cut headcount. Process payments faster.
But there is a question nobody is asking before they flip the switch: what happens when the invoice is fake?
MMLU tests trivia. SWE-bench tests code. Neither tests whether an LLM will rubber-stamp a $84,000 payment to a fraudster. There is no standard environment, no shared benchmark, no reproducible test harness for enterprise financial agent safety.
Enterprise AP-Env is that benchmark. A procedurally generated, OpenEnv-compliant, multi-application simulation that forces AI agents through the exact failure modes that cost enterprises $2.9 billion a year.
Features:
Backend & API
- UUID-based session isolation β every
/resetcall generates a freshuuid4session ID; no two agents ever share state - 300-second TTL eviction β idle sessions are automatically garbage-collected via monotonic clock, preventing memory leaks from abandoned episodes
- Thread-safe parallel sessions β multiple LLMs or users can run simultaneous episodes against the same server with zero state collision
- FastAPI + Uvicorn β production-grade ASGI backend with auto-generated OpenAPI docs at
/docs - OpenAI-compatible REST interface β any LLM client that speaks
/v1/chat/completionscan drive the environment without custom integration
Environment & Task Engine
- OpenEnv-compliant state machine β inherits
openenv-corebase class, exposing standardreset()/step()/stateGym-style API - 5-vendor procedural pool β vendor names, domains, fraud domains, IBANs, and item catalogues rotate across 5 distinct companies every episode (5 for now only)
- Randomised line items β item quantities, unit prices, subtotals, tax rates (8%, 10%, 12%, 15%), and invoice dates are all independently randomised
- Cryptographic fraud IBANs β fraudulent bank accounts generated with Python's
secretsmodule (OS-level entropy), impossible to pre-compute or memorise - lookalike domains β fraud domains use visually identical Unicode substitutions:
techsuppIies.com,0fficemart.ltd,g1obaltech.com,vertx.com,c1oudserve.io - Hard ERP floor in reward β if the agent never queries the ERP, max possible score is capped at 0.10 regardless of email extraction quality, enforced in
grade_task() - 30-step hard termination β fixed step budget per episode; environment force-closes at step 30 to prevent infinite loops
- Schema drift injection β on the
hardtask,vendor_nameis silently deprecated mid-session; agent must read the API error and switch tovendor_tax_id - Simulated vendor email injection β on
expert_negotiation, a corrected invoice is injected directly into the inbox after the agent sends a negotiation email - Duplicate invoice detection β the
hardtask embeds a duplicate invoice number that must be flagged before approval - Multi-turn negotiation state tracking β
self.negotiatedflag tracked separately so the reward function grades negotiation as a distinct behaviour
Reward System
- Granular step-level shaping β
+0.05read email,+0.10ERP query,+0.07per correct field extracted,+0.12flag match/duplicate,+0.20send negotiation email - 3-axis final rubric β Extraction Accuracy 40%, Workflow Flags 30%, Final Decision 30%
- Non-binary scoring β no 0/1 reward; every correct action earns a signal, making the gradient informative for RL training
- Decision penalty β approving a fraudulent invoice or rejecting a legitimate one scores 0.0 on the decision axis (30% of the episode score)
Training & Curriculum
- Adaptive curriculum in
train.pyβ 5-episode rolling average auto-promotes agent to harder tasks at >88% and demotes at <50% - Direct env mode (no HTTP) β
train.pyruns the environment in-process without a server, cutting episode latency to near zero - HTTP mode for LLM benchmarking β
inference.pydrives the live FastAPI server over HTTP using any HuggingFace Router model - Sliding context window β
inference.pykeeps only the last 16 messages (messages[:2] + messages[-16:]) to prevent LLM context overflow on long episodes - Exponential backoff retry β LLM API calls retry up to 4 times with doubling wait (15s β 30s β 60s β 120s) on 429/500/502/503/504 errors
- GRPO RL training on Colab T4 β full reinforcement learning loop runs in ~35 minutes on a free T4 GPU using Unsloth 4-bit + TRL GRPOTrainer
- LoRA fine-tuning β rank-16 LoRA adapters update only 1β2% of model parameters, keeping peak GPU memory under 12 GB
Demo & UI
- Dual-mode Gradio UI β no token = Rule-Based Reference Agent (green badge); token provided = real LLM Agent with your model name (blue badge)
- Any HuggingFace model supported β plug in Llama, Mistral, Qwen, Falcon, or your own fine-tuned checkpoint via
MODEL_NAMEenv variable - Live step-by-step visualisation β Gradio dashboard streams each action, observation, and reward in real time as the agent plays the episode
- HuggingFace Spaces deployed β environment is live and publicly accessible without any local setup
What the Environment Forces the Agent to Do
The agent starts every episode with one thing: an email inbox. What happens next depends entirely on what actions it chooses.
Feature 1 β Multi-App Workflow (The Core Loop)
The agent cannot complete any task by reading a single source of truth. It must synthesize information across two separate simulated applications:
- Email Inbox β unstructured natural language. The invoice arrives as a realistic email body with line items, prices, tax amounts, an IBAN bank account, and a vendor name embedded in prose.
- ERP Database β a structured REST API (think SAP or Oracle). The agent must query it with the correct schema to fetch the matching Purchase Order and cross-reference every field.
The multi-app floor is enforced in the reward function: if the agent never queries the ERP, its maximum possible episode score is capped at 0.10, regardless of how perfectly it reads the email. This is hardcoded into grade_task() in app/tasks.py and cannot be gamed. It forces genuine cross-system reasoning every single episode.
Feature 2 β Schema Drift (The Hard Task)
On the hard task, the ERP API silently upgrades mid-session. The agent's first query β using vendor_name as the lookup key β returns:
SCHEMA DRIFT: API v2 requires vendor_tax_id. vendor_name is deprecated.
The agent must parse this error, infer the new schema from the message, and retry the query with vendor_tax_id. No hints. No retry logic built in. On top of this, the hard task also requires the agent to detect a duplicate invoice number by running match_duplicate, and flag a tax rate inflation from the correct 8-12% to a fraudulent 15%.
This is exactly how real enterprise ERP systems behave during upgrades. Any agent that cannot adapt produces a false approved and lets the payment through.
Feature 3 β Expert Fraud Detection (The Ultimate Test)
The expert_fraud task injects two independent attack vectors that must both be caught for full score:
Attack 1 β Lookalike Email Domain: Each of the 5 vendors has a hand-crafted fraud domain baked into app/tasks.py:
| Legitimate Domain | Fraud Domain | Attack Technique |
|---|---|---|
techsupplies.com |
techsuppIies.com |
Capital-I substituting lowercase-L |
officemart.ltd |
0fficemart.ltd |
Zero substituting letter-O |
globaltech.com |
g1obaltech.com |
Numeral-1 substituting letter-L |
vertex.com |
vertx.com |
Silent letter drop |
cloudserve.io |
c1oudserve.io |
Numeral-1 substituting letter-L |
Attack 2 β Fraudulent IBAN: The invoice contains a bank account number that does not match the ERP vendor profile. This IBAN is generated fresh every episode using Python's secrets module (OS-level entropy) β it cannot be predicted by seeding any random number generator. The agent must catch the mismatch by comparing the invoice IBAN against the ERP's registered iban field.
The fraud email also creates urgency with a suspiciously short 10-day due date (vs. standard 15β45 days) β a social engineering signal a trained agent should flag.
The agent must raise both fraud (domain mismatch) and fraud_iban (IBAN mismatch) flags to earn full score. Catching only one is partial credit.
Feature 4 β Multi-Turn Vendor Negotiation
The expert_negotiation task tests something no standard benchmark does: can an AI agent close a real business loop autonomously?
The invoice arrives inflated by 10β25% β the vendor forgot to apply a pre-agreed partnership discount. The ERP shows the correct approved amount. The agent must:
- Detect the discrepancy (invoice total β ERP
approved_amount) - Compose and send a
send_emailaction to the vendor's sales address - The environment's
simulated_responsesengine triggers: it detects thesend_emailtargeting the correct vendor email and dynamically injects a corrected invoice (email_005) directly into the inbox - Read the corrected email β which contains the vendor's apology and revised line items with the discount applied
- Re-extract all 8 fields from the corrected invoice
- Approve β only the corrected amounts are the ground truth; the original was wrong
Feature 5 β Adaptive Curriculum Training
The training loop in train.py implements an Adaptive Self-Improving Curriculum that tracks a rolling 5-episode average per task:
- Score > 88% β automatically promoted to the next difficulty tier
- Score < 50% β demoted to rebuild competence
This ensures the agent's compute budget is spent exactly at the frontier of its current ability β not replaying tasks it has already mastered.
Feature 6 β Procedural Generation (No Memorization Possible)
Every call to reset() generates a completely fresh episode. The generator randomly selects from:
- 5 vendors with unique domains, fraud domains, tax IDs, IBAN numbers, and product catalogues
- Tax rates: 8%, 10%, 12%, or 15%
- Invoice dates: random across a 700-day window (2024β2026)
- Due dates: 10, 15, 30, or 45 days from invoice date
- Line items: 2β3 items randomly sampled from each vendor's catalogue, with quantities and prices randomized within per-item ranges
- Fraud IBANs: generated with
secrets.choice()(OS entropy) β unseeded and unpredictable per episode
An agent cannot memorize answers. It must reason every time.
The Reward Architecture: Why This Environment Actually Teaches
Most environments use binary scoring: win = 1, lose = 0. Binary rewards create sparse gradients β sparse gradients mean slow learning. We used OpenEnv's Rubric system to build a dense, step-level reward function:
| Action | Reward | Why |
|---|---|---|
read_email β correct email found |
+0.05 | Rewarded for navigating the inbox correctly |
query_erp β vendor located in ERP |
+0.10 | Cross-system lookup completed |
extract β field value matches ground truth |
+0.07 | Accurate extraction from unstructured text |
flag β correct anomaly flagged |
+0.12 | Agent identified a genuine issue |
send_email β vendor negotiation triggered |
+0.20 | Multi-turn resolution loop initiated |
match_duplicate β duplicate invoice confirmed |
+0.12 | Resubmitted invoice caught |
| Incorrect action / wrong state | β0.01 to β0.05 | Penalty proportional to severity |
| ERP never queried (any task) | Hard floor: 0.10 | Multi-app requirement enforced unconditionally |
The final episode score is a weighted rubric across three components:
- 40% β Field extraction accuracy (8 fields:
vendor_name,invoice_number,invoice_date,due_date,subtotal,tax_amount,total_amount,iban) - 30% β Workflow compliance (correct flags raised, negotiation completed, or correct clean-invoice handling)
- 30% β Final decision accuracy (
approvevs.rejectβ must matchexpected_decisionin the task spec)
A model that extracts data perfectly but makes the wrong final decision scores ~0.40. A model that makes the right decision without querying the ERP scores 0.10. The reward function is not gameable by exploiting any single component.
The 5 Levels of Enterprise Complexity
| Level | Task | Key Challenge |
|---|---|---|
| 1 | Easy | Read email β Query ERP β Extract 8 fields β Approve |
| 2 | Medium | Detect a 12β30% price discrepancy vs. the signed PO, flag and reject |
| 3 | Hard | ERP API silently upgrades: vendor_name deprecated, vendor_tax_id required. Also detect duplicate invoice + tax mismatch. |
| 4 | Expert Negotiation | Invoice is inflated. Email the vendor, receive corrected invoice dynamically injected into inbox, re-extract all 8 fields, approve. |
| 5 | Expert Fraud | Sender is a lookalike domain. IBAN is cryptographically random and doesn't match ERP. Flag both fraud + fraud_iban, reject. |
Each level introduces a failure mode that breaks standard automation. The hardest tasks require the agent to reason across multiple turns, multiple data sources, and multiple adversarial signals simultaneously.
Proving the Gym Works: GRPO Reinforcement Learning
To validate that the environment produces a learnable gradient signal, we ran GRPO (Group Relative Policy Optimization) using Unsloth + TRL on a free Google Colab T4 GPU. Full loop in under 35 minutes.
Training configuration:
| Parameter | Value |
|---|---|
| Base model | unsloth/llama-3-8b-Instruct-bnb-4bit |
| Quantization | 4-bit NF4 (Unsloth) β ~5 GB VRAM |
| Fine-tuning method | LoRA (r=16, Ξ±=32) β ~1% of parameters trainable |
| RL algorithm | GRPO (GRPOTrainer from TRL) |
| Group size | 4 candidate responses per prompt |
| Training steps | 100 |
| Dataset size | 125 synthetic AP workflow state prompts |
| Reward function | AP environment rubric distilled from grade_task() |
| Hardware | Google Colab T4 GPU (free tier) |
| Runtime | ~35 minutes end-to-end |
Why GRPO over PPO? PPO requires a separate value-head and reference model, which doubles VRAM usage and OOMs on a free T4. GRPO computes advantage by comparing the model's own outputs within a group β no extra model needed.
Why Unsloth? Unsloth's custom CUDA kernels and 4-bit quantization reduce the 8B model from 16 GB β ~5 GB, leaving headroom for LoRA gradients.
What Happened During Training
Left panel: Training loss drops from ~0.0025 to a final of 0.001 β the model is consistently improving. Right panel: Average reward per step climbs from below 0.2 and stabilises around 0.48β0.65, approaching the 0.70 target threshold (dashed line). The smoothed green trend confirms a genuine upward learning signal β not noise.
Before vs. After GRPO β The Result
Easy Task: 0.26 β 0.88 (+0.62). Expert Negotiation: 0.18 β 0.78 (+0.60). Both tasks now exceed the 0.70 pass threshold. Peak reward nearly tripled on Easy. The model learned when to approve a clean invoice instead of hallucinating flags.
| Task | Before Training | After GRPO | Improvement |
|---|---|---|---|
| Easy | 0.26 | 0.88 | +0.62 (+238%) |
| Expert Negotiation | 0.18 | 0.78 | +0.60 (+333%) |
The reward curve goes up. The loss curve goes down. The gym works. The signal is real.
Full Tech Stack:
| Tool | Role | Why We Chose It |
|---|---|---|
OpenEnv (openenv-core) |
Gym base class + openenv.yaml spec |
Standard interface β any agent can plug in instantly via Gym-style API |
| FastAPI | REST simulation server (app/main.py) |
High-performance, async-ready, auto-generates /docs for judges |
| Pydantic v2 | Action & observation schema validation (app/models.py) |
Strict type enforcement on every agent action at runtime |
| Gradio | Live visual dashboard (app/demo.py) |
Judges can watch the agent play episodes in real-time on HF Spaces |
| Uvicorn | ASGI server | Production-grade concurrency for multi-agent training |
Any HF model (we used Llama-3.1-8B-Instruct) |
LLM agent via HF Router API | The environment is model-agnostic β plug in any HuggingFace-compatible LLM or your own fine-tuned model |
| Unsloth | 4-bit quantized model loading + CUDA kernels | 8B model VRAM: 16 GB β 5 GB; enables free T4 training |
| TRL (GRPOTrainer) | RL training loop | No reference model needed β GRPO fits in a single T4 |
LoRA (via peft) |
Efficient fine-tuning adapters | ~1% of parameters trained β full model quality at fraction of compute |
| HuggingFace Hub | Model hosting + Space deployment | Free GPU hosting for the live demo |
| HuggingFace Router API | LLM inference for inference.py |
Provider-agnostic β swap models without changing code |
| Matplotlib | All result charts | Generated directly from real run JSON files |
Python secrets module |
Fraud IBAN generation | OS-level entropy β fraud IBANs are truly unpredictable per episode |
| Google Colab T4 | Training hardware | Anyone can reproduce our results for free |
Technical Architecture
enterprise-ap-env/
βββ app/
β βββ main.py # FastAPI server β UUID sessions, TTL eviction, thread-safe
β βββ environment.py # OpenEnv state machine β reset() / step() / state
β βββ tasks.py # 5 procedural task generators + grade_task() rubric
β βββ models.py # Pydantic schemas: Action, Observation, StepResult
β βββ demo.py # Gradio live dashboard β rule-based + LLM agent modes
βββ train.py # Adaptive curriculum training loop (reference agent)
βββ inference.py # Headless LLM agent β HF Router API, any model
βββ plot_llm_results.py # Reward curve visualization from JSON results
βββ colab_rl_training.ipynb # Unsloth GRPO training notebook (T4-optimized)
βββ eval_after_training.py # Before/after evaluation script (Colab-compatible)
βββ openenv.yaml # OpenEnv environment specification
βββ Dockerfile # HuggingFace Spaces deployment
FastAPI Backend β Thread-Safe Multi-Agent Server
- UUID-based session management β every episode gets a unique isolated session
- Idle-timeout garbage collection β sessions auto-expire, preventing memory leaks during multi-agent training
- Thread-safe state isolation β multiple LLMs can train simultaneously on the same server without state collisions
- OpenAI-compatible REST interface β
/reset,/step,/state,/health,/docs - Fully decoupled architecture β the FastAPI server, headless benchmarking script (
inference.py), and Gradio dashboard can each run independently
Any agent framework β LangChain, AutoGPT, raw requests.post() β can plug in.
Gradio Dashboard β
app/demo.py is not just a demo. It is an observability tool. Watch live: inbox loads, email opens, ERP response appears, fields extract one by one, a flag raises, final decision renders.
The dashboard has two agent modes β it switches automatically based on whether you provide an HF token:
| Mode | How to activate | Who runs the episode |
|---|---|---|
| Scripted Agent (default) | Open the Space β no token needed | A deterministic rule-based agent plays the episode automatically. Always works, no API calls. |
| Autonomous LLM Agent | Paste your HuggingFace token in the sidebar and set the model name, then click Run | Any HuggingFace-compatible LLM drives the episode live via the Router API β Llama, Mistral, Qwen, your own fine-tuned model, anything. Every action is generated by the model in real time. |
No token β scripted reference agent plays. Token + model name provided β your chosen LLM takes over. The environment, reward function, and observation format are identical in both modes β the only difference is who is making the decisions.
This means any researcher can plug in their own trained model and immediately benchmark it against the same 5 tasks, the same reward rubric, and the same adversarial conditions β without writing a single line of integration code.
OpenEnv β The Standard Interface
The environment inherits from openenv-core's Environment base class and exposes the standard reset(), step(), state API. The openenv.yaml specification declares all 5 tasks, their action/observation spaces, and the full reward rubric β researchers can understand the environment without reading source code.
API Reference
| Endpoint | Method | Description |
|---|---|---|
/reset?task_name=easy |
POST | Start a new episode β returns unique session_id |
/step?session_id=<uuid> |
POST | Take one action |
/state?session_id=<uuid> |
GET | Inspect live state of active session |
/sessions |
GET | List all active sessions |
/tasks |
GET | List all available tasks |
/health |
GET | Health check |
/docs |
GET | Interactive Swagger UI |
Quick Start
pip install -r requirements.txt
# Start the environment server
python -m uvicorn app.main:app --host 0.0.0.0 --port 7860
# Run the Gradio live demo (no server needed)
python app/demo.py
# Run adaptive curriculum training
python train.py --episodes 60
# Benchmark any LLM (set HF_TOKEN first)
export HF_TOKEN="hf_your_token_here"
python inference.py --all --episodes 5
# Plot reward curves
python plot_llm_results.py
GRPO Training on Colab: Open colab_rl_training.ipynb β Runtime β T4 GPU β Run All. Completes in ~35 minutes.
We open-sourced everything.
Enterprise is production-grade infrastructure for a $2.9 billion real-world problem.
Built at the Meta AI OpenEnv Hackathon Grand Finale, April 2026. Team SHIPWithTEA: Prachi & Dharmendra
Stack: OpenEnv Β· FastAPI Β· Pydantic Β· Gradio Β· Uvicorn Β· Unsloth Β· TRL (GRPO) Β· LoRA Β· HuggingFace Hub Β· Llama-3.1-8B-Instruct Β· Matplotlib Β· Python secrets Β· Google Colab T4

