Skip to content

mg2660/MAiLBox

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

25 Commits
 
 
 
 
 
 
 
 

Repository files navigation

📬 Mailbox

Your email, simplified.

Mailbox is an AI-powered mail web application where the assistant controls the UI deterministically — not as a chatbot, but as a structured UI controller.

When a user says:

“Open the latest email from Cognizant”

The assistant:

  1. Navigates to Inbox
  2. Applies the correct filters
  3. Waits for inbox loading to finish
  4. Opens the correct email
  5. Confirms execution via the UI

The assistant does not narrate actions — it executes them visibly in the interface.


🎯 Project Goal

This project was built for the AI-Powered Mail Web Application Hiring Task .

The core requirement:

The AI must control the UI — not just respond in chat.

Mailbox satisfies this by implementing a deterministic, agentic architecture where:

  • AI emits structured UIAction[]
  • A central dispatcher executes them
  • The UI reflects visible changes
  • Task completion is confirmed only by execution

🧠 Architecture Overview

High-Level Flow

User
↓
Assistant Panel (Natural Language)
↓
/api/assistant (Intent Orchestration)
↓
Task Agent (Single Owner)
↓
UIAction[]
↓
dispatchAction (Execution Layer)
↓
Zustand Store + Next.js Router + Gmail API
↓
Visible UI Changes
↓
Execution Feedback

Core Principle

The AI never touches the DOM.

The assistant:

  • ❌ Never mutates UI state directly
  • ❌ Never performs side effects
  • ❌ Never assumes execution success
  • ✅ Only emits structured actions

All mutations and side effects occur through a single execution layer.

This guarantees:

  • Determinism
  • Debuggability
  • Replayability
  • Async correctness
  • Safety from hallucinated success

🏗 Tech Stack

  • Framework: Next.js (App Router)
  • Language: TypeScript
  • State Management: Zustand
  • Mail Provider: Gmail API (OAuth2)
  • AI: OpenAI (JSON-only structured output)
  • Styling: Tailwind CSS

📁 Project Structure

/app
  /inbox
  /sent
  /compose
  /email/[id]

/api
  /auth
  /gmail
  /assistant

/components
  AssistantPanel.tsx

/lib
  assistant/
    orchestrator.ts
    aiContext.ts
    buildAIContext.ts
    agents/
      navigationAgent.ts
      filterTaskAgent.ts
      filterApplyAgent.ts
      readEmailTaskAgent.ts
      emailTaskAgent.ts
      replyEmailTaskAgent.ts
      forwardEmailTaskAgent.ts
      sendEmailAgent.ts
  dispatchAction.ts
  uiActions.ts
  gmailClient.ts
  tokenStore.ts

/store
  uiStore.ts

📬 Mail Features

✅ Inbox

  • Real Gmail inbox

  • Click to open email

  • AI-controllable filters:

    • Sender
    • Keyword
    • Date range
    • Read / unread
  • State-driven filtering

  • Near real-time sync via polling


✅ Email Detail

  • Full email rendering
  • Reply and forward support
  • Thread-aware replies

✅ Sent

  • Real Gmail sent mail
  • Clickable → detail view

✅ Compose

  • Fully state-driven

  • Works via:

    • Manual UI interaction
    • AI-assisted drafting
  • Real Gmail send


🎮 UI Action System (Deterministic Core)

All AI control flows through:

type UIAction =
  | { type: "OPEN_INBOX" }
  | { type: "OPEN_SENT" }
  | { type: "OPEN_COMPOSE" }
  | { type: "OPEN_EMAIL"; payload: { id: string } }
  | { type: "FILL_COMPOSE"; payload: { to?: string; subject?: string; body?: string } }
  | { type: "SEND_EMAIL" }
  | { type: "APPLY_FILTER"; payload: InboxFilters }
  | { type: "CLEAR_FILTERS" };

A single dispatchAction() function executes:

  • Zustand state updates
  • Route navigation
  • Gmail API side effects

Humans and AI share the same execution path.


🤖 AI Assistant Design

Mailbox implements a deterministic, agentic architecture .


Intent Orchestration

The assistant classifies user intent into:

  • navigate
  • filter
  • read
  • email_task
  • reply
  • forward
  • send
  • unknown

Exactly one task agent owns each request.

No monolithic “super-agent”.


Task Ownership Model

Each agent owns a semantic responsibility:

  • navigationAgent
  • filterTaskAgent
  • readEmailTaskAgent
  • emailTaskAgent
  • replyEmailTaskAgent
  • forwardEmailTaskAgent
  • sendEmailAgent

Agents:

  • Plan actions
  • Coordinate multi-step flows
  • Never execute side effects
  • Never declare success

🔄 Async-Safe Agentic Control

The Real Problem

Applying a filter does not mean inbox data is immediately available.

A naive system would guess or use timeouts.

Mailbox does not.


The Solution: Deferred Execution & Re-Entry

The UI exposes:

inboxLoading: boolean

Agents are forbidden from selecting emails while loading.

Flow:

Apply filter
→ inboxLoading = true
→ agent returns awaiting_load
→ inbox finishes loading
→ assistant re-enters
→ agent proceeds

This makes the assistant truly agentic, not heuristic.


✉️ Email Workflows

New Email

  • LLM-assisted drafting
  • Multi-turn field completion
  • Optional confirmation before sending

Reply (Thread-Aware)

  • Valid only in email detail view

  • Injects:

    • threadId
    • messageId
    • references
  • LLM detects send intent (even with typos)

  • Execution layer confirms success


Forward

  • No threading metadata
  • Mechanical transformation
  • Lightweight and fast
  • Optional auto-send

Send (Execution-Only)

sendEmailAgent performs no reasoning.

It sends whatever is currently in compose.


✅ Execution-Confirmed Task Completion

Agents never declare success.

Only the execution layer emits:

taskFeedback

Assistant UI reacts to real outcomes.

This prevents:

  • Duplicate sends
  • Hallucinated success
  • Optimistic UI errors

🔐 Gmail Integration

  • OAuth2 flow implemented

  • Scopes:

    • gmail.readonly
    • gmail.send
  • Tokens stored in memory (demo trade-off)

Endpoints

  • GET /api/gmail/inbox
  • GET /api/gmail/sent
  • GET /api/gmail/email/[id]
  • POST /api/gmail/send

🧪 How To Run Locally

1️⃣ Clone Repository

git clone https://github.com/mg2660/MAiLBox
cd mailbox

2️⃣ Install Dependencies

npm install

3️⃣ Setup Environment Variables

Create .env.local:

GOOGLE_CLIENT_ID=your_client_id
GOOGLE_CLIENT_SECRET=your_client_secret
OPENAI_API_KEY=your_openai_key
NEXT_PUBLIC_BASE_URL=http://localhost:3000

Enable Gmail API in Google Cloud Console.


4️⃣ Start Development Server

npm run dev

Open:

http://localhost:3000

Login via Gmail OAuth.


📸 Demo (not included as of now)

Include:

  • Screenshot of inbox
  • Screenshot of assistant filling compose
  • Screenshot of filter execution
  • Short Loom video (recommended)

⚖️ Trade-Offs & Decisions

In-Memory Token Storage

  • Simpler implementation
  • Not production-ready
  • Requires re-auth on server restart

Polling Instead of Push Notifications

  • Simpler to implement
  • Sufficient for demo
  • Pub/Sub integration possible next

LLM Used Selectively

LLM is used only where reasoning adds value:

  • Intent classification
  • Filter interpretation
  • Email drafting
  • Reply body extraction

Not used for:

  • Navigation
  • Execution
  • Mechanical transformations

🚀 Completed Evaluation Checklist

  • ✅ Real emails sent & received
  • ✅ Inbox & Sent display real data
  • ✅ Compose works manually
  • ✅ AI fills compose form
  • ✅ AI filters inbox visibly
  • ✅ AI navigates & opens emails
  • ✅ Context-aware reply
  • ✅ Async-safe agent re-entry
  • ✅ Execution-confirmed completion

🔮 What I’d Improve With More Time

  1. Gmail Pub/Sub push sync
  2. Attachments support
  3. Reply-all
  4. Thread grouping view
  5. Persistent token storage
  6. Unit tests for agents
  7. Visual action preview panel

🧠 Final Architectural Insight

The key idea behind Mailbox:

The assistant proposes intent. The application decides truth.

By separating:

  • Planning
  • Execution
  • Confirmation

Mailbox achieves true agentic UI control, not a chat overlay.


About

MAiLbox -- Your email, simplified. Postman is the built-in assistant -- it opens emails, drafts replies, filters your inbox, and delivers exactly what you ask for.

Resources

License

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors