{"slug": "folder-automation-let-rules-sort-the-agent-s-mail", "title": "Folder Automation: Let Rules Sort the Agent's Mail", "summary": "Nylas Agent Accounts, currently in beta, support server-side mail rules that sort, tag, and discard email before webhooks fire, reducing LLM inference costs by routing messages to custom folders. Rules match on sender fields with operators like 'is' or 'contains' and can assign to folders, mark as read, archive, trash, or block. This infrastructure-level filtering ensures agents only process relevant messages, with rules organized by priority and grouped by workspace.", "body_md": "How many of your email agent's LLM calls are spent classifying newsletters? If your architecture is \"webhook fires, model decides,\" the honest answer is: all of them. Every mailer-daemon notice, every drip campaign, every \"we've updated our privacy policy\" gets a full inference pass just to conclude *ignore this*. You're paying reasoning prices for routing work.\n\nThere's an older, cheaper tool for routing work: mail rules. [Nylas Agent Accounts](https://developer.nylas.com/docs/v3/agent-accounts/) — API-controlled hosted mailboxes, currently in beta — support server-side rules that sort, tag, and discard mail *before* your webhook fires, so the agent only reasons over what's left.\n\nEvery Agent Account ships with six system folders — `inbox`\n\n, `sent`\n\n, `drafts`\n\n, `trash`\n\n, `junk`\n\n, `archive`\n\n— and you can create custom ones alongside them (system folder names are reserved):\n\n```\ncurl --request POST \\\n  --url \"https://api.us.nylas.com/v3/grants/<GRANT_ID>/folders\" \\\n  --header \"Authorization: Bearer <NYLAS_API_KEY>\" \\\n  --header \"Content-Type: application/json\" \\\n  --data '{ \"name\": \"invoices\" }'\n```\n\nFor an agent, custom folders aren't organization — they're queues with different processing semantics. `invoices`\n\ngets the extraction pipeline. `newsletters`\n\ngets read by nobody. `inbox`\n\n— whatever rules didn't claim — gets the expensive LLM treatment. Your message-listing code filters by folder (`in=invoices`\n\n), and suddenly each worker pulls exactly its own workload.\n\nA rule pairs match conditions with actions. Inbound rules match on sender fields — `from.address`\n\n, `from.domain`\n\n, `from.tld`\n\n— with operators `is`\n\n, `is_not`\n\n, `contains`\n\n, or `in_list`\n\n, and run actions like `assign_to_folder`\n\n, `mark_as_read`\n\n, `mark_as_starred`\n\n, `archive`\n\n, `trash`\n\n, `mark_as_spam`\n\n, or `block`\n\n.\n\nHere's the newsletter problem solved at the infrastructure layer, straight from the [policies and rules docs](https://developer.nylas.com/docs/v3/agent-accounts/policies-rules-lists/):\n\n```\ncurl --request POST \\\n  --url \"https://api.us.nylas.com/v3/rules\" \\\n  --header \"Authorization: Bearer <NYLAS_API_KEY>\" \\\n  --header \"Content-Type: application/json\" \\\n  --data '{\n    \"name\": \"Newsletters → Reading folder\",\n    \"trigger\": \"inbound\",\n    \"match\": {\n      \"operator\": \"any\",\n      \"conditions\": [\n        { \"field\": \"from.address\", \"operator\": \"contains\", \"value\": \"newsletter@\" },\n        { \"field\": \"from.domain\", \"operator\": \"contains\", \"value\": \"substack.com\" }\n      ]\n    },\n    \"actions\": [\n      { \"type\": \"assign_to_folder\", \"value\": \"<READING_FOLDER_ID>\" },\n      { \"type\": \"mark_as_read\" }\n    ]\n  }'\n```\n\nThe `operator: \"any\"`\n\nmakes the conditions an OR; omit it and you get AND (`all`\n\n). Pairing `assign_to_folder`\n\nwith `mark_as_read`\n\nis a nice touch for agent mailboxes — if your agent uses the unread flag as its \"needs processing\" marker, routed mail arrives pre-cleared.\n\nA rule does nothing until a workspace references it: add its ID to the workspace's `rule_ids`\n\narray, and it runs for every Agent Account in that workspace. Group accounts by archetype — your support agents in one workspace, outreach agents in another — and each fleet gets its own routing table.\n\nRules run in `priority`\n\norder: lower numbers first, range 0–1000, default 10. Order them specific-before-broad — an `is`\n\nmatch on a known sender ahead of a `contains`\n\ncatch-all — because the `block`\n\naction is terminal: first match rejects the message at the SMTP level and nothing else runs. (Blocking is for spam; for sorting, you want the non-terminal actions.)\n\nThe structural caps are roomy enough that you'll rarely hit them: 50 conditions per rule, 20 actions per rule, 10 lists per `in_list`\n\ncondition, 500 characters per condition value.\n\nWhen the matching set changes often — a growing roster of vendor domains that should route to `invoices`\n\n— put the values in a **list** instead of inline. Lists are typed collections (`domain`\n\n, `tld`\n\n, or `address`\n\n) that rules reference via the `in_list`\n\noperator. The vendor-routing setup is three calls — create the list, fill it, point a rule at it:\n\n```\ncurl --request POST \\\n  --url \"https://api.us.nylas.com/v3/lists\" \\\n  --header \"Authorization: Bearer <NYLAS_API_KEY>\" \\\n  --header \"Content-Type: application/json\" \\\n  --data '{ \"name\": \"Vendor domains\", \"type\": \"domain\" }'\n\ncurl --request POST \\\n  --url \"https://api.us.nylas.com/v3/lists/<LIST_ID>/items\" \\\n  --header \"Authorization: Bearer <NYLAS_API_KEY>\" \\\n  --header \"Content-Type: application/json\" \\\n  --data '{ \"items\": [\"vendor-one.com\", \"vendor-two.net\"] }'\n```\n\nThen the rule's condition becomes `{ \"field\": \"from.domain\", \"operator\": \"in_list\", \"value\": [\"<LIST_ID>\"] }`\n\n. You can add up to 1,000 items per request — values are lowercased, trimmed, validated against the list's type, and duplicates are silently ignored — and every rule pointing at the list picks up changes immediately. That means a non-engineer can maintain the routing table by updating list items, with zero rule edits and zero deploys.\n\nTwo boundaries to know before you design around rules. First, inbound rules match **sender fields only** — `from.address`\n\n, `from.domain`\n\n, `from.tld`\n\n. There's no subject or body matching, so \"route anything mentioning 'invoice' in the subject\" stays in your application code; rules handle the *who*, your code handles the *what*. In practice sender-based routing covers more than you'd expect, because automated mail comes from stable addresses.\n\nSecond, `block`\n\nrules fail closed. If a block rule can't be evaluated because of a transient infrastructure error — say, a list lookup fails mid-`in_list`\n\nmatch — Nylas blocks the message rather than letting it through, responding with a `451`\n\ntempfail so the sending server retries instead of bouncing. The audit record carries `blocked_by_evaluation_error: true`\n\nso you can tell an infrastructure hiccup from a genuine match.\n\nServer-side sorting has a classic downside — \"why is this message in that folder?\" becomes an infrastructure mystery. The rule engine logs every evaluation, and you can pull the audit trail per grant:\n\n```\ncurl --request GET \\\n  --url \"https://api.us.nylas.com/v3/grants/<GRANT_ID>/rule-evaluations?limit=50\" \\\n  --header \"Authorization: Bearer <NYLAS_API_KEY>\"\n```\n\nEach record shows the evaluation stage, the sender data considered, which rules matched, and which actions applied — `folder_ids`\n\nincluded. When your invoice pipeline misses a message, this endpoint answers whether routing failed or extraction did.\n\nThe [mailbox docs](https://developer.nylas.com/docs/v3/agent-accounts/mailboxes/) put it plainly: inbound filtering is cheaper than reacting to noise. Rules run during the inbound lifecycle, before storage and before `message.created`\n\nfires — so by the time your application is involved, the junk is in `junk`\n\n, the newsletters are in `reading`\n\n, the invoices are in `invoices`\n\n, and the inbox contains only mail that genuinely needs a model's judgment.\n\nPull a day of your agent's inbound traffic and count how many messages actually required reasoning. If the number's under half — and it usually is — write the three rules that would've handled the rest, and check the difference in your token bill next week.", "url": "https://wpnews.pro/news/folder-automation-let-rules-sort-the-agent-s-mail", "canonical_source": "https://dev.to/qasim157/folder-automation-let-rules-sort-the-agents-mail-4o8i", "published_at": "2026-06-16 17:06:02+00:00", "updated_at": "2026-06-16 17:17:30.884981+00:00", "lang": "en", "topics": ["ai-agents", "developer-tools", "ai-infrastructure"], "entities": ["Nylas", "Nylas Agent Accounts"], "alternates": {"html": "https://wpnews.pro/news/folder-automation-let-rules-sort-the-agent-s-mail", "markdown": "https://wpnews.pro/news/folder-automation-let-rules-sort-the-agent-s-mail.md", "text": "https://wpnews.pro/news/folder-automation-let-rules-sort-the-agent-s-mail.txt", "jsonld": "https://wpnews.pro/news/folder-automation-let-rules-sort-the-agent-s-mail.jsonld"}}