Mayanak/metaHFprojectGagannMayank
๐ง Email Triage OpenEnv
A real-world email support triage environment for training and evaluating AI agents.
This OpenEnv-compatible environment simulates a customer support inbox. Agents must classify, prioritise, reply to, escalate, or archive support emails across three tasks of increasing difficulty.
This is a genuine real-world task โ every company with a customer support function deals with email triage. Getting it right matters: missed security incidents can cost millions, while spam flooding agents' time reduces productivity.
๐ฏ Environment Overview
๐ฌ Tasks
Task 1: classify_only โ Easy
- Inbox: 5 emails
- Max Steps: 10
- Objective: Classify each email with the correct category and priority.
- What's tested: Basic text understanding, priority reasoning, spam detection.
- Expected baseline score: 0.55โ0.75
Task 2: triage_and_reply โ Medium
- Inbox: 8 emails
- Max Steps: 20
- Objective: Classify + draft professional replies. Escalate where required. Archive spam.
- What's tested: Reply quality, escalation judgment, multi-step planning.
- Expected baseline score: 0.40โ0.65
Task 3: crisis_response โ Hard
- Inbox: 12 emails
- Max Steps: 30
- Objective: Handle a critical inbox with security incidents, SLA violations, outages, GDPR requests, and billing disputes. Every wrong decision is costly.
- What's tested: Priority under pressure, nuanced escalation, compliance awareness, handling adversarial/ambiguous emails.
- Expected baseline score: 0.30โ0.55
๐ง Action Space
class EmailTriageAction(BaseModel):
action_type: ActionType # classify | draft_reply | escalate | archive | request_info
email_id: str # ID of the email being acted on
category: Optional[Category] # billing | technical | security | general_inquiry |
# spam | outage | feature_request | compliance
priority: Optional[Priority] # critical | high | medium | low
reply_text: Optional[str] # For draft_reply and request_info
escalation_reason: Optional[str]
reasoning: Optional[str] # Agent's chain-of-thought (not graded, used for debugging)๐๏ธ Observation Space
class EmailTriageObservation(BaseModel):
current_email: Optional[Email] # The email to process
inbox_remaining: int # How many emails are left
step_feedback: str # Human-readable feedback from last action
last_action_valid: bool
last_action_error: Optional[str]
episode_done: bool
task_name: strThe Email object contains: email_id, sender, subject, body, received_at, attachments, thread_history.
๐ Reward Function
Rewards are non-sparse โ the agent receives signal on every step.
Reply quality is measured by keyword coverage (domain-specific terms expected in good replies) + length bonus + professionalism bonus.
Final episode score = grade_episode(processed_records) โ normalized 0.0โ1.0.
๐ Quick Start
Docker
docker build -t email-triage-env .
docker run -p 7860:7860 email-triage-envThen test:
curl http://localhost:7860/health
curl -X POST http://localhost:7860/reset -H "Content-Type: application/json" \
-d '{"task_name": "classify_only"}'Local (Python)
pip install -r requirements.txt
uvicorn server.app:app --host 0.0.0.0 --port 7860Python Client
from client import EmailTriageEnv
from models import EmailTriageAction, ActionType, Category, Priority
with EmailTriageEnv(base_url="http://localhost:7860").sync() as env:
result = env.reset(task_name="triage_and_reply")
email = result.observation.current_email
action = EmailTriageAction(
action_type=ActionType.DRAFT_REPLY,
email_id=email.email_id,
category=Category.BILLING,
priority=Priority.HIGH,
reply_text="Dear Alice, We've identified the duplicate charge and will process a refund within 3-5 business days. We apologize for the inconvenience. โ Support Team",
)
result = env.step(action)
print(f"Reward: {result.reward:.2f} | Feedback: {result.observation.step_feedback}")๐ค Baseline Inference Script
# Set environment variables
export API_BASE_URL="https://router.huggingface.co/v1"
export MODEL_NAME="Qwen/Qwen2.5-72B-Instruct"
export HF_TOKEN="your_token_here"
export EMAIL_TRIAGE_URL="http://localhost:7860"
# Run all three tasks
python inference.pyExpected output:
[START] task=classify_only env=email_triage_env model=Qwen/Qwen2.5-72B-Instruct
[STEP] step=1 action=classify(email=email_001, cat=billing, pri=high) reward=0.70 done=false error=null
[STEP] step=2 action=classify(email=email_002, cat=technical, pri=critical) reward=0.70 done=false error=null
...
[END] success=true steps=5 score=0.612 rewards=0.70,0.70,0.40,0.70,0.80
[START] task=triage_and_reply env=email_triage_env model=Qwen/Qwen2.5-72B-Instruct
...
[END] success=true steps=14 score=0.521 rewards=...
[START] task=crisis_response env=email_triage_env model=Qwen/Qwen2.5-72B-Instruct
...
[END] success=true steps=22 score=0.443 rewards=...๐งช Tests
pip install pytest pytest-asyncio
pytest test_environment.py -v๐ Project Structure
email_triage_env/
โโโ __init__.py # Public API exports
โโโ models.py # Pydantic models (Action, Observation, State, StepResult)
โโโ client.py # Async + sync Python client
โโโ inference.py # Baseline inference script (OpenAI client)
โโโ test_environment.py # Unit + integration tests
โโโ openenv.yaml # OpenEnv spec manifest
โโโ requirements.txt
โโโ pyproject.toml
โโโ Dockerfile
โโโ README.md # This file
โโโ server/
โโโ __init__.py
โโโ app.py # FastAPI server (HTTP + WebSocket)
โโโ environment.py # Core logic: tasks, graders, reward functions๐ API Endpoints
๐๏ธ Design Decisions
- Real-world utility: Email triage is a universal business problem. Agents trained here transfer to production support tools.
- Non-sparse rewards: Every action gets a meaningful reward signal, making RL feasible.
- Partial credit: Wrong-but-close classifications (billing vs compliance) get partial reward โ more realistic than binary scoring.
- Severity-aware penalties: Archiving a critical security email costs
-0.5, teaching agents that stakes matter. - Reply quality via keywords: Rather than LLM-judged quality (expensive), we use domain keyword coverage as a proxy that remains deterministic and reproducible.
- Escalation as a first-class action: Forces the agent to reason about human-in-the-loop handoffs โ critical for real production deployments.
๐ Baseline Scores (Qwen2.5-72B)
๐ License
MIT License. Built for the OpenEnv Hackathon by Meta & Hugging Face.
