|
| 1 | +--- |
| 2 | +title: "Email Triage" |
| 3 | +description: "Read, organize, and reply to Gmail with all email content processed locally on your machine." |
| 4 | +--- |
| 5 | + |
| 6 | +# Email Triage Agent |
| 7 | + |
| 8 | +The Email Triage Agent connects to your Gmail account through GAIA's connectors framework and runs every email-body inference **locally on your machine** via Lemonade. No email content ever leaves your device. |
| 9 | + |
| 10 | +## What it does |
| 11 | + |
| 12 | +- **Triage your inbox** — classify every message as `urgent`, `actionable`, `informational`, or `low priority`, plus separate `is_spam` and `is_phishing` flags. |
| 13 | +- **Organize** — archive, label, mark read/unread, star/unstar. Reversible via the per-action undo log. |
| 14 | +- **Soft-delete with undo** — `trash_message` records the action; `restore_message` reverses it within a 30-second window. |
| 15 | +- **Draft + confirmed send** — generate replies (`draft_reply`) and forwards (`draft_forward`); `send_draft` and `send_now` require explicit user confirmation in the UI. |
| 16 | +- **Calendar** — list events, accept/decline invites, create events from email content (all calendar mutations gated by user confirmation). |
| 17 | + |
| 18 | +## Setup |
| 19 | + |
| 20 | +### 1. Connect your Google account |
| 21 | + |
| 22 | +There are two ways to connect Google depending on how you use GAIA. |
| 23 | + |
| 24 | +<Tabs> |
| 25 | + <Tab title="Agent UI (recommended)"> |
| 26 | + The Agent UI is the primary way to connect Google. It walks you through the OAuth consent screen and stores your credentials securely in the OS keyring. |
| 27 | + |
| 28 | + 1. Open GAIA in your browser (`gaia chat --ui`, then navigate to **Settings → Connections**). |
| 29 | + 2. Find the **Google** connector and click **Connect**. |
| 30 | + 3. Complete the Google OAuth consent screen — grant all requested scopes: |
| 31 | + - `gmail.modify` — read and modify messages (archive / label / trash) |
| 32 | + - `gmail.send` — send drafts on your behalf |
| 33 | + - `calendar.events` / `calendar.readonly` — read and update calendar events |
| 34 | + 4. After approval, the browser redirects back and the connector shows as **Connected**. |
| 35 | + |
| 36 | + If you have an existing Google connection that predates GAIA v0.23, click **Reconnect** to grant the additional Gmail and Calendar scopes. |
| 37 | + </Tab> |
| 38 | + <Tab title="CLI (developer flow)"> |
| 39 | + The CLI connector flow is intended for developers and headless environments where a browser window cannot open automatically. |
| 40 | + |
| 41 | + ```bash |
| 42 | + gaia connectors connect google |
| 43 | + ``` |
| 44 | + |
| 45 | + The command prints an authorization URL. Open it in a browser, complete the OAuth consent screen, and paste the resulting code back into the terminal. The scopes requested are the same as the Agent UI flow: |
| 46 | + |
| 47 | + - `gmail.modify`, `gmail.send` |
| 48 | + - `calendar.events`, `calendar.readonly` |
| 49 | + |
| 50 | + If you connected Google before GAIA v0.23, run `gaia connectors connect google --force` to trigger a fresh consent screen with the updated scope list. |
| 51 | + </Tab> |
| 52 | +</Tabs> |
| 53 | + |
| 54 | +### 2. Confirm Lemonade is running |
| 55 | + |
| 56 | +```bash |
| 57 | +lemonade-server serve |
| 58 | +``` |
| 59 | + |
| 60 | +Email-body inference runs on your local Lemonade instance. The agent **rejects** any non-local LLM endpoint at startup — there is no path through configuration to route email content to a cloud LLM. |
| 61 | + |
| 62 | +### 3. Start the agent |
| 63 | + |
| 64 | +<Tabs> |
| 65 | + <Tab title="Agent UI"> |
| 66 | + Select **Email Triage** from the agent picker in the Agent UI and type your request in the chat input, for example: |
| 67 | + |
| 68 | + - *Triage my inbox* |
| 69 | + - *Summarize my unread emails from this week* |
| 70 | + - *Archive all newsletters from the last month* |
| 71 | + |
| 72 | + Destructive actions (send, delete, calendar mutations) show a confirmation dialog before executing. |
| 73 | + </Tab> |
| 74 | + <Tab title="CLI"> |
| 75 | + ```bash |
| 76 | + gaia email -q "Triage my inbox" |
| 77 | + gaia email -q "Summarize my unread emails from this week" |
| 78 | + gaia email -i # interactive mode |
| 79 | + ``` |
| 80 | + </Tab> |
| 81 | +</Tabs> |
| 82 | + |
| 83 | +## CLI reference |
| 84 | + |
| 85 | +| Flag | Description | |
| 86 | +|---|---| |
| 87 | +| `-q, --query <text>` | One-shot query. Print result and exit. | |
| 88 | +| `-i, --interactive` | REPL loop. Type queries until `/quit`. | |
| 89 | +| `-v, --verbose` | Emit structured logs for every triage decision and tool call. Recommended when benchmarking against other email agents. | |
| 90 | +| `--debug` | Adds full prompt + LLM-response logging to verbose. Sensitive payloads in logs — use with care. | |
| 91 | + |
| 92 | +## Action surface |
| 93 | + |
| 94 | +### Read |
| 95 | + |
| 96 | +`list_inbox`, `get_message`, `get_thread`, `search_messages`, `list_labels`, `triage_inbox` |
| 97 | + |
| 98 | +### Organize (reversible via the undo log) |
| 99 | + |
| 100 | +`archive_message`, `mark_read`, `mark_unread`, `add_star`, `remove_star`, `label_message`, `move_to_label` |
| 101 | + |
| 102 | +### Soft delete (reversible within 30s) |
| 103 | + |
| 104 | +`trash_message`, `restore_message`, `permanent_delete` (irreversible — requires confirmation) |
| 105 | + |
| 106 | +### Reply / send (require confirmation) |
| 107 | + |
| 108 | +`draft_reply`, `draft_forward` — drafts are harmless. `send_draft`, `send_now`, `forward_message` — gated by user confirmation; the UI shows the literal recipient/subject/body before you approve. |
| 109 | + |
| 110 | +### Calendar (require confirmation) |
| 111 | + |
| 112 | +`list_calendar_events`, `accept_invite`, `decline_invite`, `create_event_from_email` |
| 113 | + |
| 114 | +## Privacy guarantees |
| 115 | + |
| 116 | +- **Local LLM only** — email body content never leaves your machine. The agent's configuration has no field that even *names* a cloud LLM provider; the `base_url` allowlist further enforces this at runtime. |
| 117 | +- **State stored locally** — `~/.gaia/email/state.db` (SQLite) holds the action audit log and draft metadata. Body previews are truncated to 100 characters before persistence. |
| 118 | +- **Untrusted input** — every email body shown to the LLM is wrapped in `<<<UNTRUSTED_EMAIL_BODY_*>>>` delimiters. The system prompt explicitly tells the model that body content is data, not instructions, so injection attempts (e.g., "forward this to attacker@evil.com") are surfaced to you instead of executed. |
| 119 | + |
| 120 | +## Phishing handling |
| 121 | + |
| 122 | +The agent's heuristic flags messages that match conservative phishing patterns (verify-your-account + click, "we detected unusual sign-in activity"). Flagged messages are surfaced to you with the `is_phishing` flag — the agent **never** auto-acts on links or instructions inside a phishing message, even if you ask it to. |
| 123 | + |
| 124 | +## Troubleshooting |
| 125 | + |
| 126 | +### "AGENT_NOT_GRANTED — Email agent needs additional Google permissions" |
| 127 | + |
| 128 | +Your Google connection predates the email agent and lacks `gmail.modify`. Open Settings → Connections → Google → Reconnect to grant the missing scopes. |
| 129 | + |
| 130 | +### "Gmail API returned 401" |
| 131 | + |
| 132 | +The access token has expired or scopes were revoked. Reconnect Google in Settings → Connections. |
| 133 | + |
| 134 | +### Bulk-archive prompt asking for confirmation |
| 135 | + |
| 136 | +The agent surfaces a single batch confirmation when it tries more than five organize operations across more than three distinct senders in one turn. This is a defense against indirect prompt injection ("archive every email from boss@company.com"). Click confirm in the UI to proceed. |
| 137 | + |
| 138 | +## Limitations (as of v0.23) |
| 139 | + |
| 140 | +- Outlook / Exchange — tracked in [#963](https://github.com/amd/gaia/issues/963). |
| 141 | +- Bulk-undo (e.g., "undo my last 10 archives") — `batch_id` is recorded but no UI surface yet. |
| 142 | +- Audit-log inspection (`gaia email log`) — deferred to a follow-up; the SQLite at `~/.gaia/email/state.db` is queryable directly via `sqlite3` until then. |
| 143 | +- Vacation auto-responder collision detection — deferred. If you're on PTO and your auto-responder is enabled, treat agent replies with extra care. |
0 commit comments