title: Email Triage OpenEnv
emoji: π§
colorFrom: blue
colorTo: indigo
sdk: docker
app_port: 7860
pinned: false
short_description: OpenEnv email triage benchmark β GRPO fine-tuned agent
tags:
- openenv
- agents
- evaluation
- email-triage
π§ Multi-Agent Email Triage Environment
A real-world RL environment that trains LLMs to intelligently triage a corporate inbox β classifying, routing, prioritizing, and drafting replies for incoming emails using GRPO reinforcement learning.
π Deliverables
| Item | Link |
|---|---|
| π€ HF Space | (this repo) |
| π Training Notebook | Open in Kaggle |
| π Blog / Writeup | BLOG.md in this repo |
| π wandb Training Run | Live metrics |
π§ What Was Trained
A Qwen/Qwen2.5-3B-Instruct model fine-tuned with GRPO (Group Relative Policy Optimization) via HuggingFace TRL.
- Base model:
Qwen/Qwen2.5-3B-Instruct - Method: GRPO with LoRA (r=4, alpha=8, target: q_proj + v_proj)
- Training steps: 200
- Reward signal: Environment reward (priority + category + routing + reply quality + SLA compliance)
π Training Results
Reward Curve
Red line = 10-step rolling average. Agent improves from 3.47 β 4.10+ over 200 GRPO steps.
Before vs After
Key Numbers
| Metric | Baseline (untrained) | After GRPO (200 steps) |
|---|---|---|
| Avg reward | 3.47 | 4.10+ |
| Best episode reward | 3.65 | 4.41 |
| Worst episode reward | 2.78 | 3.60 |
| Final evaluation score | β | 4.189 / 5.0 |
| Correct routing | ~40% | 100% (5/5) |
| Null reply drafts | frequent | eliminated |
| Invalid categories | occasional | eliminated |
| Escalation budget abuse | frequent | eliminated |
Before vs After Routing (Final Evaluation)
| Untrained | Trained | Per-email Reward | |
|---|---|---|---|
| URGENT: My account has been hacked! | general_inquiry β support_tier1 | customer_complaint β support_tier2 β | 0.705 |
| Congratulations! You've WON $1,000,000! | urgent β support_tier1 | spam_phishing β trash β | 0.840 |
| Team lunch this Friday | low β trash | internal_hr β hr β | 0.988 |
| Invoice #INV-2024-0042 - Payment Overdue | medium β support_tier1 | billing_inquiry β billing β | 0.798 |
| Interested in your Enterprise plan | general_inquiry β archive | sales_lead β sales β | 0.858 |
| Total | 4.189 / ~5.0 |
π― Problem Statement
Every company receives hundreds of emails daily. Manually reading, classifying, and routing each one is time-consuming and error-prone. This environment trains an LLM agent to handle this automatically.
This falls under Theme #3.2 β Personalized Tasks (World Modeling).
π Environment Interface
The environment follows the OpenEnv-style interface:
reset()β starts a fresh episodestep(action)β applies action, returns next observation + rewardstate()β returns current internal state
Observation Space
| Field | Description |
|---|---|
current_email |
Email to triage (header + body) |
inbox |
Full list of emails in episode |
processed |
IDs of already handled emails |
escalation_budget_remaining |
Remaining flag_review capacity |
team_queue_remaining |
Capacity per routing destination |
active_sla_warnings |
Emails close to SLA deadline |
sla_breaches_so_far |
Number of SLA breaches triggered |
Action Space
| Field | Valid Values |
|---|---|
email_id |
Copy exactly from current_email |
priority |
urgent | high | medium | low | spam |
category |
customer_complaint | billing_inquiry | technical_support | sales_lead | internal_hr | legal_compliance | spam_phishing | general_inquiry |
route_to |
support_tier1 | support_tier2 | billing | sales | legal | hr | management | trash | archive |
summary |
β€280 chars |
flag_review |
true or false (uses escalation budget) |
reply_draft |
Professional reply to sender |
Tasks
| Task | Emails | Difficulty | Expected Score |
|---|---|---|---|
| easy | 5 | Easy | 0.75β0.99 |
| medium | 8 | Medium | 0.55β0.80 |
| hard | 12 | Hard | 0.35β0.65 |
Reward Design
Per-email scoring:
- β Correct priority β ~0.2 pts
- β Correct category β ~0.2 pts
- β Correct routing β ~0.3 pts
- β Reply draft quality β ~0.2 pts (20% of score)
- β Appropriate escalation
- β Penalty for SLA breaches
- β Penalty for invalid field values
ποΈ Training
MODEL_NAME = "Qwen/Qwen2.5-3B-Instruct"
TRAINING_STEPS = 200
BATCH_SIZE = 1
NUM_GENERATIONS = 4
learning_rate = 2e-6
lora_r = 4
To run training:
pip install trl transformers datasets peft accelerate bitsandbytes wandb
# Then open the Colab notebook linked above
π Inference
import requests
BASE_URL = "https://Vansh04092003-multi-agent-email-env2.hf.space"
# Start episode
obs = requests.post(f"{BASE_URL}/reset").json()["observation"]
# Take action
action = {
"email_id": "e001",
"priority": "urgent",
"category": "customer_complaint",
"route_to": "support_tier2",
"summary": "Account hacked, needs immediate lock.",
"flag_review": True,
"reply_draft": "We are securing your account immediately."
}
result = requests.post(f"{BASE_URL}/step", json=action).json()
print(f"Reward: {result['reward']}")
π Repository Structure
βββ README.md
βββ BLOG.md
βββ openenv.yaml
βββ training/
β βββ notebook_training.ipynb
β βββ train_grpo.py
β βββ plots/
β βββ reward_curve.png
β βββ before_after.png
βββ src/
βββ openenv_email_triage/
βββ environment.py
βββ models.py
π³ Local Run
export HF_TOKEN=your_token_here
uv run server
Docker
docker build -t email-triage-env .
docker run -p 7860:7860 -e HF_TOKEN=$HF_TOKEN email-triage-env
Validate
openenv validate

