CoolFace
Apppublic

bunny-143/email-triage-env

sourceHugging Faceapache-2.0updated 6mo agoView on Hugging Face
0likes
App README

๐Ÿ“ง Email Triage Environment

OpenEnv | Real-world agentic email management environment for RL training and agent evaluation.

An agentic execution environment where an AI agent manages a realistic email inbox โ€” classifying messages, prioritizing batches by urgency, and drafting professional replies. Knowledge workers spend 2โ€“4 hours per day on email; this environment turns that into a concrete, measurable benchmark.

Why Email Triage?

CriterionThis Environment
Real-world taskโœ… Universal human task, measurable at scale
Partial progress signalโœ… Dense rewards at each tool call
Difficulty progressionโœ… Easy โ†’ Medium โ†’ Hard
Deterministic gradersโœ… Reproducible scoring across runs
Novel domainโœ… No prior OpenEnv email environment

Environment Overview

Action Space

Actions are MCP tool calls โ€” the agent calls tools by name with typed arguments:

ToolArgumentsPurpose
get_emailemail_id: strRead full email content
list_emails(none)List emails in current episode
classify_emailemail_id, categoryTask 1: submit classification
set_email_priorityemail_id, priority, labelsTask 2: triage + label email
submit_replyemail_id, reply_textTask 3: submit drafted reply
get_task_status(none)Check score and remaining steps

Observation Space

Each tool call returns a string response with:

  • โ€”Email content (body, subject, sender, timestamp)
  • โ€”Feedback on the last action
  • โ€”Running score
  • โ€”Episode completion signal

Reward Function

Rewards are dense โ€” the agent receives partial credit throughout each episode:

TaskReward Signal
classify_email1.0 correct, 0.3 related category, 0.0 wrong
triage_inboxSpearman rank correlation (priorities) + label F1, updated per email
draft_replyTone (30%) + Coverage (40%) + Length (20%) + Structure (10%)

Tasks

Task 1 โ€” classify_email (Easy)

  • โ€”Objective: Read a single email and classify it into one of 7 categories
  • โ€”Categories: urgent, spam, newsletter, support, meeting, security, general
  • โ€”Max steps: 6
  • โ€”Baseline score: ~0.40 (random = 0.14)

Task 2 โ€” triage_inbox (Medium)

  • โ€”Objective: Assign priority (1โ€“5) and category labels to all 5 emails in a batch
  • โ€”Grader: Weighted combination of Spearman rank correlation + label accuracy
  • โ€”Max steps: 15
  • โ€”Baseline score: ~0.35

Task 3 โ€” draft_reply (Hard)

  • โ€”Objective: Read an important email and draft a professional, complete reply
  • โ€”Grader: NLP heuristics on tone, keyword coverage, length, and structure
  • โ€”Max steps: 8
  • โ€”Baseline score: ~0.30

Setup

Quick Start (Local)

bash
# 1. Install dependencies
pip install openenv-core fastmcp uvicorn pydantic openai

# 2. Start server
uvicorn server.app:app --host 0.0.0.0 --port 8000

# 3. Test in another terminal
curl http://localhost:8000/health
curl -X POST http://localhost:8000/reset -H "Content-Type: application/json" -d "{}"

Docker

bash
docker build -t email-triage-env .
docker run -p 8000:8000 email-triage-env

Run Baseline Inference

bash
export HF_TOKEN=your_hf_token
export API_BASE_URL=https://router.huggingface.co/v1
export MODEL_NAME=Qwen/Qwen2.5-72B-Instruct
export EMAIL_ENV_URL=http://localhost:8000

python inference.py

Expected output format:

[START] task=classify_email env=email_triage_env model=Qwen/Qwen2.5-72B-Instruct
[STEP] step=1 action=get_task_status({}) reward=0.00 done=false error=null
[STEP] step=2 action=get_email({"email_id": "e001"}) reward=0.00 done=false error=null
[STEP] step=3 action=classify_email({"email_id": "e001", "category": "urgent"}) reward=1.00 done=true error=null
[END] success=true steps=3 score=1.000 rewards=0.00,0.00,1.00

Use as Python Client

python
from client import EmailTriageEnv

with EmailTriageEnv(base_url="http://localhost:8000").sync() as env:
    # Reset and get task briefing
    result = env.reset(task_name="classify_email")
    
    # Read an email
    content = env.call_tool("get_email", email_id="e001")
    print(content)
    
    # Classify it
    feedback = env.call_tool("classify_email", email_id="e001", category="urgent")
    print(feedback)

Project Structure

email_triage_env/
โ”œโ”€โ”€ openenv.yaml              # OpenEnv manifest
โ”œโ”€โ”€ pyproject.toml            # Python dependencies
โ”œโ”€โ”€ Dockerfile                # Container build
โ”œโ”€โ”€ README.md                 # This file
โ”œโ”€โ”€ models.py                 # Pydantic Action/Observation models
โ”œโ”€โ”€ client.py                 # EmailTriageEnv client
โ”œโ”€โ”€ inference.py              # Baseline inference script
โ””โ”€โ”€ server/
    โ”œโ”€โ”€ __init__.py
    โ”œโ”€โ”€ app.py                # FastAPI application
    โ”œโ”€โ”€ email_environment.py  # MCPEnvironment implementation
    โ”œโ”€โ”€ email_data.py         # Synthetic email dataset (seed=42)
    โ””โ”€โ”€ tasks.py              # Task definitions + graders

Baseline Scores

Model: Qwen/Qwen2.5-72B-Instruct via HuggingFace Router

TaskDifficultyBaseline Score
classify_emailEasy~0.40
triage_inboxMedium~0.35
draft_replyHard~0.30
Average~0.35

Scores are deterministic across runs given the same model and seed.


OpenEnv Spec Compliance

  • โ€”โœ… spec_version: 1 in openenv.yaml
  • โ€”โœ… reset() โ†’ fresh episode with task briefing
  • โ€”โœ… step() / step_async() โ†’ observation + reward + done
  • โ€”โœ… state property โ†’ episodeid + stepcount
  • โ€”โœ… Typed Pydantic Action and Observation models
  • โ€”โœ… MCP tool interface (FastMCP + MCPEnvironment)
  • โ€”โœ… create_app() factory for HTTP/WebSocket server
  • โ€”โœ… Dockerfile builds and runs cleanly
  • โ€”โœ… openenv validate passes

Environment Variables

VariableDefaultDescription
HF_TOKEN(required)Hugging Face / API key
API_BASE_URLhttps://router.huggingface.co/v1LLM endpoint
MODEL_NAMEQwen/Qwen2.5-72B-InstructModel identifier
EMAIL_ENV_URLhttp://localhost:8000Environment server URL
ENABLE_WEB_INTERFACEtrueEnable built-in web UI

License

Apache 2.0