An email-based personal AI agent built on Val Town. Interact entirely via email — send messages, tasks, ideas, and memories to memory-do@valtown.email and the agent classifies, stores, executes, and replies.
Send an email. The agent reads it, figures out what you mean, and acts on it.
You → "Remind me Thursday to call the dentist"
→ "I like chickens"
→ "What's the latest news on WebAssembly?"
→ "Every Monday, give me a summary of my active tasks"
Under the hood:
- Classify — Claude analyzes your email and extracts structured entries (memories, tasks, ideas, people, meetings, projects)
- Store — Everything goes into a unified SQLite database with full-text search and a relationship graph linking entries together
- Execute — Instant tasks run immediately through an agentic loop; future/recurring tasks get scheduled
- Reply — You get an email back with results, follow-up questions, and any generated file attachments
Emails sent via voice transcription work great. The classifier is tuned for misspellings, run-on sentences, and implicit intent — it interprets what you mean, not what you literally typed.
The agent doesn't just make a single LLM call and reply. It runs an iterative tool-use loop — Claude can call tools mid-task to gather information, search the web, query your stored knowledge, and create follow-up work.
┌─────────────────────────────────────────────┐
│ 1. Load user context (memories, tasks, etc) │
│ 2. Send task + context + tools to Claude │
│ 3. Claude responds: │
│ ├─ Final answer? → Done, send reply │
│ └─ Tool call? → Execute tool, loop to 2 │
│ 4. Safety: max 15 iterations │
│ 5. Extract attachments, generate subject │
└─────────────────────────────────────────────┘
| Tool | What It Does |
|---|---|
search_memories | Full-text search across all your stored entries |
get_entries | Browse entries by type (all tasks, all people, all ideas, etc.) |
get_linked_entries | Traverse the relationship graph between entries |
store_memory | Save new facts discovered during task execution |
create_task | Create follow-up tasks — instant, future, or recurring |
fetch_url | Fetch live data from the web (news, APIs, weather, docs) |
This means the agent can do multi-step research: search your memories, fetch a web page, cross-reference with your stored projects, save what it learned, and compose a rich reply — all in one email exchange.
Everything is an entry with a type. The system is extensible — new types need zero code changes.
| Type | Example |
|---|---|
memory | "I work at Acme Corp", "I like chickens" |
task | "Remind me Thursday to call the dentist" |
idea | "I have an idea for a recipe app..." |
person | "My friend Sarah works at Google" |
meeting | "Lunch with Bob on Friday at noon" |
project | "I'm building a Chrome extension" |
interaction | Every email sent/received (automatic) |
Entries are linked to each other in a relationship graph — "this idea became this project", "these entries came from the same email", "this person is connected to this meeting".
| Type | Behavior | Example |
|---|---|---|
| Instant | Executes immediately, reply in same email | "What's the weather in London?" |
| Future | Scheduled for a specific time | "Remind me Thursday at 10am to call dentist" |
| Recurring | Repeats on a schedule | "Every Monday, summarize my active tasks" |
Future and recurring tasks are processed by a task runner that checks every 15 minutes.
Each user gets a persistent system prompt — a personal "CLAUDE.md" that shapes how the agent behaves for them.
Set it by emailing instructions:
- "Be more casual and use emojis"
- "Call me Paul"
- "Always use bullet points"
- "Don't be so wordy"
These are extracted automatically and applied to every future interaction.
Full bidirectional support:
- Inbound — Email attachments (CSV, JSON, text, code files, etc.) are stored and their content is fed to both the classifier and the agent as context
- Outbound — The agent can generate files (reports, CSV exports, data dumps) and send them back as email attachments
email-agent/
README.md ← You are here
CLAUDE.md — Internal dev guide and conventions
main.ts — HTTP admin/debug endpoint
email-handler.ts — Email ingestion (memory-do@valtown.email)
task-runner.ts — Scheduled task processor (runs every 15 min)
lib/
classifier.ts — Claude-powered email → structured entries
agent.ts — Agentic task execution with tool-use loop
scheduler.ts — Natural language → ISO datetime
attachments.ts — Blob storage for inbound/outbound files
db/
schema.ts — SQLite schema (entries + FTS5 + links)
queries.ts — CRUD, search, user context builder
- Runtime: Val Town (Deno-based serverless)
- LLM: Claude Sonnet via Anthropic SDK
- Database: Project-scoped SQLite with FTS5 full-text search
- Storage: Val Town Blob API for attachments
- Email: Val Town email sending/receiving
┌──────────────┐
│ Incoming │
│ Email │
└──────┬───────┘
│
┌──────▼───────┐
│ Classifier │ ← Claude: extract entries, instructions, follow-ups
│ (1 LLM call) │
└──────┬───────┘
│
┌──────▼───────┐
│ Store in DB │ ← Entries, FTS sync, cross-links
└──────┬───────┘
│
┌───────┴────────┐
│ │
┌────▼─────┐ ┌─────▼──────┐
│ Instant │ │ Future / │
│ Tasks │ │ Recurring │
│ │ │ Tasks │
│ ┌───────┐ │ │ │
│ │ Agent │ │ │ Queued for │
│ │ Loop │ │ │ task-runner│
│ │ ↻ │ │ └────────────┘
│ └───┬───┘ │
│ │ │
└─────┼─────┘
│
┌─────▼─────┐
│ Reply │ ← Results + attachments + follow-up questions
│ Email │
└────────────┘
| Variable | Required | Description |
|---|---|---|
ANTHROPIC_API_KEY | Yes | Used by all Claude API calls (classifier, scheduler, agent) |
The HTTP endpoint (main.ts) provides:
GET /orGET /stats— System-wide entry counts, entries by type, link countsGET /user/:email— Full user profile with entries grouped by type
- No conversation threading — Each email is independent (though recent history is loaded as context)
- Plain text replies — No HTML email rendering
- No admin auth — HTTP endpoints are open
- No rate limiting — No flood protection
- No memory deduplication — Semantic similarity dedup not yet implemented
- No system prompt reset — Users can add instructions but can't easily clear them yet
Built on Val Town. Do what you want with it.