A customisable email agent built with LangGraph that automates triage, response drafting, and human-in-the-loop review. Includes a built-in web frontend for testing and reviewing email drafts locally.
- Email Triage: Automatically classifies emails as
respond,notify, orignore - Response Drafting: Uses LLMs to draft contextual email responses
- Safe by default: The agent never sends emails without human approval. All drafts are paused for review via the web UI, CLI, or LangGraph Studio. Auto-send requires explicitly enabling
WORKER_AUTO_ACCEPT_INTERRUPTS=true(testing only) - Web UI: Built-in dashboard for reviewing and approving email drafts
- Memory System: Learns user preferences over time
- Gmail Integration: Full Gmail API support for reading and sending emails
- RAG Support: Optional knowledge base search for informed responses
- PDF Processing: Extracts and summarizes PDF attachments
Originally developed with Renbee to automate DNO (distribution network operator) communications for heat pump installers, this repo is the generalised, open-source version of that work. Unlike simple filters, pure RAG, or Gmail's built-in AI, AgentMantis handles multi-step workflows — asking clarifying questions, learning preferences over time, and requiring human approval before taking action.
Design choices: Azure OpenAI for data residency; FlagEmbedding/BAAI for local embeddings (no PII sent to external APIs).
Customisation points: swap the RAG knowledge base, PDF extraction rules, or prompts (email_agent/agent/prompts.py) to adapt to your domain.
email_agent/
├── agent_api/ # FastAPI server + background worker
│ ├── server.py # REST API endpoints
│ ├── web_routes.py # Web UI routes
│ ├── worker.py # LangGraph worker (polls Gmail, processes emails)
│ ├── storage.py # PostgreSQL persistence
│ ├── schemas.py # Pydantic models
│ └── templates/ # Jinja2 templates for web UI
│
├── agent/ # LangGraph email assistant
│ ├── graph.py # Main workflow definition
│ ├── prompts.py # LLM prompts and instructions
│ ├── schemas.py # State and message types
│ ├── configuration.py # Mode configuration
│ ├── utils.py # Parsing, formatting utilities
│ ├── eval/ # Evaluation framework
│ └── tools/ # LangGraph tools
│ ├── default/ # Basic email/calendar tools
│ ├── gmail/ # Gmail API integration
│ └── rag/ # Document retrieval
│
└── config/ # YAML configuration files
- Python 3.11+
- PostgreSQL 16+
- Gmail OAuth credentials (for Gmail integration)
# Clone the repository
git clone https://github.com/simonwisdom/nesta-email-agent-framework.git
cd nesta-email-agent-framework
# Install dependencies with uv
uv sync
# Install dev dependencies (linting, tests, pre-commit)
uv sync --group dev
# Copy and configure environment variables
cp .env.example .env
# Edit .env with your settings
# Install pre-commit hooks
uv run pre-commit install --install-hooks# Start Postgres (or use docker compose below)
# Example: docker run --name email-agent-postgres -p 5432:5432 -e POSTGRES_USER=email_user -e POSTGRES_PASSWORD=email_password -e POSTGRES_DB=email_agent -d postgres:16-alpine
# Start the API server
uv run uvicorn email_agent.agent_api.server:app --reload
# In another terminal, start the worker
uv run python -m email_agent.agent_api.worker# Ensure .env exists at repo root
cp .env.example .env
cd docker
docker compose up -dCopy .env.example to .env and configure your settings. Key variables:
DATABASE_URL- PostgreSQL connection stringGMAIL_CLIENT_ID/GMAIL_CLIENT_SECRET- OAuth credentialsAZURE_OPENAI_*- Azure OpenAI endpoints and API key
The email assistant follows this workflow:
- Triage: Classify incoming email as
respond,notify, orignore - Response Agent: If
respond, draft a response using available tools - Human Review: Interrupt for user approval before sending
- Memory Update: Learn from user feedback to improve future responses
When the agent drafts an email or needs user input, it pauses execution using LangGraph's interrupt() mechanism. You have several options for handling these interrupts:
The framework includes a web interface for reviewing pending actions:
- Dashboard (
/) - View all pending jobs with auto-refresh - Review Page (
/jobs/{job_id}) - Review email drafts, edit content, approve or reject - Setup Wizard (
/setup) - Configure Gmail OAuth credentials - Status Page (
/status) - Check system health and worker status
Simply start the server and navigate to http://localhost:8000 in your browser.
The framework includes a built-in CLI for reviewing pending actions:
# List all pending jobs awaiting review
uv run email-agent-review list
# Review a specific job interactively
uv run email-agent-review review hitl-abc123
# Watch mode - get notified of new jobs
uv run email-agent-review watch
# Quick actions (skip interactive review)
uv run email-agent-review accept hitl-abc123
uv run email-agent-review ignore hitl-abc123The CLI requires these environment variables:
DATABASE_URL- PostgreSQL connection stringAGENT_API_URL- API URL (default:http://localhost:8000)AGENT_API_KEY- API key if authentication is enabled
LangGraph Studio provides a visual interface for managing agent workflows, including an "Agent Inbox" for handling interrupts.
- Install LangGraph Studio following the official documentation
- Point it to your running LangGraph instance
- Use the Agent Inbox to review and respond to pending actions
For development and testing, you can bypass human review entirely:
WORKER_AUTO_ACCEPT_INTERRUPTS=trueThis automatically accepts all proposed actions without human review.
Create a new tool in email_agent/agent/tools/:
from langchain_core.tools import tool
@tool
def my_custom_tool(arg: str) -> str:
"""Description of what your tool does."""
return f"Result: {arg}"Register it in tools/base.py and add to the appropriate mode in configuration.py.
Edit email_agent/prompts.py to customize:
- Triage rules (
default_triage_instructions) - Response style (
default_response_preferences) - System prompts (
agent_system_prompt_hitl_memory)
# Format code
uv run ruff format .
# Lint
uv run ruff check . --fix
# Run pre-commit on all files
uv run pre-commit run --all-files
# Run tests
uv run pytestMIT License - see LICENSE for details.
Contributions are welcome! Please submit pull requests to the main branch.
This framework was developed by Nesta as part of the Agentic AI Residency program.


