Inspiration

As a university student, my inbox contains coursework, applications, interviews, society updates, invoices, subscriptions, and administrative messages. The difficult emails are not always urgent when they arrive. An application deadline may be several weeks away, but forgetting it still has serious consequences.

Most inbox assistants summarize a message and then forget about it. I wanted to build an agent that could understand an email, remember the obligation inside it, contact me through another channel when action is required, and help me respond without taking control away from me.

That became Priority Inbox Guardian: a cross-channel agent that gives an inbox both memory and hands.

What it does

Priority Inbox Guardian receives email through Caspian and uses Featherless.ai to extract structured information:

  • A one-sentence summary
  • Category: career, academic, finance, or general
  • Whether action is required
  • A task description
  • A due date

If the email requires action, the agent stores the obligation and proactively alerts me through Telegram. The alert includes the email ID, subject, summary, category, due date, and commands I can use next.

From Telegram, I can:

  • Inspect the original email
  • View its AI-generated summary
  • Generate a professional reply draft
  • Refine the draft using natural-language feedback
  • Approve or cancel the draft
  • Explicitly send an approved reply
  • View all upcoming deadlines

The reply process intentionally separates drafting, approval, and sending. Generating a draft does not send it, and approving it does not send it. The final send command is required so the human remains in control.

A background scheduler also checks stored deadlines. When a reminder becomes due, the agent sends it through Telegram and records a delivery timestamp so the same reminder is not sent again after a restart.

How I built it

The agent is written in Python and uses caspian-sdk to connect Email and Telegram through one shared on_message handler.

Incoming email is normalized into a common event structure and passed to an orchestrator. Featherless.ai, using DeepSeek V3, returns structured JSON containing the classification, summary, urgency, task, and due date.

I separated persistence into SQLite repositories for:

  • Processed emails
  • Deadlines
  • Reply drafts
  • Application settings

The settings database remembers the Telegram conversation ID, allowing an email event to trigger a proactive alert in a different channel.

Drafts use a state-based workflow:

pending → approved → sent
        ↘ cancelled

This prevents cancelled or previously sent drafts from being delivered again.

Duplicate incoming email deliveries are detected using the Caspian message_id. Scheduled reminders use a reminder_sent_at timestamp, and sent drafts retain their final state. These safeguards make the agent idempotent across repeated events and container restarts.

The project is Dockerized with Docker Compose. SQLite files are stored in a persistent mounted data directory, while API keys remain outside the image in environment variables.

Accomplishments that I’m proud of

I am most proud that Priority Inbox Guardian is a complete, working agent rather than a mocked interface. A real email enters through Caspian, is interpreted by an LLM, creates persistent state, triggers a Telegram alert, and can receive an approved reply in its original email conversation.

I am particularly proud of:

  • Building one shared handler that operates across Email and Telegram
  • Creating a proactive workflow where an email event initiates action on another channel
  • Implementing persistent deadline memory that survives application and Docker restarts
  • Preventing duplicate emails, reminders, and outbound replies
  • Designing a human-in-the-loop workflow where drafting, approval, and sending are separate actions
  • Supporting natural-language refinement of generated replies
  • Successfully routing an approved response back to the original email conversation
  • Dockerizing the complete application with persistent SQLite storage
  • Debugging real integration problems instead of replacing them with mocked behavior

I also built the project incrementally using Git feature branches, testing each workflow before merging it into the stable application.

The most meaningful accomplishment was moving from a basic email classifier to a dependable cross-channel system with memory, state, safety controls, and real outbound communication. Every feature shown in the demonstration runs through the actual application.

Challenges I faced

One major challenge was understanding the difference between a Caspian message ID and conversation ID. Proactive Telegram alerts require a conversation ID, while replying to the original email requires its message ID. Using the wrong identifier produced delivery failures until I traced the stored events and corrected the routing.

Caspian also supplies sender information as a dictionary, so I had to normalize the sender name and address before storing them.

Duplicate event delivery created another challenge. Initially, the agent replied more than once to the same email. I added message-level deduplication and ensured duplicates are silently ignored.

I also encountered SQLite schema migration problems while adding conversation IDs and reminder timestamps to databases that already existed. I added lightweight migrations using PRAGMA table_info and ALTER TABLE, allowing existing data to remain usable.

LLM output was not always perfectly formatted. Sometimes it included Markdown code fences or unwanted subject lines. I added defensive JSON cleanup and stricter prompting so classification and reply drafts remain consistent.

Finally, Docker introduced environment-variable formatting and persistent-storage issues. Solving those problems helped me make the agent reproducible rather than dependent on my local Python environment.

What I learned

This project taught me that a working agent requires more than an LLM prompt. The difficult parts are routing messages correctly, maintaining persistent state, handling failures, protecting against duplicate actions, and designing safe boundaries for automation.

I learned how to:

  • Build one agent across multiple communication channels
  • Design repository and orchestration layers
  • Work with external APIs and structured LLM output
  • Model human approval as explicit state transitions
  • Implement idempotent email, reminder, and sending workflows
  • Migrate existing SQLite schemas
  • Persist application state across Docker restarts
  • Debug real delivery failures using logs and stored message data

Most importantly, I learned that useful automation should not remove human control. Priority Inbox Guardian assists with understanding, memory, and preparation, but the user still decides what gets sent.

What’s next

The current version is a private, single-user implementation. The next stage is to turn it into a broader application with:

  • Gmail OAuth for personal inbox connections
  • A web dashboard
  • Multi-user accounts
  • PostgreSQL
  • Calendar integration
  • Encrypted OAuth token storage
  • Multiple AI providers
  • Analytics for deadlines and response activity

The long-term goal is an inbox assistant that works wherever the user communicates, remembers what matters, and helps them act safely before important opportunities are missed.

Built With

Share this project:

Updates

Submission history