An intelligent email assistant powered by Microsoft's Phi-4 local model, featuring a modern web UI, human-in-the-loop approvals, calendar integration, and Microsoft 365 connectivity via MCP (Model Context Protocol).

This project demonstrates how to build a local email agent using:
1. Install Foundry Local:
Windows:
winget install Microsoft.FoundryLocal
MacOS:
brew install microsoft/foundrylocal/foundrylocal
Note: Foundry Local doesn't currently support Linux
2. Install Dependencies:
# Create virtual environment
python3 -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Install Python packages
pip install -r email_agent/requirements.txt
# Install Microsoft 365 MCP Server
npm install -g @softeria/ms-365-mcp-server
# Login to the M365 account you want to use
npx @softeria/ms-365-mcp-server --login
# Install frontend dependencies
cd email_agent/frontend
npm install
cd ../..
3. Start PostgreSQL + pgvector:
# Start Docker container
docker compose up -d
# Wait ~10 seconds for PostgreSQL to initialize
# Enable pgvector extension
docker exec -it email-postgres psql -U postgres -d emaildb -c "CREATE EXTENSION IF NOT EXISTS vector;"
# Verify
docker exec -it email-postgres psql -U postgres -d emaildb -c "\dx"
If successful, you should see the vector extension listed:
Name | Version | Schema | Description
---------+---------+------------+-----------------------------------------------------------
plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language
vector | 0.5.0 | public | vector data type and ivfflat and hnsw access methods
4. Configure Environment:
# Copy local env template
cp email_agent/.env.local.example email_agent/.env
Edit the .env file and add your Azure OpenAI credentials:
AZURE_OPENAI_ENDPOINT=https://your-endpoint.openai.azure.com/
AZURE_OPENAI_API_KEY=your-api-key
AZURE_OPENAI_EMBEDDING_DEPLOYMENT=text-embedding-ada-002
5. Import Your Emails (Optional)
# Import last 3 months of emails from Outlook
python3 -m email_agent.import_emails --months 3 --batch-size 50 --storage local
6. Run the Agent:
Start both the backend and frontend:
# Terminal 1: Start the FastAPI backend
source venv/bin/activate
python -m email_agent.api
# Terminal 2: Start the Next.js frontend
cd email_agent/frontend
npm run dev
Then open http://localhost:3000 in your browser.
The agent requires human approval for sensitive actions:
The agent uses a supervisor pattern with specialized sub-agents:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Supervisor Agent β
β (Routes requests to appropriate sub-agent or tool) β
βββββββββββββββββ¬ββββββββββββββββββ¬ββββββββββββββββββ¬ββββββββββββββ
β β β
βββββββββΌββββββββ βββββββββΌββββββββ βββββββββΌββββββββ
β Calendar β β Email β β Search β
β Sub-Agent β β Sub-Agent β β Email History β
β β β β β β
β MCP Tools: β β MCP Tools: β β Vector Store β
β β’ get-calendarβ β β’ send-mail β β (pgvector) β
β β’ create-eventβ β β’ create-draftβ β β
β β’ update-eventβ β β’ list-mail β β β
βββββββββββββββββ βββββββββββββββββ βββββββββββββββββ
Since Phi-4 doesn't have native tool calling, this project uses LangChain's with_structured_output(method='json_mode') to force valid JSON responses for reliable tool selection.
@softeria/ms-365-mcp-server)data/local_email_storage/manage_email sub-agentsend-mail MCP tool| File | Purpose |
|---|---|
agent_graph.py | LangGraph agent with supervisor and sub-agents, HITL interrupts |
api.py | FastAPI backend with REST endpoints and SSE streaming |
foundry_service.py | Foundry Local singleton for persistent LLM connection |
hitl_schemas.py | Human-in-the-loop interrupt and response schemas |
email_storage.py | PostgreSQL + pgvector integration for semantic search |
frontend/ | Next.js Agent Inbox UI with real-time streaming |
If you see FATAL: role postgres does not exist:
# Stop local PostgreSQL
brew services stop postgresql@14
# Restart Docker container
docker compose restart
Ensure Foundry Local service is running:
curl http://127.0.0.1:63911/foundry/list
# Should return list of loaded models
If email/calendar tools fail:
# Re-authenticate with Microsoft 365
npx @softeria/ms-365-mcp-server --login
If the frontend shows connection errors:
next.config.ts has the correct proxy settings18 commits
1 commits
1 commits
1 commits
Python
75.2%
TypeScript
23.0%
Shell
1.0%
An intelligent email assistant powered by Microsoft's Phi-4 local model, featuring a modern web UI, human-in-the-loop approvals, calendar integration, and Microsoft 365 connectivity via MCP (Model Context Protocol).

This project demonstrates how to build a local email agent using:
1. Install Foundry Local:
Windows:
winget install Microsoft.FoundryLocal
MacOS:
brew install microsoft/foundrylocal/foundrylocal
Note: Foundry Local doesn't currently support Linux
2. Install Dependencies:
# Create virtual environment
python3 -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activate
# Install Python packages
pip install -r email_agent/requirements.txt
# Install Microsoft 365 MCP Server
npm install -g @softeria/ms-365-mcp-server
# Login to the M365 account you want to use
npx @softeria/ms-365-mcp-server --login
# Install frontend dependencies
cd email_agent/frontend
npm install
cd ../..
3. Start PostgreSQL + pgvector:
# Start Docker container
docker compose up -d
# Wait ~10 seconds for PostgreSQL to initialize
# Enable pgvector extension
docker exec -it email-postgres psql -U postgres -d emaildb -c "CREATE EXTENSION IF NOT EXISTS vector;"
# Verify
docker exec -it email-postgres psql -U postgres -d emaildb -c "\dx"
If successful, you should see the vector extension listed:
Name | Version | Schema | Description
---------+---------+------------+-----------------------------------------------------------
plpgsql | 1.0 | pg_catalog | PL/pgSQL procedural language
vector | 0.5.0 | public | vector data type and ivfflat and hnsw access methods
4. Configure Environment:
# Copy local env template
cp email_agent/.env.local.example email_agent/.env
Edit the .env file and add your Azure OpenAI credentials:
AZURE_OPENAI_ENDPOINT=https://your-endpoint.openai.azure.com/
AZURE_OPENAI_API_KEY=your-api-key
AZURE_OPENAI_EMBEDDING_DEPLOYMENT=text-embedding-ada-002
5. Import Your Emails (Optional)
# Import last 3 months of emails from Outlook
python3 -m email_agent.import_emails --months 3 --batch-size 50 --storage local
6. Run the Agent:
Start both the backend and frontend:
# Terminal 1: Start the FastAPI backend
source venv/bin/activate
python -m email_agent.api
# Terminal 2: Start the Next.js frontend
cd email_agent/frontend
npm run dev
Then open http://localhost:3000 in your browser.
The agent requires human approval for sensitive actions:
The agent uses a supervisor pattern with specialized sub-agents:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Supervisor Agent β
β (Routes requests to appropriate sub-agent or tool) β
βββββββββββββββββ¬ββββββββββββββββββ¬ββββββββββββββββββ¬ββββββββββββββ
β β β
βββββββββΌββββββββ βββββββββΌββββββββ βββββββββΌββββββββ
β Calendar β β Email β β Search β
β Sub-Agent β β Sub-Agent β β Email History β
β β β β β β
β MCP Tools: β β MCP Tools: β β Vector Store β
β β’ get-calendarβ β β’ send-mail β β (pgvector) β
β β’ create-eventβ β β’ create-draftβ β β
β β’ update-eventβ β β’ list-mail β β β
βββββββββββββββββ βββββββββββββββββ βββββββββββββββββ
Since Phi-4 doesn't have native tool calling, this project uses LangChain's with_structured_output(method='json_mode') to force valid JSON responses for reliable tool selection.
@softeria/ms-365-mcp-server)data/local_email_storage/manage_email sub-agentsend-mail MCP tool| File | Purpose |
|---|---|
agent_graph.py | LangGraph agent with supervisor and sub-agents, HITL interrupts |
api.py | FastAPI backend with REST endpoints and SSE streaming |
foundry_service.py | Foundry Local singleton for persistent LLM connection |
hitl_schemas.py | Human-in-the-loop interrupt and response schemas |
email_storage.py | PostgreSQL + pgvector integration for semantic search |
frontend/ | Next.js Agent Inbox UI with real-time streaming |
If you see FATAL: role postgres does not exist:
# Stop local PostgreSQL
brew services stop postgresql@14
# Restart Docker container
docker compose restart
Ensure Foundry Local service is running:
curl http://127.0.0.1:63911/foundry/list
# Should return list of loaded models
If email/calendar tools fail:
# Re-authenticate with Microsoft 365
npx @softeria/ms-365-mcp-server --login
If the frontend shows connection errors:
next.config.ts has the correct proxy settings18 commits
1 commits
1 commits
1 commits
Python
75.2%
TypeScript
23.0%
Shell
1.0%